summaryrefslogtreecommitdiff
path: root/libre/linux-libre-lts
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-04-16 13:50:02 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-04-16 16:35:59 -0300
commit34ca297417c42efaca3ae88c59713c0c9a699349 (patch)
treeec6d658741c836f935f84ae94a72d8d60fe2875f /libre/linux-libre-lts
parentd319d9bd1ab26bfdd9727774ef4d8d87d1213a8c (diff)
linux-libre-lts-4.4.7_gnu-1: updating version
Diffstat (limited to 'libre/linux-libre-lts')
-rw-r--r--libre/linux-libre-lts/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch7
-rw-r--r--libre/linux-libre-lts/0001-ARM-sunxi-Add-R8-support.patch81
-rw-r--r--libre/linux-libre-lts/0001-drm-radeon-Make-the-driver-load-without-the-firmwares.patch16
-rw-r--r--libre/linux-libre-lts/0001-sdhci-revert.patch25
-rw-r--r--libre/linux-libre-lts/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch7
-rw-r--r--libre/linux-libre-lts/0002-ARM-sun5i-Add-CHIP-DTS.patch256
-rw-r--r--libre/linux-libre-lts/0003-ARM-sun5i-Add-R8-DTSI.patch748
-rw-r--r--libre/linux-libre-lts/0003-SMILE-Plug-device-tree-file.patch13
-rw-r--r--libre/linux-libre-lts/0004-ARM-dts-axp209-Add-usb_power_supply-child-node-to-the-ax209-node.patch34
-rw-r--r--libre/linux-libre-lts/0004-fix-mvsdio-eMMC-timing.patch7
-rw-r--r--libre/linux-libre-lts/0005-ARM-sun5i-chip-Add-CPU-regulator-for-cpufreq.patch33
-rw-r--r--libre/linux-libre-lts/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch7
-rw-r--r--libre/linux-libre-lts/0006-ARM-TLV320AIC23-SoC-Audio-Codec-Fix-errors-reported-.patch9
-rw-r--r--libre/linux-libre-lts/0007-set-default-cubietruck-led-triggers.patch15
-rw-r--r--libre/linux-libre-lts/0008-USB-armory-support.patch200
-rw-r--r--libre/linux-libre-lts/0009-ARM-dts-dove-add-Dove-divider-clocks.patch34
-rw-r--r--libre/linux-libre-lts/PKGBUILD80
-rw-r--r--libre/linux-libre-lts/config.armv7h1683
-rw-r--r--libre/linux-libre-lts/config.i686626
-rw-r--r--libre/linux-libre-lts/config.x86_64604
-rw-r--r--libre/linux-libre-lts/patch-4.4-gnu-4.4.7-gnu.patch37457
21 files changed, 39958 insertions, 1984 deletions
diff --git a/libre/linux-libre-lts/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch b/libre/linux-libre-lts/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch
index 2f1f0f02e..37a08e2b1 100644
--- a/libre/linux-libre-lts/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch
+++ b/libre/linux-libre-lts/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch
@@ -1,7 +1,7 @@
-From c3378026429b3ff9f2236fe0700db7eb7e450a46 Mon Sep 17 00:00:00 2001
+From 7c75672c751c1a9001f39bbe76c7ee092b4e6a29 Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@xxxxxx>
Date: Sun, 2 Dec 2012 19:59:28 +0100
-Subject: [PATCH 1/8] ARM: atags: add support for Marvell's u-boot
+Subject: [PATCH 1/9] ARM: atags: add support for Marvell's u-boot
Marvell uses a specific atag in its u-boot which includes among other
information the MAC addresses for up to 4 network interfaces.
@@ -47,4 +47,5 @@ index 979ff40..d1d0c19 100644
};
--
-2.4.4
+2.6.4
+
diff --git a/libre/linux-libre-lts/0001-ARM-sunxi-Add-R8-support.patch b/libre/linux-libre-lts/0001-ARM-sunxi-Add-R8-support.patch
deleted file mode 100644
index 957a7a2ff..000000000
--- a/libre/linux-libre-lts/0001-ARM-sunxi-Add-R8-support.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From bef6229f36c1c2ddae186f4e328c2359c1dad18d Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@free-electrons.com>
-Date: Tue, 9 Jun 2015 19:38:04 +0200
-Subject: [PATCH 1/5] ARM: sunxi: Add R8 support
-
-The R8 is a new Allwinner SoC based on the A13. While both are very
-similar, there's still a few differences. Introduce a new compatible to
-deal with them.
-
-In order to have a consistent naming, instead of mentioning the Allwinner
-A series as the machine name, switch to sun4i/sun5i like what is done for
-the other families.
-
-Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Chen-Yu Tsai <wens@csie.org>
-Acked-by: Stephen Boyd <sboyd@codeaurora.org>
----
- Documentation/arm/sunxi/README | 2 +-
- Documentation/devicetree/bindings/arm/sunxi.txt | 1 +
- arch/arm/mach-sunxi/sunxi.c | 3 ++-
- drivers/clk/sunxi/clk-sunxi.c | 1 +
- 4 files changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README
-index 5e38e15..430d279 100644
---- a/Documentation/arm/sunxi/README
-+++ b/Documentation/arm/sunxi/README
-@@ -25,7 +25,7 @@ SunXi family
- + Datasheet
- http://dl.linux-sunxi.org/A10s/A10s%20Datasheet%20-%20v1.20%20%282012-03-27%29.pdf
-
-- - Allwinner A13 (sun5i)
-+ - Allwinner A13 / R8 (sun5i)
- + Datasheet
- http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
- + User Manual
-diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt
-index 67da205..bb9b0faa 100644
---- a/Documentation/devicetree/bindings/arm/sunxi.txt
-+++ b/Documentation/devicetree/bindings/arm/sunxi.txt
-@@ -6,6 +6,7 @@ using one of the following compatible strings:
- allwinner,sun4i-a10
- allwinner,sun5i-a10s
- allwinner,sun5i-a13
-+ allwinner,sun5i-r8
- allwinner,sun6i-a31
- allwinner,sun7i-a20
- allwinner,sun8i-a23
-diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
-index 65bab28..8583a9c 100644
---- a/arch/arm/mach-sunxi/sunxi.c
-+++ b/arch/arm/mach-sunxi/sunxi.c
-@@ -26,10 +26,11 @@ static const char * const sunxi_board_dt_compat[] = {
- "allwinner,sun4i-a10",
- "allwinner,sun5i-a10s",
- "allwinner,sun5i-a13",
-+ "allwinner,sun5i-r8",
- NULL,
- };
-
--DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)")
-+DT_MACHINE_START(SUNXI_DT, "Allwinner sun4i/sun5i Families")
- .dt_compat = sunxi_board_dt_compat,
- .init_late = sunxi_dt_cpufreq_init,
- MACHINE_END
-diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
-index 413070d..9c79af0c 100644
---- a/drivers/clk/sunxi/clk-sunxi.c
-+++ b/drivers/clk/sunxi/clk-sunxi.c
-@@ -1196,6 +1196,7 @@ static void __init sun5i_init_clocks(struct device_node *node)
- }
- CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks);
- CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks);
-+CLK_OF_DECLARE(sun5i_r8_clk_init, "allwinner,sun5i-r8", sun5i_init_clocks);
- CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
-
- static const char *sun6i_critical_clocks[] __initdata = {
---
-cgit v0.12
-
diff --git a/libre/linux-libre-lts/0001-drm-radeon-Make-the-driver-load-without-the-firmwares.patch b/libre/linux-libre-lts/0001-drm-radeon-Make-the-driver-load-without-the-firmwares.patch
index 52f7197ed..e271d671b 100644
--- a/libre/linux-libre-lts/0001-drm-radeon-Make-the-driver-load-without-the-firmwares.patch
+++ b/libre/linux-libre-lts/0001-drm-radeon-Make-the-driver-load-without-the-firmwares.patch
@@ -1,6 +1,6 @@
-From 98e458c66c85472984a4230f34e7386af9e7b8d6 Mon Sep 17 00:00:00 2001
+From e479cd018fcd7f32714e5172265f8d1e7c4d9f0d Mon Sep 17 00:00:00 2001
From: Jason Self <j@jxself.org>
-Date: Wed, 5 Aug 2015 09:16:03 -0700
+Date: Sun, 30 Aug 2015 14:27:44 -0700
Subject: [PATCH 1/3] drm/radeon: Make the driver load without the
firmwares.
@@ -10,10 +10,10 @@ Subject: [PATCH 1/3] drm/radeon: Make the driver load without the
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
-index 720e599..d6a92ba 100644
+index 103f5d0..98f923b4 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
-@@ -2442,7 +2442,7 @@ int r600_init_microcode(struct radeon_device *rdev)
+@@ -2489,7 +2489,7 @@ int r600_init_microcode(struct radeon_device *rdev)
}
DRM_INFO("Loading %s Microcode\n", chip_name);
@@ -22,7 +22,7 @@ index 720e599..d6a92ba 100644
snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
err = reject_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
if (err)
-@@ -2494,7 +2494,7 @@ int r600_init_microcode(struct radeon_device *rdev)
+@@ -2541,7 +2541,7 @@ int r600_init_microcode(struct radeon_device *rdev)
err = -EINVAL;
}
}
@@ -31,7 +31,7 @@ index 720e599..d6a92ba 100644
out:
if (err) {
if (err != -EINVAL)
-@@ -3154,7 +3154,7 @@ int r600_init(struct radeon_device *rdev)
+@@ -3201,7 +3201,7 @@ int r600_init(struct radeon_device *rdev)
r = radeon_bo_init(rdev);
if (r)
return r;
@@ -40,7 +40,7 @@ index 720e599..d6a92ba 100644
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
r = r600_init_microcode(rdev);
if (r) {
-@@ -3162,7 +3162,7 @@ int r600_init(struct radeon_device *rdev)
+@@ -3209,7 +3209,7 @@ int r600_init(struct radeon_device *rdev)
return r;
}
}
@@ -50,7 +50,7 @@ index 720e599..d6a92ba 100644
radeon_pm_init(rdev);
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
-index af15260..f138df9 100644
+index cd3f6ac..b09af51 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -2241,7 +2241,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
diff --git a/libre/linux-libre-lts/0001-sdhci-revert.patch b/libre/linux-libre-lts/0001-sdhci-revert.patch
new file mode 100644
index 000000000..5d4afd644
--- /dev/null
+++ b/libre/linux-libre-lts/0001-sdhci-revert.patch
@@ -0,0 +1,25 @@
+index 2cadf08..b48565e 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -1895,9 +1895,9 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ tuning_count = host->tuning_count;
+
+ /*
+- * The Host Controller needs tuning only in case of SDR104 mode
+- * and for SDR50 mode when Use Tuning for SDR50 is set in the
+- * Capabilities register.
++ * The Host Controller needs tuning in case of SDR104 and DDR50
++ * mode, and for SDR50 mode when Use Tuning for SDR50 is set in
++ * the Capabilities register.
+ * If the Host Controller supports the HS200 mode then the
+ * tuning function has to be executed.
+ */
+@@ -1917,6 +1917,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ break;
+
+ case MMC_TIMING_UHS_SDR104:
++ case MMC_TIMING_UHS_DDR50:
+ break;
+
+ case MMC_TIMING_UHS_SDR50:
+generated by cgit v0.11.2 at 2016-01-01 22:11:38 (GMT)
diff --git a/libre/linux-libre-lts/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch b/libre/linux-libre-lts/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch
index 61d60c889..ddf3690f1 100644
--- a/libre/linux-libre-lts/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch
+++ b/libre/linux-libre-lts/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch
@@ -1,7 +1,7 @@
-From 8e6e2743ebdc2f46f59190391db3d2f37290047f Mon Sep 17 00:00:00 2001
+From 1fea82d0497ae305d2110585af7f57c81e0375df Mon Sep 17 00:00:00 2001
From: Willy Tarreau <w@xxxxxx>
Date: Sun, 2 Dec 2012 19:56:58 +0100
-Subject: [PATCH 2/8] ARM: atags/fdt: retrieve MAC addresses from Marvell boot
+Subject: [PATCH 2/9] ARM: atags/fdt: retrieve MAC addresses from Marvell boot
loader
The atags are parsed and if a Marvell atag is found, up to 4 MAC
@@ -43,4 +43,5 @@ index 9448aa0..ac7b6ae 100644
}
--
-2.4.4
+2.6.4
+
diff --git a/libre/linux-libre-lts/0002-ARM-sun5i-Add-CHIP-DTS.patch b/libre/linux-libre-lts/0002-ARM-sun5i-Add-CHIP-DTS.patch
deleted file mode 100644
index 7db5ff94f..000000000
--- a/libre/linux-libre-lts/0002-ARM-sun5i-Add-CHIP-DTS.patch
+++ /dev/null
@@ -1,256 +0,0 @@
-From 465a225fb2afb3ebf1becbe76d46b084d46f30a5 Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@free-electrons.com>
-Date: Tue, 9 Jun 2015 19:38:43 +0200
-Subject: [PATCH 2/5] ARM: sun5i: Add C.H.I.P DTS
-
-The C.H.I.P. is a small SBC with an Allwinner R8, 8GB of NAND, 512MB of
-RAM, USB host and OTG, a wifi / bluetooth combo chip, an audio/video jack
-and two connectors to plug additional boards on top of it.
-
-Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Acked-by: Chen-Yu Tsai <wens@csie.org>
-Reviewed-by: André Silva <emulatorman@parabola.nu>
----
- arch/arm/boot/dts/Makefile | 3 +-
- arch/arm/boot/dts/sun5i-r8-chip.dts | 214 ++++++++++++++++++++++++++++++++++++
- 2 files changed, 216 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/boot/dts/sun5i-r8-chip.dts
-
-diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
-index 992736b..f8d18bd 100644
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -540,7 +540,8 @@ dtb-$(CONFIG_MACH_SUN5I) += \
- sun5i-a10s-r7-tv-dongle.dtb \
- sun5i-a13-hsg-h702.dtb \
- sun5i-a13-olinuxino.dtb \
-- sun5i-a13-olinuxino-micro.dtb
-+ sun5i-a13-olinuxino-micro.dtb \
-+ sun5i-r8-chip.dtb
- dtb-$(CONFIG_MACH_SUN6I) += \
- sun6i-a31-app4-evb1.dtb \
- sun6i-a31-colombus.dtb \
-diff --git a/arch/arm/boot/dts/sun5i-r8-chip.dts b/arch/arm/boot/dts/sun5i-r8-chip.dts
-new file mode 100644
-index 0000000..abf3ccb
---- /dev/null
-+++ b/arch/arm/boot/dts/sun5i-r8-chip.dts
-@@ -0,0 +1,214 @@
-+/*
-+ * Copyright 2015 Free Electrons
-+ * Copyright 2015 NextThing Co
-+ *
-+ * Maxime Ripard <maxime.ripard@free-electrons.com>
-+ *
-+ * This file is dual-licensed: you can use it either under the terms
-+ * of the GPL or the X11 license, at your option. Note that this dual
-+ * licensing only applies to this file, and not this project as a
-+ * whole.
-+ *
-+ * a) This file 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, or (at your option) any later version.
-+ *
-+ * This file 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.
-+ *
-+ * Or, alternatively,
-+ *
-+ * b) Permission is hereby granted, free of charge, to any person
-+ * obtaining a copy of this software and associated documentation
-+ * files (the "Software"), to deal in the Software without
-+ * restriction, including without limitation the rights to use,
-+ * copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following
-+ * conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be
-+ * included in all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ */
-+
-+/dts-v1/;
-+#include "sun5i-r8.dtsi"
-+#include "sunxi-common-regulators.dtsi"
-+
-+#include <dt-bindings/gpio/gpio.h>
-+#include <dt-bindings/interrupt-controller/irq.h>
-+
-+/ {
-+ model = "NextThing C.H.I.P.";
-+ compatible = "nextthing,chip", "allwinner,sun5i-r8";
-+
-+ aliases {
-+ i2c0 = &i2c0;
-+ i2c2 = &i2c2;
-+ serial0 = &uart1;
-+ serial1 = &uart3;
-+ };
-+
-+ chosen {
-+ stdout-path = "serial0:115200n8";
-+ };
-+};
-+
-+&ehci0 {
-+ status = "okay";
-+};
-+
-+&i2c0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c0_pins_a>;
-+ status = "okay";
-+
-+ axp209: pmic@34 {
-+ reg = <0x34>;
-+
-+ /*
-+ * The interrupt is routed through the "External Fast
-+ * Interrupt Request" pin (ball G13 of the module)
-+ * directly to the main interrupt controller, without
-+ * any other controller interfering.
-+ */
-+ interrupts = <0>;
-+ };
-+};
-+
-+#include "axp209.dtsi"
-+
-+&i2c2 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c2_pins_a>;
-+ status = "okay";
-+
-+ xio: gpio@38 {
-+ compatible = "nxp,pcf8574a";
-+ reg = <0x38>;
-+
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+
-+ interrupt-parent = <&pio>;
-+ interrupts = <6 0 IRQ_TYPE_EDGE_FALLING>;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ };
-+};
-+
-+&mmc0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc0_pins_a>;
-+ vmmc-supply = <&reg_vcc3v3>;
-+ bus-width = <4>;
-+ non-removable;
-+ status = "okay";
-+};
-+
-+&ohci0 {
-+ status = "okay";
-+};
-+
-+&otg_sram {
-+ status = "okay";
-+};
-+
-+&pio {
-+ chip_vbus_pin: chip_vbus_pin@0 {
-+ allwinner,pins = "PB10";
-+ allwinner,function = "gpio_out";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ chip_id_det_pin: chip_id_det_pin@0 {
-+ allwinner,pins = "PG2";
-+ allwinner,function = "gpio_in";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+};
-+
-+&reg_dcdc2 {
-+ regulator-min-microvolt = <1000000>;
-+ regulator-max-microvolt = <1400000>;
-+ regulator-name = "cpuvdd";
-+ regulator-always-on;
-+};
-+
-+&reg_dcdc3 {
-+ regulator-min-microvolt = <1000000>;
-+ regulator-max-microvolt = <1300000>;
-+ regulator-name = "corevdd";
-+ regulator-always-on;
-+};
-+
-+&reg_ldo1 {
-+ regulator-name = "rtcvdd";
-+};
-+
-+&reg_ldo2 {
-+ regulator-min-microvolt = <2700000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-name = "avcc";
-+ regulator-always-on;
-+};
-+
-+&reg_ldo5 {
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <1800000>;
-+ regulator-name = "vcc-1v8";
-+};
-+
-+&reg_usb0_vbus {
-+ pinctrl-0 = <&chip_vbus_pin>;
-+ vin-supply = <&reg_vcc5v0>;
-+ gpio = <&pio 1 10 GPIO_ACTIVE_HIGH>; /* PB10 */
-+ status = "okay";
-+};
-+
-+&uart1 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart1_pins_b>;
-+ status = "okay";
-+};
-+
-+&uart3 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart3_pins_a>,
-+ <&uart3_pins_cts_rts_a>;
-+ status = "okay";
-+};
-+
-+&usb_otg {
-+ dr_mode = "otg";
-+ status = "okay";
-+};
-+
-+&usb_power_supply {
-+ status = "okay";
-+};
-+
-+&usbphy {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&chip_id_det_pin>;
-+ status = "okay";
-+
-+ usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
-+ usb0_vbus_power-supply = <&usb_power_supply>;
-+ usb0_vbus-supply = <&reg_usb0_vbus>;
-+ usb1_vbus-supply = <&reg_vcc5v0>;
-+};
---
-cgit v0.12
-
diff --git a/libre/linux-libre-lts/0003-ARM-sun5i-Add-R8-DTSI.patch b/libre/linux-libre-lts/0003-ARM-sun5i-Add-R8-DTSI.patch
deleted file mode 100644
index e8b1099c1..000000000
--- a/libre/linux-libre-lts/0003-ARM-sun5i-Add-R8-DTSI.patch
+++ /dev/null
@@ -1,748 +0,0 @@
-From 49e4f3c3271e7eff2800596ba168c932d7d702b8 Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@free-electrons.com>
-Date: Fri, 18 Sep 2015 09:09:34 +0200
-Subject: [PATCH 3/5] ARM: sun5i: Add R8 DTSI
-
-The R8 is very close to the A13, but it still has a few differences,
-notably a composite output, which the A13 lacks.
-
-Add a DTSI based on the A13's to hold those differences.
-
-Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
-Reviewed-by: Chen-Yu Tsai <wens@csie.org>
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: André Silva <emulatorman@parabola.nu>
-Reviewed-by: Márcio Silva <coadde@parabola.nu>
----
- arch/arm/boot/dts/sun5i-r8.dtsi | 719 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 719 insertions(+)
- create mode 100644 arch/arm/boot/dts/sun5i-r8.dtsi
-
-diff --git a/arch/arm/boot/dts/sun5i-r8.dtsi b/arch/arm/boot/dts/sun5i-r8.dtsi
-new file mode 100644
-index 0000000..5d76b20
---- /dev/null
-+++ b/arch/arm/boot/dts/sun5i-r8.dtsi
-@@ -0,0 +1,719 @@
-+/*
-+ * Copyright 2015 Free Electrons
-+ * Copyright 2015 NextThing Co
-+ *
-+ * Maxime Ripard <maxime.ripard@free-electrons.com>
-+ *
-+ * This file is dual-licensed: you can use it either under the terms
-+ * of the GPL or the X11 license, at your option. Note that this dual
-+ * licensing only applies to this file, and not this project as a
-+ * whole.
-+ *
-+ * a) This file 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, or (at your option) any later version.
-+ *
-+ * This file 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.
-+ *
-+ * Or, alternatively,
-+ *
-+ * b) Permission is hereby granted, free of charge, to any person
-+ * obtaining a copy of this software and associated documentation
-+ * files (the "Software"), to deal in the Software without
-+ * restriction, including without limitation the rights to use,
-+ * copy, modify, merge, publish, distribute, sublicense, and/or
-+ * sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following
-+ * conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be
-+ * included in all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ */
-+
-+#include "skeleton.dtsi"
-+
-+#include <dt-bindings/thermal/thermal.h>
-+
-+#include <dt-bindings/dma/sun4i-a10.h>
-+#include <dt-bindings/pinctrl/sun4i-a10.h>
-+
-+/ {
-+ interrupt-parent = <&intc>;
-+
-+ chosen {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ framebuffer@0 {
-+ compatible = "allwinner,simple-framebuffer",
-+ "simple-framebuffer";
-+ allwinner,pipeline = "de_be0-lcd0";
-+ clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>;
-+ status = "disabled";
-+ };
-+
-+ framebuffer@1 {
-+ compatible = "allwinner,simple-framebuffer",
-+ "simple-framebuffer";
-+ allwinner,pipeline = "de_be0-lcd0-tve0";
-+ clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>,
-+ <&ahb_gates 44>;
-+ status = "disabled";
-+ };
-+ };
-+
-+ cpus {
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ cpu0: cpu@0 {
-+ device_type = "cpu";
-+ compatible = "arm,cortex-a8";
-+ reg = <0x0>;
-+ clocks = <&cpu>;
-+ clock-latency = <244144>; /* 8 32k periods */
-+ operating-points = <
-+ /* kHz uV */
-+ 1008000 1400000
-+ 912000 1350000
-+ 864000 1300000
-+ 624000 1200000
-+ 576000 1200000
-+ 432000 1200000
-+ >;
-+ #cooling-cells = <2>;
-+ cooling-min-level = <0>;
-+ cooling-max-level = <5>;
-+ };
-+ };
-+
-+ thermal-zones {
-+ cpu_thermal {
-+ /* milliseconds */
-+ polling-delay-passive = <250>;
-+ polling-delay = <1000>;
-+ thermal-sensors = <&rtp>;
-+
-+ cooling-maps {
-+ map0 {
-+ trip = <&cpu_alert0>;
-+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-+ };
-+ };
-+
-+ trips {
-+ cpu_alert0: cpu_alert0 {
-+ /* milliCelsius */
-+ temperature = <850000>;
-+ hysteresis = <2000>;
-+ type = "passive";
-+ };
-+
-+ cpu_crit: cpu_crit {
-+ /* milliCelsius */
-+ temperature = <100000>;
-+ hysteresis = <2000>;
-+ type = "critical";
-+ };
-+ };
-+ };
-+ };
-+
-+ memory {
-+ reg = <0x40000000 0x20000000>;
-+ };
-+
-+ clocks {
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ /*
-+ * This is a dummy clock, to be used as placeholder on
-+ * other mux clocks when a specific parent clock is not
-+ * yet implemented. It should be dropped when the driver
-+ * is complete.
-+ */
-+ dummy: dummy {
-+ #clock-cells = <0>;
-+ compatible = "fixed-clock";
-+ clock-frequency = <0>;
-+ };
-+
-+ osc24M: clk@01c20050 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-osc-clk";
-+ reg = <0x01c20050 0x4>;
-+ clock-frequency = <24000000>;
-+ clock-output-names = "osc24M";
-+ };
-+
-+ osc32k: clk@0 {
-+ #clock-cells = <0>;
-+ compatible = "fixed-clock";
-+ clock-frequency = <32768>;
-+ clock-output-names = "osc32k";
-+ };
-+
-+ pll1: clk@01c20000 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-pll1-clk";
-+ reg = <0x01c20000 0x4>;
-+ clocks = <&osc24M>;
-+ clock-output-names = "pll1";
-+ };
-+
-+ pll4: clk@01c20018 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-pll1-clk";
-+ reg = <0x01c20018 0x4>;
-+ clocks = <&osc24M>;
-+ clock-output-names = "pll4";
-+ };
-+
-+ pll5: clk@01c20020 {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun4i-a10-pll5-clk";
-+ reg = <0x01c20020 0x4>;
-+ clocks = <&osc24M>;
-+ clock-output-names = "pll5_ddr", "pll5_other";
-+ };
-+
-+ pll6: clk@01c20028 {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun4i-a10-pll6-clk";
-+ reg = <0x01c20028 0x4>;
-+ clocks = <&osc24M>;
-+ clock-output-names = "pll6_sata", "pll6_other", "pll6";
-+ };
-+
-+ /* dummy is 200M */
-+ cpu: cpu@01c20054 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-cpu-clk";
-+ reg = <0x01c20054 0x4>;
-+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
-+ clock-output-names = "cpu";
-+ };
-+
-+ axi: axi@01c20054 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-axi-clk";
-+ reg = <0x01c20054 0x4>;
-+ clocks = <&cpu>;
-+ clock-output-names = "axi";
-+ };
-+
-+ axi_gates: clk@01c2005c {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun4i-a10-axi-gates-clk";
-+ reg = <0x01c2005c 0x4>;
-+ clocks = <&axi>;
-+ clock-output-names = "axi_dram";
-+ };
-+
-+ ahb: ahb@01c20054 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-ahb-clk";
-+ reg = <0x01c20054 0x4>;
-+ clocks = <&axi>;
-+ clock-output-names = "ahb";
-+ };
-+
-+ ahb_gates: clk@01c20060 {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun5i-a13-ahb-gates-clk";
-+ reg = <0x01c20060 0x8>;
-+ clocks = <&ahb>;
-+ clock-output-names = "ahb_usbotg", "ahb_ehci", "ahb_ohci",
-+ "ahb_ss", "ahb_dma", "ahb_bist", "ahb_mmc0",
-+ "ahb_mmc1", "ahb_mmc2", "ahb_nand", "ahb_sdram",
-+ "ahb_spi0", "ahb_spi1", "ahb_spi2", "ahb_stimer",
-+ "ahb_ve", "ahb_lcd", "ahb_csi", "ahb_de_be",
-+ "ahb_de_fe", "ahb_iep", "ahb_mali400";
-+ };
-+
-+ apb0: apb0@01c20054 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-apb0-clk";
-+ reg = <0x01c20054 0x4>;
-+ clocks = <&ahb>;
-+ clock-output-names = "apb0";
-+ };
-+
-+ apb0_gates: clk@01c20068 {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun5i-a13-apb0-gates-clk";
-+ reg = <0x01c20068 0x4>;
-+ clocks = <&apb0>;
-+ clock-output-names = "apb0_codec", "apb0_pio", "apb0_ir";
-+ };
-+
-+ apb1: clk@01c20058 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-apb1-clk";
-+ reg = <0x01c20058 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
-+ clock-output-names = "apb1";
-+ };
-+
-+ apb1_gates: clk@01c2006c {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun5i-a13-apb1-gates-clk";
-+ reg = <0x01c2006c 0x4>;
-+ clocks = <&apb1>;
-+ clock-output-names = "apb1_i2c0", "apb1_i2c1",
-+ "apb1_i2c2", "apb1_uart1", "apb1_uart3";
-+ };
-+
-+ nand_clk: clk@01c20080 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c20080 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "nand";
-+ };
-+
-+ ms_clk: clk@01c20084 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c20084 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "ms";
-+ };
-+
-+ mmc0_clk: clk@01c20088 {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun4i-a10-mmc-clk";
-+ reg = <0x01c20088 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "mmc0",
-+ "mmc0_output",
-+ "mmc0_sample";
-+ };
-+
-+ mmc1_clk: clk@01c2008c {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun4i-a10-mmc-clk";
-+ reg = <0x01c2008c 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "mmc1",
-+ "mmc1_output",
-+ "mmc1_sample";
-+ };
-+
-+ mmc2_clk: clk@01c20090 {
-+ #clock-cells = <1>;
-+ compatible = "allwinner,sun4i-a10-mmc-clk";
-+ reg = <0x01c20090 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "mmc2",
-+ "mmc2_output",
-+ "mmc2_sample";
-+ };
-+
-+ ts_clk: clk@01c20098 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c20098 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "ts";
-+ };
-+
-+ ss_clk: clk@01c2009c {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c2009c 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "ss";
-+ };
-+
-+ spi0_clk: clk@01c200a0 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c200a0 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "spi0";
-+ };
-+
-+ spi1_clk: clk@01c200a4 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c200a4 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "spi1";
-+ };
-+
-+ spi2_clk: clk@01c200a8 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c200a8 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "spi2";
-+ };
-+
-+ ir0_clk: clk@01c200b0 {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun4i-a10-mod0-clk";
-+ reg = <0x01c200b0 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "ir0";
-+ };
-+
-+ usb_clk: clk@01c200cc {
-+ #clock-cells = <1>;
-+ #reset-cells = <1>;
-+ compatible = "allwinner,sun5i-a13-usb-clk";
-+ reg = <0x01c200cc 0x4>;
-+ clocks = <&pll6 1>;
-+ clock-output-names = "usb_ohci0", "usb_phy";
-+ };
-+
-+ mbus_clk: clk@01c2015c {
-+ #clock-cells = <0>;
-+ compatible = "allwinner,sun5i-a13-mbus-clk";
-+ reg = <0x01c2015c 0x4>;
-+ clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
-+ clock-output-names = "mbus";
-+ };
-+ };
-+
-+ soc@01c00000 {
-+ compatible = "simple-bus";
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ sram-controller@01c00000 {
-+ compatible = "allwinner,sun4i-a10-sram-controller";
-+ reg = <0x01c00000 0x30>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges;
-+
-+ sram_a: sram@00000000 {
-+ compatible = "mmio-sram";
-+ reg = <0x00000000 0xc000>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges = <0 0x00000000 0xc000>;
-+ };
-+
-+ sram_d: sram@00010000 {
-+ compatible = "mmio-sram";
-+ reg = <0x00010000 0x1000>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges = <0 0x00010000 0x1000>;
-+
-+ otg_sram: sram-section@0000 {
-+ compatible = "allwinner,sun4i-a10-sram-d";
-+ reg = <0x0000 0x1000>;
-+ status = "disabled";
-+ };
-+ };
-+ };
-+
-+ dma: dma-controller@01c02000 {
-+ compatible = "allwinner,sun4i-a10-dma";
-+ reg = <0x01c02000 0x1000>;
-+ interrupts = <27>;
-+ clocks = <&ahb_gates 6>;
-+ #dma-cells = <2>;
-+ };
-+
-+ spi0: spi@01c05000 {
-+ compatible = "allwinner,sun4i-a10-spi";
-+ reg = <0x01c05000 0x1000>;
-+ interrupts = <10>;
-+ clocks = <&ahb_gates 20>, <&spi0_clk>;
-+ clock-names = "ahb", "mod";
-+ dmas = <&dma SUN4I_DMA_DEDICATED 27>,
-+ <&dma SUN4I_DMA_DEDICATED 26>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ spi1: spi@01c06000 {
-+ compatible = "allwinner,sun4i-a10-spi";
-+ reg = <0x01c06000 0x1000>;
-+ interrupts = <11>;
-+ clocks = <&ahb_gates 21>, <&spi1_clk>;
-+ clock-names = "ahb", "mod";
-+ dmas = <&dma SUN4I_DMA_DEDICATED 9>,
-+ <&dma SUN4I_DMA_DEDICATED 8>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ mmc0: mmc@01c0f000 {
-+ compatible = "allwinner,sun5i-a13-mmc";
-+ reg = <0x01c0f000 0x1000>;
-+ clocks = <&ahb_gates 8>,
-+ <&mmc0_clk 0>,
-+ <&mmc0_clk 1>,
-+ <&mmc0_clk 2>;
-+ clock-names = "ahb",
-+ "mmc",
-+ "output",
-+ "sample";
-+ interrupts = <32>;
-+ status = "disabled";
-+ };
-+
-+ mmc2: mmc@01c11000 {
-+ compatible = "allwinner,sun5i-a13-mmc";
-+ reg = <0x01c11000 0x1000>;
-+ clocks = <&ahb_gates 10>,
-+ <&mmc2_clk 0>,
-+ <&mmc2_clk 1>,
-+ <&mmc2_clk 2>;
-+ clock-names = "ahb",
-+ "mmc",
-+ "output",
-+ "sample";
-+ interrupts = <34>;
-+ status = "disabled";
-+ };
-+
-+ usb_otg: usb@01c13000 {
-+ compatible = "allwinner,sun4i-a10-musb";
-+ reg = <0x01c13000 0x0400>;
-+ clocks = <&ahb_gates 0>;
-+ interrupts = <38>;
-+ interrupt-names = "mc";
-+ phys = <&usbphy 0>;
-+ phy-names = "usb";
-+ extcon = <&usbphy 0>;
-+ allwinner,sram = <&otg_sram 1>;
-+ status = "disabled";
-+ };
-+
-+ usbphy: phy@01c13400 {
-+ #phy-cells = <1>;
-+ compatible = "allwinner,sun5i-a13-usb-phy";
-+ reg = <0x01c13400 0x10 0x01c14800 0x4>;
-+ reg-names = "phy_ctrl", "pmu1";
-+ clocks = <&usb_clk 8>;
-+ clock-names = "usb_phy";
-+ resets = <&usb_clk 0>, <&usb_clk 1>;
-+ reset-names = "usb0_reset", "usb1_reset";
-+ status = "disabled";
-+ };
-+
-+ ehci0: usb@01c14000 {
-+ compatible = "allwinner,sun5i-a13-ehci", "generic-ehci";
-+ reg = <0x01c14000 0x100>;
-+ interrupts = <39>;
-+ clocks = <&ahb_gates 1>;
-+ phys = <&usbphy 1>;
-+ phy-names = "usb";
-+ status = "disabled";
-+ };
-+
-+ ohci0: usb@01c14400 {
-+ compatible = "allwinner,sun5i-a13-ohci", "generic-ohci";
-+ reg = <0x01c14400 0x100>;
-+ interrupts = <40>;
-+ clocks = <&usb_clk 6>, <&ahb_gates 2>;
-+ phys = <&usbphy 1>;
-+ phy-names = "usb";
-+ status = "disabled";
-+ };
-+
-+ spi2: spi@01c17000 {
-+ compatible = "allwinner,sun4i-a10-spi";
-+ reg = <0x01c17000 0x1000>;
-+ interrupts = <12>;
-+ clocks = <&ahb_gates 22>, <&spi2_clk>;
-+ clock-names = "ahb", "mod";
-+ dmas = <&dma SUN4I_DMA_DEDICATED 29>,
-+ <&dma SUN4I_DMA_DEDICATED 28>;
-+ dma-names = "rx", "tx";
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ intc: interrupt-controller@01c20400 {
-+ compatible = "allwinner,sun4i-a10-ic";
-+ reg = <0x01c20400 0x400>;
-+ interrupt-controller;
-+ #interrupt-cells = <1>;
-+ };
-+
-+ pio: pinctrl@01c20800 {
-+ compatible = "allwinner,sun5i-a13-pinctrl";
-+ reg = <0x01c20800 0x400>;
-+ interrupts = <28>;
-+ clocks = <&apb0_gates 5>;
-+ gpio-controller;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ #size-cells = <0>;
-+ #gpio-cells = <3>;
-+
-+ uart1_pins_a: uart1@0 {
-+ allwinner,pins = "PE10", "PE11";
-+ allwinner,function = "uart1";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ uart1_pins_b: uart1@1 {
-+ allwinner,pins = "PG3", "PG4";
-+ allwinner,function = "uart1";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ uart3_pins_a: uart3@0 {
-+ allwinner,pins = "PG9", "PG10";
-+ allwinner,function = "uart3";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ uart3_pins_cts_rts_a: uart3-cts-rts@0 {
-+ allwinner,pins = "PG11", "PG12";
-+ allwinner,function = "uart3";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ i2c0_pins_a: i2c0@0 {
-+ allwinner,pins = "PB0", "PB1";
-+ allwinner,function = "i2c0";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ i2c1_pins_a: i2c1@0 {
-+ allwinner,pins = "PB15", "PB16";
-+ allwinner,function = "i2c1";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ i2c2_pins_a: i2c2@0 {
-+ allwinner,pins = "PB17", "PB18";
-+ allwinner,function = "i2c2";
-+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+
-+ mmc0_pins_a: mmc0@0 {
-+ allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
-+ allwinner,function = "mmc0";
-+ allwinner,drive = <SUN4I_PINCTRL_30_MA>;
-+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-+ };
-+ };
-+
-+ timer@01c20c00 {
-+ compatible = "allwinner,sun4i-a10-timer";
-+ reg = <0x01c20c00 0x90>;
-+ interrupts = <22>;
-+ clocks = <&osc24M>;
-+ };
-+
-+ wdt: watchdog@01c20c90 {
-+ compatible = "allwinner,sun4i-a10-wdt";
-+ reg = <0x01c20c90 0x10>;
-+ };
-+
-+ lradc: lradc@01c22800 {
-+ compatible = "allwinner,sun4i-a10-lradc-keys";
-+ reg = <0x01c22800 0x100>;
-+ interrupts = <31>;
-+ status = "disabled";
-+ };
-+
-+ sid: eeprom@01c23800 {
-+ compatible = "allwinner,sun4i-a10-sid";
-+ reg = <0x01c23800 0x10>;
-+ };
-+
-+ rtp: rtp@01c25000 {
-+ compatible = "allwinner,sun4i-a10-ts";
-+ reg = <0x01c25000 0x100>;
-+ interrupts = <29>;
-+ #thermal-sensor-cells = <0>;
-+ };
-+
-+ uart1: serial@01c28400 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x01c28400 0x400>;
-+ interrupts = <2>;
-+ reg-shift = <2>;
-+ reg-io-width = <4>;
-+ clocks = <&apb1_gates 17>;
-+ status = "disabled";
-+ };
-+
-+ uart3: serial@01c28c00 {
-+ compatible = "snps,dw-apb-uart";
-+ reg = <0x01c28c00 0x400>;
-+ interrupts = <4>;
-+ reg-shift = <2>;
-+ reg-io-width = <4>;
-+ clocks = <&apb1_gates 19>;
-+ status = "disabled";
-+ };
-+
-+ i2c0: i2c@01c2ac00 {
-+ compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
-+ reg = <0x01c2ac00 0x400>;
-+ interrupts = <7>;
-+ clocks = <&apb1_gates 0>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ i2c1: i2c@01c2b000 {
-+ compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
-+ reg = <0x01c2b000 0x400>;
-+ interrupts = <8>;
-+ clocks = <&apb1_gates 1>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ i2c2: i2c@01c2b400 {
-+ compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
-+ reg = <0x01c2b400 0x400>;
-+ interrupts = <9>;
-+ clocks = <&apb1_gates 2>;
-+ status = "disabled";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
-+
-+ timer@01c60000 {
-+ compatible = "allwinner,sun5i-a13-hstimer";
-+ reg = <0x01c60000 0x1000>;
-+ interrupts = <82>, <83>;
-+ clocks = <&ahb_gates 28>;
-+ };
-+ };
-+};
---
-cgit v0.12
-
diff --git a/libre/linux-libre-lts/0003-SMILE-Plug-device-tree-file.patch b/libre/linux-libre-lts/0003-SMILE-Plug-device-tree-file.patch
index 3e5faf6b5..a5fc05c6d 100644
--- a/libre/linux-libre-lts/0003-SMILE-Plug-device-tree-file.patch
+++ b/libre/linux-libre-lts/0003-SMILE-Plug-device-tree-file.patch
@@ -1,7 +1,7 @@
-From 67570590136361a2bb0ed62beef15151dc1a4572 Mon Sep 17 00:00:00 2001
+From 58707640a58c98688345a01cc4aaab5e9a5302ae Mon Sep 17 00:00:00 2001
From: Kevin Mihelich <kevin@archlinuxarm.org>
Date: Fri, 5 Sep 2014 15:41:19 -0600
-Subject: [PATCH 3/8] SMILE Plug device tree file
+Subject: [PATCH 3/9] SMILE Plug device tree file
This adds a dts file for the SMILE Plug, which only differs from the Mirabox
dts with the LED definitions.
@@ -14,12 +14,12 @@ Signed-off-by: Kevin Mihelich <kevin@archlinuxarm.org>
create mode 100644 arch/arm/boot/dts/armada-370-smileplug.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
-index 992736b..2373ab3 100644
+index bb8fa02..4a41a60 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
-@@ -625,6 +625,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
- dtb-$(CONFIG_MACH_ARMADA_370) += \
+@@ -699,6 +699,7 @@ dtb-$(CONFIG_MACH_ARMADA_370) += \
armada-370-db.dtb \
+ armada-370-dlink-dns327l.dtb \
armada-370-mirabox.dtb \
+ armada-370-smileplug.dtb \
armada-370-netgear-rn102.dtb \
@@ -205,4 +205,5 @@ index 0000000..d01308a
+ };
+};
--
-2.4.4
+2.6.4
+
diff --git a/libre/linux-libre-lts/0004-ARM-dts-axp209-Add-usb_power_supply-child-node-to-the-ax209-node.patch b/libre/linux-libre-lts/0004-ARM-dts-axp209-Add-usb_power_supply-child-node-to-the-ax209-node.patch
deleted file mode 100644
index b9333b202..000000000
--- a/libre/linux-libre-lts/0004-ARM-dts-axp209-Add-usb_power_supply-child-node-to-the-ax209-node.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 5b3abbee42562a7bcdc6b589a3d8f9b5752550ed Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Tue, 22 Sep 2015 15:36:00 +0200
-Subject: [PATCH 4/5] ARM: dts: axp209: Add usb_power_supply child node to the ax209 node
-
-Add a node representing the usb power supply part of the axp209 pmic, note
-that the usb power supply and the (to be added later) ac power supply will
-each have their own child-node, so that they can be separately specified
-as power-supply for other nodes using a power-supply property with a
-phandle pointing to the right axp209 child-node.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- arch/arm/boot/dts/axp209.dtsi | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/arch/arm/boot/dts/axp209.dtsi b/arch/arm/boot/dts/axp209.dtsi
-index 24c935c..051ab3b 100644
---- a/arch/arm/boot/dts/axp209.dtsi
-+++ b/arch/arm/boot/dts/axp209.dtsi
-@@ -89,4 +89,9 @@
- regulator-name = "ldo5";
- };
- };
-+
-+ usb_power_supply: usb_power_supply {
-+ compatible = "x-powers,axp202-usb-power-supply";
-+ status = "disabled";
-+ };
- };
---
-cgit v0.12
-
diff --git a/libre/linux-libre-lts/0004-fix-mvsdio-eMMC-timing.patch b/libre/linux-libre-lts/0004-fix-mvsdio-eMMC-timing.patch
index a147f3bc0..6a6b04148 100644
--- a/libre/linux-libre-lts/0004-fix-mvsdio-eMMC-timing.patch
+++ b/libre/linux-libre-lts/0004-fix-mvsdio-eMMC-timing.patch
@@ -1,7 +1,7 @@
-From 3fe82206833efc04b2625c60eb7f3ea6972d5a53 Mon Sep 17 00:00:00 2001
+From 279ad74e38e3c692eab7c59fae909fe22ea5d1dd Mon Sep 17 00:00:00 2001
From: Kevin Mihelich <kevin@archlinuxarm.org>
Date: Fri, 5 Sep 2014 15:43:56 -0600
-Subject: [PATCH 4/8] fix mvsdio eMMC timing
+Subject: [PATCH 4/9] fix mvsdio eMMC timing
These changes from Globalscale change the MMC timing to allow the eMMC versions
of the Mirabox and SMILE Plug to work.
@@ -34,4 +34,5 @@ index a448498..14441a6 100644
host->clock = ios->clock;
host->ns_per_clk = 1000000000 / (host->base_clock / (m+1));
--
-2.4.4
+2.6.4
+
diff --git a/libre/linux-libre-lts/0005-ARM-sun5i-chip-Add-CPU-regulator-for-cpufreq.patch b/libre/linux-libre-lts/0005-ARM-sun5i-chip-Add-CPU-regulator-for-cpufreq.patch
deleted file mode 100644
index 3128e7cd5..000000000
--- a/libre/linux-libre-lts/0005-ARM-sun5i-chip-Add-CPU-regulator-for-cpufreq.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From db30fce1eea58e50ae8b2722704b4f529c394dba Mon Sep 17 00:00:00 2001
-From: Maxime Ripard <maxime.ripard@free-electrons.com>
-Date: Wed, 25 Nov 2015 16:39:04 +0100
-Subject: [PATCH 5/5] ARM: sun5i: chip: Add CPU regulator for cpufreq
-
-The current DT doesn't have a phandle to the CPU regulator in the CPU node,
-which disables the CPU voltage scaling entirely.
-
-Add that phandle.
-
-Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
----
- arch/arm/boot/dts/sun5i-r8-chip.dts | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/arch/arm/boot/dts/sun5i-r8-chip.dts b/arch/arm/boot/dts/sun5i-r8-chip.dts
-index 530ab28..f6898c6 100644
---- a/arch/arm/boot/dts/sun5i-r8-chip.dts
-+++ b/arch/arm/boot/dts/sun5i-r8-chip.dts
-@@ -70,6 +70,10 @@
- status = "okay";
- };
-
-+&cpu0 {
-+ cpu-supply = <&reg_dcdc2>;
-+};
-+
- &ehci0 {
- status = "okay";
- };
---
-cgit v0.12
-
diff --git a/libre/linux-libre-lts/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch b/libre/linux-libre-lts/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch
index 961e49c51..6ab41a175 100644
--- a/libre/linux-libre-lts/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch
+++ b/libre/linux-libre-lts/0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch
@@ -1,7 +1,7 @@
-From 0cca0b90853cd9e03a5c6d2018d1fb5c790dce59 Mon Sep 17 00:00:00 2001
+From dad3e39a200b3f91e5e4790fe95cdbfc27a18673 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 18 Feb 2014 01:43:50 -0300
-Subject: [PATCH 5/8] net/smsc95xx: Allow mac address to be set as a parameter
+Subject: [PATCH 5/9] net/smsc95xx: Allow mac address to be set as a parameter
---
drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
@@ -91,4 +91,5 @@ index 26423ad..e29a323 100644
if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
dev->net->dev_addr) == 0) {
--
-2.4.4
+2.6.4
+
diff --git a/libre/linux-libre-lts/0006-ARM-TLV320AIC23-SoC-Audio-Codec-Fix-errors-reported-.patch b/libre/linux-libre-lts/0006-ARM-TLV320AIC23-SoC-Audio-Codec-Fix-errors-reported-.patch
index 6ca1f4b74..63cd5b038 100644
--- a/libre/linux-libre-lts/0006-ARM-TLV320AIC23-SoC-Audio-Codec-Fix-errors-reported-.patch
+++ b/libre/linux-libre-lts/0006-ARM-TLV320AIC23-SoC-Audio-Codec-Fix-errors-reported-.patch
@@ -1,7 +1,7 @@
-From 493b50d16cd287231bbe11da07f82184d80ceba2 Mon Sep 17 00:00:00 2001
+From 7e8b6c3551ea6a2b4e9201188a5fb79c5970f114 Mon Sep 17 00:00:00 2001
From: dobatog <dobatog@gmail.com>
Date: Thu, 26 Feb 2015 12:32:27 +0100
-Subject: [PATCH 6/8] ARM: TLV320AIC23 SoC Audio Codec: Fix errors reported
+Subject: [PATCH 6/9] ARM: TLV320AIC23 SoC Audio Codec: Fix errors reported
related to input routing signals.
The following patch, based on stable v3.19, corrects the errors that are reported in the boot trace in reference to the Input Signals of the audio codec TLV320AIC23:
@@ -27,7 +27,7 @@ Tested-by: Max Filippov <jcmvbkbc@gmail.com>
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
-index cc17e7e..891f3aa 100644
+index cd8c02b..95e6b11 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -174,10 +174,10 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
@@ -45,6 +45,5 @@ index cc17e7e..891f3aa 100644
/* input mux */
{"Capture Source", "Line", "Line Input"},
--
-2.4.4
-
+2.6.4
diff --git a/libre/linux-libre-lts/0007-set-default-cubietruck-led-triggers.patch b/libre/linux-libre-lts/0007-set-default-cubietruck-led-triggers.patch
index 38c0482a3..f11ac2737 100644
--- a/libre/linux-libre-lts/0007-set-default-cubietruck-led-triggers.patch
+++ b/libre/linux-libre-lts/0007-set-default-cubietruck-led-triggers.patch
@@ -1,7 +1,7 @@
-From b9c28f3bd758d09374fe35e86d5d5d4aeb7c6a0a Mon Sep 17 00:00:00 2001
+From 31e04e014a3f8cc88b3755be8aa44a4d2051f53a Mon Sep 17 00:00:00 2001
From: Kevin Mihelich <kevin@archlinuxarm.org>
-Date: Sun, 14 Jun 2015 13:20:25 -0600
-Subject: [PATCH 7/8] set default cubietruck led triggers
+Date: Sat, 14 Feb 2015 12:32:27 +0100
+Subject: [PATCH 7/9] set default cubietruck led triggers
Signed-off-by: Kevin Mihelich <kevin@archlinuxarm.org>
---
@@ -9,10 +9,10 @@ Signed-off-by: Kevin Mihelich <kevin@archlinuxarm.org>
1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-index 8f74a64..1161296 100644
+index e6b0192..fff91d3 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
-@@ -205,6 +205,7 @@
+@@ -70,6 +70,7 @@
blue {
label = "cubietruck:blue:usr";
gpios = <&pio 7 21 GPIO_ACTIVE_HIGH>;
@@ -20,7 +20,7 @@ index 8f74a64..1161296 100644
};
orange {
-@@ -220,6 +221,7 @@
+@@ -85,6 +86,7 @@
green {
label = "cubietruck:green:usr";
gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>;
@@ -29,4 +29,5 @@ index 8f74a64..1161296 100644
};
--
-2.4.4
+2.6.4
+
diff --git a/libre/linux-libre-lts/0008-USB-armory-support.patch b/libre/linux-libre-lts/0008-USB-armory-support.patch
index eccf0bb62..14e8e2530 100644
--- a/libre/linux-libre-lts/0008-USB-armory-support.patch
+++ b/libre/linux-libre-lts/0008-USB-armory-support.patch
@@ -1,40 +1,46 @@
-From 163421a4fef11bea6cf4bdb4ad9de67fb340bb90 Mon Sep 17 00:00:00 2001
+From 0bef4c3483f1a30f027ae375e1c04a2e6be91150 Mon Sep 17 00:00:00 2001
From: Kevin Mihelich <kevin@archlinuxarm.org>
-Date: Sat, 7 Mar 2015 16:51:15 -0700
-Subject: [PATCH 8/8] USB armory support
+Date: Sat, 7 Feb 2015 12:32:27 +0100
+Subject: [PATCH 8/9] USB armory support
---
- arch/arm/boot/dts/Makefile | 3 +
- arch/arm/boot/dts/imx53-usbarmory-common.dtsi | 209 ++++++++++++++++++++++++++
- arch/arm/boot/dts/imx53-usbarmory-gpio.dts | 26 ++++
- arch/arm/boot/dts/imx53-usbarmory-host.dts | 18 +++
- arch/arm/boot/dts/imx53-usbarmory.dts | 18 +++
- 5 files changed, 274 insertions(+)
+ arch/arm/boot/dts/Makefile | 5 +
+ arch/arm/boot/dts/imx53-usbarmory-common.dtsi | 241 ++++++++++++++++++++++++++
+ arch/arm/boot/dts/imx53-usbarmory-gpio.dts | 26 +++
+ arch/arm/boot/dts/imx53-usbarmory-host.dts | 18 ++
+ arch/arm/boot/dts/imx53-usbarmory-i2c.dts | 32 ++++
+ arch/arm/boot/dts/imx53-usbarmory-spi.dts | 45 +++++
+ arch/arm/boot/dts/imx53-usbarmory.dts | 18 ++
+ 7 files changed, 385 insertions(+)
create mode 100644 arch/arm/boot/dts/imx53-usbarmory-common.dtsi
create mode 100644 arch/arm/boot/dts/imx53-usbarmory-gpio.dts
create mode 100644 arch/arm/boot/dts/imx53-usbarmory-host.dts
+ create mode 100644 arch/arm/boot/dts/imx53-usbarmory-i2c.dts
+ create mode 100644 arch/arm/boot/dts/imx53-usbarmory-spi.dts
create mode 100644 arch/arm/boot/dts/imx53-usbarmory.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
-index 2373ab3..27728dd 100644
+index 4a41a60..a2df2c2 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
-@@ -252,6 +252,9 @@ dtb-$(CONFIG_SOC_IMX53) += \
+@@ -268,6 +268,11 @@ dtb-$(CONFIG_SOC_IMX53) += \
imx53-smd.dtb \
imx53-tx53-x03x.dtb \
imx53-tx53-x13x.dtb \
+ imx53-usbarmory.dtb \
+ imx53-usbarmory-gpio.dtb \
+ imx53-usbarmory-host.dtb \
++ imx53-usbarmory-i2c.dtb \
++ imx53-usbarmory-spi.dtb \
imx53-voipac-bsb.dtb
dtb-$(CONFIG_SOC_IMX6Q) += \
- imx6dl-aristainetos_4.dtb \
+ imx6dl-apf6dev.dtb \
diff --git a/arch/arm/boot/dts/imx53-usbarmory-common.dtsi b/arch/arm/boot/dts/imx53-usbarmory-common.dtsi
new file mode 100644
-index 0000000..c7cbd84
+index 0000000..b73c399
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-usbarmory-common.dtsi
-@@ -0,0 +1,209 @@
+@@ -0,0 +1,241 @@
+/*
+ * USB armory MkI device tree include file
+ * http://inversepath.com/usbarmory
@@ -112,16 +118,6 @@ index 0000000..c7cbd84
+ pinctrl-names = "default";
+
+ imx53-usbarmory {
-+ pinctrl_pinheader: pinheadergrp {
-+ fsl,pins = <
-+ MX53_PAD_CSI0_DAT8__GPIO5_26 0xc0
-+ MX53_PAD_CSI0_DAT9__GPIO5_27 0xc0
-+ MX53_PAD_CSI0_DAT10__GPIO5_28 0xc0
-+ MX53_PAD_CSI0_DAT11__GPIO5_29 0xc0
-+ MX53_PAD_CSI0_DAT12__GPIO5_30 0xc0
-+ >;
-+ };
-+
+ led_pin_gpio4_27: led_gpio4_27@0 {
+ fsl,pins = <
+ MX53_PAD_DISP0_DAT6__GPIO4_27 0x80000000
@@ -139,26 +135,67 @@ index 0000000..c7cbd84
+ >;
+ };
+
-+ pinctrl_i2c1: i2c1grp {
++ pinctrl_i2c1_pmic: i2c1grp_pmic {
+ fsl,pins = <
-+ MX53_PAD_CSI0_DAT8__I2C1_SDA 0xc0000000
-+ MX53_PAD_CSI0_DAT9__I2C1_SCL 0xc0000000
++ MX53_PAD_EIM_D21__I2C1_SCL 0xc0000000
++ MX53_PAD_EIM_D28__I2C1_SDA 0xc0000000
+ >;
+ };
+
++ /*
++ UART mode pin header configration:
++ pin number: 1 2 3 4 5 6 7
++ function: GND 5V ? ? TX RX ?
++ */
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
+ MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
+ >;
+ };
++
++ /*
++ GPIO mode pin header configuration:
++ 1 2 3 4 5 6 7
++ GND 5V GPIO5[26] GPIO5[27] GPIO5[28] GPIO5[29] GPIO5[30]
++ */
+ pinctrl_gpio5: gpio5grp {
+ fsl,pins = <
-+ MX53_PAD_CSI0_DAT8__GPIO5_26 0xc0
-+ MX53_PAD_CSI0_DAT9__GPIO5_27 0xc0
-+ MX53_PAD_CSI0_DAT10__GPIO5_28 0xc0
-+ MX53_PAD_CSI0_DAT11__GPIO5_29 0xc0
-+ MX53_PAD_CSI0_DAT12__GPIO5_30 0xc0
++ MX53_PAD_CSI0_DAT8__GPIO5_26 0xc0
++ MX53_PAD_CSI0_DAT9__GPIO5_27 0xc0
++ MX53_PAD_CSI0_DAT10__GPIO5_28 0xc0
++ MX53_PAD_CSI0_DAT11__GPIO5_29 0xc0
++ MX53_PAD_CSI0_DAT12__GPIO5_30 0xc0
++ >;
++ };
++
++ /*
++ SPI mode pin header configuration:
++ 1 2 3 4 5 6 7
++ GND 5V SCLK MOSI MISO /SS0 /SS1
++ */
++ pinctrl_ecspi2: ecspi2grp {
++ fsl,pins = <
++ MX53_PAD_CSI0_DAT8__ECSPI2_SCLK 0x80000000
++ MX53_PAD_CSI0_DAT9__ECSPI2_MOSI 0x80000000
++ MX53_PAD_CSI0_DAT10__ECSPI2_MISO 0x80000000
++ MX53_PAD_CSI0_DAT11__GPIO5_29 0x80000000
++ MX53_PAD_CSI0_DAT12__GPIO5_30 0x80000000
++ >;
++ };
++
++ /*
++ I2C mode pin header configuration:
++ 1 2 3 4 5 6 7
++ GND 5V SDA SCL GPIO5[28] GPIO5[29] GPIO5[30]
++ */
++ pinctrl_i2c1_pinheader: i2c1grp_pinheader {
++ fsl,pins = <
++ MX53_PAD_CSI0_DAT8__I2C1_SDA 0xc0000000
++ MX53_PAD_CSI0_DAT9__I2C1_SCL 0xc0000000
++ MX53_PAD_CSI0_DAT10__GPIO5_28 0x80000000
++ MX53_PAD_CSI0_DAT11__GPIO5_29 0x80000000
++ MX53_PAD_CSI0_DAT12__GPIO5_30 0x80000000
+ >;
+ };
+ };
@@ -175,10 +212,11 @@ index 0000000..c7cbd84
+};
+
+&i2c1 {
++ pinctrl-0 = <&pinctrl_i2c1_pmic>;
++ status = "okay";
+ ltc3589: pmic@34 {
+ compatible = "lltc,ltc3589-2";
+ reg = <0x34>;
-+
+ regulators {
+ sw1_reg: sw1 {
+ regulator-min-microvolt = <591930>;
@@ -246,7 +284,7 @@ index 0000000..c7cbd84
+};
diff --git a/arch/arm/boot/dts/imx53-usbarmory-gpio.dts b/arch/arm/boot/dts/imx53-usbarmory-gpio.dts
new file mode 100644
-index 0000000..bf85ffa
+index 0000000..a27c759
--- /dev/null
+++ b/arch/arm/boot/dts/imx53-usbarmory-gpio.dts
@@ -0,0 +1,26 @@
@@ -270,7 +308,7 @@ index 0000000..bf85ffa
+};
+
+&iomuxc {
-+ pinctrl-0 = <&pinctrl_pinheader>;
++ pinctrl-0 = <&pinctrl_gpio5>;
+};
+
+&uart1 {
@@ -300,6 +338,95 @@ index 0000000..ea2ea45
+ dr_mode = "host";
+ status = "okay";
+};
+diff --git a/arch/arm/boot/dts/imx53-usbarmory-i2c.dts b/arch/arm/boot/dts/imx53-usbarmory-i2c.dts
+new file mode 100644
+index 0000000..c66bbb5
+--- /dev/null
++++ b/arch/arm/boot/dts/imx53-usbarmory-i2c.dts
+@@ -0,0 +1,32 @@
++/*
++ * USB armory MkI device mode device tree file
++ * http://inversepath.com/usbarmory
++ *
++ * Copyright (C) 2015, Inverse Path
++ * Andrej Rosano <andrej@inversepath.com>
++ *
++ * Licensed under GPLv2
++ */
++
++/dts-v1/;
++
++#include "imx53-usbarmory-common.dtsi"
++
++&usbotg {
++ dr_mode = "peripheral";
++ status = "okay";
++};
++
++&uart1 {
++ status = "disabled";
++};
++
++&iomuxc {
++ pinctrl-0 = <&pinctrl_i2c1_pinheader>;
++};
++
++&i2c1 {
++ ltc3589: pmic@34 {
++ status = "disabled";
++ };
++};
+diff --git a/arch/arm/boot/dts/imx53-usbarmory-spi.dts b/arch/arm/boot/dts/imx53-usbarmory-spi.dts
+new file mode 100644
+index 0000000..414d641
+--- /dev/null
++++ b/arch/arm/boot/dts/imx53-usbarmory-spi.dts
+@@ -0,0 +1,45 @@
++/*
++ * USB armory MkI device mode device tree file
++ * http://inversepath.com/usbarmory
++ *
++ * Copyright (C) 2015, Inverse Path
++ * Andrej Rosano <andrej@inversepath.com>
++ *
++ * Licensed under GPLv2
++ */
++
++/dts-v1/;
++
++#include "imx53-usbarmory-common.dtsi"
++
++&usbotg {
++ dr_mode = "peripheral";
++ status = "okay";
++};
++
++&uart1 {
++ status = "disabled";
++};
++
++&iomuxc {
++ pinctrl-0 = <&pinctrl_ecspi2>;
++};
++
++&ecspi2 {
++ fsl,spi-num-chipselects = <2>;
++ cs-gpios = <&gpio5 29 0>, <&gpio5 30 0>;
++ status = "okay";
++
++ flash: m25p40@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "st,m25p40", "st,m25p";
++ spi-max-frequency = <20000000>;
++ reg = <0>;
++
++ partition@0 {
++ label = "test-partition";
++ reg = <0x0 0x80000>;
++ };
++ };
++};
diff --git a/arch/arm/boot/dts/imx53-usbarmory.dts b/arch/arm/boot/dts/imx53-usbarmory.dts
new file mode 100644
index 0000000..902a73b
@@ -325,4 +452,5 @@ index 0000000..902a73b
+ status = "okay";
+};
--
-2.4.4
+2.6.4
+
diff --git a/libre/linux-libre-lts/0009-ARM-dts-dove-add-Dove-divider-clocks.patch b/libre/linux-libre-lts/0009-ARM-dts-dove-add-Dove-divider-clocks.patch
new file mode 100644
index 000000000..af564c2a3
--- /dev/null
+++ b/libre/linux-libre-lts/0009-ARM-dts-dove-add-Dove-divider-clocks.patch
@@ -0,0 +1,34 @@
+From 1fdf53fafef2ccc0684a3b655e716b9921642197 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Sun, 6 Dec 2015 23:28:37 +0000
+Subject: [PATCH 9/9] ARM: dts: dove: add Dove divider clocks
+
+Add the Dove divider clocks to the Dove dtsi file.
+
+Acked-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ arch/arm/boot/dts/dove.dtsi | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
+index 1791216..ea36a26 100644
+--- a/arch/arm/boot/dts/dove.dtsi
++++ b/arch/arm/boot/dts/dove.dtsi
+@@ -459,6 +459,12 @@
+ #clock-cells = <1>;
+ };
+
++ divider_clk: core-clock@0064 {
++ compatible = "marvell,dove-divider-clock";
++ reg = <0x0064 0x8>;
++ #clock-cells = <1>;
++ };
++
+ pinctrl: pin-ctrl@0200 {
+ compatible = "marvell,dove-pinctrl";
+ reg = <0x0200 0x14>,
+--
+2.6.4
+
diff --git a/libre/linux-libre-lts/PKGBUILD b/libre/linux-libre-lts/PKGBUILD
index af2e75c78..b76173923 100644
--- a/libre/linux-libre-lts/PKGBUILD
+++ b/libre/linux-libre-lts/PKGBUILD
@@ -9,8 +9,8 @@
# Based on linux-lts package
pkgbase=linux-libre-lts
-_pkgbasever=4.1-gnu
-_pkgver=4.1.21-gnu
+_pkgbasever=4.4-gnu
+_pkgver=4.4.7-gnu
_replacesarchkernel=('linux%') # '%' gets replaced with _kernelname
_replacesoldkernels=() # '%' gets replaced with _kernelname
@@ -19,8 +19,8 @@ _replacesoldmodules=() # '%' gets replaced with _kernelname
_srcname=linux-${_pkgbasever%-*}
_archpkgver=${_pkgver%-*}
pkgver=${_pkgver//-/_}
-pkgrel=1.1
-rcnrel=armv7-x7
+pkgrel=1
+rcnrel=armv7-x6
arch=('i686' 'x86_64' 'armv7h')
url="http://linux-libre.fsfla.org/"
license=('GPL2')
@@ -44,17 +44,13 @@ source=("http://linux-libre.fsfla.org/pub/linux-libre/releases/${_pkgbasever}/li
# standard config files for mkinitcpio ramdisk
'linux.preset'
'change-default-console-loglevel.patch'
+ '0001-sdhci-revert.patch'
'0001-drm-radeon-Make-the-driver-load-without-the-firmwares.patch'
'0002-usb-serial-gadget-no-TTY-hangup-on-USB-disconnect-WI.patch'
'0003-fix-Atmel-maXTouch-touchscreen-support.patch'
# armv7h patches
"https://repo.parabola.nu/other/rcn-libre/patches/${_pkgver%-*}/rcn-libre-${_pkgver%-*}-${rcnrel}.patch"
"https://repo.parabola.nu/other/rcn-libre/patches/${_pkgver%-*}/rcn-libre-${_pkgver%-*}-${rcnrel}.patch.sig"
- '0001-ARM-sunxi-Add-R8-support.patch'
- '0002-ARM-sun5i-Add-CHIP-DTS.patch'
- '0003-ARM-sun5i-Add-R8-DTSI.patch'
- '0004-ARM-dts-axp209-Add-usb_power_supply-child-node-to-the-ax209-node.patch'
- '0005-ARM-sun5i-chip-Add-CPU-regulator-for-cpufreq.patch'
'0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch'
'0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch'
'0003-SMILE-Plug-device-tree-file.patch'
@@ -62,10 +58,11 @@ source=("http://linux-libre.fsfla.org/pub/linux-libre/releases/${_pkgbasever}/li
'0005-net-smsc95xx-Allow-mac-address-to-be-set-as-a-parame.patch'
'0006-ARM-TLV320AIC23-SoC-Audio-Codec-Fix-errors-reported-.patch'
'0007-set-default-cubietruck-led-triggers.patch'
- '0008-USB-armory-support.patch')
-sha256sums=('48b2e5ea077d0a0bdcb205e67178e8eb5b2867db3b2364b701dbc801d9755324'
+ '0008-USB-armory-support.patch'
+ '0009-ARM-dts-dove-add-Dove-divider-clocks.patch')
+sha256sums=('f53e99866c751f21412737d1f06b0721e207f495c8c64f97dffb681795ee69a0'
'SKIP'
- '4344dfe5c74414baafcf05de768082788cba3c4baefe2f66d8d6e97afc0fd14a'
+ '589e412cfd54f4683c6b9512d50fe4f25d23f019633f5c57b2c8b083d74f3890'
'SKIP'
'bfd4a7f61febe63c880534dcb7c31c5b932dde6acf991810b41a939a93535494'
'SKIP'
@@ -73,29 +70,26 @@ sha256sums=('48b2e5ea077d0a0bdcb205e67178e8eb5b2867db3b2364b701dbc801d9755324'
'SKIP'
'6de8a8319271809ffdb072b68d53d155eef12438e6d04ff06a5a4db82c34fa8a'
'SKIP'
- '235a8cb8f79a38cfea0e74984b2b46b1921709a37c58f43db9dc837abcf4a469'
- '0fbf6fc9105593aa821a79b653d57d1751f57a0169927765edee626ccdd3be3d'
- 'e64cd7bf23e42a0db85e2d48a5af4fefacb26de5f517da8f268b18d1fc319769'
+ 'd862f4829d8b8a7af0cb4ac9053a25941888b2c02c36fd70091cfa0cf8d10f6e'
+ '63680e592608c8d8640d2fb8c3389afa04ee2bed8f74b1c36aed7761448f54ba'
+ '87da21f263e97f98f0dcd03280c07fa27fd1797fb70b2047f9ba20207942619c'
'f0d90e756f14533ee67afda280500511a62465b4f76adcc5effa95a40045179c'
'1256b241cd477b265a3c2d64bdc19ffe3c9bbcee82ea3994c590c2c76e767d99'
- '838d6c91ffcfa0230f048e4d0b3f664e36906041027cd280d131ff88fd9a72e8'
+ '5313df7cb5b4d005422bd4cd0dae956b2dadba8f3db904275aaf99ac53894375'
+ 'f0a10ea9a669e5200aa33656565c209718b24ff1add03ac5279c4a1f46ab8798'
'96c6c7d4057b8d08238adae85d476c863c082770a182057163a45480511d35a8'
'2ca85ee212ef8d8aab3d3c2a0cef304a355d86e7aa520e19471f56ace68a0cf4'
- '3743d0478507d160f24326241831df8c4d3f2e268bcaf2f62dfe2ef5e8a69188'
+ 'c9b668d89e08633e5ba42e7a855f7ba46bffa38c44a835aebff47c7cc33062b7'
'SKIP'
- '349691937f0a2881c5fc981d7fb85f64ad3c341ce77a716638d328750d3e9f41'
- '26274259a896a6a362bf89a5ba014c01c5126c646dcd50b51255d94743a9ad7f'
- '80d426c53296b0a04d7817caafe628135ac28abfe32cc7f4740049b89d7bd956'
- '32673476cec6024851c5e084f920c72a4c5297c092d0b40a65ab5c05089bb36e'
- 'fdb50c0b420d374de0552412a5b65f568eda3bf9dc896682578a74797c5c4dab'
- '203b07cc241f2374d1e18583fc9940cc69da134f992bff65a8b376c717aa7ea7'
- '28fb8c937c2a0dc824ea755efba26ac5a4555f9a97d79f4e31f24b23c5eae59c'
- '39bfd7f6e2df0b87b52488462edb2fbcfaf9e3eb2a974fc7b3bc22147352fece'
- '59444ed7dce62697f1c35be340b740899e1d71398b334c419ad07cea838c6ed6'
- '90cff98e43322e79c8d8b1c6456a328650f6af3ebf018086a82ab690a688da5d'
- 'ed6cf79434d3b1c10e0e141ab6bdc2aa9abfe7e7df6bbb24b2097c0e0d62ac17'
- '2c3df3d9a3d8fe11fefc485167a81c6fc53635b04ba0312bef144505dc0a6ce4'
- '0f6b0146096ee7a04938d39a013c23cfd8719f3bef0956b5c88a33e7d7ecafdc')
+ 'a851312b26800a7e189b34547d5d4b2b62a18874f07335ac6f426c32b47c3817'
+ '486976f36e1919eac5ee984cb9a8d23a972f23f22f8344eda47b487ea91047f4'
+ '6dadc17ea56d93ec0f1d0c3c98c25a7863e9ba3c4af50dc411d630a1bcc98f08'
+ '9c5d6d035c9a7103f19804c2284291d461d4b848cccd3ec07272bde68ba29513'
+ '6644705cd73c55056b5fed91cfb3199c1114b088d96dbd3c29358cd49863aeba'
+ '08d0aa76393ea2d1a853d0ea9b02aa616224ac915473ab057bb98285212bc994'
+ '1cb502674bf7a1ea79b359d1613fe891ba37f6aa64f5f5eca309d46ba01ab417'
+ '05bf1d8f94feab06bdd9fd958bc9bde4d1249a0cdeb8d3d3e16e6fac6dc5baed'
+ '5e1b8b1e9b3243a5ab315481c39b1b88f28923148659dcc0ac7ed78d9ba4f072')
validpgpkeys=(
'474402C8C582DAFBE389C427BCB7CF877E7D47A7' # Alexandre Oliva
'C92BAA713B8D53D3CAE63FC9E6974752F9704456' # André Silva
@@ -121,17 +115,12 @@ prepare() {
fi
if [ "${CARCH}" = "armv7h" ]; then
- # RCN patch (CM3 firmware deblobbed)
+ # RCN patch (CM3 firmware deblobbed and AUFS removed)
+ # Note: AUFS was removed in the RCN patch since it are being supported by
+ # linux-libre-pck through PCK patch for all available architectures.
+ # See https://wiki.parabola.nu/PCK for further details.
git apply -v "${srcdir}/rcn-libre-${_pkgver%-*}-${rcnrel}.patch"
- # Parabola patches
- # add C.H.I.P single-board computer support
- patch -p1 -i "${srcdir}/0001-ARM-sunxi-Add-R8-support.patch"
- patch -p1 -i "${srcdir}/0002-ARM-sun5i-Add-CHIP-DTS.patch"
- patch -p1 -i "${srcdir}/0003-ARM-sun5i-Add-R8-DTSI.patch"
- patch -p1 -i "${srcdir}/0004-ARM-dts-axp209-Add-usb_power_supply-child-node-to-the-ax209-node.patch"
- patch -p1 -i "${srcdir}/0005-ARM-sun5i-chip-Add-CPU-regulator-for-cpufreq.patch"
-
# ALARM patches
patch -p1 -i "${srcdir}/0001-ARM-atags-add-support-for-Marvell-s-u-boot.patch"
patch -p1 -i "${srcdir}/0002-ARM-atags-fdt-retrieve-MAC-addresses-from-Marvell-bo.patch"
@@ -141,6 +130,7 @@ prepare() {
patch -p1 -i "${srcdir}/0006-ARM-TLV320AIC23-SoC-Audio-Codec-Fix-errors-reported-.patch"
patch -p1 -i "${srcdir}/0007-set-default-cubietruck-led-triggers.patch"
patch -p1 -i "${srcdir}/0008-USB-armory-support.patch"
+ patch -p1 -i "${srcdir}/0009-ARM-dts-dove-add-Dove-divider-clocks.patch"
fi
# add freedo as boot logo
@@ -149,6 +139,11 @@ prepare() {
# add latest fixes from stable queue, if needed
# http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git
+
+ # revert http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=9faac7b95ea4f9e83b7a914084cc81ef1632fd91
+ # fixes #47778 sdhci broken on some boards
+ # https://bugzilla.kernel.org/show_bug.cgi?id=106541
+ patch -Rp1 -i "${srcdir}/0001-sdhci-revert.patch"
# set DEFAULT_CONSOLE_LOGLEVEL to 4 (same value as the 'quiet' kernel param)
# remove this when a Kconfig knob is made available by upstream
@@ -403,6 +398,11 @@ _package-headers() {
# remove unneeded architectures
find "${pkgdir}"/usr/lib/modules/${_kernver}/build/arch -mindepth 1 -maxdepth 1 -type d -not -name "$KARCH" -exec rm -rf {} +
+
+ # remove files already in docs package
+ rm -f "${pkgdir}/usr/lib/modules/${_kernver}/build/Documentation/kbuild/Kconfig.recursion-issue-01"
+ rm -f "${pkgdir}/usr/lib/modules/${_kernver}/build/Documentation/kbuild/Kconfig.recursion-issue-02"
+ rm -f "${pkgdir}/usr/lib/modules/${_kernver}/build/Documentation/kbuild/Kconfig.select-break"
}
_package-docs() {
@@ -418,7 +418,7 @@ _package-docs() {
find "${pkgdir}" -type f -exec chmod 444 {} \;
find "${pkgdir}" -type d -exec chmod 755 {} \;
- # remove a file already in linux package
+ # remove a file already in kernel package
rm -f "${pkgdir}/usr/lib/modules/${_kernver}/build/Documentation/DocBook/Makefile"
}
diff --git a/libre/linux-libre-lts/config.armv7h b/libre/linux-libre-lts/config.armv7h
index 70616be22..f071a3f9f 100644
--- a/libre/linux-libre-lts/config.armv7h
+++ b/libre/linux-libre-lts/config.armv7h
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm 4.1.7-gnu-2-lts Kernel Configuration
+# Linux/arm 4.4.6-gnu-1-lts Kernel Configuration
#
CONFIG_ARM=y
CONFIG_ARM_HAS_SG_CHAIN=y
@@ -16,6 +16,7 @@ CONFIG_LOCKDEP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_BANDGAP=y
+CONFIG_FIX_EARLYCON_MEM=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_NEED_DMA_MAP_STATE=y
@@ -87,7 +88,7 @@ CONFIG_NO_HZ_COMMON=y
# CONFIG_HZ_PERIODIC is not set
CONFIG_NO_HZ_IDLE=y
# CONFIG_NO_HZ_FULL is not set
-# CONFIG_NO_HZ is not set
+CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
#
@@ -106,17 +107,15 @@ CONFIG_TASK_IO_ACCOUNTING=y
#
# RCU Subsystem
#
-CONFIG_PREEMPT_RCU=y
+CONFIG_TREE_RCU=y
+CONFIG_RCU_EXPERT=y
CONFIG_SRCU=y
# CONFIG_TASKS_RCU is not set
CONFIG_RCU_STALL_COMMON=y
-# CONFIG_RCU_USER_QS is not set
CONFIG_RCU_FANOUT=32
CONFIG_RCU_FANOUT_LEAF=16
-# CONFIG_RCU_FANOUT_EXACT is not set
-CONFIG_RCU_FAST_NO_HZ=y
+# CONFIG_RCU_FAST_NO_HZ is not set
# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_RCU_BOOST is not set
CONFIG_RCU_KTHREAD_PRIO=0
# CONFIG_RCU_NOCB_CPU is not set
# CONFIG_RCU_EXPEDITE_BOOT is not set
@@ -129,6 +128,7 @@ CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
@@ -142,9 +142,10 @@ CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
-# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_CGROUP_WRITEBACK=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
@@ -189,7 +190,9 @@ CONFIG_BPF_SYSCALL=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
CONFIG_PCI_QUIRKS=y
+CONFIG_MEMBARRIER=y
CONFIG_EMBEDDED=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
@@ -206,13 +209,16 @@ CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_SLUB_CPU_PARTIAL=y
-# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
+CONFIG_KEXEC_CORE=y
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+CONFIG_OPTPROBES=y
CONFIG_UPROBES=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -237,10 +243,10 @@ CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP_FILTER=y
CONFIG_HAVE_CC_STACKPROTECTOR=y
-# CONFIG_CC_STACKPROTECTOR is not set
-CONFIG_CC_STACKPROTECTOR_NONE=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
-# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
@@ -267,7 +273,7 @@ CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_MODULE_SIG is not set
# CONFIG_MODULE_COMPRESS is not set
-CONFIG_STOP_MACHINE=y
+CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_BLOCK=y
CONFIG_LBDAF=y
CONFIG_BLK_DEV_BSG=y
@@ -308,12 +314,16 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_CFQ_GROUP_IOSCHED=y
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_PADATA=y
-CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
@@ -345,7 +355,6 @@ CONFIG_ARCH_MULTIPLATFORM=y
# CONFIG_ARCH_W90X900 is not set
# CONFIG_ARCH_LPC32XX is not set
# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_SHMOBILE_LEGACY is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C24XX is not set
@@ -371,7 +380,7 @@ CONFIG_MACH_MVEBU_V7=y
CONFIG_MACH_ARMADA_370=y
CONFIG_MACH_ARMADA_375=y
CONFIG_MACH_ARMADA_38X=y
-# CONFIG_MACH_ARMADA_39X is not set
+CONFIG_MACH_ARMADA_39X=y
CONFIG_MACH_ARMADA_XP=y
CONFIG_MACH_DOVE=y
# CONFIG_ARCH_ALPINE is not set
@@ -385,6 +394,7 @@ CONFIG_ARCH_KEYSTONE=y
CONFIG_ARCH_MESON=y
CONFIG_MACH_MESON6=y
CONFIG_MACH_MESON8=y
+CONFIG_MACH_MESON8B=y
CONFIG_ARCH_MXC=y
CONFIG_MXC_TZIC=y
CONFIG_HAVE_IMX_ANATOP=y
@@ -395,6 +405,10 @@ CONFIG_HAVE_IMX_SRC=y
#
# Device tree only
#
+
+#
+# Cortex-A platforms
+#
CONFIG_SOC_IMX5=y
CONFIG_SOC_IMX50=y
CONFIG_SOC_IMX51=y
@@ -403,10 +417,16 @@ CONFIG_SOC_IMX6=y
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
CONFIG_SOC_IMX6SX=y
+CONFIG_SOC_IMX6UL=y
+CONFIG_SOC_IMX7D=y
+CONFIG_SOC_LS1021A=y
+
+#
+# Cortex-A/Cortex-M asymmetric multiprocessing platforms
+#
CONFIG_SOC_VF610=y
CONFIG_VF_USE_ARM_GLOBAL_TIMER=y
# CONFIG_VF_USE_PIT_TIMER is not set
-CONFIG_SOC_LS1021A=y
CONFIG_WAND_RFKILL=m
# CONFIG_ARCH_MEDIATEK is not set
CONFIG_ARCH_OMAP=y
@@ -440,6 +460,7 @@ CONFIG_SOC_AM33XX=y
CONFIG_SOC_AM43XX=y
CONFIG_SOC_DRA7XX=y
CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_OMAP_INTERCONNECT_BARRIER=y
#
# TI OMAP2/3/4 Specific Features
@@ -453,23 +474,20 @@ CONFIG_SOC_TI81XX=y
#
# OMAP Legacy Platform Data Board Type
#
-# CONFIG_MACH_OMAP3_BEAGLE is not set
# CONFIG_MACH_OMAP_LDP is not set
-# CONFIG_MACH_OMAP3530_LV_SOM is not set
-# CONFIG_MACH_OMAP3_TORPEDO is not set
-# CONFIG_MACH_OVERO is not set
# CONFIG_MACH_OMAP3517EVM is not set
# CONFIG_MACH_OMAP3_PANDORA is not set
# CONFIG_MACH_NOKIA_RX51 is not set
-# CONFIG_MACH_CM_T35 is not set
# CONFIG_OMAP3_SDRC_AC_TIMING is not set
# CONFIG_ARCH_QCOM is not set
CONFIG_ARCH_ROCKCHIP=y
-# CONFIG_ARCH_SOCFPGA is not set
+CONFIG_ARCH_SOCFPGA=y
+# CONFIG_SOCFPGA_SUSPEND is not set
# CONFIG_PLAT_SPEAR is not set
# CONFIG_ARCH_STI is not set
# CONFIG_ARCH_S5PV210 is not set
CONFIG_ARCH_EXYNOS=y
+CONFIG_S5P_DEV_MFC=y
# CONFIG_ARCH_EXYNOS3 is not set
CONFIG_ARCH_EXYNOS4=y
CONFIG_ARCH_EXYNOS5=y
@@ -498,7 +516,6 @@ CONFIG_PLAT_SAMSUNG=y
#
# Boot options
#
-CONFIG_S5P_DEV_MFC=y
#
# Power management
@@ -518,11 +535,18 @@ CONFIG_ARCH_TEGRA_2x_SOC=y
CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_ARCH_TEGRA_114_SOC=y
CONFIG_ARCH_TEGRA_124_SOC=y
+# CONFIG_ARCH_UNIPHIER is not set
# CONFIG_ARCH_U8500 is not set
-# CONFIG_ARCH_VEXPRESS is not set
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y
+CONFIG_ARCH_VEXPRESS_DCSCB=y
+CONFIG_ARCH_VEXPRESS_SPC=y
+CONFIG_ARCH_VEXPRESS_TC2_PM=y
# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
CONFIG_ARCH_ZYNQ=y
CONFIG_PLAT_ORION=y
+CONFIG_PLAT_VERSATILE=y
CONFIG_ARCH_SUPPORTS_FIRMWARE=y
CONFIG_ARCH_SUPPORTS_TRUSTED_FOUNDATIONS=y
@@ -571,12 +595,13 @@ CONFIG_MIGHT_HAVE_CACHE_L2X0=y
CONFIG_CACHE_L2X0=y
CONFIG_PL310_ERRATA_588369=y
CONFIG_PL310_ERRATA_727915=y
-# CONFIG_PL310_ERRATA_753970 is not set
+CONFIG_PL310_ERRATA_753970=y
CONFIG_PL310_ERRATA_769419=y
CONFIG_CACHE_TAUROS2=y
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARM_HEAVY_MB=y
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
# CONFIG_ARM_KERNMEM_PERMS is not set
CONFIG_IWMMXT=y
@@ -592,7 +617,6 @@ CONFIG_ARM_ERRATA_775420=y
CONFIG_ARM_ERRATA_798181=y
# CONFIG_ARM_ERRATA_773022 is not set
CONFIG_ICST=y
-CONFIG_TI_PRIV_EDMA=y
#
# Bus support
@@ -603,8 +627,8 @@ CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_SYSCALL=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
-# CONFIG_PCI_STUB is not set
+CONFIG_PCI_REALLOC_ENABLE_AUTO=y
+CONFIG_PCI_STUB=m
# CONFIG_PCI_IOV is not set
# CONFIG_PCI_PRI is not set
# CONFIG_PCI_PASID is not set
@@ -612,19 +636,26 @@ CONFIG_PCI_MSI=y
#
# PCI host controller drivers
#
-# CONFIG_PCI_DRA7XX is not set
CONFIG_PCI_MVEBU=y
+CONFIG_PCIE_DW=y
# CONFIG_PCI_EXYNOS is not set
-# CONFIG_PCI_IMX6 is not set
+CONFIG_PCI_IMX6=y
CONFIG_PCI_TEGRA=y
# CONFIG_PCI_HOST_GENERIC is not set
# CONFIG_PCI_KEYSTONE is not set
-# CONFIG_PCIE_XILINX is not set
+CONFIG_PCIE_XILINX=y
# CONFIG_PCI_LAYERSCAPE is not set
# CONFIG_PCIE_IPROC is not set
+# CONFIG_PCIE_ALTERA is not set
CONFIG_PCIEPORTBUS=y
-# CONFIG_PCIEAER is not set
-# CONFIG_PCIEASPM is not set
+CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIEAER_INJECT=m
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
CONFIG_PCIE_PME=y
# CONFIG_PCCARD is not set
@@ -645,6 +676,7 @@ CONFIG_BIG_LITTLE=y
CONFIG_BL_SWITCHER=y
# CONFIG_BL_SWITCHER_DUMMY_IF is not set
CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_1G is not set
CONFIG_PAGE_OFFSET=0xC0000000
@@ -652,12 +684,11 @@ CONFIG_NR_CPUS=8
CONFIG_HOTPLUG_CPU=y
CONFIG_ARM_PSCI=y
CONFIG_ARCH_NR_GPIO=1024
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_PREEMPT=y
-CONFIG_PREEMPT_COUNT=y
-CONFIG_HZ_FIXED=200
-CONFIG_HZ=200
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=100
+CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
# CONFIG_THUMB2_KERNEL is not set
CONFIG_AEABI=y
@@ -668,15 +699,16 @@ CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
CONFIG_HAVE_ARCH_PFN_VALID=y
CONFIG_HIGHMEM=y
CONFIG_HIGHPTE=y
+CONFIG_CPU_SW_DOMAIN_PAN=y
CONFIG_HW_PERF_EVENTS=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_NO_BOOTMEM=y
CONFIG_MEMORY_ISOLATION=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MEMORY_BALLOON=y
CONFIG_BALLOON_COMPACTION=y
@@ -685,6 +717,7 @@ CONFIG_MIGRATION=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_BOUNCE=y
+CONFIG_MMU_NOTIFIER=y
CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_CLEANCACHE is not set
@@ -696,9 +729,11 @@ CONFIG_CMA_AREAS=7
CONFIG_ZSWAP=y
CONFIG_ZPOOL=y
CONFIG_ZBUD=y
-CONFIG_ZSMALLOC=y
+CONFIG_ZSMALLOC=m
# CONFIG_PGTABLE_MAPPING is not set
# CONFIG_ZSMALLOC_STAT is not set
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_UACCESS_WITH_MEMCPY is not set
@@ -753,17 +788,14 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPUFREQ_DT=y
CONFIG_ARM_BIG_LITTLE_CPUFREQ=y
CONFIG_ARM_DT_BL_CPUFREQ=y
-CONFIG_ARM_EXYNOS_CPUFREQ=y
-CONFIG_ARM_EXYNOS4210_CPUFREQ=y
-CONFIG_ARM_EXYNOS4X12_CPUFREQ=y
-CONFIG_ARM_EXYNOS5250_CPUFREQ=y
-# CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW is not set
+CONFIG_ARM_VEXPRESS_SPC_CPUFREQ=y
CONFIG_ARM_EXYNOS5440_CPUFREQ=y
CONFIG_ARM_IMX6Q_CPUFREQ=y
# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set
# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
-CONFIG_ARM_TEGRA_CPUFREQ=y
-# CONFIG_QORIQ_CPUFREQ is not set
+CONFIG_ARM_TEGRA20_CPUFREQ=y
+CONFIG_ARM_TEGRA124_CPUFREQ=y
+CONFIG_QORIQ_CPUFREQ=y
#
# CPU Idle
@@ -798,6 +830,7 @@ CONFIG_COREDUMP=y
#
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
+# CONFIG_SUSPEND_SKIP_SYNC is not set
CONFIG_HIBERNATE_CALLBACKS=y
CONFIG_HIBERNATION=y
CONFIG_PM_STD_PARTITION=""
@@ -824,6 +857,7 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARM_CPU_SUSPEND=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_NET=y
+CONFIG_NET_INGRESS=y
#
# Networking options
@@ -867,7 +901,6 @@ CONFIG_NET_IPVTI=m
CONFIG_NET_UDP_TUNNEL=m
CONFIG_NET_FOU=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -894,6 +927,7 @@ CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_TCP_CONG_DCTCP=m
+CONFIG_TCP_CONG_CDG=m
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -906,6 +940,7 @@ CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_ILA=m
CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
@@ -935,6 +970,7 @@ CONFIG_BRIDGE_NETFILTER=m
#
# Core Netfilter Configuration
#
+CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_ACCT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
@@ -967,7 +1003,7 @@ CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_NETLINK_TIMEOUT=m
CONFIG_NF_CT_NETLINK_HELPER=m
-CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
+CONFIG_NETFILTER_NETLINK_GLUE_CT=y
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_NF_NAT_PROTO_DCCP=m
@@ -982,6 +1018,7 @@ CONFIG_NF_NAT_REDIRECT=m
CONFIG_NETFILTER_SYNPROXY=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -1124,6 +1161,7 @@ CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_FO=m
+CONFIG_IP_VS_OVF=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
@@ -1152,7 +1190,9 @@ CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_NF_TABLES_IPV4=m
CONFIG_NFT_CHAIN_ROUTE_IPV4=m
CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_DUP_IPV4=m
CONFIG_NF_LOG_ARP=m
CONFIG_NF_LOG_IPV4=m
CONFIG_NF_REJECT_IPV4=m
@@ -1195,6 +1235,8 @@ CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_NF_TABLES_IPV6=m
CONFIG_NFT_CHAIN_ROUTE_IPV6=m
CONFIG_NFT_REJECT_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
+CONFIG_NF_DUP_IPV6=m
CONFIG_NF_REJECT_IPV6=m
CONFIG_NF_LOG_IPV6=m
CONFIG_NF_NAT_IPV6=m
@@ -1272,9 +1314,11 @@ CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y
CONFIG_SCTP_COOKIE_HMAC_MD5=y
CONFIG_SCTP_COOKIE_HMAC_SHA1=y
CONFIG_RDS=m
+CONFIG_RDS_RDMA=m
CONFIG_RDS_TCP=m
# CONFIG_RDS_DEBUG is not set
CONFIG_TIPC=m
+CONFIG_TIPC_MEDIA_IB=y
CONFIG_TIPC_MEDIA_UDP=y
CONFIG_ATM=m
CONFIG_ATM_CLIP=m
@@ -1319,6 +1363,7 @@ CONFIG_6LOWPAN_NHC_MOBILITY=m
CONFIG_6LOWPAN_NHC_ROUTING=m
CONFIG_6LOWPAN_NHC_UDP=m
CONFIG_IEEE802154=m
+# CONFIG_IEEE802154_NL802154_EXPERIMENTAL is not set
CONFIG_IEEE802154_SOCKET=m
CONFIG_IEEE802154_6LOWPAN=m
CONFIG_MAC802154=m
@@ -1369,6 +1414,7 @@ CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_NET_CLS_BPF=m
+# CONFIG_NET_CLS_FLOWER is not set
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_STACK=32
CONFIG_NET_EMATCH_CMP=m
@@ -1411,9 +1457,11 @@ CONFIG_NETLINK_MMAP=y
CONFIG_NETLINK_DIAG=m
CONFIG_MPLS=y
CONFIG_NET_MPLS_GSO=m
-# CONFIG_MPLS_ROUTING is not set
+CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
CONFIG_HSR=m
# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_XPS=y
@@ -1448,8 +1496,16 @@ CONFIG_CAN_TI_HECC=m
# CONFIG_CAN_FLEXCAN is not set
CONFIG_CAN_GRCAN=m
# CONFIG_CAN_RCAR is not set
-# CONFIG_CAN_XILINXCAN is not set
-# CONFIG_CAN_SJA1000 is not set
+CONFIG_CAN_SUN4I=m
+CONFIG_CAN_XILINXCAN=m
+CONFIG_CAN_SJA1000=m
+CONFIG_CAN_SJA1000_ISA=m
+# CONFIG_CAN_SJA1000_PLATFORM is not set
+CONFIG_CAN_EMS_PCI=m
+CONFIG_CAN_PEAK_PCI=m
+CONFIG_CAN_PEAK_PCIEC=y
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
CONFIG_CAN_C_CAN=m
CONFIG_CAN_C_CAN_PLATFORM=m
# CONFIG_CAN_C_CAN_PCI is not set
@@ -1531,6 +1587,7 @@ CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
+CONFIG_BT_HS=y
CONFIG_BT_LE=y
CONFIG_BT_6LOWPAN=m
# CONFIG_BT_SELFTEST is not set
@@ -1541,8 +1598,11 @@ CONFIG_BT_DEBUGFS=y
#
CONFIG_BT_INTEL=m
CONFIG_BT_BCM=m
+CONFIG_BT_RTL=m
+CONFIG_BT_QCA=m
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTUSB_BCM=y
+CONFIG_BT_HCIBTUSB_RTL=y
CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_H4=y
@@ -1550,8 +1610,9 @@ CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_ATH3K=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_3WIRE=y
-# CONFIG_BT_HCIUART_INTEL is not set
+CONFIG_BT_HCIUART_INTEL=y
CONFIG_BT_HCIUART_BCM=y
+CONFIG_BT_HCIUART_QCA=y
CONFIG_BT_HCIBCM203X=m
CONFIG_BT_HCIBPA10X=m
CONFIG_BT_HCIBFUSB=m
@@ -1578,7 +1639,9 @@ CONFIG_NL80211_TESTMODE=y
CONFIG_CFG80211_DEFAULT_PS=y
# CONFIG_CFG80211_DEBUGFS is not set
# CONFIG_CFG80211_INTERNAL_REGDB is not set
-# CONFIG_CFG80211_WEXT is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_CFG80211_WEXT_EXPORT=y
CONFIG_LIB80211=m
CONFIG_LIB80211_CRYPT_WEP=m
CONFIG_LIB80211_CRYPT_CCMP=m
@@ -1596,6 +1659,7 @@ CONFIG_MAC80211_LEDS=y
# CONFIG_MAC80211_DEBUGFS is not set
# CONFIG_MAC80211_MESSAGE_TRACING is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
CONFIG_WIMAX=m
CONFIG_WIMAX_DEBUG_LEVEL=8
CONFIG_RFKILL=m
@@ -1604,7 +1668,8 @@ CONFIG_RFKILL_INPUT=y
CONFIG_RFKILL_REGULATOR=m
# CONFIG_RFKILL_GPIO is not set
CONFIG_NET_9P=m
-# CONFIG_NET_9P_VIRTIO is not set
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NET_9P_RDMA=m
# CONFIG_NET_9P_DEBUG is not set
# CONFIG_CAIF is not set
CONFIG_CEPH_LIB=m
@@ -1613,7 +1678,8 @@ CONFIG_CEPH_LIB=m
CONFIG_NFC=m
CONFIG_NFC_DIGITAL=m
CONFIG_NFC_NCI=m
-CONFIG_NFC_NCI_SPI=y
+CONFIG_NFC_NCI_SPI=m
+# CONFIG_NFC_NCI_UART is not set
CONFIG_NFC_HCI=m
CONFIG_NFC_SHDLC=y
@@ -1625,15 +1691,20 @@ CONFIG_NFC_WILINK=m
# CONFIG_NFC_TRF7970A is not set
CONFIG_NFC_SIM=m
CONFIG_NFC_PORT100=m
+# CONFIG_NFC_FDP is not set
CONFIG_NFC_PN544=m
CONFIG_NFC_PN544_I2C=m
CONFIG_NFC_MICROREAD=m
CONFIG_NFC_MICROREAD_I2C=m
CONFIG_NFC_MRVL=m
CONFIG_NFC_MRVL_USB=m
+# CONFIG_NFC_MRVL_I2C is not set
+# CONFIG_NFC_MRVL_SPI is not set
# CONFIG_NFC_ST21NFCA is not set
-# CONFIG_NFC_ST21NFCB is not set
+# CONFIG_NFC_ST_NCI is not set
# CONFIG_NFC_NXP_NCI is not set
+# CONFIG_NFC_S3FWRN5_I2C is not set
+CONFIG_LWTUNNEL=y
CONFIG_HAVE_BPF_JIT=y
#
@@ -1645,15 +1716,16 @@ CONFIG_TEGRA_AHB=y
#
# Generic Driver Options
#
-CONFIG_UEVENT_HELPER=y
-CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_UEVENT_HELPER is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
+CONFIG_EXTRA_FIRMWARE="am335x-bone-scale-data.bin am335x-evm-scale-data.bin am43x-evm-scale-data.bin"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_FW_LOADER_USER_HELPER=y
# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
CONFIG_WANT_DEV_COREDUMP=y
CONFIG_ALLOW_DEV_COREDUMP=y
@@ -1675,7 +1747,7 @@ CONFIG_DMA_CMA=y
#
# Default contiguous memory area size:
#
-CONFIG_CMA_SIZE_MBYTES=16
+CONFIG_CMA_SIZE_MBYTES=24
CONFIG_CMA_SIZE_SEL_MBYTES=y
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
# CONFIG_CMA_SIZE_SEL_MIN is not set
@@ -1686,16 +1758,19 @@ CONFIG_CMA_ALIGNMENT=8
# Bus devices
#
CONFIG_ARM_CCI=y
+CONFIG_ARM_CCI_PMU=y
CONFIG_ARM_CCI400_COMMON=y
CONFIG_ARM_CCI400_PMU=y
CONFIG_ARM_CCI400_PORT_CTRL=y
+CONFIG_ARM_CCI500_PMU=y
# CONFIG_ARM_CCN is not set
# CONFIG_BRCMSTB_GISB_ARB is not set
# CONFIG_IMX_WEIM is not set
CONFIG_MVEBU_MBUS=y
CONFIG_OMAP_INTERCONNECT=y
CONFIG_OMAP_OCP2SCP=y
-# CONFIG_VEXPRESS_CONFIG is not set
+CONFIG_SUNXI_RSB=y
+CONFIG_VEXPRESS_CONFIG=y
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
CONFIG_MTD=y
@@ -1703,7 +1778,7 @@ CONFIG_MTD=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_OF_PARTS=m
CONFIG_MTD_AR7_PARTS=m
#
@@ -1759,7 +1834,7 @@ CONFIG_MTD_PHYSMAP=m
# CONFIG_MTD_PHYSMAP_COMPAT is not set
CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_IMPA7 is not set
-# CONFIG_MTD_INTEL_VR_NOR is not set
+CONFIG_MTD_INTEL_VR_NOR=m
CONFIG_MTD_PLATRAM=m
#
@@ -1784,21 +1859,24 @@ CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_ECC_SMC=y
CONFIG_MTD_NAND=y
# CONFIG_MTD_NAND_ECC_BCH is not set
-# CONFIG_MTD_SM_COMMON is not set
-# CONFIG_MTD_NAND_DENALI is not set
+CONFIG_MTD_SM_COMMON=m
+# CONFIG_MTD_NAND_DENALI_PCI is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
# CONFIG_MTD_NAND_GPIO is not set
# CONFIG_MTD_NAND_OMAP2 is not set
# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
CONFIG_MTD_NAND_IDS=y
-# CONFIG_MTD_NAND_RICOH is not set
+CONFIG_MTD_NAND_RICOH=m
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_DOCG4 is not set
-# CONFIG_MTD_NAND_CAFE is not set
+CONFIG_MTD_NAND_CAFE=m
CONFIG_MTD_NAND_PXA3xx=y
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_GPMI_NAND is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
# CONFIG_MTD_NAND_PLATFORM is not set
# CONFIG_MTD_NAND_ORION is not set
+# CONFIG_MTD_NAND_VF610_NFC is not set
CONFIG_MTD_NAND_MXC=m
# CONFIG_MTD_NAND_DAVINCI is not set
CONFIG_MTD_NAND_SUNXI=y
@@ -1828,10 +1906,6 @@ CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_DTC=y
CONFIG_OF=y
-
-#
-# Device Tree and Open Firmware support
-#
# CONFIG_OF_UNITTEST is not set
CONFIG_OF_FLATTREE=y
CONFIG_OF_EARLY_FLATTREE=y
@@ -1852,10 +1926,9 @@ CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_NULL_BLK=m
-# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
CONFIG_ZRAM=m
CONFIG_ZRAM_LZ4_COMPRESS=y
-# CONFIG_ZRAM_DEBUG is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
@@ -1866,19 +1939,18 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_DRBD=m
# CONFIG_DRBD_FAULT_INJECTION is not set
CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_NVME is not set
CONFIG_BLK_DEV_OSD=m
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384
-# CONFIG_BLK_DEV_PMEM is not set
# CONFIG_CDROM_PKTCDVD is not set
CONFIG_ATA_OVER_ETH=m
# CONFIG_MG_DISK is not set
# CONFIG_VIRTIO_BLK is not set
CONFIG_BLK_DEV_RBD=m
# CONFIG_BLK_DEV_RSXX is not set
+CONFIG_BLK_DEV_NVME=m
#
# Misc devices
@@ -1889,8 +1961,9 @@ CONFIG_AD525X_DPOT_I2C=m
CONFIG_AD525X_DPOT_SPI=m
# CONFIG_DUMMY_IRQ is not set
# CONFIG_PHANTOM is not set
-# CONFIG_SGI_IOC4 is not set
-# CONFIG_TIFM_CORE is not set
+CONFIG_SGI_IOC4=m
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
CONFIG_ICS932S401=y
CONFIG_ENCLOSURE_SERVICES=m
# CONFIG_HP_ILO is not set
@@ -1904,11 +1977,13 @@ CONFIG_SENSORS_APDS990X=m
CONFIG_HMC6352=m
CONFIG_DS1682=m
CONFIG_TI_DAC7512=m
+CONFIG_ARM_CHARLCD=y
# CONFIG_BMP085_I2C is not set
# CONFIG_BMP085_SPI is not set
# CONFIG_USB_SWITCH_FSA9480 is not set
# CONFIG_LATTICE_ECP3_CONFIG is not set
CONFIG_SRAM=y
+CONFIG_VEXPRESS_SYSCFG=y
CONFIG_BONE_CAPEMGR=y
# CONFIG_DEV_OVERLAYMGR is not set
CONFIG_TIEQEP=m
@@ -1923,8 +1998,9 @@ CONFIG_EEPROM_LEGACY=m
CONFIG_EEPROM_MAX6875=m
CONFIG_EEPROM_93CX6=m
CONFIG_EEPROM_93XX46=m
-# CONFIG_EEPROM_SUNXI_SID is not set
-# CONFIG_CB710_CORE is not set
+CONFIG_CB710_CORE=m
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
#
# Texas Instruments shared transport line discipline
@@ -1943,6 +2019,10 @@ CONFIG_ALTERA_STAPL=m
#
#
+# SCIF Bus Driver
+#
+
+#
# Intel MIC Host Driver
#
@@ -1951,12 +2031,22 @@ CONFIG_ALTERA_STAPL=m
#
#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
# Argus cape driver for beaglebone black
#
CONFIG_CAPE_BONE_ARGUS=y
# CONFIG_BEAGLEBONE_PINMUX_HELPER is not set
# CONFIG_ECHO is not set
# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+# CONFIG_CXL_EEH is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -1967,7 +2057,7 @@ CONFIG_SCSI_MOD=y
CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_SCSI_DMA=y
-# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_NETLINK=y
# CONFIG_SCSI_MQ_DEFAULT is not set
CONFIG_SCSI_PROC_FS=y
@@ -1989,62 +2079,87 @@ CONFIG_CHR_DEV_SG=y
#
# SCSI Transports
#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
CONFIG_SCSI_ISCSI_ATTRS=y
-# CONFIG_SCSI_SAS_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_ATA is not set
+CONFIG_SCSI_SAS_HOST_SMP=y
+CONFIG_SCSI_SRP_ATTRS=m
CONFIG_SCSI_LOWLEVEL=y
CONFIG_ISCSI_TCP=y
CONFIG_ISCSI_BOOT_SYSFS=y
-# CONFIG_SCSI_CXGB3_ISCSI is not set
-# CONFIG_SCSI_CXGB4_ISCSI is not set
-# CONFIG_SCSI_BNX2_ISCSI is not set
+CONFIG_SCSI_CXGB3_ISCSI=m
+CONFIG_SCSI_CXGB4_ISCSI=m
+CONFIG_SCSI_BNX2_ISCSI=m
+CONFIG_SCSI_BNX2X_FCOE=m
# CONFIG_BE2ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_HPSA is not set
+CONFIG_SCSI_HPSA=m
# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_3W_SAS is not set
-# CONFIG_SCSI_ACARD is not set
+CONFIG_SCSI_3W_SAS=m
+CONFIG_SCSI_ACARD=m
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_MVSAS is not set
-# CONFIG_SCSI_MVUMI is not set
+CONFIG_SCSI_MVSAS=m
+# CONFIG_SCSI_MVSAS_DEBUG is not set
+# CONFIG_SCSI_MVSAS_TASKLET is not set
+CONFIG_SCSI_MVUMI=m
+CONFIG_SCSI_ADVANSYS=m
# CONFIG_SCSI_ARCMSR is not set
-# CONFIG_SCSI_ESAS2R is not set
+CONFIG_SCSI_ESAS2R=m
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_MPT2SAS is not set
-# CONFIG_SCSI_MPT3SAS is not set
-# CONFIG_SCSI_UFSHCD is not set
+CONFIG_SCSI_MPT3SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
+CONFIG_SCSI_MPT3SAS_MAX_SGE=128
+CONFIG_SCSI_MPT2SAS=m
+CONFIG_SCSI_UFSHCD=m
+CONFIG_SCSI_UFSHCD_PCI=m
+# CONFIG_SCSI_UFSHCD_PLATFORM is not set
# CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_DMX3191D is not set
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+# CONFIG_FCOE is not set
+CONFIG_SCSI_SNIC=m
+# CONFIG_SCSI_SNIC_DEBUG_FS is not set
+CONFIG_SCSI_DMX3191D=m
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_STEX is not set
+CONFIG_SCSI_STEX=m
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_QLA_ISCSI is not set
+CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_AM53C974 is not set
+CONFIG_SCSI_AM53C974=m
# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_WD719X is not set
+CONFIG_SCSI_WD719X=m
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_PMCRAID is not set
-# CONFIG_SCSI_PM8001 is not set
-# CONFIG_SCSI_VIRTIO is not set
-# CONFIG_SCSI_DH is not set
+CONFIG_SCSI_PMCRAID=m
+CONFIG_SCSI_PM8001=m
+CONFIG_SCSI_BFA_FC=m
+CONFIG_SCSI_VIRTIO=y
+# CONFIG_SCSI_CHELSIO_FCOE is not set
+CONFIG_SCSI_DH=y
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
CONFIG_SCSI_OSD_INITIATOR=m
CONFIG_SCSI_OSD_ULD=m
CONFIG_SCSI_OSD_DPRINT_SENSE=1
# CONFIG_SCSI_OSD_DEBUG is not set
+CONFIG_HAVE_PATA_PLATFORM=y
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_ATA_VERBOSE_ERROR=y
@@ -2053,23 +2168,25 @@ CONFIG_SATA_PMP=y
#
# Controllers with non-SFF native interface
#
-# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_AHCI_IMX=y
+# CONFIG_AHCI_CEVA is not set
CONFIG_AHCI_MVEBU=y
CONFIG_AHCI_SUNXI=y
CONFIG_AHCI_TEGRA=y
+CONFIG_AHCI_QORIQ=y
# CONFIG_SATA_INIC162X is not set
-# CONFIG_SATA_ACARD_AHCI is not set
-# CONFIG_SATA_SIL24 is not set
+CONFIG_SATA_ACARD_AHCI=m
+CONFIG_SATA_SIL24=m
CONFIG_ATA_SFF=y
#
# SFF controllers with custom DMA interface
#
-# CONFIG_PDC_ADMA is not set
-# CONFIG_SATA_QSTOR is not set
-# CONFIG_SATA_SX4 is not set
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_SX4=m
CONFIG_ATA_BMDMA=y
#
@@ -2077,24 +2194,24 @@ CONFIG_ATA_BMDMA=y
#
# CONFIG_ATA_PIIX is not set
CONFIG_SATA_MV=y
-# CONFIG_SATA_NV is not set
-# CONFIG_SATA_PROMISE is not set
-# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIS is not set
-# CONFIG_SATA_SVW is not set
-# CONFIG_SATA_ULI is not set
-# CONFIG_SATA_VIA is not set
-# CONFIG_SATA_VITESSE is not set
+CONFIG_SATA_NV=y
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_SVW=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
#
# PATA SFF controllers with BMDMA
#
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
-# CONFIG_PATA_ARTOP is not set
+CONFIG_PATA_ARTOP=m
# CONFIG_PATA_ATIIXP is not set
-# CONFIG_PATA_ATP867X is not set
-# CONFIG_PATA_CMD64X is not set
+CONFIG_PATA_ATP867X=m
+CONFIG_PATA_CMD64X=m
# CONFIG_PATA_CYPRESS is not set
# CONFIG_PATA_EFAR is not set
# CONFIG_PATA_HPT366 is not set
@@ -2102,24 +2219,24 @@ CONFIG_SATA_MV=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
CONFIG_PATA_IMX=y
-# CONFIG_PATA_IT8213 is not set
-# CONFIG_PATA_IT821X is not set
-# CONFIG_PATA_JMICRON is not set
-# CONFIG_PATA_MARVELL is not set
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_MARVELL=m
# CONFIG_PATA_NETCELL is not set
-# CONFIG_PATA_NINJA32 is not set
+CONFIG_PATA_NINJA32=m
# CONFIG_PATA_NS87415 is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_OPTIDMA is not set
# CONFIG_PATA_PDC2027X is not set
# CONFIG_PATA_PDC_OLD is not set
# CONFIG_PATA_RADISYS is not set
-# CONFIG_PATA_RDC is not set
-# CONFIG_PATA_SCH is not set
+CONFIG_PATA_RDC=m
+CONFIG_PATA_SCH=m
# CONFIG_PATA_SERVERWORKS is not set
# CONFIG_PATA_SIL680 is not set
-# CONFIG_PATA_SIS is not set
-# CONFIG_PATA_TOSHIBA is not set
+CONFIG_PATA_SIS=m
+CONFIG_PATA_TOSHIBA=m
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
@@ -2138,7 +2255,7 @@ CONFIG_PATA_OF_PLATFORM=y
#
# Generic fallback / legacy drivers
#
-# CONFIG_ATA_GENERIC is not set
+CONFIG_ATA_GENERIC=m
# CONFIG_PATA_LEGACY is not set
CONFIG_MD=y
CONFIG_BLK_DEV_MD=m
@@ -2165,6 +2282,7 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
CONFIG_DM_CACHE_MQ=m
+CONFIG_DM_CACHE_SMQ=m
CONFIG_DM_CACHE_CLEANER=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
@@ -2179,21 +2297,32 @@ CONFIG_DM_UEVENT=y
CONFIG_DM_FLAKEY=m
CONFIG_DM_VERITY=m
CONFIG_DM_SWITCH=m
-# CONFIG_DM_LOG_WRITES is not set
+CONFIG_DM_LOG_WRITES=m
CONFIG_TARGET_CORE=m
CONFIG_TCM_IBLOCK=m
CONFIG_TCM_FILEIO=m
CONFIG_TCM_PSCSI=m
-# CONFIG_TCM_USER2 is not set
+CONFIG_TCM_USER2=m
CONFIG_LOOPBACK_TARGET=m
+CONFIG_TCM_FC=m
CONFIG_ISCSI_TARGET=m
-# CONFIG_FUSION is not set
+CONFIG_SBP_TARGET=m
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LOGGING is not set
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_FIREWIRE is not set
-# CONFIG_FIREWIRE_NOSY is not set
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_SBP2=m
+CONFIG_FIREWIRE_NET=m
+CONFIG_FIREWIRE_NOSY=m
CONFIG_NETDEVICES=y
CONFIG_MII=m
CONFIG_NET_CORE=y
@@ -2212,13 +2341,15 @@ CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_NETPOLL=y
CONFIG_NET_POLL_CONTROLLER=y
CONFIG_TUN=m
+# CONFIG_TUN_VNET_CROSS_LE is not set
CONFIG_VETH=m
-# CONFIG_VIRTIO_NET is not set
+CONFIG_VIRTIO_NET=m
CONFIG_NLMON=m
# CONFIG_ARCNET is not set
CONFIG_ATM_DRIVERS=y
@@ -2226,16 +2357,25 @@ CONFIG_ATM_DUMMY=m
# CONFIG_ATM_TCP is not set
# CONFIG_ATM_LANAI is not set
# CONFIG_ATM_ENI is not set
-# CONFIG_ATM_NICSTAR is not set
+CONFIG_ATM_NICSTAR=m
+CONFIG_ATM_NICSTAR_USE_SUNI=y
+CONFIG_ATM_NICSTAR_USE_IDT77105=y
# CONFIG_ATM_IDT77252 is not set
-# CONFIG_ATM_IA is not set
-# CONFIG_ATM_FORE200E is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+# CONFIG_ATM_FORE200E_USE_TASKLET is not set
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
# CONFIG_ATM_HE is not set
-# CONFIG_ATM_SOLOS is not set
+CONFIG_ATM_SOLOS=m
#
# CAIF transport drivers
#
+# CONFIG_VHOST_NET is not set
+# CONFIG_VHOST_SCSI is not set
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
#
# Distributed Switch Architecture drivers
@@ -2243,109 +2383,229 @@ CONFIG_ATM_DUMMY=m
# CONFIG_NET_DSA_MV88E6XXX is not set
# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
CONFIG_ETHERNET=y
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_ADAPTEC is not set
+CONFIG_MDIO=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_TYPHOON=m
+CONFIG_NET_VENDOR_ADAPTEC=y
+CONFIG_ADAPTEC_STARFIRE=m
CONFIG_NET_VENDOR_AGERE=y
-# CONFIG_ET131X is not set
+CONFIG_ET131X=m
CONFIG_NET_VENDOR_ALLWINNER=y
CONFIG_SUN4I_EMAC=m
-# CONFIG_NET_VENDOR_ALTEON is not set
+CONFIG_NET_VENDOR_ALTEON=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
# CONFIG_ALTERA_TSE is not set
-# CONFIG_NET_VENDOR_AMD is not set
+CONFIG_NET_VENDOR_AMD=y
+# CONFIG_AMD8111_ETH is not set
+CONFIG_PCNET32=m
CONFIG_NET_VENDOR_ARC=y
CONFIG_ARC_EMAC_CORE=m
CONFIG_ARC_EMAC=m
CONFIG_EMAC_ROCKCHIP=m
-# CONFIG_NET_VENDOR_ATHEROS is not set
+CONFIG_NET_VENDOR_ATHEROS=y
+CONFIG_ATL2=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_ATL1C=m
+CONFIG_ALX=m
+# CONFIG_NET_VENDOR_AURORA is not set
# CONFIG_NET_CADENCE is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_BROCADE is not set
-# CONFIG_NET_VENDOR_CHELSIO is not set
-# CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_CISCO is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BCMGENET is not set
+CONFIG_BNX2=m
+CONFIG_CNIC=m
+CONFIG_TIGON3=m
+CONFIG_BNX2X=m
+# CONFIG_BNX2X_VXLAN is not set
+# CONFIG_SYSTEMPORT is not set
+# CONFIG_BNXT is not set
+CONFIG_NET_VENDOR_BROCADE=y
+CONFIG_BNA=m
+CONFIG_NET_VENDOR_CAVIUM=y
+CONFIG_NET_VENDOR_CHELSIO=y
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4_DCB=y
+CONFIG_CHELSIO_T4VF=m
+CONFIG_NET_VENDOR_CIRRUS=y
+# CONFIG_CS89x0 is not set
+CONFIG_NET_VENDOR_CISCO=y
+CONFIG_ENIC=m
# CONFIG_DM9000 is not set
# CONFIG_DNET is not set
-# CONFIG_NET_VENDOR_DEC is not set
-# CONFIG_NET_VENDOR_DLINK is not set
-# CONFIG_NET_VENDOR_EMULEX is not set
-# CONFIG_NET_VENDOR_EXAR is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_NET_VENDOR_DEC=y
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_DE2104X_DSL=0
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+CONFIG_TULIP_NAPI_HW_MITIGATION=y
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_NET_VENDOR_DLINK=y
+CONFIG_DL2K=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_NET_VENDOR_EMULEX=y
+CONFIG_BE2NET=m
+CONFIG_BE2NET_HWMON=y
+CONFIG_BE2NET_VXLAN=y
+CONFIG_NET_VENDOR_EZCHIP=y
+# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set
+CONFIG_NET_VENDOR_EXAR=y
+CONFIG_S2IO=m
+CONFIG_VXGE=m
+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set
+CONFIG_NET_VENDOR_FARADAY=y
+# CONFIG_FTMAC100 is not set
+# CONFIG_FTGMAC100 is not set
CONFIG_NET_VENDOR_FREESCALE=y
CONFIG_FEC=y
# CONFIG_FSL_PQ_MDIO is not set
# CONFIG_FSL_XGMAC_MDIO is not set
+# CONFIG_GIANFAR is not set
CONFIG_NET_VENDOR_HISILICON=y
# CONFIG_HIX5HD2_GMAC is not set
# CONFIG_HIP04_ETH is not set
-# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_HNS is not set
+# CONFIG_HNS_DSAF is not set
+# CONFIG_HNS_ENET is not set
+CONFIG_NET_VENDOR_HP=y
+# CONFIG_HP100 is not set
CONFIG_NET_VENDOR_INTEL=y
-# CONFIG_E100 is not set
-# CONFIG_E1000 is not set
-# CONFIG_E1000E is not set
+CONFIG_E100=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
CONFIG_IGB=m
CONFIG_IGB_HWMON=y
-# CONFIG_IGBVF is not set
-# CONFIG_IXGB is not set
-# CONFIG_IXGBE is not set
-# CONFIG_IXGBEVF is not set
-# CONFIG_I40E is not set
-# CONFIG_I40EVF is not set
+CONFIG_IGBVF=m
+CONFIG_IXGB=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_VXLAN=y
+CONFIG_IXGBE_HWMON=y
+CONFIG_IXGBE_DCB=y
+CONFIG_IXGBEVF=m
+CONFIG_I40E=m
+CONFIG_I40E_VXLAN=y
+CONFIG_I40E_DCB=y
+CONFIG_I40EVF=m
# CONFIG_FM10K is not set
CONFIG_NET_VENDOR_I825XX=y
-# CONFIG_IP1000 is not set
-# CONFIG_JME is not set
+CONFIG_JME=m
CONFIG_NET_VENDOR_MARVELL=y
CONFIG_MV643XX_ETH=y
CONFIG_MVMDIO=y
CONFIG_MVNETA=m
CONFIG_MVPP2=m
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKGE_GENESIS=y
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
CONFIG_NET_VENDOR_MELLANOX=y
-# CONFIG_MLX4_EN is not set
-# CONFIG_MLX4_CORE is not set
-# CONFIG_MLX5_CORE is not set
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_EN_DCB=y
+CONFIG_MLX4_EN_VXLAN=y
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_MLX5_CORE=m
+CONFIG_MLX5_CORE_EN=y
+# CONFIG_MLXSW_CORE is not set
CONFIG_NET_VENDOR_MICREL=y
-# CONFIG_KS8842 is not set
+CONFIG_KS8842=m
CONFIG_KS8851=m
# CONFIG_KS8851_MLL is not set
# CONFIG_KSZ884X_PCI is not set
-# CONFIG_NET_VENDOR_MICROCHIP is not set
-# CONFIG_NET_VENDOR_MYRI is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_NVIDIA is not set
-# CONFIG_NET_VENDOR_OKI is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ENCX24J600=m
+CONFIG_NET_VENDOR_MYRI=y
+CONFIG_MYRI10GE=m
+CONFIG_FEALNX=m
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NATSEMI=m
+CONFIG_NS83820=m
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_AX88796 is not set
+CONFIG_NE2K_PCI=m
+CONFIG_NET_VENDOR_NVIDIA=y
+# CONFIG_FORCEDETH is not set
+CONFIG_NET_VENDOR_OKI=y
# CONFIG_ETHOC is not set
-# CONFIG_NET_PACKET_ENGINE is not set
-# CONFIG_NET_VENDOR_QLOGIC is not set
+CONFIG_NET_PACKET_ENGINE=y
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_NET_VENDOR_QLOGIC=y
+CONFIG_QLA3XXX=m
+CONFIG_QLCNIC=m
+CONFIG_QLCNIC_DCB=y
+CONFIG_QLCNIC_VXLAN=y
+CONFIG_QLCNIC_HWMON=y
+CONFIG_QLGE=m
+CONFIG_NETXEN_NIC=m
+# CONFIG_QED is not set
CONFIG_NET_VENDOR_QUALCOMM=y
# CONFIG_QCA7000 is not set
CONFIG_NET_VENDOR_REALTEK=y
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
CONFIG_R8169=m
-# CONFIG_NET_VENDOR_RDC is not set
+CONFIG_NET_VENDOR_RENESAS=y
+CONFIG_NET_VENDOR_RDC=y
+CONFIG_R6040=m
CONFIG_NET_VENDOR_ROCKER=y
CONFIG_NET_VENDOR_SAMSUNG=y
# CONFIG_SXGBE_ETH is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SILAN is not set
-# CONFIG_NET_VENDOR_SIS is not set
-# CONFIG_SFC is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SILAN=y
+CONFIG_SC92031=m
+CONFIG_NET_VENDOR_SIS=y
+CONFIG_SIS900=m
+CONFIG_SIS190=m
+CONFIG_SFC=m
+CONFIG_SFC_MTD=y
+CONFIG_SFC_MCDI_MON=y
+CONFIG_SFC_MCDI_LOGGING=y
CONFIG_NET_VENDOR_SMSC=y
-# CONFIG_SMC91X is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SMC911X is not set
+CONFIG_SMC91X=m
+CONFIG_EPIC100=m
+CONFIG_SMC911X=m
CONFIG_SMSC911X=m
# CONFIG_SMSC911X_ARCH_HOOKS is not set
-# CONFIG_SMSC9420 is not set
+CONFIG_SMSC9420=m
CONFIG_NET_VENDOR_STMICRO=y
CONFIG_STMMAC_ETH=m
CONFIG_STMMAC_PLATFORM=m
+CONFIG_DWMAC_GENERIC=m
+# CONFIG_DWMAC_IPQ806X is not set
+# CONFIG_DWMAC_LPC18XX is not set
+CONFIG_DWMAC_MESON=m
+CONFIG_DWMAC_ROCKCHIP=m
+CONFIG_DWMAC_SOCFPGA=m
+# CONFIG_DWMAC_STI is not set
+CONFIG_DWMAC_SUNXI=m
# CONFIG_STMMAC_PCI is not set
-# CONFIG_NET_VENDOR_SUN is not set
-# CONFIG_NET_VENDOR_TEHUTI is not set
+CONFIG_NET_VENDOR_SUN=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+CONFIG_CASSINI=m
+CONFIG_NIU=m
+CONFIG_NET_VENDOR_SYNOPSYS=y
+# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set
+CONFIG_NET_VENDOR_TEHUTI=y
+CONFIG_TEHUTI=m
CONFIG_NET_VENDOR_TI=y
CONFIG_TI_DAVINCI_EMAC=y
CONFIG_TI_DAVINCI_MDIO=y
@@ -2354,18 +2614,26 @@ CONFIG_TI_CPSW_PHY_SEL=y
CONFIG_TI_CPSW_ALE=y
CONFIG_TI_CPSW=y
CONFIG_TI_CPTS=y
-# CONFIG_TLAN is not set
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_TLAN=m
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
CONFIG_NET_VENDOR_XILINX=y
CONFIG_XILINX_EMACLITE=m
-# CONFIG_FDDI is not set
+CONFIG_FDDI=m
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
# CONFIG_HIPPI is not set
CONFIG_PHYLIB=y
#
# MII PHY device drivers
#
+# CONFIG_AQUANTIA_PHY is not set
CONFIG_AT803X_PHY=m
CONFIG_AMD_PHY=m
CONFIG_MARVELL_PHY=y
@@ -2374,7 +2642,9 @@ CONFIG_QSEMI_PHY=m
CONFIG_LXT_PHY=m
CONFIG_CICADA_PHY=m
CONFIG_VITESSE_PHY=m
+# CONFIG_TERANETICS_PHY is not set
CONFIG_SMSC_PHY=y
+CONFIG_BCM_NET_PHYLIB=m
CONFIG_BROADCOM_PHY=m
# CONFIG_BCM7XXX_PHY is not set
CONFIG_BCM87XX_PHY=m
@@ -2384,7 +2654,10 @@ CONFIG_NATIONAL_PHY=m
CONFIG_STE10XP=m
CONFIG_LSI_ET1011C_PHY=m
CONFIG_MICREL_PHY=m
-# CONFIG_FIXED_PHY is not set
+CONFIG_DP83848_PHY=m
+CONFIG_DP83867_PHY=m
+CONFIG_MICROCHIP_PHY=m
+CONFIG_FIXED_PHY=m
# CONFIG_MDIO_BITBANG is not set
CONFIG_MDIO_SUN4I=m
# CONFIG_MDIO_BUS_MUX_GPIO is not set
@@ -2414,6 +2687,7 @@ CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_AX88179_178A=m
@@ -2449,6 +2723,7 @@ CONFIG_USB_CDC_PHONET=m
CONFIG_USB_IPHETH=m
CONFIG_USB_SIERRA_NET=m
CONFIG_USB_VL600=m
+CONFIG_USB_NET_CH9200=m
CONFIG_WLAN=y
CONFIG_LIBERTAS_THINFIRM=m
# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
@@ -2459,10 +2734,10 @@ CONFIG_AT76C50X_USB=m
CONFIG_PRISM54=m
CONFIG_USB_ZD1201=m
CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_ADM8211=m
CONFIG_RTL8180=m
CONFIG_RTL8187=m
CONFIG_RTL8187_LEDS=y
-CONFIG_ADM8211=m
CONFIG_MAC80211_HWSIM=m
CONFIG_MWL8K=m
CONFIG_ATH_COMMON=m
@@ -2496,7 +2771,9 @@ CONFIG_ATH6KL_USB=m
# CONFIG_ATH6KL_DEBUG is not set
# CONFIG_ATH6KL_TRACING is not set
CONFIG_AR5523=m
-# CONFIG_WIL6210 is not set
+CONFIG_WIL6210=m
+CONFIG_WIL6210_ISR_COR=y
+CONFIG_WIL6210_TRACING=y
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
# CONFIG_ATH10K_DEBUG is not set
@@ -2537,9 +2814,10 @@ CONFIG_BRCMUTIL=m
CONFIG_BRCMSMAC=m
CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_PROTO_BCDC=y
+CONFIG_BRCMFMAC_PROTO_MSGBUF=y
CONFIG_BRCMFMAC_SDIO=y
CONFIG_BRCMFMAC_USB=y
-# CONFIG_BRCMFMAC_PCIE is not set
+CONFIG_BRCMFMAC_PCIE=y
# CONFIG_BRCM_TRACING is not set
# CONFIG_BRCMDBG is not set
CONFIG_HOSTAP=m
@@ -2629,6 +2907,8 @@ CONFIG_RTLWIFI_USB=m
CONFIG_RTL8192C_COMMON=m
CONFIG_RTL8723_COMMON=m
CONFIG_RTLBTCOEXIST=m
+CONFIG_RTL8XXXU=m
+# CONFIG_RTL8XXXU_UNTESTED is not set
CONFIG_WL_TI=y
CONFIG_WL1251=m
CONFIG_WL1251_SPI=m
@@ -2663,15 +2943,19 @@ CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
CONFIG_IEEE802154_DRIVERS=m
CONFIG_IEEE802154_FAKELB=m
CONFIG_IEEE802154_AT86RF230=m
+# CONFIG_IEEE802154_AT86RF230_DEBUGFS is not set
CONFIG_IEEE802154_MRF24J40=m
CONFIG_IEEE802154_CC2520=m
+CONFIG_IEEE802154_ATUSB=m
# CONFIG_VMXNET3 is not set
# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
#
# Input device support
#
CONFIG_INPUT=y
+CONFIG_INPUT_LEDS=y
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_POLLDEV=m
CONFIG_INPUT_SPARSEKMAP=m
@@ -2708,6 +2992,7 @@ CONFIG_KEYBOARD_LM8333=m
CONFIG_KEYBOARD_MAX7359=m
CONFIG_KEYBOARD_MCS=m
CONFIG_KEYBOARD_MPR121=m
+CONFIG_KEYBOARD_SNVS_PWRKEY=m
CONFIG_KEYBOARD_IMX=m
CONFIG_KEYBOARD_NEWTON=m
CONFIG_KEYBOARD_TEGRA=m
@@ -2719,7 +3004,7 @@ CONFIG_KEYBOARD_SUN4I_LRADC=m
CONFIG_KEYBOARD_OMAP4=m
CONFIG_KEYBOARD_TWL4030=m
CONFIG_KEYBOARD_XTKBD=m
-CONFIG_KEYBOARD_CROS_EC=m
+CONFIG_KEYBOARD_CROS_EC=y
CONFIG_KEYBOARD_CAP11XX=m
CONFIG_KEYBOARD_BCM=m
CONFIG_INPUT_MOUSE=y
@@ -2779,7 +3064,7 @@ CONFIG_TABLET_USB_HANWANG=m
CONFIG_TABLET_USB_KBTAB=m
CONFIG_TABLET_SERIAL_WACOM4=m
CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_OF_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
CONFIG_TOUCHSCREEN_ADS7846=m
CONFIG_TOUCHSCREEN_AD7877=m
CONFIG_TOUCHSCREEN_AD7879=m
@@ -2802,6 +3087,7 @@ CONFIG_TOUCHSCREEN_DYNAPRO=m
CONFIG_TOUCHSCREEN_HAMPSHIRE=m
CONFIG_TOUCHSCREEN_EETI=m
CONFIG_TOUCHSCREEN_EGALAX=m
+CONFIG_TOUCHSCREEN_FT6236=m
CONFIG_TOUCHSCREEN_FUJITSU=m
CONFIG_TOUCHSCREEN_GOODIX=m
CONFIG_TOUCHSCREEN_ILI210X=m
@@ -2814,6 +3100,7 @@ CONFIG_TOUCHSCREEN_MAX11801=m
CONFIG_TOUCHSCREEN_MCS5000=m
CONFIG_TOUCHSCREEN_MMS114=m
CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_IMX6UL_TSC=m
CONFIG_TOUCHSCREEN_INEXIO=m
CONFIG_TOUCHSCREEN_MK712=m
CONFIG_TOUCHSCREEN_PENMOUNT=m
@@ -2822,6 +3109,7 @@ CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
CONFIG_TOUCHSCREEN_TOUCHWIN=m
CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_WDT87XX_I2C=m
CONFIG_TOUCHSCREEN_WM97XX=m
CONFIG_TOUCHSCREEN_WM9705=y
CONFIG_TOUCHSCREEN_WM9712=y
@@ -2848,14 +3136,18 @@ CONFIG_TOUCHSCREEN_USB_NEXIO=y
CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
CONFIG_TOUCHSCREEN_TOUCHIT213=m
CONFIG_TOUCHSCREEN_TSC_SERIO=m
+CONFIG_TOUCHSCREEN_TSC200X_CORE=m
+CONFIG_TOUCHSCREEN_TSC2004=m
CONFIG_TOUCHSCREEN_TSC2005=m
CONFIG_TOUCHSCREEN_TSC2007=m
CONFIG_TOUCHSCREEN_ST1232=m
CONFIG_TOUCHSCREEN_SUN4I=m
CONFIG_TOUCHSCREEN_SUR40=m
-# CONFIG_TOUCHSCREEN_SX8654 is not set
+CONFIG_TOUCHSCREEN_SX8654=m
CONFIG_TOUCHSCREEN_TPS6507X=m
CONFIG_TOUCHSCREEN_ZFORCE=m
+CONFIG_TOUCHSCREEN_COLIBRI_VF50=m
+CONFIG_TOUCHSCREEN_ROHM_BU21023=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_AD714X=m
CONFIG_INPUT_AD714X_I2C=m
@@ -2890,6 +3182,7 @@ CONFIG_INPUT_PCF8574=m
CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
CONFIG_INPUT_DA9052_ONKEY=m
CONFIG_INPUT_DA9055_ONKEY=m
+# CONFIG_INPUT_DA9063_ONKEY is not set
CONFIG_INPUT_ADXL34X=m
CONFIG_INPUT_ADXL34X_I2C=m
CONFIG_INPUT_ADXL34X_SPI=m
@@ -2898,6 +3191,7 @@ CONFIG_INPUT_CMA3000=m
CONFIG_INPUT_CMA3000_I2C=m
# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set
CONFIG_INPUT_DRV260X_HAPTICS=m
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
CONFIG_INPUT_DRV2667_HAPTICS=m
#
@@ -2905,7 +3199,7 @@ CONFIG_INPUT_DRV2667_HAPTICS=m
#
CONFIG_SERIO=y
CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_AMBAKMI=m
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
@@ -2913,7 +3207,8 @@ CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_PS2MULT is not set
# CONFIG_SERIO_ARC_PS2 is not set
# CONFIG_SERIO_APBPS2 is not set
-# CONFIG_SERIO_SUN4I_PS2 is not set
+CONFIG_SERIO_SUN4I_PS2=m
+# CONFIG_USERIO is not set
CONFIG_GAMEPORT=m
# CONFIG_GAMEPORT_NS558 is not set
# CONFIG_GAMEPORT_L4 is not set
@@ -2932,10 +3227,9 @@ CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_NOZOMI is not set
+CONFIG_NOZOMI=m
CONFIG_N_GSM=m
# CONFIG_TRACE_SINK is not set
CONFIG_DEVMEM=y
@@ -2948,14 +3242,19 @@ CONFIG_SERIAL_EARLYCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_DMA=y
+# CONFIG_SERIAL_8250_DMA is not set
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=6
CONFIG_SERIAL_8250_RUNTIME_UARTS=6
# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_8250_DW=y
# CONFIG_SERIAL_8250_EM is not set
-# CONFIG_SERIAL_8250_OMAP is not set
+CONFIG_SERIAL_8250_OMAP=y
+CONFIG_SERIAL_8250_OMAP_TTYO_FIXUP=y
+# CONFIG_SERIAL_8250_MID is not set
+# CONFIG_SERIAL_8250_MOXA is not set
+CONFIG_SERIAL_OF_PLATFORM=y
#
# Non-8250 serial port support
@@ -2982,22 +3281,24 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_CONSOLE_POLL=y
# CONFIG_SERIAL_JSM is not set
-CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_SERIAL_OMAP=y
-CONFIG_SERIAL_OMAP_CONSOLE=y
+# CONFIG_SERIAL_OMAP is not set
# CONFIG_SERIAL_SCCNXP is not set
# CONFIG_SERIAL_SC16IS7XX is not set
# CONFIG_SERIAL_BCM63XX is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
# CONFIG_SERIAL_IFX6X60 is not set
-# CONFIG_SERIAL_XILINX_PS_UART is not set
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
# CONFIG_SERIAL_ARC is not set
-# CONFIG_SERIAL_RP2 is not set
+CONFIG_SERIAL_RP2=m
+CONFIG_SERIAL_RP2_NR_UARTS=32
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_SERIAL_MVEBU_UART is not set
# CONFIG_TTY_PRINTK is not set
CONFIG_HVC_DRIVER=y
# CONFIG_HVC_DCC is not set
@@ -3026,7 +3327,6 @@ CONFIG_DEVPORT=y
# I2C support
#
CONFIG_I2C=y
-CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=y
@@ -3040,6 +3340,7 @@ CONFIG_I2C_ARB_GPIO_CHALLENGE=y
# CONFIG_I2C_MUX_PCA9541 is not set
CONFIG_I2C_MUX_PCA954x=y
CONFIG_I2C_MUX_PINCTRL=y
+# CONFIG_I2C_MUX_REG is not set
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_SMBUS=m
CONFIG_I2C_ALGOBIT=y
@@ -3076,6 +3377,7 @@ CONFIG_I2C_DAVINCI=y
CONFIG_I2C_DESIGNWARE_CORE=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
# CONFIG_I2C_DESIGNWARE_PCI is not set
+# CONFIG_I2C_EMEV2 is not set
CONFIG_I2C_EXYNOS5=y
CONFIG_I2C_GPIO=y
CONFIG_I2C_IMX=y
@@ -3092,6 +3394,7 @@ CONFIG_I2C_S3C2410=y
CONFIG_I2C_SIMTEC=m
CONFIG_I2C_SUN6I_P2WI=y
CONFIG_I2C_TEGRA=y
+CONFIG_I2C_VERSATILE=y
CONFIG_I2C_XILINX=y
#
@@ -3125,15 +3428,15 @@ CONFIG_SPI_MASTER=y
CONFIG_SPI_BITBANG=y
# CONFIG_SPI_CADENCE is not set
CONFIG_SPI_DAVINCI=y
-# CONFIG_SPI_DLN2 is not set
-CONFIG_SPI_GPIO=y
+CONFIG_SPI_DLN2=m
+CONFIG_SPI_GPIO=m
CONFIG_SPI_IMX=m
# CONFIG_SPI_FSL_SPI is not set
# CONFIG_SPI_FSL_DSPI is not set
CONFIG_SPI_MESON_SPIFC=m
# CONFIG_SPI_OC_TINY is not set
CONFIG_SPI_OMAP24XX=m
-# CONFIG_SPI_TI_QSPI is not set
+CONFIG_SPI_TI_QSPI=m
CONFIG_SPI_ORION=y
CONFIG_SPI_PL022=m
# CONFIG_SPI_PXA2XX is not set
@@ -3148,12 +3451,13 @@ CONFIG_SPI_TEGRA20_SFLASH=m
CONFIG_SPI_TEGRA20_SLINK=m
# CONFIG_SPI_XCOMM is not set
CONFIG_SPI_XILINX=y
+CONFIG_SPI_ZYNQMP_GQSPI=m
# CONFIG_SPI_DESIGNWARE is not set
#
# SPI Protocol Masters
#
-CONFIG_SPI_SPIDEV=y
+CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_SPMI is not set
CONFIG_HSI=m
@@ -3168,7 +3472,8 @@ CONFIG_OMAP_SSI_PORT=m
#
# HSI clients
#
-# CONFIG_CMT_SPEECH is not set
+CONFIG_NOKIA_MODEM=m
+CONFIG_CMT_SPEECH=m
CONFIG_SSI_PROTOCOL=m
# CONFIG_HSI_CHAR is not set
@@ -3218,6 +3523,7 @@ CONFIG_PINCTRL_TEGRA30=y
CONFIG_PINCTRL_TEGRA114=y
CONFIG_PINCTRL_TEGRA124=y
CONFIG_PINCTRL_TEGRA_XUSB=y
+CONFIG_PINCTRL_TI_IODELAY=y
CONFIG_PINCTRL_PALMAS=y
CONFIG_PINCTRL_ZYNQ=y
CONFIG_PINCTRL_IMX=y
@@ -3227,12 +3533,15 @@ CONFIG_PINCTRL_IMX53=y
CONFIG_PINCTRL_IMX6Q=y
CONFIG_PINCTRL_IMX6SL=y
CONFIG_PINCTRL_IMX6SX=y
+CONFIG_PINCTRL_IMX6UL=y
+CONFIG_PINCTRL_IMX7D=y
CONFIG_PINCTRL_VF610=y
CONFIG_PINCTRL_MVEBU=y
CONFIG_PINCTRL_DOVE=y
CONFIG_PINCTRL_ARMADA_370=y
CONFIG_PINCTRL_ARMADA_375=y
CONFIG_PINCTRL_ARMADA_38X=y
+CONFIG_PINCTRL_ARMADA_39X=y
CONFIG_PINCTRL_ARMADA_XP=y
CONFIG_PINCTRL_SAMSUNG=y
CONFIG_PINCTRL_EXYNOS=y
@@ -3246,6 +3555,8 @@ CONFIG_PINCTRL_SUN6I_A31S=y
CONFIG_PINCTRL_SUN6I_A31_R=y
CONFIG_PINCTRL_SUN7I_A20=y
CONFIG_PINCTRL_SUN8I_A23=y
+CONFIG_PINCTRL_SUN8I_A33=y
+CONFIG_PINCTRL_SUN8I_A83T=y
CONFIG_PINCTRL_SUN8I_A23_R=y
CONFIG_PINCTRL_SUN9I_A80=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
@@ -3275,13 +3586,13 @@ CONFIG_GPIO_MVEBU=y
CONFIG_GPIO_MXC=y
CONFIG_GPIO_OMAP=y
CONFIG_GPIO_PL061=y
-# CONFIG_GPIO_SCH311X is not set
-# CONFIG_GPIO_SYSCON is not set
+CONFIG_GPIO_SYSCON=y
CONFIG_GPIO_VF610=y
# CONFIG_GPIO_VX855 is not set
CONFIG_GPIO_XILINX=y
# CONFIG_GPIO_ZEVIO is not set
-# CONFIG_GPIO_ZYNQ is not set
+CONFIG_GPIO_ZYNQ=y
+# CONFIG_GPIO_ZX is not set
#
# I2C GPIO expanders
@@ -3312,7 +3623,6 @@ CONFIG_GPIO_TWL6040=y
# PCI GPIO expanders
#
# CONFIG_GPIO_AMD8111 is not set
-# CONFIG_GPIO_BT8XX is not set
# CONFIG_GPIO_ML_IOH is not set
# CONFIG_GPIO_RDC321X is not set
@@ -3321,10 +3631,14 @@ CONFIG_GPIO_TWL6040=y
#
CONFIG_GPIO_74X164=m
CONFIG_GPIO_MAX7301=m
-CONFIG_GPIO_MCP23S08=m
CONFIG_GPIO_MC33880=m
#
+# SPI or I2C GPIO expanders
+#
+CONFIG_GPIO_MCP23S08=m
+
+#
# USB GPIO expanders
#
# CONFIG_GPIO_VIPERBOARD is not set
@@ -3334,7 +3648,7 @@ CONFIG_W1_CON=y
#
# 1-wire Bus Masters
#
-# CONFIG_W1_MASTER_MATROX is not set
+CONFIG_W1_MASTER_MATROX=m
CONFIG_W1_MASTER_DS2490=m
CONFIG_W1_MASTER_DS2482=m
CONFIG_W1_MASTER_MXC=m
@@ -3370,29 +3684,35 @@ CONFIG_GENERIC_ADC_BATTERY=m
# CONFIG_BATTERY_DS2781 is not set
# CONFIG_BATTERY_DS2782 is not set
CONFIG_BATTERY_SBS=m
-CONFIG_BATTERY_BQ27x00=m
-CONFIG_BATTERY_BQ27X00_I2C=y
-CONFIG_BATTERY_BQ27X00_PLATFORM=y
+CONFIG_BATTERY_BQ27XXX=m
+CONFIG_BATTERY_BQ27XXX_I2C=y
+CONFIG_BATTERY_BQ27XXX_PLATFORM=y
CONFIG_BATTERY_DA9052=m
CONFIG_AXP288_FUEL_GAUGE=m
# CONFIG_BATTERY_MAX17040 is not set
# CONFIG_BATTERY_MAX17042 is not set
# CONFIG_BATTERY_TWL4030_MADC is not set
-# CONFIG_BATTERY_RX51 is not set
+CONFIG_BATTERY_RX51=m
CONFIG_CHARGER_ISP1704=m
# CONFIG_CHARGER_MAX8903 is not set
# CONFIG_CHARGER_TWL4030 is not set
# CONFIG_CHARGER_LP8727 is not set
CONFIG_CHARGER_GPIO=m
# CONFIG_CHARGER_MANAGER is not set
+# CONFIG_CHARGER_MAX14577 is not set
# CONFIG_CHARGER_MAX77693 is not set
# CONFIG_CHARGER_MAX8997 is not set
CONFIG_CHARGER_BQ2415X=m
# CONFIG_CHARGER_BQ24190 is not set
-# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+CONFIG_CHARGER_BQ24735=m
+# CONFIG_CHARGER_BQ25890 is not set
# CONFIG_CHARGER_SMB347 is not set
CONFIG_CHARGER_TPS65090=m
+CONFIG_CHARGER_TPS65217=m
# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+CONFIG_AXP20X_POWER=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_AS3722=y
# CONFIG_POWER_RESET_BRCMSTB is not set
@@ -3402,7 +3722,8 @@ CONFIG_POWER_RESET_IMX=y
# CONFIG_POWER_RESET_LTC2952 is not set
# CONFIG_POWER_RESET_QNAP is not set
CONFIG_POWER_RESET_RESTART=y
-# CONFIG_POWER_RESET_VERSATILE is not set
+CONFIG_POWER_RESET_VERSATILE=y
+CONFIG_POWER_RESET_VEXPRESS=y
CONFIG_POWER_RESET_KEYSTONE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
@@ -3437,7 +3758,7 @@ CONFIG_SENSORS_DS620=m
CONFIG_SENSORS_DS1621=m
CONFIG_SENSORS_DA9052_ADC=m
CONFIG_SENSORS_DA9055=m
-# CONFIG_SENSORS_I5K_AMB is not set
+CONFIG_SENSORS_I5K_AMB=m
CONFIG_SENSORS_F71805F=m
CONFIG_SENSORS_F71882FG=m
CONFIG_SENSORS_F75375S=m
@@ -3469,6 +3790,7 @@ CONFIG_SENSORS_MAX6639=m
CONFIG_SENSORS_MAX6642=m
CONFIG_SENSORS_MAX6650=m
CONFIG_SENSORS_MAX6697=m
+CONFIG_SENSORS_MAX31790=m
CONFIG_SENSORS_HTU21=m
CONFIG_SENSORS_MCP3021=m
CONFIG_SENSORS_ADCXX=m
@@ -3503,6 +3825,7 @@ CONFIG_SENSORS_LM25066=m
CONFIG_SENSORS_LTC2978=m
CONFIG_SENSORS_LTC2978_REGULATOR=y
CONFIG_SENSORS_MAX16064=m
+CONFIG_SENSORS_MAX20751=m
CONFIG_SENSORS_MAX34440=m
CONFIG_SENSORS_MAX8688=m
CONFIG_SENSORS_TPS40422=m
@@ -3532,15 +3855,17 @@ CONFIG_SENSORS_ADS7871=m
CONFIG_SENSORS_AMC6821=m
CONFIG_SENSORS_INA209=m
CONFIG_SENSORS_INA2XX=m
+# CONFIG_SENSORS_TC74 is not set
CONFIG_SENSORS_THMC50=m
CONFIG_SENSORS_TMP102=m
CONFIG_SENSORS_TMP103=m
CONFIG_SENSORS_TMP401=m
CONFIG_SENSORS_TMP421=m
CONFIG_SENSORS_TWL4030_MADC=m
+CONFIG_SENSORS_VEXPRESS=y
# CONFIG_SENSORS_VIA686A is not set
CONFIG_SENSORS_VT1211=m
-# CONFIG_SENSORS_VT8231 is not set
+CONFIG_SENSORS_VT8231=m
CONFIG_SENSORS_W83781D=m
CONFIG_SENSORS_W83791D=m
CONFIG_SENSORS_W83792D=m
@@ -3554,15 +3879,19 @@ CONFIG_SENSORS_W83627EHF=m
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
CONFIG_THERMAL_OF=y
+# CONFIG_THERMAL_WRITABLE_TRIPS is not set
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
+# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
CONFIG_CPU_THERMAL=y
CONFIG_CLOCK_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
# CONFIG_THERMAL_EMULATION is not set
CONFIG_IMX_THERMAL=y
CONFIG_ROCKCHIP_THERMAL=y
@@ -3575,6 +3904,7 @@ CONFIG_TEGRA_SOCTHERM=y
#
CONFIG_TI_SOC_THERMAL=y
CONFIG_TI_THERMAL=y
+CONFIG_OMAP3_THERMAL=y
CONFIG_OMAP4_THERMAL=y
CONFIG_OMAP5_THERMAL=y
CONFIG_DRA752_THERMAL=y
@@ -3612,6 +3942,7 @@ CONFIG_TEGRA_WATCHDOG=y
CONFIG_MESON_WATCHDOG=y
# CONFIG_ALIM7101_WDT is not set
# CONFIG_I6300ESB_WDT is not set
+# CONFIG_BCM7038_WDT is not set
# CONFIG_MEN_A21_WDT is not set
#
@@ -3637,6 +3968,7 @@ CONFIG_SSB_PCIHOST=y
CONFIG_SSB_B43_PCI_BRIDGE=y
CONFIG_SSB_SDIOHOST_POSSIBLE=y
CONFIG_SSB_SDIOHOST=y
+# CONFIG_SSB_HOST_SOC is not set
# CONFIG_SSB_SILENT is not set
# CONFIG_SSB_DEBUG is not set
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
@@ -3665,18 +3997,20 @@ CONFIG_MFD_CORE=y
CONFIG_MFD_AS3722=y
# CONFIG_PMIC_ADP5520 is not set
# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
# CONFIG_MFD_ATMEL_HLCDC is not set
CONFIG_MFD_BCM590XX=y
CONFIG_MFD_AXP20X=y
CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_I2C=y
-# CONFIG_MFD_CROS_EC_SPI is not set
+CONFIG_MFD_CROS_EC_SPI=y
# CONFIG_MFD_ASIC3 is not set
# CONFIG_PMIC_DA903X is not set
CONFIG_PMIC_DA9052=y
CONFIG_MFD_DA9052_SPI=y
CONFIG_MFD_DA9052_I2C=y
CONFIG_MFD_DA9055=y
+# CONFIG_MFD_DA9062 is not set
CONFIG_MFD_DA9063=y
# CONFIG_MFD_DA9150 is not set
CONFIG_MFD_DLN2=m
@@ -3688,14 +4022,14 @@ CONFIG_MFD_MC13XXX_I2C=y
# CONFIG_HTC_PASIC3 is not set
# CONFIG_HTC_I2CPLD is not set
# CONFIG_LPC_ICH is not set
-# CONFIG_LPC_SCH is not set
+CONFIG_LPC_SCH=m
# CONFIG_INTEL_SOC_PMIC is not set
# CONFIG_MFD_JANZ_CMODIO is not set
# CONFIG_MFD_KEMPLD is not set
# CONFIG_MFD_88PM800 is not set
# CONFIG_MFD_88PM805 is not set
# CONFIG_MFD_88PM860X is not set
-# CONFIG_MFD_MAX14577 is not set
+CONFIG_MFD_MAX14577=y
CONFIG_MFD_MAX77686=y
CONFIG_MFD_MAX77693=y
# CONFIG_MFD_MAX77843 is not set
@@ -3712,11 +4046,11 @@ CONFIG_MFD_VIPERBOARD=m
# CONFIG_UCB1400_CORE is not set
# CONFIG_MFD_PM8921_CORE is not set
# CONFIG_MFD_RDC321X is not set
-# CONFIG_MFD_RTSX_PCI is not set
+CONFIG_MFD_RTSX_PCI=m
# CONFIG_MFD_RT5033 is not set
CONFIG_MFD_RTSX_USB=m
# CONFIG_MFD_RC5T583 is not set
-# CONFIG_MFD_RK808 is not set
+CONFIG_MFD_RK808=y
# CONFIG_MFD_RN5T618 is not set
CONFIG_MFD_SEC_CORE=y
# CONFIG_MFD_SI476X_CORE is not set
@@ -3763,6 +4097,7 @@ CONFIG_MFD_WL1273_CORE=m
# CONFIG_MFD_WM831X_SPI is not set
# CONFIG_MFD_WM8350_I2C is not set
CONFIG_MFD_WM8994=y
+CONFIG_MFD_VEXPRESS_SYSREG=y
CONFIG_REGULATOR=y
# CONFIG_REGULATOR_DEBUG is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -3779,21 +4114,22 @@ CONFIG_REGULATOR_DA9052=y
CONFIG_REGULATOR_DA9063=y
# CONFIG_REGULATOR_DA9210 is not set
# CONFIG_REGULATOR_DA9211 is not set
-# CONFIG_REGULATOR_FAN53555 is not set
+CONFIG_REGULATOR_FAN53555=m
CONFIG_REGULATOR_GPIO=y
-# CONFIG_REGULATOR_ISL9305 is not set
+CONFIG_REGULATOR_ISL9305=y
# CONFIG_REGULATOR_ISL6271A is not set
# CONFIG_REGULATOR_LP3971 is not set
# CONFIG_REGULATOR_LP3972 is not set
# CONFIG_REGULATOR_LP872X is not set
# CONFIG_REGULATOR_LP8755 is not set
-CONFIG_REGULATOR_LTC3589=y
+# CONFIG_REGULATOR_LTC3589 is not set
+CONFIG_REGULATOR_MAX14577=y
# CONFIG_REGULATOR_MAX1586 is not set
# CONFIG_REGULATOR_MAX8649 is not set
# CONFIG_REGULATOR_MAX8660 is not set
CONFIG_REGULATOR_MAX8907=y
# CONFIG_REGULATOR_MAX8952 is not set
-# CONFIG_REGULATOR_MAX8973 is not set
+CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_MAX8997=y
CONFIG_REGULATOR_MAX77686=y
CONFIG_REGULATOR_MAX77693=y
@@ -3801,10 +4137,12 @@ CONFIG_REGULATOR_MAX77802=y
CONFIG_REGULATOR_MC13XXX_CORE=m
CONFIG_REGULATOR_MC13783=m
CONFIG_REGULATOR_MC13892=m
+CONFIG_REGULATOR_MT6311=y
CONFIG_REGULATOR_PALMAS=y
CONFIG_REGULATOR_PBIAS=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPA01=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_S5M8767=y
@@ -3820,6 +4158,7 @@ CONFIG_REGULATOR_TPS65218=y
CONFIG_REGULATOR_TPS6586X=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_REGULATOR_TWL4030=y
+CONFIG_REGULATOR_VEXPRESS=y
# CONFIG_REGULATOR_WM8994 is not set
CONFIG_MEDIA_SUPPORT=y
@@ -3841,6 +4180,7 @@ CONFIG_VIDEO_V4L2=y
CONFIG_VIDEO_TUNER=m
CONFIG_V4L2_MEM2MEM_DEV=y
CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
CONFIG_VIDEOBUF_VMALLOC=m
CONFIG_VIDEOBUF_DMA_CONTIG=m
CONFIG_VIDEOBUF_DVB=m
@@ -3849,6 +4189,7 @@ CONFIG_VIDEOBUF2_MEMOPS=y
CONFIG_VIDEOBUF2_DMA_CONTIG=y
CONFIG_VIDEOBUF2_VMALLOC=y
CONFIG_VIDEOBUF2_DMA_SG=m
+CONFIG_VIDEOBUF2_DVB=m
CONFIG_DVB_CORE=y
CONFIG_DVB_NET=y
CONFIG_TTPCI_EEPROM=m
@@ -4048,9 +4389,76 @@ CONFIG_VIDEO_EM28XX_RC=m
CONFIG_USB_AIRSPY=m
CONFIG_USB_HACKRF=m
CONFIG_USB_MSI2500=m
-# CONFIG_MEDIA_PCI_SUPPORT is not set
+CONFIG_MEDIA_PCI_SUPPORT=y
+
+#
+# Media capture support
+#
+CONFIG_VIDEO_SOLO6X10=m
+CONFIG_VIDEO_TW68=m
+
+#
+# Media capture/analog TV support
+#
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_IVTV_ALSA=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_MXB=m
+# CONFIG_VIDEO_DT3155 is not set
+
+#
+# Media capture/analog/hybrid TV support
+#
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CX18_ALSA=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_MEDIA_ALTERA_CI=m
+CONFIG_VIDEO_CX25821=m
+CONFIG_VIDEO_CX25821_ALSA=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_ENABLE_VP3054=y
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX88_MPEG=m
+CONFIG_VIDEO_BT848=m
+CONFIG_DVB_BT8XX=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_RC=y
+CONFIG_VIDEO_SAA7134_DVB=m
+# CONFIG_VIDEO_SAA7134_GO7007 is not set
+CONFIG_VIDEO_SAA7164=m
+
+#
+# Media digital TV PCI Adapters
+#
+CONFIG_DVB_AV7110_IR=y
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set
+CONFIG_DVB_PLUTO2=m
+CONFIG_DVB_DM1105=m
+CONFIG_DVB_PT1=m
+CONFIG_DVB_PT3=m
+CONFIG_MANTIS_CORE=m
+CONFIG_DVB_MANTIS=m
+CONFIG_DVB_HOPPER=m
+CONFIG_DVB_NGENE=m
+CONFIG_DVB_DDBRIDGE=m
+CONFIG_DVB_SMIPCIE=m
+CONFIG_DVB_NETUP_UNIDVB=m
CONFIG_V4L_PLATFORM_DRIVERS=y
-# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_VIDEO_CAFE_CCIC=m
CONFIG_VIDEO_OMAP2_VOUT_VRFB=y
CONFIG_VIDEO_OMAP2_VOUT=m
CONFIG_VIDEO_OMAP3=m
@@ -4059,21 +4467,34 @@ CONFIG_SOC_CAMERA=m
CONFIG_SOC_CAMERA_PLATFORM=m
# CONFIG_VIDEO_MX3 is not set
# CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS is not set
-# CONFIG_VIDEO_SAMSUNG_S5P_TV is not set
+CONFIG_VIDEO_SAMSUNG_S5P_TV=y
+CONFIG_VIDEO_SAMSUNG_S5P_HDMI=y
+# CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG is not set
+CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY=y
+# CONFIG_VIDEO_SAMSUNG_S5P_SII9234 is not set
+# CONFIG_VIDEO_SAMSUNG_S5P_SDO is not set
+CONFIG_VIDEO_SAMSUNG_S5P_MIXER=y
+# CONFIG_VIDEO_SAMSUNG_S5P_MIXER_DEBUG is not set
CONFIG_VIDEO_AM437X_VPFE=m
-# CONFIG_VIDEO_XILINX is not set
+CONFIG_VIDEO_XILINX=m
+CONFIG_VIDEO_XILINX_TPG=m
+CONFIG_VIDEO_XILINX_VTC=m
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_CODA=y
CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
-# CONFIG_VIDEO_SAMSUNG_S5P_G2D is not set
-# CONFIG_VIDEO_SAMSUNG_S5P_JPEG is not set
-# CONFIG_VIDEO_SAMSUNG_S5P_MFC is not set
-# CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC is not set
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=m
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
+CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
# CONFIG_VIDEO_SH_VEU is not set
-# CONFIG_VIDEO_TI_VPE is not set
+CONFIG_VIDEO_TI_VPE=m
+# CONFIG_VIDEO_TI_VPE_DEBUG is not set
CONFIG_V4L_TEST_DRIVERS=y
CONFIG_VIDEO_VIVID=m
+CONFIG_VIDEO_VIVID_MAX_DEVS=64
# CONFIG_VIDEO_VIM2M is not set
+CONFIG_DVB_PLATFORM_DRIVERS=y
+CONFIG_DVB_C8SECTPFE=m
#
# Supported MMC/SDIO adapters
@@ -4105,6 +4526,12 @@ CONFIG_RADIO_WL1273=m
# Texas Instruments WL128x FM driver (ST based)
#
CONFIG_RADIO_WL128X=m
+
+#
+# Supported FireWire (IEEE 1394) Adapters
+#
+CONFIG_DVB_FIREDTV=m
+CONFIG_DVB_FIREDTV_INPUT=y
CONFIG_MEDIA_COMMON_OPTIONS=y
#
@@ -4114,6 +4541,8 @@ CONFIG_VIDEO_CX2341X=m
CONFIG_VIDEO_TVEEPROM=m
CONFIG_CYPRESS_FIRMWARE=m
CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
CONFIG_SMS_SIANO_MDTV=m
CONFIG_SMS_SIANO_RC=y
# CONFIG_SMS_SIANO_DEBUGFS is not set
@@ -4128,15 +4557,24 @@ CONFIG_VIDEO_IR_I2C=y
#
# Audio decoders, processors and mixers
#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
CONFIG_VIDEO_CS53L32A=m
CONFIG_VIDEO_UDA1342=m
CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
CONFIG_VIDEO_SONY_BTF_MPX=m
#
# RDS decoders
#
+CONFIG_VIDEO_SAA6588=m
#
# Video decoders
@@ -4150,16 +4588,19 @@ CONFIG_VIDEO_TW9906=m
#
# Video and audio decoders
#
+CONFIG_VIDEO_SAA717X=m
CONFIG_VIDEO_CX25840=m
#
# Video encoders
#
+CONFIG_VIDEO_SAA7127=m
#
# Camera sensor devices
#
CONFIG_VIDEO_OV7640=m
+CONFIG_VIDEO_OV7670=m
CONFIG_VIDEO_MT9V011=m
#
@@ -4169,14 +4610,18 @@ CONFIG_VIDEO_MT9V011=m
#
# Video improvement chips
#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
#
# Audio/Video compression chips
#
+CONFIG_VIDEO_SAA6752HS=m
#
# Miscellaneous helper chips
#
+CONFIG_VIDEO_M52790=m
#
# Sensors used on soc_camera driver
@@ -4212,6 +4657,7 @@ CONFIG_MEDIA_TUNER_MT20XX=y
CONFIG_MEDIA_TUNER_MT2060=m
CONFIG_MEDIA_TUNER_MT2063=m
CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
CONFIG_MEDIA_TUNER_QT1010=m
CONFIG_MEDIA_TUNER_XC2028=y
CONFIG_MEDIA_TUNER_XC5000=y
@@ -4227,10 +4673,13 @@ CONFIG_MEDIA_TUNER_FC0013=m
CONFIG_MEDIA_TUNER_TDA18212=m
CONFIG_MEDIA_TUNER_E4000=m
CONFIG_MEDIA_TUNER_FC2580=m
+CONFIG_MEDIA_TUNER_M88RS6000T=m
CONFIG_MEDIA_TUNER_TUA9001=m
CONFIG_MEDIA_TUNER_SI2157=m
CONFIG_MEDIA_TUNER_IT913X=m
CONFIG_MEDIA_TUNER_R820T=m
+CONFIG_MEDIA_TUNER_MXL301RF=m
+CONFIG_MEDIA_TUNER_QM1D1C0042=m
#
# Multistandard (satellite) frontends
@@ -4251,8 +4700,10 @@ CONFIG_DVB_SI2165=m
#
# DVB-S (satellite) frontends
#
+CONFIG_DVB_CX24110=m
CONFIG_DVB_CX24123=m
CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10036=m
CONFIG_DVB_ZL10039=m
CONFIG_DVB_S5H1420=m
CONFIG_DVB_STV0288=m
@@ -4262,21 +4713,30 @@ CONFIG_DVB_STV6110=m
CONFIG_DVB_STV0900=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
CONFIG_DVB_TUNER_ITD1000=m
CONFIG_DVB_TUNER_CX24113=m
CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
CONFIG_DVB_CX24116=m
+CONFIG_DVB_CX24117=m
+CONFIG_DVB_CX24120=m
CONFIG_DVB_SI21XX=m
CONFIG_DVB_TS2020=m
CONFIG_DVB_DS3000=m
+CONFIG_DVB_MB86A16=m
CONFIG_DVB_TDA10071=m
#
# DVB-T (terrestrial) frontends
#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
CONFIG_DVB_CX22700=m
CONFIG_DVB_CX22702=m
CONFIG_DVB_DRXD=m
+CONFIG_DVB_L64781=m
CONFIG_DVB_TDA1004X=m
CONFIG_DVB_NXT6000=m
CONFIG_DVB_MT352=m
@@ -4288,7 +4748,9 @@ CONFIG_DVB_DIB7000P=m
CONFIG_DVB_TDA10048=m
CONFIG_DVB_AF9013=m
CONFIG_DVB_EC100=m
+CONFIG_DVB_STV0367=m
CONFIG_DVB_CXD2820R=m
+CONFIG_DVB_CXD2841ER=m
CONFIG_DVB_RTL2830=m
CONFIG_DVB_RTL2832=m
CONFIG_DVB_RTL2832_SDR=m
@@ -4299,6 +4761,7 @@ CONFIG_DVB_AS102_FE=m
# DVB-C (cable) frontends
#
CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
CONFIG_DVB_TDA10023=m
CONFIG_DVB_STV0297=m
@@ -4306,6 +4769,8 @@ CONFIG_DVB_STV0297=m
# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
#
CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
CONFIG_DVB_BCM3510=m
CONFIG_DVB_LGDT330X=m
CONFIG_DVB_LGDT3305=m
@@ -4327,6 +4792,7 @@ CONFIG_DVB_MB86A20S=m
#
# ISDB-S (satellite) & ISDB-T (terrestrial) frontends
#
+CONFIG_DVB_TC90522=m
#
# Digital terrestrial only tuners/PLL
@@ -4339,17 +4805,22 @@ CONFIG_DVB_TUNER_DIB0090=m
# SEC control devices for DVB-S
#
CONFIG_DVB_DRX39XYJ=m
+CONFIG_DVB_LNBH25=m
CONFIG_DVB_LNBP21=m
CONFIG_DVB_LNBP22=m
+CONFIG_DVB_ISL6405=m
CONFIG_DVB_ISL6421=m
CONFIG_DVB_ISL6423=m
CONFIG_DVB_A8293=m
CONFIG_DVB_SP2=m
CONFIG_DVB_LGS8GXX=m
CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_TDA665x=m
CONFIG_DVB_IX2505V=m
CONFIG_DVB_M88RS2000=m
CONFIG_DVB_AF9033=m
+CONFIG_DVB_HORUS3A=m
+CONFIG_DVB_ASCOT2E=m
#
# Tools to develop new frontends
@@ -4364,14 +4835,11 @@ CONFIG_VGA_ARB_MAX_GPUS=16
CONFIG_TEGRA_HOST1X=m
CONFIG_TEGRA_HOST1X_FIREWALL=y
CONFIG_IMX_IPUV3_CORE=m
-
-#
-# Direct Rendering Manager
-#
CONFIG_DRM=y
CONFIG_DRM_MIPI_DSI=y
-CONFIG_DRM_KMS_HELPER=m
+CONFIG_DRM_KMS_HELPER=y
CONFIG_DRM_KMS_FB_HELPER=y
+CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_TTM=m
CONFIG_DRM_GEM_CMA_HELPER=y
@@ -4380,49 +4848,64 @@ CONFIG_DRM_KMS_CMA_HELPER=y
#
# I2C encoder or helper chips
#
-# CONFIG_DRM_I2C_ADV7511 is not set
+CONFIG_DRM_I2C_ADV7511=m
+CONFIG_DRM_I2C_ADIHDMI=m
CONFIG_DRM_I2C_CH7006=m
CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_I2C_NXP_TDA998X=m
-CONFIG_DRM_DW_HDMI=m
-CONFIG_DRM_PTN3460=m
-# CONFIG_DRM_PS8622 is not set
# CONFIG_DRM_TDFX is not set
# CONFIG_DRM_R128 is not set
# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_AMDGPU is not set
CONFIG_DRM_NOUVEAU=m
CONFIG_NOUVEAU_PLATFORM_DRIVER=y
CONFIG_NOUVEAU_DEBUG=5
CONFIG_NOUVEAU_DEBUG_DEFAULT=3
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_VIA is not set
-# CONFIG_DRM_SAVAGE is not set
-# CONFIG_DRM_VGEM is not set
-CONFIG_DRM_EXYNOS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+CONFIG_DRM_VGEM=m
+CONFIG_DRM_EXYNOS=y
CONFIG_DRM_EXYNOS_IOMMU=y
+
+#
+# CRTCs
+#
CONFIG_DRM_EXYNOS_FIMD=y
+# CONFIG_DRM_EXYNOS5433_DECON is not set
# CONFIG_DRM_EXYNOS7_DECON is not set
-# CONFIG_DRM_EXYNOS_DPI is not set
-# CONFIG_DRM_EXYNOS_DSI is not set
-CONFIG_DRM_EXYNOS_DP=y
-CONFIG_DRM_EXYNOS_HDMI=y
# CONFIG_DRM_EXYNOS_VIDI is not set
+
+#
+# Encoders and Bridges
+#
+CONFIG_DRM_EXYNOS_DPI=y
+CONFIG_DRM_EXYNOS_DSI=y
+CONFIG_DRM_EXYNOS_DP=y
+
+#
+# Sub-drivers
+#
CONFIG_DRM_EXYNOS_G2D=y
-# CONFIG_DRM_EXYNOS_IPP is not set
-CONFIG_DRM_ROCKCHIP=m
-CONFIG_ROCKCHIP_DW_HDMI=m
-# CONFIG_DRM_VMWGFX is not set
+CONFIG_DRM_EXYNOS_IPP=y
+CONFIG_DRM_EXYNOS_FIMC=y
+CONFIG_DRM_EXYNOS_ROTATOR=y
+CONFIG_DRM_ROCKCHIP=y
+CONFIG_ROCKCHIP_DW_HDMI=y
CONFIG_DRM_UDL=m
# CONFIG_DRM_AST is not set
# CONFIG_DRM_MGAG200 is not set
-# CONFIG_DRM_CIRRUS_QEMU is not set
+CONFIG_DRM_CIRRUS_QEMU=m
CONFIG_DRM_ARMADA=m
CONFIG_DRM_OMAP=m
CONFIG_DRM_OMAP_NUM_CRTCS=1
CONFIG_DRM_TILCDC=m
-# CONFIG_DRM_QXL is not set
-# CONFIG_DRM_BOCHS is not set
+CONFIG_DRM_TILCDC_SLAVE_COMPAT=y
+CONFIG_DRM_QXL=m
+CONFIG_DRM_BOCHS=m
+CONFIG_DRM_VIRTIO_GPU=m
+# CONFIG_DRM_FSL_DCU is not set
CONFIG_DRM_TEGRA=m
CONFIG_DRM_TEGRA_FBDEV=y
# CONFIG_DRM_TEGRA_DEBUG is not set
@@ -4433,9 +4916,19 @@ CONFIG_DRM_PANEL=y
# Display Panels
#
CONFIG_DRM_PANEL_SIMPLE=y
-# CONFIG_DRM_PANEL_LD9040 is not set
-# CONFIG_DRM_PANEL_S6E8AA0 is not set
+# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set
+# CONFIG_DRM_PANEL_LG_LG4573 is not set
+CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set
+CONFIG_DRM_BRIDGE=y
+
+#
+# Display Interface Bridges
+#
+CONFIG_DRM_DW_HDMI=y
+CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
+CONFIG_DRM_NXP_PTN3460=y
+CONFIG_DRM_PARADE_PS8622=y
# CONFIG_DRM_STI is not set
CONFIG_DRM_IMX=m
CONFIG_DRM_IMX_FB_HELPER=m
@@ -4444,6 +4937,8 @@ CONFIG_DRM_IMX_TVE=m
CONFIG_DRM_IMX_LDB=m
CONFIG_DRM_IMX_IPUV3=m
CONFIG_DRM_IMX_HDMI=m
+CONFIG_DRM_ETNAVIV=m
+# CONFIG_DRM_ETNAVIV_REGISTER_LOGGING is not set
#
# Frame buffer Devices
@@ -4451,7 +4946,7 @@ CONFIG_DRM_IMX_HDMI=m
CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
CONFIG_FB_CMDLINE=y
-# CONFIG_FB_DDC is not set
+CONFIG_FB_DDC=m
# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
@@ -4463,7 +4958,7 @@ CONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_FOREIGN_ENDIAN is not set
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_DEFERRED_IO=y
-# CONFIG_FB_SVGALIB is not set
+CONFIG_FB_SVGALIB=m
# CONFIG_FB_MACMODES is not set
CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
@@ -4475,7 +4970,7 @@ CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
CONFIG_FB_ARMCLCD=y
-# CONFIG_PLAT_VERSATILE_CLCD is not set
+CONFIG_PLAT_VERSATILE_CLCD=y
# CONFIG_FB_IMX is not set
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_ASILIANT is not set
@@ -4490,26 +4985,32 @@ CONFIG_FB_ARMCLCD=y
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
+CONFIG_FB_S3=m
+CONFIG_FB_S3_DDC=y
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
+CONFIG_FB_3DFX=m
+# CONFIG_FB_3DFX_ACCEL is not set
+CONFIG_FB_3DFX_I2C=y
# CONFIG_FB_VOODOO1 is not set
CONFIG_FB_VT8623=m
# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_ARK is not set
-# CONFIG_FB_PM3 is not set
+CONFIG_FB_ARK=m
+CONFIG_FB_PM3=m
# CONFIG_FB_CARMINE is not set
# CONFIG_FB_S3C is not set
# CONFIG_FB_SMSCUFX is not set
CONFIG_FB_UDL=m
-# CONFIG_FB_XILINX is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_XILINX=y
CONFIG_FB_DA8XX=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
-# CONFIG_FB_MB862XX is not set
+CONFIG_FB_MB862XX=m
+CONFIG_FB_MB862XX_PCI_GDC=y
+CONFIG_FB_MB862XX_I2C=y
CONFIG_FB_MX3=y
# CONFIG_FB_BROADSHEET is not set
# CONFIG_FB_AUO_K190X is not set
@@ -4550,9 +5051,11 @@ CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1=m
# CONFIG_DISPLAY_PANEL_NEC_NL8048HL11 is not set
CONFIG_EXYNOS_VIDEO=y
CONFIG_EXYNOS_MIPI_DSI=y
+# CONFIG_EXYNOS_LCD_S6E8AX0 is not set
CONFIG_FB_SSD1307=y
+# CONFIG_FB_SM712 is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_CLASS_DEVICE=y
# CONFIG_LCD_L4F00242T03 is not set
# CONFIG_LCD_LMS283GF05 is not set
# CONFIG_LCD_LTV350QV is not set
@@ -4560,7 +5063,7 @@ CONFIG_LCD_CLASS_DEVICE=m
# CONFIG_LCD_ILI9320 is not set
# CONFIG_LCD_TDO24M is not set
# CONFIG_LCD_VGG2432A4 is not set
-CONFIG_LCD_PLATFORM=m
+CONFIG_LCD_PLATFORM=y
# CONFIG_LCD_S6E63M0 is not set
# CONFIG_LCD_LD9040 is not set
# CONFIG_LCD_AMS369FG06 is not set
@@ -4570,6 +5073,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_GENERIC=m
CONFIG_BACKLIGHT_PWM=y
# CONFIG_BACKLIGHT_DA9052 is not set
+# CONFIG_BACKLIGHT_PM8941_WLED is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
# CONFIG_BACKLIGHT_LM3630A is not set
@@ -4580,7 +5084,7 @@ CONFIG_BACKLIGHT_PWM=y
CONFIG_BACKLIGHT_GPIO=m
# CONFIG_BACKLIGHT_LV5207LP is not set
# CONFIG_BACKLIGHT_BD6107 is not set
-# CONFIG_VGASTATE is not set
+CONFIG_VGASTATE=m
CONFIG_VIDEOMODE_HELPERS=y
CONFIG_HDMI=y
@@ -4601,10 +5105,11 @@ CONFIG_SOUND_OSS_CORE_PRECLAIM=y
CONFIG_SND=y
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
+CONFIG_SND_PCM_ELD=y
+CONFIG_SND_PCM_IEC958=y
CONFIG_SND_DMAENGINE_PCM=m
CONFIG_SND_HWDEP=m
CONFIG_SND_RAWMIDI=m
-CONFIG_SND_COMPRESS_OFFLOAD=m
CONFIG_SND_JACK=y
CONFIG_SND_SEQUENCER=m
CONFIG_SND_SEQ_DUMMY=m
@@ -4612,22 +5117,25 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_PCM_TIMER=y
CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_HRTIMER=m
CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_MAX_CARDS=32
CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_PROC_FS=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
CONFIG_SND_VMASTER=y
-CONFIG_SND_KCTL_JACK=y
CONFIG_SND_RAWMIDI_SEQ=m
-# CONFIG_SND_OPL3_LIB_SEQ is not set
+CONFIG_SND_OPL3_LIB_SEQ=m
# CONFIG_SND_OPL4_LIB_SEQ is not set
# CONFIG_SND_SBAWE_SEQ is not set
# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
CONFIG_SND_AC97_CODEC=m
CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
@@ -4638,66 +5146,55 @@ CONFIG_SND_DRIVERS=y
# CONFIG_SND_MPU401 is not set
# CONFIG_SND_AC97_POWER_SAVE is not set
CONFIG_SND_PCI=y
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS300 is not set
-# CONFIG_SND_ALI5451 is not set
+CONFIG_SND_AD1889=m
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
# CONFIG_SND_AU8810 is not set
# CONFIG_SND_AU8820 is not set
# CONFIG_SND_AU8830 is not set
# CONFIG_SND_AW2 is not set
-# CONFIG_SND_AZT3328 is not set
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_OXYGEN is not set
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CTXFI is not set
-# CONFIG_SND_DARLA20 is not set
-# CONFIG_SND_GINA20 is not set
-# CONFIG_SND_LAYLA20 is not set
-# CONFIG_SND_DARLA24 is not set
-# CONFIG_SND_GINA24 is not set
-# CONFIG_SND_LAYLA24 is not set
-# CONFIG_SND_MONA is not set
-# CONFIG_SND_MIA is not set
-# CONFIG_SND_ECHO3G is not set
-# CONFIG_SND_INDIGO is not set
-# CONFIG_SND_INDIGOIO is not set
-# CONFIG_SND_INDIGODJ is not set
-# CONFIG_SND_INDIGOIOX is not set
-# CONFIG_SND_INDIGODJX is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
+CONFIG_SND_CTXFI=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_INDIGOIOX=m
+CONFIG_SND_INDIGODJX=m
# CONFIG_SND_ENS1370 is not set
# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
# CONFIG_SND_FM801 is not set
# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_ICE1712 is not set
+CONFIG_SND_HDSPM=m
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_LOLA is not set
-# CONFIG_SND_MAESTRO3 is not set
+CONFIG_SND_LOLA=m
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RIPTIDE is not set
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SE6X is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VIRTUOSO is not set
+CONFIG_SND_VIRTUOSO=m
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set
@@ -4707,13 +5204,10 @@ CONFIG_SND_PCI=y
CONFIG_SND_HDA=m
# CONFIG_SND_HDA_INTEL is not set
CONFIG_SND_HDA_TEGRA=m
-CONFIG_SND_HDA_DSP_LOADER=y
-CONFIG_SND_HDA_PREALLOC_SIZE=64
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_RECONFIG=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_INPUT_BEEP_MODE=1
-CONFIG_SND_HDA_INPUT_JACK=y
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_CODEC_REALTEK=m
CONFIG_SND_HDA_CODEC_ANALOG=m
@@ -4730,8 +5224,10 @@ CONFIG_SND_HDA_CODEC_SI3054=m
CONFIG_SND_HDA_GENERIC=m
CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
CONFIG_SND_HDA_CORE=m
+CONFIG_SND_HDA_DSP_LOADER=y
+CONFIG_SND_HDA_PREALLOC_SIZE=64
CONFIG_SND_ARM=y
-# CONFIG_SND_ARMAACI is not set
+CONFIG_SND_ARMAACI=m
CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=m
@@ -4746,6 +5242,16 @@ CONFIG_SND_USB_POD=m
CONFIG_SND_USB_PODHD=m
CONFIG_SND_USB_TONEPORT=m
CONFIG_SND_USB_VARIAX=m
+CONFIG_SND_FIREWIRE=y
+CONFIG_SND_FIREWIRE_LIB=m
+CONFIG_SND_DICE=m
+CONFIG_SND_OXFW=m
+CONFIG_SND_ISIGHT=m
+CONFIG_SND_SCS1X=m
+CONFIG_SND_FIREWORKS=m
+CONFIG_SND_BEBOB=m
+# CONFIG_SND_FIREWIRE_DIGI00X is not set
+# CONFIG_SND_FIREWIRE_TASCAM is not set
CONFIG_SND_SOC=m
CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
@@ -4796,9 +5302,11 @@ CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
CONFIG_SND_KIRKWOOD_SOC=m
CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB=m
-# CONFIG_SND_SOC_QCOM is not set
CONFIG_SND_SOC_ROCKCHIP=m
CONFIG_SND_SOC_ROCKCHIP_I2S=m
+CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
+CONFIG_SND_SOC_ROCKCHIP_MAX98090=m
+CONFIG_SND_SOC_ROCKCHIP_RT5645=m
CONFIG_SND_SOC_SAMSUNG=m
CONFIG_SND_SAMSUNG_PCM=m
CONFIG_SND_SAMSUNG_SPDIF=m
@@ -4809,6 +5317,11 @@ CONFIG_SND_SOC_SMDK_WM8994_PCM=m
CONFIG_SND_SOC_SNOW=m
CONFIG_SND_SOC_ODROIDX2=m
CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631=m
+
+#
+# Allwinner SoC Audio support
+#
+CONFIG_SND_SUN4I_CODEC=m
CONFIG_SND_SOC_TEGRA=m
CONFIG_SND_SOC_TEGRA20_AC97=m
CONFIG_SND_SOC_TEGRA20_DAS=m
@@ -4823,7 +5336,7 @@ CONFIG_SND_SOC_TEGRA_WM9712=m
CONFIG_SND_SOC_TEGRA_TRIMSLICE=m
CONFIG_SND_SOC_TEGRA_ALC5632=m
CONFIG_SND_SOC_TEGRA_MAX98090=m
-# CONFIG_SND_SOC_TEGRA_RT5677 is not set
+CONFIG_SND_SOC_TEGRA_RT5677=m
# CONFIG_SND_SOC_XTFPGA_I2S is not set
CONFIG_SND_SOC_I2C_AND_SPI=m
@@ -4831,9 +5344,11 @@ CONFIG_SND_SOC_I2C_AND_SPI=m
# CODEC drivers
#
CONFIG_SND_SOC_WM_HUBS=m
+# CONFIG_SND_SOC_AC97_CODEC is not set
# CONFIG_SND_SOC_ADAU1701 is not set
# CONFIG_SND_SOC_AK4104 is not set
# CONFIG_SND_SOC_AK4554 is not set
+# CONFIG_SND_SOC_AK4613 is not set
# CONFIG_SND_SOC_AK4642 is not set
# CONFIG_SND_SOC_AK5386 is not set
# CONFIG_SND_SOC_ALC5623 is not set
@@ -4849,11 +5364,12 @@ CONFIG_SND_SOC_CS42L51=m
# CONFIG_SND_SOC_CS4271_I2C is not set
# CONFIG_SND_SOC_CS4271_SPI is not set
# CONFIG_SND_SOC_CS42XX8_I2C is not set
+# CONFIG_SND_SOC_CS4349 is not set
CONFIG_SND_SOC_DMIC=m
-CONFIG_SND_SOC_HDMI_CODEC=m
CONFIG_SND_SOC_ES8328=m
CONFIG_SND_SOC_ES8328_I2C=m
CONFIG_SND_SOC_ES8328_SPI=m
+# CONFIG_SND_SOC_GTM601 is not set
CONFIG_SND_SOC_MAX98090=m
CONFIG_SND_SOC_MAX98095=m
# CONFIG_SND_SOC_PCM1681 is not set
@@ -4863,7 +5379,9 @@ CONFIG_SND_SOC_MAX98095=m
CONFIG_SND_SOC_RL6231=m
CONFIG_SND_SOC_RT5631=m
CONFIG_SND_SOC_RT5640=m
-# CONFIG_SND_SOC_RT5677_SPI is not set
+CONFIG_SND_SOC_RT5645=m
+CONFIG_SND_SOC_RT5677=m
+CONFIG_SND_SOC_RT5677_SPI=m
CONFIG_SND_SOC_SGTL5000=m
# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set
CONFIG_SND_SOC_SPDIF=m
@@ -4872,15 +5390,17 @@ CONFIG_SND_SOC_SPDIF=m
# CONFIG_SND_SOC_SSM4567 is not set
# CONFIG_SND_SOC_STA32X is not set
# CONFIG_SND_SOC_STA350 is not set
+# CONFIG_SND_SOC_STI_SAS is not set
# CONFIG_SND_SOC_TAS2552 is not set
# CONFIG_SND_SOC_TAS5086 is not set
+# CONFIG_SND_SOC_TAS571X is not set
# CONFIG_SND_SOC_TFA9879 is not set
CONFIG_SND_SOC_TLV320AIC23=m
CONFIG_SND_SOC_TLV320AIC23_I2C=m
# CONFIG_SND_SOC_TLV320AIC23_SPI is not set
CONFIG_SND_SOC_TLV320AIC31XX=m
CONFIG_SND_SOC_TLV320AIC3X=m
-# CONFIG_SND_SOC_TS3A227E is not set
+CONFIG_SND_SOC_TS3A227E=m
CONFIG_SND_SOC_TWL4030=m
CONFIG_SND_SOC_TWL6040=m
# CONFIG_SND_SOC_WM8510 is not set
@@ -4930,6 +5450,7 @@ CONFIG_HID_BELKIN=m
CONFIG_HID_BETOP_FF=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
+CONFIG_HID_CORSAIR=m
CONFIG_HID_PRODIKEYS=m
CONFIG_HID_CP2112=m
CONFIG_HID_CYPRESS=m
@@ -4939,6 +5460,8 @@ CONFIG_HID_EMS_FF=m
CONFIG_HID_ELECOM=m
CONFIG_HID_ELO=m
CONFIG_HID_EZKEY=m
+CONFIG_HID_GEMBIRD=m
+CONFIG_HID_GFRM=m
CONFIG_HID_HOLTEK=m
CONFIG_HOLTEK_FF=y
CONFIG_HID_GT683R=m
@@ -5031,7 +5554,8 @@ CONFIG_USB_OTG=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
# CONFIG_USB_OTG_FSM is not set
-CONFIG_USB_MON=y
+# CONFIG_USB_ULPI_BUS is not set
+CONFIG_USB_MON=m
CONFIG_USB_WUSB=m
CONFIG_USB_WUSB_CBAF=m
# CONFIG_USB_WUSB_CBAF_DEBUG is not set
@@ -5057,7 +5581,6 @@ CONFIG_USB_EHCI_HCD_PLATFORM=y
# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1362_HCD is not set
-# CONFIG_USB_FUSBH200_HCD is not set
# CONFIG_USB_FOTG210_HCD is not set
# CONFIG_USB_MAX3421_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -5126,14 +5649,16 @@ CONFIG_USB_MUSB_DUAL_ROLE=y
#
# Platform Glue Layer
#
+CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB_MUSB_TUSB6010=y
CONFIG_USB_MUSB_OMAP2PLUS=y
CONFIG_USB_MUSB_AM35X=y
CONFIG_USB_MUSB_DSPS=y
CONFIG_USB_MUSB_AM335X_CHILD=y
-# CONFIG_USB_INVENTRA_DMA is not set
-# CONFIG_USB_TI_CPPI41_DMA is not set
-# CONFIG_USB_TUSB_OMAP_DMA is not set
+
+#
+# MUSB DMA mode
+#
CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_DWC3=y
# CONFIG_USB_DWC3_HOST is not set
@@ -5147,19 +5672,29 @@ CONFIG_USB_DWC3_OMAP=y
CONFIG_USB_DWC3_EXYNOS=y
CONFIG_USB_DWC3_PCI=y
CONFIG_USB_DWC3_KEYSTONE=y
+CONFIG_USB_DWC2=y
+# CONFIG_USB_DWC2_HOST is not set
#
-# Debugging features
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
#
-# CONFIG_USB_DWC3_DEBUG is not set
-# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_DWC2_PERIPHERAL is not set
+CONFIG_USB_DWC2_DUAL_ROLE=y
+# CONFIG_USB_DWC2_PCI is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_OF=y
CONFIG_USB_CHIPIDEA_PCI=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
# CONFIG_USB_CHIPIDEA_DEBUG is not set
-# CONFIG_USB_ISP1760 is not set
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_ISP1761_UDC=y
+# CONFIG_USB_ISP1760_HOST_ROLE is not set
+# CONFIG_USB_ISP1760_GADGET_ROLE is not set
+CONFIG_USB_ISP1760_DUAL_ROLE=y
#
# USB port drivers
@@ -5259,6 +5794,7 @@ CONFIG_USB_EZUSB_FX2=m
CONFIG_USB_HSIC_USB3503=y
# CONFIG_USB_LINK_LAYER_TEST is not set
CONFIG_USB_CHAOSKEY=m
+CONFIG_USB_ONBOARD_DEVICE=y
CONFIG_USB_ATM=m
CONFIG_USB_SPEEDTOUCH=m
CONFIG_USB_CXACRU=m
@@ -5275,7 +5811,7 @@ CONFIG_AM335X_CONTROL_USB=y
CONFIG_AM335X_PHY_USB=y
CONFIG_TWL6030_USB=y
CONFIG_USB_GPIO_VBUS=y
-# CONFIG_USB_ISP1301 is not set
+CONFIG_USB_ISP1301=y
CONFIG_USB_MXS_PHY=y
CONFIG_USB_ULPI=y
CONFIG_USB_ULPI_VIEWPORT=y
@@ -5301,10 +5837,10 @@ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
# CONFIG_USB_BDC_UDC is not set
# CONFIG_USB_AMD5536UDC is not set
# CONFIG_USB_NET2272 is not set
-# CONFIG_USB_NET2280 is not set
+CONFIG_USB_NET2280=m
# CONFIG_USB_GOKU is not set
# CONFIG_USB_EG20T is not set
-# CONFIG_USB_GADGET_XILINX is not set
+CONFIG_USB_GADGET_XILINX=y
# CONFIG_USB_DUMMY_HCD is not set
CONFIG_USB_LIBCOMPOSITE=m
CONFIG_USB_F_ACM=m
@@ -5352,7 +5888,6 @@ CONFIG_UWB_WHCI=m
CONFIG_UWB_I1480U=m
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_CLKGATE is not set
#
# MMC/SD/SDIO Card Drivers
@@ -5366,12 +5901,15 @@ CONFIG_SDIO_UART=m
#
# MMC/SD/SDIO Host Controller Drivers
#
-CONFIG_MMC_ARMMMCI=m
+CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
-# CONFIG_MMC_SDHCI_PCI is not set
+CONFIG_MMC_SDHCI_PCI=y
+CONFIG_MMC_RICOH_MMC=y
CONFIG_MMC_SDHCI_PLTFM=y
-# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+CONFIG_MMC_SDHCI_OF_ARASAN=y
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_OF_ESDHC=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MMC_SDHCI_DOVE=y
CONFIG_MMC_SDHCI_TEGRA=y
@@ -5382,12 +5920,11 @@ CONFIG_MMC_SDHCI_S3C_DMA=y
CONFIG_MMC_OMAP=y
CONFIG_MMC_OMAP_HS=y
# CONFIG_MMC_MXC is not set
-# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_TIFM_SD=m
CONFIG_MMC_MVSDIO=y
-# CONFIG_MMC_CB710 is not set
-# CONFIG_MMC_VIA_SDMMC is not set
+CONFIG_MMC_CB710=m
+CONFIG_MMC_VIA_SDMMC=y
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
CONFIG_MMC_DW_PLTFM=y
CONFIG_MMC_DW_EXYNOS=y
# CONFIG_MMC_DW_K3 is not set
@@ -5396,10 +5933,29 @@ CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_VUB300=m
CONFIG_MMC_USHC=m
# CONFIG_MMC_USDHI6ROL0 is not set
+CONFIG_MMC_REALTEK_PCI=m
CONFIG_MMC_REALTEK_USB=m
CONFIG_MMC_SUNXI=y
-# CONFIG_MMC_TOSHIBA_PCI is not set
-# CONFIG_MEMSTICK is not set
+CONFIG_MMC_TOSHIBA_PCI=m
+# CONFIG_MMC_MTK is not set
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+# CONFIG_MS_BLOCK is not set
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_MEMSTICK_R592=m
+CONFIG_MEMSTICK_REALTEK_PCI=m
+CONFIG_MEMSTICK_REALTEK_USB=m
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_CLASS_FLASH is not set
@@ -5407,6 +5963,8 @@ CONFIG_LEDS_CLASS=y
#
# LED drivers
#
+# CONFIG_LEDS_BCM6328 is not set
+# CONFIG_LEDS_BCM6358 is not set
CONFIG_LEDS_LM3530=m
CONFIG_LEDS_LM3642=m
CONFIG_LEDS_PCA9532=m
@@ -5428,7 +5986,9 @@ CONFIG_LEDS_REGULATOR=m
CONFIG_LEDS_BD2802=m
CONFIG_LEDS_LT3593=m
CONFIG_LEDS_MC13783=m
+CONFIG_LEDS_NS2=y
CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_TLC591XX=m
CONFIG_LEDS_MAX8997=m
CONFIG_LEDS_LM355x=m
@@ -5436,8 +5996,7 @@ CONFIG_LEDS_LM355x=m
# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
#
CONFIG_LEDS_BLINKM=m
-# CONFIG_LEDS_SYSCON is not set
-# CONFIG_LEDS_PM8941_WLED is not set
+CONFIG_LEDS_SYSCON=y
#
# LED Triggers
@@ -5457,17 +6016,44 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_TRANSIENT=m
CONFIG_LEDS_TRIGGER_CAMERA=m
# CONFIG_ACCESSIBILITY is not set
-# CONFIG_INFINIBAND is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_INFINIBAND_CXGB4=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_MLX5_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_OCRDMA=m
+CONFIG_INFINIBAND_IPOIB=m
+CONFIG_INFINIBAND_IPOIB_CM=y
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_SRP=m
+CONFIG_INFINIBAND_SRPT=m
+CONFIG_INFINIBAND_ISER=m
+CONFIG_INFINIBAND_ISERT=m
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
CONFIG_EDAC=y
CONFIG_EDAC_LEGACY_SYSFS=y
# CONFIG_EDAC_DEBUG is not set
CONFIG_EDAC_MM_EDAC=y
+# CONFIG_EDAC_ALTERA_MC is not set
# CONFIG_EDAC_SYNOPSYS is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
# CONFIG_RTC_DEBUG is not set
#
@@ -5485,7 +6071,7 @@ CONFIG_RTC_INTF_DEV_UIE_EMUL=y
# CONFIG_RTC_DRV_ABB5ZES3 is not set
# CONFIG_RTC_DRV_ABX80X is not set
CONFIG_RTC_DRV_AS3722=y
-CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_DS1374=m
CONFIG_RTC_DRV_DS1374_WDT=y
CONFIG_RTC_DRV_DS1672=m
@@ -5493,9 +6079,10 @@ CONFIG_RTC_DRV_DS3232=m
CONFIG_RTC_DRV_HYM8563=m
CONFIG_RTC_DRV_MAX6900=m
CONFIG_RTC_DRV_MAX8907=m
-# CONFIG_RTC_DRV_MAX8997 is not set
+CONFIG_RTC_DRV_MAX8997=m
CONFIG_RTC_DRV_MAX77686=y
-# CONFIG_RTC_DRV_MAX77802 is not set
+CONFIG_RTC_DRV_RK808=m
+CONFIG_RTC_DRV_MAX77802=m
CONFIG_RTC_DRV_RS5C372=m
CONFIG_RTC_DRV_ISL1208=m
CONFIG_RTC_DRV_ISL12022=m
@@ -5504,7 +6091,7 @@ CONFIG_RTC_DRV_X1205=m
CONFIG_RTC_DRV_PALMAS=y
CONFIG_RTC_DRV_PCF2127=m
CONFIG_RTC_DRV_PCF8523=y
-CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8563=y
CONFIG_RTC_DRV_PCF85063=m
CONFIG_RTC_DRV_PCF8583=m
CONFIG_RTC_DRV_M41T80=m
@@ -5517,8 +6104,9 @@ CONFIG_RTC_DRV_S35390A=y
CONFIG_RTC_DRV_FM3130=m
CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_RX8025=m
-CONFIG_RTC_DRV_EM3027=y
+CONFIG_RTC_DRV_EM3027=m
CONFIG_RTC_DRV_RV3029C2=m
+CONFIG_RTC_DRV_RV8803=m
CONFIG_RTC_DRV_S5M=y
#
@@ -5566,6 +6154,7 @@ CONFIG_RTC_DRV_MSM6242=m
CONFIG_RTC_DRV_BQ4802=m
CONFIG_RTC_DRV_RP5C01=m
CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_ZYNQMP=m
#
# on-CPU RTC drivers
@@ -5579,12 +6168,11 @@ CONFIG_RTC_DRV_PL031=y
CONFIG_RTC_DRV_SUN6I=y
CONFIG_RTC_DRV_SUNXI=y
CONFIG_RTC_DRV_MV=y
-# CONFIG_RTC_DRV_ARMADA38X is not set
+CONFIG_RTC_DRV_ARMADA38X=y
CONFIG_RTC_DRV_MC13XXX=y
CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_MXC=y
CONFIG_RTC_DRV_SNVS=y
-# CONFIG_RTC_DRV_XGENE is not set
#
# HID Sensor RTC drivers
@@ -5597,29 +6185,32 @@ CONFIG_DMADEVICES=y
# DMA Devices
#
CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_OF=y
CONFIG_AMBA_PL08X=y
-CONFIG_DW_DMAC_CORE=y
-CONFIG_DW_DMAC=y
-# CONFIG_DW_DMAC_PCI is not set
-# CONFIG_HSU_DMA_PCI is not set
+CONFIG_AXI_DMAC=y
+CONFIG_DMA_OMAP=y
+CONFIG_DMA_SUN4I=y
+CONFIG_DMA_SUN6I=y
+CONFIG_FSL_EDMA=y
+CONFIG_IMX_DMA=y
+CONFIG_IMX_SDMA=y
+# CONFIG_INTEL_IDMA64 is not set
CONFIG_MV_XOR=y
+CONFIG_MXS_DMA=y
CONFIG_MX3_IPU=y
CONFIG_MX3_IPU_IRQS=4
-CONFIG_TEGRA20_APB_DMA=y
-CONFIG_TI_EDMA=y
+# CONFIG_NBPFAXI_DMA is not set
CONFIG_PL330_DMA=y
-CONFIG_IMX_SDMA=y
-CONFIG_IMX_DMA=y
-CONFIG_MXS_DMA=y
-CONFIG_DMA_OMAP=y
+CONFIG_TEGRA20_APB_DMA=y
CONFIG_TI_CPPI41=y
-CONFIG_FSL_EDMA=y
+CONFIG_TI_DMA_CROSSBAR=y
+CONFIG_TI_EDMA=y
# CONFIG_XILINX_VDMA is not set
-CONFIG_DMA_SUN6I=y
-# CONFIG_NBPFAXI_DMA is not set
-CONFIG_DMA_ENGINE=y
-CONFIG_DMA_VIRTUAL_CHANNELS=y
-CONFIG_DMA_OF=y
+CONFIG_DW_DMAC_CORE=y
+CONFIG_DW_DMAC=y
+# CONFIG_DW_DMAC_PCI is not set
#
# DMA Clients
@@ -5629,15 +6220,15 @@ CONFIG_ASYNC_TX_DMA=y
CONFIG_DMA_ENGINE_RAID=y
# CONFIG_AUXDISPLAY is not set
CONFIG_UIO=m
-# CONFIG_UIO_CIF is not set
+CONFIG_UIO_CIF=m
CONFIG_UIO_PDRV_GENIRQ=m
CONFIG_UIO_DMEM_GENIRQ=m
-# CONFIG_UIO_AEC is not set
-# CONFIG_UIO_SERCOS3 is not set
-# CONFIG_UIO_PCI_GENERIC is not set
-# CONFIG_UIO_NETX is not set
-# CONFIG_UIO_PRUSS is not set
-# CONFIG_UIO_MF624 is not set
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+CONFIG_UIO_PCI_GENERIC=m
+CONFIG_UIO_NETX=m
+CONFIG_UIO_PRUSS=m
+CONFIG_UIO_MF624=m
# CONFIG_VFIO is not set
# CONFIG_VIRT_DRIVERS is not set
CONFIG_VIRTIO=y
@@ -5645,10 +6236,12 @@ CONFIG_VIRTIO=y
#
# Virtio drivers
#
-# CONFIG_VIRTIO_PCI is not set
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_PCI_LEGACY=y
CONFIG_VIRTIO_BALLOON=m
-# CONFIG_VIRTIO_INPUT is not set
-# CONFIG_VIRTIO_MMIO is not set
+CONFIG_VIRTIO_INPUT=m
+CONFIG_VIRTIO_MMIO=m
+# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
#
# Microsoft Hyper-V guest support
@@ -5738,13 +6331,6 @@ CONFIG_TSL2583=m
CONFIG_TSL2x7x=m
#
-# Magnetometer sensors
-#
-CONFIG_SENSORS_HMC5843=m
-CONFIG_SENSORS_HMC5843_I2C=m
-CONFIG_SENSORS_HMC5843_SPI=m
-
-#
# Active energy metering IC
#
CONFIG_ADE7753=m
@@ -5765,12 +6351,9 @@ CONFIG_AD2S1210=m
#
# Triggers - standalone
#
-# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set
# CONFIG_IIO_SIMPLE_DUMMY is not set
-# CONFIG_FB_SM7XX is not set
# CONFIG_FB_SM750 is not set
# CONFIG_FB_XGI is not set
-# CONFIG_FT1000 is not set
#
# Speakup console speech
@@ -5785,9 +6368,6 @@ CONFIG_NVEC_PAZ00=m
CONFIG_STAGING_MEDIA=y
CONFIG_I2C_BCM2048=m
CONFIG_DVB_CXD2099=m
-CONFIG_VIDEO_DT3155=m
-CONFIG_DT3155_CCIR=y
-CONFIG_DT3155_STREAMING=y
# CONFIG_DVB_MN88472 is not set
# CONFIG_DVB_MN88473 is not set
# CONFIG_VIDEO_OMAP4 is not set
@@ -5799,6 +6379,7 @@ CONFIG_LIRC_SERIAL=m
CONFIG_LIRC_SERIAL_TRANSMITTER=y
CONFIG_LIRC_SIR=m
CONFIG_LIRC_ZILOG=m
+# CONFIG_STAGING_RDMA is not set
#
# Android
@@ -5810,7 +6391,7 @@ CONFIG_ANDROID_TIMED_GPIO=m
CONFIG_SYNC=y
# CONFIG_SW_SYNC is not set
# CONFIG_ION is not set
-CONFIG_USB_WPAN_HCD=m
+# CONFIG_STAGING_BOARD is not set
CONFIG_WIMAX_GDM72XX=m
CONFIG_WIMAX_GDM72XX_QOS=y
CONFIG_WIMAX_GDM72XX_K_MODE=y
@@ -5819,15 +6400,52 @@ CONFIG_WIMAX_GDM72XX_USB=y
# CONFIG_WIMAX_GDM72XX_SDIO is not set
CONFIG_WIMAX_GDM72XX_USB_PM=y
CONFIG_LTE_GDM724X=m
+# CONFIG_FIREWIRE_SERIAL is not set
# CONFIG_MTD_SPINAND_MT29F is not set
# CONFIG_LUSTRE_FS is not set
# CONFIG_DGNC is not set
# CONFIG_DGAP is not set
CONFIG_GS_FPGABOOT=m
# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set
-# CONFIG_FB_TFT is not set
-# CONFIG_I2O is not set
-# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_FB_TFT=m
+CONFIG_FB_TFT_AGM1264K_FL=m
+CONFIG_FB_TFT_BD663474=m
+CONFIG_FB_TFT_HX8340BN=m
+CONFIG_FB_TFT_HX8347D=m
+CONFIG_FB_TFT_HX8353D=m
+CONFIG_FB_TFT_HX8357D=m
+CONFIG_FB_TFT_ILI9163=m
+CONFIG_FB_TFT_ILI9320=m
+CONFIG_FB_TFT_ILI9325=m
+CONFIG_FB_TFT_ILI9340=m
+CONFIG_FB_TFT_ILI9341=m
+CONFIG_FB_TFT_ILI9481=m
+CONFIG_FB_TFT_ILI9486=m
+CONFIG_FB_TFT_PCD8544=m
+CONFIG_FB_TFT_RA8875=m
+CONFIG_FB_TFT_S6D02A1=m
+CONFIG_FB_TFT_S6D1121=m
+CONFIG_FB_TFT_SSD1289=m
+CONFIG_FB_TFT_SSD1305=m
+CONFIG_FB_TFT_SSD1306=m
+CONFIG_FB_TFT_SSD1325=m
+CONFIG_FB_TFT_SSD1331=m
+CONFIG_FB_TFT_SSD1351=m
+CONFIG_FB_TFT_ST7735R=m
+CONFIG_FB_TFT_ST7789V=m
+CONFIG_FB_TFT_TINYLCD=m
+CONFIG_FB_TFT_TLS8204=m
+CONFIG_FB_TFT_UC1611=m
+CONFIG_FB_TFT_UC1701=m
+CONFIG_FB_TFT_UPD161704=m
+CONFIG_FB_TFT_WATTEROTT=m
+CONFIG_FB_FLEX=m
+CONFIG_FB_TFT_FBTFT_DEVICE=m
+# CONFIG_WILC1000_DRIVER is not set
+# CONFIG_MOST is not set
+CONFIG_CHROME_PLATFORMS=y
+CONFIG_CROS_EC_CHARDEV=y
+CONFIG_CROS_EC_PROTO=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y
@@ -5835,15 +6453,21 @@ CONFIG_COMMON_CLK=y
#
# Common Clock Framework
#
+CONFIG_COMMON_CLK_VERSATILE=y
+CONFIG_CLK_SP810=y
+CONFIG_CLK_VEXPRESS_OSC=y
CONFIG_COMMON_CLK_MAX_GEN=y
CONFIG_COMMON_CLK_MAX77686=y
-# CONFIG_COMMON_CLK_MAX77802 is not set
+CONFIG_COMMON_CLK_MAX77802=y
+CONFIG_COMMON_CLK_RK808=y
# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_CLK_TWL6040=y
# CONFIG_COMMON_CLK_AXI_CLKGEN is not set
-# CONFIG_CLK_QORIQ is not set
+CONFIG_CLK_QORIQ=y
CONFIG_COMMON_CLK_KEYSTONE=y
CONFIG_COMMON_CLK_PALMAS=y
# CONFIG_COMMON_CLK_PWM is not set
@@ -5855,9 +6479,11 @@ CONFIG_MVEBU_CLK_COREDIV=y
CONFIG_ARMADA_370_CLK=y
CONFIG_ARMADA_375_CLK=y
CONFIG_ARMADA_38X_CLK=y
+CONFIG_ARMADA_39X_CLK=y
CONFIG_ARMADA_XP_CLK=y
CONFIG_DOVE_CLK=y
CONFIG_COMMON_CLK_SAMSUNG=y
+CONFIG_TEGRA_CLK_EMC=y
CONFIG_HWSPINLOCK=y
#
@@ -5869,6 +6495,7 @@ CONFIG_HWSPINLOCK_OMAP=y
# Clock Source drivers
#
CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
CONFIG_CLKSRC_MMIO=y
CONFIG_DW_APB_TIMER=y
CONFIG_DW_APB_TIMER_OF=y
@@ -5880,9 +6507,11 @@ CONFIG_SUN4I_TIMER=y
CONFIG_SUN5I_HSTIMER=y
CONFIG_TEGRA_TIMER=y
CONFIG_CADENCE_TTC_TIMER=y
+CONFIG_CLKSRC_TI_32K=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
CONFIG_ARM_GLOBAL_TIMER=y
+CONFIG_ARM_TIMER_SP804=y
CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y
# CONFIG_ATMEL_PIT is not set
CONFIG_CLKSRC_EXYNOS_MCT=y
@@ -5891,12 +6520,15 @@ CONFIG_CLKSRC_SAMSUNG_PWM=y
# CONFIG_SH_TIMER_MTU2 is not set
# CONFIG_SH_TIMER_TMU is not set
# CONFIG_EM_TIMER_STI is not set
+CONFIG_CLKSRC_VERSATILE=y
+CONFIG_CLKSRC_IMX_GPT=y
CONFIG_MAILBOX=y
# CONFIG_ARM_MHU is not set
CONFIG_PL320_MBOX=y
CONFIG_OMAP2PLUS_MBOX=y
CONFIG_OMAP_MBOX_KFIFO_SIZE=256
# CONFIG_ALTERA_MBOX is not set
+# CONFIG_MAILBOX_TEST is not set
CONFIG_IOMMU_API=y
CONFIG_IOMMU_SUPPORT=y
@@ -5932,6 +6564,9 @@ CONFIG_RPMSG=y
#
# SOC (System On Chip) specific Drivers
#
+# CONFIG_SOC_BRCMSTB is not set
+CONFIG_ROCKCHIP_PM_DOMAINS=y
+CONFIG_SUNXI_SRAM=y
CONFIG_SOC_TI=y
# CONFIG_KEYSTONE_NAVIGATOR_QMSS is not set
# CONFIG_KEYSTONE_NAVIGATOR_DMA is not set
@@ -5957,43 +6592,60 @@ CONFIG_EXTCON=y
# Extcon Device Drivers
#
# CONFIG_EXTCON_ADC_JACK is not set
+# CONFIG_EXTCON_AXP288 is not set
CONFIG_EXTCON_GPIO=y
-# CONFIG_EXTCON_MAX77693 is not set
+CONFIG_EXTCON_MAX14577=y
+CONFIG_EXTCON_MAX77693=y
# CONFIG_EXTCON_MAX8997 is not set
CONFIG_EXTCON_PALMAS=y
# CONFIG_EXTCON_RT8973A is not set
# CONFIG_EXTCON_SM5502 is not set
CONFIG_EXTCON_USB_GPIO=y
CONFIG_MEMORY=y
+# CONFIG_ARM_PL172_MPMC is not set
CONFIG_TI_AEMIF=y
CONFIG_TI_EMIF=y
CONFIG_OMAP_GPMC=y
+# CONFIG_OMAP_GPMC_DEBUG is not set
CONFIG_MVEBU_DEVBUS=y
CONFIG_TEGRA20_MC=y
CONFIG_TEGRA_MC=y
+CONFIG_TEGRA124_EMC=y
CONFIG_IIO=m
CONFIG_IIO_BUFFER=y
-CONFIG_IIO_BUFFER_CB=y
+CONFIG_IIO_BUFFER_CB=m
CONFIG_IIO_KFIFO_BUF=m
CONFIG_IIO_TRIGGERED_BUFFER=m
+CONFIG_IIO_CONFIGFS=m
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+CONFIG_IIO_SW_TRIGGER=m
+CONFIG_IIO_TRIGGERED_EVENT=m
#
# Accelerometers
#
CONFIG_BMA180=m
CONFIG_BMC150_ACCEL=m
+CONFIG_BMC150_ACCEL_I2C=m
+CONFIG_BMC150_ACCEL_SPI=m
CONFIG_HID_SENSOR_ACCEL_3D=m
CONFIG_IIO_ST_ACCEL_3AXIS=m
CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m
CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m
CONFIG_KXSD9=m
-CONFIG_MMA8452=m
CONFIG_KXCJK1013=m
+CONFIG_MMA7455=m
+CONFIG_MMA7455_I2C=m
+CONFIG_MMA7455_SPI=m
+CONFIG_MMA8452=m
CONFIG_MMA9551_CORE=m
CONFIG_MMA9551=m
CONFIG_MMA9553=m
+CONFIG_MXC4005=m
+CONFIG_MXC6255=m
+CONFIG_STK8312=m
+CONFIG_STK8BA50=m
#
# Analog to digital converters
@@ -6011,14 +6663,21 @@ CONFIG_AD799X=m
CONFIG_AXP288_ADC=m
CONFIG_CC10001_ADC=m
CONFIG_EXYNOS_ADC=m
+CONFIG_HI8435=m
+CONFIG_INA2XX_ADC=m
+CONFIG_IMX7D_ADC=m
CONFIG_MAX1027=m
CONFIG_MAX1363=m
CONFIG_MCP320X=m
CONFIG_MCP3422=m
CONFIG_NAU7802=m
+CONFIG_PALMAS_GPADC=m
CONFIG_ROCKCHIP_SARADC=m
CONFIG_TI_ADC081C=m
+CONFIG_TI_ADC0832=m
CONFIG_TI_ADC128S052=m
+CONFIG_TI_ADS1015=m
+CONFIG_TI_ADS8688=m
CONFIG_TI_AM335X_ADC=m
CONFIG_TWL4030_MADC=m
CONFIG_TWL6030_GPADC=m
@@ -6032,15 +6691,23 @@ CONFIG_XILINX_XADC=m
CONFIG_AD8366=m
#
+# Chemical Sensors
+#
+CONFIG_ATLAS_PH_SENSOR=m
+CONFIG_IAQCORE=m
+CONFIG_VZ89X=m
+
+#
# Hid Sensor IIO Common
#
CONFIG_HID_SENSOR_IIO_COMMON=m
CONFIG_HID_SENSOR_IIO_TRIGGER=m
+CONFIG_IIO_MS_SENSORS_I2C=m
#
# SSP Sensor Common
#
-# CONFIG_IIO_SSP_SENSORS_COMMONS is not set
+CONFIG_IIO_SSP_SENSORS_COMMONS=m
CONFIG_IIO_SSP_SENSORHUB=m
CONFIG_IIO_ST_SENSORS_I2C=m
CONFIG_IIO_ST_SENSORS_SPI=m
@@ -6059,13 +6726,21 @@ CONFIG_AD5504=m
CONFIG_AD5624R_SPI=m
CONFIG_AD5686=m
CONFIG_AD5755=m
+CONFIG_AD5761=m
CONFIG_AD5764=m
CONFIG_AD5791=m
CONFIG_AD7303=m
+CONFIG_M62332=m
CONFIG_MAX517=m
CONFIG_MAX5821=m
CONFIG_MCP4725=m
CONFIG_MCP4922=m
+CONFIG_VF610_DAC=m
+
+#
+# IIO dummy driver
+#
+# CONFIG_IIO_SIMPLE_DUMMY is not set
#
# Frequency Synthesizers DDS/PLL
@@ -6090,6 +6765,8 @@ CONFIG_ADIS16136=m
CONFIG_ADIS16260=m
CONFIG_ADXRS450=m
CONFIG_BMG160=m
+CONFIG_BMG160_I2C=m
+CONFIG_BMG160_SPI=m
CONFIG_HID_SENSOR_GYRO_3D=m
CONFIG_IIO_ST_GYRO_3AXIS=m
CONFIG_IIO_ST_GYRO_I2C_3AXIS=m
@@ -6097,9 +6774,22 @@ CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
CONFIG_ITG3200=m
#
+# Health Sensors
+#
+
+#
+# Heart Rate Monitors
+#
+CONFIG_AFE4403=m
+CONFIG_AFE4404=m
+CONFIG_MAX30100=m
+
+#
# Humidity sensors
#
CONFIG_DHT11=m
+CONFIG_HDC100X=m
+CONFIG_HTU21=m
CONFIG_SI7005=m
CONFIG_SI7020=m
@@ -6110,6 +6800,8 @@ CONFIG_ADIS16400=m
CONFIG_ADIS16480=m
CONFIG_KMX61=m
CONFIG_INV_MPU6050_IIO=m
+CONFIG_INV_MPU6050_I2C=m
+CONFIG_INV_MPU6050_SPI=m
CONFIG_IIO_ADIS_LIB=m
CONFIG_IIO_ADIS_LIB_BUFFER=y
@@ -6119,6 +6811,8 @@ CONFIG_IIO_ADIS_LIB_BUFFER=y
CONFIG_ADJD_S311=m
CONFIG_AL3320A=m
CONFIG_APDS9300=m
+CONFIG_APDS9960=m
+CONFIG_BH1750=m
CONFIG_CM32181=m
CONFIG_CM3232=m
CONFIG_CM3323=m
@@ -6128,11 +6822,16 @@ CONFIG_ISL29125=m
CONFIG_HID_SENSOR_ALS=m
CONFIG_HID_SENSOR_PROX=m
CONFIG_JSA1212=m
+CONFIG_RPR0521=m
CONFIG_LTR501=m
+CONFIG_OPT3001=m
+CONFIG_PA12203001=m
+CONFIG_STK3310=m
CONFIG_TCS3414=m
CONFIG_TCS3472=m
CONFIG_SENSORS_TSL2563=m
CONFIG_TSL4531=m
+CONFIG_US5182D=m
CONFIG_VCNL4000=m
#
@@ -6140,11 +6839,16 @@ CONFIG_VCNL4000=m
#
CONFIG_AK8975=m
CONFIG_AK09911=m
+CONFIG_BMC150_MAGN=m
CONFIG_MAG3110=m
CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+CONFIG_MMC35240=m
CONFIG_IIO_ST_MAGN_3AXIS=m
CONFIG_IIO_ST_MAGN_I2C_3AXIS=m
CONFIG_IIO_ST_MAGN_SPI_3AXIS=m
+CONFIG_SENSORS_HMC5843=m
+CONFIG_SENSORS_HMC5843_I2C=m
+CONFIG_SENSORS_HMC5843_SPI=m
#
# Inclinometer sensors
@@ -6155,19 +6859,29 @@ CONFIG_HID_SENSOR_DEVICE_ROTATION=m
#
# Triggers - standalone
#
+CONFIG_IIO_HRTIMER_TRIGGER=m
CONFIG_IIO_INTERRUPT_TRIGGER=m
CONFIG_IIO_SYSFS_TRIGGER=m
#
+# Digital potentiometers
+#
+CONFIG_MCP4531=m
+CONFIG_TPL0102=m
+
+#
# Pressure sensors
#
CONFIG_BMP280=m
CONFIG_HID_SENSOR_PRESS=m
CONFIG_MPL115=m
+CONFIG_MPL115_I2C=m
+CONFIG_MPL115_SPI=m
CONFIG_MPL3115=m
CONFIG_MS5611=m
CONFIG_MS5611_I2C=m
CONFIG_MS5611_SPI=m
+CONFIG_MS5637=m
CONFIG_IIO_ST_PRESS=m
CONFIG_IIO_ST_PRESS_I2C=m
CONFIG_IIO_ST_PRESS_SPI=m
@@ -6181,6 +6895,7 @@ CONFIG_AS3935=m
#
# Proximity sensors
#
+CONFIG_LIDAR_LITE_V2=m
CONFIG_SX9500=m
#
@@ -6188,11 +6903,15 @@ CONFIG_SX9500=m
#
CONFIG_MLX90614=m
CONFIG_TMP006=m
+CONFIG_TSYS01=m
+CONFIG_TSYS02D=m
+# CONFIG_NTB is not set
# CONFIG_VME_BUS is not set
CONFIG_PWM=y
CONFIG_PWM_SYSFS=y
# CONFIG_PWM_FSL_FTM is not set
CONFIG_PWM_IMX=m
+CONFIG_PWM_OMAP_DMTIMER=m
CONFIG_PWM_PCA9685=m
CONFIG_PWM_ROCKCHIP=m
CONFIG_PWM_SAMSUNG=m
@@ -6224,6 +6943,8 @@ CONFIG_GENERIC_PHY=y
CONFIG_ARMADA375_USBCLUSTER_PHY=y
# CONFIG_PHY_DM816X_USB is not set
CONFIG_PHY_EXYNOS_MIPI_VIDEO=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
CONFIG_PHY_MVEBU_SATA=y
CONFIG_OMAP_CONTROL_PHY=y
CONFIG_OMAP_USB2=y
@@ -6233,7 +6954,7 @@ CONFIG_PHY_EXYNOS_DP_VIDEO=y
# CONFIG_BCM_KONA_USB2_PHY is not set
CONFIG_PHY_EXYNOS5250_SATA=y
CONFIG_PHY_SUN4I_USB=y
-# CONFIG_PHY_SUN9I_USB is not set
+CONFIG_PHY_SUN9I_USB=y
CONFIG_PHY_SAMSUNG_USB2=y
CONFIG_PHY_EXYNOS4210_USB2=y
CONFIG_PHY_EXYNOS4X12_USB2=y
@@ -6242,6 +6963,11 @@ CONFIG_PHY_EXYNOS5_USBDRD=y
CONFIG_PHY_ROCKCHIP_USB=y
# CONFIG_POWERCAP is not set
# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+CONFIG_ARM_PMU=y
CONFIG_RAS=y
# CONFIG_THUNDERBOLT is not set
@@ -6252,11 +6978,26 @@ CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDER_IPC_32BIT=y
CONFIG_NVMEM=y
+CONFIG_NVMEM_IMX_OCOTP=y
+CONFIG_ROCKCHIP_EFUSE=y
CONFIG_NVMEM_SUNXI_SID=y
+CONFIG_NVMEM_VF610_OCOTP=y
+# CONFIG_STM is not set
+# CONFIG_STM_DUMMY is not set
+# CONFIG_STM_SOURCE_CONSOLE is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+CONFIG_FPGA=m
+CONFIG_FPGA_MGR_SOCFPGA=m
+CONFIG_FPGA_MGR_ZYNQ_FPGA=m
#
# Firmware Drivers
#
+CONFIG_ARM_PSCI_FW=y
# CONFIG_FIRMWARE_MEMMAP is not set
#
@@ -6266,7 +7007,7 @@ CONFIG_DCACHE_WORD_ACCESS=y
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
CONFIG_EXT4_FS=y
-CONFIG_EXT4_USE_FOR_EXT23=y
+CONFIG_EXT4_USE_FOR_EXT2=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_ENCRYPTION=y
@@ -6306,6 +7047,7 @@ CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_F2FS_FS_SECURITY=y
# CONFIG_F2FS_CHECK_FS is not set
+CONFIG_F2FS_FS_ENCRYPTION=y
# CONFIG_F2FS_IO_TRACE is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_EXPORTFS=y
@@ -6365,6 +7107,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_CHILDREN=y
CONFIG_KERNFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
@@ -6389,6 +7132,7 @@ CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
CONFIG_LOGFS=m
CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m
@@ -6463,6 +7207,7 @@ CONFIG_SUNRPC_BACKCHANNEL=y
CONFIG_SUNRPC_SWAP=y
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_SUNRPC_DEBUG is not set
+CONFIG_SUNRPC_XPRT_RDMA=m
CONFIG_CEPH_FS=m
CONFIG_CEPH_FSCACHE=y
CONFIG_CEPH_FS_POSIX_ACL=y
@@ -6478,6 +7223,7 @@ CONFIG_CIFS_DEBUG=y
# CONFIG_CIFS_DEBUG2 is not set
CONFIG_CIFS_DFS_UPCALL=y
CONFIG_CIFS_SMB2=y
+# CONFIG_CIFS_SMB311 is not set
CONFIG_CIFS_FSCACHE=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -6562,6 +7308,7 @@ CONFIG_UNUSED_SYMBOLS=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
CONFIG_MAGIC_SYSRQ=y
@@ -6595,11 +7342,11 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_SCHED_DEBUG=y
+CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
# CONFIG_DEBUG_TIMEKEEPING is not set
CONFIG_TIMER_STATS=y
-# CONFIG_DEBUG_PREEMPT is not set
#
# Lock Debugging (spinlocks, mutexes, etc...)
@@ -6631,8 +7378,8 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_TORTURE_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60
-# CONFIG_RCU_CPU_STALL_INFO is not set
# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
@@ -6655,7 +7402,6 @@ CONFIG_FTRACE=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
CONFIG_FTRACE_SYSCALLS=y
# CONFIG_TRACER_SNAPSHOT is not set
@@ -6676,6 +7422,7 @@ CONFIG_FTRACE_MCOUNT_RECORD=y
# CONFIG_RING_BUFFER_BENCHMARK is not set
# CONFIG_RING_BUFFER_STARTUP_TEST is not set
# CONFIG_TRACE_ENUM_MAP_FILE is not set
+CONFIG_TRACING_EVENTS_GPIO=y
#
# Runtime Testing
@@ -6692,6 +7439,7 @@ CONFIG_FTRACE_MCOUNT_RECORD=y
# CONFIG_TEST_HEXDUMP is not set
# CONFIG_TEST_STRING_HELPERS is not set
# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
# CONFIG_TEST_RHASHTABLE is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_TEST_LKM is not set
@@ -6700,6 +7448,7 @@ CONFIG_FTRACE_MCOUNT_RECORD=y
# CONFIG_TEST_FIRMWARE is not set
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_KGDB=y
@@ -6766,7 +7515,7 @@ CONFIG_CRYPTO=y
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
@@ -6774,14 +7523,18 @@ CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_AKCIPHER2=y
+# CONFIG_CRYPTO_RSA is not set
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_PCRYPT=m
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
@@ -6795,18 +7548,21 @@ CONFIG_CRYPTO_ABLK_HELPER=m
#
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
#
# Block modes
#
CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_CTS=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=y
+# CONFIG_CRYPTO_KEYWRAP is not set
#
# Hash modes
@@ -6823,6 +7579,7 @@ CONFIG_CRYPTO_CRC32C=y
# CONFIG_CRYPTO_CRC32 is not set
CONFIG_CRYPTO_CRCT10DIF=y
CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_POLY1305=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
@@ -6852,6 +7609,7 @@ CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_CHACHA20=m
CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TEA=m
@@ -6864,6 +7622,7 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
@@ -6871,31 +7630,51 @@ CONFIG_CRYPTO_LZ4HC=m
# Random Number Generation
#
CONFIG_CRYPTO_ANSI_CPRNG=m
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
-CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_USER_API=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
-# CONFIG_CRYPTO_USER_API_RNG is not set
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_HW=y
-CONFIG_CRYPTO_DEV_MV_CESA=y
+CONFIG_CRYPTO_DEV_MV_CESA=m
+CONFIG_CRYPTO_DEV_MARVELL_CESA=m
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
-CONFIG_CRYPTO_DEV_OMAP_SHAM=y
-CONFIG_CRYPTO_DEV_OMAP_AES=y
-# CONFIG_CRYPTO_DEV_OMAP_DES is not set
-CONFIG_CRYPTO_DEV_SAHARA=y
-CONFIG_CRYPTO_DEV_S5P=y
+CONFIG_CRYPTO_DEV_FSL_CAAM=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_JR=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9
+# CONFIG_CRYPTO_DEV_FSL_CAAM_INTC is not set
+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=m
+CONFIG_CRYPTO_DEV_FSL_CAAM_IMX=y
+CONFIG_CRYPTO_DEV_FSL_CAAM_LE=y
+# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set
+CONFIG_CRYPTO_DEV_OMAP_SHAM=m
+CONFIG_CRYPTO_DEV_OMAP_AES=m
+CONFIG_CRYPTO_DEV_OMAP_DES=m
+CONFIG_CRYPTO_DEV_SAHARA=m
+CONFIG_CRYPTO_DEV_S5P=m
+# CONFIG_CRYPTO_DEV_MXS_DCP is not set
+CONFIG_CRYPTO_DEV_SUN4I_SS=m
# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
CONFIG_ARM_CRYPTO=y
CONFIG_CRYPTO_SHA1_ARM=y
CONFIG_CRYPTO_SHA1_ARM_NEON=m
# CONFIG_CRYPTO_SHA1_ARM_CE is not set
# CONFIG_CRYPTO_SHA2_ARM_CE is not set
CONFIG_CRYPTO_SHA256_ARM=m
-CONFIG_CRYPTO_SHA512_ARM_NEON=m
+CONFIG_CRYPTO_SHA512_ARM=m
CONFIG_CRYPTO_AES_ARM=y
CONFIG_CRYPTO_AES_ARM_BS=m
# CONFIG_CRYPTO_AES_ARM_CE is not set
@@ -6915,7 +7694,6 @@ CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IO=y
CONFIG_STMP_DEVICE=y
-CONFIG_PERCPU_RWSEM=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
@@ -6955,6 +7733,8 @@ CONFIG_DECOMPRESS_XZ=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_LZ4=y
CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
@@ -6963,6 +7743,7 @@ CONFIG_BTREE=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
CONFIG_CPU_RMAP=y
CONFIG_DQL=y
CONFIG_GLOB=y
@@ -6970,7 +7751,6 @@ CONFIG_GLOB=y
CONFIG_NLATTR=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_LRU_CACHE=m
-CONFIG_AVERAGE=y
CONFIG_CORDIC=m
CONFIG_DDR=y
CONFIG_LIBFDT=y
@@ -6979,5 +7759,6 @@ CONFIG_FONT_SUPPORT=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
+# CONFIG_SG_SPLIT is not set
CONFIG_ARCH_HAS_SG_CHAIN=y
CONFIG_VIRTUALIZATION=y
diff --git a/libre/linux-libre-lts/config.i686 b/libre/linux-libre-lts/config.i686
index e38c3419e..2185e9510 100644
--- a/libre/linux-libre-lts/config.i686
+++ b/libre/linux-libre-lts/config.i686
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/x86 4.1.7-gnu-2-lts Kernel Configuration
+# Linux/x86 4.4.6-gnu-1-lts Kernel Configuration
#
# CONFIG_64BIT is not set
CONFIG_X86_32=y
@@ -34,7 +34,6 @@ CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_HAVE_INTEL_TXT=y
CONFIG_X86_32_SMP=y
-CONFIG_X86_HT=y
CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_FIX_EARLYCON_MEM=y
@@ -80,10 +79,11 @@ CONFIG_HAVE_ARCH_AUDITSYSCALL=y
#
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
# CONFIG_IRQ_DOMAIN_DEBUG is not set
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
@@ -122,12 +122,12 @@ CONFIG_TASK_IO_ACCOUNTING=y
# RCU Subsystem
#
CONFIG_TREE_RCU=y
+CONFIG_RCU_EXPERT=y
CONFIG_SRCU=y
# CONFIG_TASKS_RCU is not set
CONFIG_RCU_STALL_COMMON=y
CONFIG_RCU_FANOUT=32
CONFIG_RCU_FANOUT_LEAF=16
-# CONFIG_RCU_FANOUT_EXACT is not set
# CONFIG_RCU_FAST_NO_HZ is not set
# CONFIG_TREE_RCU_TRACE is not set
CONFIG_RCU_KTHREAD_PRIO=0
@@ -139,9 +139,11 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=19
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
@@ -159,6 +161,7 @@ CONFIG_CFS_BANDWIDTH=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_CGROUP_WRITEBACK=y
# CONFIG_CHECKPOINT_RESTORE is not set
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
@@ -202,11 +205,13 @@ CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
-# CONFIG_BPF_SYSCALL is not set
+CONFIG_BPF_SYSCALL=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_ADVISE_SYSCALLS=y
+CONFIG_USERFAULTFD=y
CONFIG_PCI_QUIRKS=y
+CONFIG_MEMBARRIER=y
# CONFIG_EMBEDDED is not set
CONFIG_HAVE_PERF_EVENTS=y
@@ -221,15 +226,17 @@ CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SLUB_CPU_PARTIAL=y
-CONFIG_SYSTEM_TRUSTED_KEYRING=y
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
+CONFIG_KEXEC_CORE=y
CONFIG_OPROFILE=m
# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_NMI_TIMER=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
CONFIG_OPTPROBES=y
CONFIG_KPROBES_ON_FTRACE=y
CONFIG_UPROBES=y
@@ -247,6 +254,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_DMA_API_DEBUG=y
@@ -273,6 +281,7 @@ CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OLD_SIGACTION=y
@@ -296,7 +305,7 @@ CONFIG_MODVERSIONS=y
CONFIG_MODULE_COMPRESS=y
CONFIG_MODULE_COMPRESS_GZIP=y
# CONFIG_MODULE_COMPRESS_XZ is not set
-CONFIG_STOP_MACHINE=y
+CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_BLOCK=y
CONFIG_LBDAF=y
CONFIG_BLK_DEV_BSG=y
@@ -353,8 +362,10 @@ CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_LOCK_SPIN_ON_OWNER=y
-CONFIG_ARCH_USE_QUEUE_RWLOCK=y
-CONFIG_QUEUE_RWLOCK=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
CONFIG_FREEZER=y
#
@@ -441,18 +452,17 @@ CONFIG_X86_MCE_AMD=y
CONFIG_X86_MCE_THRESHOLD=y
# CONFIG_X86_MCE_INJECT is not set
CONFIG_X86_THERMAL_VECTOR=y
-CONFIG_VM86=y
+# CONFIG_X86_LEGACY_VM86 is not set
+# CONFIG_VM86 is not set
CONFIG_X86_16BIT=y
CONFIG_X86_ESPFIX32=y
CONFIG_TOSHIBA=m
CONFIG_I8K=m
CONFIG_X86_REBOOTFIXUPS=y
-CONFIG_MICROCODE=m
+CONFIG_MICROCODE=y
# CONFIG_MICROCODE_INTEL is not set
# CONFIG_MICROCODE_AMD is not set
CONFIG_MICROCODE_OLD_INTERFACE=y
-# CONFIG_MICROCODE_INTEL_EARLY is not set
-# CONFIG_MICROCODE_AMD_EARLY is not set
CONFIG_X86_MSR=m
CONFIG_X86_CPUID=m
# CONFIG_NOHIGHMEM is not set
@@ -475,7 +485,6 @@ CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_MEMORY_ISOLATION=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MEMORY_BALLOON=y
CONFIG_BALLOON_COMPACTION=y
@@ -504,7 +513,9 @@ CONFIG_ZSMALLOC=y
# CONFIG_PGTABLE_MAPPING is not set
# CONFIG_ZSMALLOC_STAT is not set
CONFIG_GENERIC_EARLY_IOREMAP=y
-CONFIG_X86_PMEM_LEGACY=y
+CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
# CONFIG_HIGHPTE is not set
CONFIG_X86_CHECK_BIOS_CORRUPTION=y
CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
@@ -529,7 +540,7 @@ CONFIG_HZ_100=y
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
CONFIG_KEXEC=y
-# CONFIG_CRASH_DUMP is not set
+CONFIG_CRASH_DUMP=y
CONFIG_KEXEC_JUMP=y
CONFIG_PHYSICAL_START=0x1000000
CONFIG_RELOCATABLE=y
@@ -541,6 +552,7 @@ CONFIG_HOTPLUG_CPU=y
# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
# CONFIG_COMPAT_VDSO is not set
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MODIFY_LDT_SYSCALL=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
#
@@ -571,8 +583,10 @@ CONFIG_ACPI=y
CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
+# CONFIG_ACPI_DEBUGGER is not set
CONFIG_ACPI_SLEEP=y
# CONFIG_ACPI_PROCFS_POWER is not set
+# CONFIG_ACPI_REV_OVERRIDE_POSSIBLE is not set
CONFIG_ACPI_EC_DEBUGFS=m
CONFIG_ACPI_AC=m
CONFIG_ACPI_BATTERY=m
@@ -580,6 +594,8 @@ CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_VIDEO=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_CPU_FREQ_PSS=y
+CONFIG_ACPI_PROCESSOR_IDLE=y
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_IPMI=m
CONFIG_ACPI_HOTPLUG_CPU=y
@@ -698,6 +714,7 @@ CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_PERFORMANCE is not set
CONFIG_PCIE_PME=y
CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
# CONFIG_PCI_DEBUG is not set
CONFIG_PCI_REALLOC_ENABLE_AUTO=y
CONFIG_PCI_STUB=m
@@ -775,7 +792,7 @@ CONFIG_RAPIDIO_CPS_GEN2=m
# Executable file formats / Emulations
#
CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
@@ -784,6 +801,7 @@ CONFIG_COREDUMP=y
CONFIG_HAVE_ATOMIC_IOMAP=y
CONFIG_PMC_ATOM=y
CONFIG_NET=y
+CONFIG_NET_INGRESS=y
#
# Networking options
@@ -816,7 +834,7 @@ CONFIG_NET_IP_TUNNEL=m
CONFIG_NET_IPGRE=m
# CONFIG_NET_IPGRE_BROADCAST is not set
CONFIG_IP_MROUTE=y
-# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_SYN_COOKIES=y
@@ -824,7 +842,6 @@ CONFIG_NET_IPVTI=m
CONFIG_NET_UDP_TUNNEL=m
CONFIG_NET_FOU=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -851,6 +868,7 @@ CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_TCP_CONG_DCTCP=m
+CONFIG_TCP_CONG_CDG=m
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -863,6 +881,7 @@ CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=m
+CONFIG_IPV6_ILA=m
CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
@@ -877,7 +896,9 @@ CONFIG_IPV6_TUNNEL=m
CONFIG_IPV6_GRE=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
-# CONFIG_IPV6_MROUTE is not set
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETLABEL=y
CONFIG_NETWORK_SECMARK=y
CONFIG_NET_PTP_CLASSIFY=y
@@ -890,6 +911,7 @@ CONFIG_BRIDGE_NETFILTER=m
#
# Core Netfilter Configuration
#
+CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_ACCT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
@@ -922,7 +944,7 @@ CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_NETLINK_TIMEOUT=m
CONFIG_NF_CT_NETLINK_HELPER=m
-CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
+CONFIG_NETFILTER_NETLINK_GLUE_CT=y
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_NF_NAT_PROTO_DCCP=m
@@ -937,6 +959,7 @@ CONFIG_NF_NAT_REDIRECT=m
CONFIG_NETFILTER_SYNPROXY=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -1079,6 +1102,7 @@ CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_FO=m
+CONFIG_IP_VS_OVF=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
@@ -1107,7 +1131,9 @@ CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_TABLES_IPV4=m
CONFIG_NFT_CHAIN_ROUTE_IPV4=m
CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_DUP_IPV4=m
CONFIG_NF_LOG_ARP=m
CONFIG_NF_LOG_IPV4=m
CONFIG_NF_REJECT_IPV4=m
@@ -1150,6 +1176,8 @@ CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_NF_TABLES_IPV6=m
CONFIG_NFT_CHAIN_ROUTE_IPV6=m
CONFIG_NFT_REJECT_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
+CONFIG_NF_DUP_IPV6=m
CONFIG_NF_REJECT_IPV6=m
CONFIG_NF_LOG_IPV6=m
CONFIG_NF_NAT_IPV6=m
@@ -1273,6 +1301,7 @@ CONFIG_6LOWPAN_NHC_MOBILITY=m
CONFIG_6LOWPAN_NHC_ROUTING=m
CONFIG_6LOWPAN_NHC_UDP=m
CONFIG_IEEE802154=m
+CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y
CONFIG_IEEE802154_SOCKET=m
CONFIG_IEEE802154_6LOWPAN=m
CONFIG_MAC802154=m
@@ -1323,6 +1352,7 @@ CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_NET_CLS_BPF=m
+CONFIG_NET_CLS_FLOWER=m
# CONFIG_NET_EMATCH is not set
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=m
@@ -1359,8 +1389,10 @@ CONFIG_NETLINK_DIAG=m
CONFIG_MPLS=y
CONFIG_NET_MPLS_GSO=m
CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
CONFIG_HSR=m
CONFIG_NET_SWITCHDEV=y
+CONFIG_NET_L3_MASTER_DEV=y
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_XPS=y
@@ -1400,7 +1432,57 @@ CONFIG_BAYCOM_SER_HDX=m
CONFIG_BAYCOM_PAR=m
CONFIG_BAYCOM_EPP=m
CONFIG_YAM=m
-# CONFIG_CAN is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_LEDS=y
+CONFIG_PCH_CAN=m
+# CONFIG_CAN_GRCAN is not set
+CONFIG_CAN_SJA1000=m
+# CONFIG_CAN_SJA1000_ISA is not set
+CONFIG_CAN_SJA1000_PLATFORM=m
+# CONFIG_CAN_EMS_PCMCIA is not set
+CONFIG_CAN_EMS_PCI=m
+CONFIG_CAN_PEAK_PCMCIA=m
+CONFIG_CAN_PEAK_PCI=m
+CONFIG_CAN_PEAK_PCIEC=y
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
+# CONFIG_CAN_TSCAN1 is not set
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+CONFIG_CAN_C_CAN_PCI=m
+CONFIG_CAN_M_CAN=m
+CONFIG_CAN_CC770=m
+# CONFIG_CAN_CC770_ISA is not set
+CONFIG_CAN_CC770_PLATFORM=m
+
+#
+# CAN SPI interfaces
+#
+# CONFIG_CAN_MCP251X is not set
+
+#
+# CAN USB interfaces
+#
+CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB2=m
+CONFIG_CAN_GS_USB=m
+CONFIG_CAN_KVASER_USB=m
+CONFIG_CAN_PEAK_USB=m
+CONFIG_CAN_8DEV_USB=m
+CONFIG_CAN_SOFTING=m
+# CONFIG_CAN_SOFTING_CS is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
CONFIG_IRDA=m
#
@@ -1467,6 +1549,7 @@ CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_CMTP=m
CONFIG_BT_HIDP=m
+CONFIG_BT_HS=y
CONFIG_BT_LE=y
CONFIG_BT_6LOWPAN=m
# CONFIG_BT_SELFTEST is not set
@@ -1477,8 +1560,11 @@ CONFIG_BT_DEBUGFS=y
#
CONFIG_BT_INTEL=m
CONFIG_BT_BCM=m
+CONFIG_BT_RTL=m
+CONFIG_BT_QCA=m
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTUSB_BCM=y
+CONFIG_BT_HCIBTUSB_RTL=y
CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_H4=y
@@ -1488,6 +1574,7 @@ CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_3WIRE=y
CONFIG_BT_HCIUART_INTEL=y
CONFIG_BT_HCIUART_BCM=y
+CONFIG_BT_HCIUART_QCA=y
CONFIG_BT_HCIBCM203X=m
CONFIG_BT_HCIBPA10X=m
CONFIG_BT_HCIBFUSB=m
@@ -1517,6 +1604,7 @@ CONFIG_CFG80211=m
CONFIG_CFG80211_DEFAULT_PS=y
# CONFIG_CFG80211_DEBUGFS is not set
# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
CONFIG_CFG80211_WEXT=y
CONFIG_CFG80211_WEXT_EXPORT=y
CONFIG_LIB80211=m
@@ -1536,6 +1624,7 @@ CONFIG_MAC80211_LEDS=y
CONFIG_MAC80211_DEBUGFS=y
# CONFIG_MAC80211_MESSAGE_TRACING is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
CONFIG_WIMAX=m
CONFIG_WIMAX_DEBUG_LEVEL=8
CONFIG_RFKILL=m
@@ -1557,6 +1646,7 @@ CONFIG_NFC=m
CONFIG_NFC_DIGITAL=m
CONFIG_NFC_NCI=m
# CONFIG_NFC_NCI_SPI is not set
+# CONFIG_NFC_NCI_UART is not set
CONFIG_NFC_HCI=m
# CONFIG_NFC_SHDLC is not set
@@ -1569,16 +1659,22 @@ CONFIG_NFC_TRF7970A=m
CONFIG_NFC_MEI_PHY=m
CONFIG_NFC_SIM=m
CONFIG_NFC_PORT100=m
+CONFIG_NFC_FDP=m
+CONFIG_NFC_FDP_I2C=m
CONFIG_NFC_PN544=m
CONFIG_NFC_PN544_MEI=m
CONFIG_NFC_MICROREAD=m
CONFIG_NFC_MICROREAD_MEI=m
CONFIG_NFC_MRVL=m
CONFIG_NFC_MRVL_USB=m
+CONFIG_NFC_MRVL_I2C=m
CONFIG_NFC_ST21NFCA=m
-CONFIG_NFC_ST21NFCB=m
-CONFIG_NFC_ST21NFCB_I2C=m
+CONFIG_NFC_ST_NCI=m
+CONFIG_NFC_ST_NCI_I2C=m
+# CONFIG_NFC_ST_NCI_SPI is not set
# CONFIG_NFC_NXP_NCI is not set
+# CONFIG_NFC_S3FWRN5_I2C is not set
+CONFIG_LWTUNNEL=y
#
# Device Drivers
@@ -1606,8 +1702,9 @@ CONFIG_DEV_COREDUMP=y
# CONFIG_GENERIC_CPU_DEVICES is not set
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_REGMAP=y
-CONFIG_REGMAP_I2C=m
+CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=m
+CONFIG_REGMAP_SPMI=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
CONFIG_DMA_SHARED_BUFFER=y
@@ -1685,7 +1782,8 @@ CONFIG_MTD_SCB2_FLASH=m
# CONFIG_MTD_NETtel is not set
# CONFIG_MTD_L440GX is not set
CONFIG_MTD_PCI=m
-# CONFIG_MTD_PCMCIA is not set
+CONFIG_MTD_PCMCIA=m
+# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
CONFIG_MTD_PLATRAM=m
@@ -1717,7 +1815,10 @@ CONFIG_MTD_NAND_ECC_SMC=y
CONFIG_MTD_NAND=m
# CONFIG_MTD_NAND_ECC_BCH is not set
CONFIG_MTD_SM_COMMON=m
-# CONFIG_MTD_NAND_DENALI is not set
+CONFIG_MTD_NAND_DENALI=m
+CONFIG_MTD_NAND_DENALI_PCI=m
+CONFIG_MTD_NAND_DENALI_DT=m
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
CONFIG_MTD_NAND_GPIO=m
# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
CONFIG_MTD_NAND_IDS=m
@@ -1745,12 +1846,9 @@ CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_LIMIT=20
# CONFIG_MTD_UBI_FASTMAP is not set
# CONFIG_MTD_UBI_GLUEBI is not set
-# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_MTD_UBI_BLOCK=y
CONFIG_OF=y
-
-#
-# Device Tree and Open Firmware support
-#
+# CONFIG_OF_UNITTEST is not set
CONFIG_OF_PROMTREE=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_ADDRESS_PCI=y
@@ -1788,7 +1886,6 @@ CONFIG_BLK_DEV_FD=m
CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
CONFIG_ZRAM=m
CONFIG_ZRAM_LZ4_COMPRESS=y
-# CONFIG_ZRAM_DEBUG is not set
CONFIG_BLK_CPQ_CISS_DA=m
# CONFIG_CISS_SCSI_TAPE is not set
CONFIG_BLK_DEV_DAC960=m
@@ -1800,13 +1897,11 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_DRBD=m
# CONFIG_DRBD_FAULT_INJECTION is not set
CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_NVME=m
CONFIG_BLK_DEV_OSD=m
CONFIG_BLK_DEV_SX8=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -1815,6 +1910,7 @@ CONFIG_VIRTIO_BLK=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_RBD=m
CONFIG_BLK_DEV_RSXX=m
+CONFIG_BLK_DEV_NVME=m
#
# Misc devices
@@ -1889,14 +1985,28 @@ CONFIG_VMWARE_VMCI=m
#
#
+# SCIF Bus Driver
+#
+
+#
# Intel MIC Host Driver
#
#
# Intel MIC Card Driver
#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
CONFIG_ECHO=m
# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+# CONFIG_CXL_EEH is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -1982,12 +2092,10 @@ CONFIG_MEGARAID_MM=m
CONFIG_MEGARAID_MAILBOX=m
CONFIG_MEGARAID_LEGACY=m
CONFIG_MEGARAID_SAS=m
-CONFIG_SCSI_MPT2SAS=m
-CONFIG_SCSI_MPT2SAS_MAX_SGE=128
-# CONFIG_SCSI_MPT2SAS_LOGGING is not set
CONFIG_SCSI_MPT3SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
CONFIG_SCSI_MPT3SAS_MAX_SGE=128
-CONFIG_SCSI_MPT3SAS_LOGGING=y
+CONFIG_SCSI_MPT2SAS=m
CONFIG_SCSI_UFSHCD=m
CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
@@ -2000,6 +2108,8 @@ CONFIG_LIBFC=m
CONFIG_LIBFCOE=m
CONFIG_FCOE=m
CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_SNIC=m
+# CONFIG_SCSI_SNIC_DEBUG_FS is not set
CONFIG_SCSI_DMX3191D=m
CONFIG_SCSI_DTC3280=m
CONFIG_SCSI_EATA=m
@@ -2060,7 +2170,7 @@ CONFIG_PCMCIA_FDOMAIN=m
CONFIG_PCMCIA_NINJA_SCSI=m
CONFIG_PCMCIA_QLOGIC=m
CONFIG_PCMCIA_SYM53C500=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_HP_SW=m
CONFIG_SCSI_DH_EMC=m
@@ -2081,6 +2191,8 @@ CONFIG_SATA_PMP=y
#
CONFIG_SATA_AHCI=m
CONFIG_SATA_AHCI_PLATFORM=m
+# CONFIG_AHCI_CEVA is not set
+# CONFIG_AHCI_QORIQ is not set
CONFIG_SATA_INIC162X=m
CONFIG_SATA_ACARD_AHCI=m
CONFIG_SATA_SIL24=m
@@ -2196,6 +2308,7 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
CONFIG_DM_CACHE_MQ=m
+CONFIG_DM_CACHE_SMQ=m
CONFIG_DM_CACHE_CLEANER=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
@@ -2256,6 +2369,7 @@ CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_NETPOLL=y
@@ -2264,9 +2378,11 @@ CONFIG_RIONET=m
CONFIG_RIONET_TX_SIZE=128
CONFIG_RIONET_RX_SIZE=128
CONFIG_TUN=m
+# CONFIG_TUN_VNET_CROSS_LE is not set
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
CONFIG_NLMON=m
+CONFIG_NET_VRF=m
CONFIG_SUNGEM_PHY=m
# CONFIG_ARCNET is not set
CONFIG_ATM_DRIVERS=y
@@ -2312,6 +2428,7 @@ CONFIG_VHOST_NET=m
CONFIG_VHOST_SCSI=m
CONFIG_VHOST_RING=m
CONFIG_VHOST=m
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
#
# Distributed Switch Architecture drivers
@@ -2356,6 +2473,8 @@ CONFIG_ATL1=m
CONFIG_ATL1E=m
CONFIG_ATL1C=m
CONFIG_ALX=m
+CONFIG_NET_VENDOR_AURORA=y
+CONFIG_AURORA_NB8800=m
CONFIG_NET_CADENCE=y
CONFIG_MACB=m
CONFIG_NET_VENDOR_BROADCOM=y
@@ -2369,9 +2488,13 @@ CONFIG_CNIC=m
CONFIG_TIGON3=m
CONFIG_BNX2X=m
CONFIG_BNX2X_SRIOV=y
+CONFIG_BNX2X_VXLAN=y
CONFIG_SYSTEMPORT=m
+CONFIG_BNXT=m
+CONFIG_BNXT_SRIOV=y
CONFIG_NET_VENDOR_BROCADE=y
CONFIG_BNA=m
+# CONFIG_NET_VENDOR_CAVIUM is not set
CONFIG_NET_VENDOR_CHELSIO=y
CONFIG_CHELSIO_T1=m
CONFIG_CHELSIO_T1_1G=y
@@ -2404,7 +2527,9 @@ CONFIG_SUNDANCE=m
# CONFIG_SUNDANCE_MMIO is not set
CONFIG_NET_VENDOR_EMULEX=y
CONFIG_BE2NET=m
+CONFIG_BE2NET_HWMON=y
CONFIG_BE2NET_VXLAN=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
CONFIG_NET_VENDOR_EXAR=y
CONFIG_S2IO=m
CONFIG_VXGE=m
@@ -2419,13 +2544,11 @@ CONFIG_E1000=m
CONFIG_E1000E=m
CONFIG_IGB=m
CONFIG_IGB_HWMON=y
-CONFIG_IGB_DCA=y
CONFIG_IGBVF=m
CONFIG_IXGB=m
CONFIG_IXGBE=m
CONFIG_IXGBE_VXLAN=y
CONFIG_IXGBE_HWMON=y
-CONFIG_IXGBE_DCA=y
CONFIG_IXGBEVF=m
CONFIG_I40E=m
CONFIG_I40E_VXLAN=y
@@ -2433,7 +2556,6 @@ CONFIG_I40EVF=m
CONFIG_FM10K=m
# CONFIG_FM10K_VXLAN is not set
CONFIG_NET_VENDOR_I825XX=y
-CONFIG_IP1000=m
CONFIG_JME=m
CONFIG_NET_VENDOR_MARVELL=y
CONFIG_MVMDIO=m
@@ -2448,6 +2570,11 @@ CONFIG_MLX4_EN_VXLAN=y
CONFIG_MLX4_CORE=m
CONFIG_MLX4_DEBUG=y
CONFIG_MLX5_CORE=m
+CONFIG_MLX5_CORE_EN=y
+CONFIG_MLXSW_CORE=m
+CONFIG_MLXSW_PCI=m
+CONFIG_MLXSW_SWITCHX2=m
+CONFIG_MLXSW_SPECTRUM=m
CONFIG_NET_VENDOR_MICREL=y
CONFIG_KS8842=m
CONFIG_KS8851=m
@@ -2456,9 +2583,9 @@ CONFIG_KSZ884X_PCI=m
CONFIG_NET_VENDOR_MICROCHIP=y
CONFIG_ENC28J60=m
# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ENCX24J600=m
CONFIG_NET_VENDOR_MYRI=y
CONFIG_MYRI10GE=m
-CONFIG_MYRI10GE_DCA=y
CONFIG_FEALNX=m
CONFIG_NET_VENDOR_NATSEMI=y
CONFIG_NATSEMI=m
@@ -2486,6 +2613,8 @@ CONFIG_QLCNIC_VXLAN=y
CONFIG_QLCNIC_HWMON=y
CONFIG_QLGE=m
CONFIG_NETXEN_NIC=m
+CONFIG_QED=m
+CONFIG_QEDE=m
CONFIG_NET_VENDOR_QUALCOMM=y
CONFIG_QCA7000=m
CONFIG_NET_VENDOR_REALTEK=y
@@ -2497,6 +2626,7 @@ CONFIG_8139TOO_TUNE_TWISTER=y
CONFIG_8139TOO_8129=y
# CONFIG_8139_OLD_RX_RESET is not set
CONFIG_R8169=m
+# CONFIG_NET_VENDOR_RENESAS is not set
CONFIG_NET_VENDOR_RDC=y
CONFIG_R6040=m
CONFIG_NET_VENDOR_ROCKER=y
@@ -2513,6 +2643,7 @@ CONFIG_SFC=m
CONFIG_SFC_MTD=y
CONFIG_SFC_MCDI_MON=y
CONFIG_SFC_SRIOV=y
+CONFIG_SFC_MCDI_LOGGING=y
CONFIG_NET_VENDOR_SMSC=y
CONFIG_SMC9194=m
CONFIG_PCMCIA_SMC91C92=m
@@ -2529,6 +2660,8 @@ CONFIG_HAPPYMEAL=m
CONFIG_SUNGEM=m
CONFIG_CASSINI=m
CONFIG_NIU=m
+CONFIG_NET_VENDOR_SYNOPSYS=y
+CONFIG_SYNOPSYS_DWC_ETH_QOS=m
CONFIG_NET_VENDOR_TEHUTI=y
CONFIG_TEHUTI=m
CONFIG_NET_VENDOR_TI=y
@@ -2554,6 +2687,7 @@ CONFIG_PHYLIB=m
#
# MII PHY device drivers
#
+CONFIG_AQUANTIA_PHY=m
CONFIG_AT803X_PHY=m
CONFIG_AMD_PHY=m
CONFIG_MARVELL_PHY=m
@@ -2562,7 +2696,9 @@ CONFIG_QSEMI_PHY=m
CONFIG_LXT_PHY=m
CONFIG_CICADA_PHY=m
CONFIG_VITESSE_PHY=m
+CONFIG_TERANETICS_PHY=m
CONFIG_SMSC_PHY=m
+CONFIG_BCM_NET_PHYLIB=m
CONFIG_BROADCOM_PHY=m
CONFIG_BCM7XXX_PHY=m
CONFIG_BCM87XX_PHY=m
@@ -2572,6 +2708,9 @@ CONFIG_NATIONAL_PHY=m
CONFIG_STE10XP=m
CONFIG_LSI_ET1011C_PHY=m
CONFIG_MICREL_PHY=m
+CONFIG_DP83848_PHY=m
+CONFIG_DP83867_PHY=m
+CONFIG_MICROCHIP_PHY=m
CONFIG_FIXED_PHY=m
CONFIG_MDIO_BITBANG=m
# CONFIG_MDIO_GPIO is not set
@@ -2608,6 +2747,7 @@ CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_AX88179_178A=m
@@ -2643,6 +2783,7 @@ CONFIG_USB_CDC_PHONET=m
CONFIG_USB_IPHETH=m
CONFIG_USB_SIERRA_NET=m
CONFIG_USB_VL600=m
+CONFIG_USB_NET_CH9200=m
CONFIG_WLAN=y
CONFIG_PCMCIA_RAYCS=m
CONFIG_LIBERTAS_THINFIRM=m
@@ -2658,10 +2799,10 @@ CONFIG_PCMCIA_WL3501=m
CONFIG_PRISM54=m
CONFIG_USB_ZD1201=m
CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_ADM8211=m
CONFIG_RTL8180=m
CONFIG_RTL8187=m
CONFIG_RTL8187_LEDS=y
-CONFIG_ADM8211=m
# CONFIG_MAC80211_HWSIM is not set
CONFIG_MWL8K=m
CONFIG_ATH_COMMON=m
@@ -2715,7 +2856,6 @@ CONFIG_B43_BUSES_BCMA_AND_SSB=y
# CONFIG_B43_BUSES_SSB is not set
CONFIG_B43_PCI_AUTOSELECT=y
CONFIG_B43_PCICORE_AUTOSELECT=y
-CONFIG_B43_PCMCIA=y
CONFIG_B43_SDIO=y
CONFIG_B43_BCMA_PIO=y
CONFIG_B43_PIO=y
@@ -2830,6 +2970,8 @@ CONFIG_RT2X00_LIB_CRYPTO=y
CONFIG_RT2X00_LIB_LEDS=y
# CONFIG_RT2X00_LIB_DEBUGFS is not set
# CONFIG_RT2X00_DEBUG is not set
+CONFIG_WL_MEDIATEK=y
+CONFIG_MT7601U=m
CONFIG_RTL_CARDS=m
CONFIG_RTL8192CE=m
CONFIG_RTL8192SE=m
@@ -2847,6 +2989,8 @@ CONFIG_RTLWIFI_USB=m
CONFIG_RTL8192C_COMMON=m
CONFIG_RTL8723_COMMON=m
CONFIG_RTLBTCOEXIST=m
+CONFIG_RTL8XXXU=m
+CONFIG_RTL8XXXU_UNTESTED=y
CONFIG_WL_TI=y
CONFIG_WL1251=m
# CONFIG_WL1251_SPI is not set
@@ -2881,9 +3025,12 @@ CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
CONFIG_IEEE802154_DRIVERS=m
CONFIG_IEEE802154_FAKELB=m
CONFIG_IEEE802154_AT86RF230=m
+# CONFIG_IEEE802154_AT86RF230_DEBUGFS is not set
# CONFIG_IEEE802154_MRF24J40 is not set
# CONFIG_IEEE802154_CC2520 is not set
+CONFIG_IEEE802154_ATUSB=m
CONFIG_VMXNET3=m
+CONFIG_FUJITSU_ES=m
CONFIG_HYPERV_NET=m
CONFIG_ISDN=y
CONFIG_ISDN_I4L=m
@@ -3031,11 +3178,13 @@ CONFIG_MISDN_NETJET=m
CONFIG_MISDN_IPAC=m
CONFIG_MISDN_ISAR=m
CONFIG_ISDN_HDLC=m
+# CONFIG_NVM is not set
#
# Input device support
#
CONFIG_INPUT=y
+CONFIG_INPUT_LEDS=m
CONFIG_INPUT_FF_MEMLESS=m
CONFIG_INPUT_POLLDEV=m
CONFIG_INPUT_SPARSEKMAP=m
@@ -3150,7 +3299,7 @@ CONFIG_TABLET_USB_HANWANG=m
CONFIG_TABLET_USB_KBTAB=m
CONFIG_TABLET_SERIAL_WACOM4=m
CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_OF_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
# CONFIG_TOUCHSCREEN_ADS7846 is not set
# CONFIG_TOUCHSCREEN_AD7877 is not set
CONFIG_TOUCHSCREEN_AD7879=m
@@ -3172,6 +3321,7 @@ CONFIG_TOUCHSCREEN_DYNAPRO=m
CONFIG_TOUCHSCREEN_HAMPSHIRE=m
CONFIG_TOUCHSCREEN_EETI=m
CONFIG_TOUCHSCREEN_EGALAX=m
+CONFIG_TOUCHSCREEN_FT6236=m
CONFIG_TOUCHSCREEN_FUJITSU=m
CONFIG_TOUCHSCREEN_GOODIX=m
CONFIG_TOUCHSCREEN_ILI210X=m
@@ -3184,6 +3334,7 @@ CONFIG_TOUCHSCREEN_MAX11801=m
CONFIG_TOUCHSCREEN_MCS5000=m
CONFIG_TOUCHSCREEN_MMS114=m
CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_IMX6UL_TSC=m
CONFIG_TOUCHSCREEN_INEXIO=m
CONFIG_TOUCHSCREEN_MK712=m
CONFIG_TOUCHSCREEN_HTCPEN=m
@@ -3194,6 +3345,7 @@ CONFIG_TOUCHSCREEN_TOUCHWIN=m
CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
CONFIG_TOUCHSCREEN_UCB1400=m
CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_WDT87XX_I2C=m
CONFIG_TOUCHSCREEN_WM97XX=m
CONFIG_TOUCHSCREEN_WM9705=y
CONFIG_TOUCHSCREEN_WM9712=y
@@ -3220,6 +3372,8 @@ CONFIG_TOUCHSCREEN_USB_NEXIO=y
CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
CONFIG_TOUCHSCREEN_TOUCHIT213=m
CONFIG_TOUCHSCREEN_TSC_SERIO=m
+CONFIG_TOUCHSCREEN_TSC200X_CORE=m
+CONFIG_TOUCHSCREEN_TSC2004=m
# CONFIG_TOUCHSCREEN_TSC2005 is not set
CONFIG_TOUCHSCREEN_TSC2007=m
CONFIG_TOUCHSCREEN_ST1232=m
@@ -3227,6 +3381,7 @@ CONFIG_TOUCHSCREEN_SUR40=m
# CONFIG_TOUCHSCREEN_SX8654 is not set
CONFIG_TOUCHSCREEN_TPS6507X=m
CONFIG_TOUCHSCREEN_ZFORCE=m
+CONFIG_TOUCHSCREEN_ROHM_BU21023=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_AD714X=m
CONFIG_INPUT_AD714X_I2C=m
@@ -3266,6 +3421,7 @@ CONFIG_INPUT_CMA3000=m
CONFIG_INPUT_CMA3000_I2C=m
CONFIG_INPUT_IDEAPAD_SLIDEBAR=m
# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
# CONFIG_INPUT_DRV2667_HAPTICS is not set
#
@@ -3286,6 +3442,7 @@ CONFIG_SERIO_ARC_PS2=m
CONFIG_SERIO_APBPS2=m
CONFIG_SERIO_OLPC_APSP=m
CONFIG_HYPERV_KEYBOARD=m
+# CONFIG_USERIO is not set
CONFIG_GAMEPORT=m
CONFIG_GAMEPORT_NS558=m
CONFIG_GAMEPORT_L4=m
@@ -3337,20 +3494,27 @@ CONFIG_SERIAL_8250_CS=m
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_FSL is not set
CONFIG_SERIAL_8250_DW=m
+CONFIG_SERIAL_8250_RT288X=y
# CONFIG_SERIAL_8250_FINTEK is not set
+CONFIG_SERIAL_8250_MID=y
#
# Non-8250 serial port support
#
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_JSM=m
CONFIG_SERIAL_OF_PLATFORM=m
CONFIG_SERIAL_SCCNXP=m
+CONFIG_SERIAL_SC16IS7XX_CORE=m
CONFIG_SERIAL_SC16IS7XX=m
+CONFIG_SERIAL_SC16IS7XX_I2C=y
+# CONFIG_SERIAL_SC16IS7XX_SPI is not set
# CONFIG_SERIAL_TIMBERDALE is not set
CONFIG_SERIAL_ALTERA_JTAGUART=m
CONFIG_SERIAL_ALTERA_UART=m
@@ -3440,6 +3604,7 @@ CONFIG_I2C_MUX=m
CONFIG_I2C_MUX_PCA9541=m
CONFIG_I2C_MUX_PCA954x=m
# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_SMBUS=m
CONFIG_I2C_ALGOBIT=m
@@ -3483,6 +3648,7 @@ CONFIG_I2C_DESIGNWARE_CORE=m
CONFIG_I2C_DESIGNWARE_PLATFORM=m
CONFIG_I2C_DESIGNWARE_PCI=m
CONFIG_I2C_EG20T=m
+# CONFIG_I2C_EMEV2 is not set
# CONFIG_I2C_GPIO is not set
CONFIG_I2C_OCORES=m
CONFIG_I2C_PCA_PLATFORM=m
@@ -3537,6 +3703,7 @@ CONFIG_SPI_SC18IS602=m
CONFIG_SPI_TOPCLIFF_PCH=m
CONFIG_SPI_XCOMM=m
CONFIG_SPI_XILINX=m
+CONFIG_SPI_ZYNQMP_GQSPI=m
CONFIG_SPI_DESIGNWARE=m
CONFIG_SPI_DW_PCI=m
# CONFIG_SPI_DW_MID_DMA is not set
@@ -3588,6 +3755,7 @@ CONFIG_GENERIC_PINCONF=y
CONFIG_PINCTRL_BAYTRAIL=y
CONFIG_PINCTRL_CHERRYVIEW=m
CONFIG_PINCTRL_INTEL=m
+CONFIG_PINCTRL_BROXTON=m
CONFIG_PINCTRL_SUNRISEPOINT=m
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_GPIOLIB=y
@@ -3603,18 +3771,25 @@ CONFIG_GPIO_SYSFS=y
#
# CONFIG_GPIO_74XX_MMIO is not set
# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_AMDPT is not set
# CONFIG_GPIO_DWAPB is not set
-# CONFIG_GPIO_F7188X is not set
# CONFIG_GPIO_GENERIC_PLATFORM is not set
# CONFIG_GPIO_GRGPIO is not set
CONFIG_GPIO_ICH=m
-# CONFIG_GPIO_IT8761E is not set
CONFIG_GPIO_LYNXPOINT=m
-CONFIG_GPIO_SCH=m
-CONFIG_GPIO_SCH311X=m
# CONFIG_GPIO_SYSCON is not set
# CONFIG_GPIO_VX855 is not set
# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# Port-mapped I/O GPIO drivers
+#
+# CONFIG_GPIO_104_IDIO_16 is not set
+# CONFIG_GPIO_F7188X is not set
+# CONFIG_GPIO_IT87 is not set
+CONFIG_GPIO_SCH=m
+CONFIG_GPIO_SCH311X=m
#
# I2C GPIO expanders
@@ -3631,6 +3806,7 @@ CONFIG_GPIO_SCH311X=m
# MFD GPIO expanders
#
# CONFIG_GPIO_ARIZONA is not set
+CONFIG_GPIO_CRYSTAL_COVE=y
CONFIG_GPIO_CS5535=y
# CONFIG_GPIO_LP3943 is not set
# CONFIG_GPIO_UCB1400 is not set
@@ -3650,10 +3826,14 @@ CONFIG_GPIO_AMD8111=m
#
# CONFIG_GPIO_74X164 is not set
# CONFIG_GPIO_MAX7301 is not set
-# CONFIG_GPIO_MCP23S08 is not set
# CONFIG_GPIO_MC33880 is not set
#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
# USB GPIO expanders
#
CONFIG_GPIO_VIPERBOARD=m
@@ -3668,7 +3848,7 @@ CONFIG_TEST_POWER=m
# CONFIG_BATTERY_DS2782 is not set
CONFIG_BATTERY_OLPC=m
# CONFIG_BATTERY_SBS is not set
-# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_BQ27XXX is not set
# CONFIG_BATTERY_MAX17040 is not set
# CONFIG_BATTERY_MAX17042 is not set
# CONFIG_CHARGER_PCF50633 is not set
@@ -3678,9 +3858,14 @@ CONFIG_BATTERY_OLPC=m
# CONFIG_CHARGER_GPIO is not set
# CONFIG_CHARGER_BQ2415X is not set
# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
CONFIG_CHARGER_BQ24735=m
+# CONFIG_CHARGER_BQ25890 is not set
# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_CHARGER_TPS65217 is not set
# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_BATTERY_RT5033 is not set
+# CONFIG_CHARGER_RT9455 is not set
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO=y
# CONFIG_POWER_RESET_GPIO_RESTART is not set
@@ -3723,6 +3908,7 @@ CONFIG_SENSORS_ASB100=m
CONFIG_SENSORS_ATXP1=m
CONFIG_SENSORS_DS620=m
CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_DELL_SMM=m
CONFIG_SENSORS_I5K_AMB=m
CONFIG_SENSORS_F71805F=m
CONFIG_SENSORS_F71882FG=m
@@ -3760,6 +3946,7 @@ CONFIG_SENSORS_MAX6639=m
CONFIG_SENSORS_MAX6642=m
CONFIG_SENSORS_MAX6650=m
CONFIG_SENSORS_MAX6697=m
+CONFIG_SENSORS_MAX31790=m
CONFIG_SENSORS_HTU21=m
CONFIG_SENSORS_MCP3021=m
CONFIG_SENSORS_ADCXX=m
@@ -3793,6 +3980,7 @@ CONFIG_SENSORS_ADM1275=m
CONFIG_SENSORS_LM25066=m
CONFIG_SENSORS_LTC2978=m
CONFIG_SENSORS_MAX16064=m
+CONFIG_SENSORS_MAX20751=m
CONFIG_SENSORS_MAX34440=m
CONFIG_SENSORS_MAX8688=m
CONFIG_SENSORS_TPS40422=m
@@ -3822,6 +4010,7 @@ CONFIG_SENSORS_ADS7871=m
CONFIG_SENSORS_AMC6821=m
CONFIG_SENSORS_INA209=m
CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_TC74=m
CONFIG_SENSORS_THMC50=m
CONFIG_SENSORS_TMP102=m
CONFIG_SENSORS_TMP103=m
@@ -3850,24 +4039,26 @@ CONFIG_SENSORS_ATK0110=m
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
CONFIG_THERMAL_OF=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
+# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
# CONFIG_CPU_THERMAL is not set
# CONFIG_THERMAL_EMULATION is not set
CONFIG_INTEL_POWERCLAMP=m
CONFIG_X86_PKG_TEMP_THERMAL=m
+CONFIG_INTEL_SOC_DTS_IOSF_CORE=m
CONFIG_INTEL_SOC_DTS_THERMAL=m
CONFIG_INT340X_THERMAL=m
CONFIG_ACPI_THERMAL_REL=m
-
-#
-# Texas Instruments thermal drivers
-#
+CONFIG_INTEL_PCH_THERMAL=m
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -3881,6 +4072,7 @@ CONFIG_XILINX_WATCHDOG=m
# CONFIG_CADENCE_WATCHDOG is not set
CONFIG_DW_WATCHDOG=m
# CONFIG_RN5T618_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
CONFIG_RETU_WATCHDOG=m
CONFIG_ACQUIRE_WDT=m
CONFIG_ADVANTECH_WDT=m
@@ -3917,6 +4109,7 @@ CONFIG_W83877F_WDT=m
CONFIG_W83977F_WDT=m
CONFIG_MACHZ_WDT=m
CONFIG_SBC_EPX_C3_WATCHDOG=m
+CONFIG_BCM7038_WDT=m
CONFIG_MEN_A21_WDT=m
#
@@ -3951,6 +4144,7 @@ CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
CONFIG_SSB_PCMCIAHOST=y
CONFIG_SSB_SDIOHOST_POSSIBLE=y
CONFIG_SSB_SDIOHOST=y
+CONFIG_SSB_HOST_SOC=y
# CONFIG_SSB_DEBUG is not set
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_DRIVER_PCICORE=y
@@ -3979,6 +4173,7 @@ CONFIG_MFD_CS5535=m
# CONFIG_MFD_AS3722 is not set
# CONFIG_PMIC_ADP5520 is not set
# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
# CONFIG_MFD_ATMEL_HLCDC is not set
CONFIG_MFD_BCM590XX=m
# CONFIG_MFD_AXP20X is not set
@@ -3989,6 +4184,7 @@ CONFIG_MFD_CROS_EC_SPI=m
# CONFIG_MFD_DA9052_SPI is not set
# CONFIG_MFD_DA9052_I2C is not set
# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
# CONFIG_MFD_DA9063 is not set
# CONFIG_MFD_DA9150 is not set
# CONFIG_MFD_DLN2 is not set
@@ -4001,7 +4197,10 @@ CONFIG_HTC_PASIC3=m
# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
CONFIG_LPC_ICH=m
CONFIG_LPC_SCH=m
-# CONFIG_INTEL_SOC_PMIC is not set
+CONFIG_INTEL_SOC_PMIC=y
+CONFIG_MFD_INTEL_LPSS=m
+CONFIG_MFD_INTEL_LPSS_ACPI=m
+CONFIG_MFD_INTEL_LPSS_PCI=m
# CONFIG_MFD_JANZ_CMODIO is not set
# CONFIG_MFD_KEMPLD is not set
# CONFIG_MFD_88PM800 is not set
@@ -4026,7 +4225,7 @@ CONFIG_PCF50633_GPIO=m
CONFIG_UCB1400_CORE=m
CONFIG_MFD_RDC321X=m
CONFIG_MFD_RTSX_PCI=m
-# CONFIG_MFD_RT5033 is not set
+CONFIG_MFD_RT5033=m
CONFIG_MFD_RTSX_USB=m
# CONFIG_MFD_RC5T583 is not set
CONFIG_MFD_RK808=m
@@ -4071,6 +4270,7 @@ CONFIG_MFD_ARIZONA_I2C=m
CONFIG_MFD_WM5102=y
CONFIG_MFD_WM5110=y
# CONFIG_MFD_WM8997 is not set
+# CONFIG_MFD_WM8998 is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM831X_I2C is not set
# CONFIG_MFD_WM831X_SPI is not set
@@ -4096,6 +4296,7 @@ CONFIG_VIDEO_V4L2=m
# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEO_TUNER=m
CONFIG_V4L2_MEM2MEM_DEV=m
+# CONFIG_V4L2_FLASH_LED_CLASS is not set
CONFIG_VIDEOBUF_GEN=m
CONFIG_VIDEOBUF_DMA_SG=m
CONFIG_VIDEOBUF_VMALLOC=m
@@ -4314,13 +4515,8 @@ CONFIG_MEDIA_PCI_SUPPORT=y
# Media capture support
#
CONFIG_VIDEO_MEYE=m
-
-#
-# Media capture/analog TV support
-#
-CONFIG_VIDEO_IVTV=m
-CONFIG_VIDEO_IVTV_ALSA=m
-CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_SOLO6X10=m
+CONFIG_VIDEO_TW68=m
CONFIG_VIDEO_ZORAN=m
CONFIG_VIDEO_ZORAN_DC30=m
CONFIG_VIDEO_ZORAN_ZR36060=m
@@ -4329,11 +4525,17 @@ CONFIG_VIDEO_ZORAN_DC10=m
CONFIG_VIDEO_ZORAN_LML33=m
CONFIG_VIDEO_ZORAN_LML33R10=m
CONFIG_VIDEO_ZORAN_AVS6EYES=m
+
+#
+# Media capture/analog TV support
+#
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_IVTV_ALSA=m
+CONFIG_VIDEO_FB_IVTV=m
CONFIG_VIDEO_HEXIUM_GEMINI=m
CONFIG_VIDEO_HEXIUM_ORION=m
CONFIG_VIDEO_MXB=m
-CONFIG_VIDEO_SOLO6X10=m
-CONFIG_VIDEO_TW68=m
+CONFIG_VIDEO_DT3155=m
#
# Media capture/analog/hybrid TV support
@@ -4359,6 +4561,7 @@ CONFIG_VIDEO_SAA7134_RC=y
CONFIG_VIDEO_SAA7134_DVB=m
CONFIG_VIDEO_SAA7134_GO7007=m
CONFIG_VIDEO_SAA7164=m
+CONFIG_VIDEO_COBALT=m
#
# Media digital TV PCI Adapters
@@ -4383,6 +4586,7 @@ CONFIG_DVB_HOPPER=m
CONFIG_DVB_NGENE=m
CONFIG_DVB_DDBRIDGE=m
CONFIG_DVB_SMIPCIE=m
+CONFIG_DVB_NETUP_UNIDVB=m
# CONFIG_V4L_PLATFORM_DRIVERS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
@@ -4390,6 +4594,7 @@ CONFIG_VIDEO_SH_VEU=m
CONFIG_V4L_TEST_DRIVERS=y
# CONFIG_VIDEO_VIVID is not set
# CONFIG_VIDEO_VIM2M is not set
+# CONFIG_DVB_PLATFORM_DRIVERS is not set
#
# Supported MMC/SDIO adapters
@@ -4476,6 +4681,8 @@ CONFIG_VIDEO_SAA6588=m
#
# Video decoders
#
+CONFIG_VIDEO_ADV7604=m
+CONFIG_VIDEO_ADV7842=m
CONFIG_VIDEO_BT819=m
CONFIG_VIDEO_BT856=m
CONFIG_VIDEO_BT866=m
@@ -4501,6 +4708,7 @@ CONFIG_VIDEO_SAA7127=m
CONFIG_VIDEO_SAA7185=m
CONFIG_VIDEO_ADV7170=m
CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_ADV7511=m
#
# Camera sensor devices
@@ -4608,6 +4816,7 @@ CONFIG_DVB_TDA826X=m
CONFIG_DVB_TUA6100=m
CONFIG_DVB_CX24116=m
CONFIG_DVB_CX24117=m
+CONFIG_DVB_CX24120=m
CONFIG_DVB_SI21XX=m
CONFIG_DVB_TS2020=m
CONFIG_DVB_DS3000=m
@@ -4636,6 +4845,7 @@ CONFIG_DVB_AF9013=m
CONFIG_DVB_EC100=m
CONFIG_DVB_STV0367=m
CONFIG_DVB_CXD2820R=m
+CONFIG_DVB_CXD2841ER=m
CONFIG_DVB_RTL2830=m
CONFIG_DVB_RTL2832=m
CONFIG_DVB_RTL2832_SDR=m
@@ -4690,6 +4900,7 @@ CONFIG_DVB_TUNER_DIB0090=m
# SEC control devices for DVB-S
#
CONFIG_DVB_DRX39XYJ=m
+CONFIG_DVB_LNBH25=m
CONFIG_DVB_LNBP21=m
CONFIG_DVB_LNBP22=m
CONFIG_DVB_ISL6405=m
@@ -4703,6 +4914,8 @@ CONFIG_DVB_TDA665x=m
CONFIG_DVB_IX2505V=m
CONFIG_DVB_M88RS2000=m
CONFIG_DVB_AF9033=m
+CONFIG_DVB_HORUS3A=m
+CONFIG_DVB_ASCOT2E=m
#
# Tools to develop new frontends
@@ -4727,14 +4940,11 @@ CONFIG_INTEL_GTT=m
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
CONFIG_VGA_SWITCHEROO=y
-
-#
-# Direct Rendering Manager
-#
CONFIG_DRM=m
CONFIG_DRM_MIPI_DSI=y
CONFIG_DRM_KMS_HELPER=m
CONFIG_DRM_KMS_FB_HELPER=y
+CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_TTM=m
@@ -4745,21 +4955,20 @@ CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_I2C_CH7006=m
CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_I2C_NXP_TDA998X=m
-CONFIG_DRM_PTN3460=m
-CONFIG_DRM_PS8622=m
CONFIG_DRM_TDFX=m
CONFIG_DRM_R128=m
CONFIG_DRM_RADEON=m
# CONFIG_DRM_RADEON_USERPTR is not set
# CONFIG_DRM_RADEON_UMS is not set
+CONFIG_DRM_AMDGPU=m
+# CONFIG_DRM_AMDGPU_CIK is not set
+CONFIG_DRM_AMDGPU_USERPTR=y
CONFIG_DRM_NOUVEAU=m
CONFIG_NOUVEAU_DEBUG=5
CONFIG_NOUVEAU_DEBUG_DEFAULT=3
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
-CONFIG_DRM_I810=m
+# CONFIG_DRM_I810 is not set
CONFIG_DRM_I915=m
-CONFIG_DRM_I915_KMS=y
-CONFIG_DRM_I915_FBDEV=y
# CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set
CONFIG_DRM_MGA=m
CONFIG_DRM_SIS=m
@@ -4777,15 +4986,24 @@ CONFIG_DRM_MGAG200=m
CONFIG_DRM_CIRRUS_QEMU=m
CONFIG_DRM_QXL=m
CONFIG_DRM_BOCHS=m
+CONFIG_DRM_VIRTIO_GPU=m
CONFIG_DRM_PANEL=y
#
# Display Panels
#
# CONFIG_DRM_PANEL_SIMPLE is not set
-# CONFIG_DRM_PANEL_LD9040 is not set
-# CONFIG_DRM_PANEL_S6E8AA0 is not set
+# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set
+# CONFIG_DRM_PANEL_LG_LG4573 is not set
+# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set
# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set
+CONFIG_DRM_BRIDGE=y
+
+#
+# Display Interface Bridges
+#
+# CONFIG_DRM_NXP_PTN3460 is not set
+# CONFIG_DRM_PARADE_PS8622 is not set
#
# Frame buffer Devices
@@ -4858,6 +5076,7 @@ CONFIG_FB_VT8623=m
# CONFIG_FB_SM501 is not set
# CONFIG_FB_SMSCUFX is not set
CONFIG_FB_UDL=m
+# CONFIG_FB_IBM_GXT4500 is not set
CONFIG_FB_VIRTUAL=m
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
@@ -4866,6 +5085,7 @@ CONFIG_FB_VIRTUAL=m
CONFIG_FB_HYPERV=m
# CONFIG_FB_SIMPLE is not set
CONFIG_FB_SSD1307=m
+# CONFIG_FB_SM712 is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=m
# CONFIG_LCD_L4F00242T03 is not set
@@ -4886,6 +5106,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_LM3533=m
# CONFIG_BACKLIGHT_PWM is not set
CONFIG_BACKLIGHT_APPLE=m
+# CONFIG_BACKLIGHT_PM8941_WLED is not set
# CONFIG_BACKLIGHT_SAHARA is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
@@ -4905,7 +5126,8 @@ CONFIG_HDMI=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
@@ -4931,17 +5153,18 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_PCM_TIMER=y
CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_HRTIMER=m
CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_MAX_CARDS=32
# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_PROC_FS=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
CONFIG_SND_VMASTER=y
-CONFIG_SND_KCTL_JACK=y
CONFIG_SND_DMA_SGBUF=y
CONFIG_SND_RAWMIDI_SEQ=m
CONFIG_SND_OPL3_LIB_SEQ=m
@@ -5084,20 +5307,16 @@ CONFIG_SND_YMFPCI=m
#
CONFIG_SND_HDA=m
CONFIG_SND_HDA_INTEL=m
-CONFIG_SND_HDA_DSP_LOADER=y
-CONFIG_SND_HDA_PREALLOC_SIZE=4096
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_RECONFIG=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_INPUT_BEEP_MODE=1
-CONFIG_SND_HDA_INPUT_JACK=y
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_CODEC_REALTEK=m
CONFIG_SND_HDA_CODEC_ANALOG=m
CONFIG_SND_HDA_CODEC_SIGMATEL=m
CONFIG_SND_HDA_CODEC_VIA=m
CONFIG_SND_HDA_CODEC_HDMI=m
-CONFIG_SND_HDA_I915=y
CONFIG_SND_HDA_CODEC_CIRRUS=m
CONFIG_SND_HDA_CODEC_CONEXANT=m
CONFIG_SND_HDA_CODEC_CA0110=m
@@ -5108,6 +5327,10 @@ CONFIG_SND_HDA_CODEC_SI3054=m
CONFIG_SND_HDA_GENERIC=m
CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
CONFIG_SND_HDA_CORE=m
+CONFIG_SND_HDA_DSP_LOADER=y
+CONFIG_SND_HDA_I915=y
+CONFIG_SND_HDA_EXT_CORE=m
+CONFIG_SND_HDA_PREALLOC_SIZE=4096
CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=m
@@ -5132,11 +5355,16 @@ CONFIG_SND_ISIGHT=m
CONFIG_SND_SCS1X=m
CONFIG_SND_FIREWORKS=m
CONFIG_SND_BEBOB=m
+CONFIG_SND_FIREWIRE_DIGI00X=m
+CONFIG_SND_FIREWIRE_TASCAM=m
CONFIG_SND_PCMCIA=y
CONFIG_SND_VXPOCKET=m
CONFIG_SND_PDAUDIOCF=m
CONFIG_SND_SOC=m
+CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
+CONFIG_SND_SOC_COMPRESS=y
+CONFIG_SND_SOC_TOPOLOGY=y
# CONFIG_SND_ATMEL_SOC is not set
CONFIG_SND_DESIGNWARE_I2S=m
@@ -5167,16 +5395,25 @@ CONFIG_SND_SOC_INTEL_BROADWELL_MACH=m
CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=m
-# CONFIG_SND_SOC_QCOM is not set
+CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m
+CONFIG_SND_SOC_INTEL_SKYLAKE=m
+CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
+
+#
+# Allwinner SoC Audio support
+#
+# CONFIG_SND_SUN4I_CODEC is not set
# CONFIG_SND_SOC_XTFPGA_I2S is not set
CONFIG_SND_SOC_I2C_AND_SPI=m
#
# CODEC drivers
#
+CONFIG_SND_SOC_AC97_CODEC=m
# CONFIG_SND_SOC_ADAU1701 is not set
# CONFIG_SND_SOC_AK4104 is not set
# CONFIG_SND_SOC_AK4554 is not set
+# CONFIG_SND_SOC_AK4613 is not set
# CONFIG_SND_SOC_AK4642 is not set
# CONFIG_SND_SOC_AK5386 is not set
# CONFIG_SND_SOC_ALC5623 is not set
@@ -5190,14 +5427,17 @@ CONFIG_SND_SOC_I2C_AND_SPI=m
# CONFIG_SND_SOC_CS4271_I2C is not set
# CONFIG_SND_SOC_CS4271_SPI is not set
# CONFIG_SND_SOC_CS42XX8_I2C is not set
-CONFIG_SND_SOC_HDMI_CODEC=m
+# CONFIG_SND_SOC_CS4349 is not set
+CONFIG_SND_SOC_DMIC=m
# CONFIG_SND_SOC_ES8328 is not set
+# CONFIG_SND_SOC_GTM601 is not set
CONFIG_SND_SOC_MAX98090=m
# CONFIG_SND_SOC_PCM1681 is not set
# CONFIG_SND_SOC_PCM1792A is not set
# CONFIG_SND_SOC_PCM512x_I2C is not set
# CONFIG_SND_SOC_PCM512x_SPI is not set
CONFIG_SND_SOC_RL6231=m
+CONFIG_SND_SOC_RL6347A=m
CONFIG_SND_SOC_RT286=m
# CONFIG_SND_SOC_RT5631 is not set
CONFIG_SND_SOC_RT5640=m
@@ -5213,14 +5453,16 @@ CONFIG_SND_SOC_SPDIF=m
# CONFIG_SND_SOC_SSM4567 is not set
# CONFIG_SND_SOC_STA32X is not set
# CONFIG_SND_SOC_STA350 is not set
+# CONFIG_SND_SOC_STI_SAS is not set
# CONFIG_SND_SOC_TAS2552 is not set
# CONFIG_SND_SOC_TAS5086 is not set
+# CONFIG_SND_SOC_TAS571X is not set
# CONFIG_SND_SOC_TFA9879 is not set
# CONFIG_SND_SOC_TLV320AIC23_I2C is not set
# CONFIG_SND_SOC_TLV320AIC23_SPI is not set
# CONFIG_SND_SOC_TLV320AIC31XX is not set
# CONFIG_SND_SOC_TLV320AIC3X is not set
-# CONFIG_SND_SOC_TS3A227E is not set
+CONFIG_SND_SOC_TS3A227E=m
# CONFIG_SND_SOC_WM8510 is not set
# CONFIG_SND_SOC_WM8523 is not set
# CONFIG_SND_SOC_WM8580 is not set
@@ -5265,6 +5507,7 @@ CONFIG_HID_BELKIN=m
CONFIG_HID_BETOP_FF=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
+CONFIG_HID_CORSAIR=m
CONFIG_HID_PRODIKEYS=m
CONFIG_HID_CP2112=m
CONFIG_HID_CYPRESS=m
@@ -5274,6 +5517,8 @@ CONFIG_HID_EMS_FF=m
CONFIG_HID_ELECOM=m
CONFIG_HID_ELO=m
CONFIG_HID_EZKEY=m
+CONFIG_HID_GEMBIRD=m
+CONFIG_HID_GFRM=m
CONFIG_HID_HOLTEK=m
CONFIG_HOLTEK_FF=y
CONFIG_HID_GT683R=m
@@ -5365,7 +5610,7 @@ CONFIG_USB_DEFAULT_PERSIST=y
CONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_FSM is not set
+# CONFIG_USB_ULPI_BUS is not set
CONFIG_USB_MON=m
CONFIG_USB_WUSB=m
CONFIG_USB_WUSB_CBAF=m
@@ -5377,6 +5622,7 @@ CONFIG_USB_WUSB_CBAF=m
CONFIG_USB_C67X00_HCD=m
CONFIG_USB_XHCI_HCD=m
CONFIG_USB_XHCI_PCI=m
+# CONFIG_USB_XHCI_PLATFORM is not set
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
@@ -5385,7 +5631,6 @@ CONFIG_USB_EHCI_PCI=m
CONFIG_USB_OXU210HP_HCD=m
CONFIG_USB_ISP116X_HCD=m
CONFIG_USB_ISP1362_HCD=m
-CONFIG_USB_FUSBH200_HCD=m
# CONFIG_USB_FOTG210_HCD is not set
CONFIG_USB_MAX3421_HCD=m
CONFIG_USB_OHCI_HCD=m
@@ -5454,6 +5699,10 @@ CONFIG_USB_MUSB_DUAL_ROLE=y
#
# Platform Glue Layer
#
+
+#
+# MUSB DMA mode
+#
CONFIG_MUSB_PIO_ONLY=y
# CONFIG_USB_DWC3 is not set
# CONFIG_USB_DWC2 is not set
@@ -5646,7 +5895,6 @@ CONFIG_UWB_WHCI=m
CONFIG_UWB_I1480U=m
CONFIG_MMC=m
# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_CLKGATE is not set
#
# MMC/SD/SDIO Card Drivers
@@ -5666,6 +5914,7 @@ CONFIG_MMC_RICOH_MMC=y
CONFIG_MMC_SDHCI_ACPI=m
CONFIG_MMC_SDHCI_PLTFM=m
CONFIG_MMC_SDHCI_OF_ARASAN=m
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
# CONFIG_MMC_SDHCI_F_SDH30 is not set
CONFIG_MMC_WBSD=m
CONFIG_MMC_TIFM_SD=m
@@ -5678,6 +5927,7 @@ CONFIG_MMC_USDHI6ROL0=m
CONFIG_MMC_REALTEK_PCI=m
CONFIG_MMC_REALTEK_USB=m
CONFIG_MMC_TOSHIBA_PCI=m
+CONFIG_MMC_MTK=m
CONFIG_MEMSTICK=m
# CONFIG_MEMSTICK_DEBUG is not set
@@ -5703,6 +5953,9 @@ CONFIG_LEDS_CLASS_FLASH=m
#
# LED drivers
#
+CONFIG_LEDS_AAT1290=m
+CONFIG_LEDS_BCM6328=m
+CONFIG_LEDS_BCM6358=m
CONFIG_LEDS_LM3530=m
CONFIG_LEDS_LM3533=m
CONFIG_LEDS_LM3642=m
@@ -5710,11 +5963,10 @@ CONFIG_LEDS_PCA9532=m
# CONFIG_LEDS_PCA9532_GPIO is not set
CONFIG_LEDS_GPIO=m
CONFIG_LEDS_LP3944=m
-CONFIG_LEDS_LP55XX_COMMON=m
-CONFIG_LEDS_LP5521=m
-CONFIG_LEDS_LP5523=m
-CONFIG_LEDS_LP5562=m
-CONFIG_LEDS_LP8501=m
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_LP5562 is not set
+# CONFIG_LEDS_LP8501 is not set
CONFIG_LEDS_LP8860=m
CONFIG_LEDS_CLEVO_MAIL=m
CONFIG_LEDS_PCA955X=m
@@ -5727,14 +5979,15 @@ CONFIG_LEDS_LT3593=m
CONFIG_LEDS_DELL_NETBOOKS=m
CONFIG_LEDS_MC13783=m
CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_TLC591XX=m
CONFIG_LEDS_LM355x=m
CONFIG_LEDS_OT200=m
+CONFIG_LEDS_KTD2692=m
#
# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
#
CONFIG_LEDS_BLINKM=m
-# CONFIG_LEDS_PM8941_WLED is not set
#
# LED Triggers
@@ -5763,8 +6016,6 @@ CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
-CONFIG_INFINIBAND_AMSO1100=m
-# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
CONFIG_INFINIBAND_CXGB3=m
# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
CONFIG_INFINIBAND_CXGB4=m
@@ -5782,11 +6033,12 @@ CONFIG_INFINIBAND_SRP=m
CONFIG_INFINIBAND_SRPT=m
CONFIG_INFINIBAND_ISER=m
CONFIG_INFINIBAND_ISERT=m
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
CONFIG_EDAC=y
CONFIG_EDAC_LEGACY_SYSFS=y
# CONFIG_EDAC_DEBUG is not set
CONFIG_EDAC_DECODE_MCE=m
-CONFIG_EDAC_MCE_INJ=m
CONFIG_EDAC_MM_EDAC=m
CONFIG_EDAC_AMD64=m
CONFIG_EDAC_AMD64_ERROR_INJECTION=y
@@ -5809,8 +6061,9 @@ CONFIG_EDAC_I7300=m
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
# CONFIG_RTC_DEBUG is not set
#
@@ -5854,6 +6107,7 @@ CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_RX8025=m
CONFIG_RTC_DRV_EM3027=m
CONFIG_RTC_DRV_RV3029C2=m
+# CONFIG_RTC_DRV_RV8803 is not set
#
# SPI RTC drivers
@@ -5898,13 +6152,13 @@ CONFIG_RTC_DRV_BQ4802=m
CONFIG_RTC_DRV_RP5C01=m
CONFIG_RTC_DRV_V3020=m
CONFIG_RTC_DRV_PCF50633=m
+CONFIG_RTC_DRV_ZYNQMP=m
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_MC13XXX=m
CONFIG_RTC_DRV_SNVS=m
-# CONFIG_RTC_DRV_XGENE is not set
#
# HID Sensor RTC drivers
@@ -5916,25 +6170,23 @@ CONFIG_DMADEVICES=y
#
# DMA Devices
#
-CONFIG_INTEL_IOATDMA=m
-CONFIG_DW_DMAC_CORE=m
-CONFIG_DW_DMAC=m
-CONFIG_DW_DMAC_PCI=m
-# CONFIG_HSU_DMA_PCI is not set
-CONFIG_PCH_DMA=m
-CONFIG_FSL_EDMA=m
CONFIG_DMA_ENGINE=y
-CONFIG_DMA_VIRTUAL_CHANNELS=m
+CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DMA_ACPI=y
CONFIG_DMA_OF=y
+CONFIG_FSL_EDMA=m
+CONFIG_INTEL_IDMA64=m
+CONFIG_PCH_DMA=m
+CONFIG_DW_DMAC_CORE=m
+CONFIG_DW_DMAC=m
+CONFIG_DW_DMAC_PCI=m
+CONFIG_HSU_DMA=y
#
# DMA Clients
#
CONFIG_ASYNC_TX_DMA=y
# CONFIG_DMATEST is not set
-CONFIG_DMA_ENGINE_RAID=y
-CONFIG_DCA=m
CONFIG_AUXDISPLAY=y
CONFIG_KS0108=m
CONFIG_KS0108_PORT=0x378
@@ -5949,6 +6201,7 @@ CONFIG_UIO_AEC=m
CONFIG_UIO_SERCOS3=m
CONFIG_UIO_PCI_GENERIC=m
CONFIG_UIO_NETX=m
+CONFIG_UIO_PRUSS=m
# CONFIG_UIO_MF624 is not set
CONFIG_VFIO_IOMMU_TYPE1=m
CONFIG_VFIO_VIRQFD=m
@@ -5957,6 +6210,7 @@ CONFIG_VFIO_PCI=m
CONFIG_VFIO_PCI_VGA=y
CONFIG_VFIO_PCI_MMAP=y
CONFIG_VFIO_PCI_INTX=y
+CONFIG_IRQ_BYPASS_MANAGER=m
CONFIG_VIRT_DRIVERS=y
CONFIG_VIRTIO=m
@@ -6017,7 +6271,6 @@ CONFIG_COMEDI_DT2815=m
CONFIG_COMEDI_DT2817=m
CONFIG_COMEDI_DT282X=m
CONFIG_COMEDI_DMM32AT=m
-CONFIG_COMEDI_UNIOXX5=m
CONFIG_COMEDI_FL512=m
CONFIG_COMEDI_AIO_AIO12_8=m
CONFIG_COMEDI_AIO_IIRO_16=m
@@ -6108,6 +6361,7 @@ CONFIG_COMEDI_USBDUXSIGMA=m
CONFIG_COMEDI_VMK80XX=m
CONFIG_COMEDI_8254=m
CONFIG_COMEDI_8255=m
+CONFIG_COMEDI_8255_SA=m
CONFIG_COMEDI_KCOMEDILIB=m
CONFIG_COMEDI_AMPLC_DIO200=m
CONFIG_COMEDI_AMPLC_PC236=m
@@ -6225,12 +6479,8 @@ CONFIG_SENSORS_HMC5843_SPI=m
#
# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set
# CONFIG_IIO_SIMPLE_DUMMY is not set
-# CONFIG_FB_SM7XX is not set
# CONFIG_FB_SM750 is not set
CONFIG_FB_XGI=m
-CONFIG_FT1000=m
-CONFIG_FT1000_USB=m
-CONFIG_FT1000_PCMCIA=m
#
# Speakup console speech
@@ -6255,9 +6505,6 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m
CONFIG_STAGING_MEDIA=y
CONFIG_I2C_BCM2048=m
CONFIG_DVB_CXD2099=m
-CONFIG_VIDEO_DT3155=m
-CONFIG_DT3155_CCIR=y
-CONFIG_DT3155_STREAMING=y
CONFIG_DVB_MN88472=m
CONFIG_DVB_MN88473=m
CONFIG_LIRC_STAGING=y
@@ -6269,11 +6516,12 @@ CONFIG_LIRC_SERIAL=m
CONFIG_LIRC_SERIAL_TRANSMITTER=y
CONFIG_LIRC_SIR=m
CONFIG_LIRC_ZILOG=m
+# CONFIG_STAGING_RDMA is not set
#
# Android
#
-CONFIG_USB_WPAN_HCD=m
+# CONFIG_STAGING_BOARD is not set
CONFIG_WIMAX_GDM72XX=m
CONFIG_WIMAX_GDM72XX_QOS=y
CONFIG_WIMAX_GDM72XX_K_MODE=y
@@ -6299,15 +6547,8 @@ CONFIG_DGAP=m
CONFIG_GS_FPGABOOT=m
CONFIG_COMMON_CLK_XLNX_CLKWZRD=m
# CONFIG_FB_TFT is not set
-CONFIG_I2O=m
-CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
-CONFIG_I2O_EXT_ADAPTEC=y
-CONFIG_I2O_CONFIG=m
-CONFIG_I2O_CONFIG_OLD_IOCTL=y
-CONFIG_I2O_BUS=m
-CONFIG_I2O_BLOCK=m
-CONFIG_I2O_SCSI=m
-CONFIG_I2O_PROC=m
+# CONFIG_WILC1000_DRIVER is not set
+# CONFIG_MOST is not set
CONFIG_X86_PLATFORM_DEVICES=y
CONFIG_ACER_WMI=m
CONFIG_ACERHDF=m
@@ -6317,6 +6558,7 @@ CONFIG_DELL_LAPTOP=m
CONFIG_DELL_WMI=m
CONFIG_DELL_WMI_AIO=m
CONFIG_DELL_SMO8800=m
+CONFIG_DELL_RBTN=m
CONFIG_FUJITSU_LAPTOP=m
# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
CONFIG_FUJITSU_TABLET=m
@@ -6350,6 +6592,7 @@ CONFIG_TOPSTAR_LAPTOP=m
CONFIG_ACPI_TOSHIBA=m
CONFIG_TOSHIBA_BT_RFKILL=m
CONFIG_TOSHIBA_HAPS=m
+CONFIG_TOSHIBA_WMI=m
CONFIG_ACPI_CMPC=m
CONFIG_INTEL_IPS=m
CONFIG_IBM_RTL=m
@@ -6363,11 +6606,14 @@ CONFIG_APPLE_GMUX=m
CONFIG_INTEL_RST=m
CONFIG_INTEL_SMARTCONNECT=y
CONFIG_PVPANIC=m
+CONFIG_INTEL_PMC_IPC=m
+CONFIG_SURFACE_PRO3_BUTTON=m
CONFIG_CHROME_PLATFORMS=y
CONFIG_CHROMEOS_LAPTOP=m
CONFIG_CHROMEOS_PSTORE=m
CONFIG_CROS_EC_CHARDEV=m
CONFIG_CROS_EC_LPC=m
+CONFIG_CROS_EC_PROTO=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y
@@ -6377,7 +6623,9 @@ CONFIG_COMMON_CLK=y
#
CONFIG_COMMON_CLK_RK808=m
# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
# CONFIG_COMMON_CLK_PWM is not set
# CONFIG_COMMON_CLK_PXA is not set
# CONFIG_COMMON_CLK_CDCE706 is not set
@@ -6409,6 +6657,7 @@ CONFIG_IOMMU_IOVA=y
CONFIG_OF_IOMMU=y
CONFIG_DMAR_TABLE=y
CONFIG_INTEL_IOMMU=y
+CONFIG_INTEL_IOMMU_SVM=y
# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
CONFIG_INTEL_IOMMU_FLOPPY_WA=y
@@ -6425,6 +6674,7 @@ CONFIG_STE_MODEM_RPROC=m
#
# SOC (System On Chip) specific Drivers
#
+# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
CONFIG_PM_DEVFREQ=y
@@ -6454,7 +6704,7 @@ CONFIG_EXTCON_SM5502=m
CONFIG_MEMORY=y
CONFIG_IIO=m
CONFIG_IIO_BUFFER=y
-CONFIG_IIO_BUFFER_CB=y
+CONFIG_IIO_BUFFER_CB=m
CONFIG_IIO_KFIFO_BUF=m
CONFIG_IIO_TRIGGERED_BUFFER=m
CONFIG_IIO_TRIGGER=y
@@ -6470,10 +6720,13 @@ CONFIG_IIO_ST_ACCEL_3AXIS=m
CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m
CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m
# CONFIG_KXSD9 is not set
-# CONFIG_MMA8452 is not set
CONFIG_KXCJK1013=m
+# CONFIG_MMA8452 is not set
# CONFIG_MMA9551 is not set
# CONFIG_MMA9553 is not set
+# CONFIG_MXC4005 is not set
+# CONFIG_STK8312 is not set
+# CONFIG_STK8BA50 is not set
#
# Analog to digital converters
@@ -6487,6 +6740,7 @@ CONFIG_KXCJK1013=m
# CONFIG_AD7887 is not set
# CONFIG_AD7923 is not set
# CONFIG_AD799X is not set
+# CONFIG_HI8435 is not set
# CONFIG_MAX1027 is not set
# CONFIG_MAX1363 is not set
# CONFIG_MCP320X is not set
@@ -6506,6 +6760,11 @@ CONFIG_KXCJK1013=m
# CONFIG_AD8366 is not set
#
+# Chemical Sensors
+#
+# CONFIG_VZ89X is not set
+
+#
# Hid Sensor IIO Common
#
CONFIG_HID_SENSOR_IIO_COMMON=m
@@ -6535,6 +6794,7 @@ CONFIG_IIO_ST_SENSORS_CORE=m
# CONFIG_AD5764 is not set
# CONFIG_AD5791 is not set
# CONFIG_AD7303 is not set
+# CONFIG_M62332 is not set
# CONFIG_MAX517 is not set
# CONFIG_MAX5821 is not set
# CONFIG_MCP4725 is not set
@@ -6573,6 +6833,8 @@ CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
# Humidity sensors
#
# CONFIG_DHT11 is not set
+# CONFIG_HDC100X is not set
+# CONFIG_HTU21 is not set
# CONFIG_SI7005 is not set
# CONFIG_SI7020 is not set
@@ -6587,9 +6849,12 @@ CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
#
# Light sensors
#
+CONFIG_ACPI_ALS=m
# CONFIG_ADJD_S311 is not set
# CONFIG_AL3320A is not set
# CONFIG_APDS9300 is not set
+# CONFIG_APDS9960 is not set
+CONFIG_BH1750=m
# CONFIG_CM32181 is not set
# CONFIG_CM3232 is not set
# CONFIG_CM3323 is not set
@@ -6599,12 +6864,17 @@ CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
CONFIG_HID_SENSOR_ALS=m
# CONFIG_HID_SENSOR_PROX is not set
# CONFIG_JSA1212 is not set
+CONFIG_RPR0521=m
# CONFIG_SENSORS_LM3533 is not set
# CONFIG_LTR501 is not set
+CONFIG_OPT3001=m
+CONFIG_PA12203001=m
+CONFIG_STK3310=m
# CONFIG_TCS3414 is not set
# CONFIG_TCS3472 is not set
# CONFIG_SENSORS_TSL2563 is not set
# CONFIG_TSL4531 is not set
+# CONFIG_US5182D is not set
# CONFIG_VCNL4000 is not set
#
@@ -6612,8 +6882,10 @@ CONFIG_HID_SENSOR_ALS=m
#
# CONFIG_AK8975 is not set
# CONFIG_AK09911 is not set
+# CONFIG_BMC150_MAGN is not set
# CONFIG_MAG3110 is not set
CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+# CONFIG_MMC35240 is not set
CONFIG_IIO_ST_MAGN_3AXIS=m
CONFIG_IIO_ST_MAGN_I2C_3AXIS=m
CONFIG_IIO_ST_MAGN_SPI_3AXIS=m
@@ -6631,6 +6903,11 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
# CONFIG_IIO_SYSFS_TRIGGER is not set
#
+# Digital potentiometers
+#
+# CONFIG_MCP4531 is not set
+
+#
# Pressure sensors
#
# CONFIG_BMP280 is not set
@@ -6638,6 +6915,7 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
# CONFIG_MPL115 is not set
# CONFIG_MPL3115 is not set
# CONFIG_MS5611 is not set
+# CONFIG_MS5637 is not set
# CONFIG_IIO_ST_PRESS is not set
# CONFIG_T5403 is not set
@@ -6649,6 +6927,7 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
#
# Proximity sensors
#
+# CONFIG_LIDAR_LITE_V2 is not set
# CONFIG_SX9500 is not set
#
@@ -6656,10 +6935,13 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
#
# CONFIG_MLX90614 is not set
# CONFIG_TMP006 is not set
+# CONFIG_TSYS01 is not set
+# CONFIG_TSYS02D is not set
# CONFIG_NTB is not set
# CONFIG_VME_BUS is not set
CONFIG_PWM=y
CONFIG_PWM_SYSFS=y
+# CONFIG_PWM_CRC is not set
CONFIG_PWM_FSL_FTM=m
# CONFIG_PWM_LP3943 is not set
CONFIG_PWM_LPSS=m
@@ -6681,17 +6963,34 @@ CONFIG_FMC_CHARDEV=m
# PHY Subsystem
#
CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
CONFIG_BCM_KONA_USB2_PHY=m
CONFIG_POWERCAP=y
CONFIG_INTEL_RAPL=m
# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
CONFIG_RAS=y
+CONFIG_AMD_MCE_INJ=m
CONFIG_THUNDERBOLT=m
#
# Android
#
# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_STM_DUMMY is not set
+# CONFIG_STM_SOURCE_CONSOLE is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
#
# Firmware Drivers
@@ -6712,7 +7011,9 @@ CONFIG_ISCSI_IBFT=m
# EFI (Extensible Firmware Interface) Support
#
# CONFIG_EFI_VARS is not set
+CONFIG_EFI_ESRT=y
CONFIG_EFI_RUNTIME_MAP=y
+# CONFIG_EFI_FAKE_MEMMAP is not set
CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_UEFI_CPER=y
@@ -6723,7 +7024,7 @@ CONFIG_DCACHE_WORD_ACCESS=y
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
CONFIG_EXT4_FS=m
-CONFIG_EXT4_USE_FOR_EXT23=y
+CONFIG_EXT4_USE_FOR_EXT2=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_ENCRYPTION is not set
@@ -6769,6 +7070,7 @@ CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_CHECK_FS=y
+CONFIG_F2FS_FS_ENCRYPTION=y
# CONFIG_F2FS_IO_TRACE is not set
# CONFIG_FS_DAX is not set
CONFIG_FS_POSIX_ACL=y
@@ -6830,8 +7132,10 @@ CONFIG_NTFS_RW=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_CHILDREN=y
CONFIG_KERNFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
@@ -6868,6 +7172,7 @@ CONFIG_UBIFS_FS=m
# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
CONFIG_LOGFS=m
CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m
@@ -6946,8 +7251,7 @@ CONFIG_SUNRPC_BACKCHANNEL=y
CONFIG_SUNRPC_SWAP=y
CONFIG_RPCSEC_GSS_KRB5=m
CONFIG_SUNRPC_DEBUG=y
-CONFIG_SUNRPC_XPRT_RDMA_CLIENT=m
-CONFIG_SUNRPC_XPRT_RDMA_SERVER=m
+CONFIG_SUNRPC_XPRT_RDMA=m
CONFIG_CEPH_FS=m
CONFIG_CEPH_FSCACHE=y
CONFIG_CEPH_FS_POSIX_ACL=y
@@ -6962,6 +7266,7 @@ CONFIG_CIFS_ACL=y
# CONFIG_CIFS_DEBUG is not set
CONFIG_CIFS_DFS_UPCALL=y
CONFIG_CIFS_SMB2=y
+CONFIG_CIFS_SMB311=y
CONFIG_CIFS_FSCACHE=y
CONFIG_NCP_FS=m
# CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -7061,6 +7366,7 @@ CONFIG_UNUSED_SYMBOLS=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
@@ -7106,6 +7412,7 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_SCHED_DEBUG=y
+CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
# CONFIG_SCHED_STACK_END_CHECK is not set
# CONFIG_DEBUG_TIMEKEEPING is not set
@@ -7141,8 +7448,8 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_TORTURE_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60
-# CONFIG_RCU_CPU_STALL_INFO is not set
# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
@@ -7183,6 +7490,7 @@ CONFIG_STACK_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_KPROBE_EVENT=y
CONFIG_UPROBE_EVENT=y
+CONFIG_BPF_EVENTS=y
CONFIG_PROBE_EVENTS=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
@@ -7195,6 +7503,7 @@ CONFIG_MMIOTRACE=y
CONFIG_RING_BUFFER_BENCHMARK=m
# CONFIG_RING_BUFFER_STARTUP_TEST is not set
# CONFIG_TRACE_ENUM_MAP_FILE is not set
+# CONFIG_TRACING_EVENTS_GPIO is not set
#
# Runtime Testing
@@ -7211,6 +7520,7 @@ CONFIG_ASYNC_RAID6_TEST=m
# CONFIG_TEST_HEXDUMP is not set
# CONFIG_TEST_STRING_HELPERS is not set
CONFIG_TEST_KSTRTOX=m
+# CONFIG_TEST_PRINTF is not set
# CONFIG_TEST_RHASHTABLE is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_DMA_API_DEBUG is not set
@@ -7220,17 +7530,21 @@ CONFIG_TEST_KSTRTOX=m
# CONFIG_TEST_FIRMWARE is not set
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_STRICT_DEVMEM=y
-CONFIG_X86_VERBOSE_BOOTUP=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_EARLY_PRINTK_DBGP is not set
CONFIG_EARLY_PRINTK_EFI=y
+# CONFIG_X86_PTDUMP_CORE is not set
# CONFIG_X86_PTDUMP is not set
+# CONFIG_EFI_PGT_DUMP is not set
CONFIG_DEBUG_RODATA=y
# CONFIG_DEBUG_RODATA_TEST is not set
+# CONFIG_DEBUG_WX is not set
CONFIG_DEBUG_SET_MODULE_RONX=y
# CONFIG_DEBUG_NX_TEST is not set
CONFIG_DOUBLEFAULT=y
@@ -7250,8 +7564,11 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0
# CONFIG_DEBUG_BOOT_PARAMS is not set
# CONFIG_CPA_DEBUG is not set
# CONFIG_OPTIMIZE_INLINING is not set
+# CONFIG_DEBUG_ENTRY is not set
# CONFIG_DEBUG_NMI_SELFTEST is not set
# CONFIG_X86_DEBUG_STATIC_CPU_HAS is not set
+# CONFIG_X86_DEBUG_FPU is not set
+# CONFIG_PUNIT_ATOM_DEBUG is not set
#
# Security options
@@ -7271,12 +7588,10 @@ CONFIG_SECURITY_PATH=y
# CONFIG_SECURITY_TOMOYO is not set
# CONFIG_SECURITY_APPARMOR is not set
CONFIG_SECURITY_YAMA=y
-CONFIG_SECURITY_YAMA_STACKED=y
CONFIG_INTEGRITY=y
# CONFIG_INTEGRITY_SIGNATURE is not set
# CONFIG_IMA is not set
# CONFIG_EVM is not set
-# CONFIG_DEFAULT_SECURITY_YAMA is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_DEFAULT_SECURITY=""
CONFIG_XOR_BLOCKS=m
@@ -7300,14 +7615,19 @@ CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_AKCIPHER=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=m
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_PCRYPT=m
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
@@ -7322,7 +7642,9 @@ CONFIG_CRYPTO_GLUE_HELPER_X86=m
#
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
#
# Block modes
@@ -7334,6 +7656,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
#
# Hash modes
@@ -7352,6 +7675,7 @@ CONFIG_CRYPTO_CRC32=m
CONFIG_CRYPTO_CRC32_PCLMUL=m
CONFIG_CRYPTO_CRCT10DIF=y
CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_POLY1305=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
@@ -7384,6 +7708,7 @@ CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=m
CONFIG_CRYPTO_SALSA20_586=m
+CONFIG_CRYPTO_CHACHA20=m
CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SERPENT_SSE2_586=m
@@ -7398,6 +7723,7 @@ CONFIG_CRYPTO_TWOFISH_586=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
@@ -7405,11 +7731,17 @@ CONFIG_CRYPTO_LZ4HC=m
# Random Number Generation
#
CONFIG_CRYPTO_ANSI_CPRNG=m
-# CONFIG_CRYPTO_DRBG_MENU is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_HASH=y
+CONFIG_CRYPTO_DRBG_CTR=y
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
CONFIG_CRYPTO_USER_API=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_PADLOCK=m
@@ -7423,12 +7755,19 @@ CONFIG_CRYPTO_DEV_CCP_DD=m
CONFIG_CRYPTO_DEV_CCP_CRYPTO=m
CONFIG_CRYPTO_DEV_QAT=m
CONFIG_CRYPTO_DEV_QAT_DH895xCC=m
+CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=m
CONFIG_ASYMMETRIC_KEY_TYPE=m
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
CONFIG_PUBLIC_KEY_ALGO_RSA=m
CONFIG_X509_CERTIFICATE_PARSER=m
CONFIG_PKCS7_MESSAGE_PARSER=m
CONFIG_PKCS7_TEST_KEY=m
+
+#
+# Certificates for signature checking
+#
+CONFIG_SYSTEM_TRUSTED_KEYRING=y
+CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_IRQFD=y
@@ -7441,6 +7780,7 @@ CONFIG_HAVE_KVM_MSI=y
CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
CONFIG_KVM_VFIO=y
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
+CONFIG_HAVE_KVM_IRQ_BYPASS=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_KVM_INTEL=m
@@ -7464,7 +7804,6 @@ CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IO=y
-CONFIG_PERCPU_RWSEM=y
CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
@@ -7481,6 +7820,8 @@ CONFIG_LIBCRC32C=m
CONFIG_CRC8=m
# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_842_COMPRESS=m
+CONFIG_842_DECOMPRESS=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
@@ -7528,7 +7869,6 @@ CONFIG_GLOB=y
CONFIG_NLATTR=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_LRU_CACHE=m
-CONFIG_AVERAGE=y
CONFIG_CLZ_TAB=y
CONFIG_CORDIC=m
CONFIG_DDR=y
@@ -7549,4 +7889,6 @@ CONFIG_FONT_8x16=y
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
CONFIG_FONT_AUTOSELECT=y
+# CONFIG_SG_SPLIT is not set
CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_MMIO_FLUSH=y
diff --git a/libre/linux-libre-lts/config.x86_64 b/libre/linux-libre-lts/config.x86_64
index 613c9f1fb..8214477d7 100644
--- a/libre/linux-libre-lts/config.x86_64
+++ b/libre/linux-libre-lts/config.x86_64
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/x86 4.1.7-gnu-2-lts Kernel Configuration
+# Linux/x86 4.4.6-gnu-1-lts Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
@@ -37,7 +37,6 @@ CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_HAVE_INTEL_TXT=y
CONFIG_X86_64_SMP=y
-CONFIG_X86_HT=y
CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_FIX_EARLYCON_MEM=y
@@ -83,10 +82,11 @@ CONFIG_HAVE_ARCH_AUDITSYSCALL=y
#
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
# CONFIG_IRQ_DOMAIN_DEBUG is not set
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
@@ -127,13 +127,12 @@ CONFIG_TASK_IO_ACCOUNTING=y
# RCU Subsystem
#
CONFIG_TREE_RCU=y
+CONFIG_RCU_EXPERT=y
CONFIG_SRCU=y
# CONFIG_TASKS_RCU is not set
CONFIG_RCU_STALL_COMMON=y
-# CONFIG_RCU_USER_QS is not set
CONFIG_RCU_FANOUT=64
CONFIG_RCU_FANOUT_LEAF=16
-# CONFIG_RCU_FANOUT_EXACT is not set
# CONFIG_RCU_FAST_NO_HZ is not set
# CONFIG_TREE_RCU_TRACE is not set
CONFIG_RCU_KTHREAD_PRIO=0
@@ -146,12 +145,14 @@ CONFIG_LOG_BUF_SHIFT=19
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
CONFIG_ARCH_SUPPORTS_INT128=y
CONFIG_NUMA_BALANCING=y
CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
@@ -169,6 +170,7 @@ CONFIG_CFS_BANDWIDTH=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_CGROUP_WRITEBACK=y
# CONFIG_CHECKPOINT_RESTORE is not set
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
@@ -212,11 +214,13 @@ CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
-# CONFIG_BPF_SYSCALL is not set
+CONFIG_BPF_SYSCALL=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_ADVISE_SYSCALLS=y
+CONFIG_USERFAULTFD=y
CONFIG_PCI_QUIRKS=y
+CONFIG_MEMBARRIER=y
# CONFIG_EMBEDDED is not set
CONFIG_HAVE_PERF_EVENTS=y
@@ -231,15 +235,17 @@ CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
CONFIG_SLUB_CPU_PARTIAL=y
-CONFIG_SYSTEM_TRUSTED_KEYRING=y
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_PROFILING=y
CONFIG_TRACEPOINTS=y
+CONFIG_KEXEC_CORE=y
CONFIG_OPROFILE=m
# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE_NMI_TIMER=y
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
CONFIG_OPTPROBES=y
CONFIG_KPROBES_ON_FTRACE=y
CONFIG_UPROBES=y
@@ -257,6 +263,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_DMA_API_DEBUG=y
@@ -289,6 +296,7 @@ CONFIG_HAVE_ARCH_SOFT_DIRTY=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_COMPAT_OLD_SIGACTION=y
@@ -311,7 +319,7 @@ CONFIG_MODVERSIONS=y
CONFIG_MODULE_COMPRESS=y
CONFIG_MODULE_COMPRESS_GZIP=y
# CONFIG_MODULE_COMPRESS_XZ is not set
-CONFIG_STOP_MACHINE=y
+CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_BLOCK=y
CONFIG_BLK_DEV_BSG=y
CONFIG_BLK_DEV_BSGLIB=y
@@ -368,8 +376,10 @@ CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_LOCK_SPIN_ON_OWNER=y
-CONFIG_ARCH_USE_QUEUE_RWLOCK=y
-CONFIG_QUEUE_RWLOCK=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
CONFIG_FREEZER=y
#
@@ -394,7 +404,7 @@ CONFIG_PARAVIRT=y
CONFIG_XEN=y
CONFIG_XEN_DOM0=y
CONFIG_XEN_PVHVM=y
-CONFIG_XEN_MAX_DOMAIN_MEMORY=500
+CONFIG_XEN_512GB=y
CONFIG_XEN_SAVE_RESTORE=y
# CONFIG_XEN_DEBUG_FS is not set
CONFIG_XEN_PVH=y
@@ -442,16 +452,15 @@ CONFIG_X86_MCE_AMD=y
CONFIG_X86_MCE_THRESHOLD=y
# CONFIG_X86_MCE_INJECT is not set
CONFIG_X86_THERMAL_VECTOR=y
+# CONFIG_VM86 is not set
CONFIG_X86_16BIT=y
CONFIG_X86_ESPFIX64=y
CONFIG_X86_VSYSCALL_EMULATION=y
CONFIG_I8K=m
-CONFIG_MICROCODE=m
+CONFIG_MICROCODE=y
# CONFIG_MICROCODE_INTEL is not set
# CONFIG_MICROCODE_AMD is not set
CONFIG_MICROCODE_OLD_INTERFACE=y
-# CONFIG_MICROCODE_INTEL_EARLY is not set
-# CONFIG_MICROCODE_AMD_EARLY is not set
CONFIG_X86_MSR=m
CONFIG_X86_CPUID=m
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
@@ -487,7 +496,6 @@ CONFIG_HAVE_BOOTMEM_INFO_NODE=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_MEMORY_HOTREMOVE=y
-CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
CONFIG_MEMORY_BALLOON=y
@@ -518,6 +526,11 @@ CONFIG_ZSMALLOC=y
# CONFIG_PGTABLE_MAPPING is not set
# CONFIG_ZSMALLOC_STAT is not set
CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y
+# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_X86_PMEM_LEGACY_DEVICE=y
CONFIG_X86_PMEM_LEGACY=y
CONFIG_X86_CHECK_BIOS_CORRUPTION=y
CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
@@ -542,7 +555,7 @@ CONFIG_HZ_100=y
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
CONFIG_KEXEC=y
-# CONFIG_CRASH_DUMP is not set
+CONFIG_CRASH_DUMP=y
CONFIG_KEXEC_JUMP=y
CONFIG_PHYSICAL_START=0x1000000
CONFIG_RELOCATABLE=y
@@ -552,7 +565,11 @@ CONFIG_HOTPLUG_CPU=y
# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set
# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
# CONFIG_COMPAT_VDSO is not set
+# CONFIG_LEGACY_VSYSCALL_NATIVE is not set
+CONFIG_LEGACY_VSYSCALL_EMULATE=y
+# CONFIG_LEGACY_VSYSCALL_NONE is not set
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MODIFY_LDT_SYSCALL=y
CONFIG_HAVE_LIVEPATCH=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -587,8 +604,10 @@ CONFIG_ACPI=y
CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
+# CONFIG_ACPI_DEBUGGER is not set
CONFIG_ACPI_SLEEP=y
# CONFIG_ACPI_PROCFS_POWER is not set
+# CONFIG_ACPI_REV_OVERRIDE_POSSIBLE is not set
CONFIG_ACPI_EC_DEBUGFS=m
CONFIG_ACPI_AC=m
CONFIG_ACPI_BATTERY=m
@@ -596,6 +615,8 @@ CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_VIDEO=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_CPU_FREQ_PSS=y
+CONFIG_ACPI_PROCESSOR_IDLE=y
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_IPMI=m
CONFIG_ACPI_HOTPLUG_CPU=y
@@ -615,6 +636,8 @@ CONFIG_ACPI_HED=y
CONFIG_ACPI_CUSTOM_METHOD=m
CONFIG_ACPI_BGRT=y
# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
+CONFIG_ACPI_NFIT=m
+# CONFIG_ACPI_NFIT_DEBUG is not set
CONFIG_HAVE_ACPI_APEI=y
CONFIG_HAVE_ACPI_APEI_NMI=y
CONFIG_ACPI_APEI=y
@@ -698,6 +721,7 @@ CONFIG_PCIEASPM_DEFAULT=y
CONFIG_PCIE_PME=y
CONFIG_PCI_BUS_ADDR_T_64BIT=y
CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
# CONFIG_PCI_DEBUG is not set
CONFIG_PCI_REALLOC_ENABLE_AUTO=y
CONFIG_PCI_STUB=m
@@ -760,7 +784,7 @@ CONFIG_RAPIDIO_CPS_GEN2=m
#
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_BINFMT_SCRIPT=y
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
@@ -776,6 +800,7 @@ CONFIG_X86_DEV_DMA_OPS=y
CONFIG_PMC_ATOM=y
CONFIG_NET=y
CONFIG_COMPAT_NETLINK_MESSAGES=y
+CONFIG_NET_INGRESS=y
#
# Networking options
@@ -808,7 +833,7 @@ CONFIG_NET_IP_TUNNEL=m
CONFIG_NET_IPGRE=m
# CONFIG_NET_IPGRE_BROADCAST is not set
CONFIG_IP_MROUTE=y
-# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
CONFIG_SYN_COOKIES=y
@@ -816,7 +841,6 @@ CONFIG_NET_IPVTI=m
CONFIG_NET_UDP_TUNNEL=m
CONFIG_NET_FOU=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -843,6 +867,7 @@ CONFIG_TCP_CONG_VENO=m
CONFIG_TCP_CONG_YEAH=m
CONFIG_TCP_CONG_ILLINOIS=m
CONFIG_TCP_CONG_DCTCP=m
+CONFIG_TCP_CONG_CDG=m
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -855,6 +880,7 @@ CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=m
+CONFIG_IPV6_ILA=m
CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_INET6_XFRM_MODE_TRANSPORT=m
@@ -869,7 +895,9 @@ CONFIG_IPV6_TUNNEL=m
CONFIG_IPV6_GRE=m
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
-# CONFIG_IPV6_MROUTE is not set
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
CONFIG_NETLABEL=y
CONFIG_NETWORK_SECMARK=y
CONFIG_NET_PTP_CLASSIFY=y
@@ -882,6 +910,7 @@ CONFIG_BRIDGE_NETFILTER=m
#
# Core Netfilter Configuration
#
+CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_ACCT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
@@ -914,7 +943,7 @@ CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CT_NETLINK_TIMEOUT=m
CONFIG_NF_CT_NETLINK_HELPER=m
-CONFIG_NETFILTER_NETLINK_QUEUE_CT=y
+CONFIG_NETFILTER_NETLINK_GLUE_CT=y
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_NF_NAT_PROTO_DCCP=m
@@ -929,6 +958,7 @@ CONFIG_NF_NAT_REDIRECT=m
CONFIG_NETFILTER_SYNPROXY=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -1071,6 +1101,7 @@ CONFIG_IP_VS_WRR=m
CONFIG_IP_VS_LC=m
CONFIG_IP_VS_WLC=m
CONFIG_IP_VS_FO=m
+CONFIG_IP_VS_OVF=m
CONFIG_IP_VS_LBLC=m
CONFIG_IP_VS_LBLCR=m
CONFIG_IP_VS_DH=m
@@ -1099,7 +1130,9 @@ CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_TABLES_IPV4=m
CONFIG_NFT_CHAIN_ROUTE_IPV4=m
CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_DUP_IPV4=m
CONFIG_NF_LOG_ARP=m
CONFIG_NF_LOG_IPV4=m
CONFIG_NF_REJECT_IPV4=m
@@ -1142,6 +1175,8 @@ CONFIG_NF_CONNTRACK_IPV6=m
CONFIG_NF_TABLES_IPV6=m
CONFIG_NFT_CHAIN_ROUTE_IPV6=m
CONFIG_NFT_REJECT_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
+CONFIG_NF_DUP_IPV6=m
CONFIG_NF_REJECT_IPV6=m
CONFIG_NF_LOG_IPV6=m
CONFIG_NF_NAT_IPV6=m
@@ -1265,6 +1300,7 @@ CONFIG_6LOWPAN_NHC_MOBILITY=m
CONFIG_6LOWPAN_NHC_ROUTING=m
CONFIG_6LOWPAN_NHC_UDP=m
CONFIG_IEEE802154=m
+CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y
CONFIG_IEEE802154_SOCKET=m
CONFIG_IEEE802154_6LOWPAN=m
CONFIG_MAC802154=m
@@ -1315,6 +1351,7 @@ CONFIG_NET_CLS_RSVP6=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_CGROUP=m
CONFIG_NET_CLS_BPF=m
+CONFIG_NET_CLS_FLOWER=m
# CONFIG_NET_EMATCH is not set
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=m
@@ -1351,8 +1388,10 @@ CONFIG_NETLINK_DIAG=m
CONFIG_MPLS=y
CONFIG_NET_MPLS_GSO=m
CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
CONFIG_HSR=m
CONFIG_NET_SWITCHDEV=y
+CONFIG_NET_L3_MASTER_DEV=y
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_XPS=y
@@ -1389,7 +1428,54 @@ CONFIG_BAYCOM_SER_FDX=m
CONFIG_BAYCOM_SER_HDX=m
CONFIG_BAYCOM_PAR=m
CONFIG_YAM=m
-# CONFIG_CAN is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_LEDS=y
+CONFIG_CAN_SJA1000=m
+# CONFIG_CAN_SJA1000_ISA is not set
+CONFIG_CAN_SJA1000_PLATFORM=m
+# CONFIG_CAN_EMS_PCMCIA is not set
+CONFIG_CAN_EMS_PCI=m
+# CONFIG_CAN_PEAK_PCMCIA is not set
+CONFIG_CAN_PEAK_PCI=m
+CONFIG_CAN_PEAK_PCIEC=y
+CONFIG_CAN_KVASER_PCI=m
+CONFIG_CAN_PLX_PCI=m
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+CONFIG_CAN_C_CAN_PCI=m
+CONFIG_CAN_M_CAN=m
+CONFIG_CAN_CC770=m
+# CONFIG_CAN_CC770_ISA is not set
+CONFIG_CAN_CC770_PLATFORM=m
+
+#
+# CAN SPI interfaces
+#
+# CONFIG_CAN_MCP251X is not set
+
+#
+# CAN USB interfaces
+#
+CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB2=m
+CONFIG_CAN_GS_USB=m
+CONFIG_CAN_KVASER_USB=m
+CONFIG_CAN_PEAK_USB=m
+CONFIG_CAN_8DEV_USB=m
+CONFIG_CAN_SOFTING=m
+# CONFIG_CAN_SOFTING_CS is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
CONFIG_IRDA=m
#
@@ -1455,6 +1541,7 @@ CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_CMTP=m
CONFIG_BT_HIDP=m
+CONFIG_BT_HS=y
CONFIG_BT_LE=y
CONFIG_BT_6LOWPAN=m
# CONFIG_BT_SELFTEST is not set
@@ -1465,8 +1552,11 @@ CONFIG_BT_DEBUGFS=y
#
CONFIG_BT_INTEL=m
CONFIG_BT_BCM=m
+CONFIG_BT_RTL=m
+CONFIG_BT_QCA=m
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTUSB_BCM=y
+CONFIG_BT_HCIBTUSB_RTL=y
CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_H4=y
@@ -1476,6 +1566,7 @@ CONFIG_BT_HCIUART_LL=y
CONFIG_BT_HCIUART_3WIRE=y
CONFIG_BT_HCIUART_INTEL=y
CONFIG_BT_HCIUART_BCM=y
+CONFIG_BT_HCIUART_QCA=y
CONFIG_BT_HCIBCM203X=m
CONFIG_BT_HCIBPA10X=m
CONFIG_BT_HCIBFUSB=m
@@ -1505,6 +1596,7 @@ CONFIG_CFG80211=m
CONFIG_CFG80211_DEFAULT_PS=y
# CONFIG_CFG80211_DEBUGFS is not set
# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
CONFIG_CFG80211_WEXT=y
CONFIG_CFG80211_WEXT_EXPORT=y
CONFIG_LIB80211=m
@@ -1524,6 +1616,7 @@ CONFIG_MAC80211_LEDS=y
CONFIG_MAC80211_DEBUGFS=y
# CONFIG_MAC80211_MESSAGE_TRACING is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
CONFIG_WIMAX=m
CONFIG_WIMAX_DEBUG_LEVEL=8
CONFIG_RFKILL=m
@@ -1545,6 +1638,7 @@ CONFIG_NFC=m
CONFIG_NFC_DIGITAL=m
CONFIG_NFC_NCI=m
# CONFIG_NFC_NCI_SPI is not set
+# CONFIG_NFC_NCI_UART is not set
CONFIG_NFC_HCI=m
# CONFIG_NFC_SHDLC is not set
@@ -1557,16 +1651,22 @@ CONFIG_NFC_TRF7970A=m
CONFIG_NFC_MEI_PHY=m
CONFIG_NFC_SIM=m
CONFIG_NFC_PORT100=m
+CONFIG_NFC_FDP=m
+CONFIG_NFC_FDP_I2C=m
CONFIG_NFC_PN544=m
CONFIG_NFC_PN544_MEI=m
CONFIG_NFC_MICROREAD=m
CONFIG_NFC_MICROREAD_MEI=m
CONFIG_NFC_MRVL=m
CONFIG_NFC_MRVL_USB=m
+CONFIG_NFC_MRVL_I2C=m
CONFIG_NFC_ST21NFCA=m
-CONFIG_NFC_ST21NFCB=m
-CONFIG_NFC_ST21NFCB_I2C=m
+CONFIG_NFC_ST_NCI=m
+CONFIG_NFC_ST_NCI_I2C=m
+# CONFIG_NFC_ST_NCI_SPI is not set
# CONFIG_NFC_NXP_NCI is not set
+# CONFIG_NFC_S3FWRN5_I2C is not set
+CONFIG_LWTUNNEL=y
CONFIG_HAVE_BPF_JIT=y
#
@@ -1595,7 +1695,7 @@ CONFIG_SYS_HYPERVISOR=y
# CONFIG_GENERIC_CPU_DEVICES is not set
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_REGMAP=y
-CONFIG_REGMAP_I2C=m
+CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -1672,7 +1772,8 @@ CONFIG_MTD_SCB2_FLASH=m
# CONFIG_MTD_NETtel is not set
# CONFIG_MTD_L440GX is not set
CONFIG_MTD_PCI=m
-# CONFIG_MTD_PCMCIA is not set
+CONFIG_MTD_PCMCIA=m
+# CONFIG_MTD_PCMCIA_ANONYMOUS is not set
# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
CONFIG_MTD_PLATRAM=m
@@ -1704,7 +1805,10 @@ CONFIG_MTD_NAND_ECC_SMC=y
CONFIG_MTD_NAND=m
# CONFIG_MTD_NAND_ECC_BCH is not set
CONFIG_MTD_SM_COMMON=m
-# CONFIG_MTD_NAND_DENALI is not set
+CONFIG_MTD_NAND_DENALI=m
+CONFIG_MTD_NAND_DENALI_PCI=m
+CONFIG_MTD_NAND_DENALI_DT=m
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
CONFIG_MTD_NAND_GPIO=m
# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
CONFIG_MTD_NAND_IDS=m
@@ -1731,7 +1835,8 @@ CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_LIMIT=20
# CONFIG_MTD_UBI_FASTMAP is not set
# CONFIG_MTD_UBI_GLUEBI is not set
-# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_MTD_UBI_BLOCK=y
+# CONFIG_OF is not set
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
@@ -1757,7 +1862,6 @@ CONFIG_BLK_DEV_FD=m
CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
CONFIG_ZRAM=m
CONFIG_ZRAM_LZ4_COMPRESS=y
-# CONFIG_ZRAM_DEBUG is not set
CONFIG_BLK_CPQ_CISS_DA=m
# CONFIG_CISS_SCSI_TAPE is not set
CONFIG_BLK_DEV_DAC960=m
@@ -1769,14 +1873,12 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_DRBD=m
# CONFIG_DRBD_FAULT_INJECTION is not set
CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_NVME=m
CONFIG_BLK_DEV_SKD=m
CONFIG_BLK_DEV_OSD=m
CONFIG_BLK_DEV_SX8=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -1787,6 +1889,7 @@ CONFIG_VIRTIO_BLK=m
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_RBD=m
CONFIG_BLK_DEV_RSXX=m
+CONFIG_BLK_DEV_NVME=m
#
# Misc devices
@@ -1858,6 +1961,11 @@ CONFIG_VMWARE_VMCI=m
CONFIG_INTEL_MIC_BUS=m
#
+# SCIF Bus Driver
+#
+CONFIG_SCIF_BUS=m
+
+#
# Intel MIC Host Driver
#
CONFIG_INTEL_MIC_HOST=m
@@ -1866,10 +1974,22 @@ CONFIG_INTEL_MIC_HOST=m
# Intel MIC Card Driver
#
CONFIG_INTEL_MIC_CARD=m
+
+#
+# SCIF Driver
+#
+CONFIG_SCIF=m
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+CONFIG_MIC_COSM=m
CONFIG_GENWQE=m
CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY=0
CONFIG_ECHO=m
# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_KERNEL_API is not set
+# CONFIG_CXL_EEH is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -1951,12 +2071,10 @@ CONFIG_MEGARAID_MM=m
CONFIG_MEGARAID_MAILBOX=m
CONFIG_MEGARAID_LEGACY=m
CONFIG_MEGARAID_SAS=m
-CONFIG_SCSI_MPT2SAS=m
-CONFIG_SCSI_MPT2SAS_MAX_SGE=128
-# CONFIG_SCSI_MPT2SAS_LOGGING is not set
CONFIG_SCSI_MPT3SAS=m
+CONFIG_SCSI_MPT2SAS_MAX_SGE=128
CONFIG_SCSI_MPT3SAS_MAX_SGE=128
-CONFIG_SCSI_MPT3SAS_LOGGING=y
+CONFIG_SCSI_MPT2SAS=m
CONFIG_SCSI_UFSHCD=m
CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
@@ -1970,6 +2088,8 @@ CONFIG_LIBFC=m
CONFIG_LIBFCOE=m
CONFIG_FCOE=m
CONFIG_FCOE_FNIC=m
+CONFIG_SCSI_SNIC=m
+# CONFIG_SCSI_SNIC_DEBUG_FS is not set
CONFIG_SCSI_DMX3191D=m
CONFIG_SCSI_EATA=m
# CONFIG_SCSI_EATA_TAGGED_QUEUE is not set
@@ -2014,7 +2134,7 @@ CONFIG_PCMCIA_AHA152X=m
CONFIG_PCMCIA_FDOMAIN=m
CONFIG_PCMCIA_QLOGIC=m
CONFIG_PCMCIA_SYM53C500=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_HP_SW=m
CONFIG_SCSI_DH_EMC=m
@@ -2142,6 +2262,7 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=m
CONFIG_DM_CACHE_MQ=m
+CONFIG_DM_CACHE_SMQ=m
CONFIG_DM_CACHE_CLEANER=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
@@ -2202,6 +2323,7 @@ CONFIG_MACVLAN=m
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_NETPOLL=y
@@ -2210,9 +2332,11 @@ CONFIG_RIONET=m
CONFIG_RIONET_TX_SIZE=128
CONFIG_RIONET_RX_SIZE=128
CONFIG_TUN=m
+# CONFIG_TUN_VNET_CROSS_LE is not set
CONFIG_VETH=m
CONFIG_VIRTIO_NET=m
CONFIG_NLMON=m
+CONFIG_NET_VRF=m
CONFIG_SUNGEM_PHY=m
# CONFIG_ARCNET is not set
CONFIG_ATM_DRIVERS=y
@@ -2258,6 +2382,7 @@ CONFIG_VHOST_NET=m
CONFIG_VHOST_SCSI=m
CONFIG_VHOST_RING=m
CONFIG_VHOST=m
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
#
# Distributed Switch Architecture drivers
@@ -2296,6 +2421,8 @@ CONFIG_ATL1=m
CONFIG_ATL1E=m
CONFIG_ATL1C=m
CONFIG_ALX=m
+CONFIG_NET_VENDOR_AURORA=y
+CONFIG_AURORA_NB8800=m
CONFIG_NET_CADENCE=y
CONFIG_MACB=m
CONFIG_NET_VENDOR_BROADCOM=y
@@ -2309,8 +2436,12 @@ CONFIG_CNIC=m
CONFIG_TIGON3=m
CONFIG_BNX2X=m
CONFIG_BNX2X_SRIOV=y
+CONFIG_BNX2X_VXLAN=y
+CONFIG_BNXT=m
+CONFIG_BNXT_SRIOV=y
CONFIG_NET_VENDOR_BROCADE=y
CONFIG_BNA=m
+# CONFIG_NET_VENDOR_CAVIUM is not set
CONFIG_NET_VENDOR_CHELSIO=y
CONFIG_CHELSIO_T1=m
CONFIG_CHELSIO_T1_1G=y
@@ -2340,7 +2471,9 @@ CONFIG_SUNDANCE=m
# CONFIG_SUNDANCE_MMIO is not set
CONFIG_NET_VENDOR_EMULEX=y
CONFIG_BE2NET=m
+CONFIG_BE2NET_HWMON=y
CONFIG_BE2NET_VXLAN=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
CONFIG_NET_VENDOR_EXAR=y
CONFIG_S2IO=m
CONFIG_VXGE=m
@@ -2369,7 +2502,6 @@ CONFIG_I40EVF=m
CONFIG_FM10K=m
# CONFIG_FM10K_VXLAN is not set
CONFIG_NET_VENDOR_I825XX=y
-CONFIG_IP1000=m
CONFIG_JME=m
CONFIG_NET_VENDOR_MARVELL=y
CONFIG_MVMDIO=m
@@ -2384,6 +2516,11 @@ CONFIG_MLX4_EN_VXLAN=y
CONFIG_MLX4_CORE=m
CONFIG_MLX4_DEBUG=y
CONFIG_MLX5_CORE=m
+CONFIG_MLX5_CORE_EN=y
+CONFIG_MLXSW_CORE=m
+CONFIG_MLXSW_PCI=m
+CONFIG_MLXSW_SWITCHX2=m
+CONFIG_MLXSW_SPECTRUM=m
CONFIG_NET_VENDOR_MICREL=y
CONFIG_KS8842=m
CONFIG_KS8851=m
@@ -2392,6 +2529,7 @@ CONFIG_KSZ884X_PCI=m
CONFIG_NET_VENDOR_MICROCHIP=y
CONFIG_ENC28J60=m
# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_ENCX24J600=m
CONFIG_NET_VENDOR_MYRI=y
CONFIG_MYRI10GE=m
CONFIG_MYRI10GE_DCA=y
@@ -2418,6 +2556,8 @@ CONFIG_QLCNIC_VXLAN=y
CONFIG_QLCNIC_HWMON=y
CONFIG_QLGE=m
CONFIG_NETXEN_NIC=m
+CONFIG_QED=m
+CONFIG_QEDE=m
CONFIG_NET_VENDOR_QUALCOMM=y
CONFIG_NET_VENDOR_REALTEK=y
CONFIG_ATP=m
@@ -2428,6 +2568,7 @@ CONFIG_8139TOO_TUNE_TWISTER=y
CONFIG_8139TOO_8129=y
# CONFIG_8139_OLD_RX_RESET is not set
CONFIG_R8169=m
+# CONFIG_NET_VENDOR_RENESAS is not set
CONFIG_NET_VENDOR_RDC=y
CONFIG_R6040=m
CONFIG_NET_VENDOR_ROCKER=y
@@ -2444,6 +2585,7 @@ CONFIG_SFC=m
CONFIG_SFC_MTD=y
CONFIG_SFC_MCDI_MON=y
CONFIG_SFC_SRIOV=y
+CONFIG_SFC_MCDI_LOGGING=y
CONFIG_NET_VENDOR_SMSC=y
CONFIG_PCMCIA_SMC91C92=m
CONFIG_EPIC100=m
@@ -2459,6 +2601,7 @@ CONFIG_HAPPYMEAL=m
CONFIG_SUNGEM=m
CONFIG_CASSINI=m
CONFIG_NIU=m
+CONFIG_NET_VENDOR_SYNOPSYS=y
CONFIG_NET_VENDOR_TEHUTI=y
CONFIG_TEHUTI=m
CONFIG_NET_VENDOR_TI=y
@@ -2484,6 +2627,7 @@ CONFIG_PHYLIB=m
#
# MII PHY device drivers
#
+CONFIG_AQUANTIA_PHY=m
CONFIG_AT803X_PHY=m
CONFIG_AMD_PHY=m
CONFIG_MARVELL_PHY=m
@@ -2492,7 +2636,9 @@ CONFIG_QSEMI_PHY=m
CONFIG_LXT_PHY=m
CONFIG_CICADA_PHY=m
CONFIG_VITESSE_PHY=m
+CONFIG_TERANETICS_PHY=m
CONFIG_SMSC_PHY=m
+CONFIG_BCM_NET_PHYLIB=m
CONFIG_BROADCOM_PHY=m
CONFIG_BCM7XXX_PHY=m
CONFIG_BCM87XX_PHY=m
@@ -2502,9 +2648,13 @@ CONFIG_NATIONAL_PHY=m
CONFIG_STE10XP=m
CONFIG_LSI_ET1011C_PHY=m
CONFIG_MICREL_PHY=m
+CONFIG_DP83848_PHY=m
+CONFIG_DP83867_PHY=m
+CONFIG_MICROCHIP_PHY=m
CONFIG_FIXED_PHY=m
CONFIG_MDIO_BITBANG=m
# CONFIG_MDIO_GPIO is not set
+CONFIG_MDIO_OCTEON=m
CONFIG_MDIO_BCM_UNIMAC=m
# CONFIG_MICREL_KS8995MA is not set
CONFIG_PLIP=m
@@ -2535,6 +2685,7 @@ CONFIG_USB_KAWETH=m
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_AX88179_178A=m
@@ -2570,6 +2721,7 @@ CONFIG_USB_CDC_PHONET=m
CONFIG_USB_IPHETH=m
CONFIG_USB_SIERRA_NET=m
CONFIG_USB_VL600=m
+CONFIG_USB_NET_CH9200=m
CONFIG_WLAN=y
CONFIG_PCMCIA_RAYCS=m
CONFIG_LIBERTAS_THINFIRM=m
@@ -2585,10 +2737,10 @@ CONFIG_PCMCIA_WL3501=m
CONFIG_PRISM54=m
CONFIG_USB_ZD1201=m
CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_ADM8211=m
CONFIG_RTL8180=m
CONFIG_RTL8187=m
CONFIG_RTL8187_LEDS=y
-CONFIG_ADM8211=m
# CONFIG_MAC80211_HWSIM is not set
CONFIG_MWL8K=m
CONFIG_ATH_COMMON=m
@@ -2642,7 +2794,6 @@ CONFIG_B43_BUSES_BCMA_AND_SSB=y
# CONFIG_B43_BUSES_SSB is not set
CONFIG_B43_PCI_AUTOSELECT=y
CONFIG_B43_PCICORE_AUTOSELECT=y
-CONFIG_B43_PCMCIA=y
CONFIG_B43_SDIO=y
CONFIG_B43_BCMA_PIO=y
CONFIG_B43_PIO=y
@@ -2757,6 +2908,8 @@ CONFIG_RT2X00_LIB_CRYPTO=y
CONFIG_RT2X00_LIB_LEDS=y
# CONFIG_RT2X00_LIB_DEBUGFS is not set
# CONFIG_RT2X00_DEBUG is not set
+CONFIG_WL_MEDIATEK=y
+CONFIG_MT7601U=m
CONFIG_RTL_CARDS=m
CONFIG_RTL8192CE=m
CONFIG_RTL8192SE=m
@@ -2774,6 +2927,8 @@ CONFIG_RTLWIFI_USB=m
CONFIG_RTL8192C_COMMON=m
CONFIG_RTL8723_COMMON=m
CONFIG_RTLBTCOEXIST=m
+CONFIG_RTL8XXXU=m
+CONFIG_RTL8XXXU_UNTESTED=y
CONFIG_WL_TI=y
CONFIG_WL1251=m
# CONFIG_WL1251_SPI is not set
@@ -2808,11 +2963,14 @@ CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8
CONFIG_IEEE802154_DRIVERS=m
CONFIG_IEEE802154_FAKELB=m
CONFIG_IEEE802154_AT86RF230=m
+# CONFIG_IEEE802154_AT86RF230_DEBUGFS is not set
# CONFIG_IEEE802154_MRF24J40 is not set
# CONFIG_IEEE802154_CC2520 is not set
+CONFIG_IEEE802154_ATUSB=m
CONFIG_XEN_NETDEV_FRONTEND=m
CONFIG_XEN_NETDEV_BACKEND=m
CONFIG_VMXNET3=m
+CONFIG_FUJITSU_ES=m
CONFIG_HYPERV_NET=m
CONFIG_ISDN=y
CONFIG_ISDN_I4L=m
@@ -2944,11 +3102,13 @@ CONFIG_MISDN_NETJET=m
CONFIG_MISDN_IPAC=m
CONFIG_MISDN_ISAR=m
CONFIG_ISDN_HDLC=m
+# CONFIG_NVM is not set
#
# Input device support
#
CONFIG_INPUT=y
+CONFIG_INPUT_LEDS=m
CONFIG_INPUT_FF_MEMLESS=m
CONFIG_INPUT_POLLDEV=m
CONFIG_INPUT_SPARSEKMAP=m
@@ -3055,6 +3215,7 @@ CONFIG_TABLET_USB_HANWANG=m
CONFIG_TABLET_USB_KBTAB=m
CONFIG_TABLET_SERIAL_WACOM4=m
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
# CONFIG_TOUCHSCREEN_ADS7846 is not set
# CONFIG_TOUCHSCREEN_AD7877 is not set
CONFIG_TOUCHSCREEN_AD7879=m
@@ -3073,6 +3234,7 @@ CONFIG_TOUCHSCREEN_CYTTSP4_SPI=m
CONFIG_TOUCHSCREEN_DYNAPRO=m
CONFIG_TOUCHSCREEN_HAMPSHIRE=m
CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FT6236=m
CONFIG_TOUCHSCREEN_FUJITSU=m
CONFIG_TOUCHSCREEN_GOODIX=m
CONFIG_TOUCHSCREEN_ILI210X=m
@@ -3094,6 +3256,7 @@ CONFIG_TOUCHSCREEN_TOUCHWIN=m
CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
CONFIG_TOUCHSCREEN_UCB1400=m
CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_WDT87XX_I2C=m
CONFIG_TOUCHSCREEN_WM97XX=m
CONFIG_TOUCHSCREEN_WM9705=y
CONFIG_TOUCHSCREEN_WM9712=y
@@ -3120,6 +3283,8 @@ CONFIG_TOUCHSCREEN_USB_NEXIO=y
CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
CONFIG_TOUCHSCREEN_TOUCHIT213=m
CONFIG_TOUCHSCREEN_TSC_SERIO=m
+CONFIG_TOUCHSCREEN_TSC200X_CORE=m
+CONFIG_TOUCHSCREEN_TSC2004=m
# CONFIG_TOUCHSCREEN_TSC2005 is not set
CONFIG_TOUCHSCREEN_TSC2007=m
CONFIG_TOUCHSCREEN_ST1232=m
@@ -3127,6 +3292,7 @@ CONFIG_TOUCHSCREEN_SUR40=m
# CONFIG_TOUCHSCREEN_SX8654 is not set
CONFIG_TOUCHSCREEN_TPS6507X=m
CONFIG_TOUCHSCREEN_ZFORCE=m
+CONFIG_TOUCHSCREEN_ROHM_BU21023=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_AD714X=m
CONFIG_INPUT_AD714X_I2C=m
@@ -3165,6 +3331,7 @@ CONFIG_INPUT_CMA3000_I2C=m
CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m
CONFIG_INPUT_IDEAPAD_SLIDEBAR=m
# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
# CONFIG_INPUT_DRV2667_HAPTICS is not set
#
@@ -3183,6 +3350,7 @@ CONFIG_SERIO_ALTERA_PS2=m
CONFIG_SERIO_PS2MULT=m
CONFIG_SERIO_ARC_PS2=m
CONFIG_HYPERV_KEYBOARD=m
+# CONFIG_USERIO is not set
CONFIG_GAMEPORT=m
CONFIG_GAMEPORT_NS558=m
CONFIG_GAMEPORT_L4=m
@@ -3234,19 +3402,26 @@ CONFIG_SERIAL_8250_CS=m
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_FSL is not set
CONFIG_SERIAL_8250_DW=m
+CONFIG_SERIAL_8250_RT288X=y
# CONFIG_SERIAL_8250_FINTEK is not set
+CONFIG_SERIAL_8250_MID=y
#
# Non-8250 serial port support
#
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_JSM=m
CONFIG_SERIAL_SCCNXP=m
+CONFIG_SERIAL_SC16IS7XX_CORE=m
CONFIG_SERIAL_SC16IS7XX=m
+CONFIG_SERIAL_SC16IS7XX_I2C=y
+# CONFIG_SERIAL_SC16IS7XX_SPI is not set
CONFIG_SERIAL_ALTERA_JTAGUART=m
CONFIG_SERIAL_ALTERA_UART=m
CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
@@ -3330,6 +3505,7 @@ CONFIG_I2C_MUX=m
CONFIG_I2C_MUX_PCA9541=m
CONFIG_I2C_MUX_PCA954x=m
# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_SMBUS=m
CONFIG_I2C_ALGOBIT=m
@@ -3372,6 +3548,7 @@ CONFIG_I2C_SCMI=m
CONFIG_I2C_DESIGNWARE_CORE=m
CONFIG_I2C_DESIGNWARE_PLATFORM=m
CONFIG_I2C_DESIGNWARE_PCI=m
+# CONFIG_I2C_EMEV2 is not set
# CONFIG_I2C_GPIO is not set
CONFIG_I2C_OCORES=m
CONFIG_I2C_PCA_PLATFORM=m
@@ -3420,6 +3597,7 @@ CONFIG_SPI_PXA2XX_PCI=m
CONFIG_SPI_SC18IS602=m
CONFIG_SPI_XCOMM=m
CONFIG_SPI_XILINX=m
+CONFIG_SPI_ZYNQMP_GQSPI=m
CONFIG_SPI_DESIGNWARE=m
CONFIG_SPI_DW_PCI=m
# CONFIG_SPI_DW_MID_DMA is not set
@@ -3469,6 +3647,7 @@ CONFIG_GENERIC_PINCONF=y
CONFIG_PINCTRL_BAYTRAIL=y
CONFIG_PINCTRL_CHERRYVIEW=m
CONFIG_PINCTRL_INTEL=m
+CONFIG_PINCTRL_BROXTON=m
CONFIG_PINCTRL_SUNRISEPOINT=m
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_GPIOLIB=y
@@ -3481,15 +3660,22 @@ CONFIG_GPIO_SYSFS=y
#
# Memory mapped GPIO drivers
#
+# CONFIG_GPIO_AMDPT is not set
# CONFIG_GPIO_DWAPB is not set
-# CONFIG_GPIO_F7188X is not set
# CONFIG_GPIO_GENERIC_PLATFORM is not set
CONFIG_GPIO_ICH=m
-# CONFIG_GPIO_IT8761E is not set
CONFIG_GPIO_LYNXPOINT=m
+# CONFIG_GPIO_VX855 is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# Port-mapped I/O GPIO drivers
+#
+# CONFIG_GPIO_104_IDIO_16 is not set
+# CONFIG_GPIO_F7188X is not set
+# CONFIG_GPIO_IT87 is not set
CONFIG_GPIO_SCH=m
CONFIG_GPIO_SCH311X=m
-# CONFIG_GPIO_VX855 is not set
#
# I2C GPIO expanders
@@ -3505,6 +3691,7 @@ CONFIG_GPIO_SCH311X=m
# MFD GPIO expanders
#
# CONFIG_GPIO_ARIZONA is not set
+CONFIG_GPIO_CRYSTAL_COVE=y
# CONFIG_GPIO_LP3943 is not set
# CONFIG_GPIO_UCB1400 is not set
@@ -3520,10 +3707,14 @@ CONFIG_GPIO_AMD8111=m
# SPI GPIO expanders
#
# CONFIG_GPIO_MAX7301 is not set
-# CONFIG_GPIO_MCP23S08 is not set
# CONFIG_GPIO_MC33880 is not set
#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
# USB GPIO expanders
#
CONFIG_GPIO_VIPERBOARD=m
@@ -3537,7 +3728,7 @@ CONFIG_TEST_POWER=m
# CONFIG_BATTERY_DS2781 is not set
# CONFIG_BATTERY_DS2782 is not set
# CONFIG_BATTERY_SBS is not set
-# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_BQ27XXX is not set
# CONFIG_BATTERY_MAX17040 is not set
# CONFIG_BATTERY_MAX17042 is not set
# CONFIG_CHARGER_PCF50633 is not set
@@ -3547,9 +3738,14 @@ CONFIG_TEST_POWER=m
# CONFIG_CHARGER_GPIO is not set
# CONFIG_CHARGER_BQ2415X is not set
# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
CONFIG_CHARGER_BQ24735=m
+# CONFIG_CHARGER_BQ25890 is not set
# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_CHARGER_TPS65217 is not set
# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_BATTERY_RT5033 is not set
+# CONFIG_CHARGER_RT9455 is not set
CONFIG_POWER_RESET=y
# CONFIG_POWER_RESET_RESTART is not set
CONFIG_POWER_AVS=y
@@ -3587,6 +3783,7 @@ CONFIG_SENSORS_ASB100=m
CONFIG_SENSORS_ATXP1=m
CONFIG_SENSORS_DS620=m
CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_DELL_SMM=m
CONFIG_SENSORS_I5K_AMB=m
CONFIG_SENSORS_F71805F=m
CONFIG_SENSORS_F71882FG=m
@@ -3624,6 +3821,7 @@ CONFIG_SENSORS_MAX6639=m
CONFIG_SENSORS_MAX6642=m
CONFIG_SENSORS_MAX6650=m
CONFIG_SENSORS_MAX6697=m
+CONFIG_SENSORS_MAX31790=m
CONFIG_SENSORS_HTU21=m
CONFIG_SENSORS_MCP3021=m
CONFIG_SENSORS_ADCXX=m
@@ -3657,6 +3855,7 @@ CONFIG_SENSORS_ADM1275=m
CONFIG_SENSORS_LM25066=m
CONFIG_SENSORS_LTC2978=m
CONFIG_SENSORS_MAX16064=m
+CONFIG_SENSORS_MAX20751=m
CONFIG_SENSORS_MAX34440=m
CONFIG_SENSORS_MAX8688=m
CONFIG_SENSORS_TPS40422=m
@@ -3685,6 +3884,7 @@ CONFIG_SENSORS_ADS7871=m
CONFIG_SENSORS_AMC6821=m
CONFIG_SENSORS_INA209=m
CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_TC74=m
CONFIG_SENSORS_THMC50=m
CONFIG_SENSORS_TMP102=m
CONFIG_SENSORS_TMP103=m
@@ -3712,23 +3912,24 @@ CONFIG_SENSORS_ACPI_POWER=m
CONFIG_SENSORS_ATK0110=m
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
+# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_EMULATION is not set
CONFIG_INTEL_POWERCLAMP=m
CONFIG_X86_PKG_TEMP_THERMAL=m
+CONFIG_INTEL_SOC_DTS_IOSF_CORE=m
CONFIG_INTEL_SOC_DTS_THERMAL=m
CONFIG_INT340X_THERMAL=m
CONFIG_ACPI_THERMAL_REL=m
-
-#
-# Texas Instruments thermal drivers
-#
+CONFIG_INTEL_PCH_THERMAL=m
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -3741,6 +3942,7 @@ CONFIG_XILINX_WATCHDOG=m
# CONFIG_CADENCE_WATCHDOG is not set
CONFIG_DW_WATCHDOG=m
# CONFIG_RN5T618_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
CONFIG_RETU_WATCHDOG=m
CONFIG_ACQUIRE_WDT=m
CONFIG_ADVANTECH_WDT=m
@@ -3774,6 +3976,7 @@ CONFIG_W83877F_WDT=m
CONFIG_W83977F_WDT=m
CONFIG_MACHZ_WDT=m
CONFIG_SBC_EPX_C3_WATCHDOG=m
+CONFIG_BCM7038_WDT=m
CONFIG_MEN_A21_WDT=m
CONFIG_XEN_WDT=m
@@ -3802,6 +4005,7 @@ CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
CONFIG_SSB_PCMCIAHOST=y
CONFIG_SSB_SDIOHOST_POSSIBLE=y
CONFIG_SSB_SDIOHOST=y
+CONFIG_SSB_HOST_SOC=y
# CONFIG_SSB_DEBUG is not set
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_DRIVER_PCICORE=y
@@ -3832,10 +4036,12 @@ CONFIG_MFD_BCM590XX=m
# CONFIG_MFD_AXP20X is not set
CONFIG_MFD_CROS_EC=m
CONFIG_MFD_CROS_EC_I2C=m
+# CONFIG_MFD_CROS_EC_SPI is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_DA9052_SPI is not set
# CONFIG_MFD_DA9052_I2C is not set
# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
# CONFIG_MFD_DA9063 is not set
# CONFIG_MFD_DA9150 is not set
# CONFIG_MFD_DLN2 is not set
@@ -3847,7 +4053,10 @@ CONFIG_HTC_PASIC3=m
# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
CONFIG_LPC_ICH=m
CONFIG_LPC_SCH=m
-# CONFIG_INTEL_SOC_PMIC is not set
+CONFIG_INTEL_SOC_PMIC=y
+CONFIG_MFD_INTEL_LPSS=m
+CONFIG_MFD_INTEL_LPSS_ACPI=m
+CONFIG_MFD_INTEL_LPSS_PCI=m
# CONFIG_MFD_JANZ_CMODIO is not set
# CONFIG_MFD_KEMPLD is not set
# CONFIG_MFD_88PM800 is not set
@@ -3871,7 +4080,7 @@ CONFIG_PCF50633_GPIO=m
CONFIG_UCB1400_CORE=m
CONFIG_MFD_RDC321X=m
CONFIG_MFD_RTSX_PCI=m
-# CONFIG_MFD_RT5033 is not set
+CONFIG_MFD_RT5033=m
CONFIG_MFD_RTSX_USB=m
# CONFIG_MFD_RC5T583 is not set
CONFIG_MFD_RN5T618=m
@@ -3912,6 +4121,7 @@ CONFIG_MFD_ARIZONA_I2C=m
CONFIG_MFD_WM5102=y
CONFIG_MFD_WM5110=y
# CONFIG_MFD_WM8997 is not set
+# CONFIG_MFD_WM8998 is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM831X_I2C is not set
# CONFIG_MFD_WM831X_SPI is not set
@@ -3937,6 +4147,7 @@ CONFIG_VIDEO_V4L2=m
# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
CONFIG_VIDEO_TUNER=m
CONFIG_V4L2_MEM2MEM_DEV=m
+# CONFIG_V4L2_FLASH_LED_CLASS is not set
CONFIG_VIDEOBUF_GEN=m
CONFIG_VIDEOBUF_DMA_SG=m
CONFIG_VIDEOBUF_VMALLOC=m
@@ -4155,13 +4366,8 @@ CONFIG_MEDIA_PCI_SUPPORT=y
# Media capture support
#
CONFIG_VIDEO_MEYE=m
-
-#
-# Media capture/analog TV support
-#
-CONFIG_VIDEO_IVTV=m
-CONFIG_VIDEO_IVTV_ALSA=m
-CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_SOLO6X10=m
+CONFIG_VIDEO_TW68=m
CONFIG_VIDEO_ZORAN=m
CONFIG_VIDEO_ZORAN_DC30=m
CONFIG_VIDEO_ZORAN_ZR36060=m
@@ -4170,11 +4376,17 @@ CONFIG_VIDEO_ZORAN_DC10=m
CONFIG_VIDEO_ZORAN_LML33=m
CONFIG_VIDEO_ZORAN_LML33R10=m
CONFIG_VIDEO_ZORAN_AVS6EYES=m
+
+#
+# Media capture/analog TV support
+#
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_IVTV_ALSA=m
+CONFIG_VIDEO_FB_IVTV=m
CONFIG_VIDEO_HEXIUM_GEMINI=m
CONFIG_VIDEO_HEXIUM_ORION=m
CONFIG_VIDEO_MXB=m
-CONFIG_VIDEO_SOLO6X10=m
-CONFIG_VIDEO_TW68=m
+CONFIG_VIDEO_DT3155=m
#
# Media capture/analog/hybrid TV support
@@ -4200,6 +4412,7 @@ CONFIG_VIDEO_SAA7134_RC=y
CONFIG_VIDEO_SAA7134_DVB=m
CONFIG_VIDEO_SAA7134_GO7007=m
CONFIG_VIDEO_SAA7164=m
+CONFIG_VIDEO_COBALT=m
#
# Media digital TV PCI Adapters
@@ -4224,6 +4437,7 @@ CONFIG_DVB_HOPPER=m
CONFIG_DVB_NGENE=m
CONFIG_DVB_DDBRIDGE=m
CONFIG_DVB_SMIPCIE=m
+CONFIG_DVB_NETUP_UNIDVB=m
# CONFIG_V4L_PLATFORM_DRIVERS is not set
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
@@ -4231,6 +4445,7 @@ CONFIG_VIDEO_SH_VEU=m
CONFIG_V4L_TEST_DRIVERS=y
# CONFIG_VIDEO_VIVID is not set
# CONFIG_VIDEO_VIM2M is not set
+# CONFIG_DVB_PLATFORM_DRIVERS is not set
#
# Supported MMC/SDIO adapters
@@ -4316,6 +4531,8 @@ CONFIG_VIDEO_SAA6588=m
#
# Video decoders
#
+CONFIG_VIDEO_ADV7604=m
+CONFIG_VIDEO_ADV7842=m
CONFIG_VIDEO_BT819=m
CONFIG_VIDEO_BT856=m
CONFIG_VIDEO_BT866=m
@@ -4341,6 +4558,7 @@ CONFIG_VIDEO_SAA7127=m
CONFIG_VIDEO_SAA7185=m
CONFIG_VIDEO_ADV7170=m
CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_ADV7511=m
#
# Camera sensor devices
@@ -4448,6 +4666,7 @@ CONFIG_DVB_TDA826X=m
CONFIG_DVB_TUA6100=m
CONFIG_DVB_CX24116=m
CONFIG_DVB_CX24117=m
+CONFIG_DVB_CX24120=m
CONFIG_DVB_SI21XX=m
CONFIG_DVB_TS2020=m
CONFIG_DVB_DS3000=m
@@ -4476,6 +4695,7 @@ CONFIG_DVB_AF9013=m
CONFIG_DVB_EC100=m
CONFIG_DVB_STV0367=m
CONFIG_DVB_CXD2820R=m
+CONFIG_DVB_CXD2841ER=m
CONFIG_DVB_RTL2830=m
CONFIG_DVB_RTL2832=m
CONFIG_DVB_RTL2832_SDR=m
@@ -4530,6 +4750,7 @@ CONFIG_DVB_TUNER_DIB0090=m
# SEC control devices for DVB-S
#
CONFIG_DVB_DRX39XYJ=m
+CONFIG_DVB_LNBH25=m
CONFIG_DVB_LNBP21=m
CONFIG_DVB_LNBP22=m
CONFIG_DVB_ISL6405=m
@@ -4543,6 +4764,8 @@ CONFIG_DVB_TDA665x=m
CONFIG_DVB_IX2505V=m
CONFIG_DVB_M88RS2000=m
CONFIG_DVB_AF9033=m
+CONFIG_DVB_HORUS3A=m
+CONFIG_DVB_ASCOT2E=m
#
# Tools to develop new frontends
@@ -4561,14 +4784,11 @@ CONFIG_INTEL_GTT=m
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
CONFIG_VGA_SWITCHEROO=y
-
-#
-# Direct Rendering Manager
-#
CONFIG_DRM=m
CONFIG_DRM_MIPI_DSI=y
CONFIG_DRM_KMS_HELPER=m
CONFIG_DRM_KMS_FB_HELPER=y
+CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
CONFIG_DRM_TTM=m
@@ -4584,14 +4804,15 @@ CONFIG_DRM_R128=m
CONFIG_DRM_RADEON=m
# CONFIG_DRM_RADEON_USERPTR is not set
# CONFIG_DRM_RADEON_UMS is not set
+CONFIG_DRM_AMDGPU=m
+# CONFIG_DRM_AMDGPU_CIK is not set
+CONFIG_DRM_AMDGPU_USERPTR=y
CONFIG_DRM_NOUVEAU=m
CONFIG_NOUVEAU_DEBUG=5
CONFIG_NOUVEAU_DEBUG_DEFAULT=3
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
-CONFIG_DRM_I810=m
+# CONFIG_DRM_I810 is not set
CONFIG_DRM_I915=m
-CONFIG_DRM_I915_KMS=y
-CONFIG_DRM_I915_FBDEV=y
# CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set
CONFIG_DRM_MGA=m
CONFIG_DRM_SIS=m
@@ -4609,11 +4830,17 @@ CONFIG_DRM_MGAG200=m
CONFIG_DRM_CIRRUS_QEMU=m
CONFIG_DRM_QXL=m
CONFIG_DRM_BOCHS=m
+CONFIG_DRM_VIRTIO_GPU=m
CONFIG_DRM_PANEL=y
#
# Display Panels
#
+CONFIG_DRM_BRIDGE=y
+
+#
+# Display Interface Bridges
+#
CONFIG_HSA_AMD=m
#
@@ -4683,6 +4910,7 @@ CONFIG_FB_VT8623=m
# CONFIG_FB_SM501 is not set
# CONFIG_FB_SMSCUFX is not set
CONFIG_FB_UDL=m
+# CONFIG_FB_IBM_GXT4500 is not set
CONFIG_FB_VIRTUAL=m
CONFIG_XEN_FBDEV_FRONTEND=m
# CONFIG_FB_METRONOME is not set
@@ -4691,6 +4919,7 @@ CONFIG_XEN_FBDEV_FRONTEND=m
# CONFIG_FB_AUO_K190X is not set
CONFIG_FB_HYPERV=m
# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SM712 is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=m
# CONFIG_LCD_L4F00242T03 is not set
@@ -4710,6 +4939,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_BACKLIGHT_LM3533=m
CONFIG_BACKLIGHT_APPLE=m
+# CONFIG_BACKLIGHT_PM8941_WLED is not set
# CONFIG_BACKLIGHT_SAHARA is not set
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
@@ -4726,7 +4956,8 @@ CONFIG_HDMI=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=80
CONFIG_DUMMY_CONSOLE_ROWS=25
@@ -4751,17 +4982,18 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_PCM_TIMER=y
CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_HRTIMER=m
CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_MAX_CARDS=32
# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_PROC_FS=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
CONFIG_SND_VMASTER=y
-CONFIG_SND_KCTL_JACK=y
CONFIG_SND_DMA_SGBUF=y
CONFIG_SND_RAWMIDI_SEQ=m
CONFIG_SND_OPL3_LIB_SEQ=m
@@ -4863,20 +5095,16 @@ CONFIG_SND_YMFPCI=m
#
CONFIG_SND_HDA=m
CONFIG_SND_HDA_INTEL=m
-CONFIG_SND_HDA_DSP_LOADER=y
-CONFIG_SND_HDA_PREALLOC_SIZE=4096
CONFIG_SND_HDA_HWDEP=y
CONFIG_SND_HDA_RECONFIG=y
CONFIG_SND_HDA_INPUT_BEEP=y
CONFIG_SND_HDA_INPUT_BEEP_MODE=1
-CONFIG_SND_HDA_INPUT_JACK=y
CONFIG_SND_HDA_PATCH_LOADER=y
CONFIG_SND_HDA_CODEC_REALTEK=m
CONFIG_SND_HDA_CODEC_ANALOG=m
CONFIG_SND_HDA_CODEC_SIGMATEL=m
CONFIG_SND_HDA_CODEC_VIA=m
CONFIG_SND_HDA_CODEC_HDMI=m
-CONFIG_SND_HDA_I915=y
CONFIG_SND_HDA_CODEC_CIRRUS=m
CONFIG_SND_HDA_CODEC_CONEXANT=m
CONFIG_SND_HDA_CODEC_CA0110=m
@@ -4887,6 +5115,10 @@ CONFIG_SND_HDA_CODEC_SI3054=m
CONFIG_SND_HDA_GENERIC=m
CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
CONFIG_SND_HDA_CORE=m
+CONFIG_SND_HDA_DSP_LOADER=y
+CONFIG_SND_HDA_I915=y
+CONFIG_SND_HDA_EXT_CORE=m
+CONFIG_SND_HDA_PREALLOC_SIZE=4096
CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=m
@@ -4911,11 +5143,16 @@ CONFIG_SND_ISIGHT=m
CONFIG_SND_SCS1X=m
CONFIG_SND_FIREWORKS=m
CONFIG_SND_BEBOB=m
+CONFIG_SND_FIREWIRE_DIGI00X=m
+CONFIG_SND_FIREWIRE_TASCAM=m
CONFIG_SND_PCMCIA=y
CONFIG_SND_VXPOCKET=m
CONFIG_SND_PDAUDIOCF=m
CONFIG_SND_SOC=m
+CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
+CONFIG_SND_SOC_COMPRESS=y
+CONFIG_SND_SOC_TOPOLOGY=y
# CONFIG_SND_ATMEL_SOC is not set
CONFIG_SND_DESIGNWARE_I2S=m
@@ -4946,16 +5183,25 @@ CONFIG_SND_SOC_INTEL_BROADWELL_MACH=m
CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=m
CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=m
-# CONFIG_SND_SOC_QCOM is not set
+CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=m
+CONFIG_SND_SOC_INTEL_SKYLAKE=m
+CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
+
+#
+# Allwinner SoC Audio support
+#
+# CONFIG_SND_SUN4I_CODEC is not set
# CONFIG_SND_SOC_XTFPGA_I2S is not set
CONFIG_SND_SOC_I2C_AND_SPI=m
#
# CODEC drivers
#
+CONFIG_SND_SOC_AC97_CODEC=m
# CONFIG_SND_SOC_ADAU1701 is not set
# CONFIG_SND_SOC_AK4104 is not set
# CONFIG_SND_SOC_AK4554 is not set
+# CONFIG_SND_SOC_AK4613 is not set
# CONFIG_SND_SOC_AK4642 is not set
# CONFIG_SND_SOC_AK5386 is not set
# CONFIG_SND_SOC_ALC5623 is not set
@@ -4969,14 +5215,17 @@ CONFIG_SND_SOC_I2C_AND_SPI=m
# CONFIG_SND_SOC_CS4271_I2C is not set
# CONFIG_SND_SOC_CS4271_SPI is not set
# CONFIG_SND_SOC_CS42XX8_I2C is not set
-CONFIG_SND_SOC_HDMI_CODEC=m
+# CONFIG_SND_SOC_CS4349 is not set
+CONFIG_SND_SOC_DMIC=m
# CONFIG_SND_SOC_ES8328 is not set
+# CONFIG_SND_SOC_GTM601 is not set
CONFIG_SND_SOC_MAX98090=m
# CONFIG_SND_SOC_PCM1681 is not set
# CONFIG_SND_SOC_PCM1792A is not set
# CONFIG_SND_SOC_PCM512x_I2C is not set
# CONFIG_SND_SOC_PCM512x_SPI is not set
CONFIG_SND_SOC_RL6231=m
+CONFIG_SND_SOC_RL6347A=m
CONFIG_SND_SOC_RT286=m
# CONFIG_SND_SOC_RT5631 is not set
CONFIG_SND_SOC_RT5640=m
@@ -4992,14 +5241,16 @@ CONFIG_SND_SOC_SPDIF=m
# CONFIG_SND_SOC_SSM4567 is not set
# CONFIG_SND_SOC_STA32X is not set
# CONFIG_SND_SOC_STA350 is not set
+# CONFIG_SND_SOC_STI_SAS is not set
# CONFIG_SND_SOC_TAS2552 is not set
# CONFIG_SND_SOC_TAS5086 is not set
+# CONFIG_SND_SOC_TAS571X is not set
# CONFIG_SND_SOC_TFA9879 is not set
# CONFIG_SND_SOC_TLV320AIC23_I2C is not set
# CONFIG_SND_SOC_TLV320AIC23_SPI is not set
# CONFIG_SND_SOC_TLV320AIC31XX is not set
# CONFIG_SND_SOC_TLV320AIC3X is not set
-# CONFIG_SND_SOC_TS3A227E is not set
+CONFIG_SND_SOC_TS3A227E=m
# CONFIG_SND_SOC_WM8510 is not set
# CONFIG_SND_SOC_WM8523 is not set
# CONFIG_SND_SOC_WM8580 is not set
@@ -5044,6 +5295,7 @@ CONFIG_HID_BELKIN=m
CONFIG_HID_BETOP_FF=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
+CONFIG_HID_CORSAIR=m
CONFIG_HID_PRODIKEYS=m
CONFIG_HID_CP2112=m
CONFIG_HID_CYPRESS=m
@@ -5053,6 +5305,8 @@ CONFIG_HID_EMS_FF=m
CONFIG_HID_ELECOM=m
CONFIG_HID_ELO=m
CONFIG_HID_EZKEY=m
+CONFIG_HID_GEMBIRD=m
+CONFIG_HID_GFRM=m
CONFIG_HID_HOLTEK=m
CONFIG_HOLTEK_FF=y
CONFIG_HID_GT683R=m
@@ -5144,7 +5398,7 @@ CONFIG_USB_DEFAULT_PERSIST=y
CONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_FSM is not set
+# CONFIG_USB_ULPI_BUS is not set
CONFIG_USB_MON=m
CONFIG_USB_WUSB=m
CONFIG_USB_WUSB_CBAF=m
@@ -5156,6 +5410,7 @@ CONFIG_USB_WUSB_CBAF=m
CONFIG_USB_C67X00_HCD=m
CONFIG_USB_XHCI_HCD=m
CONFIG_USB_XHCI_PCI=m
+# CONFIG_USB_XHCI_PLATFORM is not set
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
@@ -5164,7 +5419,6 @@ CONFIG_USB_EHCI_PCI=m
CONFIG_USB_OXU210HP_HCD=m
CONFIG_USB_ISP116X_HCD=m
CONFIG_USB_ISP1362_HCD=m
-CONFIG_USB_FUSBH200_HCD=m
# CONFIG_USB_FOTG210_HCD is not set
CONFIG_USB_MAX3421_HCD=m
CONFIG_USB_OHCI_HCD=m
@@ -5233,6 +5487,10 @@ CONFIG_USB_MUSB_DUAL_ROLE=y
#
# Platform Glue Layer
#
+
+#
+# MUSB DMA mode
+#
CONFIG_MUSB_PIO_ONLY=y
# CONFIG_USB_DWC3 is not set
# CONFIG_USB_DWC2 is not set
@@ -5423,7 +5681,6 @@ CONFIG_UWB_WHCI=m
CONFIG_UWB_I1480U=m
CONFIG_MMC=m
# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_CLKGATE is not set
#
# MMC/SD/SDIO Card Drivers
@@ -5454,6 +5711,7 @@ CONFIG_MMC_USDHI6ROL0=m
CONFIG_MMC_REALTEK_PCI=m
CONFIG_MMC_REALTEK_USB=m
CONFIG_MMC_TOSHIBA_PCI=m
+CONFIG_MMC_MTK=m
CONFIG_MEMSTICK=m
# CONFIG_MEMSTICK_DEBUG is not set
@@ -5486,11 +5744,10 @@ CONFIG_LEDS_PCA9532=m
# CONFIG_LEDS_PCA9532_GPIO is not set
CONFIG_LEDS_GPIO=m
CONFIG_LEDS_LP3944=m
-CONFIG_LEDS_LP55XX_COMMON=m
-CONFIG_LEDS_LP5521=m
-CONFIG_LEDS_LP5523=m
-CONFIG_LEDS_LP5562=m
-CONFIG_LEDS_LP8501=m
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_LP5562 is not set
+# CONFIG_LEDS_LP8501 is not set
CONFIG_LEDS_LP8860=m
CONFIG_LEDS_CLEVO_MAIL=m
CONFIG_LEDS_PCA955X=m
@@ -5502,13 +5759,13 @@ CONFIG_LEDS_LT3593=m
CONFIG_LEDS_DELL_NETBOOKS=m
CONFIG_LEDS_MC13783=m
CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_TLC591XX=m
CONFIG_LEDS_LM355x=m
#
# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
#
CONFIG_LEDS_BLINKM=m
-# CONFIG_LEDS_PM8941_WLED is not set
#
# LED Triggers
@@ -5537,11 +5794,8 @@ CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
-CONFIG_INFINIBAND_IPATH=m
CONFIG_INFINIBAND_QIB=m
# CONFIG_INFINIBAND_QIB_DCA is not set
-CONFIG_INFINIBAND_AMSO1100=m
-# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
CONFIG_INFINIBAND_CXGB3=m
# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
CONFIG_INFINIBAND_CXGB4=m
@@ -5559,11 +5813,12 @@ CONFIG_INFINIBAND_SRP=m
CONFIG_INFINIBAND_SRPT=m
CONFIG_INFINIBAND_ISER=m
CONFIG_INFINIBAND_ISERT=m
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
CONFIG_EDAC=y
CONFIG_EDAC_LEGACY_SYSFS=y
# CONFIG_EDAC_DEBUG is not set
CONFIG_EDAC_DECODE_MCE=m
-CONFIG_EDAC_MCE_INJ=m
CONFIG_EDAC_MM_EDAC=m
CONFIG_EDAC_AMD64=m
# CONFIG_EDAC_AMD64_ERROR_INJECTION is not set
@@ -5582,8 +5837,9 @@ CONFIG_EDAC_SBRIDGE=m
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
# CONFIG_RTC_DEBUG is not set
#
@@ -5625,6 +5881,7 @@ CONFIG_RTC_DRV_RX8581=m
CONFIG_RTC_DRV_RX8025=m
CONFIG_RTC_DRV_EM3027=m
CONFIG_RTC_DRV_RV3029C2=m
+# CONFIG_RTC_DRV_RV8803 is not set
#
# SPI RTC drivers
@@ -5674,7 +5931,6 @@ CONFIG_RTC_DRV_PCF50633=m
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_MC13XXX=m
-# CONFIG_RTC_DRV_XGENE is not set
#
# HID Sensor RTC drivers
@@ -5686,14 +5942,16 @@ CONFIG_DMADEVICES=y
#
# DMA Devices
#
-CONFIG_INTEL_MIC_X100_DMA=m
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DMA_ACPI=y
+CONFIG_INTEL_IDMA64=m
CONFIG_INTEL_IOATDMA=m
+CONFIG_INTEL_MIC_X100_DMA=m
CONFIG_DW_DMAC_CORE=m
CONFIG_DW_DMAC=m
CONFIG_DW_DMAC_PCI=m
-# CONFIG_HSU_DMA_PCI is not set
-CONFIG_DMA_ENGINE=y
-CONFIG_DMA_ACPI=y
+CONFIG_HSU_DMA=y
#
# DMA Clients
@@ -5716,6 +5974,7 @@ CONFIG_UIO_AEC=m
CONFIG_UIO_SERCOS3=m
CONFIG_UIO_PCI_GENERIC=m
CONFIG_UIO_NETX=m
+CONFIG_UIO_PRUSS=m
# CONFIG_UIO_MF624 is not set
CONFIG_VFIO_IOMMU_TYPE1=m
CONFIG_VFIO_VIRQFD=m
@@ -5724,6 +5983,7 @@ CONFIG_VFIO_PCI=m
CONFIG_VFIO_PCI_VGA=y
CONFIG_VFIO_PCI_MMAP=y
CONFIG_VFIO_PCI_INTX=y
+CONFIG_IRQ_BYPASS_MANAGER=m
CONFIG_VIRT_DRIVERS=y
CONFIG_VIRTIO=m
@@ -5771,6 +6031,8 @@ CONFIG_XEN_HAVE_PVMMU=y
CONFIG_XEN_EFI=y
CONFIG_XEN_AUTO_XLATE=y
CONFIG_XEN_ACPI=y
+CONFIG_XEN_SYMS=y
+CONFIG_XEN_HAVE_VPMU=y
CONFIG_STAGING=y
CONFIG_SLICOSS=m
CONFIG_PRISM2_USB=m
@@ -5856,6 +6118,7 @@ CONFIG_COMEDI_USBDUXSIGMA=m
CONFIG_COMEDI_VMK80XX=m
CONFIG_COMEDI_8254=m
CONFIG_COMEDI_8255=m
+CONFIG_COMEDI_8255_SA=m
CONFIG_COMEDI_KCOMEDILIB=m
CONFIG_COMEDI_AMPLC_DIO200=m
CONFIG_COMEDI_AMPLC_PC236=m
@@ -5968,12 +6231,8 @@ CONFIG_SENSORS_HMC5843_SPI=m
#
# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set
# CONFIG_IIO_SIMPLE_DUMMY is not set
-# CONFIG_FB_SM7XX is not set
# CONFIG_FB_SM750 is not set
CONFIG_FB_XGI=m
-CONFIG_FT1000=m
-CONFIG_FT1000_USB=m
-CONFIG_FT1000_PCMCIA=m
#
# Speakup console speech
@@ -5994,9 +6253,6 @@ CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=m
CONFIG_STAGING_MEDIA=y
CONFIG_I2C_BCM2048=m
CONFIG_DVB_CXD2099=m
-CONFIG_VIDEO_DT3155=m
-CONFIG_DT3155_CCIR=y
-CONFIG_DT3155_STREAMING=y
CONFIG_DVB_MN88472=m
CONFIG_DVB_MN88473=m
CONFIG_LIRC_STAGING=y
@@ -6008,11 +6264,11 @@ CONFIG_LIRC_SERIAL=m
CONFIG_LIRC_SERIAL_TRANSMITTER=y
CONFIG_LIRC_SIR=m
CONFIG_LIRC_ZILOG=m
+# CONFIG_STAGING_RDMA is not set
#
# Android
#
-CONFIG_USB_WPAN_HCD=m
CONFIG_WIMAX_GDM72XX=m
CONFIG_WIMAX_GDM72XX_QOS=y
CONFIG_WIMAX_GDM72XX_K_MODE=y
@@ -6039,16 +6295,8 @@ CONFIG_GS_FPGABOOT=m
CONFIG_CRYPTO_SKEIN=y
# CONFIG_UNISYSSPAR is not set
# CONFIG_FB_TFT is not set
-CONFIG_I2O=m
-CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
-CONFIG_I2O_EXT_ADAPTEC=y
-CONFIG_I2O_EXT_ADAPTEC_DMA64=y
-CONFIG_I2O_CONFIG=m
-CONFIG_I2O_CONFIG_OLD_IOCTL=y
-CONFIG_I2O_BUS=m
-CONFIG_I2O_BLOCK=m
-CONFIG_I2O_SCSI=m
-CONFIG_I2O_PROC=m
+# CONFIG_WILC1000_DRIVER is not set
+# CONFIG_MOST is not set
CONFIG_X86_PLATFORM_DEVICES=y
CONFIG_ACER_WMI=m
CONFIG_ACERHDF=m
@@ -6058,6 +6306,7 @@ CONFIG_DELL_LAPTOP=m
CONFIG_DELL_WMI=m
CONFIG_DELL_WMI_AIO=m
CONFIG_DELL_SMO8800=m
+CONFIG_DELL_RBTN=m
CONFIG_FUJITSU_LAPTOP=m
# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
CONFIG_FUJITSU_TABLET=m
@@ -6090,6 +6339,7 @@ CONFIG_TOPSTAR_LAPTOP=m
CONFIG_ACPI_TOSHIBA=m
CONFIG_TOSHIBA_BT_RFKILL=m
CONFIG_TOSHIBA_HAPS=m
+CONFIG_TOSHIBA_WMI=m
CONFIG_ACPI_CMPC=m
CONFIG_INTEL_IPS=m
CONFIG_IBM_RTL=m
@@ -6101,11 +6351,14 @@ CONFIG_APPLE_GMUX=m
CONFIG_INTEL_RST=m
CONFIG_INTEL_SMARTCONNECT=y
CONFIG_PVPANIC=m
+CONFIG_INTEL_PMC_IPC=m
+CONFIG_SURFACE_PRO3_BUTTON=m
CONFIG_CHROME_PLATFORMS=y
CONFIG_CHROMEOS_LAPTOP=m
CONFIG_CHROMEOS_PSTORE=m
CONFIG_CROS_EC_CHARDEV=m
CONFIG_CROS_EC_LPC=m
+CONFIG_CROS_EC_PROTO=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y
@@ -6145,6 +6398,7 @@ CONFIG_AMD_IOMMU=y
CONFIG_AMD_IOMMU_V2=m
CONFIG_DMAR_TABLE=y
CONFIG_INTEL_IOMMU=y
+CONFIG_INTEL_IOMMU_SVM=y
# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
CONFIG_INTEL_IOMMU_FLOPPY_WA=y
CONFIG_IRQ_REMAP=y
@@ -6162,6 +6416,7 @@ CONFIG_STE_MODEM_RPROC=m
#
# SOC (System On Chip) specific Drivers
#
+# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
CONFIG_PM_DEVFREQ=y
@@ -6191,7 +6446,7 @@ CONFIG_EXTCON_SM5502=m
CONFIG_MEMORY=y
CONFIG_IIO=m
CONFIG_IIO_BUFFER=y
-CONFIG_IIO_BUFFER_CB=y
+CONFIG_IIO_BUFFER_CB=m
CONFIG_IIO_KFIFO_BUF=m
CONFIG_IIO_TRIGGERED_BUFFER=m
CONFIG_IIO_TRIGGER=y
@@ -6207,10 +6462,13 @@ CONFIG_IIO_ST_ACCEL_3AXIS=m
CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m
CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m
# CONFIG_KXSD9 is not set
-# CONFIG_MMA8452 is not set
CONFIG_KXCJK1013=m
+# CONFIG_MMA8452 is not set
# CONFIG_MMA9551 is not set
# CONFIG_MMA9553 is not set
+# CONFIG_MXC4005 is not set
+# CONFIG_STK8312 is not set
+# CONFIG_STK8BA50 is not set
#
# Analog to digital converters
@@ -6224,6 +6482,7 @@ CONFIG_KXCJK1013=m
# CONFIG_AD7887 is not set
# CONFIG_AD7923 is not set
# CONFIG_AD799X is not set
+# CONFIG_HI8435 is not set
# CONFIG_MAX1027 is not set
# CONFIG_MAX1363 is not set
# CONFIG_MCP320X is not set
@@ -6242,6 +6501,11 @@ CONFIG_KXCJK1013=m
# CONFIG_AD8366 is not set
#
+# Chemical Sensors
+#
+# CONFIG_VZ89X is not set
+
+#
# Hid Sensor IIO Common
#
CONFIG_HID_SENSOR_IIO_COMMON=m
@@ -6271,6 +6535,7 @@ CONFIG_IIO_ST_SENSORS_CORE=m
# CONFIG_AD5764 is not set
# CONFIG_AD5791 is not set
# CONFIG_AD7303 is not set
+# CONFIG_M62332 is not set
# CONFIG_MAX517 is not set
# CONFIG_MCP4725 is not set
# CONFIG_MCP4922 is not set
@@ -6308,6 +6573,8 @@ CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
# Humidity sensors
#
# CONFIG_DHT11 is not set
+# CONFIG_HDC100X is not set
+# CONFIG_HTU21 is not set
# CONFIG_SI7005 is not set
# CONFIG_SI7020 is not set
@@ -6322,9 +6589,12 @@ CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
#
# Light sensors
#
+CONFIG_ACPI_ALS=m
# CONFIG_ADJD_S311 is not set
# CONFIG_AL3320A is not set
# CONFIG_APDS9300 is not set
+# CONFIG_APDS9960 is not set
+CONFIG_BH1750=m
# CONFIG_CM32181 is not set
# CONFIG_CM3232 is not set
# CONFIG_CM3323 is not set
@@ -6334,12 +6604,17 @@ CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
CONFIG_HID_SENSOR_ALS=m
# CONFIG_HID_SENSOR_PROX is not set
# CONFIG_JSA1212 is not set
+CONFIG_RPR0521=m
# CONFIG_SENSORS_LM3533 is not set
# CONFIG_LTR501 is not set
+CONFIG_OPT3001=m
+CONFIG_PA12203001=m
+CONFIG_STK3310=m
# CONFIG_TCS3414 is not set
# CONFIG_TCS3472 is not set
# CONFIG_SENSORS_TSL2563 is not set
# CONFIG_TSL4531 is not set
+# CONFIG_US5182D is not set
# CONFIG_VCNL4000 is not set
#
@@ -6347,8 +6622,10 @@ CONFIG_HID_SENSOR_ALS=m
#
# CONFIG_AK8975 is not set
# CONFIG_AK09911 is not set
+# CONFIG_BMC150_MAGN is not set
# CONFIG_MAG3110 is not set
CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+# CONFIG_MMC35240 is not set
CONFIG_IIO_ST_MAGN_3AXIS=m
CONFIG_IIO_ST_MAGN_I2C_3AXIS=m
CONFIG_IIO_ST_MAGN_SPI_3AXIS=m
@@ -6366,6 +6643,11 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
# CONFIG_IIO_SYSFS_TRIGGER is not set
#
+# Digital potentiometers
+#
+# CONFIG_MCP4531 is not set
+
+#
# Pressure sensors
#
# CONFIG_BMP280 is not set
@@ -6373,6 +6655,7 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
# CONFIG_MPL115 is not set
# CONFIG_MPL3115 is not set
# CONFIG_MS5611 is not set
+# CONFIG_MS5637 is not set
# CONFIG_IIO_ST_PRESS is not set
# CONFIG_T5403 is not set
@@ -6384,6 +6667,7 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
#
# Proximity sensors
#
+# CONFIG_LIDAR_LITE_V2 is not set
# CONFIG_SX9500 is not set
#
@@ -6391,6 +6675,8 @@ CONFIG_IIO_INTERRUPT_TRIGGER=m
#
# CONFIG_MLX90614 is not set
# CONFIG_TMP006 is not set
+# CONFIG_TSYS01 is not set
+# CONFIG_TSYS02D is not set
# CONFIG_NTB is not set
# CONFIG_VME_BUS is not set
# CONFIG_PWM is not set
@@ -6408,17 +6694,40 @@ CONFIG_FMC_CHARDEV=m
# PHY Subsystem
#
CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
CONFIG_BCM_KONA_USB2_PHY=m
CONFIG_POWERCAP=y
CONFIG_INTEL_RAPL=m
# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
CONFIG_RAS=y
+CONFIG_AMD_MCE_INJ=m
CONFIG_THUNDERBOLT=m
#
# Android
#
# CONFIG_ANDROID is not set
+CONFIG_LIBNVDIMM=y
+CONFIG_BLK_DEV_PMEM=m
+CONFIG_ND_BLK=m
+CONFIG_ND_CLAIM=y
+CONFIG_ND_BTT=m
+CONFIG_BTT=y
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_STM_DUMMY is not set
+# CONFIG_STM_SOURCE_CONSOLE is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
#
# Firmware Drivers
@@ -6439,7 +6748,9 @@ CONFIG_ISCSI_IBFT=m
# EFI (Extensible Firmware Interface) Support
#
# CONFIG_EFI_VARS is not set
+CONFIG_EFI_ESRT=y
CONFIG_EFI_RUNTIME_MAP=y
+# CONFIG_EFI_FAKE_MEMMAP is not set
CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_UEFI_CPER=y
@@ -6450,7 +6761,7 @@ CONFIG_DCACHE_WORD_ACCESS=y
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
CONFIG_EXT4_FS=m
-CONFIG_EXT4_USE_FOR_EXT23=y
+CONFIG_EXT4_USE_FOR_EXT2=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_ENCRYPTION is not set
@@ -6496,6 +6807,7 @@ CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_POSIX_ACL=y
CONFIG_F2FS_FS_SECURITY=y
CONFIG_F2FS_CHECK_FS=y
+CONFIG_F2FS_FS_ENCRYPTION=y
# CONFIG_F2FS_IO_TRACE is not set
# CONFIG_FS_DAX is not set
CONFIG_FS_POSIX_ACL=y
@@ -6558,8 +6870,10 @@ CONFIG_NTFS_RW=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_VMCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_CHILDREN=y
CONFIG_KERNFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
@@ -6596,6 +6910,7 @@ CONFIG_UBIFS_FS=m
# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
CONFIG_LOGFS=m
CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m
@@ -6674,8 +6989,7 @@ CONFIG_SUNRPC_BACKCHANNEL=y
CONFIG_SUNRPC_SWAP=y
CONFIG_RPCSEC_GSS_KRB5=m
CONFIG_SUNRPC_DEBUG=y
-CONFIG_SUNRPC_XPRT_RDMA_CLIENT=m
-CONFIG_SUNRPC_XPRT_RDMA_SERVER=m
+CONFIG_SUNRPC_XPRT_RDMA=m
CONFIG_CEPH_FS=m
CONFIG_CEPH_FSCACHE=y
CONFIG_CEPH_FS_POSIX_ACL=y
@@ -6690,6 +7004,7 @@ CONFIG_CIFS_ACL=y
# CONFIG_CIFS_DEBUG is not set
CONFIG_CIFS_DFS_UPCALL=y
CONFIG_CIFS_SMB2=y
+CONFIG_CIFS_SMB311=y
CONFIG_CIFS_FSCACHE=y
CONFIG_NCP_FS=m
# CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -6789,6 +7104,7 @@ CONFIG_UNUSED_SYMBOLS=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
@@ -6816,7 +7132,6 @@ CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_HAVE_ARCH_KMEMCHECK=y
CONFIG_HAVE_ARCH_KASAN=y
# CONFIG_KASAN is not set
-CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
# CONFIG_DEBUG_SHIRQ is not set
#
@@ -6836,6 +7151,7 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_SCHED_DEBUG=y
+CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
# CONFIG_SCHED_STACK_END_CHECK is not set
# CONFIG_DEBUG_TIMEKEEPING is not set
@@ -6871,8 +7187,8 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_TORTURE_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60
-# CONFIG_RCU_CPU_STALL_INFO is not set
# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
@@ -6914,6 +7230,7 @@ CONFIG_STACK_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_KPROBE_EVENT=y
CONFIG_UPROBE_EVENT=y
+CONFIG_BPF_EVENTS=y
CONFIG_PROBE_EVENTS=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
@@ -6926,6 +7243,7 @@ CONFIG_MMIOTRACE=y
CONFIG_RING_BUFFER_BENCHMARK=m
# CONFIG_RING_BUFFER_STARTUP_TEST is not set
# CONFIG_TRACE_ENUM_MAP_FILE is not set
+# CONFIG_TRACING_EVENTS_GPIO is not set
#
# Runtime Testing
@@ -6942,6 +7260,7 @@ CONFIG_ASYNC_RAID6_TEST=m
# CONFIG_TEST_HEXDUMP is not set
# CONFIG_TEST_STRING_HELPERS is not set
CONFIG_TEST_KSTRTOX=m
+# CONFIG_TEST_PRINTF is not set
# CONFIG_TEST_RHASHTABLE is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_DMA_API_DEBUG is not set
@@ -6951,17 +7270,21 @@ CONFIG_TEST_KSTRTOX=m
# CONFIG_TEST_FIRMWARE is not set
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_STRICT_DEVMEM=y
-CONFIG_X86_VERBOSE_BOOTUP=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_EARLY_PRINTK_DBGP is not set
CONFIG_EARLY_PRINTK_EFI=y
+# CONFIG_X86_PTDUMP_CORE is not set
# CONFIG_X86_PTDUMP is not set
+# CONFIG_EFI_PGT_DUMP is not set
CONFIG_DEBUG_RODATA=y
# CONFIG_DEBUG_RODATA_TEST is not set
+# CONFIG_DEBUG_WX is not set
CONFIG_DEBUG_SET_MODULE_RONX=y
# CONFIG_DEBUG_NX_TEST is not set
CONFIG_DOUBLEFAULT=y
@@ -6982,8 +7305,11 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0
# CONFIG_DEBUG_BOOT_PARAMS is not set
# CONFIG_CPA_DEBUG is not set
# CONFIG_OPTIMIZE_INLINING is not set
+# CONFIG_DEBUG_ENTRY is not set
# CONFIG_DEBUG_NMI_SELFTEST is not set
# CONFIG_X86_DEBUG_STATIC_CPU_HAS is not set
+# CONFIG_X86_DEBUG_FPU is not set
+# CONFIG_PUNIT_ATOM_DEBUG is not set
#
# Security options
@@ -7003,12 +7329,10 @@ CONFIG_SECURITY_PATH=y
# CONFIG_SECURITY_TOMOYO is not set
# CONFIG_SECURITY_APPARMOR is not set
CONFIG_SECURITY_YAMA=y
-CONFIG_SECURITY_YAMA_STACKED=y
CONFIG_INTEGRITY=y
# CONFIG_INTEGRITY_SIGNATURE is not set
# CONFIG_IMA is not set
# CONFIG_EVM is not set
-# CONFIG_DEFAULT_SECURITY_YAMA is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_DEFAULT_SECURITY=""
CONFIG_XOR_BLOCKS=m
@@ -7032,14 +7356,19 @@ CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_AKCIPHER=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=m
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_PCRYPT=m
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CRYPTD=m
@@ -7054,7 +7383,9 @@ CONFIG_CRYPTO_GLUE_HELPER_X86=m
#
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
#
# Block modes
@@ -7066,6 +7397,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
#
# Hash modes
@@ -7085,6 +7417,8 @@ CONFIG_CRYPTO_CRC32_PCLMUL=m
CONFIG_CRYPTO_CRCT10DIF=y
CONFIG_CRYPTO_CRCT10DIF_PCLMUL=m
CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_POLY1305=m
+CONFIG_CRYPTO_POLY1305_X86_64=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
@@ -7129,6 +7463,8 @@ CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SALSA20=m
CONFIG_CRYPTO_SALSA20_X86_64=m
+CONFIG_CRYPTO_CHACHA20=m
+CONFIG_CRYPTO_CHACHA20_X86_64=m
CONFIG_CRYPTO_SEED=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m
@@ -7147,6 +7483,7 @@ CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
@@ -7154,11 +7491,17 @@ CONFIG_CRYPTO_LZ4HC=m
# Random Number Generation
#
CONFIG_CRYPTO_ANSI_CPRNG=m
-# CONFIG_CRYPTO_DRBG_MENU is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_HASH=y
+CONFIG_CRYPTO_DRBG_CTR=y
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
CONFIG_CRYPTO_USER_API=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_PADLOCK=m
@@ -7169,12 +7512,19 @@ CONFIG_CRYPTO_DEV_CCP_DD=m
CONFIG_CRYPTO_DEV_CCP_CRYPTO=m
CONFIG_CRYPTO_DEV_QAT=m
CONFIG_CRYPTO_DEV_QAT_DH895xCC=m
+CONFIG_CRYPTO_DEV_QAT_DH895xCCVF=m
CONFIG_ASYMMETRIC_KEY_TYPE=m
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
CONFIG_PUBLIC_KEY_ALGO_RSA=m
CONFIG_X509_CERTIFICATE_PARSER=m
CONFIG_PKCS7_MESSAGE_PARSER=m
CONFIG_PKCS7_TEST_KEY=m
+
+#
+# Certificates for signature checking
+#
+CONFIG_SYSTEM_TRUSTED_KEYRING=y
+CONFIG_SYSTEM_TRUSTED_KEYS=""
CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_IRQFD=y
@@ -7188,6 +7538,7 @@ CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
CONFIG_KVM_VFIO=y
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
CONFIG_KVM_COMPAT=y
+CONFIG_HAVE_KVM_IRQ_BYPASS=y
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_KVM_INTEL=m
@@ -7210,7 +7561,6 @@ CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_IO=y
-CONFIG_PERCPU_RWSEM=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
CONFIG_CRC_CCITT=m
@@ -7228,6 +7578,8 @@ CONFIG_LIBCRC32C=m
CONFIG_CRC8=m
# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_842_COMPRESS=m
+CONFIG_842_DECOMPRESS=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
@@ -7275,7 +7627,6 @@ CONFIG_GLOB=y
CONFIG_NLATTR=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_LRU_CACHE=m
-CONFIG_AVERAGE=y
CONFIG_CLZ_TAB=y
CONFIG_CORDIC=m
CONFIG_DDR=y
@@ -7296,4 +7647,7 @@ CONFIG_FONT_8x16=y
# CONFIG_FONT_SUN12x22 is not set
# CONFIG_FONT_10x18 is not set
CONFIG_FONT_AUTOSELECT=y
+# CONFIG_SG_SPLIT is not set
CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_PMEM_API=y
+CONFIG_ARCH_HAS_MMIO_FLUSH=y
diff --git a/libre/linux-libre-lts/patch-4.4-gnu-4.4.7-gnu.patch b/libre/linux-libre-lts/patch-4.4-gnu-4.4.7-gnu.patch
new file mode 100644
index 000000000..014dfa298
--- /dev/null
+++ b/libre/linux-libre-lts/patch-4.4-gnu-4.4.7-gnu.patch
@@ -0,0 +1,37457 @@
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arc/include/asm/bitops.h linux-libre-4.4.7-gnu/arch/arc/include/asm/bitops.h
+--- linux-libre-4.4-gnu/arch/arc/include/asm/bitops.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arc/include/asm/bitops.h 2016-04-12 12:09:26.000000000 -0400
+@@ -35,21 +35,6 @@ static inline void op##_bit(unsigned lon
+ \
+ m += nr >> 5; \
+ \
+- /* \
+- * ARC ISA micro-optimization: \
+- * \
+- * Instructions dealing with bitpos only consider lower 5 bits \
+- * e.g (x << 33) is handled like (x << 1) by ASL instruction \
+- * (mem pointer still needs adjustment to point to next word) \
+- * \
+- * Hence the masking to clamp @nr arg can be elided in general. \
+- * \
+- * However if @nr is a constant (above assumed in a register), \
+- * and greater than 31, gcc can optimize away (x << 33) to 0, \
+- * as overflow, given the 32-bit ISA. Thus masking needs to be \
+- * done for const @nr, but no code is generated due to gcc \
+- * const prop. \
+- */ \
+ nr &= 0x1f; \
+ \
+ __asm__ __volatile__( \
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arc/include/asm/io.h linux-libre-4.4.7-gnu/arch/arc/include/asm/io.h
+--- linux-libre-4.4-gnu/arch/arc/include/asm/io.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arc/include/asm/io.h 2016-04-12 12:09:26.000000000 -0400
+@@ -129,15 +129,23 @@ static inline void __raw_writel(u32 w, v
+ #define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); })
+
+ /*
+- * Relaxed API for drivers which can handle any ordering themselves
++ * Relaxed API for drivers which can handle barrier ordering themselves
++ *
++ * Also these are defined to perform little endian accesses.
++ * To provide the typical device register semantics of fixed endian,
++ * swap the byte order for Big Endian
++ *
++ * http://lkml.kernel.org/r/201603100845.30602.arnd@arndb.de
+ */
+ #define readb_relaxed(c) __raw_readb(c)
+-#define readw_relaxed(c) __raw_readw(c)
+-#define readl_relaxed(c) __raw_readl(c)
++#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
++ __raw_readw(c)); __r; })
++#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
++ __raw_readl(c)); __r; })
+
+ #define writeb_relaxed(v,c) __raw_writeb(v,c)
+-#define writew_relaxed(v,c) __raw_writew(v,c)
+-#define writel_relaxed(v,c) __raw_writel(v,c)
++#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
++#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)
+
+ #include <asm-generic/io.h>
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arc/include/asm/irqflags-arcv2.h linux-libre-4.4.7-gnu/arch/arc/include/asm/irqflags-arcv2.h
+--- linux-libre-4.4-gnu/arch/arc/include/asm/irqflags-arcv2.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arc/include/asm/irqflags-arcv2.h 2016-04-12 12:09:26.000000000 -0400
+@@ -22,6 +22,7 @@
+ #define AUX_IRQ_CTRL 0x00E
+ #define AUX_IRQ_ACT 0x043 /* Active Intr across all levels */
+ #define AUX_IRQ_LVL_PEND 0x200 /* Pending Intr across all levels */
++#define AUX_IRQ_HINT 0x201 /* For generating Soft Interrupts */
+ #define AUX_IRQ_PRIORITY 0x206
+ #define ICAUSE 0x40a
+ #define AUX_IRQ_SELECT 0x40b
+@@ -112,6 +113,16 @@ static inline int arch_irqs_disabled(voi
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+ }
+
++static inline void arc_softirq_trigger(int irq)
++{
++ write_aux_reg(AUX_IRQ_HINT, irq);
++}
++
++static inline void arc_softirq_clear(int irq)
++{
++ write_aux_reg(AUX_IRQ_HINT, 0);
++}
++
+ #else
+
+ .macro IRQ_DISABLE scratch
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arc/kernel/entry-arcv2.S linux-libre-4.4.7-gnu/arch/arc/kernel/entry-arcv2.S
+--- linux-libre-4.4-gnu/arch/arc/kernel/entry-arcv2.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arc/kernel/entry-arcv2.S 2016-04-12 12:09:26.000000000 -0400
+@@ -45,11 +45,12 @@ VECTOR reserved ; Reserved slots
+ VECTOR handle_interrupt ; (16) Timer0
+ VECTOR handle_interrupt ; unused (Timer1)
+ VECTOR handle_interrupt ; unused (WDT)
+-VECTOR handle_interrupt ; (19) ICI (inter core interrupt)
+-VECTOR handle_interrupt
+-VECTOR handle_interrupt
+-VECTOR handle_interrupt
+-VECTOR handle_interrupt ; (23) End of fixed IRQs
++VECTOR handle_interrupt ; (19) Inter core Interrupt (IPI)
++VECTOR handle_interrupt ; (20) perf Interrupt
++VECTOR handle_interrupt ; (21) Software Triggered Intr (Self IPI)
++VECTOR handle_interrupt ; unused
++VECTOR handle_interrupt ; (23) unused
++# End of fixed IRQs
+
+ .rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
+ VECTOR handle_interrupt
+@@ -211,7 +212,11 @@ debug_marker_syscall:
+ ; (since IRQ NOT allowed in DS in ARCv2, this can only happen if orig
+ ; entry was via Exception in DS which got preempted in kernel).
+ ;
+-; IRQ RTIE won't reliably restore DE bit and/or BTA, needs handling
++; IRQ RTIE won't reliably restore DE bit and/or BTA, needs workaround
++;
++; Solution is return from Intr w/o any delay slot quirks into a kernel trampoline
++; and from pure kernel mode return to delay slot which handles DS bit/BTA correctly
++
+ .Lintr_ret_to_delay_slot:
+ debug_marker_ds:
+
+@@ -222,18 +227,23 @@ debug_marker_ds:
+ ld r2, [sp, PT_ret]
+ ld r3, [sp, PT_status32]
+
++ ; STAT32 for Int return created from scratch
++ ; (No delay dlot, disable Further intr in trampoline)
++
+ bic r0, r3, STATUS_U_MASK|STATUS_DE_MASK|STATUS_IE_MASK|STATUS_L_MASK
+ st r0, [sp, PT_status32]
+
+ mov r1, .Lintr_ret_to_delay_slot_2
+ st r1, [sp, PT_ret]
+
++ ; Orig exception PC/STAT32 safekept @orig_r0 and @event stack slots
+ st r2, [sp, 0]
+ st r3, [sp, 4]
+
+ b .Lisr_ret_fast_path
+
+ .Lintr_ret_to_delay_slot_2:
++ ; Trampoline to restore orig exception PC/STAT32/BTA/AUX_USER_SP
+ sub sp, sp, SZ_PT_REGS
+ st r9, [sp, -4]
+
+@@ -243,11 +253,19 @@ debug_marker_ds:
+ ld r9, [sp, 4]
+ sr r9, [erstatus]
+
++ ; restore AUX_USER_SP if returning to U mode
++ bbit0 r9, STATUS_U_BIT, 1f
++ ld r9, [sp, PT_sp]
++ sr r9, [AUX_USER_SP]
++
++1:
+ ld r9, [sp, 8]
+ sr r9, [erbta]
+
+ ld r9, [sp, -4]
+ add sp, sp, SZ_PT_REGS
++
++ ; return from pure kernel mode to delay slot
+ rtie
+
+ END(ret_from_exception)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arc/kernel/mcip.c linux-libre-4.4.7-gnu/arch/arc/kernel/mcip.c
+--- linux-libre-4.4-gnu/arch/arc/kernel/mcip.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arc/kernel/mcip.c 2016-04-12 12:09:26.000000000 -0400
+@@ -11,9 +11,12 @@
+ #include <linux/smp.h>
+ #include <linux/irq.h>
+ #include <linux/spinlock.h>
++#include <asm/irqflags-arcv2.h>
+ #include <asm/mcip.h>
+ #include <asm/setup.h>
+
++#define SOFTIRQ_IRQ 21
++
+ static char smp_cpuinfo_buf[128];
+ static int idu_detected;
+
+@@ -22,6 +25,7 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
+ static void mcip_setup_per_cpu(int cpu)
+ {
+ smp_ipi_irq_setup(cpu, IPI_IRQ);
++ smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
+ }
+
+ static void mcip_ipi_send(int cpu)
+@@ -29,6 +33,12 @@ static void mcip_ipi_send(int cpu)
+ unsigned long flags;
+ int ipi_was_pending;
+
++ /* ARConnect can only send IPI to others */
++ if (unlikely(cpu == raw_smp_processor_id())) {
++ arc_softirq_trigger(SOFTIRQ_IRQ);
++ return;
++ }
++
+ /*
+ * NOTE: We must spin here if the other cpu hasn't yet
+ * serviced a previous message. This can burn lots
+@@ -63,6 +73,11 @@ static void mcip_ipi_clear(int irq)
+ unsigned long flags;
+ unsigned int __maybe_unused copy;
+
++ if (unlikely(irq == SOFTIRQ_IRQ)) {
++ arc_softirq_clear(irq);
++ return;
++ }
++
+ raw_spin_lock_irqsave(&mcip_lock, flags);
+
+ /* Who sent the IPI */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-388-gp.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-388-gp.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-388-gp.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-388-gp.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -303,16 +303,6 @@
+ gpio = <&expander0 4 GPIO_ACTIVE_HIGH>;
+ };
+
+- reg_usb2_1_vbus: v5-vbus1 {
+- compatible = "regulator-fixed";
+- regulator-name = "v5.0-vbus1";
+- regulator-min-microvolt = <5000000>;
+- regulator-max-microvolt = <5000000>;
+- enable-active-high;
+- regulator-always-on;
+- gpio = <&expander0 4 GPIO_ACTIVE_HIGH>;
+- };
+-
+ reg_sata0: pwr-sata0 {
+ compatible = "regulator-fixed";
+ regulator-name = "pwr_en_sata0";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -70,8 +70,8 @@
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ pcie-controller {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-db.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-db.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-db.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-db.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -76,8 +76,8 @@
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+ MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ devbus-bootcs {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-gp.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-gp.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-gp.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-gp.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -95,8 +95,8 @@
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+ MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ devbus-bootcs {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -65,8 +65,8 @@
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ pcie-controller {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -70,8 +70,8 @@
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ pcie-controller {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-matrix.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-matrix.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-matrix.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-matrix.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -68,8 +68,8 @@
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ internal-regs {
+ serial@12000 {
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -64,8 +64,8 @@
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ pcie-controller {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -65,9 +65,9 @@
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+- MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x01, 0x2f) 0 0 0xe8000000 0x8000000
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ devbus-bootcs {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -78,8 +78,8 @@
+ soc {
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+ MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+- MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
+- MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
++ MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
++ MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+
+ pcie-controller {
+ status = "okay";
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/at91-sama5d3_xplained.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -303,6 +303,7 @@
+ regulator-name = "mmc0-card-supply";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
+ };
+
+ gpio_keys {
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/at91-sama5d4ek.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/at91-sama5d4ek.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/at91-sama5d4ek.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/at91-sama5d4ek.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -160,8 +160,15 @@
+ };
+
+ macb0: ethernet@f8020000 {
++ pinctrl-0 = <&pinctrl_macb0_rmii &pinctrl_macb0_phy_irq>;
+ phy-mode = "rmii";
+ status = "okay";
++
++ ethernet-phy@1 {
++ reg = <0x1>;
++ interrupt-parent = <&pioE>;
++ interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
++ };
+ };
+
+ mmc1: mmc@fc000000 {
+@@ -193,6 +200,10 @@
+
+ pinctrl@fc06a000 {
+ board {
++ pinctrl_macb0_phy_irq: macb0_phy_irq {
++ atmel,pins =
++ <AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
++ };
+ pinctrl_mmc0_cd: mmc0_cd {
+ atmel,pins =
+ <AT91_PIOE 5 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/at91-sama5d4_xplained.dts linux-libre-4.4.7-gnu/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/at91-sama5d4_xplained.dts 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/at91-sama5d4_xplained.dts 2016-04-12 12:09:26.000000000 -0400
+@@ -86,10 +86,12 @@
+ macb0: ethernet@f8020000 {
+ phy-mode = "rmii";
+ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_macb0_rmii &pinctrl_macb0_phy_irq>;
+
+ phy0: ethernet-phy@1 {
+ interrupt-parent = <&pioE>;
+- interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
++ interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+ reg = <1>;
+ };
+ };
+@@ -152,6 +154,10 @@
+ atmel,pins =
+ <AT91_PIOE 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+ };
++ pinctrl_macb0_phy_irq: macb0_phy_irq_0 {
++ atmel,pins =
++ <AT91_PIOE 1 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
++ };
+ };
+ };
+ };
+@@ -262,5 +268,6 @@
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_reg>;
++ regulator-always-on;
+ };
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/dra7.dtsi linux-libre-4.4.7-gnu/arch/arm/boot/dts/dra7.dtsi
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/dra7.dtsi 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/dra7.dtsi 2016-04-12 12:09:26.000000000 -0400
+@@ -1497,6 +1497,16 @@
+ 0x48485200 0x2E00>;
+ #address-cells = <1>;
+ #size-cells = <1>;
++
++ /*
++ * Do not allow gating of cpsw clock as workaround
++ * for errata i877. Keeping internal clock disabled
++ * causes the device switching characteristics
++ * to degrade over time and eventually fail to meet
++ * the data manual delay time/skew specs.
++ */
++ ti,no-idle;
++
+ /*
+ * rx_thresh_pend
+ * rx_pend
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi linux-libre-4.4.7-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/logicpd-torpedo-som.dtsi 2016-04-12 12:09:26.000000000 -0400
+@@ -122,6 +122,7 @@
+ interrupt-parent = <&gpio5>;
+ interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; /* gpio 152 */
+ ref-clock-frequency = <26000000>;
++ tcxo-clock-frequency = <26000000>;
+ };
+ };
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/omap5-board-common.dtsi linux-libre-4.4.7-gnu/arch/arm/boot/dts/omap5-board-common.dtsi
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/omap5-board-common.dtsi 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/omap5-board-common.dtsi 2016-04-12 12:09:26.000000000 -0400
+@@ -130,6 +130,16 @@
+ };
+ };
+
++&gpio8 {
++ /* TI trees use GPIO instead of msecure, see also muxing */
++ p234 {
++ gpio-hog;
++ gpios = <10 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "gpio8_234/msecure";
++ };
++};
++
+ &omap5_pmx_core {
+ pinctrl-names = "default";
+ pinctrl-0 = <
+@@ -213,6 +223,13 @@
+ >;
+ };
+
++ /* TI trees use GPIO mode; msecure mode does not work reliably? */
++ palmas_msecure_pins: palmas_msecure_pins {
++ pinctrl-single,pins = <
++ OMAP5_IOPAD(0x180, PIN_OUTPUT | MUX_MODE6) /* gpio8_234 */
++ >;
++ };
++
+ usbhost_pins: pinmux_usbhost_pins {
+ pinctrl-single,pins = <
+ 0x84 (PIN_INPUT | MUX_MODE0) /* usbb2_hsic_strobe */
+@@ -278,6 +295,12 @@
+ &usbhost_wkup_pins
+ >;
+
++ palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
++ pinctrl-single,pins = <
++ OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0) /* sys_nirq1 */
++ >;
++ };
++
+ usbhost_wkup_pins: pinmux_usbhost_wkup_pins {
+ pinctrl-single,pins = <
+ 0x1A (PIN_OUTPUT | MUX_MODE0) /* fref_clk1_out, USB hub clk */
+@@ -345,6 +368,8 @@
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ ti,system-power-controller;
++ pinctrl-names = "default";
++ pinctrl-0 = <&palmas_sys_nirq_pins &palmas_msecure_pins>;
+
+ extcon_usb3: palmas_usb {
+ compatible = "ti,palmas-usb-vid";
+@@ -358,6 +383,14 @@
+ #clock-cells = <0>;
+ };
+
++ rtc {
++ compatible = "ti,palmas-rtc";
++ interrupt-parent = <&palmas>;
++ interrupts = <8 IRQ_TYPE_NONE>;
++ ti,backup-battery-chargeable;
++ ti,backup-battery-charge-high-current;
++ };
++
+ palmas_pmic {
+ compatible = "ti,palmas-pmic";
+ interrupt-parent = <&palmas>;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h linux-libre-4.4.7-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h 2016-04-12 12:09:26.000000000 -0400
+@@ -90,7 +90,7 @@
+ #define PIN_PA14__I2SC1_MCK PINMUX_PIN(PIN_PA14, 4, 2)
+ #define PIN_PA14__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA14, 5, 1)
+ #define PIN_PA14__D9 PINMUX_PIN(PIN_PA14, 6, 2)
+-#define PIN_PA15 14
++#define PIN_PA15 15
+ #define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0)
+ #define PIN_PA15__SPI0_MOSI PINMUX_PIN(PIN_PA15, 1, 1)
+ #define PIN_PA15__TF1 PINMUX_PIN(PIN_PA15, 2, 1)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/sama5d4.dtsi linux-libre-4.4.7-gnu/arch/arm/boot/dts/sama5d4.dtsi
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/sama5d4.dtsi 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/sama5d4.dtsi 2016-04-12 12:09:26.000000000 -0400
+@@ -1342,7 +1342,7 @@
+ dbgu: serial@fc069000 {
+ compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+ reg = <0xfc069000 0x200>;
+- interrupts = <2 IRQ_TYPE_LEVEL_HIGH 7>;
++ interrupts = <45 IRQ_TYPE_LEVEL_HIGH 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
+ clocks = <&dbgu_clk>;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi linux-libre-4.4.7-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
+--- linux-libre-4.4-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi 2016-04-12 12:09:26.000000000 -0400
+@@ -127,22 +127,14 @@
+ };
+ mmcsd_default_mode: mmcsd_default {
+ mmcsd_default_cfg1 {
+- /* MCCLK */
+- pins = "GPIO8_B10";
+- ste,output = <0>;
+- };
+- mmcsd_default_cfg2 {
+- /* MCCMDDIR, MCDAT0DIR, MCDAT31DIR, MCDATDIR2 */
+- pins = "GPIO10_C11", "GPIO15_A12",
+- "GPIO16_C13", "GPIO23_D15";
+- ste,output = <1>;
+- };
+- mmcsd_default_cfg3 {
+- /* MCCMD, MCDAT3-0, MCMSFBCLK */
+- pins = "GPIO9_A10", "GPIO11_B11",
+- "GPIO12_A11", "GPIO13_C12",
+- "GPIO14_B12", "GPIO24_C15";
+- ste,input = <1>;
++ /*
++ * MCCLK, MCCMDDIR, MCDAT0DIR, MCDAT31DIR, MCDATDIR2
++ * MCCMD, MCDAT3-0, MCMSFBCLK
++ */
++ pins = "GPIO8_B10", "GPIO9_A10", "GPIO10_C11", "GPIO11_B11",
++ "GPIO12_A11", "GPIO13_C12", "GPIO14_B12", "GPIO15_A12",
++ "GPIO16_C13", "GPIO23_D15", "GPIO24_C15";
++ ste,output = <2>;
+ };
+ };
+ };
+@@ -802,10 +794,21 @@
+ clock-names = "mclk", "apb_pclk";
+ interrupt-parent = <&vica>;
+ interrupts = <22>;
+- max-frequency = <48000000>;
++ max-frequency = <400000>;
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
++ full-pwr-cycle;
++ /*
++ * The STw4811 circuit used with the Nomadik strictly
++ * requires that all of these signal direction pins be
++ * routed and used for its 4-bit levelshifter.
++ */
++ st,sig-dir-dat0;
++ st,sig-dir-dat2;
++ st,sig-dir-dat31;
++ st,sig-dir-cmd;
++ st,sig-pin-fbclk;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>;
+ vmmc-supply = <&vmmc_regulator>;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/common/icst.c linux-libre-4.4.7-gnu/arch/arm/common/icst.c
+--- linux-libre-4.4-gnu/arch/arm/common/icst.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/common/icst.c 2016-04-12 12:09:26.000000000 -0400
+@@ -16,7 +16,7 @@
+ */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-
++#include <asm/div64.h>
+ #include <asm/hardware/icst.h>
+
+ /*
+@@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div);
+
+ unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco)
+ {
+- return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]);
++ u64 dividend = p->ref * 2 * (u64)(vco.v + 8);
++ u32 divisor = (vco.r + 2) * p->s2div[vco.s];
++
++ do_div(dividend, divisor);
++ return (unsigned long)dividend;
+ }
+
+ EXPORT_SYMBOL(icst_hz);
+@@ -58,6 +62,7 @@ icst_hz_to_vco(const struct icst_params
+
+ if (f > p->vco_min && f <= p->vco_max)
+ break;
++ i++;
+ } while (i < 8);
+
+ if (i >= 8)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/include/asm/psci.h linux-libre-4.4.7-gnu/arch/arm/include/asm/psci.h
+--- linux-libre-4.4-gnu/arch/arm/include/asm/psci.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/include/asm/psci.h 2016-04-12 12:09:26.000000000 -0400
+@@ -16,7 +16,7 @@
+
+ extern struct smp_operations psci_smp_ops;
+
+-#ifdef CONFIG_ARM_PSCI
++#if defined(CONFIG_SMP) && defined(CONFIG_ARM_PSCI)
+ bool psci_smp_available(void);
+ #else
+ static inline bool psci_smp_available(void) { return false; }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/include/asm/xen/page-coherent.h linux-libre-4.4.7-gnu/arch/arm/include/asm/xen/page-coherent.h
+--- linux-libre-4.4-gnu/arch/arm/include/asm/xen/page-coherent.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/include/asm/xen/page-coherent.h 2016-04-12 12:09:26.000000000 -0400
+@@ -35,14 +35,21 @@ static inline void xen_dma_map_page(stru
+ dma_addr_t dev_addr, unsigned long offset, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+ {
+- bool local = XEN_PFN_DOWN(dev_addr) == page_to_xen_pfn(page);
++ unsigned long page_pfn = page_to_xen_pfn(page);
++ unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
++ unsigned long compound_pages =
++ (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
++ bool local = (page_pfn <= dev_pfn) &&
++ (dev_pfn - page_pfn < compound_pages);
++
+ /*
+- * Dom0 is mapped 1:1, while the Linux page can be spanned accross
+- * multiple Xen page, it's not possible to have a mix of local and
+- * foreign Xen page. So if the first xen_pfn == mfn the page is local
+- * otherwise it's a foreign page grant-mapped in dom0. If the page is
+- * local we can safely call the native dma_ops function, otherwise we
+- * call the xen specific function.
++ * Dom0 is mapped 1:1, while the Linux page can span across
++ * multiple Xen pages, it's not possible for it to contain a
++ * mix of local and foreign Xen pages. So if the first xen_pfn
++ * == mfn the page is local otherwise it's a foreign page
++ * grant-mapped in dom0. If the page is local we can safely
++ * call the native dma_ops function, otherwise we call the xen
++ * specific function.
+ */
+ if (local)
+ __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/Kconfig.debug linux-libre-4.4.7-gnu/arch/arm/Kconfig.debug
+--- linux-libre-4.4-gnu/arch/arm/Kconfig.debug 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/Kconfig.debug 2016-04-12 12:09:26.000000000 -0400
+@@ -162,10 +162,9 @@ choice
+ mobile SoCs in the Kona family of chips (e.g. bcm28155,
+ bcm11351, etc...)
+
+- config DEBUG_BCM63XX
++ config DEBUG_BCM63XX_UART
+ bool "Kernel low-level debugging on BCM63XX UART"
+ depends on ARCH_BCM_63XX
+- select DEBUG_UART_BCM63XX
+
+ config DEBUG_BERLIN_UART
+ bool "Marvell Berlin SoC Debug UART"
+@@ -1348,7 +1347,7 @@ config DEBUG_LL_INCLUDE
+ default "debug/vf.S" if DEBUG_VF_UART
+ default "debug/vt8500.S" if DEBUG_VT8500_UART0
+ default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
+- default "debug/bcm63xx.S" if DEBUG_UART_BCM63XX
++ default "debug/bcm63xx.S" if DEBUG_BCM63XX_UART
+ default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0
+ default "mach/debug-macro.S"
+
+@@ -1364,10 +1363,6 @@ config DEBUG_UART_8250
+ ARCH_IOP33X || ARCH_IXP4XX || \
+ ARCH_LPC32XX || ARCH_MV78XX0 || ARCH_ORION5X || ARCH_RPC
+
+-# Compatibility options for BCM63xx
+-config DEBUG_UART_BCM63XX
+- def_bool ARCH_BCM_63XX
+-
+ config DEBUG_UART_PHYS
+ hex "Physical base address of debug UART"
+ default 0x00100a00 if DEBUG_NETX_UART
+@@ -1462,7 +1457,7 @@ config DEBUG_UART_PHYS
+ default 0xfffb0000 if DEBUG_OMAP1UART1 || DEBUG_OMAP7XXUART1
+ default 0xfffb0800 if DEBUG_OMAP1UART2 || DEBUG_OMAP7XXUART2
+ default 0xfffb9800 if DEBUG_OMAP1UART3 || DEBUG_OMAP7XXUART3
+- default 0xfffe8600 if DEBUG_UART_BCM63XX
++ default 0xfffe8600 if DEBUG_BCM63XX_UART
+ default 0xfffff700 if ARCH_IOP33X
+ depends on ARCH_EP93XX || \
+ DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
+@@ -1474,7 +1469,7 @@ config DEBUG_UART_PHYS
+ DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
+ DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
+ DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
+- DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
++ DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
+ DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
+ DEBUG_AT91_UART
+
+@@ -1515,7 +1510,7 @@ config DEBUG_UART_VIRT
+ default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT
+ default 0xfc40ab00 if DEBUG_BRCMSTB_UART
+ default 0xfc705000 if DEBUG_ZTE_ZX
+- default 0xfcfe8600 if DEBUG_UART_BCM63XX
++ default 0xfcfe8600 if DEBUG_BCM63XX_UART
+ default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
+ default 0xfd000000 if ARCH_SPEAR13XX
+ default 0xfd012000 if ARCH_MV78XX0
+@@ -1566,7 +1561,7 @@ config DEBUG_UART_VIRT
+ DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
+ DEBUG_NETX_UART || \
+ DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
+- DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
++ DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
+ DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0
+
+ config DEBUG_UART_8250_SHIFT
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/kvm/guest.c linux-libre-4.4.7-gnu/arch/arm/kvm/guest.c
+--- linux-libre-4.4-gnu/arch/arm/kvm/guest.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/kvm/guest.c 2016-04-12 12:09:26.000000000 -0400
+@@ -155,7 +155,7 @@ static int get_timer_reg(struct kvm_vcpu
+ u64 val;
+
+ val = kvm_arm_timer_get_reg(vcpu, reg->id);
+- return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
++ return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
+ }
+
+ static unsigned long num_core_regs(void)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/mach-omap2/gpmc-onenand.c linux-libre-4.4.7-gnu/arch/arm/mach-omap2/gpmc-onenand.c
+--- linux-libre-4.4-gnu/arch/arm/mach-omap2/gpmc-onenand.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/mach-omap2/gpmc-onenand.c 2016-04-12 12:09:26.000000000 -0400
+@@ -101,10 +101,8 @@ static void omap2_onenand_set_async_mode
+
+ static void set_onenand_cfg(void __iomem *onenand_base)
+ {
+- u32 reg;
++ u32 reg = ONENAND_SYS_CFG1_RDY | ONENAND_SYS_CFG1_INT;
+
+- reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
+- reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
+ reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
+ ONENAND_SYS_CFG1_BL_16;
+ if (onenand_flags & ONENAND_FLAG_SYNCREAD)
+@@ -123,6 +121,7 @@ static void set_onenand_cfg(void __iomem
+ reg |= ONENAND_SYS_CFG1_VHF;
+ else
+ reg &= ~ONENAND_SYS_CFG1_VHF;
++
+ writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+ }
+
+@@ -289,6 +288,7 @@ static int omap2_onenand_setup_async(voi
+ }
+ }
+
++ onenand_async.sync_write = true;
+ omap2_onenand_calc_async_timings(&t);
+
+ ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/mach-omap2/omap_hwmod.c linux-libre-4.4.7-gnu/arch/arm/mach-omap2/omap_hwmod.c
+--- linux-libre-4.4-gnu/arch/arm/mach-omap2/omap_hwmod.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/mach-omap2/omap_hwmod.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2200,6 +2200,11 @@ static int _enable(struct omap_hwmod *oh
+ */
+ static int _idle(struct omap_hwmod *oh)
+ {
++ if (oh->flags & HWMOD_NO_IDLE) {
++ oh->_int_flags |= _HWMOD_SKIP_ENABLE;
++ return 0;
++ }
++
+ pr_debug("omap_hwmod: %s: idling\n", oh->name);
+
+ if (oh->_state != _HWMOD_STATE_ENABLED) {
+@@ -2504,6 +2509,8 @@ static int __init _init(struct omap_hwmo
+ oh->flags |= HWMOD_INIT_NO_RESET;
+ if (of_find_property(np, "ti,no-idle-on-init", NULL))
+ oh->flags |= HWMOD_INIT_NO_IDLE;
++ if (of_find_property(np, "ti,no-idle", NULL))
++ oh->flags |= HWMOD_NO_IDLE;
+ }
+
+ oh->_state = _HWMOD_STATE_INITIALIZED;
+@@ -2630,7 +2637,7 @@ static void __init _setup_postsetup(stru
+ * XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
+ * it should be set by the core code as a runtime flag during startup
+ */
+- if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
++ if ((oh->flags & (HWMOD_INIT_NO_IDLE | HWMOD_NO_IDLE)) &&
+ (postsetup_state == _HWMOD_STATE_IDLE)) {
+ oh->_int_flags |= _HWMOD_SKIP_ENABLE;
+ postsetup_state = _HWMOD_STATE_ENABLED;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/mach-omap2/omap_hwmod.h linux-libre-4.4.7-gnu/arch/arm/mach-omap2/omap_hwmod.h
+--- linux-libre-4.4-gnu/arch/arm/mach-omap2/omap_hwmod.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/mach-omap2/omap_hwmod.h 2016-04-12 12:09:26.000000000 -0400
+@@ -525,6 +525,8 @@ struct omap_hwmod_omap4_prcm {
+ * or idled.
+ * HWMOD_OPT_CLKS_NEEDED: The optional clocks are needed for the module to
+ * operate and they need to be handled at the same time as the main_clk.
++ * HWMOD_NO_IDLE: Do not idle the hwmod at all. Useful to handle certain
++ * IPs like CPSW on DRA7, where clocks to this module cannot be disabled.
+ */
+ #define HWMOD_SWSUP_SIDLE (1 << 0)
+ #define HWMOD_SWSUP_MSTANDBY (1 << 1)
+@@ -541,6 +543,7 @@ struct omap_hwmod_omap4_prcm {
+ #define HWMOD_SWSUP_SIDLE_ACT (1 << 12)
+ #define HWMOD_RECONFIG_IO_CHAIN (1 << 13)
+ #define HWMOD_OPT_CLKS_NEEDED (1 << 14)
++#define HWMOD_NO_IDLE (1 << 15)
+
+ /*
+ * omap_hwmod._int_flags definitions
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/mach-omap2/sleep34xx.S linux-libre-4.4.7-gnu/arch/arm/mach-omap2/sleep34xx.S
+--- linux-libre-4.4-gnu/arch/arm/mach-omap2/sleep34xx.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/mach-omap2/sleep34xx.S 2016-04-12 12:09:26.000000000 -0400
+@@ -86,13 +86,18 @@ ENTRY(enable_omap3630_toggle_l2_on_resto
+ stmfd sp!, {lr} @ save registers on stack
+ /* Setup so that we will disable and enable l2 */
+ mov r1, #0x1
+- adrl r2, l2dis_3630 @ may be too distant for plain adr
+- str r1, [r2]
++ adrl r3, l2dis_3630_offset @ may be too distant for plain adr
++ ldr r2, [r3] @ value for offset
++ str r1, [r2, r3] @ write to l2dis_3630
+ ldmfd sp!, {pc} @ restore regs and return
+ ENDPROC(enable_omap3630_toggle_l2_on_restore)
+
+- .text
+-/* Function to call rom code to save secure ram context */
++/*
++ * Function to call rom code to save secure ram context. This gets
++ * relocated to SRAM, so it can be all in .data section. Otherwise
++ * we need to initialize api_params separately.
++ */
++ .data
+ .align 3
+ ENTRY(save_secure_ram_context)
+ stmfd sp!, {r4 - r11, lr} @ save registers on stack
+@@ -126,6 +131,8 @@ ENDPROC(save_secure_ram_context)
+ ENTRY(save_secure_ram_context_sz)
+ .word . - save_secure_ram_context
+
++ .text
++
+ /*
+ * ======================
+ * == Idle entry point ==
+@@ -289,12 +296,6 @@ wait_sdrc_ready:
+ bic r5, r5, #0x40
+ str r5, [r4]
+
+-/*
+- * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+- * base instead.
+- * Be careful not to clobber r7 when maintaing this code.
+- */
+-
+ is_dll_in_lock_mode:
+ /* Is dll in lock mode? */
+ ldr r4, sdrc_dlla_ctrl
+@@ -302,11 +303,7 @@ is_dll_in_lock_mode:
+ tst r5, #0x4
+ bne exit_nonoff_modes @ Return if locked
+ /* wait till dll locks */
+- adr r7, kick_counter
+ wait_dll_lock_timed:
+- ldr r4, wait_dll_lock_counter
+- add r4, r4, #1
+- str r4, [r7, #wait_dll_lock_counter - kick_counter]
+ ldr r4, sdrc_dlla_status
+ /* Wait 20uS for lock */
+ mov r6, #8
+@@ -330,9 +327,6 @@ kick_dll:
+ orr r6, r6, #(1<<3) @ enable dll
+ str r6, [r4]
+ dsb
+- ldr r4, kick_counter
+- add r4, r4, #1
+- str r4, [r7] @ kick_counter
+ b wait_dll_lock_timed
+
+ exit_nonoff_modes:
+@@ -360,15 +354,6 @@ sdrc_dlla_status:
+ .word SDRC_DLLA_STATUS_V
+ sdrc_dlla_ctrl:
+ .word SDRC_DLLA_CTRL_V
+- /*
+- * When exporting to userspace while the counters are in SRAM,
+- * these 2 words need to be at the end to facilitate retrival!
+- */
+-kick_counter:
+- .word 0
+-wait_dll_lock_counter:
+- .word 0
+-
+ ENTRY(omap3_do_wfi_sz)
+ .word . - omap3_do_wfi
+
+@@ -437,7 +422,9 @@ ENTRY(omap3_restore)
+ cmp r2, #0x0 @ Check if target power state was OFF or RET
+ bne logic_l1_restore
+
+- ldr r0, l2dis_3630
++ adr r1, l2dis_3630_offset @ address for offset
++ ldr r0, [r1] @ value for offset
++ ldr r0, [r1, r0] @ value at l2dis_3630
+ cmp r0, #0x1 @ should we disable L2 on 3630?
+ bne skipl2dis
+ mrc p15, 0, r0, c1, c0, 1
+@@ -449,12 +436,14 @@ skipl2dis:
+ and r1, #0x700
+ cmp r1, #0x300
+ beq l2_inv_gp
++ adr r0, l2_inv_api_params_offset
++ ldr r3, [r0]
++ add r3, r3, r0 @ r3 points to dummy parameters
+ mov r0, #40 @ set service ID for PPA
+ mov r12, r0 @ copy secure Service ID in r12
+ mov r1, #0 @ set task id for ROM code in r1
+ mov r2, #4 @ set some flags in r2, r6
+ mov r6, #0xff
+- adr r3, l2_inv_api_params @ r3 points to dummy parameters
+ dsb @ data write barrier
+ dmb @ data memory barrier
+ smc #1 @ call SMI monitor (smi #1)
+@@ -488,8 +477,8 @@ skipl2dis:
+ b logic_l1_restore
+
+ .align
+-l2_inv_api_params:
+- .word 0x1, 0x00
++l2_inv_api_params_offset:
++ .long l2_inv_api_params - .
+ l2_inv_gp:
+ /* Execute smi to invalidate L2 cache */
+ mov r12, #0x1 @ set up to invalidate L2
+@@ -506,7 +495,9 @@ l2_inv_gp:
+ mov r12, #0x2
+ smc #0 @ Call SMI monitor (smieq)
+ logic_l1_restore:
+- ldr r1, l2dis_3630
++ adr r0, l2dis_3630_offset @ adress for offset
++ ldr r1, [r0] @ value for offset
++ ldr r1, [r0, r1] @ value at l2dis_3630
+ cmp r1, #0x1 @ Test if L2 re-enable needed on 3630
+ bne skipl2reen
+ mrc p15, 0, r1, c1, c0, 1
+@@ -535,9 +526,17 @@ control_stat:
+ .word CONTROL_STAT
+ control_mem_rta:
+ .word CONTROL_MEM_RTA_CTRL
++l2dis_3630_offset:
++ .long l2dis_3630 - .
++
++ .data
+ l2dis_3630:
+ .word 0
+
++ .data
++l2_inv_api_params:
++ .word 0x1, 0x00
++
+ /*
+ * Internal functions
+ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/mach-omap2/sleep44xx.S linux-libre-4.4.7-gnu/arch/arm/mach-omap2/sleep44xx.S
+--- linux-libre-4.4-gnu/arch/arm/mach-omap2/sleep44xx.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/mach-omap2/sleep44xx.S 2016-04-12 12:09:26.000000000 -0400
+@@ -29,12 +29,6 @@
+ dsb
+ .endm
+
+-ppa_zero_params:
+- .word 0x0
+-
+-ppa_por_params:
+- .word 1, 0
+-
+ #ifdef CONFIG_ARCH_OMAP4
+
+ /*
+@@ -266,7 +260,9 @@ ENTRY(omap4_cpu_resume)
+ beq skip_ns_smp_enable
+ ppa_actrl_retry:
+ mov r0, #OMAP4_PPA_CPU_ACTRL_SMP_INDEX
+- adr r3, ppa_zero_params @ Pointer to parameters
++ adr r1, ppa_zero_params_offset
++ ldr r3, [r1]
++ add r3, r3, r1 @ Pointer to ppa_zero_params
+ mov r1, #0x0 @ Process ID
+ mov r2, #0x4 @ Flag
+ mov r6, #0xff
+@@ -303,7 +299,9 @@ skip_ns_smp_enable:
+ ldr r0, =OMAP4_PPA_L2_POR_INDEX
+ ldr r1, =OMAP44XX_SAR_RAM_BASE
+ ldr r4, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
+- adr r3, ppa_por_params
++ adr r1, ppa_por_params_offset
++ ldr r3, [r1]
++ add r3, r3, r1 @ Pointer to ppa_por_params
+ str r4, [r3, #0x04]
+ mov r1, #0x0 @ Process ID
+ mov r2, #0x4 @ Flag
+@@ -328,6 +326,8 @@ skip_l2en:
+ #endif
+
+ b cpu_resume @ Jump to generic resume
++ppa_por_params_offset:
++ .long ppa_por_params - .
+ ENDPROC(omap4_cpu_resume)
+ #endif /* CONFIG_ARCH_OMAP4 */
+
+@@ -380,4 +380,13 @@ ENTRY(omap_do_wfi)
+ nop
+
+ ldmfd sp!, {pc}
++ppa_zero_params_offset:
++ .long ppa_zero_params - .
+ ENDPROC(omap_do_wfi)
++
++ .data
++ppa_zero_params:
++ .word 0
++
++ppa_por_params:
++ .word 1, 0
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/mach-s3c64xx/dev-audio.c linux-libre-4.4.7-gnu/arch/arm/mach-s3c64xx/dev-audio.c
+--- linux-libre-4.4-gnu/arch/arm/mach-s3c64xx/dev-audio.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/mach-s3c64xx/dev-audio.c 2016-04-12 12:09:26.000000000 -0400
+@@ -54,12 +54,12 @@ static int s3c64xx_i2s_cfg_gpio(struct p
+
+ static struct resource s3c64xx_iis0_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256),
+- [1] = DEFINE_RES_DMA(DMACH_I2S0_OUT),
+- [2] = DEFINE_RES_DMA(DMACH_I2S0_IN),
+ };
+
+-static struct s3c_audio_pdata i2sv3_pdata = {
++static struct s3c_audio_pdata i2s0_pdata = {
+ .cfg_gpio = s3c64xx_i2s_cfg_gpio,
++ .dma_playback = DMACH_I2S0_OUT,
++ .dma_capture = DMACH_I2S0_IN,
+ };
+
+ struct platform_device s3c64xx_device_iis0 = {
+@@ -68,15 +68,19 @@ struct platform_device s3c64xx_device_ii
+ .num_resources = ARRAY_SIZE(s3c64xx_iis0_resource),
+ .resource = s3c64xx_iis0_resource,
+ .dev = {
+- .platform_data = &i2sv3_pdata,
++ .platform_data = &i2s0_pdata,
+ },
+ };
+ EXPORT_SYMBOL(s3c64xx_device_iis0);
+
+ static struct resource s3c64xx_iis1_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256),
+- [1] = DEFINE_RES_DMA(DMACH_I2S1_OUT),
+- [2] = DEFINE_RES_DMA(DMACH_I2S1_IN),
++};
++
++static struct s3c_audio_pdata i2s1_pdata = {
++ .cfg_gpio = s3c64xx_i2s_cfg_gpio,
++ .dma_playback = DMACH_I2S1_OUT,
++ .dma_capture = DMACH_I2S1_IN,
+ };
+
+ struct platform_device s3c64xx_device_iis1 = {
+@@ -85,19 +89,19 @@ struct platform_device s3c64xx_device_ii
+ .num_resources = ARRAY_SIZE(s3c64xx_iis1_resource),
+ .resource = s3c64xx_iis1_resource,
+ .dev = {
+- .platform_data = &i2sv3_pdata,
++ .platform_data = &i2s1_pdata,
+ },
+ };
+ EXPORT_SYMBOL(s3c64xx_device_iis1);
+
+ static struct resource s3c64xx_iisv4_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256),
+- [1] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_TX),
+- [2] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_RX),
+ };
+
+ static struct s3c_audio_pdata i2sv4_pdata = {
+ .cfg_gpio = s3c64xx_i2s_cfg_gpio,
++ .dma_playback = DMACH_HSI_I2SV40_TX,
++ .dma_capture = DMACH_HSI_I2SV40_RX,
+ .type = {
+ .i2s = {
+ .quirks = QUIRK_PRI_6CHAN,
+@@ -142,12 +146,12 @@ static int s3c64xx_pcm_cfg_gpio(struct p
+
+ static struct resource s3c64xx_pcm0_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256),
+- [1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
+- [2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
+ };
+
+ static struct s3c_audio_pdata s3c_pcm0_pdata = {
+ .cfg_gpio = s3c64xx_pcm_cfg_gpio,
++ .dma_capture = DMACH_PCM0_RX,
++ .dma_playback = DMACH_PCM0_TX,
+ };
+
+ struct platform_device s3c64xx_device_pcm0 = {
+@@ -163,12 +167,12 @@ EXPORT_SYMBOL(s3c64xx_device_pcm0);
+
+ static struct resource s3c64xx_pcm1_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256),
+- [1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
+- [2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
+ };
+
+ static struct s3c_audio_pdata s3c_pcm1_pdata = {
+ .cfg_gpio = s3c64xx_pcm_cfg_gpio,
++ .dma_playback = DMACH_PCM1_TX,
++ .dma_capture = DMACH_PCM1_RX,
+ };
+
+ struct platform_device s3c64xx_device_pcm1 = {
+@@ -196,13 +200,14 @@ static int s3c64xx_ac97_cfg_gpe(struct p
+
+ static struct resource s3c64xx_ac97_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256),
+- [1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
+- [2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
+- [3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
+- [4] = DEFINE_RES_IRQ(IRQ_AC97),
++ [1] = DEFINE_RES_IRQ(IRQ_AC97),
+ };
+
+-static struct s3c_audio_pdata s3c_ac97_pdata;
++static struct s3c_audio_pdata s3c_ac97_pdata = {
++ .dma_playback = DMACH_AC97_PCMOUT,
++ .dma_capture = DMACH_AC97_PCMIN,
++ .dma_capture_mic = DMACH_AC97_MICIN,
++};
+
+ static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h linux-libre-4.4.7-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h
+--- linux-libre-4.4-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/mach-s3c64xx/include/mach/dma.h 2016-04-12 12:09:26.000000000 -0400
+@@ -14,38 +14,38 @@
+ #define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
+
+ /* DMA0/SDMA0 */
+-#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
+-#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
+-#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
+-#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
+-#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
+-#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
+-#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
+-#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
+-#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
+-#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
+-#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
+-#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
++#define DMACH_UART0 "uart0_tx"
++#define DMACH_UART0_SRC2 "uart0_rx"
++#define DMACH_UART1 "uart1_tx"
++#define DMACH_UART1_SRC2 "uart1_rx"
++#define DMACH_UART2 "uart2_tx"
++#define DMACH_UART2_SRC2 "uart2_rx"
++#define DMACH_UART3 "uart3_tx"
++#define DMACH_UART3_SRC2 "uart3_rx"
++#define DMACH_PCM0_TX "pcm0_tx"
++#define DMACH_PCM0_RX "pcm0_rx"
++#define DMACH_I2S0_OUT "i2s0_tx"
++#define DMACH_I2S0_IN "i2s0_rx"
+ #define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
+ #define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
+-#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
+-#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
++#define DMACH_HSI_I2SV40_TX "i2s2_tx"
++#define DMACH_HSI_I2SV40_RX "i2s2_rx"
+
+ /* DMA1/SDMA1 */
+-#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
+-#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
+-#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
+-#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
++#define DMACH_PCM1_TX "pcm1_tx"
++#define DMACH_PCM1_RX "pcm1_rx"
++#define DMACH_I2S1_OUT "i2s1_tx"
++#define DMACH_I2S1_IN "i2s1_rx"
+ #define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
+ #define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
+-#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
+-#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
+-#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
+-#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
+-#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
+-#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
+-#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
+-#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
++#define DMACH_AC97_PCMOUT "ac97_out"
++#define DMACH_AC97_PCMIN "ac97_in"
++#define DMACH_AC97_MICIN "ac97_mic"
++#define DMACH_PWM "pwm"
++#define DMACH_IRDA "irda"
++#define DMACH_EXTERNAL "external"
++#define DMACH_SECURITY_RX "sec_rx"
++#define DMACH_SECURITY_TX "sec_tx"
+
+ enum dma_ch {
+ DMACH_MAX = 32
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm/plat-samsung/devs.c linux-libre-4.4.7-gnu/arch/arm/plat-samsung/devs.c
+--- linux-libre-4.4-gnu/arch/arm/plat-samsung/devs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm/plat-samsung/devs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -65,6 +65,7 @@
+ #include <linux/platform_data/usb-ohci-s3c2410.h>
+ #include <plat/usb-phy.h>
+ #include <plat/regs-spi.h>
++#include <linux/platform_data/asoc-s3c.h>
+ #include <linux/platform_data/spi-s3c64xx.h>
+
+ static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+@@ -74,9 +75,12 @@ static u64 samsung_device_dma_mask = DMA
+ static struct resource s3c_ac97_resource[] = {
+ [0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
+ [1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
+- [2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
+- [3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
+- [4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
++};
++
++static struct s3c_audio_pdata s3c_ac97_pdata = {
++ .dma_playback = (void *)DMACH_PCM_OUT,
++ .dma_capture = (void *)DMACH_PCM_IN,
++ .dma_capture_mic = (void *)DMACH_MIC_IN,
+ };
+
+ struct platform_device s3c_device_ac97 = {
+@@ -87,6 +91,7 @@ struct platform_device s3c_device_ac97 =
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
++ .platform_data = &s3c_ac97_pdata,
+ }
+ };
+ #endif /* CONFIG_CPU_S3C2440 */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/include/asm/pgtable.h linux-libre-4.4.7-gnu/arch/arm64/include/asm/pgtable.h
+--- linux-libre-4.4-gnu/arch/arm64/include/asm/pgtable.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/include/asm/pgtable.h 2016-04-12 12:09:26.000000000 -0400
+@@ -34,7 +34,7 @@
+ /*
+ * VMALLOC and SPARSEMEM_VMEMMAP ranges.
+ *
+- * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
++ * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
+ * (rounded up to PUD_SIZE).
+ * VMALLOC_START: beginning of the kernel VA space
+ * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
+@@ -51,7 +51,9 @@
+
+ #define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
+
+-#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K))
++#define VMEMMAP_START (VMALLOC_END + SZ_64K)
++#define vmemmap ((struct page *)VMEMMAP_START - \
++ SECTION_ALIGN_DOWN(memstart_addr >> PAGE_SHIFT))
+
+ #define FIRST_USER_ADDRESS 0UL
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/kernel/head.S linux-libre-4.4.7-gnu/arch/arm64/kernel/head.S
+--- linux-libre-4.4-gnu/arch/arm64/kernel/head.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/kernel/head.S 2016-04-12 12:09:26.000000000 -0400
+@@ -512,9 +512,14 @@ CPU_LE( movk x0, #0x30d0, lsl #16 ) // C
+ #endif
+
+ /* EL2 debug */
++ mrs x0, id_aa64dfr0_el1 // Check ID_AA64DFR0_EL1 PMUVer
++ sbfx x0, x0, #8, #4
++ cmp x0, #1
++ b.lt 4f // Skip if no PMU present
+ mrs x0, pmcr_el0 // Disable debug access traps
+ ubfx x0, x0, #11, #5 // to EL2 and allow access to
+ msr mdcr_el2, x0 // all PMU counters from EL1
++4:
+
+ /* Stage-2 translation */
+ msr vttbr_el2, xzr
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/kernel/perf_event.c linux-libre-4.4.7-gnu/arch/arm64/kernel/perf_event.c
+--- linux-libre-4.4-gnu/arch/arm64/kernel/perf_event.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/kernel/perf_event.c 2016-04-12 12:09:26.000000000 -0400
+@@ -574,9 +574,6 @@ static void armv8pmu_reset(void *info)
+
+ /* Initialize & Reset PMNC: C and P bits. */
+ armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C);
+-
+- /* Disable access from userspace. */
+- asm volatile("msr pmuserenr_el0, %0" :: "r" (0));
+ }
+
+ static int armv8_pmuv3_map_event(struct perf_event *event)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/kernel/ptrace.c linux-libre-4.4.7-gnu/arch/arm64/kernel/ptrace.c
+--- linux-libre-4.4-gnu/arch/arm64/kernel/ptrace.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/kernel/ptrace.c 2016-04-12 12:09:26.000000000 -0400
+@@ -58,6 +58,12 @@
+ */
+ void ptrace_disable(struct task_struct *child)
+ {
++ /*
++ * This would be better off in core code, but PTRACE_DETACH has
++ * grown its fair share of arch-specific worts and changing it
++ * is likely to cause regressions on obscure architectures.
++ */
++ user_disable_single_step(child);
+ }
+
+ #ifdef CONFIG_HAVE_HW_BREAKPOINT
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/kvm/guest.c linux-libre-4.4.7-gnu/arch/arm64/kvm/guest.c
+--- linux-libre-4.4-gnu/arch/arm64/kvm/guest.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/kvm/guest.c 2016-04-12 12:09:26.000000000 -0400
+@@ -186,7 +186,7 @@ static int get_timer_reg(struct kvm_vcpu
+ u64 val;
+
+ val = kvm_arm_timer_get_reg(vcpu, reg->id);
+- return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
++ return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/Makefile linux-libre-4.4.7-gnu/arch/arm64/Makefile
+--- linux-libre-4.4-gnu/arch/arm64/Makefile 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/Makefile 2016-04-12 12:09:26.000000000 -0400
+@@ -27,6 +27,7 @@ $(warning LSE atomics not supported by b
+ endif
+
+ KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr)
++KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads)
+ KBUILD_AFLAGS += $(lseinstr)
+
+ ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/mm/dma-mapping.c linux-libre-4.4.7-gnu/arch/arm64/mm/dma-mapping.c
+--- linux-libre-4.4-gnu/arch/arm64/mm/dma-mapping.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/mm/dma-mapping.c 2016-04-12 12:09:26.000000000 -0400
+@@ -933,6 +933,10 @@ static int __init __iommu_dma_init(void)
+ ret = register_iommu_dma_ops_notifier(&platform_bus_type);
+ if (!ret)
+ ret = register_iommu_dma_ops_notifier(&amba_bustype);
++
++ /* handle devices queued before this arch_initcall */
++ if (!ret)
++ __iommu_attach_notifier(NULL, BUS_NOTIFY_ADD_DEVICE, NULL);
+ return ret;
+ }
+ arch_initcall(__iommu_dma_init);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/mm/init.c linux-libre-4.4.7-gnu/arch/arm64/mm/init.c
+--- linux-libre-4.4-gnu/arch/arm64/mm/init.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/mm/init.c 2016-04-12 12:09:26.000000000 -0400
+@@ -319,8 +319,8 @@ void __init mem_init(void)
+ #endif
+ MLG(VMALLOC_START, VMALLOC_END),
+ #ifdef CONFIG_SPARSEMEM_VMEMMAP
+- MLG((unsigned long)vmemmap,
+- (unsigned long)vmemmap + VMEMMAP_SIZE),
++ MLG(VMEMMAP_START,
++ VMEMMAP_START + VMEMMAP_SIZE),
+ MLM((unsigned long)virt_to_page(PAGE_OFFSET),
+ (unsigned long)virt_to_page(high_memory)),
+ #endif
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/mm/mmu.c linux-libre-4.4.7-gnu/arch/arm64/mm/mmu.c
+--- linux-libre-4.4-gnu/arch/arm64/mm/mmu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/mm/mmu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -456,6 +456,9 @@ void __init paging_init(void)
+
+ empty_zero_page = virt_to_page(zero_page);
+
++ /* Ensure the zero page is visible to the page table walker */
++ dsb(ishst);
++
+ /*
+ * TTBR0 is only used for the identity mapping at this stage. Make it
+ * point to zero page to avoid speculatively fetching new entries.
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/mm/pageattr.c linux-libre-4.4.7-gnu/arch/arm64/mm/pageattr.c
+--- linux-libre-4.4-gnu/arch/arm64/mm/pageattr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/mm/pageattr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -57,6 +57,9 @@ static int change_memory_common(unsigned
+ if (end < MODULES_VADDR || end >= MODULES_END)
+ return -EINVAL;
+
++ if (!numpages)
++ return 0;
++
+ data.set_mask = set_mask;
+ data.clear_mask = clear_mask;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/mm/proc-macros.S linux-libre-4.4.7-gnu/arch/arm64/mm/proc-macros.S
+--- linux-libre-4.4-gnu/arch/arm64/mm/proc-macros.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/mm/proc-macros.S 2016-04-12 12:09:26.000000000 -0400
+@@ -62,3 +62,15 @@
+ bfi \valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
+ #endif
+ .endm
++
++/*
++ * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
++ */
++ .macro reset_pmuserenr_el0, tmpreg
++ mrs \tmpreg, id_aa64dfr0_el1 // Check ID_AA64DFR0_EL1 PMUVer
++ sbfx \tmpreg, \tmpreg, #8, #4
++ cmp \tmpreg, #1 // Skip if no PMU present
++ b.lt 9000f
++ msr pmuserenr_el0, xzr // Disable PMU access from EL0
++9000:
++ .endm
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/arm64/mm/proc.S linux-libre-4.4.7-gnu/arch/arm64/mm/proc.S
+--- linux-libre-4.4-gnu/arch/arm64/mm/proc.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/arm64/mm/proc.S 2016-04-12 12:09:26.000000000 -0400
+@@ -117,6 +117,7 @@ ENTRY(cpu_do_resume)
+ */
+ ubfx x11, x11, #1, #1
+ msr oslar_el1, x11
++ reset_pmuserenr_el0 x0 // Disable PMU access from EL0
+ mov x0, x12
+ dsb nsh // Make sure local tlb invalidation completed
+ isb
+@@ -155,6 +156,7 @@ ENTRY(__cpu_setup)
+ msr cpacr_el1, x0 // Enable FP/ASIMD
+ mov x0, #1 << 12 // Reset mdscr_el1 and disable
+ msr mdscr_el1, x0 // access to the DCC from EL0
++ reset_pmuserenr_el0 x0 // Disable PMU access from EL0
+ /*
+ * Memory region attributes for LPAE:
+ *
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/ia64/include/asm/io.h linux-libre-4.4.7-gnu/arch/ia64/include/asm/io.h
+--- linux-libre-4.4-gnu/arch/ia64/include/asm/io.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/ia64/include/asm/io.h 2016-04-12 12:09:26.000000000 -0400
+@@ -436,6 +436,7 @@ static inline void __iomem * ioremap_cac
+ return ioremap(phys_addr, size);
+ }
+ #define ioremap_cache ioremap_cache
++#define ioremap_uc ioremap_nocache
+
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/m32r/kernel/setup.c linux-libre-4.4.7-gnu/arch/m32r/kernel/setup.c
+--- linux-libre-4.4-gnu/arch/m32r/kernel/setup.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/m32r/kernel/setup.c 2016-04-12 12:09:26.000000000 -0400
+@@ -81,7 +81,10 @@ static struct resource code_resource = {
+ };
+
+ unsigned long memory_start;
++EXPORT_SYMBOL(memory_start);
++
+ unsigned long memory_end;
++EXPORT_SYMBOL(memory_end);
+
+ void __init setup_arch(char **);
+ int get_cpuinfo(char *);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/include/asm/page.h linux-libre-4.4.7-gnu/arch/mips/include/asm/page.h
+--- linux-libre-4.4-gnu/arch/mips/include/asm/page.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/include/asm/page.h 2016-04-12 12:09:26.000000000 -0400
+@@ -33,7 +33,7 @@
+ #define PAGE_SHIFT 16
+ #endif
+ #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
+-#define PAGE_MASK (~(PAGE_SIZE - 1))
++#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+
+ /*
+ * This is used for calculating the real page sizes
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/include/asm/pgtable.h linux-libre-4.4.7-gnu/arch/mips/include/asm/pgtable.h
+--- linux-libre-4.4-gnu/arch/mips/include/asm/pgtable.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/include/asm/pgtable.h 2016-04-12 12:09:26.000000000 -0400
+@@ -353,7 +353,7 @@ static inline pte_t pte_mkdirty(pte_t pt
+ static inline pte_t pte_mkyoung(pte_t pte)
+ {
+ pte_val(pte) |= _PAGE_ACCESSED;
+-#ifdef CONFIG_CPU_MIPSR2
++#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
+ if (!(pte_val(pte) & _PAGE_NO_READ))
+ pte_val(pte) |= _PAGE_SILENT_READ;
+ else
+@@ -560,7 +560,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pm
+ {
+ pmd_val(pmd) |= _PAGE_ACCESSED;
+
+-#ifdef CONFIG_CPU_MIPSR2
++#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
+ if (!(pmd_val(pmd) & _PAGE_NO_READ))
+ pmd_val(pmd) |= _PAGE_SILENT_READ;
+ else
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/include/asm/syscall.h linux-libre-4.4.7-gnu/arch/mips/include/asm/syscall.h
+--- linux-libre-4.4-gnu/arch/mips/include/asm/syscall.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/include/asm/syscall.h 2016-04-12 12:09:26.000000000 -0400
+@@ -101,10 +101,8 @@ static inline void syscall_get_arguments
+ /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
+ if ((config_enabled(CONFIG_32BIT) ||
+ test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
+- (regs->regs[2] == __NR_syscall)) {
++ (regs->regs[2] == __NR_syscall))
+ i++;
+- n++;
+- }
+
+ while (n--)
+ ret |= mips_get_syscall_arg(args++, task, regs, i++);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/Kconfig linux-libre-4.4.7-gnu/arch/mips/Kconfig
+--- linux-libre-4.4-gnu/arch/mips/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -2155,7 +2155,7 @@ config MIPS_MT_SMP
+ select CPU_MIPSR2_IRQ_VI
+ select CPU_MIPSR2_IRQ_EI
+ select SYNC_R4K
+- select MIPS_GIC_IPI
++ select MIPS_GIC_IPI if MIPS_GIC
+ select MIPS_MT
+ select SMP
+ select SMP_UP
+@@ -2253,7 +2253,7 @@ config MIPS_VPE_APSP_API_MT
+ config MIPS_CMP
+ bool "MIPS CMP framework support (DEPRECATED)"
+ depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
+- select MIPS_GIC_IPI
++ select MIPS_GIC_IPI if MIPS_GIC
+ select SMP
+ select SYNC_R4K
+ select SYS_SUPPORTS_SMP
+@@ -2273,7 +2273,7 @@ config MIPS_CPS
+ select MIPS_CM
+ select MIPS_CPC
+ select MIPS_CPS_PM if HOTPLUG_CPU
+- select MIPS_GIC_IPI
++ select MIPS_GIC_IPI if MIPS_GIC
+ select SMP
+ select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
+ select SYS_SUPPORTS_HOTPLUG_CPU
+@@ -2292,6 +2292,7 @@ config MIPS_CPS_PM
+ bool
+
+ config MIPS_GIC_IPI
++ depends on MIPS_GIC
+ bool
+
+ config MIPS_CM
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/kernel/smp.c linux-libre-4.4.7-gnu/arch/mips/kernel/smp.c
+--- linux-libre-4.4-gnu/arch/mips/kernel/smp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/kernel/smp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -121,6 +121,7 @@ static inline void calculate_cpu_foreign
+ cpumask_t temp_foreign_map;
+
+ /* Re-calculate the mask */
++ cpumask_clear(&temp_foreign_map);
+ for_each_online_cpu(i) {
+ core_present = 0;
+ for_each_cpu(k, &temp_foreign_map)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/kernel/traps.c linux-libre-4.4.7-gnu/arch/mips/kernel/traps.c
+--- linux-libre-4.4-gnu/arch/mips/kernel/traps.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/kernel/traps.c 2016-04-12 12:09:26.000000000 -0400
+@@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs
+ asmlinkage void do_ov(struct pt_regs *regs)
+ {
+ enum ctx_state prev_state;
+- siginfo_t info;
++ siginfo_t info = {
++ .si_signo = SIGFPE,
++ .si_code = FPE_INTOVF,
++ .si_addr = (void __user *)regs->cp0_epc,
++ };
+
+ prev_state = exception_enter();
+ die_if_kernel("Integer overflow", regs);
+
+- info.si_code = FPE_INTOVF;
+- info.si_signo = SIGFPE;
+- info.si_errno = 0;
+- info.si_addr = (void __user *) regs->cp0_epc;
+ force_sig_info(SIGFPE, &info, current);
+ exception_exit(prev_state);
+ }
+@@ -874,7 +874,7 @@ out:
+ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+ const char *str)
+ {
+- siginfo_t info;
++ siginfo_t info = { 0 };
+ char b[40];
+
+ #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
+@@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs,
+ else
+ info.si_code = FPE_INTOVF;
+ info.si_signo = SIGFPE;
+- info.si_errno = 0;
+ info.si_addr = (void __user *) regs->cp0_epc;
+ force_sig_info(SIGFPE, &info, current);
+ break;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/kvm/mips.c linux-libre-4.4.7-gnu/arch/mips/kvm/mips.c
+--- linux-libre-4.4-gnu/arch/mips/kvm/mips.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/kvm/mips.c 2016-04-12 12:09:26.000000000 -0400
+@@ -702,7 +702,7 @@ static int kvm_mips_get_reg(struct kvm_v
+ } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
+ void __user *uaddr = (void __user *)(long)reg->addr;
+
+- return copy_to_user(uaddr, vs, 16);
++ return copy_to_user(uaddr, vs, 16) ? -EFAULT : 0;
+ } else {
+ return -EINVAL;
+ }
+@@ -732,7 +732,7 @@ static int kvm_mips_set_reg(struct kvm_v
+ } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
+ void __user *uaddr = (void __user *)(long)reg->addr;
+
+- return copy_from_user(vs, uaddr, 16);
++ return copy_from_user(vs, uaddr, 16) ? -EFAULT : 0;
+ } else {
+ return -EINVAL;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/loongson64/loongson-3/hpet.c linux-libre-4.4.7-gnu/arch/mips/loongson64/loongson-3/hpet.c
+--- linux-libre-4.4-gnu/arch/mips/loongson64/loongson-3/hpet.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/loongson64/loongson-3/hpet.c 2016-04-12 12:09:26.000000000 -0400
+@@ -13,6 +13,9 @@
+ #define SMBUS_PCI_REG64 0x64
+ #define SMBUS_PCI_REGB4 0xb4
+
++#define HPET_MIN_CYCLES 64
++#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
++
+ static DEFINE_SPINLOCK(hpet_lock);
+ DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
+
+@@ -161,8 +164,9 @@ static int hpet_next_event(unsigned long
+ cnt += delta;
+ hpet_write(HPET_T0_CMP, cnt);
+
+- res = ((int)(hpet_read(HPET_COUNTER) - cnt) > 0) ? -ETIME : 0;
+- return res;
++ res = (int)(cnt - hpet_read(HPET_COUNTER));
++
++ return res < HPET_MIN_CYCLES ? -ETIME : 0;
+ }
+
+ static irqreturn_t hpet_irq_handler(int irq, void *data)
+@@ -237,7 +241,7 @@ void __init setup_hpet_timer(void)
+ cd->cpumask = cpumask_of(cpu);
+ clockevent_set_clock(cd, HPET_FREQ);
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
+- cd->min_delta_ns = 5000;
++ cd->min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, cd);
+
+ clockevents_register_device(cd);
+ setup_irq(HPET_T0_IRQ, &hpet_irq);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/loongson64/loongson-3/smp.c linux-libre-4.4.7-gnu/arch/mips/loongson64/loongson-3/smp.c
+--- linux-libre-4.4-gnu/arch/mips/loongson64/loongson-3/smp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/loongson64/loongson-3/smp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -30,13 +30,13 @@
+ #include "smp.h"
+
+ DEFINE_PER_CPU(int, cpu_state);
+-DEFINE_PER_CPU(uint32_t, core0_c0count);
+
+ static void *ipi_set0_regs[16];
+ static void *ipi_clear0_regs[16];
+ static void *ipi_status0_regs[16];
+ static void *ipi_en0_regs[16];
+ static void *ipi_mailbox_buf[16];
++static uint32_t core0_c0count[NR_CPUS];
+
+ /* read a 32bit value from ipi register */
+ #define loongson3_ipi_read32(addr) readl(addr)
+@@ -275,12 +275,14 @@ void loongson3_ipi_interrupt(struct pt_r
+ if (action & SMP_ASK_C0COUNT) {
+ BUG_ON(cpu != 0);
+ c0count = read_c0_count();
+- for (i = 1; i < num_possible_cpus(); i++)
+- per_cpu(core0_c0count, i) = c0count;
++ c0count = c0count ? c0count : 1;
++ for (i = 1; i < nr_cpu_ids; i++)
++ core0_c0count[i] = c0count;
++ __wbflush(); /* Let others see the result ASAP */
+ }
+ }
+
+-#define MAX_LOOPS 1111
++#define MAX_LOOPS 800
+ /*
+ * SMP init and finish on secondary CPUs
+ */
+@@ -305,16 +307,20 @@ static void loongson3_init_secondary(voi
+ cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
+
+ i = 0;
+- __this_cpu_write(core0_c0count, 0);
++ core0_c0count[cpu] = 0;
+ loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
+- while (!__this_cpu_read(core0_c0count)) {
++ while (!core0_c0count[cpu]) {
+ i++;
+ cpu_relax();
+ }
+
+ if (i > MAX_LOOPS)
+ i = MAX_LOOPS;
+- initcount = __this_cpu_read(core0_c0count) + i;
++ if (cpu_data[cpu].package)
++ initcount = core0_c0count[cpu] + i;
++ else /* Local access is faster for loops */
++ initcount = core0_c0count[cpu] + i/2;
++
+ write_c0_count(initcount);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/mm/sc-mips.c linux-libre-4.4.7-gnu/arch/mips/mm/sc-mips.c
+--- linux-libre-4.4-gnu/arch/mips/mm/sc-mips.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/mm/sc-mips.c 2016-04-12 12:09:26.000000000 -0400
+@@ -164,11 +164,13 @@ static int __init mips_sc_probe_cm3(void
+
+ sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
+ sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
+- c->scache.sets = 64 << sets;
++ if (sets)
++ c->scache.sets = 64 << sets;
+
+ line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
+ line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
+- c->scache.linesz = 2 << line_sz;
++ if (line_sz)
++ c->scache.linesz = 2 << line_sz;
+
+ assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
+ assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
+@@ -176,9 +178,12 @@ static int __init mips_sc_probe_cm3(void
+ c->scache.waysize = c->scache.sets * c->scache.linesz;
+ c->scache.waybit = __ffs(c->scache.waysize);
+
+- c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
++ if (c->scache.linesz) {
++ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
++ return 1;
++ }
+
+- return 1;
++ return 0;
+ }
+
+ void __weak platform_early_l2_init(void)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/mips/mm/tlbex.c linux-libre-4.4.7-gnu/arch/mips/mm/tlbex.c
+--- linux-libre-4.4-gnu/arch/mips/mm/tlbex.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/mips/mm/tlbex.c 2016-04-12 12:09:26.000000000 -0400
+@@ -242,7 +242,7 @@ static void output_pgtable_bits_defines(
+ pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
+ pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT);
+ #endif
+-#ifdef CONFIG_CPU_MIPSR2
++#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
+ if (cpu_has_rixi) {
+ #ifdef _PAGE_NO_EXEC_SHIFT
+ pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/parisc/include/asm/hugetlb.h linux-libre-4.4.7-gnu/arch/parisc/include/asm/hugetlb.h
+--- linux-libre-4.4-gnu/arch/parisc/include/asm/hugetlb.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/parisc/include/asm/hugetlb.h 2016-04-12 12:09:26.000000000 -0400
+@@ -54,24 +54,12 @@ static inline pte_t huge_pte_wrprotect(p
+ return pte_wrprotect(pte);
+ }
+
+-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+- unsigned long addr, pte_t *ptep)
+-{
+- pte_t old_pte = *ptep;
+- set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
+-}
++void huge_ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep);
+
+-static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
++int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+- pte_t pte, int dirty)
+-{
+- int changed = !pte_same(*ptep, pte);
+- if (changed) {
+- set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+- flush_tlb_page(vma, addr);
+- }
+- return changed;
+-}
++ pte_t pte, int dirty);
+
+ static inline pte_t huge_ptep_get(pte_t *ptep)
+ {
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/parisc/include/uapi/asm/siginfo.h linux-libre-4.4.7-gnu/arch/parisc/include/uapi/asm/siginfo.h
+--- linux-libre-4.4-gnu/arch/parisc/include/uapi/asm/siginfo.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/parisc/include/uapi/asm/siginfo.h 2016-04-12 12:09:26.000000000 -0400
+@@ -1,6 +1,10 @@
+ #ifndef _PARISC_SIGINFO_H
+ #define _PARISC_SIGINFO_H
+
++#if defined(__LP64__)
++#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
++#endif
++
+ #include <asm-generic/siginfo.h>
+
+ #undef NSIGTRAP
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/parisc/kernel/ptrace.c linux-libre-4.4.7-gnu/arch/parisc/kernel/ptrace.c
+--- linux-libre-4.4-gnu/arch/parisc/kernel/ptrace.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/parisc/kernel/ptrace.c 2016-04-12 12:09:26.000000000 -0400
+@@ -269,14 +269,19 @@ long compat_arch_ptrace(struct task_stru
+
+ long do_syscall_trace_enter(struct pt_regs *regs)
+ {
+- long ret = 0;
+-
+ /* Do the secure computing check first. */
+ secure_computing_strict(regs->gr[20]);
+
+ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+- tracehook_report_syscall_entry(regs))
+- ret = -1L;
++ tracehook_report_syscall_entry(regs)) {
++ /*
++ * Tracing decided this syscall should not happen or the
++ * debugger stored an invalid system call number. Skip
++ * the system call and the system call restart handling.
++ */
++ regs->gr[20] = -1UL;
++ goto out;
++ }
+
+ #ifdef CONFIG_64BIT
+ if (!is_compat_task())
+@@ -290,7 +295,8 @@ long do_syscall_trace_enter(struct pt_re
+ regs->gr[24] & 0xffffffff,
+ regs->gr[23] & 0xffffffff);
+
+- return ret ? : regs->gr[20];
++out:
++ return regs->gr[20];
+ }
+
+ void do_syscall_trace_exit(struct pt_regs *regs)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/parisc/kernel/syscall.S linux-libre-4.4.7-gnu/arch/parisc/kernel/syscall.S
+--- linux-libre-4.4-gnu/arch/parisc/kernel/syscall.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/parisc/kernel/syscall.S 2016-04-12 12:09:26.000000000 -0400
+@@ -343,7 +343,7 @@ tracesys_next:
+ #endif
+
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+- b,n .Lsyscall_nosys
++ b,n .Ltracesys_nosys
+
+ LDREGX %r20(%r19), %r19
+
+@@ -359,6 +359,9 @@ tracesys_next:
+ be 0(%sr7,%r19)
+ ldo R%tracesys_exit(%r2),%r2
+
++.Ltracesys_nosys:
++ ldo -ENOSYS(%r0),%r28 /* set errno */
++
+ /* Do *not* call this function on the gateway page, because it
+ makes a direct call to syscall_trace. */
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/parisc/mm/hugetlbpage.c linux-libre-4.4.7-gnu/arch/parisc/mm/hugetlbpage.c
+--- linux-libre-4.4-gnu/arch/parisc/mm/hugetlbpage.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/parisc/mm/hugetlbpage.c 2016-04-12 12:09:26.000000000 -0400
+@@ -105,15 +105,13 @@ static inline void purge_tlb_entries_hug
+ addr |= _HUGE_PAGE_SIZE_ENCODING_DEFAULT;
+
+ for (i = 0; i < (1 << (HPAGE_SHIFT-REAL_HPAGE_SHIFT)); i++) {
+- mtsp(mm->context, 1);
+- pdtlb(addr);
+- if (unlikely(split_tlb))
+- pitlb(addr);
++ purge_tlb_entries(mm, addr);
+ addr += (1UL << REAL_HPAGE_SHIFT);
+ }
+ }
+
+-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++/* __set_huge_pte_at() must be called holding the pa_tlb_lock. */
++static void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t entry)
+ {
+ unsigned long addr_start;
+@@ -123,14 +121,9 @@ void set_huge_pte_at(struct mm_struct *m
+ addr_start = addr;
+
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+- /* Directly write pte entry. We could call set_pte_at(mm, addr, ptep, entry)
+- * instead, but then we get double locking on pa_tlb_lock. */
+- *ptep = entry;
++ set_pte(ptep, entry);
+ ptep++;
+
+- /* Drop the PAGE_SIZE/non-huge tlb entry */
+- purge_tlb_entries(mm, addr);
+-
+ addr += PAGE_SIZE;
+ pte_val(entry) += PAGE_SIZE;
+ }
+@@ -138,18 +131,61 @@ void set_huge_pte_at(struct mm_struct *m
+ purge_tlb_entries_huge(mm, addr_start);
+ }
+
++void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
++ pte_t *ptep, pte_t entry)
++{
++ unsigned long flags;
++
++ purge_tlb_start(flags);
++ __set_huge_pte_at(mm, addr, ptep, entry);
++ purge_tlb_end(flags);
++}
++
+
+ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+ {
++ unsigned long flags;
+ pte_t entry;
+
++ purge_tlb_start(flags);
+ entry = *ptep;
+- set_huge_pte_at(mm, addr, ptep, __pte(0));
++ __set_huge_pte_at(mm, addr, ptep, __pte(0));
++ purge_tlb_end(flags);
+
+ return entry;
+ }
+
++
++void huge_ptep_set_wrprotect(struct mm_struct *mm,
++ unsigned long addr, pte_t *ptep)
++{
++ unsigned long flags;
++ pte_t old_pte;
++
++ purge_tlb_start(flags);
++ old_pte = *ptep;
++ __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
++ purge_tlb_end(flags);
++}
++
++int huge_ptep_set_access_flags(struct vm_area_struct *vma,
++ unsigned long addr, pte_t *ptep,
++ pte_t pte, int dirty)
++{
++ unsigned long flags;
++ int changed;
++
++ purge_tlb_start(flags);
++ changed = !pte_same(*ptep, pte);
++ if (changed) {
++ __set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
++ }
++ purge_tlb_end(flags);
++ return changed;
++}
++
++
+ int pmd_huge(pmd_t pmd)
+ {
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/include/asm/cmpxchg.h linux-libre-4.4.7-gnu/arch/powerpc/include/asm/cmpxchg.h
+--- linux-libre-4.4-gnu/arch/powerpc/include/asm/cmpxchg.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/include/asm/cmpxchg.h 2016-04-12 12:09:26.000000000 -0400
+@@ -18,12 +18,12 @@ __xchg_u32(volatile void *p, unsigned lo
+ unsigned long prev;
+
+ __asm__ __volatile__(
+- PPC_RELEASE_BARRIER
++ PPC_ATOMIC_ENTRY_BARRIER
+ "1: lwarx %0,0,%2 \n"
+ PPC405_ERR77(0,%2)
+ " stwcx. %3,0,%2 \n\
+ bne- 1b"
+- PPC_ACQUIRE_BARRIER
++ PPC_ATOMIC_EXIT_BARRIER
+ : "=&r" (prev), "+m" (*(volatile unsigned int *)p)
+ : "r" (p), "r" (val)
+ : "cc", "memory");
+@@ -61,12 +61,12 @@ __xchg_u64(volatile void *p, unsigned lo
+ unsigned long prev;
+
+ __asm__ __volatile__(
+- PPC_RELEASE_BARRIER
++ PPC_ATOMIC_ENTRY_BARRIER
+ "1: ldarx %0,0,%2 \n"
+ PPC405_ERR77(0,%2)
+ " stdcx. %3,0,%2 \n\
+ bne- 1b"
+- PPC_ACQUIRE_BARRIER
++ PPC_ATOMIC_EXIT_BARRIER
+ : "=&r" (prev), "+m" (*(volatile unsigned long *)p)
+ : "r" (p), "r" (val)
+ : "cc", "memory");
+@@ -151,14 +151,14 @@ __cmpxchg_u32(volatile unsigned int *p,
+ unsigned int prev;
+
+ __asm__ __volatile__ (
+- PPC_RELEASE_BARRIER
++ PPC_ATOMIC_ENTRY_BARRIER
+ "1: lwarx %0,0,%2 # __cmpxchg_u32\n\
+ cmpw 0,%0,%3\n\
+ bne- 2f\n"
+ PPC405_ERR77(0,%2)
+ " stwcx. %4,0,%2\n\
+ bne- 1b"
+- PPC_ACQUIRE_BARRIER
++ PPC_ATOMIC_EXIT_BARRIER
+ "\n\
+ 2:"
+ : "=&r" (prev), "+m" (*p)
+@@ -197,13 +197,13 @@ __cmpxchg_u64(volatile unsigned long *p,
+ unsigned long prev;
+
+ __asm__ __volatile__ (
+- PPC_RELEASE_BARRIER
++ PPC_ATOMIC_ENTRY_BARRIER
+ "1: ldarx %0,0,%2 # __cmpxchg_u64\n\
+ cmpd 0,%0,%3\n\
+ bne- 2f\n\
+ stdcx. %4,0,%2\n\
+ bne- 1b"
+- PPC_ACQUIRE_BARRIER
++ PPC_ATOMIC_EXIT_BARRIER
+ "\n\
+ 2:"
+ : "=&r" (prev), "+m" (*p)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/include/asm/eeh.h linux-libre-4.4.7-gnu/arch/powerpc/include/asm/eeh.h
+--- linux-libre-4.4-gnu/arch/powerpc/include/asm/eeh.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/include/asm/eeh.h 2016-04-12 12:09:26.000000000 -0400
+@@ -81,6 +81,7 @@ struct pci_dn;
+ #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */
+ #define EEH_PE_CFG_RESTRICTED (1 << 9) /* Block config on error */
+ #define EEH_PE_REMOVED (1 << 10) /* Removed permanently */
++#define EEH_PE_PRI_BUS (1 << 11) /* Cached primary bus */
+
+ struct eeh_pe {
+ int type; /* PE type: PHB/Bus/Device */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/include/asm/opal-api.h linux-libre-4.4.7-gnu/arch/powerpc/include/asm/opal-api.h
+--- linux-libre-4.4-gnu/arch/powerpc/include/asm/opal-api.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/include/asm/opal-api.h 2016-04-12 12:09:26.000000000 -0400
+@@ -157,7 +157,8 @@
+ #define OPAL_LEDS_GET_INDICATOR 114
+ #define OPAL_LEDS_SET_INDICATOR 115
+ #define OPAL_CEC_REBOOT2 116
+-#define OPAL_LAST 116
++#define OPAL_CONSOLE_FLUSH 117
++#define OPAL_LAST 117
+
+ /* Device tree flags */
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/include/asm/opal.h linux-libre-4.4.7-gnu/arch/powerpc/include/asm/opal.h
+--- linux-libre-4.4-gnu/arch/powerpc/include/asm/opal.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/include/asm/opal.h 2016-04-12 12:09:26.000000000 -0400
+@@ -35,6 +35,7 @@ int64_t opal_console_read(int64_t term_n
+ uint8_t *buffer);
+ int64_t opal_console_write_buffer_space(int64_t term_number,
+ __be64 *length);
++int64_t opal_console_flush(int64_t term_number);
+ int64_t opal_rtc_read(__be32 *year_month_day,
+ __be64 *hour_minute_second_millisecond);
+ int64_t opal_rtc_write(uint32_t year_month_day,
+@@ -262,6 +263,8 @@ extern int opal_resync_timebase(void);
+
+ extern void opal_lpc_init(void);
+
++extern void opal_kmsg_init(void);
++
+ extern int opal_event_request(unsigned int opal_event_nr);
+
+ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/include/asm/synch.h linux-libre-4.4.7-gnu/arch/powerpc/include/asm/synch.h
+--- linux-libre-4.4-gnu/arch/powerpc/include/asm/synch.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/include/asm/synch.h 2016-04-12 12:09:26.000000000 -0400
+@@ -44,7 +44,7 @@ static inline void isync(void)
+ MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
+ #define PPC_ACQUIRE_BARRIER "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
+ #define PPC_RELEASE_BARRIER stringify_in_c(LWSYNC) "\n"
+-#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n"
++#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(sync) "\n"
+ #define PPC_ATOMIC_EXIT_BARRIER "\n" stringify_in_c(sync) "\n"
+ #else
+ #define PPC_ACQUIRE_BARRIER
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/include/uapi/asm/elf.h linux-libre-4.4.7-gnu/arch/powerpc/include/uapi/asm/elf.h
+--- linux-libre-4.4-gnu/arch/powerpc/include/uapi/asm/elf.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/include/uapi/asm/elf.h 2016-04-12 12:09:26.000000000 -0400
+@@ -295,6 +295,8 @@ do { \
+ #define R_PPC64_TLSLD 108
+ #define R_PPC64_TOCSAVE 109
+
++#define R_PPC64_ENTRY 118
++
+ #define R_PPC64_REL16 249
+ #define R_PPC64_REL16_LO 250
+ #define R_PPC64_REL16_HI 251
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/kernel/eeh_driver.c linux-libre-4.4.7-gnu/arch/powerpc/kernel/eeh_driver.c
+--- linux-libre-4.4-gnu/arch/powerpc/kernel/eeh_driver.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/kernel/eeh_driver.c 2016-04-12 12:09:26.000000000 -0400
+@@ -418,8 +418,7 @@ static void *eeh_rmv_device(void *data,
+ eeh_pcid_put(dev);
+ if (driver->err_handler &&
+ driver->err_handler->error_detected &&
+- driver->err_handler->slot_reset &&
+- driver->err_handler->resume)
++ driver->err_handler->slot_reset)
+ return NULL;
+ }
+
+@@ -564,6 +563,7 @@ static int eeh_reset_device(struct eeh_p
+ */
+ eeh_pe_state_mark(pe, EEH_PE_KEEP);
+ if (bus) {
++ eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+ pci_lock_rescan_remove();
+ pcibios_remove_pci_devices(bus);
+ pci_unlock_rescan_remove();
+@@ -803,6 +803,7 @@ perm_error:
+ * the their PCI config any more.
+ */
+ if (frozen_bus) {
++ eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+ eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
+
+ pci_lock_rescan_remove();
+@@ -886,6 +887,7 @@ static void eeh_handle_special_event(voi
+ continue;
+
+ /* Notify all devices to be down */
++ eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+ bus = eeh_pe_bus_get(phb_pe);
+ eeh_pe_dev_traverse(pe,
+ eeh_report_failure, NULL);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/kernel/eeh_pe.c linux-libre-4.4.7-gnu/arch/powerpc/kernel/eeh_pe.c
+--- linux-libre-4.4-gnu/arch/powerpc/kernel/eeh_pe.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/kernel/eeh_pe.c 2016-04-12 12:09:26.000000000 -0400
+@@ -883,32 +883,29 @@ void eeh_pe_restore_bars(struct eeh_pe *
+ const char *eeh_pe_loc_get(struct eeh_pe *pe)
+ {
+ struct pci_bus *bus = eeh_pe_bus_get(pe);
+- struct device_node *dn = pci_bus_to_OF_node(bus);
++ struct device_node *dn;
+ const char *loc = NULL;
+
+- if (!dn)
+- goto out;
++ while (bus) {
++ dn = pci_bus_to_OF_node(bus);
++ if (!dn) {
++ bus = bus->parent;
++ continue;
++ }
+
+- /* PHB PE or root PE ? */
+- if (pci_is_root_bus(bus)) {
+- loc = of_get_property(dn, "ibm,loc-code", NULL);
+- if (!loc)
++ if (pci_is_root_bus(bus))
+ loc = of_get_property(dn, "ibm,io-base-loc-code", NULL);
++ else
++ loc = of_get_property(dn, "ibm,slot-location-code",
++ NULL);
++
+ if (loc)
+- goto out;
++ return loc;
+
+- /* Check the root port */
+- dn = dn->child;
+- if (!dn)
+- goto out;
++ bus = bus->parent;
+ }
+
+- loc = of_get_property(dn, "ibm,loc-code", NULL);
+- if (!loc)
+- loc = of_get_property(dn, "ibm,slot-location-code", NULL);
+-
+-out:
+- return loc ? loc : "N/A";
++ return "N/A";
+ }
+
+ /**
+@@ -931,7 +928,7 @@ struct pci_bus *eeh_pe_bus_get(struct ee
+ bus = pe->phb->bus;
+ } else if (pe->type & EEH_PE_BUS ||
+ pe->type & EEH_PE_DEVICE) {
+- if (pe->bus) {
++ if (pe->state & EEH_PE_PRI_BUS) {
+ bus = pe->bus;
+ goto out;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/kernel/module_64.c linux-libre-4.4.7-gnu/arch/powerpc/kernel/module_64.c
+--- linux-libre-4.4-gnu/arch/powerpc/kernel/module_64.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/kernel/module_64.c 2016-04-12 12:09:26.000000000 -0400
+@@ -335,7 +335,7 @@ static void dedotify(Elf64_Sym *syms, un
+ if (syms[i].st_shndx == SHN_UNDEF) {
+ char *name = strtab + syms[i].st_name;
+ if (name[0] == '.')
+- memmove(name, name+1, strlen(name));
++ syms[i].st_name++;
+ }
+ }
+ }
+@@ -635,6 +635,33 @@ int apply_relocate_add(Elf64_Shdr *sechd
+ */
+ break;
+
++ case R_PPC64_ENTRY:
++ /*
++ * Optimize ELFv2 large code model entry point if
++ * the TOC is within 2GB range of current location.
++ */
++ value = my_r2(sechdrs, me) - (unsigned long)location;
++ if (value + 0x80008000 > 0xffffffff)
++ break;
++ /*
++ * Check for the large code model prolog sequence:
++ * ld r2, ...(r12)
++ * add r2, r2, r12
++ */
++ if ((((uint32_t *)location)[0] & ~0xfffc)
++ != 0xe84c0000)
++ break;
++ if (((uint32_t *)location)[1] != 0x7c426214)
++ break;
++ /*
++ * If found, replace it with:
++ * addis r2, r12, (.TOC.-func)@ha
++ * addi r2, r12, (.TOC.-func)@l
++ */
++ ((uint32_t *)location)[0] = 0x3c4c0000 + PPC_HA(value);
++ ((uint32_t *)location)[1] = 0x38420000 + PPC_LO(value);
++ break;
++
+ case R_PPC64_REL16_HA:
+ /* Subtract location pointer */
+ value -= (unsigned long)location;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/kernel/process.c linux-libre-4.4.7-gnu/arch/powerpc/kernel/process.c
+--- linux-libre-4.4-gnu/arch/powerpc/kernel/process.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/kernel/process.c 2016-04-12 12:09:26.000000000 -0400
+@@ -569,6 +569,24 @@ static void tm_reclaim_thread(struct thr
+ if (!MSR_TM_SUSPENDED(mfmsr()))
+ return;
+
++ /*
++ * Use the current MSR TM suspended bit to track if we have
++ * checkpointed state outstanding.
++ * On signal delivery, we'd normally reclaim the checkpointed
++ * state to obtain stack pointer (see:get_tm_stackpointer()).
++ * This will then directly return to userspace without going
++ * through __switch_to(). However, if the stack frame is bad,
++ * we need to exit this thread which calls __switch_to() which
++ * will again attempt to reclaim the already saved tm state.
++ * Hence we need to check that we've not already reclaimed
++ * this state.
++ * We do this using the current MSR, rather tracking it in
++ * some specific thread_struct bit, as it has the additional
++ * benifit of checking for a potential TM bad thing exception.
++ */
++ if (!MSR_TM_SUSPENDED(mfmsr()))
++ return;
++
+ tm_reclaim(thr, thr->regs->msr, cause);
+
+ /* Having done the reclaim, we now have the checkpointed
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S linux-libre-4.4.7-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+--- linux-libre-4.4-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S 2016-04-12 12:09:26.000000000 -0400
+@@ -1370,6 +1370,20 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
+ std r6, VCPU_ACOP(r9)
+ stw r7, VCPU_GUEST_PID(r9)
+ std r8, VCPU_WORT(r9)
++ /*
++ * Restore various registers to 0, where non-zero values
++ * set by the guest could disrupt the host.
++ */
++ li r0, 0
++ mtspr SPRN_IAMR, r0
++ mtspr SPRN_CIABR, r0
++ mtspr SPRN_DAWRX, r0
++ mtspr SPRN_TCSCR, r0
++ mtspr SPRN_WORT, r0
++ /* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
++ li r0, 1
++ sldi r0, r0, 31
++ mtspr SPRN_MMCRS, r0
+ 8:
+
+ /* Save and reset AMR and UAMOR before turning on the MMU */
+@@ -2153,7 +2167,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
+
+ /* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
+ 2: rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW
+- rlwimi r5, r4, 1, DAWRX_WT
++ rlwimi r5, r4, 2, DAWRX_WT
+ clrrdi r4, r4, 3
+ std r4, VCPU_DAWR(r3)
+ std r5, VCPU_DAWRX(r3)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/kvm/powerpc.c linux-libre-4.4.7-gnu/arch/powerpc/kvm/powerpc.c
+--- linux-libre-4.4-gnu/arch/powerpc/kvm/powerpc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/kvm/powerpc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -919,21 +919,17 @@ int kvm_vcpu_ioctl_get_one_reg(struct kv
+ r = -ENXIO;
+ break;
+ }
+- vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
++ val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
+ break;
+ case KVM_REG_PPC_VSCR:
+ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ r = -ENXIO;
+ break;
+ }
+- vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
++ val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
+ break;
+ case KVM_REG_PPC_VRSAVE:
+- if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+- r = -ENXIO;
+- break;
+- }
+- vcpu->arch.vrsave = set_reg_val(reg->id, val);
++ val = get_reg_val(reg->id, vcpu->arch.vrsave);
+ break;
+ #endif /* CONFIG_ALTIVEC */
+ default:
+@@ -974,17 +970,21 @@ int kvm_vcpu_ioctl_set_one_reg(struct kv
+ r = -ENXIO;
+ break;
+ }
+- val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0];
++ vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
+ break;
+ case KVM_REG_PPC_VSCR:
+ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
+ r = -ENXIO;
+ break;
+ }
+- val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]);
++ vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val);
+ break;
+ case KVM_REG_PPC_VRSAVE:
+- val = get_reg_val(reg->id, vcpu->arch.vrsave);
++ if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
++ r = -ENXIO;
++ break;
++ }
++ vcpu->arch.vrsave = set_reg_val(reg->id, val);
+ break;
+ #endif /* CONFIG_ALTIVEC */
+ default:
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -444,9 +444,12 @@ static void *pnv_eeh_probe(struct pci_dn
+ * PCI devices of the PE are expected to be removed prior
+ * to PE reset.
+ */
+- if (!edev->pe->bus)
++ if (!(edev->pe->state & EEH_PE_PRI_BUS)) {
+ edev->pe->bus = pci_find_bus(hose->global_number,
+ pdn->busno);
++ if (edev->pe->bus)
++ edev->pe->state |= EEH_PE_PRI_BUS;
++ }
+
+ /*
+ * Enable EEH explicitly so that we will do EEH check
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/Makefile linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/Makefile
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/Makefile 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/Makefile 2016-04-12 12:09:26.000000000 -0400
+@@ -2,6 +2,7 @@ obj-y += setup.o opal-wrappers.o opal.
+ obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
+ obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
+ obj-y += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
++obj-y += opal-kmsg.o
+
+ obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o
+ obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/opal.c linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/opal.c
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/opal.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/opal.c 2016-04-12 12:09:26.000000000 -0400
+@@ -758,6 +758,9 @@ static int __init opal_init(void)
+ opal_pdev_init(opal_node, "ibm,opal-flash");
+ opal_pdev_init(opal_node, "ibm,opal-prd");
+
++ /* Initialise OPAL kmsg dumper for flushing console on panic */
++ opal_kmsg_init();
++
+ return 0;
+ }
+ machine_subsys_initcall(powernv, opal_init);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/opal-kmsg.c linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/opal-kmsg.c
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/opal-kmsg.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/opal-kmsg.c 2016-04-12 12:09:26.000000000 -0400
+@@ -0,0 +1,75 @@
++/*
++ * kmsg dumper that ensures the OPAL console fully flushes panic messages
++ *
++ * Author: Russell Currey <ruscur@russell.cc>
++ *
++ * Copyright 2015 IBM Corporation.
++ *
++ * 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, or (at your
++ * option) any later version.
++ */
++
++#include <linux/kmsg_dump.h>
++
++#include <asm/opal.h>
++#include <asm/opal-api.h>
++
++/*
++ * Console output is controlled by OPAL firmware. The kernel regularly calls
++ * OPAL_POLL_EVENTS, which flushes some console output. In a panic state,
++ * however, the kernel no longer calls OPAL_POLL_EVENTS and the panic message
++ * may not be completely printed. This function does not actually dump the
++ * message, it just ensures that OPAL completely flushes the console buffer.
++ */
++static void force_opal_console_flush(struct kmsg_dumper *dumper,
++ enum kmsg_dump_reason reason)
++{
++ int i;
++ int64_t ret;
++
++ /*
++ * Outside of a panic context the pollers will continue to run,
++ * so we don't need to do any special flushing.
++ */
++ if (reason != KMSG_DUMP_PANIC)
++ return;
++
++ if (opal_check_token(OPAL_CONSOLE_FLUSH)) {
++ ret = opal_console_flush(0);
++
++ if (ret == OPAL_UNSUPPORTED || ret == OPAL_PARAMETER)
++ return;
++
++ /* Incrementally flush until there's nothing left */
++ while (opal_console_flush(0) != OPAL_SUCCESS);
++ } else {
++ /*
++ * If OPAL_CONSOLE_FLUSH is not implemented in the firmware,
++ * the console can still be flushed by calling the polling
++ * function enough times to flush the buffer. We don't know
++ * how much output still needs to be flushed, but we can be
++ * generous since the kernel is in panic and doesn't need
++ * to do much else.
++ */
++ printk(KERN_NOTICE "opal: OPAL_CONSOLE_FLUSH missing.\n");
++ for (i = 0; i < 1024; i++) {
++ opal_poll_events(NULL);
++ }
++ }
++}
++
++static struct kmsg_dumper opal_kmsg_dumper = {
++ .dump = force_opal_console_flush
++};
++
++void __init opal_kmsg_init(void)
++{
++ int rc;
++
++ /* Add our dumper to the list */
++ rc = kmsg_dump_register(&opal_kmsg_dumper);
++ if (rc != 0)
++ pr_err("opal: kmsg_dump_register failed; returned %d\n", rc);
++}
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S 2016-04-12 12:09:26.000000000 -0400
+@@ -301,3 +301,4 @@ OPAL_CALL(opal_flash_erase, OPAL_FLASH
+ OPAL_CALL(opal_prd_msg, OPAL_PRD_MSG);
+ OPAL_CALL(opal_leds_get_ind, OPAL_LEDS_GET_INDICATOR);
+ OPAL_CALL(opal_leds_set_ind, OPAL_LEDS_SET_INDICATOR);
++OPAL_CALL(opal_console_flush, OPAL_CONSOLE_FLUSH);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/pci.c linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/pci.c
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -601,6 +601,9 @@ int pnv_tce_build(struct iommu_table *tb
+ u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
+ long i;
+
++ if (proto_tce & TCE_PCI_WRITE)
++ proto_tce |= TCE_PCI_READ;
++
+ for (i = 0; i < npages; i++) {
+ unsigned long newtce = proto_tce |
+ ((rpn + i) << tbl->it_page_shift);
+@@ -622,6 +625,9 @@ int pnv_tce_xchg(struct iommu_table *tbl
+
+ BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl));
+
++ if (newtce & TCE_PCI_WRITE)
++ newtce |= TCE_PCI_READ;
++
+ oldtce = xchg(pnv_tce(tbl, idx), cpu_to_be64(newtce));
+ *hpa = be64_to_cpu(oldtce) & ~(TCE_PCI_READ | TCE_PCI_WRITE);
+ *direction = iommu_tce_direction(oldtce);
+@@ -762,6 +768,26 @@ void pnv_pci_dma_dev_setup(struct pci_de
+ phb->dma_dev_setup(phb, pdev);
+ }
+
++void pnv_pci_dma_bus_setup(struct pci_bus *bus)
++{
++ struct pci_controller *hose = bus->sysdata;
++ struct pnv_phb *phb = hose->private_data;
++ struct pnv_ioda_pe *pe;
++
++ list_for_each_entry(pe, &phb->ioda.pe_list, list) {
++ if (!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)))
++ continue;
++
++ if (!pe->pbus)
++ continue;
++
++ if (bus->number == ((pe->rid >> 8) & 0xFF)) {
++ pe->pbus = bus;
++ break;
++ }
++ }
++}
++
+ void pnv_pci_shutdown(void)
+ {
+ struct pci_controller *hose;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/pci.h linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/pci.h
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/pci.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/pci.h 2016-04-12 12:09:26.000000000 -0400
+@@ -235,6 +235,7 @@ extern void pnv_pci_reset_secondary_bus(
+ extern int pnv_eeh_phb_reset(struct pci_controller *hose, int option);
+
+ extern void pnv_pci_dma_dev_setup(struct pci_dev *pdev);
++extern void pnv_pci_dma_bus_setup(struct pci_bus *bus);
+ extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
+ extern void pnv_teardown_msi_irqs(struct pci_dev *pdev);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/pci-ioda.c linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/pci-ioda.c
+--- linux-libre-4.4-gnu/arch/powerpc/platforms/powernv/pci-ioda.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/powerpc/platforms/powernv/pci-ioda.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3034,6 +3034,7 @@ static void pnv_pci_ioda_shutdown(struct
+
+ static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
+ .dma_dev_setup = pnv_pci_dma_dev_setup,
++ .dma_bus_setup = pnv_pci_dma_bus_setup,
+ #ifdef CONFIG_PCI_MSI
+ .setup_msi_irqs = pnv_setup_msi_irqs,
+ .teardown_msi_irqs = pnv_teardown_msi_irqs,
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/include/asm/fpu/internal.h linux-libre-4.4.7-gnu/arch/s390/include/asm/fpu/internal.h
+--- linux-libre-4.4-gnu/arch/s390/include/asm/fpu/internal.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/include/asm/fpu/internal.h 2016-04-12 12:09:26.000000000 -0400
+@@ -48,6 +48,7 @@ static inline void convert_fp_to_vx(__ve
+ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
+ {
+ fpregs->pad = 0;
++ fpregs->fpc = fpu->fpc;
+ if (MACHINE_HAS_VX)
+ convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
+ else
+@@ -57,6 +58,7 @@ static inline void fpregs_store(_s390_fp
+
+ static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
+ {
++ fpu->fpc = fpregs->fpc;
+ if (MACHINE_HAS_VX)
+ convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
+ else
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/include/asm/kvm_host.h linux-libre-4.4.7-gnu/arch/s390/include/asm/kvm_host.h
+--- linux-libre-4.4-gnu/arch/s390/include/asm/kvm_host.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/include/asm/kvm_host.h 2016-04-12 12:09:26.000000000 -0400
+@@ -506,7 +506,6 @@ struct kvm_vcpu_arch {
+ struct kvm_s390_sie_block *sie_block;
+ unsigned int host_acrs[NUM_ACRS];
+ struct fpu host_fpregs;
+- struct fpu guest_fpregs;
+ struct kvm_s390_local_interrupt local_int;
+ struct hrtimer ckc_timer;
+ struct kvm_s390_pgm_info pgm;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/include/asm/mmu_context.h linux-libre-4.4.7-gnu/arch/s390/include/asm/mmu_context.h
+--- linux-libre-4.4-gnu/arch/s390/include/asm/mmu_context.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/include/asm/mmu_context.h 2016-04-12 12:09:26.000000000 -0400
+@@ -15,17 +15,25 @@
+ static inline int init_new_context(struct task_struct *tsk,
+ struct mm_struct *mm)
+ {
++ spin_lock_init(&mm->context.list_lock);
++ INIT_LIST_HEAD(&mm->context.pgtable_list);
++ INIT_LIST_HEAD(&mm->context.gmap_list);
+ cpumask_clear(&mm->context.cpu_attach_mask);
+ atomic_set(&mm->context.attach_count, 0);
+ mm->context.flush_mm = 0;
+- mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
+- mm->context.asce_bits |= _ASCE_TYPE_REGION3;
+ #ifdef CONFIG_PGSTE
+ mm->context.alloc_pgste = page_table_allocate_pgste;
+ mm->context.has_pgste = 0;
+ mm->context.use_skey = 0;
+ #endif
+- mm->context.asce_limit = STACK_TOP_MAX;
++ if (mm->context.asce_limit == 0) {
++ /* context created by exec, set asce limit to 4TB */
++ mm->context.asce_bits = _ASCE_TABLE_LENGTH |
++ _ASCE_USER_BITS | _ASCE_TYPE_REGION3;
++ mm->context.asce_limit = STACK_TOP_MAX;
++ } else if (mm->context.asce_limit == (1UL << 31)) {
++ mm_inc_nr_pmds(mm);
++ }
+ crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
+ return 0;
+ }
+@@ -111,8 +119,6 @@ static inline void activate_mm(struct mm
+ static inline void arch_dup_mmap(struct mm_struct *oldmm,
+ struct mm_struct *mm)
+ {
+- if (oldmm->context.asce_limit < mm->context.asce_limit)
+- crst_table_downgrade(mm, oldmm->context.asce_limit);
+ }
+
+ static inline void arch_exit_mmap(struct mm_struct *mm)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/include/asm/pci.h linux-libre-4.4.7-gnu/arch/s390/include/asm/pci.h
+--- linux-libre-4.4-gnu/arch/s390/include/asm/pci.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/include/asm/pci.h 2016-04-12 12:09:26.000000000 -0400
+@@ -45,7 +45,7 @@ struct zpci_fmb {
+ u64 rpcit_ops;
+ u64 dma_rbytes;
+ u64 dma_wbytes;
+-} __packed __aligned(16);
++} __packed __aligned(64);
+
+ enum zpci_state {
+ ZPCI_FN_STATE_RESERVED,
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/include/asm/pgalloc.h linux-libre-4.4.7-gnu/arch/s390/include/asm/pgalloc.h
+--- linux-libre-4.4-gnu/arch/s390/include/asm/pgalloc.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/include/asm/pgalloc.h 2016-04-12 12:09:26.000000000 -0400
+@@ -100,12 +100,26 @@ static inline void pud_populate(struct m
+
+ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+- spin_lock_init(&mm->context.list_lock);
+- INIT_LIST_HEAD(&mm->context.pgtable_list);
+- INIT_LIST_HEAD(&mm->context.gmap_list);
+- return (pgd_t *) crst_table_alloc(mm);
++ unsigned long *table = crst_table_alloc(mm);
++
++ if (!table)
++ return NULL;
++ if (mm->context.asce_limit == (1UL << 31)) {
++ /* Forking a compat process with 2 page table levels */
++ if (!pgtable_pmd_page_ctor(virt_to_page(table))) {
++ crst_table_free(mm, table);
++ return NULL;
++ }
++ }
++ return (pgd_t *) table;
++}
++
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
++{
++ if (mm->context.asce_limit == (1UL << 31))
++ pgtable_pmd_page_dtor(virt_to_page(pgd));
++ crst_table_free(mm, (unsigned long *) pgd);
+ }
+-#define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
+
+ static inline void pmd_populate(struct mm_struct *mm,
+ pmd_t *pmd, pgtable_t pte)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/kernel/asm-offsets.c linux-libre-4.4.7-gnu/arch/s390/kernel/asm-offsets.c
+--- linux-libre-4.4-gnu/arch/s390/kernel/asm-offsets.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/kernel/asm-offsets.c 2016-04-12 12:09:26.000000000 -0400
+@@ -181,6 +181,7 @@ int main(void)
+ OFFSET(__LC_PSW_SAVE_AREA, _lowcore, psw_save_area);
+ OFFSET(__LC_PREFIX_SAVE_AREA, _lowcore, prefixreg_save_area);
+ OFFSET(__LC_FP_CREG_SAVE_AREA, _lowcore, fpt_creg_save_area);
++ OFFSET(__LC_TOD_PROGREG_SAVE_AREA, _lowcore, tod_progreg_save_area);
+ OFFSET(__LC_CPU_TIMER_SAVE_AREA, _lowcore, cpu_timer_save_area);
+ OFFSET(__LC_CLOCK_COMP_SAVE_AREA, _lowcore, clock_comp_save_area);
+ OFFSET(__LC_AREGS_SAVE_AREA, _lowcore, access_regs_save_area);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/kernel/compat_signal.c linux-libre-4.4.7-gnu/arch/s390/kernel/compat_signal.c
+--- linux-libre-4.4-gnu/arch/s390/kernel/compat_signal.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/kernel/compat_signal.c 2016-04-12 12:09:26.000000000 -0400
+@@ -271,7 +271,7 @@ static int restore_sigregs_ext32(struct
+
+ /* Restore high gprs from signal stack */
+ if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high,
+- sizeof(&sregs_ext->gprs_high)))
++ sizeof(sregs_ext->gprs_high)))
+ return -EFAULT;
+ for (i = 0; i < NUM_GPRS; i++)
+ *(__u32 *)&regs->gprs[i] = gprs_high[i];
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/kernel/entry.S linux-libre-4.4.7-gnu/arch/s390/kernel/entry.S
+--- linux-libre-4.4-gnu/arch/s390/kernel/entry.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/kernel/entry.S 2016-04-12 12:09:26.000000000 -0400
+@@ -1197,114 +1197,12 @@ cleanup_critical:
+ .quad .Lpsw_idle_lpsw
+
+ .Lcleanup_save_fpu_regs:
+- TSTMSK __LC_CPU_FLAGS,_CIF_FPU
+- bor %r14
+- clg %r9,BASED(.Lcleanup_save_fpu_regs_done)
+- jhe 5f
+- clg %r9,BASED(.Lcleanup_save_fpu_regs_fp)
+- jhe 4f
+- clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_high)
+- jhe 3f
+- clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_low)
+- jhe 2f
+- clg %r9,BASED(.Lcleanup_save_fpu_fpc_end)
+- jhe 1f
+- lg %r2,__LC_CURRENT
+- aghi %r2,__TASK_thread
+-0: # Store floating-point controls
+- stfpc __THREAD_FPU_fpc(%r2)
+-1: # Load register save area and check if VX is active
+- lg %r3,__THREAD_FPU_regs(%r2)
+- TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
+- jz 4f # no VX -> store FP regs
+-2: # Store vector registers (V0-V15)
+- VSTM %v0,%v15,0,%r3 # vstm 0,15,0(3)
+-3: # Store vector registers (V16-V31)
+- VSTM %v16,%v31,256,%r3 # vstm 16,31,256(3)
+- j 5f # -> done, set CIF_FPU flag
+-4: # Store floating-point registers
+- std 0,0(%r3)
+- std 1,8(%r3)
+- std 2,16(%r3)
+- std 3,24(%r3)
+- std 4,32(%r3)
+- std 5,40(%r3)
+- std 6,48(%r3)
+- std 7,56(%r3)
+- std 8,64(%r3)
+- std 9,72(%r3)
+- std 10,80(%r3)
+- std 11,88(%r3)
+- std 12,96(%r3)
+- std 13,104(%r3)
+- std 14,112(%r3)
+- std 15,120(%r3)
+-5: # Set CIF_FPU flag
+- oi __LC_CPU_FLAGS+7,_CIF_FPU
+- lg %r9,48(%r11) # return from save_fpu_regs
++ larl %r9,save_fpu_regs
+ br %r14
+-.Lcleanup_save_fpu_fpc_end:
+- .quad .Lsave_fpu_regs_fpc_end
+-.Lcleanup_save_fpu_regs_vx_low:
+- .quad .Lsave_fpu_regs_vx_low
+-.Lcleanup_save_fpu_regs_vx_high:
+- .quad .Lsave_fpu_regs_vx_high
+-.Lcleanup_save_fpu_regs_fp:
+- .quad .Lsave_fpu_regs_fp
+-.Lcleanup_save_fpu_regs_done:
+- .quad .Lsave_fpu_regs_done
+
+ .Lcleanup_load_fpu_regs:
+- TSTMSK __LC_CPU_FLAGS,_CIF_FPU
+- bnor %r14
+- clg %r9,BASED(.Lcleanup_load_fpu_regs_done)
+- jhe 1f
+- clg %r9,BASED(.Lcleanup_load_fpu_regs_fp)
+- jhe 2f
+- clg %r9,BASED(.Lcleanup_load_fpu_regs_vx_high)
+- jhe 3f
+- clg %r9,BASED(.Lcleanup_load_fpu_regs_vx)
+- jhe 4f
+- lg %r4,__LC_CURRENT
+- aghi %r4,__TASK_thread
+- lfpc __THREAD_FPU_fpc(%r4)
+- TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
+- lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area
+- jz 2f # -> no VX, load FP regs
+-4: # Load V0 ..V15 registers
+- VLM %v0,%v15,0,%r4
+-3: # Load V16..V31 registers
+- VLM %v16,%v31,256,%r4
+- j 1f
+-2: # Load floating-point registers
+- ld 0,0(%r4)
+- ld 1,8(%r4)
+- ld 2,16(%r4)
+- ld 3,24(%r4)
+- ld 4,32(%r4)
+- ld 5,40(%r4)
+- ld 6,48(%r4)
+- ld 7,56(%r4)
+- ld 8,64(%r4)
+- ld 9,72(%r4)
+- ld 10,80(%r4)
+- ld 11,88(%r4)
+- ld 12,96(%r4)
+- ld 13,104(%r4)
+- ld 14,112(%r4)
+- ld 15,120(%r4)
+-1: # Clear CIF_FPU bit
+- ni __LC_CPU_FLAGS+7,255-_CIF_FPU
+- lg %r9,48(%r11) # return from load_fpu_regs
++ larl %r9,load_fpu_regs
+ br %r14
+-.Lcleanup_load_fpu_regs_vx:
+- .quad .Lload_fpu_regs_vx
+-.Lcleanup_load_fpu_regs_vx_high:
+- .quad .Lload_fpu_regs_vx_high
+-.Lcleanup_load_fpu_regs_fp:
+- .quad .Lload_fpu_regs_fp
+-.Lcleanup_load_fpu_regs_done:
+- .quad .Lload_fpu_regs_done
+
+ /*
+ * Integer constants
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/kernel/head64.S linux-libre-4.4.7-gnu/arch/s390/kernel/head64.S
+--- linux-libre-4.4-gnu/arch/s390/kernel/head64.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/kernel/head64.S 2016-04-12 12:09:26.000000000 -0400
+@@ -16,7 +16,7 @@
+
+ __HEAD
+ ENTRY(startup_continue)
+- tm __LC_STFL_FAC_LIST+6,0x80 # LPP available ?
++ tm __LC_STFL_FAC_LIST+5,0x80 # LPP available ?
+ jz 0f
+ xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid
+ mvi __LC_LPP,0x80 # and set LPP_MAGIC
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/kernel/setup.c linux-libre-4.4.7-gnu/arch/s390/kernel/setup.c
+--- linux-libre-4.4-gnu/arch/s390/kernel/setup.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/kernel/setup.c 2016-04-12 12:09:26.000000000 -0400
+@@ -329,6 +329,7 @@ static void __init setup_lowcore(void)
+ + PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
+ lc->current_task = (unsigned long) init_thread_union.thread_info.task;
+ lc->thread_info = (unsigned long) &init_thread_union;
++ lc->lpp = LPP_MAGIC;
+ lc->machine_flags = S390_lowcore.machine_flags;
+ lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
+ memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/kvm/kvm-s390.c linux-libre-4.4.7-gnu/arch/s390/kvm/kvm-s390.c
+--- linux-libre-4.4-gnu/arch/s390/kvm/kvm-s390.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/kvm/kvm-s390.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1268,44 +1268,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *
+ return 0;
+ }
+
+-/*
+- * Backs up the current FP/VX register save area on a particular
+- * destination. Used to switch between different register save
+- * areas.
+- */
+-static inline void save_fpu_to(struct fpu *dst)
+-{
+- dst->fpc = current->thread.fpu.fpc;
+- dst->regs = current->thread.fpu.regs;
+-}
+-
+-/*
+- * Switches the FP/VX register save area from which to lazy
+- * restore register contents.
+- */
+-static inline void load_fpu_from(struct fpu *from)
+-{
+- current->thread.fpu.fpc = from->fpc;
+- current->thread.fpu.regs = from->regs;
+-}
+-
+ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+ {
+ /* Save host register state */
+ save_fpu_regs();
+- save_fpu_to(&vcpu->arch.host_fpregs);
+-
+- if (test_kvm_facility(vcpu->kvm, 129)) {
+- current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
+- /*
+- * Use the register save area in the SIE-control block
+- * for register restore and save in kvm_arch_vcpu_put()
+- */
+- current->thread.fpu.vxrs =
+- (__vector128 *)&vcpu->run->s.regs.vrs;
+- } else
+- load_fpu_from(&vcpu->arch.guest_fpregs);
++ vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
++ vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
+
++ /* Depending on MACHINE_HAS_VX, data stored to vrs either
++ * has vector register or floating point register format.
++ */
++ current->thread.fpu.regs = vcpu->run->s.regs.vrs;
++ current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
+ if (test_fp_ctl(current->thread.fpu.fpc))
+ /* User space provided an invalid FPC, let's clear it */
+ current->thread.fpu.fpc = 0;
+@@ -1321,19 +1295,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
+ atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+ gmap_disable(vcpu->arch.gmap);
+
++ /* Save guest register state */
+ save_fpu_regs();
++ vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
+
+- if (test_kvm_facility(vcpu->kvm, 129))
+- /*
+- * kvm_arch_vcpu_load() set up the register save area to
+- * the &vcpu->run->s.regs.vrs and, thus, the vector registers
+- * are already saved. Only the floating-point control must be
+- * copied.
+- */
+- vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
+- else
+- save_fpu_to(&vcpu->arch.guest_fpregs);
+- load_fpu_from(&vcpu->arch.host_fpregs);
++ /* Restore host register state */
++ current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
++ current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
+
+ save_access_regs(vcpu->run->s.regs.acrs);
+ restore_access_regs(vcpu->arch.host_acrs);
+@@ -1351,8 +1319,9 @@ static void kvm_s390_vcpu_initial_reset(
+ memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
+ vcpu->arch.sie_block->gcr[0] = 0xE0UL;
+ vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
+- vcpu->arch.guest_fpregs.fpc = 0;
+- asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
++ /* make sure the new fpc will be lazily loaded */
++ save_fpu_regs();
++ current->thread.fpu.fpc = 0;
+ vcpu->arch.sie_block->gbea = 1;
+ vcpu->arch.sie_block->pp = 0;
+ vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+@@ -1501,19 +1470,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
+ vcpu->arch.local_int.wq = &vcpu->wq;
+ vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
+
+- /*
+- * Allocate a save area for floating-point registers. If the vector
+- * extension is available, register contents are saved in the SIE
+- * control block. The allocated save area is still required in
+- * particular places, for example, in kvm_s390_vcpu_store_status().
+- */
+- vcpu->arch.guest_fpregs.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
+- GFP_KERNEL);
+- if (!vcpu->arch.guest_fpregs.fprs) {
+- rc = -ENOMEM;
+- goto out_free_sie_block;
+- }
+-
+ rc = kvm_vcpu_init(vcpu, kvm, id);
+ if (rc)
+ goto out_free_sie_block;
+@@ -1734,19 +1690,27 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct
+
+ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+ {
++ /* make sure the new values will be lazily loaded */
++ save_fpu_regs();
+ if (test_fp_ctl(fpu->fpc))
+ return -EINVAL;
+- memcpy(vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
+- vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+- save_fpu_regs();
+- load_fpu_from(&vcpu->arch.guest_fpregs);
++ current->thread.fpu.fpc = fpu->fpc;
++ if (MACHINE_HAS_VX)
++ convert_fp_to_vx(current->thread.fpu.vxrs, (freg_t *)fpu->fprs);
++ else
++ memcpy(current->thread.fpu.fprs, &fpu->fprs, sizeof(fpu->fprs));
+ return 0;
+ }
+
+ int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+ {
+- memcpy(&fpu->fprs, vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
+- fpu->fpc = vcpu->arch.guest_fpregs.fpc;
++ /* make sure we have the latest values */
++ save_fpu_regs();
++ if (MACHINE_HAS_VX)
++ convert_vx_to_fp((freg_t *)fpu->fprs, current->thread.fpu.vxrs);
++ else
++ memcpy(fpu->fprs, current->thread.fpu.fprs, sizeof(fpu->fprs));
++ fpu->fpc = current->thread.fpu.fpc;
+ return 0;
+ }
+
+@@ -2266,41 +2230,50 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
+ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
+ {
+ unsigned char archmode = 1;
++ freg_t fprs[NUM_FPRS];
+ unsigned int px;
+ u64 clkcomp;
+ int rc;
+
++ px = kvm_s390_get_prefix(vcpu);
+ if (gpa == KVM_S390_STORE_STATUS_NOADDR) {
+ if (write_guest_abs(vcpu, 163, &archmode, 1))
+ return -EFAULT;
+- gpa = SAVE_AREA_BASE;
++ gpa = 0;
+ } else if (gpa == KVM_S390_STORE_STATUS_PREFIXED) {
+ if (write_guest_real(vcpu, 163, &archmode, 1))
+ return -EFAULT;
+- gpa = kvm_s390_real_to_abs(vcpu, SAVE_AREA_BASE);
++ gpa = px;
++ } else
++ gpa -= __LC_FPREGS_SAVE_AREA;
++
++ /* manually convert vector registers if necessary */
++ if (MACHINE_HAS_VX) {
++ convert_vx_to_fp(fprs, (__vector128 *) vcpu->run->s.regs.vrs);
++ rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
++ fprs, 128);
++ } else {
++ rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
++ vcpu->run->s.regs.vrs, 128);
+ }
+- rc = write_guest_abs(vcpu, gpa + offsetof(struct save_area, fp_regs),
+- vcpu->arch.guest_fpregs.fprs, 128);
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, gp_regs),
++ rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA,
+ vcpu->run->s.regs.gprs, 128);
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, psw),
++ rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA,
+ &vcpu->arch.sie_block->gpsw, 16);
+- px = kvm_s390_get_prefix(vcpu);
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, pref_reg),
++ rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA,
+ &px, 4);
+- rc |= write_guest_abs(vcpu,
+- gpa + offsetof(struct save_area, fp_ctrl_reg),
+- &vcpu->arch.guest_fpregs.fpc, 4);
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, tod_reg),
++ rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA,
++ &vcpu->run->s.regs.fpc, 4);
++ rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA,
+ &vcpu->arch.sie_block->todpr, 4);
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, timer),
++ rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA,
+ &vcpu->arch.sie_block->cputm, 8);
+ clkcomp = vcpu->arch.sie_block->ckc >> 8;
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, clk_cmp),
++ rc |= write_guest_abs(vcpu, gpa + __LC_CLOCK_COMP_SAVE_AREA,
+ &clkcomp, 8);
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, acc_regs),
++ rc |= write_guest_abs(vcpu, gpa + __LC_AREGS_SAVE_AREA,
+ &vcpu->run->s.regs.acrs, 64);
+- rc |= write_guest_abs(vcpu, gpa + offsetof(struct save_area, ctrl_regs),
++ rc |= write_guest_abs(vcpu, gpa + __LC_CREGS_SAVE_AREA,
+ &vcpu->arch.sie_block->gcr, 128);
+ return rc ? -EFAULT : 0;
+ }
+@@ -2313,19 +2286,7 @@ int kvm_s390_vcpu_store_status(struct kv
+ * it into the save area
+ */
+ save_fpu_regs();
+- if (test_kvm_facility(vcpu->kvm, 129)) {
+- /*
+- * If the vector extension is available, the vector registers
+- * which overlaps with floating-point registers are saved in
+- * the SIE-control block. Hence, extract the floating-point
+- * registers and the FPC value and store them in the
+- * guest_fpregs structure.
+- */
+- vcpu->arch.guest_fpregs.fpc = current->thread.fpu.fpc;
+- convert_vx_to_fp(vcpu->arch.guest_fpregs.fprs,
+- current->thread.fpu.vxrs);
+- } else
+- save_fpu_to(&vcpu->arch.guest_fpregs);
++ vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
+ save_access_regs(vcpu->run->s.regs.acrs);
+
+ return kvm_s390_store_status_unloaded(vcpu, addr);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/mm/extable.c linux-libre-4.4.7-gnu/arch/s390/mm/extable.c
+--- linux-libre-4.4-gnu/arch/s390/mm/extable.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/mm/extable.c 2016-04-12 12:09:26.000000000 -0400
+@@ -52,12 +52,16 @@ void sort_extable(struct exception_table
+ int i;
+
+ /* Normalize entries to being relative to the start of the section */
+- for (p = start, i = 0; p < finish; p++, i += 8)
++ for (p = start, i = 0; p < finish; p++, i += 8) {
+ p->insn += i;
++ p->fixup += i + 4;
++ }
+ sort(start, finish - start, sizeof(*start), cmp_ex, NULL);
+ /* Denormalize all entries */
+- for (p = start, i = 0; p < finish; p++, i += 8)
++ for (p = start, i = 0; p < finish; p++, i += 8) {
+ p->insn -= i;
++ p->fixup -= i + 4;
++ }
+ }
+
+ #ifdef CONFIG_MODULES
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/s390/pci/pci.c linux-libre-4.4.7-gnu/arch/s390/pci/pci.c
+--- linux-libre-4.4-gnu/arch/s390/pci/pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/s390/pci/pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -871,8 +871,11 @@ static inline int barsize(u8 size)
+
+ static int zpci_mem_init(void)
+ {
++ BUILD_BUG_ON(!is_power_of_2(__alignof__(struct zpci_fmb)) ||
++ __alignof__(struct zpci_fmb) < sizeof(struct zpci_fmb));
++
+ zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
+- 16, 0, NULL);
++ __alignof__(struct zpci_fmb), 0, NULL);
+ if (!zdev_fmb_cache)
+ goto error_zdev;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/sh/mm/kmap.c linux-libre-4.4.7-gnu/arch/sh/mm/kmap.c
+--- linux-libre-4.4-gnu/arch/sh/mm/kmap.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/sh/mm/kmap.c 2016-04-12 12:09:26.000000000 -0400
+@@ -36,6 +36,7 @@ void *kmap_coherent(struct page *page, u
+
+ BUG_ON(!test_bit(PG_dcache_clean, &page->flags));
+
++ preempt_disable();
+ pagefault_disable();
+
+ idx = FIX_CMAP_END -
+@@ -64,4 +65,5 @@ void kunmap_coherent(void *kvaddr)
+ }
+
+ pagefault_enable();
++ preempt_enable();
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/sparc/kernel/sys_sparc_64.c linux-libre-4.4.7-gnu/arch/sparc/kernel/sys_sparc_64.c
+--- linux-libre-4.4-gnu/arch/sparc/kernel/sys_sparc_64.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/sparc/kernel/sys_sparc_64.c 2016-04-12 12:09:26.000000000 -0400
+@@ -413,7 +413,7 @@ out:
+
+ SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)
+ {
+- int ret;
++ long ret;
+
+ if (personality(current->personality) == PER_LINUX32 &&
+ personality(personality) == PER_LINUX)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/um/drivers/mconsole_kern.c linux-libre-4.4.7-gnu/arch/um/drivers/mconsole_kern.c
+--- linux-libre-4.4-gnu/arch/um/drivers/mconsole_kern.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/um/drivers/mconsole_kern.c 2016-04-12 12:09:26.000000000 -0400
+@@ -133,7 +133,7 @@ void mconsole_proc(struct mc_request *re
+ ptr += strlen("proc");
+ ptr = skip_spaces(ptr);
+
+- file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
++ file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY, 0);
+ if (IS_ERR(file)) {
+ mconsole_reply(req, "Failed to open file", 1, 0);
+ printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file));
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/um/os-Linux/start_up.c linux-libre-4.4.7-gnu/arch/um/os-Linux/start_up.c
+--- linux-libre-4.4-gnu/arch/um/os-Linux/start_up.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/um/os-Linux/start_up.c 2016-04-12 12:09:26.000000000 -0400
+@@ -94,6 +94,8 @@ static int start_ptraced_child(void)
+ {
+ int pid, n, status;
+
++ fflush(stdout);
++
+ pid = fork();
+ if (pid == 0)
+ ptrace_child();
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/crypto/chacha20-ssse3-x86_64.S linux-libre-4.4.7-gnu/arch/x86/crypto/chacha20-ssse3-x86_64.S
+--- linux-libre-4.4-gnu/arch/x86/crypto/chacha20-ssse3-x86_64.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/crypto/chacha20-ssse3-x86_64.S 2016-04-12 12:09:26.000000000 -0400
+@@ -157,7 +157,9 @@ ENTRY(chacha20_4block_xor_ssse3)
+ # done with the slightly better performing SSSE3 byte shuffling,
+ # 7/12-bit word rotation uses traditional shift+OR.
+
+- sub $0x40,%rsp
++ mov %rsp,%r11
++ sub $0x80,%rsp
++ and $~63,%rsp
+
+ # x0..15[0-3] = s0..3[0..3]
+ movq 0x00(%rdi),%xmm1
+@@ -620,6 +622,6 @@ ENTRY(chacha20_4block_xor_ssse3)
+ pxor %xmm1,%xmm15
+ movdqu %xmm15,0xf0(%rsi)
+
+- add $0x40,%rsp
++ mov %r11,%rsp
+ ret
+ ENDPROC(chacha20_4block_xor_ssse3)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/entry/common.c linux-libre-4.4.7-gnu/arch/x86/entry/common.c
+--- linux-libre-4.4-gnu/arch/x86/entry/common.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/entry/common.c 2016-04-12 12:09:26.000000000 -0400
+@@ -268,6 +268,7 @@ static void exit_to_usermode_loop(struct
+ /* Called with IRQs disabled. */
+ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
+ {
++ struct thread_info *ti = pt_regs_to_thread_info(regs);
+ u32 cached_flags;
+
+ if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled()))
+@@ -275,12 +276,22 @@ __visible inline void prepare_exit_to_us
+
+ lockdep_sys_exit();
+
+- cached_flags =
+- READ_ONCE(pt_regs_to_thread_info(regs)->flags);
++ cached_flags = READ_ONCE(ti->flags);
+
+ if (unlikely(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS))
+ exit_to_usermode_loop(regs, cached_flags);
+
++#ifdef CONFIG_COMPAT
++ /*
++ * Compat syscalls set TS_COMPAT. Make sure we clear it before
++ * returning to user mode. We need to clear it *after* signal
++ * handling, because syscall restart has a fixup for compat
++ * syscalls. The fixup is exercised by the ptrace_syscall_32
++ * selftest.
++ */
++ ti->status &= ~TS_COMPAT;
++#endif
++
+ user_enter();
+ }
+
+@@ -332,14 +343,6 @@ __visible inline void syscall_return_slo
+ if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS))
+ syscall_slow_exit_work(regs, cached_flags);
+
+-#ifdef CONFIG_COMPAT
+- /*
+- * Compat syscalls set TS_COMPAT. Make sure we clear it before
+- * returning to user mode.
+- */
+- ti->status &= ~TS_COMPAT;
+-#endif
+-
+ local_irq_disable();
+ prepare_exit_to_usermode(regs);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/entry/entry_64_compat.S linux-libre-4.4.7-gnu/arch/x86/entry/entry_64_compat.S
+--- linux-libre-4.4-gnu/arch/x86/entry/entry_64_compat.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/entry/entry_64_compat.S 2016-04-12 12:09:26.000000000 -0400
+@@ -267,6 +267,7 @@ ENTRY(entry_INT80_compat)
+ * Interrupts are off on entry.
+ */
+ PARAVIRT_ADJUST_EXCEPTION_FRAME
++ ASM_CLAC /* Do this early to minimize exposure */
+ SWAPGS
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/apic.h linux-libre-4.4.7-gnu/arch/x86/include/asm/apic.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/apic.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/apic.h 2016-04-12 12:09:26.000000000 -0400
+@@ -638,8 +638,8 @@ static inline void entering_irq(void)
+
+ static inline void entering_ack_irq(void)
+ {
+- ack_APIC_irq();
+ entering_irq();
++ ack_APIC_irq();
+ }
+
+ static inline void ipi_entering_ack_irq(void)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/boot.h linux-libre-4.4.7-gnu/arch/x86/include/asm/boot.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/boot.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/boot.h 2016-04-12 12:09:26.000000000 -0400
+@@ -27,7 +27,7 @@
+ #define BOOT_HEAP_SIZE 0x400000
+ #else /* !CONFIG_KERNEL_BZIP2 */
+
+-#define BOOT_HEAP_SIZE 0x8000
++#define BOOT_HEAP_SIZE 0x10000
+
+ #endif /* !CONFIG_KERNEL_BZIP2 */
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/hw_irq.h linux-libre-4.4.7-gnu/arch/x86/include/asm/hw_irq.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/hw_irq.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/hw_irq.h 2016-04-12 12:09:26.000000000 -0400
+@@ -136,6 +136,7 @@ struct irq_alloc_info {
+ struct irq_cfg {
+ unsigned int dest_apicid;
+ u8 vector;
++ u8 old_vector;
+ };
+
+ extern struct irq_cfg *irq_cfg(unsigned int irq);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/irq.h linux-libre-4.4.7-gnu/arch/x86/include/asm/irq.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/irq.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/irq.h 2016-04-12 12:09:26.000000000 -0400
+@@ -23,11 +23,13 @@ extern void irq_ctx_init(int cpu);
+
+ #define __ARCH_HAS_DO_SOFTIRQ
+
++struct irq_desc;
++
+ #ifdef CONFIG_HOTPLUG_CPU
+ #include <linux/cpumask.h>
+ extern int check_irq_vectors_for_cpu_disable(void);
+ extern void fixup_irqs(void);
+-extern void irq_force_complete_move(int);
++extern void irq_force_complete_move(struct irq_desc *desc);
+ #endif
+
+ #ifdef CONFIG_HAVE_KVM
+@@ -37,7 +39,6 @@ extern void kvm_set_posted_intr_wakeup_h
+ extern void (*x86_platform_ipi_callback)(void);
+ extern void native_init_IRQ(void);
+
+-struct irq_desc;
+ extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs);
+
+ extern __visible unsigned int do_IRQ(struct pt_regs *regs);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/microcode.h linux-libre-4.4.7-gnu/arch/x86/include/asm/microcode.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/microcode.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/microcode.h 2016-04-12 12:09:26.000000000 -0400
+@@ -2,6 +2,7 @@
+ #define _ASM_X86_MICROCODE_H
+
+ #include <linux/earlycpio.h>
++#include <linux/initrd.h>
+
+ #define native_rdmsr(msr, val1, val2) \
+ do { \
+@@ -168,4 +169,29 @@ static inline void reload_early_microcod
+ static inline bool
+ get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; }
+ #endif
++
++static inline unsigned long get_initrd_start(void)
++{
++#ifdef CONFIG_BLK_DEV_INITRD
++ return initrd_start;
++#else
++ return 0;
++#endif
++}
++
++static inline unsigned long get_initrd_start_addr(void)
++{
++#ifdef CONFIG_BLK_DEV_INITRD
++#ifdef CONFIG_X86_32
++ unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
++
++ return (unsigned long)__pa_nodebug(*initrd_start_p);
++#else
++ return get_initrd_start();
++#endif
++#else /* CONFIG_BLK_DEV_INITRD */
++ return 0;
++#endif
++}
++
+ #endif /* _ASM_X86_MICROCODE_H */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/mmu_context.h linux-libre-4.4.7-gnu/arch/x86/include/asm/mmu_context.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/mmu_context.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/mmu_context.h 2016-04-12 12:09:26.000000000 -0400
+@@ -116,8 +116,36 @@ static inline void switch_mm(struct mm_s
+ #endif
+ cpumask_set_cpu(cpu, mm_cpumask(next));
+
+- /* Re-load page tables */
++ /*
++ * Re-load page tables.
++ *
++ * This logic has an ordering constraint:
++ *
++ * CPU 0: Write to a PTE for 'next'
++ * CPU 0: load bit 1 in mm_cpumask. if nonzero, send IPI.
++ * CPU 1: set bit 1 in next's mm_cpumask
++ * CPU 1: load from the PTE that CPU 0 writes (implicit)
++ *
++ * We need to prevent an outcome in which CPU 1 observes
++ * the new PTE value and CPU 0 observes bit 1 clear in
++ * mm_cpumask. (If that occurs, then the IPI will never
++ * be sent, and CPU 0's TLB will contain a stale entry.)
++ *
++ * The bad outcome can occur if either CPU's load is
++ * reordered before that CPU's store, so both CPUs must
++ * execute full barriers to prevent this from happening.
++ *
++ * Thus, switch_mm needs a full barrier between the
++ * store to mm_cpumask and any operation that could load
++ * from next->pgd. TLB fills are special and can happen
++ * due to instruction fetches or for no reason at all,
++ * and neither LOCK nor MFENCE orders them.
++ * Fortunately, load_cr3() is serializing and gives the
++ * ordering guarantee we need.
++ *
++ */
+ load_cr3(next->pgd);
++
+ trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
+
+ /* Stop flush ipis for the previous mm */
+@@ -156,10 +184,14 @@ static inline void switch_mm(struct mm_s
+ * schedule, protecting us from simultaneous changes.
+ */
+ cpumask_set_cpu(cpu, mm_cpumask(next));
++
+ /*
+ * We were in lazy tlb mode and leave_mm disabled
+ * tlb flush IPI delivery. We must reload CR3
+ * to make sure to use no freed page tables.
++ *
++ * As above, load_cr3() is serializing and orders TLB
++ * fills with respect to the mm_cpumask write.
+ */
+ load_cr3(next->pgd);
+ trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/perf_event.h linux-libre-4.4.7-gnu/arch/x86/include/asm/perf_event.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/perf_event.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/perf_event.h 2016-04-12 12:09:26.000000000 -0400
+@@ -165,6 +165,7 @@ struct x86_pmu_capability {
+ #define GLOBAL_STATUS_ASIF BIT_ULL(60)
+ #define GLOBAL_STATUS_COUNTERS_FROZEN BIT_ULL(59)
+ #define GLOBAL_STATUS_LBRS_FROZEN BIT_ULL(58)
++#define GLOBAL_STATUS_TRACE_TOPAPMI BIT_ULL(55)
+
+ /*
+ * IBS cpuid feature detection
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/pgtable_types.h linux-libre-4.4.7-gnu/arch/x86/include/asm/pgtable_types.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/pgtable_types.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/pgtable_types.h 2016-04-12 12:09:26.000000000 -0400
+@@ -363,20 +363,18 @@ static inline enum page_cache_mode pgpro
+ }
+ static inline pgprot_t pgprot_4k_2_large(pgprot_t pgprot)
+ {
++ pgprotval_t val = pgprot_val(pgprot);
+ pgprot_t new;
+- unsigned long val;
+
+- val = pgprot_val(pgprot);
+ pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) |
+ ((val & _PAGE_PAT) << (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT));
+ return new;
+ }
+ static inline pgprot_t pgprot_large_2_4k(pgprot_t pgprot)
+ {
++ pgprotval_t val = pgprot_val(pgprot);
+ pgprot_t new;
+- unsigned long val;
+
+- val = pgprot_val(pgprot);
+ pgprot_val(new) = (val & ~(_PAGE_PAT | _PAGE_PAT_LARGE)) |
+ ((val & _PAGE_PAT_LARGE) >>
+ (_PAGE_BIT_PAT_LARGE - _PAGE_BIT_PAT));
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/include/asm/xen/hypervisor.h linux-libre-4.4.7-gnu/arch/x86/include/asm/xen/hypervisor.h
+--- linux-libre-4.4-gnu/arch/x86/include/asm/xen/hypervisor.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/include/asm/xen/hypervisor.h 2016-04-12 12:09:26.000000000 -0400
+@@ -62,4 +62,6 @@ void xen_arch_register_cpu(int num);
+ void xen_arch_unregister_cpu(int num);
+ #endif
+
++extern void xen_set_iopl_mask(unsigned mask);
++
+ #endif /* _ASM_X86_XEN_HYPERVISOR_H */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/Kconfig linux-libre-4.4.7-gnu/arch/x86/Kconfig
+--- linux-libre-4.4-gnu/arch/x86/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -1126,22 +1126,23 @@ config MICROCODE
+ bool "CPU microcode loading support"
+ default y
+ depends on CPU_SUP_AMD || CPU_SUP_INTEL
+- depends on BLK_DEV_INITRD
+ select FW_LOADER
+ ---help---
+-
+ If you say Y here, you will be able to update the microcode on
+- certain Intel and AMD processors. The Intel support is for the
+- IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4,
+- Xeon etc. The AMD support is for families 0x10 and later. You will
+- obviously need the actual microcode binary data itself which is not
+- shipped with the Linux kernel.
++ Intel and AMD processors. The Intel support is for the IA32 family,
++ e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The
++ AMD support is for families 0x10 and later. You will obviously need
++ the actual microcode binary data itself which is not shipped with
++ the Linux kernel.
+
+- This option selects the general module only, you need to select
+- at least one vendor specific module as well.
++ The preferred method to load microcode from a detached initrd is described
++ in Documentation/x86/early-microcode.txt. For that you need to enable
++ CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the
++ initrd for microcode blobs.
+
+- To compile this driver as a module, choose M here: the module
+- will be called microcode.
++ In addition, you can build-in the microcode into the kernel. For that you
++ need to enable FIRMWARE_IN_KERNEL and add the vendor-supplied microcode
++ to the CONFIG_EXTRA_FIRMWARE config option.
+
+ config MICROCODE_INTEL
+ bool "Intel microcode loading support"
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/acpi/sleep.c linux-libre-4.4.7-gnu/arch/x86/kernel/acpi/sleep.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/acpi/sleep.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/acpi/sleep.c 2016-04-12 12:09:26.000000000 -0400
+@@ -16,6 +16,7 @@
+ #include <asm/cacheflush.h>
+ #include <asm/realmode.h>
+
++#include <linux/ftrace.h>
+ #include "../../realmode/rm/wakeup.h"
+ #include "sleep.h"
+
+@@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void)
+ saved_magic = 0x123456789abcdef0L;
+ #endif /* CONFIG_64BIT */
+
++ /*
++ * Pause/unpause graph tracing around do_suspend_lowlevel as it has
++ * inconsistent call/return info after it jumps to the wakeup vector.
++ */
++ pause_graph_tracing();
+ do_suspend_lowlevel();
++ unpause_graph_tracing();
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-4.4.7-gnu/arch/x86/kernel/apic/io_apic.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/apic/io_apic.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/apic/io_apic.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2521,6 +2521,7 @@ void __init setup_ioapic_dest(void)
+ {
+ int pin, ioapic, irq, irq_entry;
+ const struct cpumask *mask;
++ struct irq_desc *desc;
+ struct irq_data *idata;
+ struct irq_chip *chip;
+
+@@ -2536,7 +2537,9 @@ void __init setup_ioapic_dest(void)
+ if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
+ continue;
+
+- idata = irq_get_irq_data(irq);
++ desc = irq_to_desc(irq);
++ raw_spin_lock_irq(&desc->lock);
++ idata = irq_desc_get_irq_data(desc);
+
+ /*
+ * Honour affinities which have been set in early boot
+@@ -2550,6 +2553,7 @@ void __init setup_ioapic_dest(void)
+ /* Might be lapic_chip for irq 0 */
+ if (chip->irq_set_affinity)
+ chip->irq_set_affinity(idata, mask, false);
++ raw_spin_unlock_irq(&desc->lock);
+ }
+ }
+ #endif
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/apic/vector.c linux-libre-4.4.7-gnu/arch/x86/kernel/apic/vector.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/apic/vector.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/apic/vector.c 2016-04-12 12:09:26.000000000 -0400
+@@ -30,7 +30,7 @@ struct apic_chip_data {
+
+ struct irq_domain *x86_vector_domain;
+ static DEFINE_RAW_SPINLOCK(vector_lock);
+-static cpumask_var_t vector_cpumask;
++static cpumask_var_t vector_cpumask, vector_searchmask, searched_cpumask;
+ static struct irq_chip lapic_controller;
+ #ifdef CONFIG_X86_IO_APIC
+ static struct apic_chip_data *legacy_irq_data[NR_IRQS_LEGACY];
+@@ -116,35 +116,47 @@ static int __assign_irq_vector(int irq,
+ */
+ static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
+ static int current_offset = VECTOR_OFFSET_START % 16;
+- int cpu, err;
++ int cpu, vector;
+
+- if (d->move_in_progress)
++ /*
++ * If there is still a move in progress or the previous move has not
++ * been cleaned up completely, tell the caller to come back later.
++ */
++ if (d->move_in_progress ||
++ cpumask_intersects(d->old_domain, cpu_online_mask))
+ return -EBUSY;
+
+ /* Only try and allocate irqs on cpus that are present */
+- err = -ENOSPC;
+ cpumask_clear(d->old_domain);
++ cpumask_clear(searched_cpumask);
+ cpu = cpumask_first_and(mask, cpu_online_mask);
+ while (cpu < nr_cpu_ids) {
+- int new_cpu, vector, offset;
++ int new_cpu, offset;
+
++ /* Get the possible target cpus for @mask/@cpu from the apic */
+ apic->vector_allocation_domain(cpu, vector_cpumask, mask);
+
++ /*
++ * Clear the offline cpus from @vector_cpumask for searching
++ * and verify whether the result overlaps with @mask. If true,
++ * then the call to apic->cpu_mask_to_apicid_and() will
++ * succeed as well. If not, no point in trying to find a
++ * vector in this mask.
++ */
++ cpumask_and(vector_searchmask, vector_cpumask, cpu_online_mask);
++ if (!cpumask_intersects(vector_searchmask, mask))
++ goto next_cpu;
++
+ if (cpumask_subset(vector_cpumask, d->domain)) {
+- err = 0;
+ if (cpumask_equal(vector_cpumask, d->domain))
+- break;
++ goto success;
+ /*
+- * New cpumask using the vector is a proper subset of
+- * the current in use mask. So cleanup the vector
+- * allocation for the members that are not used anymore.
++ * Mark the cpus which are not longer in the mask for
++ * cleanup.
+ */
+- cpumask_andnot(d->old_domain, d->domain,
+- vector_cpumask);
+- d->move_in_progress =
+- cpumask_intersects(d->old_domain, cpu_online_mask);
+- cpumask_and(d->domain, d->domain, vector_cpumask);
+- break;
++ cpumask_andnot(d->old_domain, d->domain, vector_cpumask);
++ vector = d->cfg.vector;
++ goto update;
+ }
+
+ vector = current_vector;
+@@ -156,45 +168,61 @@ next:
+ vector = FIRST_EXTERNAL_VECTOR + offset;
+ }
+
+- if (unlikely(current_vector == vector)) {
+- cpumask_or(d->old_domain, d->old_domain,
+- vector_cpumask);
+- cpumask_andnot(vector_cpumask, mask, d->old_domain);
+- cpu = cpumask_first_and(vector_cpumask,
+- cpu_online_mask);
+- continue;
+- }
++ /* If the search wrapped around, try the next cpu */
++ if (unlikely(current_vector == vector))
++ goto next_cpu;
+
+ if (test_bit(vector, used_vectors))
+ goto next;
+
+- for_each_cpu_and(new_cpu, vector_cpumask, cpu_online_mask) {
++ for_each_cpu(new_cpu, vector_searchmask) {
+ if (!IS_ERR_OR_NULL(per_cpu(vector_irq, new_cpu)[vector]))
+ goto next;
+ }
+ /* Found one! */
+ current_vector = vector;
+ current_offset = offset;
+- if (d->cfg.vector) {
++ /* Schedule the old vector for cleanup on all cpus */
++ if (d->cfg.vector)
+ cpumask_copy(d->old_domain, d->domain);
+- d->move_in_progress =
+- cpumask_intersects(d->old_domain, cpu_online_mask);
+- }
+- for_each_cpu_and(new_cpu, vector_cpumask, cpu_online_mask)
++ for_each_cpu(new_cpu, vector_searchmask)
+ per_cpu(vector_irq, new_cpu)[vector] = irq_to_desc(irq);
+- d->cfg.vector = vector;
+- cpumask_copy(d->domain, vector_cpumask);
+- err = 0;
+- break;
+- }
++ goto update;
+
+- if (!err) {
+- /* cache destination APIC IDs into cfg->dest_apicid */
+- err = apic->cpu_mask_to_apicid_and(mask, d->domain,
+- &d->cfg.dest_apicid);
++next_cpu:
++ /*
++ * We exclude the current @vector_cpumask from the requested
++ * @mask and try again with the next online cpu in the
++ * result. We cannot modify @mask, so we use @vector_cpumask
++ * as a temporary buffer here as it will be reassigned when
++ * calling apic->vector_allocation_domain() above.
++ */
++ cpumask_or(searched_cpumask, searched_cpumask, vector_cpumask);
++ cpumask_andnot(vector_cpumask, mask, searched_cpumask);
++ cpu = cpumask_first_and(vector_cpumask, cpu_online_mask);
++ continue;
+ }
++ return -ENOSPC;
+
+- return err;
++update:
++ /*
++ * Exclude offline cpus from the cleanup mask and set the
++ * move_in_progress flag when the result is not empty.
++ */
++ cpumask_and(d->old_domain, d->old_domain, cpu_online_mask);
++ d->move_in_progress = !cpumask_empty(d->old_domain);
++ d->cfg.old_vector = d->move_in_progress ? d->cfg.vector : 0;
++ d->cfg.vector = vector;
++ cpumask_copy(d->domain, vector_cpumask);
++success:
++ /*
++ * Cache destination APIC IDs into cfg->dest_apicid. This cannot fail
++ * as we already established, that mask & d->domain & cpu_online_mask
++ * is not empty.
++ */
++ BUG_ON(apic->cpu_mask_to_apicid_and(mask, d->domain,
++ &d->cfg.dest_apicid));
++ return 0;
+ }
+
+ static int assign_irq_vector(int irq, struct apic_chip_data *data,
+@@ -224,10 +252,8 @@ static int assign_irq_vector_policy(int
+ static void clear_irq_vector(int irq, struct apic_chip_data *data)
+ {
+ struct irq_desc *desc;
+- unsigned long flags;
+ int cpu, vector;
+
+- raw_spin_lock_irqsave(&vector_lock, flags);
+ BUG_ON(!data->cfg.vector);
+
+ vector = data->cfg.vector;
+@@ -237,10 +263,13 @@ static void clear_irq_vector(int irq, st
+ data->cfg.vector = 0;
+ cpumask_clear(data->domain);
+
+- if (likely(!data->move_in_progress)) {
+- raw_spin_unlock_irqrestore(&vector_lock, flags);
++ /*
++ * If move is in progress or the old_domain mask is not empty,
++ * i.e. the cleanup IPI has not been processed yet, we need to remove
++ * the old references to desc from all cpus vector tables.
++ */
++ if (!data->move_in_progress && cpumask_empty(data->old_domain))
+ return;
+- }
+
+ desc = irq_to_desc(irq);
+ for_each_cpu_and(cpu, data->old_domain, cpu_online_mask) {
+@@ -253,7 +282,6 @@ static void clear_irq_vector(int irq, st
+ }
+ }
+ data->move_in_progress = 0;
+- raw_spin_unlock_irqrestore(&vector_lock, flags);
+ }
+
+ void init_irq_alloc_info(struct irq_alloc_info *info,
+@@ -274,19 +302,24 @@ void copy_irq_alloc_info(struct irq_allo
+ static void x86_vector_free_irqs(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs)
+ {
++ struct apic_chip_data *apic_data;
+ struct irq_data *irq_data;
++ unsigned long flags;
+ int i;
+
+ for (i = 0; i < nr_irqs; i++) {
+ irq_data = irq_domain_get_irq_data(x86_vector_domain, virq + i);
+ if (irq_data && irq_data->chip_data) {
++ raw_spin_lock_irqsave(&vector_lock, flags);
+ clear_irq_vector(virq + i, irq_data->chip_data);
+- free_apic_chip_data(irq_data->chip_data);
++ apic_data = irq_data->chip_data;
++ irq_domain_reset_irq_data(irq_data);
++ raw_spin_unlock_irqrestore(&vector_lock, flags);
++ free_apic_chip_data(apic_data);
+ #ifdef CONFIG_X86_IO_APIC
+ if (virq + i < nr_legacy_irqs())
+ legacy_irq_data[virq + i] = NULL;
+ #endif
+- irq_domain_reset_irq_data(irq_data);
+ }
+ }
+ }
+@@ -404,6 +437,8 @@ int __init arch_early_irq_init(void)
+ arch_init_htirq_domain(x86_vector_domain);
+
+ BUG_ON(!alloc_cpumask_var(&vector_cpumask, GFP_KERNEL));
++ BUG_ON(!alloc_cpumask_var(&vector_searchmask, GFP_KERNEL));
++ BUG_ON(!alloc_cpumask_var(&searched_cpumask, GFP_KERNEL));
+
+ return arch_early_ioapic_init();
+ }
+@@ -492,14 +527,7 @@ static int apic_set_affinity(struct irq_
+ return -EINVAL;
+
+ err = assign_irq_vector(irq, data, dest);
+- if (err) {
+- if (assign_irq_vector(irq, data,
+- irq_data_get_affinity_mask(irq_data)))
+- pr_err("Failed to recover vector for irq %d\n", irq);
+- return err;
+- }
+-
+- return IRQ_SET_MASK_OK;
++ return err ? err : IRQ_SET_MASK_OK;
+ }
+
+ static struct irq_chip lapic_controller = {
+@@ -511,20 +539,12 @@ static struct irq_chip lapic_controller
+ #ifdef CONFIG_SMP
+ static void __send_cleanup_vector(struct apic_chip_data *data)
+ {
+- cpumask_var_t cleanup_mask;
+-
+- if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+- unsigned int i;
+-
+- for_each_cpu_and(i, data->old_domain, cpu_online_mask)
+- apic->send_IPI_mask(cpumask_of(i),
+- IRQ_MOVE_CLEANUP_VECTOR);
+- } else {
+- cpumask_and(cleanup_mask, data->old_domain, cpu_online_mask);
+- apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+- free_cpumask_var(cleanup_mask);
+- }
++ raw_spin_lock(&vector_lock);
++ cpumask_and(data->old_domain, data->old_domain, cpu_online_mask);
+ data->move_in_progress = 0;
++ if (!cpumask_empty(data->old_domain))
++ apic->send_IPI_mask(data->old_domain, IRQ_MOVE_CLEANUP_VECTOR);
++ raw_spin_unlock(&vector_lock);
+ }
+
+ void send_cleanup_vector(struct irq_cfg *cfg)
+@@ -568,12 +588,25 @@ asmlinkage __visible void smp_irq_move_c
+ goto unlock;
+
+ /*
+- * Check if the irq migration is in progress. If so, we
+- * haven't received the cleanup request yet for this irq.
++ * Nothing to cleanup if irq migration is in progress
++ * or this cpu is not set in the cleanup mask.
+ */
+- if (data->move_in_progress)
++ if (data->move_in_progress ||
++ !cpumask_test_cpu(me, data->old_domain))
+ goto unlock;
+
++ /*
++ * We have two cases to handle here:
++ * 1) vector is unchanged but the target mask got reduced
++ * 2) vector and the target mask has changed
++ *
++ * #1 is obvious, but in #2 we have two vectors with the same
++ * irq descriptor: the old and the new vector. So we need to
++ * make sure that we only cleanup the old vector. The new
++ * vector has the current @vector number in the config and
++ * this cpu is part of the target mask. We better leave that
++ * one alone.
++ */
+ if (vector == data->cfg.vector &&
+ cpumask_test_cpu(me, data->domain))
+ goto unlock;
+@@ -591,6 +624,7 @@ asmlinkage __visible void smp_irq_move_c
+ goto unlock;
+ }
+ __this_cpu_write(vector_irq[vector], VECTOR_UNUSED);
++ cpumask_clear_cpu(me, data->old_domain);
+ unlock:
+ raw_spin_unlock(&desc->lock);
+ }
+@@ -619,12 +653,99 @@ void irq_complete_move(struct irq_cfg *c
+ __irq_complete_move(cfg, ~get_irq_regs()->orig_ax);
+ }
+
+-void irq_force_complete_move(int irq)
++/*
++ * Called from fixup_irqs() with @desc->lock held and interrupts disabled.
++ */
++void irq_force_complete_move(struct irq_desc *desc)
+ {
+- struct irq_cfg *cfg = irq_cfg(irq);
++ struct irq_data *irqdata = irq_desc_get_irq_data(desc);
++ struct apic_chip_data *data = apic_chip_data(irqdata);
++ struct irq_cfg *cfg = data ? &data->cfg : NULL;
++ unsigned int cpu;
+
+- if (cfg)
+- __irq_complete_move(cfg, cfg->vector);
++ if (!cfg)
++ return;
++
++ /*
++ * This is tricky. If the cleanup of @data->old_domain has not been
++ * done yet, then the following setaffinity call will fail with
++ * -EBUSY. This can leave the interrupt in a stale state.
++ *
++ * All CPUs are stuck in stop machine with interrupts disabled so
++ * calling __irq_complete_move() would be completely pointless.
++ */
++ raw_spin_lock(&vector_lock);
++ /*
++ * Clean out all offline cpus (including the outgoing one) from the
++ * old_domain mask.
++ */
++ cpumask_and(data->old_domain, data->old_domain, cpu_online_mask);
++
++ /*
++ * If move_in_progress is cleared and the old_domain mask is empty,
++ * then there is nothing to cleanup. fixup_irqs() will take care of
++ * the stale vectors on the outgoing cpu.
++ */
++ if (!data->move_in_progress && cpumask_empty(data->old_domain)) {
++ raw_spin_unlock(&vector_lock);
++ return;
++ }
++
++ /*
++ * 1) The interrupt is in move_in_progress state. That means that we
++ * have not seen an interrupt since the io_apic was reprogrammed to
++ * the new vector.
++ *
++ * 2) The interrupt has fired on the new vector, but the cleanup IPIs
++ * have not been processed yet.
++ */
++ if (data->move_in_progress) {
++ /*
++ * In theory there is a race:
++ *
++ * set_ioapic(new_vector) <-- Interrupt is raised before update
++ * is effective, i.e. it's raised on
++ * the old vector.
++ *
++ * So if the target cpu cannot handle that interrupt before
++ * the old vector is cleaned up, we get a spurious interrupt
++ * and in the worst case the ioapic irq line becomes stale.
++ *
++ * But in case of cpu hotplug this should be a non issue
++ * because if the affinity update happens right before all
++ * cpus rendevouz in stop machine, there is no way that the
++ * interrupt can be blocked on the target cpu because all cpus
++ * loops first with interrupts enabled in stop machine, so the
++ * old vector is not yet cleaned up when the interrupt fires.
++ *
++ * So the only way to run into this issue is if the delivery
++ * of the interrupt on the apic/system bus would be delayed
++ * beyond the point where the target cpu disables interrupts
++ * in stop machine. I doubt that it can happen, but at least
++ * there is a theroretical chance. Virtualization might be
++ * able to expose this, but AFAICT the IOAPIC emulation is not
++ * as stupid as the real hardware.
++ *
++ * Anyway, there is nothing we can do about that at this point
++ * w/o refactoring the whole fixup_irq() business completely.
++ * We print at least the irq number and the old vector number,
++ * so we have the necessary information when a problem in that
++ * area arises.
++ */
++ pr_warn("IRQ fixup: irq %d move in progress, old vector %d\n",
++ irqdata->irq, cfg->old_vector);
++ }
++ /*
++ * If old_domain is not empty, then other cpus still have the irq
++ * descriptor set in their vector array. Clean it up.
++ */
++ for_each_cpu(cpu, data->old_domain)
++ per_cpu(vector_irq, cpu)[cfg->old_vector] = VECTOR_UNUSED;
++
++ /* Cleanup the left overs of the (half finished) move */
++ cpumask_clear(data->old_domain);
++ data->move_in_progress = 0;
++ raw_spin_unlock(&vector_lock);
+ }
+ #endif
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/cpu/microcode/intel.c linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/microcode/intel.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/cpu/microcode/intel.c 2016-01-10 20:55:06.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/microcode/intel.c 2016-04-12 21:11:04.000000000 -0400
+@@ -555,10 +555,14 @@ scan_microcode(struct mc_saved_data *mc_
+ cd.data = NULL;
+ cd.size = 0;
+
+- cd = find_cpio_data(p, (void *)start, size, &offset);
+- if (!cd.data) {
++ /* try built-in microcode if no initrd */
++ if (!size) {
+ if (!load_builtin_intel_microcode(&cd))
+ return UCODE_ERROR;
++ } else {
++ cd = find_cpio_data(p, (void *)start, size, &offset);
++ if (!cd.data)
++ return UCODE_ERROR;
+ }
+
+ return get_matching_model_microcode(0, start, cd.data, cd.size,
+@@ -694,7 +698,7 @@ int __init save_microcode_in_initrd_inte
+ if (count == 0)
+ return ret;
+
+- copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
++ copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, get_initrd_start(), count);
+ ret = save_microcode(&mc_saved_data, mc_saved, count);
+ if (ret)
+ pr_err("Cannot save microcode patches from initrd.\n");
+@@ -732,16 +736,20 @@ void __init load_ucode_intel_bsp(void)
+ struct boot_params *p;
+
+ p = (struct boot_params *)__pa_nodebug(&boot_params);
+- start = p->hdr.ramdisk_image;
+ size = p->hdr.ramdisk_size;
+
+- _load_ucode_intel_bsp(
+- (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
+- (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
+- start, size);
++ /*
++ * Set start only if we have an initrd image. We cannot use initrd_start
++ * because it is not set that early yet.
++ */
++ start = (size ? p->hdr.ramdisk_image : 0);
++
++ _load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
++ (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
++ start, size);
+ #else
+- start = boot_params.hdr.ramdisk_image + PAGE_OFFSET;
+ size = boot_params.hdr.ramdisk_size;
++ start = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0);
+
+ _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size);
+ #endif
+@@ -752,20 +760,14 @@ void load_ucode_intel_ap(void)
+ struct mc_saved_data *mc_saved_data_p;
+ struct ucode_cpu_info uci;
+ unsigned long *mc_saved_in_initrd_p;
+- unsigned long initrd_start_addr;
+ enum ucode_state ret;
+ #ifdef CONFIG_X86_32
+- unsigned long *initrd_start_p;
+
+- mc_saved_in_initrd_p =
+- (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
++ mc_saved_in_initrd_p = (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
+ mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
+- initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
+- initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p);
+ #else
+- mc_saved_data_p = &mc_saved_data;
+ mc_saved_in_initrd_p = mc_saved_in_initrd;
+- initrd_start_addr = initrd_start;
++ mc_saved_data_p = &mc_saved_data;
+ #endif
+
+ /*
+@@ -777,7 +779,7 @@ void load_ucode_intel_ap(void)
+
+ collect_cpu_info_early(&uci);
+ ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
+- initrd_start_addr, &uci);
++ get_initrd_start_addr(), &uci);
+
+ if (ret != UCODE_OK)
+ return;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event.c linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event.c 2016-04-12 12:09:26.000000000 -0400
+@@ -593,6 +593,19 @@ void x86_pmu_disable_all(void)
+ }
+ }
+
++/*
++ * There may be PMI landing after enabled=0. The PMI hitting could be before or
++ * after disable_all.
++ *
++ * If PMI hits before disable_all, the PMU will be disabled in the NMI handler.
++ * It will not be re-enabled in the NMI handler again, because enabled=0. After
++ * handling the NMI, disable_all will be called, which will not change the
++ * state either. If PMI hits after disable_all, the PMU is already disabled
++ * before entering NMI handler. The NMI handler will not change the state
++ * either.
++ *
++ * So either situation is harmless.
++ */
+ static void x86_pmu_disable(struct pmu *pmu)
+ {
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event.h linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event.h
+--- linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event.h 2016-04-12 12:09:26.000000000 -0400
+@@ -591,6 +591,7 @@ struct x86_pmu {
+ pebs_active :1,
+ pebs_broken :1;
+ int pebs_record_size;
++ int pebs_buffer_size;
+ void (*drain_pebs)(struct pt_regs *regs);
+ struct event_constraint *pebs_constraints;
+ void (*pebs_aliases)(struct perf_event *event);
+@@ -907,6 +908,8 @@ void intel_pmu_lbr_init_hsw(void);
+
+ void intel_pmu_lbr_init_skl(void);
+
++void intel_pmu_pebs_data_source_nhm(void);
++
+ int intel_pmu_setup_lbr_filter(struct perf_event *event);
+
+ void intel_pt_interrupt(void);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event_intel.c linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event_intel.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event_intel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event_intel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1458,7 +1458,15 @@ static __initconst const u64 slm_hw_cach
+ };
+
+ /*
+- * Use from PMIs where the LBRs are already disabled.
++ * Used from PMIs where the LBRs are already disabled.
++ *
++ * This function could be called consecutively. It is required to remain in
++ * disabled state if called consecutively.
++ *
++ * During consecutive calls, the same disable value will be written to related
++ * registers, so the PMU state remains unchanged. hw.state in
++ * intel_bts_disable_local will remain PERF_HES_STOPPED too in consecutive
++ * calls.
+ */
+ static void __intel_pmu_disable_all(void)
+ {
+@@ -1840,6 +1848,16 @@ again:
+ if (__test_and_clear_bit(62, (unsigned long *)&status)) {
+ handled++;
+ x86_pmu.drain_pebs(regs);
++ /*
++ * There are cases where, even though, the PEBS ovfl bit is set
++ * in GLOBAL_OVF_STATUS, the PEBS events may also have their
++ * overflow bits set for their counters. We must clear them
++ * here because they have been processed as exact samples in
++ * the drain_pebs() routine. They must not be processed again
++ * in the for_each_bit_set() loop for regular samples below.
++ */
++ status &= ~cpuc->pebs_enabled;
++ status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
+ }
+
+ /*
+@@ -1885,7 +1903,10 @@ again:
+ goto again;
+
+ done:
+- __intel_pmu_enable_all(0, true);
++ /* Only restore PMU state when it's active. See x86_pmu_disable(). */
++ if (cpuc->enabled)
++ __intel_pmu_enable_all(0, true);
++
+ /*
+ * Only unmask the NMI after the overflow counters
+ * have been reset. This avoids spurious NMIs on
+@@ -3315,6 +3336,7 @@ __init int intel_pmu_init(void)
+ intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
+ X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
+
++ intel_pmu_pebs_data_source_nhm();
+ x86_add_quirk(intel_nehalem_quirk);
+
+ pr_cont("Nehalem events, ");
+@@ -3377,6 +3399,7 @@ __init int intel_pmu_init(void)
+ intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
+ X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
+
++ intel_pmu_pebs_data_source_nhm();
+ pr_cont("Westmere events, ");
+ break;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c 2016-04-12 12:09:26.000000000 -0400
+@@ -51,7 +51,8 @@ union intel_x86_pebs_dse {
+ #define OP_LH (P(OP, LOAD) | P(LVL, HIT))
+ #define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS))
+
+-static const u64 pebs_data_source[] = {
++/* Version for Sandy Bridge and later */
++static u64 pebs_data_source[] = {
+ P(OP, LOAD) | P(LVL, MISS) | P(LVL, L3) | P(SNOOP, NA),/* 0x00:ukn L3 */
+ OP_LH | P(LVL, L1) | P(SNOOP, NONE), /* 0x01: L1 local */
+ OP_LH | P(LVL, LFB) | P(SNOOP, NONE), /* 0x02: LFB hit */
+@@ -70,6 +71,14 @@ static const u64 pebs_data_source[] = {
+ OP_LH | P(LVL, UNC) | P(SNOOP, NONE), /* 0x0f: uncached */
+ };
+
++/* Patch up minor differences in the bits */
++void __init intel_pmu_pebs_data_source_nhm(void)
++{
++ pebs_data_source[0x05] = OP_LH | P(LVL, L3) | P(SNOOP, HIT);
++ pebs_data_source[0x06] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
++ pebs_data_source[0x07] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
++}
++
+ static u64 precise_store_data(u64 status)
+ {
+ union intel_x86_pebs_dse dse;
+@@ -269,7 +278,7 @@ static int alloc_pebs_buffer(int cpu)
+ if (!x86_pmu.pebs)
+ return 0;
+
+- buffer = kzalloc_node(PEBS_BUFFER_SIZE, GFP_KERNEL, node);
++ buffer = kzalloc_node(x86_pmu.pebs_buffer_size, GFP_KERNEL, node);
+ if (unlikely(!buffer))
+ return -ENOMEM;
+
+@@ -286,7 +295,7 @@ static int alloc_pebs_buffer(int cpu)
+ per_cpu(insn_buffer, cpu) = ibuffer;
+ }
+
+- max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size;
++ max = x86_pmu.pebs_buffer_size / x86_pmu.pebs_record_size;
+
+ ds->pebs_buffer_base = (u64)(unsigned long)buffer;
+ ds->pebs_index = ds->pebs_buffer_base;
+@@ -1296,6 +1305,7 @@ void __init intel_ds_init(void)
+
+ x86_pmu.bts = boot_cpu_has(X86_FEATURE_BTS);
+ x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS);
++ x86_pmu.pebs_buffer_size = PEBS_BUFFER_SIZE;
+ if (x86_pmu.pebs) {
+ char pebs_type = x86_pmu.intel_cap.pebs_trap ? '+' : '-';
+ int format = x86_pmu.intel_cap.pebs_format;
+@@ -1304,6 +1314,14 @@ void __init intel_ds_init(void)
+ case 0:
+ printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
+ x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
++ /*
++ * Using >PAGE_SIZE buffers makes the WRMSR to
++ * PERF_GLOBAL_CTRL in intel_pmu_enable_all()
++ * mysteriously hang on Core2.
++ *
++ * As a workaround, we don't do this.
++ */
++ x86_pmu.pebs_buffer_size = PAGE_SIZE;
+ x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
+ break;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event_knc.c linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event_knc.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/cpu/perf_event_knc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/cpu/perf_event_knc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -263,7 +263,9 @@ again:
+ goto again;
+
+ done:
+- knc_pmu_enable_all(0);
++ /* Only restore PMU state when it's active. See x86_pmu_disable(). */
++ if (cpuc->enabled)
++ knc_pmu_enable_all(0);
+
+ return handled;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/ioport.c linux-libre-4.4.7-gnu/arch/x86/kernel/ioport.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/ioport.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/ioport.c 2016-04-12 12:09:26.000000000 -0400
+@@ -96,9 +96,14 @@ asmlinkage long sys_ioperm(unsigned long
+ SYSCALL_DEFINE1(iopl, unsigned int, level)
+ {
+ struct pt_regs *regs = current_pt_regs();
+- unsigned int old = (regs->flags >> 12) & 3;
+ struct thread_struct *t = &current->thread;
+
++ /*
++ * Careful: the IOPL bits in regs->flags are undefined under Xen PV
++ * and changing them has no effect.
++ */
++ unsigned int old = t->iopl >> X86_EFLAGS_IOPL_BIT;
++
+ if (level > 3)
+ return -EINVAL;
+ /* Trying to gain more privileges? */
+@@ -106,8 +111,9 @@ SYSCALL_DEFINE1(iopl, unsigned int, leve
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ }
+- regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
+- t->iopl = level << 12;
++ regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
++ (level << X86_EFLAGS_IOPL_BIT);
++ t->iopl = level << X86_EFLAGS_IOPL_BIT;
+ set_iopl_mask(t->iopl);
+
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/irq.c linux-libre-4.4.7-gnu/arch/x86/kernel/irq.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/irq.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/irq.c 2016-04-12 12:09:26.000000000 -0400
+@@ -462,7 +462,7 @@ void fixup_irqs(void)
+ * non intr-remapping case, we can't wait till this interrupt
+ * arrives at this cpu before completing the irq move.
+ */
+- irq_force_complete_move(irq);
++ irq_force_complete_move(desc);
+
+ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+ break_affinity = 1;
+@@ -470,6 +470,15 @@ void fixup_irqs(void)
+ }
+
+ chip = irq_data_get_irq_chip(data);
++ /*
++ * The interrupt descriptor might have been cleaned up
++ * already, but it is not yet removed from the radix tree
++ */
++ if (!chip) {
++ raw_spin_unlock(&desc->lock);
++ continue;
++ }
++
+ if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
+ chip->irq_mask(data);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/process_64.c linux-libre-4.4.7-gnu/arch/x86/kernel/process_64.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/process_64.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/process_64.c 2016-04-12 12:09:26.000000000 -0400
+@@ -48,6 +48,7 @@
+ #include <asm/syscalls.h>
+ #include <asm/debugreg.h>
+ #include <asm/switch_to.h>
++#include <asm/xen/hypervisor.h>
+
+ asmlinkage extern void ret_from_fork(void);
+
+@@ -411,6 +412,17 @@ __switch_to(struct task_struct *prev_p,
+ task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
+ __switch_to_xtra(prev_p, next_p, tss);
+
++#ifdef CONFIG_XEN
++ /*
++ * On Xen PV, IOPL bits in pt_regs->flags have no effect, and
++ * current_pt_regs()->flags may not match the current task's
++ * intended IOPL. We need to switch it manually.
++ */
++ if (unlikely(static_cpu_has(X86_FEATURE_XENPV) &&
++ prev->iopl != next->iopl))
++ xen_set_iopl_mask(next->iopl);
++#endif
++
+ if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
+ /*
+ * AMD CPUs have a misfeature: SYSRET sets the SS selector but
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kernel/reboot.c linux-libre-4.4.7-gnu/arch/x86/kernel/reboot.c
+--- linux-libre-4.4-gnu/arch/x86/kernel/reboot.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kernel/reboot.c 2016-04-12 12:09:26.000000000 -0400
+@@ -182,6 +182,14 @@ static struct dmi_system_id __initdata r
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
+ },
+ },
++ { /* Handle problems with rebooting on the iMac10,1. */
++ .callback = set_pci_reboot,
++ .ident = "Apple iMac10,1",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "iMac10,1"),
++ },
++ },
+
+ /* ASRock */
+ { /* Handle problems with rebooting on ASRock Q1900DC-ITX */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kvm/emulate.c linux-libre-4.4.7-gnu/arch/x86/kvm/emulate.c
+--- linux-libre-4.4-gnu/arch/x86/kvm/emulate.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kvm/emulate.c 2016-04-12 12:09:26.000000000 -0400
+@@ -650,10 +650,10 @@ static __always_inline int __linearize(s
+ u16 sel;
+
+ la = seg_base(ctxt, addr.seg) + addr.ea;
+- *linear = la;
+ *max_size = 0;
+ switch (mode) {
+ case X86EMUL_MODE_PROT64:
++ *linear = la;
+ if (is_noncanonical_address(la))
+ goto bad;
+
+@@ -662,6 +662,7 @@ static __always_inline int __linearize(s
+ goto bad;
+ break;
+ default:
++ *linear = la = (u32)la;
+ usable = ctxt->ops->get_segment(ctxt, &sel, &desc, NULL,
+ addr.seg);
+ if (!usable)
+@@ -689,7 +690,6 @@ static __always_inline int __linearize(s
+ if (size > *max_size)
+ goto bad;
+ }
+- la &= (u32)-1;
+ break;
+ }
+ if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kvm/i8254.c linux-libre-4.4.7-gnu/arch/x86/kvm/i8254.c
+--- linux-libre-4.4-gnu/arch/x86/kvm/i8254.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kvm/i8254.c 2016-04-12 12:09:26.000000000 -0400
+@@ -245,7 +245,7 @@ static void kvm_pit_ack_irq(struct kvm_i
+ * PIC is being reset. Handle it gracefully here
+ */
+ atomic_inc(&ps->pending);
+- else if (value > 0)
++ else if (value > 0 && ps->reinject)
+ /* in this case, we had multiple outstanding pit interrupts
+ * that we needed to inject. Reinject
+ */
+@@ -288,7 +288,9 @@ static void pit_do_work(struct kthread_w
+ * last one has been acked.
+ */
+ spin_lock(&ps->inject_lock);
+- if (ps->irq_ack) {
++ if (!ps->reinject)
++ inject = 1;
++ else if (ps->irq_ack) {
+ ps->irq_ack = 0;
+ inject = 1;
+ }
+@@ -317,10 +319,10 @@ static enum hrtimer_restart pit_timer_fn
+ struct kvm_kpit_state *ps = container_of(data, struct kvm_kpit_state, timer);
+ struct kvm_pit *pt = ps->kvm->arch.vpit;
+
+- if (ps->reinject || !atomic_read(&ps->pending)) {
++ if (ps->reinject)
+ atomic_inc(&ps->pending);
+- queue_kthread_work(&pt->worker, &pt->expired);
+- }
++
++ queue_kthread_work(&pt->worker, &pt->expired);
+
+ if (ps->is_periodic) {
+ hrtimer_add_expires_ns(&ps->timer, ps->period);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kvm/mmu.c linux-libre-4.4.7-gnu/arch/x86/kvm/mmu.c
+--- linux-libre-4.4-gnu/arch/x86/kvm/mmu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kvm/mmu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3754,13 +3754,15 @@ static void reset_rsvds_bits_mask_ept(st
+ void
+ reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
+ {
++ bool uses_nx = context->nx || context->base_role.smep_andnot_wp;
++
+ /*
+ * Passing "true" to the last argument is okay; it adds a check
+ * on bit 8 of the SPTEs which KVM doesn't use anyway.
+ */
+ __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
+ boot_cpu_data.x86_phys_bits,
+- context->shadow_root_level, context->nx,
++ context->shadow_root_level, uses_nx,
+ guest_cpuid_has_gbpages(vcpu), is_pse(vcpu),
+ true);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kvm/paging_tmpl.h linux-libre-4.4.7-gnu/arch/x86/kvm/paging_tmpl.h
+--- linux-libre-4.4-gnu/arch/x86/kvm/paging_tmpl.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kvm/paging_tmpl.h 2016-04-12 12:09:26.000000000 -0400
+@@ -249,7 +249,7 @@ static int FNAME(update_accessed_dirty_b
+ return ret;
+
+ kvm_vcpu_mark_page_dirty(vcpu, table_gfn);
+- walker->ptes[level] = pte;
++ walker->ptes[level - 1] = pte;
+ }
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kvm/trace.h linux-libre-4.4.7-gnu/arch/x86/kvm/trace.h
+--- linux-libre-4.4-gnu/arch/x86/kvm/trace.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kvm/trace.h 2016-04-12 12:09:26.000000000 -0400
+@@ -268,7 +268,7 @@ TRACE_EVENT(kvm_inj_virq,
+ #define kvm_trace_sym_exc \
+ EXS(DE), EXS(DB), EXS(BP), EXS(OF), EXS(BR), EXS(UD), EXS(NM), \
+ EXS(DF), EXS(TS), EXS(NP), EXS(SS), EXS(GP), EXS(PF), \
+- EXS(MF), EXS(MC)
++ EXS(MF), EXS(AC), EXS(MC)
+
+ /*
+ * Tracepoint for kvm interrupt injection:
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kvm/vmx.c linux-libre-4.4.7-gnu/arch/x86/kvm/vmx.c
+--- linux-libre-4.4-gnu/arch/x86/kvm/vmx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kvm/vmx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -595,6 +595,8 @@ struct vcpu_vmx {
+ /* Support for PML */
+ #define PML_ENTITY_NUM 512
+ struct page *pml_pg;
++
++ u64 current_tsc_ratio;
+ };
+
+ enum segment_cache_field {
+@@ -1746,6 +1748,13 @@ static void add_atomic_switch_msr(struct
+ return;
+ }
+ break;
++ case MSR_IA32_PEBS_ENABLE:
++ /* PEBS needs a quiescent period after being disabled (to write
++ * a record). Disabling PEBS through VMX MSR swapping doesn't
++ * provide that period, so a CPU could write host's record into
++ * guest's memory.
++ */
++ wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
+ }
+
+ for (i = 0; i < m->nr; ++i)
+@@ -1783,26 +1792,31 @@ static void reload_tss(void)
+
+ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
+ {
+- u64 guest_efer;
+- u64 ignore_bits;
++ u64 guest_efer = vmx->vcpu.arch.efer;
++ u64 ignore_bits = 0;
+
+- guest_efer = vmx->vcpu.arch.efer;
++ if (!enable_ept) {
++ /*
++ * NX is needed to handle CR0.WP=1, CR4.SMEP=1. Testing
++ * host CPUID is more efficient than testing guest CPUID
++ * or CR4. Host SMEP is anyway a requirement for guest SMEP.
++ */
++ if (boot_cpu_has(X86_FEATURE_SMEP))
++ guest_efer |= EFER_NX;
++ else if (!(guest_efer & EFER_NX))
++ ignore_bits |= EFER_NX;
++ }
+
+ /*
+- * NX is emulated; LMA and LME handled by hardware; SCE meaningless
+- * outside long mode
++ * LMA and LME handled by hardware; SCE meaningless outside long mode.
+ */
+- ignore_bits = EFER_NX | EFER_SCE;
++ ignore_bits |= EFER_SCE;
+ #ifdef CONFIG_X86_64
+ ignore_bits |= EFER_LMA | EFER_LME;
+ /* SCE is meaningful only in long mode on Intel */
+ if (guest_efer & EFER_LMA)
+ ignore_bits &= ~(u64)EFER_SCE;
+ #endif
+- guest_efer &= ~ignore_bits;
+- guest_efer |= host_efer & ignore_bits;
+- vmx->guest_msrs[efer_offset].data = guest_efer;
+- vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
+
+ clear_atomic_switch_msr(vmx, MSR_EFER);
+
+@@ -1813,16 +1827,21 @@ static bool update_transition_efer(struc
+ */
+ if (cpu_has_load_ia32_efer ||
+ (enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX))) {
+- guest_efer = vmx->vcpu.arch.efer;
+ if (!(guest_efer & EFER_LMA))
+ guest_efer &= ~EFER_LME;
+ if (guest_efer != host_efer)
+ add_atomic_switch_msr(vmx, MSR_EFER,
+ guest_efer, host_efer);
+ return false;
+- }
++ } else {
++ guest_efer &= ~ignore_bits;
++ guest_efer |= host_efer & ignore_bits;
+
+- return true;
++ vmx->guest_msrs[efer_offset].data = guest_efer;
++ vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
++
++ return true;
++ }
+ }
+
+ static unsigned long segment_base(u16 selector)
+@@ -2062,14 +2081,16 @@ static void vmx_vcpu_load(struct kvm_vcp
+ rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
+ vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+
+- /* Setup TSC multiplier */
+- if (cpu_has_vmx_tsc_scaling())
+- vmcs_write64(TSC_MULTIPLIER,
+- vcpu->arch.tsc_scaling_ratio);
+-
+ vmx->loaded_vmcs->cpu = cpu;
+ }
+
++ /* Setup TSC multiplier */
++ if (kvm_has_tsc_control &&
++ vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio) {
++ vmx->current_tsc_ratio = vcpu->arch.tsc_scaling_ratio;
++ vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
++ }
++
+ vmx_vcpu_pi_load(vcpu, cpu);
+ }
+
+@@ -2616,8 +2637,15 @@ static void nested_vmx_setup_ctls_msrs(s
+ } else
+ vmx->nested.nested_vmx_ept_caps = 0;
+
++ /*
++ * Old versions of KVM use the single-context version without
++ * checking for support, so declare that it is supported even
++ * though it is treated as global context. The alternative is
++ * not failing the single-context invvpid, and it is worse.
++ */
+ if (enable_vpid)
+ vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT |
++ VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT |
+ VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
+ else
+ vmx->nested.nested_vmx_vpid_caps = 0;
+@@ -7319,6 +7347,7 @@ static int handle_invept(struct kvm_vcpu
+ if (!(types & (1UL << type))) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
++ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+
+@@ -7377,6 +7406,7 @@ static int handle_invvpid(struct kvm_vcp
+ if (!(types & (1UL << type))) {
+ nested_vmx_failValid(vcpu,
+ VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
++ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+
+@@ -7393,12 +7423,17 @@ static int handle_invvpid(struct kvm_vcp
+ }
+
+ switch (type) {
++ case VMX_VPID_EXTENT_SINGLE_CONTEXT:
++ /*
++ * Old versions of KVM use the single-context version so we
++ * have to support it; just treat it the same as all-context.
++ */
+ case VMX_VPID_EXTENT_ALL_CONTEXT:
+ __vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
+ nested_vmx_succeed(vcpu);
+ break;
+ default:
+- /* Trap single context invalidation invvpid calls */
++ /* Trap individual address invalidation invvpid calls */
+ BUG_ON(1);
+ break;
+ }
+@@ -8932,7 +8967,8 @@ static void vmx_cpuid_update(struct kvm_
+ best->ebx &= ~bit(X86_FEATURE_INVPCID);
+ }
+
+- vmcs_set_secondary_exec_control(secondary_exec_ctl);
++ if (cpu_has_secondary_exec_ctrls())
++ vmcs_set_secondary_exec_control(secondary_exec_ctl);
+
+ if (static_cpu_has(X86_FEATURE_PCOMMIT) && nested) {
+ if (guest_cpuid_has_pcommit(vcpu))
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/kvm/x86.c linux-libre-4.4.7-gnu/arch/x86/kvm/x86.c
+--- linux-libre-4.4-gnu/arch/x86/kvm/x86.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/kvm/x86.c 2016-04-12 12:09:26.000000000 -0400
+@@ -951,7 +951,7 @@ static u32 msrs_to_save[] = {
+ MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
+ #endif
+ MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA,
+- MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS
++ MSR_IA32_FEATURE_CONTROL, MSR_IA32_BNDCFGS, MSR_TSC_AUX,
+ };
+
+ static unsigned num_msrs_to_save;
+@@ -2736,6 +2736,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
+ }
+
+ kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
++ vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD;
+ }
+
+ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+@@ -4006,16 +4007,17 @@ static void kvm_init_msr_list(void)
+
+ /*
+ * Even MSRs that are valid in the host may not be exposed
+- * to the guests in some cases. We could work around this
+- * in VMX with the generic MSR save/load machinery, but it
+- * is not really worthwhile since it will really only
+- * happen with nested virtualization.
++ * to the guests in some cases.
+ */
+ switch (msrs_to_save[i]) {
+ case MSR_IA32_BNDCFGS:
+ if (!kvm_x86_ops->mpx_supported())
+ continue;
+ break;
++ case MSR_TSC_AUX:
++ if (!kvm_x86_ops->rdtscp_supported())
++ continue;
++ break;
+ default:
+ break;
+ }
+@@ -6543,12 +6545,12 @@ static int vcpu_enter_guest(struct kvm_v
+ * KVM_DEBUGREG_WONT_EXIT again.
+ */
+ if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
+- int i;
+-
+ WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
+ kvm_x86_ops->sync_dirty_debug_regs(vcpu);
+- for (i = 0; i < KVM_NR_DB_REGS; i++)
+- vcpu->arch.eff_db[i] = vcpu->arch.db[i];
++ kvm_update_dr0123(vcpu);
++ kvm_update_dr6(vcpu);
++ kvm_update_dr7(vcpu);
++ vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/lib/copy_user_64.S linux-libre-4.4.7-gnu/arch/x86/lib/copy_user_64.S
+--- linux-libre-4.4-gnu/arch/x86/lib/copy_user_64.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/lib/copy_user_64.S 2016-04-12 12:09:26.000000000 -0400
+@@ -232,17 +232,31 @@ ENDPROC(copy_user_enhanced_fast_string)
+
+ /*
+ * copy_user_nocache - Uncached memory copy with exception handling
+- * This will force destination/source out of cache for more performance.
++ * This will force destination out of cache for more performance.
++ *
++ * Note: Cached memory copy is used when destination or size is not
++ * naturally aligned. That is:
++ * - Require 8-byte alignment when size is 8 bytes or larger.
++ * - Require 4-byte alignment when size is 4 bytes.
+ */
+ ENTRY(__copy_user_nocache)
+ ASM_STAC
++
++ /* If size is less than 8 bytes, go to 4-byte copy */
+ cmpl $8,%edx
+- jb 20f /* less then 8 bytes, go to byte copy loop */
++ jb .L_4b_nocache_copy_entry
++
++ /* If destination is not 8-byte aligned, "cache" copy to align it */
+ ALIGN_DESTINATION
++
++ /* Set 4x8-byte copy count and remainder */
+ movl %edx,%ecx
+ andl $63,%edx
+ shrl $6,%ecx
+- jz 17f
++ jz .L_8b_nocache_copy_entry /* jump if count is 0 */
++
++ /* Perform 4x8-byte nocache loop-copy */
++.L_4x8b_nocache_copy_loop:
+ 1: movq (%rsi),%r8
+ 2: movq 1*8(%rsi),%r9
+ 3: movq 2*8(%rsi),%r10
+@@ -262,60 +276,106 @@ ENTRY(__copy_user_nocache)
+ leaq 64(%rsi),%rsi
+ leaq 64(%rdi),%rdi
+ decl %ecx
+- jnz 1b
+-17: movl %edx,%ecx
++ jnz .L_4x8b_nocache_copy_loop
++
++ /* Set 8-byte copy count and remainder */
++.L_8b_nocache_copy_entry:
++ movl %edx,%ecx
+ andl $7,%edx
+ shrl $3,%ecx
+- jz 20f
+-18: movq (%rsi),%r8
+-19: movnti %r8,(%rdi)
++ jz .L_4b_nocache_copy_entry /* jump if count is 0 */
++
++ /* Perform 8-byte nocache loop-copy */
++.L_8b_nocache_copy_loop:
++20: movq (%rsi),%r8
++21: movnti %r8,(%rdi)
+ leaq 8(%rsi),%rsi
+ leaq 8(%rdi),%rdi
+ decl %ecx
+- jnz 18b
+-20: andl %edx,%edx
+- jz 23f
++ jnz .L_8b_nocache_copy_loop
++
++ /* If no byte left, we're done */
++.L_4b_nocache_copy_entry:
++ andl %edx,%edx
++ jz .L_finish_copy
++
++ /* If destination is not 4-byte aligned, go to byte copy: */
++ movl %edi,%ecx
++ andl $3,%ecx
++ jnz .L_1b_cache_copy_entry
++
++ /* Set 4-byte copy count (1 or 0) and remainder */
+ movl %edx,%ecx
+-21: movb (%rsi),%al
+-22: movb %al,(%rdi)
++ andl $3,%edx
++ shrl $2,%ecx
++ jz .L_1b_cache_copy_entry /* jump if count is 0 */
++
++ /* Perform 4-byte nocache copy: */
++30: movl (%rsi),%r8d
++31: movnti %r8d,(%rdi)
++ leaq 4(%rsi),%rsi
++ leaq 4(%rdi),%rdi
++
++ /* If no bytes left, we're done: */
++ andl %edx,%edx
++ jz .L_finish_copy
++
++ /* Perform byte "cache" loop-copy for the remainder */
++.L_1b_cache_copy_entry:
++ movl %edx,%ecx
++.L_1b_cache_copy_loop:
++40: movb (%rsi),%al
++41: movb %al,(%rdi)
+ incq %rsi
+ incq %rdi
+ decl %ecx
+- jnz 21b
+-23: xorl %eax,%eax
++ jnz .L_1b_cache_copy_loop
++
++ /* Finished copying; fence the prior stores */
++.L_finish_copy:
++ xorl %eax,%eax
+ ASM_CLAC
+ sfence
+ ret
+
+ .section .fixup,"ax"
+-30: shll $6,%ecx
++.L_fixup_4x8b_copy:
++ shll $6,%ecx
+ addl %ecx,%edx
+- jmp 60f
+-40: lea (%rdx,%rcx,8),%rdx
+- jmp 60f
+-50: movl %ecx,%edx
+-60: sfence
++ jmp .L_fixup_handle_tail
++.L_fixup_8b_copy:
++ lea (%rdx,%rcx,8),%rdx
++ jmp .L_fixup_handle_tail
++.L_fixup_4b_copy:
++ lea (%rdx,%rcx,4),%rdx
++ jmp .L_fixup_handle_tail
++.L_fixup_1b_copy:
++ movl %ecx,%edx
++.L_fixup_handle_tail:
++ sfence
+ jmp copy_user_handle_tail
+ .previous
+
+- _ASM_EXTABLE(1b,30b)
+- _ASM_EXTABLE(2b,30b)
+- _ASM_EXTABLE(3b,30b)
+- _ASM_EXTABLE(4b,30b)
+- _ASM_EXTABLE(5b,30b)
+- _ASM_EXTABLE(6b,30b)
+- _ASM_EXTABLE(7b,30b)
+- _ASM_EXTABLE(8b,30b)
+- _ASM_EXTABLE(9b,30b)
+- _ASM_EXTABLE(10b,30b)
+- _ASM_EXTABLE(11b,30b)
+- _ASM_EXTABLE(12b,30b)
+- _ASM_EXTABLE(13b,30b)
+- _ASM_EXTABLE(14b,30b)
+- _ASM_EXTABLE(15b,30b)
+- _ASM_EXTABLE(16b,30b)
+- _ASM_EXTABLE(18b,40b)
+- _ASM_EXTABLE(19b,40b)
+- _ASM_EXTABLE(21b,50b)
+- _ASM_EXTABLE(22b,50b)
++ _ASM_EXTABLE(1b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(2b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(3b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(4b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(5b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(6b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(7b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(8b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(9b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(10b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(11b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(12b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(13b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(14b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(15b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(16b,.L_fixup_4x8b_copy)
++ _ASM_EXTABLE(20b,.L_fixup_8b_copy)
++ _ASM_EXTABLE(21b,.L_fixup_8b_copy)
++ _ASM_EXTABLE(30b,.L_fixup_4b_copy)
++ _ASM_EXTABLE(31b,.L_fixup_4b_copy)
++ _ASM_EXTABLE(40b,.L_fixup_1b_copy)
++ _ASM_EXTABLE(41b,.L_fixup_1b_copy)
+ ENDPROC(__copy_user_nocache)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/mm/fault.c linux-libre-4.4.7-gnu/arch/x86/mm/fault.c
+--- linux-libre-4.4-gnu/arch/x86/mm/fault.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/mm/fault.c 2016-04-12 12:09:26.000000000 -0400
+@@ -287,6 +287,9 @@ static noinline int vmalloc_fault(unsign
+ if (!pmd_k)
+ return -1;
+
++ if (pmd_huge(*pmd_k))
++ return 0;
++
+ pte_k = pte_offset_kernel(pmd_k, address);
+ if (!pte_present(*pte_k))
+ return -1;
+@@ -360,8 +363,6 @@ void vmalloc_sync_all(void)
+ * 64-bit:
+ *
+ * Handle a fault on the vmalloc area
+- *
+- * This assumes no large pages in there.
+ */
+ static noinline int vmalloc_fault(unsigned long address)
+ {
+@@ -403,17 +404,23 @@ static noinline int vmalloc_fault(unsign
+ if (pud_none(*pud_ref))
+ return -1;
+
+- if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
++ if (pud_none(*pud) || pud_pfn(*pud) != pud_pfn(*pud_ref))
+ BUG();
+
++ if (pud_huge(*pud))
++ return 0;
++
+ pmd = pmd_offset(pud, address);
+ pmd_ref = pmd_offset(pud_ref, address);
+ if (pmd_none(*pmd_ref))
+ return -1;
+
+- if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
++ if (pmd_none(*pmd) || pmd_pfn(*pmd) != pmd_pfn(*pmd_ref))
+ BUG();
+
++ if (pmd_huge(*pmd))
++ return 0;
++
+ pte_ref = pte_offset_kernel(pmd_ref, address);
+ if (!pte_present(*pte_ref))
+ return -1;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/mm/mpx.c linux-libre-4.4.7-gnu/arch/x86/mm/mpx.c
+--- linux-libre-4.4-gnu/arch/x86/mm/mpx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/mm/mpx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -123,7 +123,7 @@ static int get_reg_offset(struct insn *i
+ break;
+ }
+
+- if (regno > nr_registers) {
++ if (regno >= nr_registers) {
+ WARN_ONCE(1, "decoded an instruction with an invalid register");
+ return -EINVAL;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/mm/pageattr.c linux-libre-4.4.7-gnu/arch/x86/mm/pageattr.c
+--- linux-libre-4.4-gnu/arch/x86/mm/pageattr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/mm/pageattr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -33,7 +33,7 @@ struct cpa_data {
+ pgd_t *pgd;
+ pgprot_t mask_set;
+ pgprot_t mask_clr;
+- int numpages;
++ unsigned long numpages;
+ int flags;
+ unsigned long pfn;
+ unsigned force_split : 1;
+@@ -414,24 +414,30 @@ pmd_t *lookup_pmd_address(unsigned long
+ phys_addr_t slow_virt_to_phys(void *__virt_addr)
+ {
+ unsigned long virt_addr = (unsigned long)__virt_addr;
+- unsigned long phys_addr, offset;
++ phys_addr_t phys_addr;
++ unsigned long offset;
+ enum pg_level level;
+ pte_t *pte;
+
+ pte = lookup_address(virt_addr, &level);
+ BUG_ON(!pte);
+
++ /*
++ * pXX_pfn() returns unsigned long, which must be cast to phys_addr_t
++ * before being left-shifted PAGE_SHIFT bits -- this trick is to
++ * make 32-PAE kernel work correctly.
++ */
+ switch (level) {
+ case PG_LEVEL_1G:
+- phys_addr = pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
++ phys_addr = (phys_addr_t)pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
+ offset = virt_addr & ~PUD_PAGE_MASK;
+ break;
+ case PG_LEVEL_2M:
+- phys_addr = pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
++ phys_addr = (phys_addr_t)pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
+ offset = virt_addr & ~PMD_PAGE_MASK;
+ break;
+ default:
+- phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
++ phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
+ offset = virt_addr & ~PAGE_MASK;
+ }
+
+@@ -1345,7 +1351,7 @@ static int __change_page_attr_set_clr(st
+ * CPA operation. Either a large page has been
+ * preserved or a single page update happened.
+ */
+- BUG_ON(cpa->numpages > numpages);
++ BUG_ON(cpa->numpages > numpages || !cpa->numpages);
+ numpages -= cpa->numpages;
+ if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
+ cpa->curpage++;
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/mm/tlb.c linux-libre-4.4.7-gnu/arch/x86/mm/tlb.c
+--- linux-libre-4.4-gnu/arch/x86/mm/tlb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/mm/tlb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -106,8 +106,6 @@ static void flush_tlb_func(void *info)
+
+ if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
+ return;
+- if (!f->flush_end)
+- f->flush_end = f->flush_start + PAGE_SIZE;
+
+ count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
+ if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
+@@ -135,12 +133,20 @@ void native_flush_tlb_others(const struc
+ unsigned long end)
+ {
+ struct flush_tlb_info info;
++
++ if (end == 0)
++ end = start + PAGE_SIZE;
+ info.flush_mm = mm;
+ info.flush_start = start;
+ info.flush_end = end;
+
+ count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
+- trace_tlb_flush(TLB_REMOTE_SEND_IPI, end - start);
++ if (end == TLB_FLUSH_ALL)
++ trace_tlb_flush(TLB_REMOTE_SEND_IPI, TLB_FLUSH_ALL);
++ else
++ trace_tlb_flush(TLB_REMOTE_SEND_IPI,
++ (end - start) >> PAGE_SHIFT);
++
+ if (is_uv_system()) {
+ unsigned int cpu;
+
+@@ -161,7 +167,10 @@ void flush_tlb_current_task(void)
+ preempt_disable();
+
+ count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
++
++ /* This is an implicit full barrier that synchronizes with switch_mm. */
+ local_flush_tlb();
++
+ trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL);
+ if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
+ flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL);
+@@ -188,17 +197,29 @@ void flush_tlb_mm_range(struct mm_struct
+ unsigned long base_pages_to_flush = TLB_FLUSH_ALL;
+
+ preempt_disable();
+- if (current->active_mm != mm)
++ if (current->active_mm != mm) {
++ /* Synchronize with switch_mm. */
++ smp_mb();
++
+ goto out;
++ }
+
+ if (!current->mm) {
+ leave_mm(smp_processor_id());
++
++ /* Synchronize with switch_mm. */
++ smp_mb();
++
+ goto out;
+ }
+
+ if ((end != TLB_FLUSH_ALL) && !(vmflag & VM_HUGETLB))
+ base_pages_to_flush = (end - start) >> PAGE_SHIFT;
+
++ /*
++ * Both branches below are implicit full barriers (MOV to CR or
++ * INVLPG) that synchronize with switch_mm.
++ */
+ if (base_pages_to_flush > tlb_single_page_flush_ceiling) {
+ base_pages_to_flush = TLB_FLUSH_ALL;
+ count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
+@@ -228,10 +249,18 @@ void flush_tlb_page(struct vm_area_struc
+ preempt_disable();
+
+ if (current->active_mm == mm) {
+- if (current->mm)
++ if (current->mm) {
++ /*
++ * Implicit full barrier (INVLPG) that synchronizes
++ * with switch_mm.
++ */
+ __flush_tlb_one(start);
+- else
++ } else {
+ leave_mm(smp_processor_id());
++
++ /* Synchronize with switch_mm. */
++ smp_mb();
++ }
+ }
+
+ if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/pci/fixup.c linux-libre-4.4.7-gnu/arch/x86/pci/fixup.c
+--- linux-libre-4.4-gnu/arch/x86/pci/fixup.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/pci/fixup.c 2016-04-12 12:09:26.000000000 -0400
+@@ -540,3 +540,10 @@ static void twinhead_reserve_killing_zon
+ }
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
++
++static void pci_bdwep_bar(struct pci_dev *dev)
++{
++ dev->non_compliant_bars = 1;
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/xen/enlighten.c linux-libre-4.4.7-gnu/arch/x86/xen/enlighten.c
+--- linux-libre-4.4-gnu/arch/x86/xen/enlighten.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/xen/enlighten.c 2016-04-12 12:09:26.000000000 -0400
+@@ -961,7 +961,7 @@ static void xen_load_sp0(struct tss_stru
+ tss->x86_tss.sp0 = thread->sp0;
+ }
+
+-static void xen_set_iopl_mask(unsigned mask)
++void xen_set_iopl_mask(unsigned mask)
+ {
+ struct physdev_set_iopl set_iopl;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/x86/xen/suspend.c linux-libre-4.4.7-gnu/arch/x86/xen/suspend.c
+--- linux-libre-4.4-gnu/arch/x86/xen/suspend.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/x86/xen/suspend.c 2016-04-12 12:09:26.000000000 -0400
+@@ -34,7 +34,8 @@ static void xen_hvm_post_suspend(int sus
+ {
+ #ifdef CONFIG_XEN_PVHVM
+ int cpu;
+- xen_hvm_init_shared_info();
++ if (!suspend_cancelled)
++ xen_hvm_init_shared_info();
+ xen_callback_vector();
+ xen_unplug_emulated_devices();
+ if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/xtensa/kernel/head.S linux-libre-4.4.7-gnu/arch/xtensa/kernel/head.S
+--- linux-libre-4.4-gnu/arch/xtensa/kernel/head.S 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/xtensa/kernel/head.S 2016-04-12 12:09:26.000000000 -0400
+@@ -128,7 +128,7 @@ ENTRY(_startup)
+ wsr a0, icountlevel
+
+ .set _index, 0
+- .rept XCHAL_NUM_DBREAK - 1
++ .rept XCHAL_NUM_DBREAK
+ wsr a0, SREG_DBREAKC + _index
+ .set _index, _index + 1
+ .endr
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/xtensa/mm/cache.c linux-libre-4.4.7-gnu/arch/xtensa/mm/cache.c
+--- linux-libre-4.4-gnu/arch/xtensa/mm/cache.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/xtensa/mm/cache.c 2016-04-12 12:09:26.000000000 -0400
+@@ -97,11 +97,11 @@ void clear_user_highpage(struct page *pa
+ unsigned long paddr;
+ void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr);
+
+- pagefault_disable();
++ preempt_disable();
+ kmap_invalidate_coherent(page, vaddr);
+ set_bit(PG_arch_1, &page->flags);
+ clear_page_alias(kvaddr, paddr);
+- pagefault_enable();
++ preempt_enable();
+ }
+
+ void copy_user_highpage(struct page *dst, struct page *src,
+@@ -113,11 +113,11 @@ void copy_user_highpage(struct page *dst
+ void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr,
+ &src_paddr);
+
+- pagefault_disable();
++ preempt_disable();
+ kmap_invalidate_coherent(dst, vaddr);
+ set_bit(PG_arch_1, &dst->flags);
+ copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr);
+- pagefault_enable();
++ preempt_enable();
+ }
+
+ #endif /* DCACHE_WAY_SIZE > PAGE_SIZE */
+diff -druNp --no-dereference linux-libre-4.4-gnu/arch/xtensa/platforms/iss/console.c linux-libre-4.4.7-gnu/arch/xtensa/platforms/iss/console.c
+--- linux-libre-4.4-gnu/arch/xtensa/platforms/iss/console.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/arch/xtensa/platforms/iss/console.c 2016-04-12 12:09:26.000000000 -0400
+@@ -100,21 +100,23 @@ static void rs_poll(unsigned long priv)
+ {
+ struct tty_port *port = (struct tty_port *)priv;
+ int i = 0;
++ int rd = 1;
+ unsigned char c;
+
+ spin_lock(&timer_lock);
+
+ while (simc_poll(0)) {
+- simc_read(0, &c, 1);
++ rd = simc_read(0, &c, 1);
++ if (rd <= 0)
++ break;
+ tty_insert_flip_char(port, c, TTY_NORMAL);
+ i++;
+ }
+
+ if (i)
+ tty_flip_buffer_push(port);
+-
+-
+- mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
++ if (rd)
++ mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+ spin_unlock(&timer_lock);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/block/bio.c linux-libre-4.4.7-gnu/block/bio.c
+--- linux-libre-4.4-gnu/block/bio.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/block/bio.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1090,9 +1090,12 @@ int bio_uncopy_user(struct bio *bio)
+ if (!bio_flagged(bio, BIO_NULL_MAPPED)) {
+ /*
+ * if we're in a workqueue, the request is orphaned, so
+- * don't copy into a random user address space, just free.
++ * don't copy into a random user address space, just free
++ * and return -EINTR so user space doesn't expect any data.
+ */
+- if (current->mm && bio_data_dir(bio) == READ)
++ if (!current->mm)
++ ret = -EINTR;
++ else if (bio_data_dir(bio) == READ)
+ ret = bio_copy_to_iter(bio, bmd->iter);
+ if (bmd->is_our_pages)
+ bio_free_pages(bio);
+diff -druNp --no-dereference linux-libre-4.4-gnu/block/blk-core.c linux-libre-4.4.7-gnu/block/blk-core.c
+--- linux-libre-4.4-gnu/block/blk-core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/block/blk-core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2189,7 +2189,7 @@ int blk_insert_cloned_request(struct req
+ if (q->mq_ops) {
+ if (blk_queue_io_stat(q))
+ blk_account_io_start(rq, true);
+- blk_mq_insert_request(rq, false, true, true);
++ blk_mq_insert_request(rq, false, true, false);
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/block/blk-merge.c linux-libre-4.4.7-gnu/block/blk-merge.c
+--- linux-libre-4.4-gnu/block/blk-merge.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/block/blk-merge.c 2016-04-12 12:09:26.000000000 -0400
+@@ -68,6 +68,18 @@ static struct bio *blk_bio_write_same_sp
+ return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs);
+ }
+
++static inline unsigned get_max_io_size(struct request_queue *q,
++ struct bio *bio)
++{
++ unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
++ unsigned mask = queue_logical_block_size(q) - 1;
++
++ /* aligned to logical block size */
++ sectors &= ~(mask >> 9);
++
++ return sectors;
++}
++
+ static struct bio *blk_bio_segment_split(struct request_queue *q,
+ struct bio *bio,
+ struct bio_set *bs,
+@@ -79,11 +91,9 @@ static struct bio *blk_bio_segment_split
+ unsigned front_seg_size = bio->bi_seg_front_size;
+ bool do_split = true;
+ struct bio *new = NULL;
++ const unsigned max_sectors = get_max_io_size(q, bio);
+
+ bio_for_each_segment(bv, bio, iter) {
+- if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q))
+- goto split;
+-
+ /*
+ * If the queue doesn't support SG gaps and adding this
+ * offset would create a gap, disallow it.
+@@ -91,6 +101,21 @@ static struct bio *blk_bio_segment_split
+ if (bvprvp && bvec_gap_to_prev(q, bvprvp, bv.bv_offset))
+ goto split;
+
++ if (sectors + (bv.bv_len >> 9) > max_sectors) {
++ /*
++ * Consider this a new segment if we're splitting in
++ * the middle of this vector.
++ */
++ if (nsegs < queue_max_segments(q) &&
++ sectors < max_sectors) {
++ nsegs++;
++ sectors = max_sectors;
++ }
++ if (sectors)
++ goto split;
++ /* Make this single bvec as the 1st segment */
++ }
++
+ if (bvprvp && blk_queue_cluster(q)) {
+ if (seg_size + bv.bv_len > queue_max_segment_size(q))
+ goto new_segment;
+diff -druNp --no-dereference linux-libre-4.4-gnu/block/blk-settings.c linux-libre-4.4.7-gnu/block/blk-settings.c
+--- linux-libre-4.4-gnu/block/blk-settings.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/block/blk-settings.c 2016-04-12 12:09:26.000000000 -0400
+@@ -91,8 +91,8 @@ void blk_set_default_limits(struct queue
+ lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
+ lim->virt_boundary_mask = 0;
+ lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
+- lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors =
+- BLK_SAFE_MAX_SECTORS;
++ lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
++ lim->max_dev_sectors = 0;
+ lim->chunk_sectors = 0;
+ lim->max_write_same_sectors = 0;
+ lim->max_discard_sectors = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/af_alg.c linux-libre-4.4.7-gnu/crypto/af_alg.c
+--- linux-libre-4.4-gnu/crypto/af_alg.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/af_alg.c 2016-04-12 12:09:26.000000000 -0400
+@@ -76,6 +76,8 @@ int af_alg_register_type(const struct af
+ goto unlock;
+
+ type->ops->owner = THIS_MODULE;
++ if (type->ops_nokey)
++ type->ops_nokey->owner = THIS_MODULE;
+ node->type = type;
+ list_add(&node->list, &alg_types);
+ err = 0;
+@@ -125,6 +127,26 @@ int af_alg_release(struct socket *sock)
+ }
+ EXPORT_SYMBOL_GPL(af_alg_release);
+
++void af_alg_release_parent(struct sock *sk)
++{
++ struct alg_sock *ask = alg_sk(sk);
++ unsigned int nokey = ask->nokey_refcnt;
++ bool last = nokey && !ask->refcnt;
++
++ sk = ask->parent;
++ ask = alg_sk(sk);
++
++ lock_sock(sk);
++ ask->nokey_refcnt -= nokey;
++ if (!last)
++ last = !--ask->refcnt;
++ release_sock(sk);
++
++ if (last)
++ sock_put(sk);
++}
++EXPORT_SYMBOL_GPL(af_alg_release_parent);
++
+ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ {
+ const u32 forbidden = CRYPTO_ALG_INTERNAL;
+@@ -133,6 +155,7 @@ static int alg_bind(struct socket *sock,
+ struct sockaddr_alg *sa = (void *)uaddr;
+ const struct af_alg_type *type;
+ void *private;
++ int err;
+
+ if (sock->state == SS_CONNECTED)
+ return -EINVAL;
+@@ -160,16 +183,22 @@ static int alg_bind(struct socket *sock,
+ return PTR_ERR(private);
+ }
+
++ err = -EBUSY;
+ lock_sock(sk);
++ if (ask->refcnt | ask->nokey_refcnt)
++ goto unlock;
+
+ swap(ask->type, type);
+ swap(ask->private, private);
+
++ err = 0;
++
++unlock:
+ release_sock(sk);
+
+ alg_do_release(type, private);
+
+- return 0;
++ return err;
+ }
+
+ static int alg_setkey(struct sock *sk, char __user *ukey,
+@@ -202,11 +231,15 @@ static int alg_setsockopt(struct socket
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
+ const struct af_alg_type *type;
+- int err = -ENOPROTOOPT;
++ int err = -EBUSY;
+
+ lock_sock(sk);
++ if (ask->refcnt)
++ goto unlock;
++
+ type = ask->type;
+
++ err = -ENOPROTOOPT;
+ if (level != SOL_ALG || !type)
+ goto unlock;
+
+@@ -238,6 +271,7 @@ int af_alg_accept(struct sock *sk, struc
+ struct alg_sock *ask = alg_sk(sk);
+ const struct af_alg_type *type;
+ struct sock *sk2;
++ unsigned int nokey;
+ int err;
+
+ lock_sock(sk);
+@@ -257,20 +291,29 @@ int af_alg_accept(struct sock *sk, struc
+ security_sk_clone(sk, sk2);
+
+ err = type->accept(ask->private, sk2);
+- if (err) {
+- sk_free(sk2);
++
++ nokey = err == -ENOKEY;
++ if (nokey && type->accept_nokey)
++ err = type->accept_nokey(ask->private, sk2);
++
++ if (err)
+ goto unlock;
+- }
+
+ sk2->sk_family = PF_ALG;
+
+- sock_hold(sk);
++ if (nokey || !ask->refcnt++)
++ sock_hold(sk);
++ ask->nokey_refcnt += nokey;
+ alg_sk(sk2)->parent = sk;
+ alg_sk(sk2)->type = type;
++ alg_sk(sk2)->nokey_refcnt = nokey;
+
+ newsock->ops = type->ops;
+ newsock->state = SS_CONNECTED;
+
++ if (nokey)
++ newsock->ops = type->ops_nokey;
++
+ err = 0;
+
+ unlock:
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/ahash.c linux-libre-4.4.7-gnu/crypto/ahash.c
+--- linux-libre-4.4-gnu/crypto/ahash.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/ahash.c 2016-04-12 12:09:26.000000000 -0400
+@@ -451,6 +451,7 @@ static int crypto_ahash_init_tfm(struct
+ struct ahash_alg *alg = crypto_ahash_alg(hash);
+
+ hash->setkey = ahash_nosetkey;
++ hash->has_setkey = false;
+ hash->export = ahash_no_export;
+ hash->import = ahash_no_import;
+
+@@ -463,8 +464,10 @@ static int crypto_ahash_init_tfm(struct
+ hash->finup = alg->finup ?: ahash_def_finup;
+ hash->digest = alg->digest;
+
+- if (alg->setkey)
++ if (alg->setkey) {
+ hash->setkey = alg->setkey;
++ hash->has_setkey = true;
++ }
+ if (alg->export)
+ hash->export = alg->export;
+ if (alg->import)
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/algif_hash.c linux-libre-4.4.7-gnu/crypto/algif_hash.c
+--- linux-libre-4.4-gnu/crypto/algif_hash.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/algif_hash.c 2016-04-12 12:09:26.000000000 -0400
+@@ -34,6 +34,11 @@ struct hash_ctx {
+ struct ahash_request req;
+ };
+
++struct algif_hash_tfm {
++ struct crypto_ahash *hash;
++ bool has_key;
++};
++
+ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
+ size_t ignored)
+ {
+@@ -49,7 +54,8 @@ static int hash_sendmsg(struct socket *s
+
+ lock_sock(sk);
+ if (!ctx->more) {
+- err = crypto_ahash_init(&ctx->req);
++ err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
++ &ctx->completion);
+ if (err)
+ goto unlock;
+ }
+@@ -120,6 +126,7 @@ static ssize_t hash_sendpage(struct sock
+ } else {
+ if (!ctx->more) {
+ err = crypto_ahash_init(&ctx->req);
++ err = af_alg_wait_for_completion(err, &ctx->completion);
+ if (err)
+ goto unlock;
+ }
+@@ -235,19 +242,151 @@ static struct proto_ops algif_hash_ops =
+ .accept = hash_accept,
+ };
+
++static int hash_check_key(struct socket *sock)
++{
++ int err = 0;
++ struct sock *psk;
++ struct alg_sock *pask;
++ struct algif_hash_tfm *tfm;
++ struct sock *sk = sock->sk;
++ struct alg_sock *ask = alg_sk(sk);
++
++ lock_sock(sk);
++ if (ask->refcnt)
++ goto unlock_child;
++
++ psk = ask->parent;
++ pask = alg_sk(ask->parent);
++ tfm = pask->private;
++
++ err = -ENOKEY;
++ lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
++ if (!tfm->has_key)
++ goto unlock;
++
++ if (!pask->refcnt++)
++ sock_hold(psk);
++
++ ask->refcnt = 1;
++ sock_put(psk);
++
++ err = 0;
++
++unlock:
++ release_sock(psk);
++unlock_child:
++ release_sock(sk);
++
++ return err;
++}
++
++static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t size)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_sendmsg(sock, msg, size);
++}
++
++static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
++ int offset, size_t size, int flags)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_sendpage(sock, page, offset, size, flags);
++}
++
++static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t ignored, int flags)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_recvmsg(sock, msg, ignored, flags);
++}
++
++static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
++ int flags)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_accept(sock, newsock, flags);
++}
++
++static struct proto_ops algif_hash_ops_nokey = {
++ .family = PF_ALG,
++
++ .connect = sock_no_connect,
++ .socketpair = sock_no_socketpair,
++ .getname = sock_no_getname,
++ .ioctl = sock_no_ioctl,
++ .listen = sock_no_listen,
++ .shutdown = sock_no_shutdown,
++ .getsockopt = sock_no_getsockopt,
++ .mmap = sock_no_mmap,
++ .bind = sock_no_bind,
++ .setsockopt = sock_no_setsockopt,
++ .poll = sock_no_poll,
++
++ .release = af_alg_release,
++ .sendmsg = hash_sendmsg_nokey,
++ .sendpage = hash_sendpage_nokey,
++ .recvmsg = hash_recvmsg_nokey,
++ .accept = hash_accept_nokey,
++};
++
+ static void *hash_bind(const char *name, u32 type, u32 mask)
+ {
+- return crypto_alloc_ahash(name, type, mask);
++ struct algif_hash_tfm *tfm;
++ struct crypto_ahash *hash;
++
++ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
++ if (!tfm)
++ return ERR_PTR(-ENOMEM);
++
++ hash = crypto_alloc_ahash(name, type, mask);
++ if (IS_ERR(hash)) {
++ kfree(tfm);
++ return ERR_CAST(hash);
++ }
++
++ tfm->hash = hash;
++
++ return tfm;
+ }
+
+ static void hash_release(void *private)
+ {
+- crypto_free_ahash(private);
++ struct algif_hash_tfm *tfm = private;
++
++ crypto_free_ahash(tfm->hash);
++ kfree(tfm);
+ }
+
+ static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
+ {
+- return crypto_ahash_setkey(private, key, keylen);
++ struct algif_hash_tfm *tfm = private;
++ int err;
++
++ err = crypto_ahash_setkey(tfm->hash, key, keylen);
++ tfm->has_key = !err;
++
++ return err;
+ }
+
+ static void hash_sock_destruct(struct sock *sk)
+@@ -261,12 +400,14 @@ static void hash_sock_destruct(struct so
+ af_alg_release_parent(sk);
+ }
+
+-static int hash_accept_parent(void *private, struct sock *sk)
++static int hash_accept_parent_nokey(void *private, struct sock *sk)
+ {
+ struct hash_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+- unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private);
+- unsigned ds = crypto_ahash_digestsize(private);
++ struct algif_hash_tfm *tfm = private;
++ struct crypto_ahash *hash = tfm->hash;
++ unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
++ unsigned ds = crypto_ahash_digestsize(hash);
+
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+@@ -286,7 +427,7 @@ static int hash_accept_parent(void *priv
+
+ ask->private = ctx;
+
+- ahash_request_set_tfm(&ctx->req, private);
++ ahash_request_set_tfm(&ctx->req, hash);
+ ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ af_alg_complete, &ctx->completion);
+
+@@ -295,12 +436,24 @@ static int hash_accept_parent(void *priv
+ return 0;
+ }
+
++static int hash_accept_parent(void *private, struct sock *sk)
++{
++ struct algif_hash_tfm *tfm = private;
++
++ if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
++ return -ENOKEY;
++
++ return hash_accept_parent_nokey(private, sk);
++}
++
+ static const struct af_alg_type algif_type_hash = {
+ .bind = hash_bind,
+ .release = hash_release,
+ .setkey = hash_setkey,
+ .accept = hash_accept_parent,
++ .accept_nokey = hash_accept_parent_nokey,
+ .ops = &algif_hash_ops,
++ .ops_nokey = &algif_hash_ops_nokey,
+ .name = "hash",
+ .owner = THIS_MODULE
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/algif_skcipher.c linux-libre-4.4.7-gnu/crypto/algif_skcipher.c
+--- linux-libre-4.4-gnu/crypto/algif_skcipher.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/algif_skcipher.c 2016-04-12 12:09:26.000000000 -0400
+@@ -31,6 +31,11 @@ struct skcipher_sg_list {
+ struct scatterlist sg[0];
+ };
+
++struct skcipher_tfm {
++ struct crypto_skcipher *skcipher;
++ bool has_key;
++};
++
+ struct skcipher_ctx {
+ struct list_head tsgl;
+ struct af_alg_sgl rsgl;
+@@ -60,18 +65,10 @@ struct skcipher_async_req {
+ struct skcipher_async_rsgl first_sgl;
+ struct list_head list;
+ struct scatterlist *tsg;
+- char iv[];
++ atomic_t *inflight;
++ struct skcipher_request req;
+ };
+
+-#define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \
+- crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req)))
+-
+-#define GET_REQ_SIZE(ctx) \
+- crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req))
+-
+-#define GET_IV_SIZE(ctx) \
+- crypto_skcipher_ivsize(crypto_skcipher_reqtfm(&ctx->req))
+-
+ #define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
+ sizeof(struct scatterlist) - 1)
+
+@@ -97,15 +94,12 @@ static void skcipher_free_async_sgls(str
+
+ static void skcipher_async_cb(struct crypto_async_request *req, int err)
+ {
+- struct sock *sk = req->data;
+- struct alg_sock *ask = alg_sk(sk);
+- struct skcipher_ctx *ctx = ask->private;
+- struct skcipher_async_req *sreq = GET_SREQ(req, ctx);
++ struct skcipher_async_req *sreq = req->data;
+ struct kiocb *iocb = sreq->iocb;
+
+- atomic_dec(&ctx->inflight);
++ atomic_dec(sreq->inflight);
+ skcipher_free_async_sgls(sreq);
+- kfree(req);
++ kzfree(sreq);
+ iocb->ki_complete(iocb, err, err);
+ }
+
+@@ -301,8 +295,11 @@ static int skcipher_sendmsg(struct socke
+ {
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
++ struct sock *psk = ask->parent;
++ struct alg_sock *pask = alg_sk(psk);
+ struct skcipher_ctx *ctx = ask->private;
+- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
++ struct skcipher_tfm *skc = pask->private;
++ struct crypto_skcipher *tfm = skc->skcipher;
+ unsigned ivsize = crypto_skcipher_ivsize(tfm);
+ struct skcipher_sg_list *sgl;
+ struct af_alg_control con = {};
+@@ -387,7 +384,8 @@ static int skcipher_sendmsg(struct socke
+
+ sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
+ sg = sgl->sg;
+- sg_unmark_end(sg + sgl->cur);
++ if (sgl->cur)
++ sg_unmark_end(sg + sgl->cur - 1);
+ do {
+ i = sgl->cur;
+ plen = min_t(int, len, PAGE_SIZE);
+@@ -503,37 +501,43 @@ static int skcipher_recvmsg_async(struct
+ {
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
++ struct sock *psk = ask->parent;
++ struct alg_sock *pask = alg_sk(psk);
+ struct skcipher_ctx *ctx = ask->private;
++ struct skcipher_tfm *skc = pask->private;
++ struct crypto_skcipher *tfm = skc->skcipher;
+ struct skcipher_sg_list *sgl;
+ struct scatterlist *sg;
+ struct skcipher_async_req *sreq;
+ struct skcipher_request *req;
+ struct skcipher_async_rsgl *last_rsgl = NULL;
+- unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
+- unsigned int reqlen = sizeof(struct skcipher_async_req) +
+- GET_REQ_SIZE(ctx) + GET_IV_SIZE(ctx);
++ unsigned int txbufs = 0, len = 0, tx_nents;
++ unsigned int reqsize = crypto_skcipher_reqsize(tfm);
++ unsigned int ivsize = crypto_skcipher_ivsize(tfm);
+ int err = -ENOMEM;
+ bool mark = false;
++ char *iv;
+
+- lock_sock(sk);
+- req = kmalloc(reqlen, GFP_KERNEL);
+- if (unlikely(!req))
+- goto unlock;
++ sreq = kzalloc(sizeof(*sreq) + reqsize + ivsize, GFP_KERNEL);
++ if (unlikely(!sreq))
++ goto out;
+
+- sreq = GET_SREQ(req, ctx);
++ req = &sreq->req;
++ iv = (char *)(req + 1) + reqsize;
+ sreq->iocb = msg->msg_iocb;
+- memset(&sreq->first_sgl, '\0', sizeof(struct skcipher_async_rsgl));
+ INIT_LIST_HEAD(&sreq->list);
++ sreq->inflight = &ctx->inflight;
++
++ lock_sock(sk);
++ tx_nents = skcipher_all_sg_nents(ctx);
+ sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
+- if (unlikely(!sreq->tsg)) {
+- kfree(req);
++ if (unlikely(!sreq->tsg))
+ goto unlock;
+- }
+ sg_init_table(sreq->tsg, tx_nents);
+- memcpy(sreq->iv, ctx->iv, GET_IV_SIZE(ctx));
+- skcipher_request_set_tfm(req, crypto_skcipher_reqtfm(&ctx->req));
+- skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+- skcipher_async_cb, sk);
++ memcpy(iv, ctx->iv, ivsize);
++ skcipher_request_set_tfm(req, tfm);
++ skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
++ skcipher_async_cb, sreq);
+
+ while (iov_iter_count(&msg->msg_iter)) {
+ struct skcipher_async_rsgl *rsgl;
+@@ -609,20 +613,22 @@ static int skcipher_recvmsg_async(struct
+ sg_mark_end(sreq->tsg + txbufs - 1);
+
+ skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
+- len, sreq->iv);
++ len, iv);
+ err = ctx->enc ? crypto_skcipher_encrypt(req) :
+ crypto_skcipher_decrypt(req);
+ if (err == -EINPROGRESS) {
+ atomic_inc(&ctx->inflight);
+ err = -EIOCBQUEUED;
++ sreq = NULL;
+ goto unlock;
+ }
+ free:
+ skcipher_free_async_sgls(sreq);
+- kfree(req);
+ unlock:
+ skcipher_wmem_wakeup(sk);
+ release_sock(sk);
++ kzfree(sreq);
++out:
+ return err;
+ }
+
+@@ -631,9 +637,12 @@ static int skcipher_recvmsg_sync(struct
+ {
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
++ struct sock *psk = ask->parent;
++ struct alg_sock *pask = alg_sk(psk);
+ struct skcipher_ctx *ctx = ask->private;
+- unsigned bs = crypto_skcipher_blocksize(crypto_skcipher_reqtfm(
+- &ctx->req));
++ struct skcipher_tfm *skc = pask->private;
++ struct crypto_skcipher *tfm = skc->skcipher;
++ unsigned bs = crypto_skcipher_blocksize(tfm);
+ struct skcipher_sg_list *sgl;
+ struct scatterlist *sg;
+ int err = -EAGAIN;
+@@ -642,13 +651,6 @@ static int skcipher_recvmsg_sync(struct
+
+ lock_sock(sk);
+ while (msg_data_left(msg)) {
+- sgl = list_first_entry(&ctx->tsgl,
+- struct skcipher_sg_list, list);
+- sg = sgl->sg;
+-
+- while (!sg->length)
+- sg++;
+-
+ if (!ctx->used) {
+ err = skcipher_wait_for_data(sk, flags);
+ if (err)
+@@ -669,6 +671,13 @@ static int skcipher_recvmsg_sync(struct
+ if (!used)
+ goto free;
+
++ sgl = list_first_entry(&ctx->tsgl,
++ struct skcipher_sg_list, list);
++ sg = sgl->sg;
++
++ while (!sg->length)
++ sg++;
++
+ skcipher_request_set_crypt(&ctx->req, sg, ctx->rsgl.sg, used,
+ ctx->iv);
+
+@@ -748,19 +757,139 @@ static struct proto_ops algif_skcipher_o
+ .poll = skcipher_poll,
+ };
+
++static int skcipher_check_key(struct socket *sock)
++{
++ int err = 0;
++ struct sock *psk;
++ struct alg_sock *pask;
++ struct skcipher_tfm *tfm;
++ struct sock *sk = sock->sk;
++ struct alg_sock *ask = alg_sk(sk);
++
++ lock_sock(sk);
++ if (ask->refcnt)
++ goto unlock_child;
++
++ psk = ask->parent;
++ pask = alg_sk(ask->parent);
++ tfm = pask->private;
++
++ err = -ENOKEY;
++ lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
++ if (!tfm->has_key)
++ goto unlock;
++
++ if (!pask->refcnt++)
++ sock_hold(psk);
++
++ ask->refcnt = 1;
++ sock_put(psk);
++
++ err = 0;
++
++unlock:
++ release_sock(psk);
++unlock_child:
++ release_sock(sk);
++
++ return err;
++}
++
++static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t size)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_sendmsg(sock, msg, size);
++}
++
++static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
++ int offset, size_t size, int flags)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_sendpage(sock, page, offset, size, flags);
++}
++
++static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t ignored, int flags)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_recvmsg(sock, msg, ignored, flags);
++}
++
++static struct proto_ops algif_skcipher_ops_nokey = {
++ .family = PF_ALG,
++
++ .connect = sock_no_connect,
++ .socketpair = sock_no_socketpair,
++ .getname = sock_no_getname,
++ .ioctl = sock_no_ioctl,
++ .listen = sock_no_listen,
++ .shutdown = sock_no_shutdown,
++ .getsockopt = sock_no_getsockopt,
++ .mmap = sock_no_mmap,
++ .bind = sock_no_bind,
++ .accept = sock_no_accept,
++ .setsockopt = sock_no_setsockopt,
++
++ .release = af_alg_release,
++ .sendmsg = skcipher_sendmsg_nokey,
++ .sendpage = skcipher_sendpage_nokey,
++ .recvmsg = skcipher_recvmsg_nokey,
++ .poll = skcipher_poll,
++};
++
+ static void *skcipher_bind(const char *name, u32 type, u32 mask)
+ {
+- return crypto_alloc_skcipher(name, type, mask);
++ struct skcipher_tfm *tfm;
++ struct crypto_skcipher *skcipher;
++
++ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
++ if (!tfm)
++ return ERR_PTR(-ENOMEM);
++
++ skcipher = crypto_alloc_skcipher(name, type, mask);
++ if (IS_ERR(skcipher)) {
++ kfree(tfm);
++ return ERR_CAST(skcipher);
++ }
++
++ tfm->skcipher = skcipher;
++
++ return tfm;
+ }
+
+ static void skcipher_release(void *private)
+ {
+- crypto_free_skcipher(private);
++ struct skcipher_tfm *tfm = private;
++
++ crypto_free_skcipher(tfm->skcipher);
++ kfree(tfm);
+ }
+
+ static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
+ {
+- return crypto_skcipher_setkey(private, key, keylen);
++ struct skcipher_tfm *tfm = private;
++ int err;
++
++ err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
++ tfm->has_key = !err;
++
++ return err;
+ }
+
+ static void skcipher_wait(struct sock *sk)
+@@ -788,24 +917,26 @@ static void skcipher_sock_destruct(struc
+ af_alg_release_parent(sk);
+ }
+
+-static int skcipher_accept_parent(void *private, struct sock *sk)
++static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
+ {
+ struct skcipher_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+- unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
++ struct skcipher_tfm *tfm = private;
++ struct crypto_skcipher *skcipher = tfm->skcipher;
++ unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
+
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+- ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
++ ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
+ GFP_KERNEL);
+ if (!ctx->iv) {
+ sock_kfree_s(sk, ctx, len);
+ return -ENOMEM;
+ }
+
+- memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
++ memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
+
+ INIT_LIST_HEAD(&ctx->tsgl);
+ ctx->len = len;
+@@ -818,8 +949,9 @@ static int skcipher_accept_parent(void *
+
+ ask->private = ctx;
+
+- skcipher_request_set_tfm(&ctx->req, private);
+- skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
++ skcipher_request_set_tfm(&ctx->req, skcipher);
++ skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_SLEEP |
++ CRYPTO_TFM_REQ_MAY_BACKLOG,
+ af_alg_complete, &ctx->completion);
+
+ sk->sk_destruct = skcipher_sock_destruct;
+@@ -827,12 +959,24 @@ static int skcipher_accept_parent(void *
+ return 0;
+ }
+
++static int skcipher_accept_parent(void *private, struct sock *sk)
++{
++ struct skcipher_tfm *tfm = private;
++
++ if (!tfm->has_key && crypto_skcipher_has_setkey(tfm->skcipher))
++ return -ENOKEY;
++
++ return skcipher_accept_parent_nokey(private, sk);
++}
++
+ static const struct af_alg_type algif_type_skcipher = {
+ .bind = skcipher_bind,
+ .release = skcipher_release,
+ .setkey = skcipher_setkey,
+ .accept = skcipher_accept_parent,
++ .accept_nokey = skcipher_accept_parent_nokey,
+ .ops = &algif_skcipher_ops,
++ .ops_nokey = &algif_skcipher_ops_nokey,
+ .name = "skcipher",
+ .owner = THIS_MODULE
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/asymmetric_keys/x509_cert_parser.c linux-libre-4.4.7-gnu/crypto/asymmetric_keys/x509_cert_parser.c
+--- linux-libre-4.4-gnu/crypto/asymmetric_keys/x509_cert_parser.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/asymmetric_keys/x509_cert_parser.c 2016-04-12 12:09:26.000000000 -0400
+@@ -494,7 +494,7 @@ int x509_decode_time(time64_t *_t, size
+ unsigned char tag,
+ const unsigned char *value, size_t vlen)
+ {
+- static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30,
++ static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31 };
+ const unsigned char *p = value;
+ unsigned year, mon, day, hour, min, sec, mon_len;
+@@ -540,9 +540,9 @@ int x509_decode_time(time64_t *_t, size
+ if (year % 4 == 0) {
+ mon_len = 29;
+ if (year % 100 == 0) {
+- year /= 100;
+- if (year % 4 != 0)
+- mon_len = 28;
++ mon_len = 28;
++ if (year % 400 == 0)
++ mon_len = 29;
+ }
+ }
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/crc32c_generic.c linux-libre-4.4.7-gnu/crypto/crc32c_generic.c
+--- linux-libre-4.4-gnu/crypto/crc32c_generic.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/crc32c_generic.c 2016-04-12 12:09:26.000000000 -0400
+@@ -172,4 +172,3 @@ MODULE_DESCRIPTION("CRC32c (Castagnoli)
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS_CRYPTO("crc32c");
+ MODULE_ALIAS_CRYPTO("crc32c-generic");
+-MODULE_SOFTDEP("pre: crc32c");
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/crypto_user.c linux-libre-4.4.7-gnu/crypto/crypto_user.c
+--- linux-libre-4.4-gnu/crypto/crypto_user.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/crypto_user.c 2016-04-12 12:09:26.000000000 -0400
+@@ -499,6 +499,7 @@ static int crypto_user_rcv_msg(struct sk
+ if (link->dump == NULL)
+ return -EINVAL;
+
++ down_read(&crypto_alg_sem);
+ list_for_each_entry(alg, &crypto_alg_list, cra_list)
+ dump_alloc += CRYPTO_REPORT_MAXSIZE;
+
+@@ -508,8 +509,11 @@ static int crypto_user_rcv_msg(struct sk
+ .done = link->done,
+ .min_dump_alloc = dump_alloc,
+ };
+- return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
++ err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
+ }
++ up_read(&crypto_alg_sem);
++
++ return err;
+ }
+
+ err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/keywrap.c linux-libre-4.4.7-gnu/crypto/keywrap.c
+--- linux-libre-4.4-gnu/crypto/keywrap.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/keywrap.c 2016-04-12 12:09:26.000000000 -0400
+@@ -212,7 +212,7 @@ static int crypto_kw_decrypt(struct blkc
+ SEMIBSIZE))
+ ret = -EBADMSG;
+
+- memzero_explicit(&block, sizeof(struct crypto_kw_block));
++ memzero_explicit(block, sizeof(struct crypto_kw_block));
+
+ return ret;
+ }
+@@ -297,7 +297,7 @@ static int crypto_kw_encrypt(struct blkc
+ /* establish the IV for the caller to pick up */
+ memcpy(desc->info, block->A, SEMIBSIZE);
+
+- memzero_explicit(&block, sizeof(struct crypto_kw_block));
++ memzero_explicit(block, sizeof(struct crypto_kw_block));
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/shash.c linux-libre-4.4.7-gnu/crypto/shash.c
+--- linux-libre-4.4-gnu/crypto/shash.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/shash.c 2016-04-12 12:09:26.000000000 -0400
+@@ -354,9 +354,10 @@ int crypto_init_shash_ops_async(struct c
+ crt->final = shash_async_final;
+ crt->finup = shash_async_finup;
+ crt->digest = shash_async_digest;
++ crt->setkey = shash_async_setkey;
++
++ crt->has_setkey = alg->setkey != shash_no_setkey;
+
+- if (alg->setkey)
+- crt->setkey = shash_async_setkey;
+ if (alg->export)
+ crt->export = shash_async_export;
+ if (alg->import)
+diff -druNp --no-dereference linux-libre-4.4-gnu/crypto/skcipher.c linux-libre-4.4.7-gnu/crypto/skcipher.c
+--- linux-libre-4.4-gnu/crypto/skcipher.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/crypto/skcipher.c 2016-04-12 12:09:26.000000000 -0400
+@@ -118,6 +118,7 @@ static int crypto_init_skcipher_ops_blkc
+ skcipher->decrypt = skcipher_decrypt_blkcipher;
+
+ skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher);
++ skcipher->has_setkey = calg->cra_blkcipher.max_keysize;
+
+ return 0;
+ }
+@@ -210,6 +211,7 @@ static int crypto_init_skcipher_ops_ablk
+ skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+ skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) +
+ sizeof(struct ablkcipher_request);
++ skcipher->has_setkey = calg->cra_ablkcipher.max_keysize;
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/Documentation/ABI/testing/sysfs-bus-usb linux-libre-4.4.7-gnu/Documentation/ABI/testing/sysfs-bus-usb
+--- linux-libre-4.4-gnu/Documentation/ABI/testing/sysfs-bus-usb 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/Documentation/ABI/testing/sysfs-bus-usb 2016-04-12 12:09:26.000000000 -0400
+@@ -134,19 +134,21 @@ Description:
+ enabled for the device. Developer can write y/Y/1 or n/N/0 to
+ the file to enable/disable the feature.
+
+-What: /sys/bus/usb/devices/.../power/usb3_hardware_lpm
+-Date: June 2015
++What: /sys/bus/usb/devices/.../power/usb3_hardware_lpm_u1
++ /sys/bus/usb/devices/.../power/usb3_hardware_lpm_u2
++Date: November 2015
+ Contact: Kevin Strasser <kevin.strasser@linux.intel.com>
++ Lu Baolu <baolu.lu@linux.intel.com>
+ Description:
+ If CONFIG_PM is set and a USB 3.0 lpm-capable device is plugged
+ in to a xHCI host which supports link PM, it will check if U1
+ and U2 exit latencies have been set in the BOS descriptor; if
+- the check is is passed and the host supports USB3 hardware LPM,
++ the check is passed and the host supports USB3 hardware LPM,
+ USB3 hardware LPM will be enabled for the device and the USB
+- device directory will contain a file named
+- power/usb3_hardware_lpm. The file holds a string value (enable
+- or disable) indicating whether or not USB3 hardware LPM is
+- enabled for the device.
++ device directory will contain two files named
++ power/usb3_hardware_lpm_u1 and power/usb3_hardware_lpm_u2. These
++ files hold a string value (enable or disable) indicating whether
++ or not USB3 hardware LPM U1 or U2 is enabled for the device.
+
+ What: /sys/bus/usb/devices/.../removable
+ Date: February 2012
+diff -druNp --no-dereference linux-libre-4.4-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt linux-libre-4.4.7-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt
+--- linux-libre-4.4-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt 2016-04-12 12:09:26.000000000 -0400
+@@ -23,6 +23,7 @@ Optional properties:
+ during suspend.
+ - ti,no-reset-on-init: When present, the module should not be reset at init
+ - ti,no-idle-on-init: When present, the module should not be idled at init
++- ti,no-idle: When present, the module is never allowed to idle.
+
+ Example:
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/Documentation/filesystems/efivarfs.txt linux-libre-4.4.7-gnu/Documentation/filesystems/efivarfs.txt
+--- linux-libre-4.4-gnu/Documentation/filesystems/efivarfs.txt 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/Documentation/filesystems/efivarfs.txt 2016-04-12 12:09:26.000000000 -0400
+@@ -14,3 +14,10 @@ filesystem.
+ efivarfs is typically mounted like this,
+
+ mount -t efivarfs none /sys/firmware/efi/efivars
++
++Due to the presence of numerous firmware bugs where removing non-standard
++UEFI variables causes the system firmware to fail to POST, efivarfs
++files that are not well-known standardized variables are created
++as immutable files. This doesn't prevent removal - "chattr -i" will work -
++but it does prevent this kind of failure from being accomplished
++accidentally.
+diff -druNp --no-dereference linux-libre-4.4-gnu/Documentation/usb/power-management.txt linux-libre-4.4.7-gnu/Documentation/usb/power-management.txt
+--- linux-libre-4.4-gnu/Documentation/usb/power-management.txt 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/Documentation/usb/power-management.txt 2016-04-12 12:09:26.000000000 -0400
+@@ -537,17 +537,18 @@ relevant attribute files are usb2_hardwa
+ can write y/Y/1 or n/N/0 to the file to enable/disable
+ USB2 hardware LPM manually. This is for test purpose mainly.
+
+- power/usb3_hardware_lpm
++ power/usb3_hardware_lpm_u1
++ power/usb3_hardware_lpm_u2
+
+ When a USB 3.0 lpm-capable device is plugged in to a
+ xHCI host which supports link PM, it will check if U1
+ and U2 exit latencies have been set in the BOS
+ descriptor; if the check is is passed and the host
+ supports USB3 hardware LPM, USB3 hardware LPM will be
+- enabled for the device and this file will be created.
+- The file holds a string value (enable or disable)
+- indicating whether or not USB3 hardware LPM is
+- enabled for the device.
++ enabled for the device and these files will be created.
++ The files hold a string value (enable or disable)
++ indicating whether or not USB3 hardware LPM U1 or U2
++ is enabled for the device.
+
+ USB Port Power Control
+ ----------------------
+diff -druNp --no-dereference linux-libre-4.4-gnu/Documentation/virtual/kvm/mmu.txt linux-libre-4.4.7-gnu/Documentation/virtual/kvm/mmu.txt
+--- linux-libre-4.4-gnu/Documentation/virtual/kvm/mmu.txt 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/Documentation/virtual/kvm/mmu.txt 2016-04-12 12:09:26.000000000 -0400
+@@ -358,7 +358,8 @@ In the first case there are two addition
+ - if CR4.SMEP is enabled: since we've turned the page into a kernel page,
+ the kernel may now execute it. We handle this by also setting spte.nx.
+ If we get a user fetch or read fault, we'll change spte.u=1 and
+- spte.nx=gpte.nx back.
++ spte.nx=gpte.nx back. For this to work, KVM forces EFER.NX to 1 when
++ shadow paging is in use.
+ - if CR4.SMAP is disabled: since the page has been changed to a kernel
+ page, it can not be reused when CR4.SMAP is enabled. We set
+ CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/acpi/acpi_video.c linux-libre-4.4.7-gnu/drivers/acpi/acpi_video.c
+--- linux-libre-4.4-gnu/drivers/acpi/acpi_video.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/acpi/acpi_video.c 2016-04-12 12:09:26.000000000 -0400
+@@ -465,6 +465,15 @@ static struct dmi_system_id video_dmi_ta
+ * as brightness control does not work.
+ */
+ {
++ /* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
++ .callback = video_disable_backlight_sysfs_if,
++ .ident = "Toshiba Portege R700",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R700"),
++ },
++ },
++ {
+ /* https://bugs.freedesktop.org/show_bug.cgi?id=82634 */
+ .callback = video_disable_backlight_sysfs_if,
+ .ident = "Toshiba Portege R830",
+@@ -473,6 +482,15 @@ static struct dmi_system_id video_dmi_ta
+ DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R830"),
+ },
+ },
++ {
++ /* https://bugzilla.kernel.org/show_bug.cgi?id=21012 */
++ .callback = video_disable_backlight_sysfs_if,
++ .ident = "Toshiba Satellite R830",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE R830"),
++ },
++ },
+ /*
+ * Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set
+ * but the IDs actually follow the Device ID Scheme.
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/acpi/nfit.c linux-libre-4.4.7-gnu/drivers/acpi/nfit.c
+--- linux-libre-4.4-gnu/drivers/acpi/nfit.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/acpi/nfit.c 2016-04-12 12:09:26.000000000 -0400
+@@ -468,37 +468,16 @@ static void nfit_mem_find_spa_bdw(struct
+ nfit_mem->bdw = NULL;
+ }
+
+-static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
++static void nfit_mem_init_bdw(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa)
+ {
+ u16 dcr = __to_nfit_memdev(nfit_mem)->region_index;
+ struct nfit_memdev *nfit_memdev;
+ struct nfit_flush *nfit_flush;
+- struct nfit_dcr *nfit_dcr;
+ struct nfit_bdw *nfit_bdw;
+ struct nfit_idt *nfit_idt;
+ u16 idt_idx, range_index;
+
+- list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
+- if (nfit_dcr->dcr->region_index != dcr)
+- continue;
+- nfit_mem->dcr = nfit_dcr->dcr;
+- break;
+- }
+-
+- if (!nfit_mem->dcr) {
+- dev_dbg(acpi_desc->dev, "SPA %d missing:%s%s\n",
+- spa->range_index, __to_nfit_memdev(nfit_mem)
+- ? "" : " MEMDEV", nfit_mem->dcr ? "" : " DCR");
+- return -ENODEV;
+- }
+-
+- /*
+- * We've found enough to create an nvdimm, optionally
+- * find an associated BDW
+- */
+- list_add(&nfit_mem->list, &acpi_desc->dimms);
+-
+ list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) {
+ if (nfit_bdw->bdw->region_index != dcr)
+ continue;
+@@ -507,12 +486,12 @@ static int nfit_mem_add(struct acpi_nfit
+ }
+
+ if (!nfit_mem->bdw)
+- return 0;
++ return;
+
+ nfit_mem_find_spa_bdw(acpi_desc, nfit_mem);
+
+ if (!nfit_mem->spa_bdw)
+- return 0;
++ return;
+
+ range_index = nfit_mem->spa_bdw->range_index;
+ list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
+@@ -537,8 +516,6 @@ static int nfit_mem_add(struct acpi_nfit
+ }
+ break;
+ }
+-
+- return 0;
+ }
+
+ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
+@@ -547,7 +524,6 @@ static int nfit_mem_dcr_init(struct acpi
+ struct nfit_mem *nfit_mem, *found;
+ struct nfit_memdev *nfit_memdev;
+ int type = nfit_spa_type(spa);
+- u16 dcr;
+
+ switch (type) {
+ case NFIT_SPA_DCR:
+@@ -558,14 +534,18 @@ static int nfit_mem_dcr_init(struct acpi
+ }
+
+ list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
+- int rc;
++ struct nfit_dcr *nfit_dcr;
++ u32 device_handle;
++ u16 dcr;
+
+ if (nfit_memdev->memdev->range_index != spa->range_index)
+ continue;
+ found = NULL;
+ dcr = nfit_memdev->memdev->region_index;
++ device_handle = nfit_memdev->memdev->device_handle;
+ list_for_each_entry(nfit_mem, &acpi_desc->dimms, list)
+- if (__to_nfit_memdev(nfit_mem)->region_index == dcr) {
++ if (__to_nfit_memdev(nfit_mem)->device_handle
++ == device_handle) {
+ found = nfit_mem;
+ break;
+ }
+@@ -578,6 +558,31 @@ static int nfit_mem_dcr_init(struct acpi
+ if (!nfit_mem)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&nfit_mem->list);
++ list_add(&nfit_mem->list, &acpi_desc->dimms);
++ }
++
++ list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
++ if (nfit_dcr->dcr->region_index != dcr)
++ continue;
++ /*
++ * Record the control region for the dimm. For
++ * the ACPI 6.1 case, where there are separate
++ * control regions for the pmem vs blk
++ * interfaces, be sure to record the extended
++ * blk details.
++ */
++ if (!nfit_mem->dcr)
++ nfit_mem->dcr = nfit_dcr->dcr;
++ else if (nfit_mem->dcr->windows == 0
++ && nfit_dcr->dcr->windows)
++ nfit_mem->dcr = nfit_dcr->dcr;
++ break;
++ }
++
++ if (dcr && !nfit_mem->dcr) {
++ dev_err(acpi_desc->dev, "SPA %d missing DCR %d\n",
++ spa->range_index, dcr);
++ return -ENODEV;
+ }
+
+ if (type == NFIT_SPA_DCR) {
+@@ -594,6 +599,7 @@ static int nfit_mem_dcr_init(struct acpi
+ nfit_mem->idt_dcr = nfit_idt->idt;
+ break;
+ }
++ nfit_mem_init_bdw(acpi_desc, nfit_mem, spa);
+ } else {
+ /*
+ * A single dimm may belong to multiple SPA-PM
+@@ -602,13 +608,6 @@ static int nfit_mem_dcr_init(struct acpi
+ */
+ nfit_mem->memdev_pmem = nfit_memdev->memdev;
+ }
+-
+- if (found)
+- continue;
+-
+- rc = nfit_mem_add(acpi_desc, nfit_mem, spa);
+- if (rc)
+- return rc;
+ }
+
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/acpi/resource.c linux-libre-4.4.7-gnu/drivers/acpi/resource.c
+--- linux-libre-4.4-gnu/drivers/acpi/resource.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/acpi/resource.c 2016-04-12 12:09:26.000000000 -0400
+@@ -26,8 +26,20 @@
+
+ #ifdef CONFIG_X86
+ #define valid_IRQ(i) (((i) != 0) && ((i) != 2))
++static inline bool acpi_iospace_resource_valid(struct resource *res)
++{
++ /* On X86 IO space is limited to the [0 - 64K] IO port range */
++ return res->end < 0x10003;
++}
+ #else
+ #define valid_IRQ(i) (true)
++/*
++ * ACPI IO descriptors on arches other than X86 contain MMIO CPU physical
++ * addresses mapping IO space in CPU physical address space, IO space
++ * resources can be placed anywhere in the 64-bit physical address space.
++ */
++static inline bool
++acpi_iospace_resource_valid(struct resource *res) { return true; }
+ #endif
+
+ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
+@@ -126,7 +138,7 @@ static void acpi_dev_ioresource_flags(st
+ if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
+ res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
+
+- if (res->end >= 0x10003)
++ if (!acpi_iospace_resource_valid(res))
+ res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
+
+ if (io_decode == ACPI_DECODE_16)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/acpi/sleep.c linux-libre-4.4.7-gnu/drivers/acpi/sleep.c
+--- linux-libre-4.4-gnu/drivers/acpi/sleep.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/acpi/sleep.c 2016-04-12 12:09:26.000000000 -0400
+@@ -714,6 +714,7 @@ static int acpi_hibernation_enter(void)
+
+ static void acpi_hibernation_leave(void)
+ {
++ pm_set_resume_via_firmware();
+ /*
+ * If ACPI is not enabled by the BIOS and the boot kernel, we need to
+ * enable it here.
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/acpi/video_detect.c linux-libre-4.4.7-gnu/drivers/acpi/video_detect.c
+--- linux-libre-4.4-gnu/drivers/acpi/video_detect.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/acpi/video_detect.c 2016-04-12 12:09:26.000000000 -0400
+@@ -135,14 +135,6 @@ static const struct dmi_system_id video_
+ DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
+ },
+ },
+- {
+- .callback = video_detect_force_vendor,
+- .ident = "Dell Inspiron 5737",
+- .matches = {
+- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"),
+- },
+- },
+
+ /*
+ * These models have a working acpi_video backlight control, and using
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/android/binder.c linux-libre-4.4.7-gnu/drivers/android/binder.c
+--- linux-libre-4.4-gnu/drivers/android/binder.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/android/binder.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2074,7 +2074,7 @@ static int binder_thread_write(struct bi
+ if (get_user(cookie, (binder_uintptr_t __user *)ptr))
+ return -EFAULT;
+
+- ptr += sizeof(void *);
++ ptr += sizeof(cookie);
+ list_for_each_entry(w, &proc->delivered_death, entry) {
+ struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/ata/ahci.c linux-libre-4.4.7-gnu/drivers/ata/ahci.c
+--- linux-libre-4.4-gnu/drivers/ata/ahci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/ata/ahci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -264,6 +264,26 @@ static const struct pci_device_id ahci_p
+ { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
+@@ -347,15 +367,21 @@ static const struct pci_device_id ahci_p
+ { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
+ { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
+ { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
++ { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
++ { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
++ { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
++ { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
+ { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
++ { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
++ { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
+
+ /* JMicron 360/1/3/5/6, match class to avoid IDE function */
+ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/ata/libahci.c linux-libre-4.4.7-gnu/drivers/ata/libahci.c
+--- linux-libre-4.4-gnu/drivers/ata/libahci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/ata/libahci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -495,8 +495,8 @@ void ahci_save_initial_config(struct dev
+ }
+ }
+
+- /* fabricate port_map from cap.nr_ports */
+- if (!port_map) {
++ /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
++ if (!port_map && vers < 0x10300) {
+ port_map = (1 << ahci_nr_ports(cap)) - 1;
+ dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
+
+@@ -1142,8 +1142,7 @@ static void ahci_port_init(struct device
+
+ /* mark esata ports */
+ tmp = readl(port_mmio + PORT_CMD);
+- if ((tmp & PORT_CMD_HPCP) ||
+- ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
++ if ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))
+ ap->pflags |= ATA_PFLAG_EXTERNAL;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/ata/libata-scsi.c linux-libre-4.4.7-gnu/drivers/ata/libata-scsi.c
+--- linux-libre-4.4-gnu/drivers/ata/libata-scsi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/ata/libata-scsi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -675,19 +675,18 @@ static int ata_ioc32(struct ata_port *ap
+ int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
+ int cmd, void __user *arg)
+ {
+- int val = -EINVAL, rc = -EINVAL;
++ unsigned long val;
++ int rc = -EINVAL;
+ unsigned long flags;
+
+ switch (cmd) {
+- case ATA_IOC_GET_IO32:
++ case HDIO_GET_32BIT:
+ spin_lock_irqsave(ap->lock, flags);
+ val = ata_ioc32(ap);
+ spin_unlock_irqrestore(ap->lock, flags);
+- if (copy_to_user(arg, &val, 1))
+- return -EFAULT;
+- return 0;
++ return put_user(val, (unsigned long __user *)arg);
+
+- case ATA_IOC_SET_IO32:
++ case HDIO_SET_32BIT:
+ val = (unsigned long) arg;
+ rc = 0;
+ spin_lock_irqsave(ap->lock, flags);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/ata/libata-sff.c linux-libre-4.4.7-gnu/drivers/ata/libata-sff.c
+--- linux-libre-4.4-gnu/drivers/ata/libata-sff.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/ata/libata-sff.c 2016-04-12 12:09:26.000000000 -0400
+@@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struc
+ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+ struct ata_port *ap = qc->ap;
+- unsigned long flags;
+
+ if (ap->ops->error_handler) {
+ if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+-
+ /* EH might have kicked in while host lock is
+ * released.
+ */
+@@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct a
+ } else
+ ata_port_freeze(ap);
+ }
+-
+- spin_unlock_irqrestore(ap->lock, flags);
+ } else {
+ if (likely(!(qc->err_mask & AC_ERR_HSM)))
+ ata_qc_complete(qc);
+@@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct a
+ }
+ } else {
+ if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+ ata_sff_irq_on(ap);
+ ata_qc_complete(qc);
+- spin_unlock_irqrestore(ap->lock, flags);
+ } else
+ ata_qc_complete(qc);
+ }
+@@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap
+ {
+ struct ata_link *link = qc->dev->link;
+ struct ata_eh_info *ehi = &link->eh_info;
+- unsigned long flags = 0;
+ int poll_next;
+
++ lockdep_assert_held(ap->lock);
++
+ WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+
+ /* Make sure ata_sff_qc_issue() does not throw things
+@@ -1112,14 +1106,6 @@ fsm_start:
+ }
+ }
+
+- /* Send the CDB (atapi) or the first data block (ata pio out).
+- * During the state transition, interrupt handler shouldn't
+- * be invoked before the data transfer is complete and
+- * hsm_task_state is changed. Hence, the following locking.
+- */
+- if (in_wq)
+- spin_lock_irqsave(ap->lock, flags);
+-
+ if (qc->tf.protocol == ATA_PROT_PIO) {
+ /* PIO data out protocol.
+ * send first data block.
+@@ -1135,9 +1121,6 @@ fsm_start:
+ /* send CDB */
+ atapi_send_cdb(ap, qc);
+
+- if (in_wq)
+- spin_unlock_irqrestore(ap->lock, flags);
+-
+ /* if polling, ata_sff_pio_task() handles the rest.
+ * otherwise, interrupt handler takes over from here.
+ */
+@@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct work
+ u8 status;
+ int poll_next;
+
++ spin_lock_irq(ap->lock);
++
+ BUG_ON(ap->sff_pio_task_link == NULL);
+ /* qc can be NULL if timeout occurred */
+ qc = ata_qc_from_tag(ap, link->active_tag);
+ if (!qc) {
+ ap->sff_pio_task_link = NULL;
+- return;
++ goto out_unlock;
+ }
+
+ fsm_start:
+@@ -1381,11 +1366,14 @@ fsm_start:
+ */
+ status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
+ if (status & ATA_BUSY) {
++ spin_unlock_irq(ap->lock);
+ ata_msleep(ap, 2);
++ spin_lock_irq(ap->lock);
++
+ status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
+ if (status & ATA_BUSY) {
+ ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
+- return;
++ goto out_unlock;
+ }
+ }
+
+@@ -1402,6 +1390,8 @@ fsm_start:
+ */
+ if (poll_next)
+ goto fsm_start;
++out_unlock:
++ spin_unlock_irq(ap->lock);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/ata/pata_rb532_cf.c linux-libre-4.4.7-gnu/drivers/ata/pata_rb532_cf.c
+--- linux-libre-4.4-gnu/drivers/ata/pata_rb532_cf.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/ata/pata_rb532_cf.c 2016-04-12 12:09:26.000000000 -0400
+@@ -32,6 +32,8 @@
+ #include <linux/libata.h>
+ #include <scsi/scsi_host.h>
+
++#include <asm/mach-rc32434/rb.h>
++
+ #define DRV_NAME "pata-rb532-cf"
+ #define DRV_VERSION "0.1.0"
+ #define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
+@@ -107,6 +109,7 @@ static int rb532_pata_driver_probe(struc
+ int gpio;
+ struct resource *res;
+ struct ata_host *ah;
++ struct cf_device *pdata;
+ struct rb532_cf_info *info;
+ int ret;
+
+@@ -122,7 +125,13 @@ static int rb532_pata_driver_probe(struc
+ return -ENOENT;
+ }
+
+- gpio = irq_to_gpio(irq);
++ pdata = dev_get_platdata(&pdev->dev);
++ if (!pdata) {
++ dev_err(&pdev->dev, "no platform data specified\n");
++ return -EINVAL;
++ }
++
++ gpio = pdata->gpio_pin;
+ if (gpio < 0) {
+ dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
+ return -ENOENT;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/base/platform.c linux-libre-4.4.7-gnu/drivers/base/platform.c
+--- linux-libre-4.4-gnu/drivers/base/platform.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/base/platform.c 2016-04-12 12:09:26.000000000 -0400
+@@ -513,10 +513,15 @@ static int platform_drv_probe(struct dev
+ return ret;
+
+ ret = dev_pm_domain_attach(_dev, true);
+- if (ret != -EPROBE_DEFER && drv->probe) {
+- ret = drv->probe(dev);
+- if (ret)
+- dev_pm_domain_detach(_dev, true);
++ if (ret != -EPROBE_DEFER) {
++ if (drv->probe) {
++ ret = drv->probe(dev);
++ if (ret)
++ dev_pm_domain_detach(_dev, true);
++ } else {
++ /* don't fail if just dev_pm_domain_attach failed */
++ ret = 0;
++ }
+ }
+
+ if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/block/brd.c linux-libre-4.4.7-gnu/drivers/block/brd.c
+--- linux-libre-4.4-gnu/drivers/block/brd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/block/brd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -338,7 +338,7 @@ static blk_qc_t brd_make_request(struct
+
+ if (unlikely(bio->bi_rw & REQ_DISCARD)) {
+ if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) ||
+- bio->bi_iter.bi_size & PAGE_MASK)
++ bio->bi_iter.bi_size & ~PAGE_MASK)
+ goto io_error;
+ discard_from_brd(brd, sector, bio->bi_iter.bi_size);
+ goto out;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/block/mtip32xx/mtip32xx.c linux-libre-4.4.7-gnu/drivers/block/mtip32xx/mtip32xx.c
+--- linux-libre-4.4-gnu/drivers/block/mtip32xx/mtip32xx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/block/mtip32xx/mtip32xx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_com
+ {
+ struct request *rq;
+
++ if (mtip_check_surprise_removal(dd->pdev))
++ return NULL;
++
+ rq = blk_mq_alloc_request(dd->queue, 0, __GFP_RECLAIM, true);
++ if (IS_ERR(rq))
++ return NULL;
++
+ return blk_mq_rq_to_pdu(rq);
+ }
+
+@@ -233,15 +239,9 @@ static void mtip_async_complete(struct m
+ "Command tag %d failed due to TFE\n", tag);
+ }
+
+- /* Unmap the DMA scatter list entries */
+- dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction);
+-
+ rq = mtip_rq_from_tag(dd, tag);
+
+- if (unlikely(cmd->unaligned))
+- up(&port->cmd_slot_unal);
+-
+- blk_mq_end_request(rq, status ? -EIO : 0);
++ blk_mq_complete_request(rq, status);
+ }
+
+ /*
+@@ -581,6 +581,8 @@ static void mtip_completion(struct mtip_
+ dev_warn(&port->dd->pdev->dev,
+ "Internal command %d completed with TFE\n", tag);
+
++ command->comp_func = NULL;
++ command->comp_data = NULL;
+ complete(waiting);
+ }
+
+@@ -618,8 +620,6 @@ static void mtip_handle_tfe(struct drive
+
+ port = dd->port;
+
+- set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
+-
+ if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+ cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
+ dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n");
+@@ -628,7 +628,7 @@ static void mtip_handle_tfe(struct drive
+ cmd->comp_func(port, MTIP_TAG_INTERNAL,
+ cmd, PORT_IRQ_TF_ERR);
+ }
+- goto handle_tfe_exit;
++ return;
+ }
+
+ /* clear the tag accumulator */
+@@ -701,7 +701,7 @@ static void mtip_handle_tfe(struct drive
+ fail_reason = "thermal shutdown";
+ }
+ if (buf[288] == 0xBF) {
+- set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag);
++ set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
+ dev_info(&dd->pdev->dev,
+ "Drive indicates rebuild has failed. Secure erase required.\n");
+ fail_all_ncq_cmds = 1;
+@@ -771,11 +771,6 @@ static void mtip_handle_tfe(struct drive
+ }
+ }
+ print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
+-
+-handle_tfe_exit:
+- /* clear eh_active */
+- clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
+- wake_up_interruptible(&port->svc_wait);
+ }
+
+ /*
+@@ -1007,6 +1002,7 @@ static bool mtip_pause_ncq(struct mtip_p
+ (fis->features == 0x27 || fis->features == 0x72 ||
+ fis->features == 0x62 || fis->features == 0x26))) {
+ clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
++ clear_bit(MTIP_DDF_REBUILD_FAILED_BIT, &port->dd->dd_flag);
+ /* Com reset after secure erase or lowlevel format */
+ mtip_restart_port(port);
+ clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+@@ -1021,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_p
+ *
+ * @port Pointer to port data structure
+ * @timeout Max duration to wait (ms)
++ * @atomic gfp_t flag to indicate blockable context or not
+ *
+ * return value
+ * 0 Success
+ * -EBUSY Commands still active
+ */
+-static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
++static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout,
++ gfp_t atomic)
+ {
+ unsigned long to;
+ unsigned int n;
+@@ -1037,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_p
+ to = jiffies + msecs_to_jiffies(timeout);
+ do {
+ if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) &&
+- test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
++ test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) &&
++ atomic == GFP_KERNEL) {
+ msleep(20);
+ continue; /* svc thd is actively issuing commands */
+ }
+
+- msleep(100);
++ if (atomic == GFP_KERNEL)
++ msleep(100);
++ else {
++ cpu_relax();
++ udelay(100);
++ }
++
+ if (mtip_check_surprise_removal(port->dd->pdev))
+ goto err_fault;
+- if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+- goto err_fault;
+
+ /*
+ * Ignore s_active bit 0 of array element 0.
+@@ -1099,6 +1102,7 @@ static int mtip_exec_internal_command(st
+ struct mtip_cmd *int_cmd;
+ struct driver_data *dd = port->dd;
+ int rv = 0;
++ unsigned long start;
+
+ /* Make sure the buffer is 8 byte aligned. This is asic specific. */
+ if (buffer & 0x00000007) {
+@@ -1107,6 +1111,10 @@ static int mtip_exec_internal_command(st
+ }
+
+ int_cmd = mtip_get_int_command(dd);
++ if (!int_cmd) {
++ dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n");
++ return -EFAULT;
++ }
+
+ set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
+
+@@ -1119,7 +1127,7 @@ static int mtip_exec_internal_command(st
+ if (fis->command != ATA_CMD_STANDBYNOW1) {
+ /* wait for io to complete if non atomic */
+ if (mtip_quiesce_io(port,
+- MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) {
++ MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) {
+ dev_warn(&dd->pdev->dev,
+ "Failed to quiesce IO\n");
+ mtip_put_int_command(dd, int_cmd);
+@@ -1162,6 +1170,8 @@ static int mtip_exec_internal_command(st
+ /* Populate the command header */
+ int_cmd->command_header->byte_count = 0;
+
++ start = jiffies;
++
+ /* Issue the command to the hardware */
+ mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
+
+@@ -1170,10 +1180,12 @@ static int mtip_exec_internal_command(st
+ if ((rv = wait_for_completion_interruptible_timeout(
+ &wait,
+ msecs_to_jiffies(timeout))) <= 0) {
++
+ if (rv == -ERESTARTSYS) { /* interrupted */
+ dev_err(&dd->pdev->dev,
+- "Internal command [%02X] was interrupted after %lu ms\n",
+- fis->command, timeout);
++ "Internal command [%02X] was interrupted after %u ms\n",
++ fis->command,
++ jiffies_to_msecs(jiffies - start));
+ rv = -EINTR;
+ goto exec_ic_exit;
+ } else if (rv == 0) /* timeout */
+@@ -2897,6 +2909,42 @@ static int mtip_ftl_rebuild_poll(struct
+ return -EFAULT;
+ }
+
++static void mtip_softirq_done_fn(struct request *rq)
++{
++ struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
++ struct driver_data *dd = rq->q->queuedata;
++
++ /* Unmap the DMA scatter list entries */
++ dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents,
++ cmd->direction);
++
++ if (unlikely(cmd->unaligned))
++ up(&dd->port->cmd_slot_unal);
++
++ blk_mq_end_request(rq, rq->errors);
++}
++
++static void mtip_abort_cmd(struct request *req, void *data,
++ bool reserved)
++{
++ struct driver_data *dd = data;
++
++ dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag);
++
++ clear_bit(req->tag, dd->port->cmds_to_issue);
++ req->errors = -EIO;
++ mtip_softirq_done_fn(req);
++}
++
++static void mtip_queue_cmd(struct request *req, void *data,
++ bool reserved)
++{
++ struct driver_data *dd = data;
++
++ set_bit(req->tag, dd->port->cmds_to_issue);
++ blk_abort_request(req);
++}
++
+ /*
+ * service thread to issue queued commands
+ *
+@@ -2909,7 +2957,7 @@ static int mtip_ftl_rebuild_poll(struct
+ static int mtip_service_thread(void *data)
+ {
+ struct driver_data *dd = (struct driver_data *)data;
+- unsigned long slot, slot_start, slot_wrap;
++ unsigned long slot, slot_start, slot_wrap, to;
+ unsigned int num_cmd_slots = dd->slot_groups * 32;
+ struct mtip_port *port = dd->port;
+
+@@ -2924,9 +2972,7 @@ static int mtip_service_thread(void *dat
+ * is in progress nor error handling is active
+ */
+ wait_event_interruptible(port->svc_wait, (port->flags) &&
+- !(port->flags & MTIP_PF_PAUSE_IO));
+-
+- set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
++ (port->flags & MTIP_PF_SVC_THD_WORK));
+
+ if (kthread_should_stop() ||
+ test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
+@@ -2936,6 +2982,8 @@ static int mtip_service_thread(void *dat
+ &dd->dd_flag)))
+ goto st_out;
+
++ set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
++
+ restart_eh:
+ /* Demux bits: start with error handling */
+ if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) {
+@@ -2946,6 +2994,32 @@ restart_eh:
+ if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags))
+ goto restart_eh;
+
++ if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) {
++ to = jiffies + msecs_to_jiffies(5000);
++
++ do {
++ mdelay(100);
++ } while (atomic_read(&dd->irq_workers_active) != 0 &&
++ time_before(jiffies, to));
++
++ if (atomic_read(&dd->irq_workers_active) != 0)
++ dev_warn(&dd->pdev->dev,
++ "Completion workers still active!");
++
++ spin_lock(dd->queue->queue_lock);
++ blk_mq_all_tag_busy_iter(*dd->tags.tags,
++ mtip_queue_cmd, dd);
++ spin_unlock(dd->queue->queue_lock);
++
++ set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags);
++
++ if (mtip_device_reset(dd))
++ blk_mq_all_tag_busy_iter(*dd->tags.tags,
++ mtip_abort_cmd, dd);
++
++ clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags);
++ }
++
+ if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
+ slot = 1;
+ /* used to restrict the loop to one iteration */
+@@ -2978,10 +3052,8 @@ restart_eh:
+ }
+
+ if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) {
+- if (mtip_ftl_rebuild_poll(dd) < 0)
+- set_bit(MTIP_DDF_REBUILD_FAILED_BIT,
+- &dd->dd_flag);
+- clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
++ if (mtip_ftl_rebuild_poll(dd) == 0)
++ clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
+ }
+ }
+
+@@ -3096,7 +3168,7 @@ static int mtip_hw_get_identify(struct d
+ if (buf[288] == 0xBF) {
+ dev_info(&dd->pdev->dev,
+ "Drive indicates rebuild has failed.\n");
+- /* TODO */
++ set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
+ }
+ }
+
+@@ -3270,20 +3342,25 @@ out1:
+ return rv;
+ }
+
+-static void mtip_standby_drive(struct driver_data *dd)
++static int mtip_standby_drive(struct driver_data *dd)
+ {
+- if (dd->sr)
+- return;
++ int rv = 0;
+
++ if (dd->sr || !dd->port)
++ return -ENODEV;
+ /*
+ * Send standby immediate (E0h) to the drive so that it
+ * saves its state.
+ */
+ if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags) &&
+- !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))
+- if (mtip_standby_immediate(dd->port))
++ !test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag) &&
++ !test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) {
++ rv = mtip_standby_immediate(dd->port);
++ if (rv)
+ dev_warn(&dd->pdev->dev,
+ "STANDBY IMMEDIATE failed\n");
++ }
++ return rv;
+ }
+
+ /*
+@@ -3296,10 +3373,6 @@ static void mtip_standby_drive(struct dr
+ */
+ static int mtip_hw_exit(struct driver_data *dd)
+ {
+- /*
+- * Send standby immediate (E0h) to the drive so that it
+- * saves its state.
+- */
+ if (!dd->sr) {
+ /* de-initialize the port. */
+ mtip_deinit_port(dd->port);
+@@ -3341,8 +3414,7 @@ static int mtip_hw_shutdown(struct drive
+ * Send standby immediate (E0h) to the drive so that it
+ * saves its state.
+ */
+- if (!dd->sr && dd->port)
+- mtip_standby_immediate(dd->port);
++ mtip_standby_drive(dd);
+
+ return 0;
+ }
+@@ -3365,7 +3437,7 @@ static int mtip_hw_suspend(struct driver
+ * Send standby immediate (E0h) to the drive
+ * so that it saves its state.
+ */
+- if (mtip_standby_immediate(dd->port) != 0) {
++ if (mtip_standby_drive(dd) != 0) {
+ dev_err(&dd->pdev->dev,
+ "Failed standby-immediate command\n");
+ return -EFAULT;
+@@ -3603,6 +3675,28 @@ static int mtip_block_getgeo(struct bloc
+ return 0;
+ }
+
++static int mtip_block_open(struct block_device *dev, fmode_t mode)
++{
++ struct driver_data *dd;
++
++ if (dev && dev->bd_disk) {
++ dd = (struct driver_data *) dev->bd_disk->private_data;
++
++ if (dd) {
++ if (test_bit(MTIP_DDF_REMOVAL_BIT,
++ &dd->dd_flag)) {
++ return -ENODEV;
++ }
++ return 0;
++ }
++ }
++ return -ENODEV;
++}
++
++void mtip_block_release(struct gendisk *disk, fmode_t mode)
++{
++}
++
+ /*
+ * Block device operation function.
+ *
+@@ -3610,6 +3704,8 @@ static int mtip_block_getgeo(struct bloc
+ * layer.
+ */
+ static const struct block_device_operations mtip_block_ops = {
++ .open = mtip_block_open,
++ .release = mtip_block_release,
+ .ioctl = mtip_block_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = mtip_block_compat_ioctl,
+@@ -3671,10 +3767,9 @@ static int mtip_submit_request(struct bl
+ rq_data_dir(rq))) {
+ return -ENODATA;
+ }
+- if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)))
++ if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag) ||
++ test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)))
+ return -ENODATA;
+- if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))
+- return -ENXIO;
+ }
+
+ if (rq->cmd_flags & REQ_DISCARD) {
+@@ -3786,11 +3881,33 @@ static int mtip_init_cmd(void *data, str
+ return 0;
+ }
+
++static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req,
++ bool reserved)
++{
++ struct driver_data *dd = req->q->queuedata;
++ int ret = BLK_EH_RESET_TIMER;
++
++ if (reserved)
++ goto exit_handler;
++
++ if (test_bit(req->tag, dd->port->cmds_to_issue))
++ goto exit_handler;
++
++ if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags))
++ goto exit_handler;
++
++ wake_up_interruptible(&dd->port->svc_wait);
++exit_handler:
++ return ret;
++}
++
+ static struct blk_mq_ops mtip_mq_ops = {
+ .queue_rq = mtip_queue_rq,
+ .map_queue = blk_mq_map_queue,
+ .init_request = mtip_init_cmd,
+ .exit_request = mtip_free_cmd,
++ .complete = mtip_softirq_done_fn,
++ .timeout = mtip_cmd_timeout,
+ };
+
+ /*
+@@ -3857,7 +3974,6 @@ static int mtip_block_initialize(struct
+
+ mtip_hw_debugfs_init(dd);
+
+-skip_create_disk:
+ memset(&dd->tags, 0, sizeof(dd->tags));
+ dd->tags.ops = &mtip_mq_ops;
+ dd->tags.nr_hw_queues = 1;
+@@ -3867,12 +3983,13 @@ skip_create_disk:
+ dd->tags.numa_node = dd->numa_node;
+ dd->tags.flags = BLK_MQ_F_SHOULD_MERGE;
+ dd->tags.driver_data = dd;
++ dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS;
+
+ rv = blk_mq_alloc_tag_set(&dd->tags);
+ if (rv) {
+ dev_err(&dd->pdev->dev,
+ "Unable to allocate request queue\n");
+- goto block_queue_alloc_init_error;
++ goto block_queue_alloc_tag_error;
+ }
+
+ /* Allocate the request queue. */
+@@ -3887,6 +4004,7 @@ skip_create_disk:
+ dd->disk->queue = dd->queue;
+ dd->queue->queuedata = dd;
+
++skip_create_disk:
+ /* Initialize the protocol layer. */
+ wait_for_rebuild = mtip_hw_get_identify(dd);
+ if (wait_for_rebuild < 0) {
+@@ -3983,8 +4101,9 @@ kthread_run_error:
+ read_capacity_error:
+ init_hw_cmds_error:
+ blk_cleanup_queue(dd->queue);
+- blk_mq_free_tag_set(&dd->tags);
+ block_queue_alloc_init_error:
++ blk_mq_free_tag_set(&dd->tags);
++block_queue_alloc_tag_error:
+ mtip_hw_debugfs_exit(dd);
+ disk_index_error:
+ spin_lock(&rssd_index_lock);
+@@ -4001,6 +4120,22 @@ protocol_init_error:
+ return rv;
+ }
+
++static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv)
++{
++ struct driver_data *dd = (struct driver_data *)data;
++ struct mtip_cmd *cmd;
++
++ if (likely(!reserv))
++ blk_mq_complete_request(rq, -ENODEV);
++ else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) {
++
++ cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
++ if (cmd->comp_func)
++ cmd->comp_func(dd->port, MTIP_TAG_INTERNAL,
++ cmd, -ENODEV);
++ }
++}
++
+ /*
+ * Block layer deinitialization function.
+ *
+@@ -4032,12 +4167,23 @@ static int mtip_block_remove(struct driv
+ }
+ }
+
+- if (!dd->sr)
+- mtip_standby_drive(dd);
++ if (!dd->sr) {
++ /*
++ * Explicitly wait here for IOs to quiesce,
++ * as mtip_standby_drive usually won't wait for IOs.
++ */
++ if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS,
++ GFP_KERNEL))
++ mtip_standby_drive(dd);
++ }
+ else
+ dev_info(&dd->pdev->dev, "device %s surprise removal\n",
+ dd->disk->disk_name);
+
++ blk_mq_freeze_queue_start(dd->queue);
++ blk_mq_stop_hw_queues(dd->queue);
++ blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd);
++
+ /*
+ * Delete our gendisk structure. This also removes the device
+ * from /dev
+@@ -4047,7 +4193,8 @@ static int mtip_block_remove(struct driv
+ dd->bdev = NULL;
+ }
+ if (dd->disk) {
+- del_gendisk(dd->disk);
++ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
++ del_gendisk(dd->disk);
+ if (dd->disk->queue) {
+ blk_cleanup_queue(dd->queue);
+ blk_mq_free_tag_set(&dd->tags);
+@@ -4088,7 +4235,8 @@ static int mtip_block_shutdown(struct dr
+ dev_info(&dd->pdev->dev,
+ "Shutting down %s ...\n", dd->disk->disk_name);
+
+- del_gendisk(dd->disk);
++ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
++ del_gendisk(dd->disk);
+ if (dd->disk->queue) {
+ blk_cleanup_queue(dd->queue);
+ blk_mq_free_tag_set(&dd->tags);
+@@ -4433,7 +4581,7 @@ static void mtip_pci_remove(struct pci_d
+ struct driver_data *dd = pci_get_drvdata(pdev);
+ unsigned long flags, to;
+
+- set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
++ set_bit(MTIP_DDF_REMOVAL_BIT, &dd->dd_flag);
+
+ spin_lock_irqsave(&dev_lock, flags);
+ list_del_init(&dd->online_list);
+@@ -4450,12 +4598,17 @@ static void mtip_pci_remove(struct pci_d
+ } while (atomic_read(&dd->irq_workers_active) != 0 &&
+ time_before(jiffies, to));
+
++ if (!dd->sr)
++ fsync_bdev(dd->bdev);
++
+ if (atomic_read(&dd->irq_workers_active) != 0) {
+ dev_warn(&dd->pdev->dev,
+ "Completion workers still active!\n");
+ }
+
+- blk_mq_stop_hw_queues(dd->queue);
++ blk_set_queue_dying(dd->queue);
++ set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
++
+ /* Clean up the block layer. */
+ mtip_block_remove(dd);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/block/mtip32xx/mtip32xx.h linux-libre-4.4.7-gnu/drivers/block/mtip32xx/mtip32xx.h
+--- linux-libre-4.4-gnu/drivers/block/mtip32xx/mtip32xx.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/block/mtip32xx/mtip32xx.h 2016-04-12 12:09:26.000000000 -0400
+@@ -134,16 +134,24 @@ enum {
+ MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */
+ MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */
+ MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */
++ MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */
+ MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) |
+ (1 << MTIP_PF_EH_ACTIVE_BIT) |
+ (1 << MTIP_PF_SE_ACTIVE_BIT) |
+- (1 << MTIP_PF_DM_ACTIVE_BIT)),
++ (1 << MTIP_PF_DM_ACTIVE_BIT) |
++ (1 << MTIP_PF_TO_ACTIVE_BIT)),
+
+ MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
+ MTIP_PF_ISSUE_CMDS_BIT = 5,
+ MTIP_PF_REBUILD_BIT = 6,
+ MTIP_PF_SVC_THD_STOP_BIT = 8,
+
++ MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) |
++ (1 << MTIP_PF_ISSUE_CMDS_BIT) |
++ (1 << MTIP_PF_REBUILD_BIT) |
++ (1 << MTIP_PF_SVC_THD_STOP_BIT) |
++ (1 << MTIP_PF_TO_ACTIVE_BIT)),
++
+ /* below are bit numbers in 'dd_flag' defined in driver_data */
+ MTIP_DDF_SEC_LOCK_BIT = 0,
+ MTIP_DDF_REMOVE_PENDING_BIT = 1,
+@@ -153,6 +161,7 @@ enum {
+ MTIP_DDF_RESUME_BIT = 6,
+ MTIP_DDF_INIT_DONE_BIT = 7,
+ MTIP_DDF_REBUILD_FAILED_BIT = 8,
++ MTIP_DDF_REMOVAL_BIT = 9,
+
+ MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
+ (1 << MTIP_DDF_SEC_LOCK_BIT) |
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/block/zram/zcomp.c linux-libre-4.4.7-gnu/drivers/block/zram/zcomp.c
+--- linux-libre-4.4-gnu/drivers/block/zram/zcomp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/block/zram/zcomp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -76,7 +76,7 @@ static void zcomp_strm_free(struct zcomp
+ */
+ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
+ {
+- struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
++ struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_NOIO);
+ if (!zstrm)
+ return NULL;
+
+@@ -85,7 +85,7 @@ static struct zcomp_strm *zcomp_strm_all
+ * allocate 2 pages. 1 for compressed data, plus 1 extra for the
+ * case when compressed size is larger than the original one
+ */
+- zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
++ zstrm->buffer = (void *)__get_free_pages(GFP_NOIO | __GFP_ZERO, 1);
+ if (!zstrm->private || !zstrm->buffer) {
+ zcomp_strm_free(comp, zstrm);
+ zstrm = NULL;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/block/zram/zcomp_lz4.c linux-libre-4.4.7-gnu/drivers/block/zram/zcomp_lz4.c
+--- linux-libre-4.4-gnu/drivers/block/zram/zcomp_lz4.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/block/zram/zcomp_lz4.c 2016-04-12 12:09:26.000000000 -0400
+@@ -10,17 +10,36 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/lz4.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
+
+ #include "zcomp_lz4.h"
+
+ static void *zcomp_lz4_create(void)
+ {
+- return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
++ void *ret;
++
++ /*
++ * This function can be called in swapout/fs write path
++ * so we can't use GFP_FS|IO. And it assumes we already
++ * have at least one stream in zram initialization so we
++ * don't do best effort to allocate more stream in here.
++ * A default stream will work well without further multiple
++ * streams. That's why we use NORETRY | NOWARN.
++ */
++ ret = kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
++ __GFP_NOWARN);
++ if (!ret)
++ ret = __vmalloc(LZ4_MEM_COMPRESS,
++ GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
++ __GFP_ZERO | __GFP_HIGHMEM,
++ PAGE_KERNEL);
++ return ret;
+ }
+
+ static void zcomp_lz4_destroy(void *private)
+ {
+- kfree(private);
++ kvfree(private);
+ }
+
+ static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/block/zram/zcomp_lzo.c linux-libre-4.4.7-gnu/drivers/block/zram/zcomp_lzo.c
+--- linux-libre-4.4-gnu/drivers/block/zram/zcomp_lzo.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/block/zram/zcomp_lzo.c 2016-04-12 12:09:26.000000000 -0400
+@@ -10,17 +10,36 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/lzo.h>
++#include <linux/vmalloc.h>
++#include <linux/mm.h>
+
+ #include "zcomp_lzo.h"
+
+ static void *lzo_create(void)
+ {
+- return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
++ void *ret;
++
++ /*
++ * This function can be called in swapout/fs write path
++ * so we can't use GFP_FS|IO. And it assumes we already
++ * have at least one stream in zram initialization so we
++ * don't do best effort to allocate more stream in here.
++ * A default stream will work well without further multiple
++ * streams. That's why we use NORETRY | NOWARN.
++ */
++ ret = kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
++ __GFP_NOWARN);
++ if (!ret)
++ ret = __vmalloc(LZO1X_MEM_COMPRESS,
++ GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
++ __GFP_ZERO | __GFP_HIGHMEM,
++ PAGE_KERNEL);
++ return ret;
+ }
+
+ static void lzo_destroy(void *private)
+ {
+- kfree(private);
++ kvfree(private);
+ }
+
+ static int lzo_compress(const unsigned char *src, unsigned char *dst,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/block/zram/zram_drv.c linux-libre-4.4.7-gnu/drivers/block/zram/zram_drv.c
+--- linux-libre-4.4-gnu/drivers/block/zram/zram_drv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/block/zram/zram_drv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1325,7 +1325,6 @@ static int zram_remove(struct zram *zram
+
+ pr_info("Removed device: %s\n", zram->disk->disk_name);
+
+- idr_remove(&zram_index_idr, zram->disk->first_minor);
+ blk_cleanup_queue(zram->disk->queue);
+ del_gendisk(zram->disk);
+ put_disk(zram->disk);
+@@ -1367,10 +1366,12 @@ static ssize_t hot_remove_store(struct c
+ mutex_lock(&zram_index_mutex);
+
+ zram = idr_find(&zram_index_idr, dev_id);
+- if (zram)
++ if (zram) {
+ ret = zram_remove(zram);
+- else
++ idr_remove(&zram_index_idr, dev_id);
++ } else {
+ ret = -ENODEV;
++ }
+
+ mutex_unlock(&zram_index_mutex);
+ return ret ? ret : count;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/bluetooth/ath3k.c linux-libre-4.4.7-gnu/drivers/bluetooth/ath3k.c
+--- linux-libre-4.4-gnu/drivers/bluetooth/ath3k.c 2016-01-10 21:11:47.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/bluetooth/ath3k.c 2016-04-12 21:28:07.000000000 -0400
+@@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_
+ { USB_DEVICE(0x0489, 0xe05f) },
+ { USB_DEVICE(0x0489, 0xe076) },
+ { USB_DEVICE(0x0489, 0xe078) },
++ { USB_DEVICE(0x0489, 0xe095) },
+ { USB_DEVICE(0x04c5, 0x1330) },
+ { USB_DEVICE(0x04CA, 0x3004) },
+ { USB_DEVICE(0x04CA, 0x3005) },
+@@ -92,6 +93,7 @@ static const struct usb_device_id ath3k_
+ { USB_DEVICE(0x04CA, 0x300d) },
+ { USB_DEVICE(0x04CA, 0x300f) },
+ { USB_DEVICE(0x04CA, 0x3010) },
++ { USB_DEVICE(0x04CA, 0x3014) },
+ { USB_DEVICE(0x0930, 0x0219) },
+ { USB_DEVICE(0x0930, 0x021c) },
+ { USB_DEVICE(0x0930, 0x0220) },
+@@ -113,10 +115,12 @@ static const struct usb_device_id ath3k_
+ { USB_DEVICE(0x13d3, 0x3362) },
+ { USB_DEVICE(0x13d3, 0x3375) },
+ { USB_DEVICE(0x13d3, 0x3393) },
++ { USB_DEVICE(0x13d3, 0x3395) },
+ { USB_DEVICE(0x13d3, 0x3402) },
+ { USB_DEVICE(0x13d3, 0x3408) },
+ { USB_DEVICE(0x13d3, 0x3423) },
+ { USB_DEVICE(0x13d3, 0x3432) },
++ { USB_DEVICE(0x13d3, 0x3472) },
+ { USB_DEVICE(0x13d3, 0x3474) },
+
+ /* Atheros AR5BBU12 with sflash firmware */
+@@ -144,6 +148,7 @@ static const struct usb_device_id ath3k_
+ { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+@@ -154,6 +159,7 @@ static const struct usb_device_id ath3k_
+ { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
+@@ -175,10 +181,12 @@ static const struct usb_device_id ath3k_
+ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
+
+ /* Atheros AR5BBU22 with sflash firmware */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/bluetooth/btusb.c linux-libre-4.4.7-gnu/drivers/bluetooth/btusb.c
+--- linux-libre-4.4-gnu/drivers/bluetooth/btusb.c 2016-01-10 21:12:01.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/bluetooth/btusb.c 2016-04-12 21:28:21.000000000 -0400
+@@ -153,6 +153,10 @@ static const struct usb_device_id btusb_
+ { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
+ .driver_info = BTUSB_BCM_PATCHRAM },
+
++ /* Toshiba Corp - Broadcom based */
++ { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
++ .driver_info = BTUSB_BCM_PATCHRAM },
++
+ /* Intel Bluetooth USB Bootloader (RAM module) */
+ { USB_DEVICE(0x8087, 0x0a5a),
+ .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
+@@ -192,6 +196,7 @@ static const struct usb_device_id blackl
+ { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+@@ -202,6 +207,7 @@ static const struct usb_device_id blackl
+ { USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
+@@ -223,10 +229,12 @@ static const struct usb_device_id blackl
+ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
++ { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
+
+ /* Atheros AR5BBU12 with sflash firmware */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/char/tpm/tpm-chip.c linux-libre-4.4.7-gnu/drivers/char/tpm/tpm-chip.c
+--- linux-libre-4.4-gnu/drivers/char/tpm/tpm-chip.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/char/tpm/tpm-chip.c 2016-04-12 12:09:26.000000000 -0400
+@@ -136,11 +136,13 @@ struct tpm_chip *tpmm_chip_alloc(struct
+ chip->cdev.owner = chip->pdev->driver->owner;
+ chip->cdev.kobj.parent = &chip->dev.kobj;
+
++ devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
++
+ return chip;
+ }
+ EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
+
+-static int tpm_dev_add_device(struct tpm_chip *chip)
++static int tpm_add_char_device(struct tpm_chip *chip)
+ {
+ int rc;
+
+@@ -151,7 +153,6 @@ static int tpm_dev_add_device(struct tpm
+ chip->devname, MAJOR(chip->dev.devt),
+ MINOR(chip->dev.devt), rc);
+
+- device_unregister(&chip->dev);
+ return rc;
+ }
+
+@@ -162,16 +163,17 @@ static int tpm_dev_add_device(struct tpm
+ chip->devname, MAJOR(chip->dev.devt),
+ MINOR(chip->dev.devt), rc);
+
++ cdev_del(&chip->cdev);
+ return rc;
+ }
+
+ return rc;
+ }
+
+-static void tpm_dev_del_device(struct tpm_chip *chip)
++static void tpm_del_char_device(struct tpm_chip *chip)
+ {
+ cdev_del(&chip->cdev);
+- device_unregister(&chip->dev);
++ device_del(&chip->dev);
+ }
+
+ static int tpm1_chip_register(struct tpm_chip *chip)
+@@ -222,7 +224,7 @@ int tpm_chip_register(struct tpm_chip *c
+
+ tpm_add_ppi(chip);
+
+- rc = tpm_dev_add_device(chip);
++ rc = tpm_add_char_device(chip);
+ if (rc)
+ goto out_err;
+
+@@ -274,6 +276,6 @@ void tpm_chip_unregister(struct tpm_chip
+ sysfs_remove_link(&chip->pdev->kobj, "ppi");
+
+ tpm1_chip_unregister(chip);
+- tpm_dev_del_device(chip);
++ tpm_del_char_device(chip);
+ }
+ EXPORT_SYMBOL_GPL(tpm_chip_unregister);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/char/tpm/tpm_crb.c linux-libre-4.4.7-gnu/drivers/char/tpm/tpm_crb.c
+--- linux-libre-4.4-gnu/drivers/char/tpm/tpm_crb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/char/tpm/tpm_crb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -310,11 +310,11 @@ static int crb_acpi_remove(struct acpi_d
+ struct device *dev = &device->dev;
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+
+- tpm_chip_unregister(chip);
+-
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ tpm2_shutdown(chip, TPM2_SU_CLEAR);
+
++ tpm_chip_unregister(chip);
++
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/char/tpm/tpm_eventlog.c linux-libre-4.4.7-gnu/drivers/char/tpm/tpm_eventlog.c
+--- linux-libre-4.4-gnu/drivers/char/tpm/tpm_eventlog.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/char/tpm/tpm_eventlog.c 2016-04-12 12:09:26.000000000 -0400
+@@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_
+ {
+ struct tcpa_event *event = v;
+ struct tcpa_event temp_event;
+- char *tempPtr;
++ char *temp_ptr;
+ int i;
+
+ memcpy(&temp_event, event, sizeof(struct tcpa_event));
+@@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_
+ temp_event.event_type = do_endian_conversion(event->event_type);
+ temp_event.event_size = do_endian_conversion(event->event_size);
+
+- tempPtr = (char *)&temp_event;
++ temp_ptr = (char *) &temp_event;
+
+- for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++)
+- seq_putc(m, tempPtr[i]);
++ for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
++ seq_putc(m, temp_ptr[i]);
++
++ temp_ptr = (char *) v;
++
++ for (i = (sizeof(struct tcpa_event) - 1);
++ i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
++ seq_putc(m, temp_ptr[i]);
+
+ return 0;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/clk/bcm/clk-bcm2835.c linux-libre-4.4.7-gnu/drivers/clk/bcm/clk-bcm2835.c
+--- linux-libre-4.4-gnu/drivers/clk/bcm/clk-bcm2835.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/clk/bcm/clk-bcm2835.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1097,13 +1097,15 @@ static int bcm2835_pll_divider_set_rate(
+ struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
+ struct bcm2835_cprman *cprman = divider->cprman;
+ const struct bcm2835_pll_divider_data *data = divider->data;
+- u32 cm;
+- int ret;
++ u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS;
+
+- ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
+- if (ret)
+- return ret;
++ div = DIV_ROUND_UP_ULL(parent_rate, rate);
++
++ div = min(div, max_div);
++ if (div == max_div)
++ div = 0;
+
++ cprman_write(cprman, data->a2w_reg, div);
+ cm = cprman_read(cprman, data->cm_reg);
+ cprman_write(cprman, data->cm_reg, cm | data->load_mask);
+ cprman_write(cprman, data->cm_reg, cm & ~data->load_mask);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/clk/rockchip/clk-rk3188.c linux-libre-4.4.7-gnu/drivers/clk/rockchip/clk-rk3188.c
+--- linux-libre-4.4-gnu/drivers/clk/rockchip/clk-rk3188.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/clk/rockchip/clk-rk3188.c 2016-04-12 12:09:26.000000000 -0400
+@@ -718,6 +718,7 @@ static const char *const rk3188_critical
+ "hclk_peri",
+ "pclk_cpu",
+ "pclk_peri",
++ "hclk_cpubus"
+ };
+
+ static void __init rk3188_common_clk_init(struct device_node *np)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/clk/rockchip/clk-rk3368.c linux-libre-4.4.7-gnu/drivers/clk/rockchip/clk-rk3368.c
+--- linux-libre-4.4-gnu/drivers/clk/rockchip/clk-rk3368.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/clk/rockchip/clk-rk3368.c 2016-04-12 12:09:26.000000000 -0400
+@@ -165,7 +165,7 @@ static const struct rockchip_cpuclk_reg_
+ .core_reg = RK3368_CLKSEL_CON(0),
+ .div_core_shift = 0,
+ .div_core_mask = 0x1f,
+- .mux_core_shift = 15,
++ .mux_core_shift = 7,
+ };
+
+ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
+@@ -218,29 +218,29 @@ static const struct rockchip_cpuclk_reg_
+ }
+
+ static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = {
+- RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6),
+- RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5),
+- RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5),
+- RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4),
+- RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4),
+- RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3),
+- RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3),
+- RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2),
+- RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2),
+- RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2),
++ RK3368_CPUCLKB_RATE(1512000000, 1, 5, 5),
++ RK3368_CPUCLKB_RATE(1488000000, 1, 4, 4),
++ RK3368_CPUCLKB_RATE(1416000000, 1, 4, 4),
++ RK3368_CPUCLKB_RATE(1200000000, 1, 3, 3),
++ RK3368_CPUCLKB_RATE(1008000000, 1, 3, 3),
++ RK3368_CPUCLKB_RATE( 816000000, 1, 2, 2),
++ RK3368_CPUCLKB_RATE( 696000000, 1, 2, 2),
++ RK3368_CPUCLKB_RATE( 600000000, 1, 1, 1),
++ RK3368_CPUCLKB_RATE( 408000000, 1, 1, 1),
++ RK3368_CPUCLKB_RATE( 312000000, 1, 1, 1),
+ };
+
+ static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = {
+- RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7),
+- RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6),
+- RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6),
+- RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5),
+- RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5),
+- RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4),
+- RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3),
+- RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3),
+- RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2),
+- RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2),
++ RK3368_CPUCLKL_RATE(1512000000, 1, 6, 6),
++ RK3368_CPUCLKL_RATE(1488000000, 1, 5, 5),
++ RK3368_CPUCLKL_RATE(1416000000, 1, 5, 5),
++ RK3368_CPUCLKL_RATE(1200000000, 1, 4, 4),
++ RK3368_CPUCLKL_RATE(1008000000, 1, 4, 4),
++ RK3368_CPUCLKL_RATE( 816000000, 1, 3, 3),
++ RK3368_CPUCLKL_RATE( 696000000, 1, 2, 2),
++ RK3368_CPUCLKL_RATE( 600000000, 1, 2, 2),
++ RK3368_CPUCLKL_RATE( 408000000, 1, 1, 1),
++ RK3368_CPUCLKL_RATE( 312000000, 1, 1, 1),
+ };
+
+ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
+@@ -384,10 +384,10 @@ static struct rockchip_clk_branch rk3368
+ * Clock-Architecture Diagram 3
+ */
+
+- COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0,
++ COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+ RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3368_CLKGATE_CON(4), 6, GFLAGS),
+- COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0,
++ COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+ RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3368_CLKGATE_CON(4), 7, GFLAGS),
+
+@@ -442,7 +442,7 @@ static struct rockchip_clk_branch rk3368
+ GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
+ RK3368_CLKGATE_CON(4), 13, GFLAGS),
+ GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
+- RK3368_CLKGATE_CON(5), 12, GFLAGS),
++ RK3368_CLKGATE_CON(4), 12, GFLAGS),
+
+ COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3368_CLKSEL_CON(21), 15, 1, MFLAGS,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/clk/samsung/clk-cpu.c linux-libre-4.4.7-gnu/drivers/clk/samsung/clk-cpu.c
+--- linux-libre-4.4-gnu/drivers/clk/samsung/clk-cpu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/clk/samsung/clk-cpu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -148,6 +148,7 @@ static int exynos_cpuclk_pre_rate_change
+ unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
+ unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
+ unsigned long div0, div1 = 0, mux_reg;
++ unsigned long flags;
+
+ /* find out the divider values to use for clock data */
+ while ((cfg_data->prate * 1000) != ndata->new_rate) {
+@@ -156,7 +157,7 @@ static int exynos_cpuclk_pre_rate_change
+ cfg_data++;
+ }
+
+- spin_lock(cpuclk->lock);
++ spin_lock_irqsave(cpuclk->lock, flags);
+
+ /*
+ * For the selected PLL clock frequency, get the pre-defined divider
+@@ -212,7 +213,7 @@ static int exynos_cpuclk_pre_rate_change
+ DIV_MASK_ALL);
+ }
+
+- spin_unlock(cpuclk->lock);
++ spin_unlock_irqrestore(cpuclk->lock, flags);
+ return 0;
+ }
+
+@@ -223,6 +224,7 @@ static int exynos_cpuclk_post_rate_chang
+ const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
+ unsigned long div = 0, div_mask = DIV_MASK;
+ unsigned long mux_reg;
++ unsigned long flags;
+
+ /* find out the divider values to use for clock data */
+ if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) {
+@@ -233,7 +235,7 @@ static int exynos_cpuclk_post_rate_chang
+ }
+ }
+
+- spin_lock(cpuclk->lock);
++ spin_lock_irqsave(cpuclk->lock, flags);
+
+ /* select mout_apll as the alternate parent */
+ mux_reg = readl(base + E4210_SRC_CPU);
+@@ -246,7 +248,7 @@ static int exynos_cpuclk_post_rate_chang
+ }
+
+ exynos_set_safe_div(base, div, div_mask);
+- spin_unlock(cpuclk->lock);
++ spin_unlock_irqrestore(cpuclk->lock, flags);
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/clocksource/tcb_clksrc.c linux-libre-4.4.7-gnu/drivers/clocksource/tcb_clksrc.c
+--- linux-libre-4.4-gnu/drivers/clocksource/tcb_clksrc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/clocksource/tcb_clksrc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -98,7 +98,8 @@ static int tc_shutdown(struct clock_even
+
+ __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
+ __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
+- clk_disable(tcd->clk);
++ if (!clockevent_state_detached(d))
++ clk_disable(tcd->clk);
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/clocksource/vt8500_timer.c linux-libre-4.4.7-gnu/drivers/clocksource/vt8500_timer.c
+--- linux-libre-4.4-gnu/drivers/clocksource/vt8500_timer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/clocksource/vt8500_timer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -50,6 +50,8 @@
+
+ #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
++#define MIN_OSCR_DELTA 16
++
+ static void __iomem *regbase;
+
+ static cycle_t vt8500_timer_read(struct clocksource *cs)
+@@ -80,7 +82,7 @@ static int vt8500_timer_set_next_event(u
+ cpu_relax();
+ writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL);
+
+- if ((signed)(alarm - clocksource.read(&clocksource)) <= 16)
++ if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA)
+ return -ETIME;
+
+ writel(1, regbase + TIMER_IER_VAL);
+@@ -151,7 +153,7 @@ static void __init vt8500_timer_init(str
+ pr_err("%s: setup_irq failed for %s\n", __func__,
+ clockevent.name);
+ clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ,
+- 4, 0xf0000000);
++ MIN_OSCR_DELTA * 2, 0xf0000000);
+ }
+
+ CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/cpufreq/cpufreq_governor.c linux-libre-4.4.7-gnu/drivers/cpufreq/cpufreq_governor.c
+--- linux-libre-4.4-gnu/drivers/cpufreq/cpufreq_governor.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/cpufreq/cpufreq_governor.c 2016-04-12 12:09:26.000000000 -0400
+@@ -356,16 +356,18 @@ static int cpufreq_governor_init(struct
+ if (!have_governor_per_policy())
+ cdata->gdbs_data = dbs_data;
+
++ policy->governor_data = dbs_data;
++
+ ret = sysfs_create_group(get_governor_parent_kobj(policy),
+ get_sysfs_attr(dbs_data));
+ if (ret)
+ goto reset_gdbs_data;
+
+- policy->governor_data = dbs_data;
+-
+ return 0;
+
+ reset_gdbs_data:
++ policy->governor_data = NULL;
++
+ if (!have_governor_per_policy())
+ cdata->gdbs_data = NULL;
+ cdata->exit(dbs_data, !policy->governor->initialized);
+@@ -386,16 +388,19 @@ static int cpufreq_governor_exit(struct
+ if (!cdbs->shared || cdbs->shared->policy)
+ return -EBUSY;
+
+- policy->governor_data = NULL;
+ if (!--dbs_data->usage_count) {
+ sysfs_remove_group(get_governor_parent_kobj(policy),
+ get_sysfs_attr(dbs_data));
+
++ policy->governor_data = NULL;
++
+ if (!have_governor_per_policy())
+ cdata->gdbs_data = NULL;
+
+ cdata->exit(dbs_data, policy->governor->initialized == 1);
+ kfree(dbs_data);
++ } else {
++ policy->governor_data = NULL;
+ }
+
+ free_common_dbs_info(policy, cdata);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/cpufreq/pxa2xx-cpufreq.c linux-libre-4.4.7-gnu/drivers/cpufreq/pxa2xx-cpufreq.c
+--- linux-libre-4.4-gnu/drivers/cpufreq/pxa2xx-cpufreq.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/cpufreq/pxa2xx-cpufreq.c 2016-04-12 12:09:26.000000000 -0400
+@@ -202,7 +202,7 @@ static void __init pxa_cpufreq_init_volt
+ }
+ }
+ #else
+-static int pxa_cpufreq_change_voltage(struct pxa_freqs *pxa_freq)
++static int pxa_cpufreq_change_voltage(const struct pxa_freqs *pxa_freq)
+ {
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/atmel-aes.c linux-libre-4.4.7-gnu/drivers/crypto/atmel-aes.c
+--- linux-libre-4.4-gnu/drivers/crypto/atmel-aes.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/atmel-aes.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1396,9 +1396,9 @@ static int atmel_aes_probe(struct platfo
+ }
+
+ aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res);
+- if (!aes_dd->io_base) {
++ if (IS_ERR(aes_dd->io_base)) {
+ dev_err(dev, "can't ioremap\n");
+- err = -ENOMEM;
++ err = PTR_ERR(aes_dd->io_base);
+ goto res_err;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/atmel-sha.c linux-libre-4.4.7-gnu/drivers/crypto/atmel-sha.c
+--- linux-libre-4.4-gnu/drivers/crypto/atmel-sha.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/atmel-sha.c 2016-04-12 12:09:26.000000000 -0400
+@@ -783,7 +783,7 @@ static void atmel_sha_finish_req(struct
+ dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
+ SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
+
+- clk_disable_unprepare(dd->iclk);
++ clk_disable(dd->iclk);
+
+ if (req->base.complete)
+ req->base.complete(&req->base, err);
+@@ -796,7 +796,7 @@ static int atmel_sha_hw_init(struct atme
+ {
+ int err;
+
+- err = clk_prepare_enable(dd->iclk);
++ err = clk_enable(dd->iclk);
+ if (err)
+ return err;
+
+@@ -823,7 +823,7 @@ static void atmel_sha_hw_version_init(st
+ dev_info(dd->dev,
+ "version: 0x%x\n", dd->hw_version);
+
+- clk_disable_unprepare(dd->iclk);
++ clk_disable(dd->iclk);
+ }
+
+ static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
+@@ -1405,12 +1405,16 @@ static int atmel_sha_probe(struct platfo
+ }
+
+ sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res);
+- if (!sha_dd->io_base) {
++ if (IS_ERR(sha_dd->io_base)) {
+ dev_err(dev, "can't ioremap\n");
+- err = -ENOMEM;
++ err = PTR_ERR(sha_dd->io_base);
+ goto res_err;
+ }
+
++ err = clk_prepare(sha_dd->iclk);
++ if (err)
++ goto res_err;
++
+ atmel_sha_hw_version_init(sha_dd);
+
+ atmel_sha_get_cap(sha_dd);
+@@ -1422,12 +1426,12 @@ static int atmel_sha_probe(struct platfo
+ if (IS_ERR(pdata)) {
+ dev_err(&pdev->dev, "platform data not available\n");
+ err = PTR_ERR(pdata);
+- goto res_err;
++ goto iclk_unprepare;
+ }
+ }
+ if (!pdata->dma_slave) {
+ err = -ENXIO;
+- goto res_err;
++ goto iclk_unprepare;
+ }
+ err = atmel_sha_dma_init(sha_dd, pdata);
+ if (err)
+@@ -1458,6 +1462,8 @@ err_algs:
+ if (sha_dd->caps.has_dma)
+ atmel_sha_dma_cleanup(sha_dd);
+ err_sha_dma:
++iclk_unprepare:
++ clk_unprepare(sha_dd->iclk);
+ res_err:
+ tasklet_kill(&sha_dd->done_task);
+ sha_dd_err:
+@@ -1484,12 +1490,7 @@ static int atmel_sha_remove(struct platf
+ if (sha_dd->caps.has_dma)
+ atmel_sha_dma_cleanup(sha_dd);
+
+- iounmap(sha_dd->io_base);
+-
+- clk_put(sha_dd->iclk);
+-
+- if (sha_dd->irq >= 0)
+- free_irq(sha_dd->irq, sha_dd);
++ clk_unprepare(sha_dd->iclk);
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/atmel-tdes.c linux-libre-4.4.7-gnu/drivers/crypto/atmel-tdes.c
+--- linux-libre-4.4-gnu/drivers/crypto/atmel-tdes.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/atmel-tdes.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1417,9 +1417,9 @@ static int atmel_tdes_probe(struct platf
+ }
+
+ tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res);
+- if (!tdes_dd->io_base) {
++ if (IS_ERR(tdes_dd->io_base)) {
+ dev_err(dev, "can't ioremap\n");
+- err = -ENOMEM;
++ err = PTR_ERR(tdes_dd->io_base);
+ goto res_err;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/caam/ctrl.c linux-libre-4.4.7-gnu/drivers/crypto/caam/ctrl.c
+--- linux-libre-4.4-gnu/drivers/crypto/caam/ctrl.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/caam/ctrl.c 2016-04-12 12:09:26.000000000 -0400
+@@ -534,8 +534,8 @@ static int caam_probe(struct platform_de
+ * long pointers in master configuration register
+ */
+ clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, MCFGR_AWCACHE_CACH |
+- MCFGR_WDENABLE | (sizeof(dma_addr_t) == sizeof(u64) ?
+- MCFGR_LONG_PTR : 0));
++ MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE |
++ (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
+
+ /*
+ * Read the Compile Time paramters and SCFGR to determine
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/ccp/ccp-crypto-aes-cmac.c linux-libre-4.4.7-gnu/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
+--- linux-libre-4.4-gnu/drivers/crypto/ccp/ccp-crypto-aes-cmac.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/ccp/ccp-crypto-aes-cmac.c 2016-04-12 12:09:26.000000000 -0400
+@@ -220,6 +220,39 @@ static int ccp_aes_cmac_digest(struct ah
+ return ccp_aes_cmac_finup(req);
+ }
+
++static int ccp_aes_cmac_export(struct ahash_request *req, void *out)
++{
++ struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
++ struct ccp_aes_cmac_exp_ctx state;
++
++ state.null_msg = rctx->null_msg;
++ memcpy(state.iv, rctx->iv, sizeof(state.iv));
++ state.buf_count = rctx->buf_count;
++ memcpy(state.buf, rctx->buf, sizeof(state.buf));
++
++ /* 'out' may not be aligned so memcpy from local variable */
++ memcpy(out, &state, sizeof(state));
++
++ return 0;
++}
++
++static int ccp_aes_cmac_import(struct ahash_request *req, const void *in)
++{
++ struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
++ struct ccp_aes_cmac_exp_ctx state;
++
++ /* 'in' may not be aligned so memcpy to local variable */
++ memcpy(&state, in, sizeof(state));
++
++ memset(rctx, 0, sizeof(*rctx));
++ rctx->null_msg = state.null_msg;
++ memcpy(rctx->iv, state.iv, sizeof(rctx->iv));
++ rctx->buf_count = state.buf_count;
++ memcpy(rctx->buf, state.buf, sizeof(rctx->buf));
++
++ return 0;
++}
++
+ static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int key_len)
+ {
+@@ -352,10 +385,13 @@ int ccp_register_aes_cmac_algs(struct li
+ alg->final = ccp_aes_cmac_final;
+ alg->finup = ccp_aes_cmac_finup;
+ alg->digest = ccp_aes_cmac_digest;
++ alg->export = ccp_aes_cmac_export;
++ alg->import = ccp_aes_cmac_import;
+ alg->setkey = ccp_aes_cmac_setkey;
+
+ halg = &alg->halg;
+ halg->digestsize = AES_BLOCK_SIZE;
++ halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx);
+
+ base = &halg->base;
+ snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)");
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/ccp/ccp-crypto.h linux-libre-4.4.7-gnu/drivers/crypto/ccp/ccp-crypto.h
+--- linux-libre-4.4-gnu/drivers/crypto/ccp/ccp-crypto.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/ccp/ccp-crypto.h 2016-04-12 12:09:26.000000000 -0400
+@@ -129,6 +129,15 @@ struct ccp_aes_cmac_req_ctx {
+ struct ccp_cmd cmd;
+ };
+
++struct ccp_aes_cmac_exp_ctx {
++ unsigned int null_msg;
++
++ u8 iv[AES_BLOCK_SIZE];
++
++ unsigned int buf_count;
++ u8 buf[AES_BLOCK_SIZE];
++};
++
+ /***** SHA related defines *****/
+ #define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE
+ #define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE
+@@ -171,6 +180,19 @@ struct ccp_sha_req_ctx {
+ struct ccp_cmd cmd;
+ };
+
++struct ccp_sha_exp_ctx {
++ enum ccp_sha_type type;
++
++ u64 msg_bits;
++
++ unsigned int first;
++
++ u8 ctx[MAX_SHA_CONTEXT_SIZE];
++
++ unsigned int buf_count;
++ u8 buf[MAX_SHA_BLOCK_SIZE];
++};
++
+ /***** Common Context Structure *****/
+ struct ccp_ctx {
+ int (*complete)(struct crypto_async_request *req, int ret);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/ccp/ccp-crypto-sha.c linux-libre-4.4.7-gnu/drivers/crypto/ccp/ccp-crypto-sha.c
+--- linux-libre-4.4-gnu/drivers/crypto/ccp/ccp-crypto-sha.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/ccp/ccp-crypto-sha.c 2016-04-12 12:09:26.000000000 -0400
+@@ -207,6 +207,43 @@ static int ccp_sha_digest(struct ahash_r
+ return ccp_sha_finup(req);
+ }
+
++static int ccp_sha_export(struct ahash_request *req, void *out)
++{
++ struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
++ struct ccp_sha_exp_ctx state;
++
++ state.type = rctx->type;
++ state.msg_bits = rctx->msg_bits;
++ state.first = rctx->first;
++ memcpy(state.ctx, rctx->ctx, sizeof(state.ctx));
++ state.buf_count = rctx->buf_count;
++ memcpy(state.buf, rctx->buf, sizeof(state.buf));
++
++ /* 'out' may not be aligned so memcpy from local variable */
++ memcpy(out, &state, sizeof(state));
++
++ return 0;
++}
++
++static int ccp_sha_import(struct ahash_request *req, const void *in)
++{
++ struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
++ struct ccp_sha_exp_ctx state;
++
++ /* 'in' may not be aligned so memcpy to local variable */
++ memcpy(&state, in, sizeof(state));
++
++ memset(rctx, 0, sizeof(*rctx));
++ rctx->type = state.type;
++ rctx->msg_bits = state.msg_bits;
++ rctx->first = state.first;
++ memcpy(rctx->ctx, state.ctx, sizeof(rctx->ctx));
++ rctx->buf_count = state.buf_count;
++ memcpy(rctx->buf, state.buf, sizeof(rctx->buf));
++
++ return 0;
++}
++
+ static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int key_len)
+ {
+@@ -403,9 +440,12 @@ static int ccp_register_sha_alg(struct l
+ alg->final = ccp_sha_final;
+ alg->finup = ccp_sha_finup;
+ alg->digest = ccp_sha_digest;
++ alg->export = ccp_sha_export;
++ alg->import = ccp_sha_import;
+
+ halg = &alg->halg;
+ halg->digestsize = def->digest_size;
++ halg->statesize = sizeof(struct ccp_sha_exp_ctx);
+
+ base = &halg->base;
+ snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/marvell/cesa.c linux-libre-4.4.7-gnu/drivers/crypto/marvell/cesa.c
+--- linux-libre-4.4-gnu/drivers/crypto/marvell/cesa.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/marvell/cesa.c 2016-04-12 12:09:26.000000000 -0400
+@@ -306,7 +306,7 @@ static int mv_cesa_dev_dma_init(struct m
+ return -ENOMEM;
+
+ dma->padding_pool = dmam_pool_create("cesa_padding", dev, 72, 1, 0);
+- if (!dma->cache_pool)
++ if (!dma->padding_pool)
+ return -ENOMEM;
+
+ cesa->dma = dma;
+@@ -420,7 +420,7 @@ static int mv_cesa_probe(struct platform
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+ cesa->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(cesa->regs))
+- return -ENOMEM;
++ return PTR_ERR(cesa->regs);
+
+ ret = mv_cesa_dev_dma_init(cesa);
+ if (ret)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/sunxi-ss/sun4i-ss-core.c linux-libre-4.4.7-gnu/drivers/crypto/sunxi-ss/sun4i-ss-core.c
+--- linux-libre-4.4-gnu/drivers/crypto/sunxi-ss/sun4i-ss-core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/sunxi-ss/sun4i-ss-core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -39,6 +39,7 @@ static struct sun4i_ss_alg_template ss_a
+ .import = sun4i_hash_import_md5,
+ .halg = {
+ .digestsize = MD5_DIGEST_SIZE,
++ .statesize = sizeof(struct md5_state),
+ .base = {
+ .cra_name = "md5",
+ .cra_driver_name = "md5-sun4i-ss",
+@@ -66,6 +67,7 @@ static struct sun4i_ss_alg_template ss_a
+ .import = sun4i_hash_import_sha1,
+ .halg = {
+ .digestsize = SHA1_DIGEST_SIZE,
++ .statesize = sizeof(struct sha1_state),
+ .base = {
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1-sun4i-ss",
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/ux500/cryp/cryp_core.c linux-libre-4.4.7-gnu/drivers/crypto/ux500/cryp/cryp_core.c
+--- linux-libre-4.4-gnu/drivers/crypto/ux500/cryp/cryp_core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/ux500/cryp/cryp_core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1440,9 +1440,9 @@ static int ux500_cryp_probe(struct platf
+
+ device_data->phybase = res->start;
+ device_data->base = devm_ioremap_resource(dev, res);
+- if (!device_data->base) {
++ if (IS_ERR(device_data->base)) {
+ dev_err(dev, "[%s]: ioremap failed!", __func__);
+- ret = -ENOMEM;
++ ret = PTR_ERR(device_data->base);
+ goto out;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/crypto/ux500/hash/hash_core.c linux-libre-4.4.7-gnu/drivers/crypto/ux500/hash/hash_core.c
+--- linux-libre-4.4-gnu/drivers/crypto/ux500/hash/hash_core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/crypto/ux500/hash/hash_core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1675,9 +1675,9 @@ static int ux500_hash_probe(struct platf
+
+ device_data->phybase = res->start;
+ device_data->base = devm_ioremap_resource(dev, res);
+- if (!device_data->base) {
++ if (IS_ERR(device_data->base)) {
+ dev_err(dev, "%s: ioremap() failed!\n", __func__);
+- ret = -ENOMEM;
++ ret = PTR_ERR(device_data->base);
+ goto out;
+ }
+ spin_lock_init(&device_data->ctx_lock);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/dma/at_xdmac.c linux-libre-4.4.7-gnu/drivers/dma/at_xdmac.c
+--- linux-libre-4.4-gnu/drivers/dma/at_xdmac.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/dma/at_xdmac.c 2016-04-12 12:09:26.000000000 -0400
+@@ -176,6 +176,7 @@
+ #define AT_XDMAC_MAX_CHAN 0x20
+ #define AT_XDMAC_MAX_CSIZE 16 /* 16 data */
+ #define AT_XDMAC_MAX_DWIDTH 8 /* 64 bits */
++#define AT_XDMAC_RESIDUE_MAX_RETRIES 5
+
+ #define AT_XDMAC_DMA_BUSWIDTHS\
+ (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\
+@@ -1383,8 +1384,8 @@ at_xdmac_tx_status(struct dma_chan *chan
+ struct at_xdmac_desc *desc, *_desc;
+ struct list_head *descs_list;
+ enum dma_status ret;
+- int residue;
+- u32 cur_nda, mask, value;
++ int residue, retry;
++ u32 cur_nda, check_nda, cur_ubc, mask, value;
+ u8 dwidth = 0;
+ unsigned long flags;
+
+@@ -1421,7 +1422,42 @@ at_xdmac_tx_status(struct dma_chan *chan
+ cpu_relax();
+ }
+
++ /*
++ * When processing the residue, we need to read two registers but we
++ * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
++ * we stand in the descriptor list and AT_XDMAC_CUBC is used
++ * to know how many data are remaining for the current descriptor.
++ * Since the dma channel is not paused to not loose data, between the
++ * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
++ * descriptor.
++ * For that reason, after reading AT_XDMAC_CUBC, we check if we are
++ * still using the same descriptor by reading a second time
++ * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
++ * read again AT_XDMAC_CUBC.
++ * Memory barriers are used to ensure the read order of the registers.
++ * A max number of retries is set because unlikely it can never ends if
++ * we are transferring a lot of data with small buffers.
++ */
+ cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
++ rmb();
++ cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
++ for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
++ rmb();
++ check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
++
++ if (likely(cur_nda == check_nda))
++ break;
++
++ cur_nda = check_nda;
++ rmb();
++ cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
++ }
++
++ if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
++ ret = DMA_ERROR;
++ goto spin_unlock;
++ }
++
+ /*
+ * Remove size of all microblocks already transferred and the current
+ * one. Then add the remaining size to transfer of the current
+@@ -1434,7 +1470,7 @@ at_xdmac_tx_status(struct dma_chan *chan
+ if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda)
+ break;
+ }
+- residue += at_xdmac_chan_read(atchan, AT_XDMAC_CUBC) << dwidth;
++ residue += cur_ubc << dwidth;
+
+ dma_set_residue(txstate, residue);
+
+@@ -1688,6 +1724,7 @@ static int at_xdmac_device_terminate_all
+ list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node)
+ at_xdmac_remove_xfer(atchan, desc);
+
++ clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status);
+ clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status);
+ spin_unlock_irqrestore(&atchan->lock, flags);
+
+@@ -1820,6 +1857,8 @@ static int atmel_xdmac_resume(struct dev
+ atchan = to_at_xdmac_chan(chan);
+ at_xdmac_chan_write(atchan, AT_XDMAC_CC, atchan->save_cc);
+ if (at_xdmac_chan_is_cyclic(atchan)) {
++ if (at_xdmac_chan_is_paused(atchan))
++ at_xdmac_device_resume(chan);
+ at_xdmac_chan_write(atchan, AT_XDMAC_CNDA, atchan->save_cnda);
+ at_xdmac_chan_write(atchan, AT_XDMAC_CNDC, atchan->save_cndc);
+ at_xdmac_chan_write(atchan, AT_XDMAC_CIE, atchan->save_cim);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/dma/dw/core.c linux-libre-4.4.7-gnu/drivers/dma/dw/core.c
+--- linux-libre-4.4-gnu/drivers/dma/dw/core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/dma/dw/core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -536,16 +536,17 @@ EXPORT_SYMBOL(dw_dma_get_dst_addr);
+
+ /* Called with dwc->lock held and all DMAC interrupts disabled */
+ static void dwc_handle_cyclic(struct dw_dma *dw, struct dw_dma_chan *dwc,
+- u32 status_err, u32 status_xfer)
++ u32 status_block, u32 status_err, u32 status_xfer)
+ {
+ unsigned long flags;
+
+- if (dwc->mask) {
++ if (status_block & dwc->mask) {
+ void (*callback)(void *param);
+ void *callback_param;
+
+ dev_vdbg(chan2dev(&dwc->chan), "new cyclic period llp 0x%08x\n",
+ channel_readl(dwc, LLP));
++ dma_writel(dw, CLEAR.BLOCK, dwc->mask);
+
+ callback = dwc->cdesc->period_callback;
+ callback_param = dwc->cdesc->period_callback_param;
+@@ -577,6 +578,7 @@ static void dwc_handle_cyclic(struct dw_
+ channel_writel(dwc, CTL_LO, 0);
+ channel_writel(dwc, CTL_HI, 0);
+
++ dma_writel(dw, CLEAR.BLOCK, dwc->mask);
+ dma_writel(dw, CLEAR.ERROR, dwc->mask);
+ dma_writel(dw, CLEAR.XFER, dwc->mask);
+
+@@ -585,6 +587,9 @@ static void dwc_handle_cyclic(struct dw_
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+ }
++
++ /* Re-enable interrupts */
++ channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+ }
+
+ /* ------------------------------------------------------------------------- */
+@@ -593,10 +598,12 @@ static void dw_dma_tasklet(unsigned long
+ {
+ struct dw_dma *dw = (struct dw_dma *)data;
+ struct dw_dma_chan *dwc;
++ u32 status_block;
+ u32 status_xfer;
+ u32 status_err;
+ int i;
+
++ status_block = dma_readl(dw, RAW.BLOCK);
+ status_xfer = dma_readl(dw, RAW.XFER);
+ status_err = dma_readl(dw, RAW.ERROR);
+
+@@ -605,16 +612,15 @@ static void dw_dma_tasklet(unsigned long
+ for (i = 0; i < dw->dma.chancnt; i++) {
+ dwc = &dw->chan[i];
+ if (test_bit(DW_DMA_IS_CYCLIC, &dwc->flags))
+- dwc_handle_cyclic(dw, dwc, status_err, status_xfer);
++ dwc_handle_cyclic(dw, dwc, status_block, status_err,
++ status_xfer);
+ else if (status_err & (1 << i))
+ dwc_handle_error(dw, dwc);
+ else if (status_xfer & (1 << i))
+ dwc_scan_descriptors(dw, dwc);
+ }
+
+- /*
+- * Re-enable interrupts.
+- */
++ /* Re-enable interrupts */
+ channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
+ channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
+ }
+@@ -635,6 +641,7 @@ static irqreturn_t dw_dma_interrupt(int
+ * softirq handler.
+ */
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
++ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+ status = dma_readl(dw, STATUS_INT);
+@@ -645,6 +652,7 @@ static irqreturn_t dw_dma_interrupt(int
+
+ /* Try to recover */
+ channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1);
++ channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1);
+ channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1);
+@@ -1111,6 +1119,7 @@ static void dw_dma_off(struct dw_dma *dw
+ dma_writel(dw, CFG, 0);
+
+ channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
++ channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
+ channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+@@ -1216,6 +1225,7 @@ static void dwc_free_chan_resources(stru
+
+ /* Disable interrupts */
+ channel_clear_bit(dw, MASK.XFER, dwc->mask);
++ channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
+ channel_clear_bit(dw, MASK.ERROR, dwc->mask);
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+@@ -1245,7 +1255,7 @@ static void dwc_free_chan_resources(stru
+ int dw_dma_cyclic_start(struct dma_chan *chan)
+ {
+ struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+- struct dw_dma *dw = to_dw_dma(dwc->chan.device);
++ struct dw_dma *dw = to_dw_dma(chan->device);
+ unsigned long flags;
+
+ if (!test_bit(DW_DMA_IS_CYCLIC, &dwc->flags)) {
+@@ -1255,25 +1265,10 @@ int dw_dma_cyclic_start(struct dma_chan
+
+ spin_lock_irqsave(&dwc->lock, flags);
+
+- /* Assert channel is idle */
+- if (dma_readl(dw, CH_EN) & dwc->mask) {
+- dev_err(chan2dev(&dwc->chan),
+- "%s: BUG: Attempted to start non-idle channel\n",
+- __func__);
+- dwc_dump_chan_regs(dwc);
+- spin_unlock_irqrestore(&dwc->lock, flags);
+- return -EBUSY;
+- }
+-
+- dma_writel(dw, CLEAR.ERROR, dwc->mask);
+- dma_writel(dw, CLEAR.XFER, dwc->mask);
+-
+- /* Setup DMAC channel registers */
+- channel_writel(dwc, LLP, dwc->cdesc->desc[0]->txd.phys);
+- channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
+- channel_writel(dwc, CTL_HI, 0);
++ /* Enable interrupts to perform cyclic transfer */
++ channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+
+- channel_set_bit(dw, CH_EN, dwc->mask);
++ dwc_dostart(dwc, dwc->cdesc->desc[0]);
+
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+@@ -1479,6 +1474,7 @@ void dw_dma_cyclic_free(struct dma_chan
+
+ dwc_chan_disable(dw, dwc);
+
++ dma_writel(dw, CLEAR.BLOCK, dwc->mask);
+ dma_writel(dw, CLEAR.ERROR, dwc->mask);
+ dma_writel(dw, CLEAR.XFER, dwc->mask);
+
+@@ -1567,9 +1563,6 @@ int dw_dma_probe(struct dw_dma_chip *chi
+ /* Force dma off, just in case */
+ dw_dma_off(dw);
+
+- /* Disable BLOCK interrupts as well */
+- channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+-
+ /* Create a pool of consistent memory blocks for hardware descriptors */
+ dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", chip->dev,
+ sizeof(struct dw_desc), 4, 0);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/dma/pxa_dma.c linux-libre-4.4.7-gnu/drivers/dma/pxa_dma.c
+--- linux-libre-4.4-gnu/drivers/dma/pxa_dma.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/dma/pxa_dma.c 2016-04-12 12:09:26.000000000 -0400
+@@ -583,6 +583,8 @@ static void set_updater_desc(struct pxad
+ (PXA_DCMD_LENGTH & sizeof(u32));
+ if (flags & DMA_PREP_INTERRUPT)
+ updater->dcmd |= PXA_DCMD_ENDIRQEN;
++ if (sw_desc->cyclic)
++ sw_desc->hw_desc[sw_desc->nb_desc - 2]->ddadr = sw_desc->first;
+ }
+
+ static bool is_desc_completed(struct virt_dma_desc *vd)
+@@ -673,6 +675,10 @@ static irqreturn_t pxad_chan_handler(int
+ dev_dbg(&chan->vc.chan.dev->device,
+ "%s(): checking txd %p[%x]: completed=%d\n",
+ __func__, vd, vd->tx.cookie, is_desc_completed(vd));
++ if (to_pxad_sw_desc(vd)->cyclic) {
++ vchan_cyclic_callback(vd);
++ break;
++ }
+ if (is_desc_completed(vd)) {
+ list_del(&vd->node);
+ vchan_cookie_complete(vd);
+@@ -1080,7 +1086,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dc
+ return NULL;
+
+ pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr);
+- dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH | period_len);
++ dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH & period_len);
+ dev_dbg(&chan->vc.chan.dev->device,
+ "%s(): buf_addr=0x%lx len=%zu period=%zu dir=%d flags=%lx\n",
+ __func__, (unsigned long)buf_addr, len, period_len, dir, flags);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/edac/amd64_edac.c linux-libre-4.4.7-gnu/drivers/edac/amd64_edac.c
+--- linux-libre-4.4-gnu/drivers/edac/amd64_edac.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/edac/amd64_edac.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct
+ u64 chan_off;
+ u64 dram_base = get_dram_base(pvt, range);
+ u64 hole_off = f10_dhar_offset(pvt);
+- u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16;
++ u64 dct_sel_base_off = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16;
+
+ if (hi_rng) {
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/edac/edac_device.c linux-libre-4.4.7-gnu/drivers/edac/edac_device.c
+--- linux-libre-4.4-gnu/drivers/edac/edac_device.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/edac/edac_device.c 2016-04-12 12:09:26.000000000 -0400
+@@ -435,16 +435,13 @@ void edac_device_workq_setup(struct edac
+ */
+ void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
+ {
+- int status;
+-
+ if (!edac_dev->edac_check)
+ return;
+
+- status = cancel_delayed_work(&edac_dev->work);
+- if (status == 0) {
+- /* workq instance might be running, wait for it */
+- flush_workqueue(edac_workqueue);
+- }
++ edac_dev->op_state = OP_OFFLINE;
++
++ cancel_delayed_work_sync(&edac_dev->work);
++ flush_workqueue(edac_workqueue);
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/edac/edac_mc.c linux-libre-4.4.7-gnu/drivers/edac/edac_mc.c
+--- linux-libre-4.4-gnu/drivers/edac/edac_mc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/edac/edac_mc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -586,18 +586,10 @@ static void edac_mc_workq_setup(struct m
+ */
+ static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
+ {
+- int status;
+-
+- if (mci->op_state != OP_RUNNING_POLL)
+- return;
+-
+- status = cancel_delayed_work(&mci->work);
+- if (status == 0) {
+- edac_dbg(0, "not canceled, flush the queue\n");
++ mci->op_state = OP_OFFLINE;
+
+- /* workq instance might be running, wait for it */
+- flush_workqueue(edac_workqueue);
+- }
++ cancel_delayed_work_sync(&mci->work);
++ flush_workqueue(edac_workqueue);
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/edac/edac_mc_sysfs.c linux-libre-4.4.7-gnu/drivers/edac/edac_mc_sysfs.c
+--- linux-libre-4.4-gnu/drivers/edac/edac_mc_sysfs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/edac/edac_mc_sysfs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -880,21 +880,26 @@ static struct device_type mci_attr_type
+ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
+ const struct attribute_group **groups)
+ {
++ char *name;
+ int i, err;
+
+ /*
+ * The memory controller needs its own bus, in order to avoid
+ * namespace conflicts at /sys/bus/edac.
+ */
+- mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
+- if (!mci->bus->name)
++ name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
++ if (!name)
+ return -ENOMEM;
+
++ mci->bus->name = name;
++
+ edac_dbg(0, "creating bus %s\n", mci->bus->name);
+
+ err = bus_register(mci->bus);
+- if (err < 0)
+- goto fail_free_name;
++ if (err < 0) {
++ kfree(name);
++ return err;
++ }
+
+ /* get the /sys/devices/system/edac subsys reference */
+ mci->dev.type = &mci_attr_type;
+@@ -961,8 +966,8 @@ fail_unregister_dimm:
+ device_unregister(&mci->dev);
+ fail_unregister_bus:
+ bus_unregister(mci->bus);
+-fail_free_name:
+- kfree(mci->bus->name);
++ kfree(name);
++
+ return err;
+ }
+
+@@ -993,10 +998,12 @@ void edac_remove_sysfs_mci_device(struct
+
+ void edac_unregister_sysfs(struct mem_ctl_info *mci)
+ {
++ const char *name = mci->bus->name;
++
+ edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
+ device_unregister(&mci->dev);
+ bus_unregister(mci->bus);
+- kfree(mci->bus->name);
++ kfree(name);
+ }
+
+ static void mc_attr_release(struct device *dev)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/edac/edac_pci.c linux-libre-4.4.7-gnu/drivers/edac/edac_pci.c
+--- linux-libre-4.4-gnu/drivers/edac/edac_pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/edac/edac_pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -274,13 +274,12 @@ static void edac_pci_workq_setup(struct
+ */
+ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
+ {
+- int status;
+-
+ edac_dbg(0, "\n");
+
+- status = cancel_delayed_work(&pci->work);
+- if (status == 0)
+- flush_workqueue(edac_workqueue);
++ pci->op_state = OP_OFFLINE;
++
++ cancel_delayed_work_sync(&pci->work);
++ flush_workqueue(edac_workqueue);
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/edac/sb_edac.c linux-libre-4.4.7-gnu/drivers/edac/sb_edac.c
+--- linux-libre-4.4-gnu/drivers/edac/sb_edac.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/edac/sb_edac.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1117,8 +1117,8 @@ static void get_memory_layout(const stru
+ edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
+ n_tads, gb, (mb*1000)/1024,
+ ((u64)tmp_mb) << 20L,
+- (u32)TAD_SOCK(reg),
+- (u32)TAD_CH(reg),
++ (u32)(1 << TAD_SOCK(reg)),
++ (u32)TAD_CH(reg) + 1,
+ (u32)TAD_TGT0(reg),
+ (u32)TAD_TGT1(reg),
+ (u32)TAD_TGT2(reg),
+@@ -1396,7 +1396,7 @@ static int get_memory_error_data(struct
+ }
+
+ ch_way = TAD_CH(reg) + 1;
+- sck_way = TAD_SOCK(reg) + 1;
++ sck_way = 1 << TAD_SOCK(reg);
+
+ if (ch_way == 3)
+ idx = addr >> 6;
+@@ -1453,7 +1453,7 @@ static int get_memory_error_data(struct
+ n_tads,
+ addr,
+ limit,
+- (u32)TAD_SOCK(reg),
++ sck_way,
+ ch_way,
+ offset,
+ idx,
+@@ -1468,18 +1468,12 @@ static int get_memory_error_data(struct
+ offset, addr);
+ return -EINVAL;
+ }
+- addr -= offset;
+- /* Store the low bits [0:6] of the addr */
+- ch_addr = addr & 0x7f;
+- /* Remove socket wayness and remove 6 bits */
+- addr >>= 6;
+- addr = div_u64(addr, sck_xch);
+-#if 0
+- /* Divide by channel way */
+- addr = addr / ch_way;
+-#endif
+- /* Recover the last 6 bits */
+- ch_addr |= addr << 6;
++
++ ch_addr = addr - offset;
++ ch_addr >>= (6 + shiftup);
++ ch_addr /= ch_way * sck_way;
++ ch_addr <<= (6 + shiftup);
++ ch_addr |= addr & ((1 << (6 + shiftup)) - 1);
+
+ /*
+ * Step 3) Decode rank
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/firmware/efi/efivars.c linux-libre-4.4.7-gnu/drivers/firmware/efi/efivars.c
+--- linux-libre-4.4-gnu/drivers/firmware/efi/efivars.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/firmware/efi/efivars.c 2016-04-12 12:09:26.000000000 -0400
+@@ -221,7 +221,7 @@ sanity_check(struct efi_variable *var, e
+ }
+
+ if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
+- efivar_validate(name, data, size) == false) {
++ efivar_validate(vendor, name, data, size) == false) {
+ printk(KERN_ERR "efivars: Malformed variable content\n");
+ return -EINVAL;
+ }
+@@ -447,7 +447,8 @@ static ssize_t efivar_create(struct file
+ }
+
+ if ((attributes & ~EFI_VARIABLE_MASK) != 0 ||
+- efivar_validate(name, data, size) == false) {
++ efivar_validate(new_var->VendorGuid, name, data,
++ size) == false) {
+ printk(KERN_ERR "efivars: Malformed variable content\n");
+ return -EINVAL;
+ }
+@@ -540,38 +541,30 @@ static ssize_t efivar_delete(struct file
+ static int
+ efivar_create_sysfs_entry(struct efivar_entry *new_var)
+ {
+- int i, short_name_size;
++ int short_name_size;
+ char *short_name;
+- unsigned long variable_name_size;
+- efi_char16_t *variable_name;
++ unsigned long utf8_name_size;
++ efi_char16_t *variable_name = new_var->var.VariableName;
+ int ret;
+
+- variable_name = new_var->var.VariableName;
+- variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);
+-
+ /*
+- * Length of the variable bytes in ASCII, plus the '-' separator,
++ * Length of the variable bytes in UTF8, plus the '-' separator,
+ * plus the GUID, plus trailing NUL
+ */
+- short_name_size = variable_name_size / sizeof(efi_char16_t)
+- + 1 + EFI_VARIABLE_GUID_LEN + 1;
+-
+- short_name = kzalloc(short_name_size, GFP_KERNEL);
++ utf8_name_size = ucs2_utf8size(variable_name);
++ short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
+
++ short_name = kmalloc(short_name_size, GFP_KERNEL);
+ if (!short_name)
+ return -ENOMEM;
+
+- /* Convert Unicode to normal chars (assume top bits are 0),
+- ala UTF-8 */
+- for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
+- short_name[i] = variable_name[i] & 0xFF;
+- }
++ ucs2_as_utf8(short_name, variable_name, short_name_size);
++
+ /* This is ugly, but necessary to separate one vendor's
+ private variables from another's. */
+-
+- *(short_name + strlen(short_name)) = '-';
++ short_name[utf8_name_size] = '-';
+ efi_guid_to_str(&new_var->var.VendorGuid,
+- short_name + strlen(short_name));
++ short_name + utf8_name_size + 1);
+
+ new_var->kobj.kset = efivars_kset;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/firmware/efi/vars.c linux-libre-4.4.7-gnu/drivers/firmware/efi/vars.c
+--- linux-libre-4.4-gnu/drivers/firmware/efi/vars.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/firmware/efi/vars.c 2016-04-12 12:09:26.000000000 -0400
+@@ -165,67 +165,133 @@ validate_ascii_string(efi_char16_t *var_
+ }
+
+ struct variable_validate {
++ efi_guid_t vendor;
+ char *name;
+ bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
+ unsigned long len);
+ };
+
++/*
++ * This is the list of variables we need to validate, as well as the
++ * whitelist for what we think is safe not to default to immutable.
++ *
++ * If it has a validate() method that's not NULL, it'll go into the
++ * validation routine. If not, it is assumed valid, but still used for
++ * whitelisting.
++ *
++ * Note that it's sorted by {vendor,name}, but globbed names must come after
++ * any other name with the same prefix.
++ */
+ static const struct variable_validate variable_validate[] = {
+- { "BootNext", validate_uint16 },
+- { "BootOrder", validate_boot_order },
+- { "DriverOrder", validate_boot_order },
+- { "Boot*", validate_load_option },
+- { "Driver*", validate_load_option },
+- { "ConIn", validate_device_path },
+- { "ConInDev", validate_device_path },
+- { "ConOut", validate_device_path },
+- { "ConOutDev", validate_device_path },
+- { "ErrOut", validate_device_path },
+- { "ErrOutDev", validate_device_path },
+- { "Timeout", validate_uint16 },
+- { "Lang", validate_ascii_string },
+- { "PlatformLang", validate_ascii_string },
+- { "", NULL },
++ { EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
++ { EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
++ { EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
++ { EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
++ { EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
++ { EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
++ { EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
++ { EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
++ { EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
++ { EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
++ { EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
++ { EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
++ { EFI_GLOBAL_VARIABLE_GUID, "OsIndications", NULL },
++ { EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
++ { EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
++ { LINUX_EFI_CRASH_GUID, "*", NULL },
++ { NULL_GUID, "", NULL },
+ };
+
++static bool
++variable_matches(const char *var_name, size_t len, const char *match_name,
++ int *match)
++{
++ for (*match = 0; ; (*match)++) {
++ char c = match_name[*match];
++ char u = var_name[*match];
++
++ /* Wildcard in the matching name means we've matched */
++ if (c == '*')
++ return true;
++
++ /* Case sensitive match */
++ if (!c && *match == len)
++ return true;
++
++ if (c != u)
++ return false;
++
++ if (!c)
++ return true;
++ }
++ return true;
++}
++
+ bool
+-efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len)
++efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
++ unsigned long data_size)
+ {
+ int i;
+- u16 *unicode_name = var_name;
++ unsigned long utf8_size;
++ u8 *utf8_name;
+
+- for (i = 0; variable_validate[i].validate != NULL; i++) {
+- const char *name = variable_validate[i].name;
+- int match;
++ utf8_size = ucs2_utf8size(var_name);
++ utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL);
++ if (!utf8_name)
++ return false;
+
+- for (match = 0; ; match++) {
+- char c = name[match];
+- u16 u = unicode_name[match];
++ ucs2_as_utf8(utf8_name, var_name, utf8_size);
++ utf8_name[utf8_size] = '\0';
+
+- /* All special variables are plain ascii */
+- if (u > 127)
+- return true;
++ for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
++ const char *name = variable_validate[i].name;
++ int match = 0;
+
+- /* Wildcard in the matching name means we've matched */
+- if (c == '*')
+- return variable_validate[i].validate(var_name,
+- match, data, len);
++ if (efi_guidcmp(vendor, variable_validate[i].vendor))
++ continue;
+
+- /* Case sensitive match */
+- if (c != u)
++ if (variable_matches(utf8_name, utf8_size+1, name, &match)) {
++ if (variable_validate[i].validate == NULL)
+ break;
+-
+- /* Reached the end of the string while matching */
+- if (!c)
+- return variable_validate[i].validate(var_name,
+- match, data, len);
++ kfree(utf8_name);
++ return variable_validate[i].validate(var_name, match,
++ data, data_size);
+ }
+ }
+-
++ kfree(utf8_name);
+ return true;
+ }
+ EXPORT_SYMBOL_GPL(efivar_validate);
+
++bool
++efivar_variable_is_removable(efi_guid_t vendor, const char *var_name,
++ size_t len)
++{
++ int i;
++ bool found = false;
++ int match = 0;
++
++ /*
++ * Check if our variable is in the validated variables list
++ */
++ for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
++ if (efi_guidcmp(variable_validate[i].vendor, vendor))
++ continue;
++
++ if (variable_matches(var_name, len,
++ variable_validate[i].name, &match)) {
++ found = true;
++ break;
++ }
++ }
++
++ /*
++ * If it's in our list, it is removable.
++ */
++ return found;
++}
++EXPORT_SYMBOL_GPL(efivar_variable_is_removable);
++
+ static efi_status_t
+ check_var_size(u32 attributes, unsigned long size)
+ {
+@@ -852,7 +918,7 @@ int efivar_entry_set_get_size(struct efi
+
+ *set = false;
+
+- if (efivar_validate(name, data, *size) == false)
++ if (efivar_validate(*vendor, name, data, *size) == false)
+ return -EINVAL;
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c 2016-04-12 12:09:26.000000000 -0400
+@@ -63,6 +63,10 @@ bool amdgpu_has_atpx(void) {
+ return amdgpu_atpx_priv.atpx_detected;
+ }
+
++bool amdgpu_has_atpx_dgpu_power_cntl(void) {
++ return amdgpu_atpx_priv.atpx.functions.power_cntl;
++}
++
+ /**
+ * amdgpu_atpx_call - call an ATPX method
+ *
+@@ -142,10 +146,6 @@ static void amdgpu_atpx_parse_functions(
+ */
+ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
+ {
+- /* make sure required functions are enabled */
+- /* dGPU power control is required */
+- atpx->functions.power_cntl = true;
+-
+ if (atpx->functions.px_params) {
+ union acpi_object *info;
+ struct atpx_px_params output;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c 2016-04-12 12:09:26.000000000 -0400
+@@ -77,7 +77,7 @@ void amdgpu_connector_hotplug(struct drm
+ } else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) {
+ /* Don't try to start link training before we
+ * have the dpcd */
+- if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
++ if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
+ return;
+
+ /* set it to OFF so that drm_helper_connector_dpms()
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 2016-04-12 12:09:26.000000000 -0400
+@@ -61,6 +61,12 @@ static const char *amdgpu_asic_name[] =
+ "LAST",
+ };
+
++#if defined(CONFIG_VGA_SWITCHEROO)
++bool amdgpu_has_atpx_dgpu_power_cntl(void);
++#else
++static inline bool amdgpu_has_atpx_dgpu_power_cntl(void) { return false; }
++#endif
++
+ bool amdgpu_device_is_px(struct drm_device *dev)
+ {
+ struct amdgpu_device *adev = dev->dev_private;
+@@ -1469,7 +1475,7 @@ int amdgpu_device_init(struct amdgpu_dev
+
+ if (amdgpu_runtime_pm == 1)
+ runtime = true;
+- if (amdgpu_device_is_px(ddev))
++ if (amdgpu_device_is_px(ddev) && amdgpu_has_atpx_dgpu_power_cntl())
+ runtime = true;
+ vga_switcheroo_register_client(adev->pdev, &amdgpu_switcheroo_ops, runtime);
+ if (runtime)
+@@ -1744,15 +1750,20 @@ int amdgpu_resume_kms(struct drm_device
+ }
+
+ /* post card */
+- amdgpu_atom_asic_init(adev->mode_info.atom_context);
++ if (!amdgpu_card_posted(adev))
++ amdgpu_atom_asic_init(adev->mode_info.atom_context);
+
+ r = amdgpu_resume(adev);
++ if (r)
++ DRM_ERROR("amdgpu_resume failed (%d).\n", r);
+
+ amdgpu_fence_driver_resume(adev);
+
+- r = amdgpu_ib_ring_tests(adev);
+- if (r)
+- DRM_ERROR("ib ring test failed (%d).\n", r);
++ if (resume) {
++ r = amdgpu_ib_ring_tests(adev);
++ if (r)
++ DRM_ERROR("ib ring test failed (%d).\n", r);
++ }
+
+ r = amdgpu_late_init(adev);
+ if (r)
+@@ -1788,6 +1799,7 @@ int amdgpu_resume_kms(struct drm_device
+ }
+
+ drm_kms_helper_poll_enable(dev);
++ drm_helper_hpd_irq_event(dev);
+
+ if (fbcon) {
+ amdgpu_fbdev_set_suspend(adev, 0);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c 2016-04-12 12:09:26.000000000 -0400
+@@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(struct
+
+ struct drm_crtc *crtc = &amdgpuCrtc->base;
+ unsigned long flags;
+- unsigned i;
+- int vpos, hpos, stat, min_udelay;
++ unsigned i, repcnt = 4;
++ int vpos, hpos, stat, min_udelay = 0;
+ struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
+
+ amdgpu_flip_wait_fence(adev, &work->excl);
+@@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct
+ * In practice this won't execute very often unless on very fast
+ * machines because the time window for this to happen is very small.
+ */
+- for (;;) {
++ while (amdgpuCrtc->enabled && --repcnt) {
+ /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
+ * start in hpos, and to the "fudged earlier" vblank start in
+ * vpos.
+@@ -112,12 +112,24 @@ static void amdgpu_flip_work_func(struct
+ break;
+
+ /* Sleep at least until estimated real start of hw vblank */
+- spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
++ if (min_udelay > vblank->framedur_ns / 2000) {
++ /* Don't wait ridiculously long - something is wrong */
++ repcnt = 0;
++ break;
++ }
++ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ usleep_range(min_udelay, 2 * min_udelay);
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ };
+
++ if (!repcnt)
++ DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
++ "framedur %d, linedur %d, stat %d, vpos %d, "
++ "hpos %d\n", work->crtc_id, min_udelay,
++ vblank->framedur_ns / 1000,
++ vblank->linedur_ns / 1000, stat, vpos, hpos);
++
+ /* do the flip (mmio) */
+ adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
+ /* set the flip status */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -250,11 +250,11 @@ static struct pci_device_id pciidlist[]
+ {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|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},
++ {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},
+ /* 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 -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h 2016-04-12 12:09:26.000000000 -0400
+@@ -604,8 +604,6 @@ struct amdgpu_sa_manager {
+ uint32_t align;
+ };
+
+-struct amdgpu_sa_bo;
+-
+ /* sub-allocation buffer */
+ struct amdgpu_sa_bo {
+ struct list_head olist;
+@@ -2314,6 +2312,8 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct t
+ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr,
+ uint32_t flags);
+ bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm);
++bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
++ unsigned long end);
+ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm);
+ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
+ struct ttm_mem_reg *mem);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c 2016-04-12 12:09:26.000000000 -0400
+@@ -142,7 +142,8 @@ static void amdgpu_mn_invalidate_range_s
+
+ list_for_each_entry(bo, &node->bos, mn_list) {
+
+- if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound)
++ if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start,
++ end))
+ continue;
+
+ r = amdgpu_bo_reserve(bo, true);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c 2016-04-12 12:09:26.000000000 -0400
+@@ -33,6 +33,7 @@
+ #include <linux/slab.h>
+ #include <drm/drmP.h>
+ #include <drm/amdgpu_drm.h>
++#include <drm/drm_cache.h>
+ #include "amdgpu.h"
+ #include "amdgpu_trace.h"
+
+@@ -261,6 +262,13 @@ int amdgpu_bo_create_restricted(struct a
+ AMDGPU_GEM_DOMAIN_OA);
+
+ bo->flags = flags;
++
++ /* For architectures that don't support WC memory,
++ * mask out the WC flag from the BO
++ */
++ if (!drm_arch_can_wc_memory())
++ bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC;
++
+ amdgpu_fill_placement_to_bo(bo, placement);
+ /* Kernel allocation are uninterruptible */
+ r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
+@@ -399,7 +407,8 @@ int amdgpu_bo_pin_restricted(struct amdg
+ }
+ if (fpfn > bo->placements[i].fpfn)
+ bo->placements[i].fpfn = fpfn;
+- if (lpfn && lpfn < bo->placements[i].lpfn)
++ if (!bo->placements[i].lpfn ||
++ (lpfn && lpfn < bo->placements[i].lpfn))
+ bo->placements[i].lpfn = lpfn;
+ bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -595,11 +595,6 @@ force:
+
+ /* update display watermarks based on new power state */
+ amdgpu_display_bandwidth_update(adev);
+- /* update displays */
+- amdgpu_dpm_display_configuration_changed(adev);
+-
+- adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
+- adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
+
+ /* wait for the rings to drain */
+ for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
+@@ -616,6 +611,12 @@ force:
+
+ amdgpu_dpm_post_set_power_state(adev);
+
++ /* update displays */
++ amdgpu_dpm_display_configuration_changed(adev);
++
++ adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
++ adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
++
+ if (adev->pm.funcs->force_performance_level) {
+ if (adev->pm.dpm.thermal_active) {
+ enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c 2016-04-12 12:09:26.000000000 -0400
+@@ -354,12 +354,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma
+
+ for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i)
+ if (fences[i])
+- fences[count++] = fences[i];
++ fences[count++] = fence_get(fences[i]);
+
+ if (count) {
+ spin_unlock(&sa_manager->wq.lock);
+ t = fence_wait_any_timeout(fences, count, false,
+ MAX_SCHEDULE_TIMEOUT);
++ for (i = 0; i < count; ++i)
++ fence_put(fences[i]);
++
+ r = (t > 0) ? 0 : t;
+ spin_lock(&sa_manager->wq.lock);
+ } else {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c 2016-04-12 12:09:26.000000000 -0400
+@@ -293,7 +293,8 @@ int amdgpu_sync_rings(struct amdgpu_sync
+ fence = to_amdgpu_fence(sync->sync_to[i]);
+
+ /* check if we really need to sync */
+- if (!amdgpu_fence_need_sync(fence, ring))
++ if (!amdgpu_enable_scheduler &&
++ !amdgpu_fence_need_sync(fence, ring))
+ continue;
+
+ /* prevent GPU deadlocks */
+@@ -303,7 +304,7 @@ int amdgpu_sync_rings(struct amdgpu_sync
+ }
+
+ if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) {
+- r = fence_wait(&fence->base, true);
++ r = fence_wait(sync->sync_to[i], true);
+ if (r)
+ return r;
+ continue;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -712,7 +712,7 @@ static int amdgpu_ttm_tt_populate(struct
+ 0, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(adev->pdev, gtt->ttm.dma_address[i])) {
+- while (--i) {
++ while (i--) {
+ pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i],
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ gtt->ttm.dma_address[i] = 0;
+@@ -783,6 +783,25 @@ bool amdgpu_ttm_tt_has_userptr(struct tt
+ return !!gtt->userptr;
+ }
+
++bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start,
++ unsigned long end)
++{
++ struct amdgpu_ttm_tt *gtt = (void *)ttm;
++ unsigned long size;
++
++ if (gtt == NULL)
++ return false;
++
++ if (gtt->ttm.ttm.state != tt_bound || !gtt->userptr)
++ return false;
++
++ size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE;
++ if (gtt->userptr > end || gtt->userptr + size <= start)
++ return false;
++
++ return true;
++}
++
+ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm)
+ {
+ struct amdgpu_ttm_tt *gtt = (void *)ttm;
+@@ -808,7 +827,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct
+ flags |= AMDGPU_PTE_SNOOPED;
+ }
+
+- if (adev->asic_type >= CHIP_TOPAZ)
++ if (adev->asic_type >= CHIP_TONGA)
+ flags |= AMDGPU_PTE_EXECUTABLE;
+
+ flags |= AMDGPU_PTE_READABLE;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1010,13 +1010,13 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
+ return -EINVAL;
+
+ /* make sure object fit at this offset */
+- eaddr = saddr + size;
++ eaddr = saddr + size - 1;
+ if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo)))
+ return -EINVAL;
+
+ last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
+- if (last_pfn > adev->vm_manager.max_pfn) {
+- dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n",
++ if (last_pfn >= adev->vm_manager.max_pfn) {
++ dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n",
+ last_pfn, adev->vm_manager.max_pfn);
+ return -EINVAL;
+ }
+@@ -1025,7 +1025,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
+ eaddr /= AMDGPU_GPU_PAGE_SIZE;
+
+ spin_lock(&vm->it_lock);
+- it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1);
++ it = interval_tree_iter_first(&vm->va, saddr, eaddr);
+ spin_unlock(&vm->it_lock);
+ if (it) {
+ struct amdgpu_bo_va_mapping *tmp;
+@@ -1046,7 +1046,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
+
+ INIT_LIST_HEAD(&mapping->list);
+ mapping->it.start = saddr;
+- mapping->it.last = eaddr - 1;
++ mapping->it.last = eaddr;
+ mapping->offset = offset;
+ mapping->flags = flags;
+
+@@ -1248,7 +1248,7 @@ int amdgpu_vm_init(struct amdgpu_device
+ {
+ const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE,
+ AMDGPU_VM_PTE_COUNT * 8);
+- unsigned pd_size, pd_entries, pts_size;
++ unsigned pd_size, pd_entries;
+ int i, r;
+
+ for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
+@@ -1266,8 +1266,7 @@ int amdgpu_vm_init(struct amdgpu_device
+ pd_entries = amdgpu_vm_num_pdes(adev);
+
+ /* allocate page table array */
+- pts_size = pd_entries * sizeof(struct amdgpu_vm_pt);
+- vm->page_tables = kzalloc(pts_size, GFP_KERNEL);
++ vm->page_tables = drm_calloc_large(pd_entries, sizeof(struct amdgpu_vm_pt));
+ if (vm->page_tables == NULL) {
+ DRM_ERROR("Cannot allocate memory for page table array\n");
+ return -ENOMEM;
+@@ -1327,7 +1326,7 @@ void amdgpu_vm_fini(struct amdgpu_device
+
+ for (i = 0; i < amdgpu_vm_num_pdes(adev); i++)
+ amdgpu_bo_unref(&vm->page_tables[i].bo);
+- kfree(vm->page_tables);
++ drm_free_large(vm->page_tables);
+
+ amdgpu_bo_unref(&vm->page_directory);
+ fence_put(vm->page_directory_fence);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c 2016-01-10 20:56:39.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c 2016-04-12 21:14:02.000000000 -0400
+@@ -3599,6 +3599,19 @@ static void gfx_v7_0_ring_emit_vm_flush(
+ unsigned vm_id, uint64_t pd_addr)
+ {
+ int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
++ uint32_t seq = ring->fence_drv.sync_seq;
++ uint64_t addr = ring->fence_drv.gpu_addr;
++
++ amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
++ amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
++ WAIT_REG_MEM_FUNCTION(3) | /* equal */
++ WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */
++ amdgpu_ring_write(ring, addr & 0xfffffffc);
++ amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
++ amdgpu_ring_write(ring, seq);
++ amdgpu_ring_write(ring, 0xffffffff);
++ amdgpu_ring_write(ring, 4); /* poll interval */
++
+ if (usepfp) {
+ /* synce CE with ME to prevent CE fetch CEIB before context switch done */
+ amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c 2016-01-10 20:56:07.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c 2016-04-12 21:13:26.000000000 -0400
+@@ -775,7 +775,8 @@ static int gfx_v8_0_init_microcode(struc
+ adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
+
+- if (adev->asic_type != CHIP_STONEY) {
++ if ((adev->asic_type != CHIP_STONEY) &&
++ (adev->asic_type != CHIP_TOPAZ)) {
+ snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+ err = reject_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
+ if (!err) {
+@@ -4649,7 +4650,8 @@ static void gfx_v8_0_ring_emit_vm_flush(
+
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+ amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
+- WAIT_REG_MEM_FUNCTION(3))); /* equal */
++ WAIT_REG_MEM_FUNCTION(3) | /* equal */
++ WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */
+ amdgpu_ring_write(ring, addr & 0xfffffffc);
+ amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
+ amdgpu_ring_write(ring, seq);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c 2016-01-10 20:56:42.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c 2016-04-12 21:14:16.000000000 -0400
+@@ -42,8 +42,37 @@ static void gmc_v7_0_set_irq_funcs(struc
+
+ /*(DEBLOBBED)*/
+
++static const u32 golden_settings_iceland_a11[] =
++{
++ mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff,
++ mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff,
++ mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff,
++ mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff
++};
++
++static const u32 iceland_mgcg_cgcg_init[] =
++{
++ mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
++};
++
++static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev)
++{
++ switch (adev->asic_type) {
++ case CHIP_TOPAZ:
++ amdgpu_program_register_sequence(adev,
++ iceland_mgcg_cgcg_init,
++ (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init));
++ amdgpu_program_register_sequence(adev,
++ golden_settings_iceland_a11,
++ (const u32)ARRAY_SIZE(golden_settings_iceland_a11));
++ break;
++ default:
++ break;
++ }
++}
++
+ /**
+- * gmc8_mc_wait_for_idle - wait for MC idle callback.
++ * gmc7_mc_wait_for_idle - wait for MC idle callback.
+ *
+ * @adev: amdgpu_device pointer
+ *
+@@ -131,13 +160,20 @@ static int gmc_v7_0_init_microcode(struc
+ case CHIP_HAWAII:
+ chip_name = "hawaii";
+ break;
++ case CHIP_TOPAZ:
++ chip_name = "topaz";
++ break;
+ case CHIP_KAVERI:
+ case CHIP_KABINI:
+ return 0;
+ default: BUG();
+ }
+
+- snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
++ if (adev->asic_type == CHIP_TOPAZ)
++ snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
++ else
++ snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
++
+ err = reject_firmware(&adev->mc.fw, fw_name, adev->dev);
+ if (err)
+ goto out;
+@@ -979,6 +1015,8 @@ static int gmc_v7_0_hw_init(void *handle
+ int r;
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
++ gmc_v7_0_init_golden_registers(adev);
++
+ gmc_v7_0_mc_program(adev);
+
+ if (!(adev->flags & AMD_IS_APU)) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c 2016-01-10 20:56:10.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c 2016-04-12 21:13:29.000000000 -0400
+@@ -73,19 +73,6 @@ static const u32 fiji_mgcg_cgcg_init[] =
+ mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+ };
+
+-static const u32 golden_settings_iceland_a11[] =
+-{
+- mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+- mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+- mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+- mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff
+-};
+-
+-static const u32 iceland_mgcg_cgcg_init[] =
+-{
+- mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+-};
+-
+ static const u32 cz_mgcg_cgcg_init[] =
+ {
+ mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
+@@ -100,14 +87,6 @@ static const u32 stoney_mgcg_cgcg_init[]
+ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
+ {
+ switch (adev->asic_type) {
+- case CHIP_TOPAZ:
+- amdgpu_program_register_sequence(adev,
+- iceland_mgcg_cgcg_init,
+- (const u32)ARRAY_SIZE(iceland_mgcg_cgcg_init));
+- amdgpu_program_register_sequence(adev,
+- golden_settings_iceland_a11,
+- (const u32)ARRAY_SIZE(golden_settings_iceland_a11));
+- break;
+ case CHIP_FIJI:
+ amdgpu_program_register_sequence(adev,
+ fiji_mgcg_cgcg_init,
+@@ -227,15 +206,10 @@ static int gmc_v8_0_init_microcode(struc
+ DRM_DEBUG("\n");
+
+ switch (adev->asic_type) {
+- case CHIP_TOPAZ:
+- chip_name = "topaz";
+- break;
+ case CHIP_TONGA:
+ chip_name = "tonga";
+ break;
+ case CHIP_FIJI:
+- chip_name = "fiji";
+- break;
+ case CHIP_CARRIZO:
+ case CHIP_STONEY:
+ return 0;
+@@ -1001,7 +975,7 @@ static int gmc_v8_0_hw_init(void *handle
+
+ gmc_v8_0_mc_program(adev);
+
+- if (!(adev->flags & AMD_IS_APU)) {
++ if (adev->asic_type == CHIP_TONGA) {
+ r = gmc_v8_0_mc_load_microcode(adev);
+ if (r) {
+ DRM_ERROR("Failed to load MC firmware!\n");
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/iceland_smc.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/iceland_smc.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/iceland_smc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/iceland_smc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -432,7 +432,7 @@ static uint32_t iceland_smu_get_mask_for
+ case AMDGPU_UCODE_ID_CP_ME:
+ return UCODE_ID_CP_ME_MASK;
+ case AMDGPU_UCODE_ID_CP_MEC1:
+- return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK | UCODE_ID_CP_MEC_JT2_MASK;
++ return UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK;
+ case AMDGPU_UCODE_ID_CP_MEC2:
+ return UCODE_ID_CP_MEC_MASK;
+ case AMDGPU_UCODE_ID_RLC_G:
+@@ -522,12 +522,6 @@ static int iceland_smu_request_load_fw(s
+ return -EINVAL;
+ }
+
+- if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT2,
+- &toc->entry[toc->num_entries++])) {
+- DRM_ERROR("Failed to get firmware entry for MEC_JT2\n");
+- return -EINVAL;
+- }
+-
+ if (iceland_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA0,
+ &toc->entry[toc->num_entries++])) {
+ DRM_ERROR("Failed to get firmware entry for SDMA0\n");
+@@ -550,8 +544,8 @@ static int iceland_smu_request_load_fw(s
+ UCODE_ID_CP_ME_MASK |
+ UCODE_ID_CP_PFP_MASK |
+ UCODE_ID_CP_MEC_MASK |
+- UCODE_ID_CP_MEC_JT1_MASK |
+- UCODE_ID_CP_MEC_JT2_MASK;
++ UCODE_ID_CP_MEC_JT1_MASK;
++
+
+ if (iceland_send_msg_to_smc_with_parameter_without_waiting(adev, PPSMC_MSG_LoadUcodes, fw_to_load)) {
+ DRM_ERROR("Fail to request SMU load ucode\n");
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/Makefile linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/Makefile
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/Makefile 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/Makefile 2016-04-12 12:09:26.000000000 -0400
+@@ -22,7 +22,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o
+ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o
+
+ # add asic specific block
+-amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o gmc_v7_0.o cik_ih.o kv_smc.o kv_dpm.o \
++amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
+ ci_smc.o ci_dpm.o dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o \
+ amdgpu_amdkfd_gfx_v7.o
+
+@@ -31,6 +31,7 @@ amdgpu-y += \
+
+ # add GMC block
+ amdgpu-y += \
++ gmc_v7_0.o \
+ gmc_v8_0.o
+
+ # add IH block
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c 2016-01-10 20:56:15.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c 2016-04-12 21:13:34.000000000 -0400
+@@ -32,8 +32,8 @@
+ #include "oss/oss_2_4_d.h"
+ #include "oss/oss_2_4_sh_mask.h"
+
+-#include "gmc/gmc_8_1_d.h"
+-#include "gmc/gmc_8_1_sh_mask.h"
++#include "gmc/gmc_7_1_d.h"
++#include "gmc/gmc_7_1_sh_mask.h"
+
+ #include "gca/gfx_8_0_d.h"
+ #include "gca/gfx_8_0_enum.h"
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c 2016-01-10 20:56:25.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c 2016-04-12 21:13:44.000000000 -0400
+@@ -122,25 +122,12 @@ static int tonga_dpm_hw_fini(void *handl
+
+ static int tonga_dpm_suspend(void *handle)
+ {
+- return 0;
++ return tonga_dpm_hw_fini(handle);
+ }
+
+ static int tonga_dpm_resume(void *handle)
+ {
+- int ret;
+- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+-
+- mutex_lock(&adev->pm.mutex);
+-
+- ret = tonga_smu_start(adev);
+- if (ret) {
+- DRM_ERROR("SMU start failed\n");
+- goto fail;
+- }
+-
+-fail:
+- mutex_unlock(&adev->pm.mutex);
+- return ret;
++ return tonga_dpm_hw_init(handle);
+ }
+
+ static int tonga_dpm_set_clockgating_state(void *handle,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/vi.c linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/vi.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/amd/amdgpu/vi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/amd/amdgpu/vi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -60,6 +60,7 @@
+ #include "vi.h"
+ #include "vi_dpm.h"
+ #include "gmc_v8_0.h"
++#include "gmc_v7_0.h"
+ #include "gfx_v8_0.h"
+ #include "sdma_v2_4.h"
+ #include "sdma_v3_0.h"
+@@ -1081,10 +1082,10 @@ static const struct amdgpu_ip_block_vers
+ },
+ {
+ .type = AMD_IP_BLOCK_TYPE_GMC,
+- .major = 8,
+- .minor = 0,
++ .major = 7,
++ .minor = 4,
+ .rev = 0,
+- .funcs = &gmc_v8_0_ip_funcs,
++ .funcs = &gmc_v7_0_ip_funcs,
+ },
+ {
+ .type = AMD_IP_BLOCK_TYPE_IH,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/ast/ast_main.c linux-libre-4.4.7-gnu/drivers/gpu/drm/ast/ast_main.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/ast/ast_main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/ast/ast_main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -227,7 +227,7 @@ static int ast_get_dram_info(struct drm_
+ } while (ast_read32(ast, 0x10000) != 0x01);
+ data = ast_read32(ast, 0x10004);
+
+- if (data & 0x400)
++ if (data & 0x40)
+ ast->dram_bus_width = 16;
+ else
+ ast->dram_bus_width = 32;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/drm_dp_mst_topology.c linux-libre-4.4.7-gnu/drivers/gpu/drm/drm_dp_mst_topology.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/drm_dp_mst_topology.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/drm_dp_mst_topology.c 2016-04-12 12:09:26.000000000 -0400
+@@ -798,6 +798,18 @@ static struct drm_dp_mst_branch *drm_dp_
+ return mstb;
+ }
+
++static void drm_dp_free_mst_port(struct kref *kref);
++
++static void drm_dp_free_mst_branch_device(struct kref *kref)
++{
++ struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
++ if (mstb->port_parent) {
++ if (list_empty(&mstb->port_parent->next))
++ kref_put(&mstb->port_parent->kref, drm_dp_free_mst_port);
++ }
++ kfree(mstb);
++}
++
+ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
+ {
+ struct drm_dp_mst_branch *mstb = container_of(kref, struct drm_dp_mst_branch, kref);
+@@ -805,6 +817,15 @@ static void drm_dp_destroy_mst_branch_de
+ bool wake_tx = false;
+
+ /*
++ * init kref again to be used by ports to remove mst branch when it is
++ * not needed anymore
++ */
++ kref_init(kref);
++
++ if (mstb->port_parent && list_empty(&mstb->port_parent->next))
++ kref_get(&mstb->port_parent->kref);
++
++ /*
+ * destroy all ports - don't need lock
+ * as there are no more references to the mst branch
+ * device at this point.
+@@ -830,7 +851,8 @@ static void drm_dp_destroy_mst_branch_de
+
+ if (wake_tx)
+ wake_up(&mstb->mgr->tx_waitq);
+- kfree(mstb);
++
++ kref_put(kref, drm_dp_free_mst_branch_device);
+ }
+
+ static void drm_dp_put_mst_branch_device(struct drm_dp_mst_branch *mstb)
+@@ -878,6 +900,7 @@ static void drm_dp_destroy_port(struct k
+ * from an EDID retrieval */
+
+ mutex_lock(&mgr->destroy_connector_lock);
++ kref_get(&port->parent->kref);
+ list_add(&port->next, &mgr->destroy_connector_list);
+ mutex_unlock(&mgr->destroy_connector_lock);
+ schedule_work(&mgr->destroy_connector_work);
+@@ -973,17 +996,17 @@ static struct drm_dp_mst_port *drm_dp_ge
+ static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
+ u8 *rad)
+ {
+- int lct = port->parent->lct;
++ int parent_lct = port->parent->lct;
+ int shift = 4;
+- int idx = lct / 2;
+- if (lct > 1) {
+- memcpy(rad, port->parent->rad, idx);
+- shift = (lct % 2) ? 4 : 0;
++ int idx = (parent_lct - 1) / 2;
++ if (parent_lct > 1) {
++ memcpy(rad, port->parent->rad, idx + 1);
++ shift = (parent_lct % 2) ? 4 : 0;
+ } else
+ rad[0] = 0;
+
+ rad[idx] |= port->port_num << shift;
+- return lct + 1;
++ return parent_lct + 1;
+ }
+
+ /*
+@@ -1013,18 +1036,27 @@ static bool drm_dp_port_setup_pdt(struct
+ return send_link;
+ }
+
+-static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb,
+- struct drm_dp_mst_port *port)
++static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
+ {
+ int ret;
+- if (port->dpcd_rev >= 0x12) {
+- port->guid_valid = drm_dp_validate_guid(mstb->mgr, port->guid);
+- if (!port->guid_valid) {
+- ret = drm_dp_send_dpcd_write(mstb->mgr,
+- port,
+- DP_GUID,
+- 16, port->guid);
+- port->guid_valid = true;
++
++ memcpy(mstb->guid, guid, 16);
++
++ if (!drm_dp_validate_guid(mstb->mgr, mstb->guid)) {
++ if (mstb->port_parent) {
++ ret = drm_dp_send_dpcd_write(
++ mstb->mgr,
++ mstb->port_parent,
++ DP_GUID,
++ 16,
++ mstb->guid);
++ } else {
++
++ ret = drm_dp_dpcd_write(
++ mstb->mgr->aux,
++ DP_GUID,
++ mstb->guid,
++ 16);
+ }
+ }
+ }
+@@ -1039,7 +1071,7 @@ static void build_mst_prop_path(const st
+ snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
+ for (i = 0; i < (mstb->lct - 1); i++) {
+ int shift = (i % 2) ? 0 : 4;
+- int port_num = mstb->rad[i / 2] >> shift;
++ int port_num = (mstb->rad[i / 2] >> shift) & 0xf;
+ snprintf(temp, sizeof(temp), "-%d", port_num);
+ strlcat(proppath, temp, proppath_size);
+ }
+@@ -1081,7 +1113,6 @@ static void drm_dp_add_port(struct drm_d
+ port->dpcd_rev = port_msg->dpcd_revision;
+ port->num_sdp_streams = port_msg->num_sdp_streams;
+ port->num_sdp_stream_sinks = port_msg->num_sdp_stream_sinks;
+- memcpy(port->guid, port_msg->peer_guid, 16);
+
+ /* manage mstb port lists with mgr lock - take a reference
+ for this list */
+@@ -1094,11 +1125,9 @@ static void drm_dp_add_port(struct drm_d
+
+ if (old_ddps != port->ddps) {
+ if (port->ddps) {
+- drm_dp_check_port_guid(mstb, port);
+ if (!port->input)
+ drm_dp_send_enum_path_resources(mstb->mgr, mstb, port);
+ } else {
+- port->guid_valid = false;
+ port->available_pbn = 0;
+ }
+ }
+@@ -1157,10 +1186,8 @@ static void drm_dp_update_port(struct dr
+
+ if (old_ddps != port->ddps) {
+ if (port->ddps) {
+- drm_dp_check_port_guid(mstb, port);
+ dowork = true;
+ } else {
+- port->guid_valid = false;
+ port->available_pbn = 0;
+ }
+ }
+@@ -1190,7 +1217,7 @@ static struct drm_dp_mst_branch *drm_dp_
+
+ for (i = 0; i < lct - 1; i++) {
+ int shift = (i % 2) ? 0 : 4;
+- int port_num = rad[i / 2] >> shift;
++ int port_num = (rad[i / 2] >> shift) & 0xf;
+
+ list_for_each_entry(port, &mstb->ports, next) {
+ if (port->port_num == port_num) {
+@@ -1210,6 +1237,48 @@ out:
+ return mstb;
+ }
+
++static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper(
++ struct drm_dp_mst_branch *mstb,
++ uint8_t *guid)
++{
++ struct drm_dp_mst_branch *found_mstb;
++ struct drm_dp_mst_port *port;
++
++ if (memcmp(mstb->guid, guid, 16) == 0)
++ return mstb;
++
++
++ list_for_each_entry(port, &mstb->ports, next) {
++ if (!port->mstb)
++ continue;
++
++ found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
++
++ if (found_mstb)
++ return found_mstb;
++ }
++
++ return NULL;
++}
++
++static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device_by_guid(
++ struct drm_dp_mst_topology_mgr *mgr,
++ uint8_t *guid)
++{
++ struct drm_dp_mst_branch *mstb;
++
++ /* find the port by iterating down */
++ mutex_lock(&mgr->lock);
++
++ mstb = get_mst_branch_device_by_guid_helper(mgr->mst_primary, guid);
++
++ if (mstb)
++ kref_get(&mstb->kref);
++
++ mutex_unlock(&mgr->lock);
++ return mstb;
++}
++
+ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_branch *mstb)
+ {
+@@ -1320,6 +1389,7 @@ static int set_hdr_from_dst_qlock(struct
+ struct drm_dp_sideband_msg_tx *txmsg)
+ {
+ struct drm_dp_mst_branch *mstb = txmsg->dst;
++ u8 req_type;
+
+ /* both msg slots are full */
+ if (txmsg->seqno == -1) {
+@@ -1336,7 +1406,13 @@ static int set_hdr_from_dst_qlock(struct
+ txmsg->seqno = 1;
+ mstb->tx_slots[txmsg->seqno] = txmsg;
+ }
+- hdr->broadcast = 0;
++
++ req_type = txmsg->msg[0] & 0x7f;
++ if (req_type == DP_CONNECTION_STATUS_NOTIFY ||
++ req_type == DP_RESOURCE_STATUS_NOTIFY)
++ hdr->broadcast = 1;
++ else
++ hdr->broadcast = 0;
+ hdr->path_msg = txmsg->path_msg;
+ hdr->lct = mstb->lct;
+ hdr->lcr = mstb->lct - 1;
+@@ -1438,26 +1514,18 @@ static void process_single_down_tx_qlock
+ }
+
+ /* called holding qlock */
+-static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
++static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
++ struct drm_dp_sideband_msg_tx *txmsg)
+ {
+- struct drm_dp_sideband_msg_tx *txmsg;
+ int ret;
+
+ /* construct a chunk from the first msg in the tx_msg queue */
+- if (list_empty(&mgr->tx_msg_upq)) {
+- mgr->tx_up_in_progress = false;
+- return;
+- }
+-
+- txmsg = list_first_entry(&mgr->tx_msg_upq, struct drm_dp_sideband_msg_tx, next);
+ ret = process_single_tx_qlock(mgr, txmsg, true);
+- if (ret == 1) {
+- /* up txmsgs aren't put in slots - so free after we send it */
+- list_del(&txmsg->next);
+- kfree(txmsg);
+- } else if (ret)
++
++ if (ret != 1)
+ DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
+- mgr->tx_up_in_progress = true;
++
++ txmsg->dst->tx_slots[txmsg->seqno] = NULL;
+ }
+
+ static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
+@@ -1507,6 +1575,9 @@ static void drm_dp_send_link_address(str
+ txmsg->reply.u.link_addr.ports[i].num_sdp_streams,
+ txmsg->reply.u.link_addr.ports[i].num_sdp_stream_sinks);
+ }
++
++ drm_dp_check_mstb_guid(mstb, txmsg->reply.u.link_addr.guid);
++
+ for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) {
+ drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]);
+ }
+@@ -1554,6 +1625,37 @@ static int drm_dp_send_enum_path_resourc
+ return 0;
+ }
+
++static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb)
++{
++ if (!mstb->port_parent)
++ return NULL;
++
++ if (mstb->port_parent->mstb != mstb)
++ return mstb->port_parent;
++
++ return drm_dp_get_last_connected_port_to_mstb(mstb->port_parent->parent);
++}
++
++static struct drm_dp_mst_branch *drm_dp_get_last_connected_port_and_mstb(struct drm_dp_mst_topology_mgr *mgr,
++ struct drm_dp_mst_branch *mstb,
++ int *port_num)
++{
++ struct drm_dp_mst_branch *rmstb = NULL;
++ struct drm_dp_mst_port *found_port;
++ mutex_lock(&mgr->lock);
++ if (mgr->mst_primary) {
++ found_port = drm_dp_get_last_connected_port_to_mstb(mstb);
++
++ if (found_port) {
++ rmstb = found_port->parent;
++ kref_get(&rmstb->kref);
++ *port_num = found_port->port_num;
++ }
++ }
++ mutex_unlock(&mgr->lock);
++ return rmstb;
++}
++
+ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ int id,
+@@ -1561,11 +1663,16 @@ static int drm_dp_payload_send_msg(struc
+ {
+ struct drm_dp_sideband_msg_tx *txmsg;
+ struct drm_dp_mst_branch *mstb;
+- int len, ret;
++ int len, ret, port_num;
+
++ port_num = port->port_num;
+ mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
+- if (!mstb)
+- return -EINVAL;
++ if (!mstb) {
++ mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num);
++
++ if (!mstb)
++ return -EINVAL;
++ }
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg) {
+@@ -1574,7 +1681,7 @@ static int drm_dp_payload_send_msg(struc
+ }
+
+ txmsg->dst = mstb;
+- len = build_allocate_payload(txmsg, port->port_num,
++ len = build_allocate_payload(txmsg, port_num,
+ id,
+ pbn);
+
+@@ -1844,11 +1951,12 @@ static int drm_dp_send_up_ack_reply(stru
+ drm_dp_encode_up_ack_reply(txmsg, req_type);
+
+ mutex_lock(&mgr->qlock);
+- list_add_tail(&txmsg->next, &mgr->tx_msg_upq);
+- if (!mgr->tx_up_in_progress) {
+- process_single_up_tx_qlock(mgr);
+- }
++
++ process_single_up_tx_qlock(mgr, txmsg);
++
+ mutex_unlock(&mgr->qlock);
++
++ kfree(txmsg);
+ return 0;
+ }
+
+@@ -1927,31 +2035,17 @@ int drm_dp_mst_topology_mgr_set_mst(stru
+ mgr->mst_primary = mstb;
+ kref_get(&mgr->mst_primary->kref);
+
+- {
+- struct drm_dp_payload reset_pay;
+- reset_pay.start_slot = 0;
+- reset_pay.num_slots = 0x3f;
+- drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
+- }
+-
+ ret = drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
+- DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
++ DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC);
+ if (ret < 0) {
+ goto out_unlock;
+ }
+
+-
+- /* sort out guid */
+- ret = drm_dp_dpcd_read(mgr->aux, DP_GUID, mgr->guid, 16);
+- if (ret != 16) {
+- DRM_DEBUG_KMS("failed to read DP GUID %d\n", ret);
+- goto out_unlock;
+- }
+-
+- mgr->guid_valid = drm_dp_validate_guid(mgr, mgr->guid);
+- if (!mgr->guid_valid) {
+- ret = drm_dp_dpcd_write(mgr->aux, DP_GUID, mgr->guid, 16);
+- mgr->guid_valid = true;
++ {
++ struct drm_dp_payload reset_pay;
++ reset_pay.start_slot = 0;
++ reset_pay.num_slots = 0x3f;
++ drm_dp_dpcd_write_payload(mgr, 0, &reset_pay);
+ }
+
+ queue_work(system_long_wq, &mgr->work);
+@@ -2145,28 +2239,51 @@ static int drm_dp_mst_handle_up_req(stru
+
+ if (mgr->up_req_recv.have_eomt) {
+ struct drm_dp_sideband_msg_req_body msg;
+- struct drm_dp_mst_branch *mstb;
++ struct drm_dp_mst_branch *mstb = NULL;
+ bool seqno;
+- mstb = drm_dp_get_mst_branch_device(mgr,
+- mgr->up_req_recv.initial_hdr.lct,
+- mgr->up_req_recv.initial_hdr.rad);
+- if (!mstb) {
+- DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
+- memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
+- return 0;
++
++ if (!mgr->up_req_recv.initial_hdr.broadcast) {
++ mstb = drm_dp_get_mst_branch_device(mgr,
++ mgr->up_req_recv.initial_hdr.lct,
++ mgr->up_req_recv.initial_hdr.rad);
++ if (!mstb) {
++ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
++ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
++ return 0;
++ }
+ }
+
+ seqno = mgr->up_req_recv.initial_hdr.seqno;
+ drm_dp_sideband_parse_req(&mgr->up_req_recv, &msg);
+
+ if (msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
+- drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
++ drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
++
++ if (!mstb)
++ mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.conn_stat.guid);
++
++ if (!mstb) {
++ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
++ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
++ return 0;
++ }
++
+ drm_dp_update_port(mstb, &msg.u.conn_stat);
++
+ DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type);
+ (*mgr->cbs->hotplug)(mgr);
+
+ } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
+- drm_dp_send_up_ack_reply(mgr, mstb, msg.req_type, seqno, false);
++ drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false);
++ if (!mstb)
++ mstb = drm_dp_get_mst_branch_device_by_guid(mgr, msg.u.resource_stat.guid);
++
++ if (!mstb) {
++ DRM_DEBUG_KMS("Got MST reply from unknown device %d\n", mgr->up_req_recv.initial_hdr.lct);
++ memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
++ return 0;
++ }
++
+ DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
+ }
+
+@@ -2346,6 +2463,7 @@ bool drm_dp_mst_allocate_vcpi(struct drm
+ DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn);
+ if (pbn == port->vcpi.pbn) {
+ *slots = port->vcpi.num_slots;
++ drm_dp_put_port(port);
+ return true;
+ }
+ }
+@@ -2505,32 +2623,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
+ */
+ int drm_dp_calc_pbn_mode(int clock, int bpp)
+ {
+- fixed20_12 pix_bw;
+- fixed20_12 fbpp;
+- fixed20_12 result;
+- fixed20_12 margin, tmp;
+- u32 res;
++ u64 kbps;
++ s64 peak_kbps;
++ u32 numerator;
++ u32 denominator;
+
+- pix_bw.full = dfixed_const(clock);
+- fbpp.full = dfixed_const(bpp);
+- tmp.full = dfixed_const(8);
+- fbpp.full = dfixed_div(fbpp, tmp);
++ kbps = clock * bpp;
+
+- result.full = dfixed_mul(pix_bw, fbpp);
+- margin.full = dfixed_const(54);
+- tmp.full = dfixed_const(64);
+- margin.full = dfixed_div(margin, tmp);
+- result.full = dfixed_div(result, margin);
++ /*
++ * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
++ * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
++ * common multiplier to render an integer PBN for all link rate/lane
++ * counts combinations
++ * calculate
++ * peak_kbps *= (1006/1000)
++ * peak_kbps *= (64/54)
++ * peak_kbps *= 8 convert to bytes
++ */
+
+- margin.full = dfixed_const(1006);
+- tmp.full = dfixed_const(1000);
+- margin.full = dfixed_div(margin, tmp);
+- result.full = dfixed_mul(result, margin);
++ numerator = 64 * 1006;
++ denominator = 54 * 8 * 1000 * 1000;
+
+- result.full = dfixed_div(result, tmp);
+- result.full = dfixed_ceil(result);
+- res = dfixed_trunc(result);
+- return res;
++ kbps *= numerator;
++ peak_kbps = drm_fixp_from_fraction(kbps, denominator);
++
++ return drm_fixp2int_ceil(peak_kbps);
+ }
+ EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
+
+@@ -2538,11 +2655,23 @@ static int test_calc_pbn_mode(void)
+ {
+ int ret;
+ ret = drm_dp_calc_pbn_mode(154000, 30);
+- if (ret != 689)
++ if (ret != 689) {
++ DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
++ 154000, 30, 689, ret);
+ return -EINVAL;
++ }
+ ret = drm_dp_calc_pbn_mode(234000, 30);
+- if (ret != 1047)
++ if (ret != 1047) {
++ DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
++ 234000, 30, 1047, ret);
+ return -EINVAL;
++ }
++ ret = drm_dp_calc_pbn_mode(297000, 24);
++ if (ret != 1063) {
++ DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
++ 297000, 24, 1063, ret);
++ return -EINVAL;
++ }
+ return 0;
+ }
+
+@@ -2683,6 +2812,13 @@ static void drm_dp_tx_work(struct work_s
+ mutex_unlock(&mgr->qlock);
+ }
+
++static void drm_dp_free_mst_port(struct kref *kref)
++{
++ struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
++ kref_put(&port->parent->kref, drm_dp_free_mst_branch_device);
++ kfree(port);
++}
++
+ static void drm_dp_destroy_connector_work(struct work_struct *work)
+ {
+ struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
+@@ -2703,13 +2839,22 @@ static void drm_dp_destroy_connector_wor
+ list_del(&port->next);
+ mutex_unlock(&mgr->destroy_connector_lock);
+
++ kref_init(&port->kref);
++ INIT_LIST_HEAD(&port->next);
++
+ mgr->cbs->destroy_connector(mgr, port->connector);
+
+ drm_dp_port_teardown_pdt(port, port->pdt);
+
+- if (!port->input && port->vcpi.vcpi > 0)
+- drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+- kfree(port);
++ if (!port->input && port->vcpi.vcpi > 0) {
++ if (mgr->mst_state) {
++ drm_dp_mst_reset_vcpi_slots(mgr, port);
++ drm_dp_update_payload_part1(mgr);
++ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
++ }
++ }
++
++ kref_put(&port->kref, drm_dp_free_mst_port);
+ send_hotplug = true;
+ }
+ if (send_hotplug)
+@@ -2736,7 +2881,6 @@ int drm_dp_mst_topology_mgr_init(struct
+ mutex_init(&mgr->qlock);
+ mutex_init(&mgr->payload_lock);
+ mutex_init(&mgr->destroy_connector_lock);
+- INIT_LIST_HEAD(&mgr->tx_msg_upq);
+ INIT_LIST_HEAD(&mgr->tx_msg_downq);
+ INIT_LIST_HEAD(&mgr->destroy_connector_list);
+ INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/drm_irq.c linux-libre-4.4.7-gnu/drivers/gpu/drm/drm_irq.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/drm_irq.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/drm_irq.c 2016-04-12 12:09:26.000000000 -0400
+@@ -221,6 +221,64 @@ static void drm_update_vblank_count(stru
+ diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0;
+ }
+
++ /*
++ * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
++ * interval? If so then vblank irqs keep running and it will likely
++ * happen that the hardware vblank counter is not trustworthy as it
++ * might reset at some point in that interval and vblank timestamps
++ * are not trustworthy either in that interval. Iow. this can result
++ * in a bogus diff >> 1 which must be avoided as it would cause
++ * random large forward jumps of the software vblank counter.
++ */
++ if (diff > 1 && (vblank->inmodeset & 0x2)) {
++ DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u"
++ " due to pre-modeset.\n", pipe, diff);
++ diff = 1;
++ }
++
++ /*
++ * FIMXE: Need to replace this hack with proper seqlocks.
++ *
++ * Restrict the bump of the software vblank counter to a safe maximum
++ * value of +1 whenever there is the possibility that concurrent readers
++ * of vblank timestamps could be active at the moment, as the current
++ * implementation of the timestamp caching and updating is not safe
++ * against concurrent readers for calls to store_vblank() with a bump
++ * of anything but +1. A bump != 1 would very likely return corrupted
++ * timestamps to userspace, because the same slot in the cache could
++ * be concurrently written by store_vblank() and read by one of those
++ * readers without the read-retry logic detecting the collision.
++ *
++ * Concurrent readers can exist when we are called from the
++ * drm_vblank_off() or drm_vblank_on() functions and other non-vblank-
++ * irq callers. However, all those calls to us are happening with the
++ * vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount
++ * can't increase while we are executing. Therefore a zero refcount at
++ * this point is safe for arbitrary counter bumps if we are called
++ * outside vblank irq, a non-zero count is not 100% safe. Unfortunately
++ * we must also accept a refcount of 1, as whenever we are called from
++ * drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and
++ * we must let that one pass through in order to not lose vblank counts
++ * during vblank irq off - which would completely defeat the whole
++ * point of this routine.
++ *
++ * Whenever we are called from vblank irq, we have to assume concurrent
++ * readers exist or can show up any time during our execution, even if
++ * the refcount is currently zero, as vblank irqs are usually only
++ * enabled due to the presence of readers, and because when we are called
++ * from vblank irq we can't hold the vbl_lock to protect us from sudden
++ * bumps in vblank refcount. Therefore also restrict bumps to +1 when
++ * called from vblank irq.
++ */
++ if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 ||
++ (flags & DRM_CALLED_FROM_VBLIRQ))) {
++ DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u "
++ "refcount %u, vblirq %u\n", pipe, diff,
++ atomic_read(&vblank->refcount),
++ (flags & DRM_CALLED_FROM_VBLIRQ) != 0);
++ diff = 1;
++ }
++
+ DRM_DEBUG_VBL("updating vblank count on crtc %u:"
+ " current=%u, diff=%u, hw=%u hw_last=%u\n",
+ pipe, vblank->count, diff, cur_vblank, vblank->last);
+@@ -1313,7 +1371,13 @@ void drm_vblank_off(struct drm_device *d
+ spin_lock_irqsave(&dev->event_lock, irqflags);
+
+ spin_lock(&dev->vbl_lock);
+- vblank_disable_and_save(dev, pipe);
++ DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
++ pipe, vblank->enabled, vblank->inmodeset);
++
++ /* Avoid redundant vblank disables without previous drm_vblank_on(). */
++ if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
++ vblank_disable_and_save(dev, pipe);
++
+ wake_up(&vblank->queue);
+
+ /*
+@@ -1415,6 +1479,9 @@ void drm_vblank_on(struct drm_device *de
+ return;
+
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
++ DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
++ pipe, vblank->enabled, vblank->inmodeset);
++
+ /* Drop our private "prevent drm_vblank_get" refcount */
+ if (vblank->inmodeset) {
+ atomic_dec(&vblank->refcount);
+@@ -1427,8 +1494,7 @@ void drm_vblank_on(struct drm_device *de
+ * re-enable interrupts if there are users left, or the
+ * user wishes vblank interrupts to be enabled all the time.
+ */
+- if (atomic_read(&vblank->refcount) != 0 ||
+- (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0))
++ if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
+ WARN_ON(drm_vblank_enable(dev, pipe));
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ }
+@@ -1523,6 +1589,7 @@ void drm_vblank_post_modeset(struct drm_
+ if (vblank->inmodeset) {
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+ dev->vblank_disable_allowed = true;
++ drm_reset_vblank_timestamp(dev, pipe);
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+ if (vblank->inmodeset & 0x2)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/gma500/gem.c linux-libre-4.4.7-gnu/drivers/gpu/drm/gma500/gem.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/gma500/gem.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/gma500/gem.c 2016-04-12 12:09:26.000000000 -0400
+@@ -130,7 +130,7 @@ int psb_gem_create(struct drm_file *file
+ return ret;
+ }
+ /* We have the initial and handle reference but need only one now */
+- drm_gem_object_unreference(&r->gem);
++ drm_gem_object_unreference_unlocked(&r->gem);
+ *handlep = handle;
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_dma.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_dma.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_dma.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_dma.c 2016-04-12 12:09:26.000000000 -0400
+@@ -402,6 +402,8 @@ static int i915_load_modeset_init(struct
+ if (ret)
+ goto cleanup_gem_stolen;
+
++ intel_setup_gmbus(dev);
++
+ /* Important: The output setup functions called by modeset_init need
+ * working irqs for e.g. gmbus and dp aux transfers. */
+ intel_modeset_init(dev);
+@@ -451,6 +453,7 @@ cleanup_gem:
+ cleanup_irq:
+ intel_guc_ucode_fini(dev);
+ drm_irq_uninstall(dev);
++ intel_teardown_gmbus(dev);
+ cleanup_gem_stolen:
+ i915_gem_cleanup_stolen(dev);
+ cleanup_vga_switcheroo:
+@@ -1028,7 +1031,6 @@ int i915_driver_load(struct drm_device *
+
+ /* Try to make sure MCHBAR is enabled before poking at it */
+ intel_setup_mchbar(dev);
+- intel_setup_gmbus(dev);
+ intel_opregion_setup(dev);
+
+ i915_gem_load(dev);
+@@ -1099,7 +1101,6 @@ out_gem_unload:
+ if (dev->pdev->msi_enabled)
+ pci_disable_msi(dev->pdev);
+
+- intel_teardown_gmbus(dev);
+ intel_teardown_mchbar(dev);
+ pm_qos_remove_request(&dev_priv->pm_qos);
+ destroy_workqueue(dev_priv->gpu_error.hangcheck_wq);
+@@ -1198,7 +1199,6 @@ int i915_driver_unload(struct drm_device
+
+ intel_csr_ucode_fini(dev);
+
+- intel_teardown_gmbus(dev);
+ intel_teardown_mchbar(dev);
+
+ destroy_workqueue(dev_priv->hotplug.dp_wq);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_drv.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_drv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_drv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -531,7 +531,10 @@ void intel_detect_pch(struct drm_device
+ dev_priv->pch_type = PCH_SPT;
+ DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
+ WARN_ON(!IS_SKYLAKE(dev));
+- } else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE) {
++ } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
++ ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
++ pch->subsystem_vendor == 0x1af4 &&
++ pch->subsystem_device == 0x1100)) {
+ dev_priv->pch_type = intel_virt_detect_pch(dev);
+ } else
+ continue;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_drv.h
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_drv.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_drv.h 2016-04-12 12:09:26.000000000 -0400
+@@ -2614,6 +2614,7 @@ struct drm_i915_cmd_table {
+ #define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100
+ #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00
+ #define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100
++#define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */
+
+ #define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type)
+ #define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_gem_context.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_gem_context.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_gem_context.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_gem_context.c 2016-04-12 12:09:26.000000000 -0400
+@@ -340,6 +340,10 @@ void i915_gem_context_reset(struct drm_d
+ i915_gem_context_unreference(lctx);
+ ring->last_context = NULL;
+ }
++
++ /* Force the GPU state to be reinitialised on enabling */
++ if (ring->default_context)
++ ring->default_context->legacy_hw_ctx.initialized = false;
+ }
+ }
+
+@@ -708,7 +712,7 @@ static int do_switch(struct drm_i915_gem
+ if (ret)
+ goto unpin_out;
+
+- if (!to->legacy_hw_ctx.initialized) {
++ if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to)) {
+ hw_flags |= MI_RESTORE_INHIBIT;
+ /* NB: If we inhibit the restore, the context is not allowed to
+ * die because future work may end up depending on valid address
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_irq.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/i915_irq.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/i915_irq.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2354,9 +2354,13 @@ static irqreturn_t gen8_irq_handler(int
+ spt_irq_handler(dev, pch_iir);
+ else
+ cpt_irq_handler(dev, pch_iir);
+- } else
+- DRM_ERROR("The master control interrupt lied (SDE)!\n");
+-
++ } else {
++ /*
++ * Like on previous PCH there seems to be something
++ * fishy going on with forwarding PCH interrupts.
++ */
++ DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n");
++ }
+ }
+
+ I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_ddi.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_ddi.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_ddi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_ddi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1582,7 +1582,8 @@ skl_ddi_pll_select(struct intel_crtc *in
+ DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
+ DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
+ wrpll_params.central_freq;
+- } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
++ } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
++ intel_encoder->type == INTEL_OUTPUT_DP_MST) {
+ switch (crtc_state->port_clock / 2) {
+ case 81000:
+ ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_display.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_display.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_display.c 2016-04-12 12:09:26.000000000 -0400
+@@ -11930,11 +11930,21 @@ connected_sink_compute_bpp(struct intel_
+ pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
+ }
+
+- /* Clamp bpp to 8 on screens without EDID 1.4 */
+- if (connector->base.display_info.bpc == 0 && bpp > 24) {
+- DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
+- bpp);
+- pipe_config->pipe_bpp = 24;
++ /* Clamp bpp to default limit on screens without EDID 1.4 */
++ if (connector->base.display_info.bpc == 0) {
++ int type = connector->base.connector_type;
++ int clamp_bpp = 24;
++
++ /* Fall back to 18 bpp when DP sink capability is unknown. */
++ if (type == DRM_MODE_CONNECTOR_DisplayPort ||
++ type == DRM_MODE_CONNECTOR_eDP)
++ clamp_bpp = 18;
++
++ if (bpp > clamp_bpp) {
++ DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n",
++ bpp, clamp_bpp);
++ pipe_config->pipe_bpp = clamp_bpp;
++ }
+ }
+ }
+
+@@ -13537,11 +13547,12 @@ intel_check_primary_plane(struct drm_pla
+ int max_scale = DRM_PLANE_HELPER_NO_SCALING;
+ bool can_position = false;
+
+- /* use scaler when colorkey is not required */
+- if (INTEL_INFO(plane->dev)->gen >= 9 &&
+- state->ckey.flags == I915_SET_COLORKEY_NONE) {
+- min_scale = 1;
+- max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
++ if (INTEL_INFO(plane->dev)->gen >= 9) {
++ /* use scaler when colorkey is not required */
++ if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
++ min_scale = 1;
++ max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
++ }
+ can_position = true;
+ }
+
+@@ -15565,6 +15576,8 @@ void intel_modeset_cleanup(struct drm_de
+ mutex_lock(&dev->struct_mutex);
+ intel_cleanup_gt_powersave(dev);
+ mutex_unlock(&dev->struct_mutex);
++
++ intel_teardown_gmbus(dev);
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c 2016-04-12 12:09:26.000000000 -0400
+@@ -207,7 +207,12 @@ static const u8 *mipi_exec_gpio(struct i
+ gpio = *data++;
+
+ /* pull up/down */
+- action = *data++;
++ action = *data++ & 1;
++
++ if (gpio >= ARRAY_SIZE(gtable)) {
++ DRM_DEBUG_KMS("unknown gpio %u\n", gpio);
++ goto out;
++ }
+
+ function = gtable[gpio].function_reg;
+ pad = gtable[gpio].pad_reg;
+@@ -226,6 +231,7 @@ static const u8 *mipi_exec_gpio(struct i
+ vlv_gpio_nc_write(dev_priv, pad, val);
+ mutex_unlock(&dev_priv->sb_lock);
+
++out:
+ return data;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_hotplug.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_hotplug.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_hotplug.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_hotplug.c 2016-04-12 12:09:26.000000000 -0400
+@@ -468,9 +468,14 @@ void intel_hpd_init(struct drm_i915_priv
+ list_for_each_entry(connector, &mode_config->connector_list, head) {
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ connector->polled = intel_connector->polled;
+- if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE)
+- connector->polled = DRM_CONNECTOR_POLL_HPD;
++
++ /* MST has a dynamic intel_connector->encoder and it's reprobing
++ * is all handled by the MST helpers. */
+ if (intel_connector->mst_port)
++ continue;
++
++ if (!connector->polled && I915_HAS_HOTPLUG(dev) &&
++ intel_connector->encoder->hpd_pin > HPD_NONE)
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_i2c.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_i2c.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_i2c.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_i2c.c 2016-04-12 12:09:26.000000000 -0400
+@@ -675,7 +675,7 @@ int intel_setup_gmbus(struct drm_device
+ return 0;
+
+ err:
+- while (--pin) {
++ while (pin--) {
+ if (!intel_gmbus_is_valid_pin(dev_priv, pin))
+ continue;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_lrc.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_lrc.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_lrc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_lrc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1706,6 +1706,7 @@ static int gen8_emit_flush_render(struct
+ if (flush_domains) {
+ flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
++ flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -347,6 +347,7 @@ gen7_render_ring_flush(struct drm_i915_g
+ if (flush_domains) {
+ flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
++ flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
+ }
+ if (invalidate_domains) {
+@@ -419,6 +420,7 @@ gen8_render_ring_flush(struct drm_i915_g
+ if (flush_domains) {
+ flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+ flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
++ flags |= PIPE_CONTROL_DC_FLUSH_ENABLE;
+ flags |= PIPE_CONTROL_FLUSH_ENABLE;
+ }
+ if (invalidate_domains) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c 2016-04-12 12:09:26.000000000 -0400
+@@ -969,10 +969,13 @@ nouveau_connector_hotplug(struct nvif_no
+
+ NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
+
++ mutex_lock(&drm->dev->mode_config.mutex);
+ if (plugged)
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+ else
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
++ mutex_unlock(&drm->dev->mode_config.mutex);
++
+ drm_helper_hpd_irq_event(connector->dev);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nouveau_display.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nouveau_display.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nouveau_display.c 2016-04-12 12:09:26.000000000 -0400
+@@ -634,10 +634,6 @@ nouveau_display_resume(struct drm_device
+ nv_crtc->lut.depth = 0;
+ }
+
+- /* Make sure that drm and hw vblank irqs get resumed if needed. */
+- for (head = 0; head < dev->mode_config.num_crtc; head++)
+- drm_vblank_on(dev, head);
+-
+ /* This should ensure we don't hit a locking problem when someone
+ * wakes us up via a connector. We should never go into suspend
+ * while the display is on anyways.
+@@ -647,6 +643,10 @@ nouveau_display_resume(struct drm_device
+
+ drm_helper_resume_force_mode(dev);
+
++ /* Make sure that drm and hw vblank irqs get resumed if needed. */
++ for (head = 0; head < dev->mode_config.num_crtc; head++)
++ drm_vblank_on(dev, head);
++
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.c 2016-04-12 12:09:26.000000000 -0400
+@@ -24,7 +24,7 @@
+ static int nouveau_platform_probe(struct platform_device *pdev)
+ {
+ const struct nvkm_device_tegra_func *func;
+- struct nvkm_device *device;
++ struct nvkm_device *device = NULL;
+ struct drm_device *drm;
+ int ret;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c 2016-04-12 12:09:26.000000000 -0400
+@@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_
+
+ if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
+ return -ENOMEM;
+- *pdevice = &tdev->device;
++
+ tdev->func = func;
+ tdev->pdev = pdev;
+ tdev->irq = -1;
+
+ tdev->vdd = devm_regulator_get(&pdev->dev, "vdd");
+- if (IS_ERR(tdev->vdd))
+- return PTR_ERR(tdev->vdd);
++ if (IS_ERR(tdev->vdd)) {
++ ret = PTR_ERR(tdev->vdd);
++ goto free;
++ }
+
+ tdev->rst = devm_reset_control_get(&pdev->dev, "gpu");
+- if (IS_ERR(tdev->rst))
+- return PTR_ERR(tdev->rst);
++ if (IS_ERR(tdev->rst)) {
++ ret = PTR_ERR(tdev->rst);
++ goto free;
++ }
+
+ tdev->clk = devm_clk_get(&pdev->dev, "gpu");
+- if (IS_ERR(tdev->clk))
+- return PTR_ERR(tdev->clk);
++ if (IS_ERR(tdev->clk)) {
++ ret = PTR_ERR(tdev->clk);
++ goto free;
++ }
+
+ tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
+- if (IS_ERR(tdev->clk_pwr))
+- return PTR_ERR(tdev->clk_pwr);
++ if (IS_ERR(tdev->clk_pwr)) {
++ ret = PTR_ERR(tdev->clk_pwr);
++ goto free;
++ }
+
+ nvkm_device_tegra_probe_iommu(tdev);
+
+ ret = nvkm_device_tegra_power_up(tdev);
+ if (ret)
+- return ret;
++ goto remove;
+
+ tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value;
+ ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
+@@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_
+ cfg, dbg, detect, mmio, subdev_mask,
+ &tdev->device);
+ if (ret)
+- return ret;
++ goto powerdown;
++
++ *pdevice = &tdev->device;
+
+ return 0;
++
++powerdown:
++ nvkm_device_tegra_power_down(tdev);
++remove:
++ nvkm_device_tegra_remove_iommu(tdev);
++free:
++ kfree(tdev);
++ return ret;
+ }
+ #else
+ int
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c 2016-04-12 12:09:26.000000000 -0400
+@@ -328,6 +328,7 @@ nvkm_dp_train(struct work_struct *w)
+ .outp = outp,
+ }, *dp = &_dp;
+ u32 datarate = 0;
++ u8 pwr;
+ int ret;
+
+ if (!outp->base.info.location && disp->func->sor.magic)
+@@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w)
+ /* disable link interrupt handling during link training */
+ nvkm_notify_put(&outp->irq);
+
++ /* ensure sink is not in a low-power state */
++ if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
++ if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
++ pwr &= ~DPCD_SC00_SET_POWER;
++ pwr |= DPCD_SC00_SET_POWER_D0;
++ nvkm_wraux(outp->aux, DPCD_SC00, &pwr, 1);
++ }
++ }
++
+ /* enable down-spreading and execute pre-train script from vbios */
+ dp_link_train_init(dp, outp->dpcd[3] & 0x01);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
+--- linux-libre-4.4-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h 2016-04-12 12:09:26.000000000 -0400
+@@ -71,5 +71,11 @@
+ #define DPCD_LS0C_LANE1_POST_CURSOR2 0x0c
+ #define DPCD_LS0C_LANE0_POST_CURSOR2 0x03
+
++/* DPCD Sink Control */
++#define DPCD_SC00 0x00600
++#define DPCD_SC00_SET_POWER 0x03
++#define DPCD_SC00_SET_POWER_D0 0x01
++#define DPCD_SC00_SET_POWER_D3 0x03
++
+ void nvkm_dp_train(struct work_struct *);
+ #endif
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c linux-libre-4.4.7-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c 2016-04-12 12:09:26.000000000 -0400
+@@ -168,7 +168,8 @@ static int qxl_process_single_command(st
+ cmd->command_size))
+ return -EFAULT;
+
+- reloc_info = kmalloc(sizeof(struct qxl_reloc_info) * cmd->relocs_num, GFP_KERNEL);
++ reloc_info = kmalloc_array(cmd->relocs_num,
++ sizeof(struct qxl_reloc_info), GFP_KERNEL);
+ if (!reloc_info)
+ return -ENOMEM;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/atombios_encoders.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/atombios_encoders.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/atombios_encoders.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/atombios_encoders.c 2016-04-12 12:09:26.000000000 -0400
+@@ -892,8 +892,6 @@ atombios_dig_encoder_setup2(struct drm_e
+ else
+ args.v1.ucLaneNum = 4;
+
+- if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
+- args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+ switch (radeon_encoder->encoder_id) {
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+ args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
+@@ -910,6 +908,10 @@ atombios_dig_encoder_setup2(struct drm_e
+ args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+ else
+ args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
++
++ if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode) && (dp_clock == 270000))
++ args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
++
+ break;
+ case 2:
+ case 3:
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/dce6_afmt.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/dce6_afmt.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/dce6_afmt.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/dce6_afmt.c 2016-04-12 12:09:26.000000000 -0400
+@@ -301,6 +301,14 @@ void dce6_dp_audio_set_dto(struct radeon
+ * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+ */
+ if (ASIC_IS_DCE8(rdev)) {
++ unsigned int div = (RREG32(DENTIST_DISPCLK_CNTL) &
++ DENTIST_DPREFCLK_WDIVIDER_MASK) >>
++ DENTIST_DPREFCLK_WDIVIDER_SHIFT;
++ div = radeon_audio_decode_dfs_div(div);
++
++ if (div)
++ clock = clock * 100 / div;
++
+ WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000);
+ WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock);
+ } else {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/evergreend.h linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/evergreend.h
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/evergreend.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/evergreend.h 2016-04-12 12:09:26.000000000 -0400
+@@ -511,6 +511,11 @@
+ #define DCCG_AUDIO_DTO1_CNTL 0x05cc
+ # define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3)
+
++#define DCE41_DENTIST_DISPCLK_CNTL 0x049c
++# define DENTIST_DPREFCLK_WDIVIDER(x) (((x) & 0x7f) << 24)
++# define DENTIST_DPREFCLK_WDIVIDER_MASK (0x7f << 24)
++# define DENTIST_DPREFCLK_WDIVIDER_SHIFT 24
++
+ /* DCE 4.0 AFMT */
+ #define HDMI_CONTROL 0x7030
+ # define HDMI_KEEPOUT_MODE (1 << 0)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/evergreen_hdmi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -289,6 +289,16 @@ void dce4_dp_audio_set_dto(struct radeon
+ * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE
+ * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+ */
++ if (ASIC_IS_DCE41(rdev)) {
++ unsigned int div = (RREG32(DCE41_DENTIST_DISPCLK_CNTL) &
++ DENTIST_DPREFCLK_WDIVIDER_MASK) >>
++ DENTIST_DPREFCLK_WDIVIDER_SHIFT;
++ div = radeon_audio_decode_dfs_div(div);
++
++ if (div)
++ clock = 100 * clock / div;
++ }
++
+ WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
+ WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_atombios.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_atombios.c 2016-04-12 12:09:26.000000000 -0400
+@@ -437,7 +437,9 @@ static bool radeon_atom_apply_quirks(str
+ }
+
+ /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
+- if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) &&
++ if (((dev->pdev->device == 0x9802) ||
++ (dev->pdev->device == 0x9805) ||
++ (dev->pdev->device == 0x9806)) &&
+ (dev->pdev->subsystem_vendor == 0x1734) &&
+ (dev->pdev->subsystem_device == 0x11bd)) {
+ if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
+@@ -448,14 +450,6 @@ static bool radeon_atom_apply_quirks(str
+ }
+ }
+
+- /* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */
+- if ((dev->pdev->device == 0x9805) &&
+- (dev->pdev->subsystem_vendor == 0x1734) &&
+- (dev->pdev->subsystem_device == 0x11bd)) {
+- if (*connector_type == DRM_MODE_CONNECTOR_VGA)
+- return false;
+- }
+-
+ return true;
+ }
+
+@@ -1112,6 +1106,31 @@ union firmware_info {
+ ATOM_FIRMWARE_INFO_V2_2 info_22;
+ };
+
++union igp_info {
++ struct _ATOM_INTEGRATED_SYSTEM_INFO info;
++ struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
++ struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
++ struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
++ struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8;
++};
++
++static void radeon_atombios_get_dentist_vco_freq(struct radeon_device *rdev)
++{
++ struct radeon_mode_info *mode_info = &rdev->mode_info;
++ int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
++ union igp_info *igp_info;
++ u8 frev, crev;
++ u16 data_offset;
++
++ if (atom_parse_data_header(mode_info->atom_context, index, NULL,
++ &frev, &crev, &data_offset)) {
++ igp_info = (union igp_info *)(mode_info->atom_context->bios +
++ data_offset);
++ rdev->clock.vco_freq =
++ le32_to_cpu(igp_info->info_6.ulDentistVCOFreq);
++ }
++}
++
+ bool radeon_atom_get_clock_info(struct drm_device *dev)
+ {
+ struct radeon_device *rdev = dev->dev_private;
+@@ -1263,20 +1282,25 @@ bool radeon_atom_get_clock_info(struct d
+ rdev->mode_info.firmware_flags =
+ le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess);
+
++ if (ASIC_IS_DCE8(rdev))
++ rdev->clock.vco_freq =
++ le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq);
++ else if (ASIC_IS_DCE5(rdev))
++ rdev->clock.vco_freq = rdev->clock.current_dispclk;
++ else if (ASIC_IS_DCE41(rdev))
++ radeon_atombios_get_dentist_vco_freq(rdev);
++ else
++ rdev->clock.vco_freq = rdev->clock.current_dispclk;
++
++ if (rdev->clock.vco_freq == 0)
++ rdev->clock.vco_freq = 360000; /* 3.6 GHz */
++
+ return true;
+ }
+
+ return false;
+ }
+
+-union igp_info {
+- struct _ATOM_INTEGRATED_SYSTEM_INFO info;
+- struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
+- struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
+- struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
+- struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8;
+-};
+-
+ bool radeon_atombios_sideport_present(struct radeon_device *rdev)
+ {
+ struct radeon_mode_info *mode_info = &rdev->mode_info;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2016-04-12 12:09:26.000000000 -0400
+@@ -62,6 +62,10 @@ bool radeon_has_atpx(void) {
+ return radeon_atpx_priv.atpx_detected;
+ }
+
++bool radeon_has_atpx_dgpu_power_cntl(void) {
++ return radeon_atpx_priv.atpx.functions.power_cntl;
++}
++
+ /**
+ * radeon_atpx_call - call an ATPX method
+ *
+@@ -141,10 +145,6 @@ static void radeon_atpx_parse_functions(
+ */
+ static int radeon_atpx_validate(struct radeon_atpx *atpx)
+ {
+- /* make sure required functions are enabled */
+- /* dGPU power control is required */
+- atpx->functions.power_cntl = true;
+-
+ if (atpx->functions.px_params) {
+ union acpi_object *info;
+ struct atpx_px_params output;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_audio.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_audio.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_audio.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_audio.c 2016-04-12 12:09:26.000000000 -0400
+@@ -739,9 +739,6 @@ static void radeon_audio_dp_mode_set(str
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+- struct radeon_connector_atom_dig *dig_connector =
+- radeon_connector->con_priv;
+
+ if (!dig || !dig->afmt)
+ return;
+@@ -753,10 +750,7 @@ static void radeon_audio_dp_mode_set(str
+ radeon_audio_write_speaker_allocation(encoder);
+ radeon_audio_write_sad_regs(encoder);
+ radeon_audio_write_latency_fields(encoder, mode);
+- if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev))
+- radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
+- else
+- radeon_audio_set_dto(encoder, dig_connector->dp_clock);
++ radeon_audio_set_dto(encoder, rdev->clock.vco_freq * 10);
+ radeon_audio_set_audio_packet(encoder);
+ radeon_audio_select_pin(encoder);
+
+@@ -781,3 +775,15 @@ void radeon_audio_dpms(struct drm_encode
+ if (radeon_encoder->audio && radeon_encoder->audio->dpms)
+ radeon_encoder->audio->dpms(encoder, mode == DRM_MODE_DPMS_ON);
+ }
++
++unsigned int radeon_audio_decode_dfs_div(unsigned int div)
++{
++ if (div >= 8 && div < 64)
++ return (div - 8) * 25 + 200;
++ else if (div >= 64 && div < 96)
++ return (div - 64) * 50 + 1600;
++ else if (div >= 96 && div < 128)
++ return (div - 96) * 100 + 3200;
++ else
++ return 0;
++}
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_audio.h linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_audio.h
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_audio.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_audio.h 2016-04-12 12:09:26.000000000 -0400
+@@ -79,5 +79,6 @@ void radeon_audio_fini(struct radeon_dev
+ void radeon_audio_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode);
+ void radeon_audio_dpms(struct drm_encoder *encoder, int mode);
++unsigned int radeon_audio_decode_dfs_div(unsigned int div);
+
+ #endif
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_device.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_device.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_device.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_device.c 2016-04-12 12:09:26.000000000 -0400
+@@ -103,6 +103,12 @@ static const char radeon_family_name[][1
+ "LAST",
+ };
+
++#if defined(CONFIG_VGA_SWITCHEROO)
++bool radeon_has_atpx_dgpu_power_cntl(void);
++#else
++static inline bool radeon_has_atpx_dgpu_power_cntl(void) { return false; }
++#endif
++
+ #define RADEON_PX_QUIRK_DISABLE_PX (1 << 0)
+ #define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
+
+@@ -1433,7 +1439,7 @@ int radeon_device_init(struct radeon_dev
+ * ignore it */
+ vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
+
+- if (rdev->flags & RADEON_IS_PX)
++ if ((rdev->flags & RADEON_IS_PX) && radeon_has_atpx_dgpu_power_cntl())
+ runtime = true;
+ vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
+ if (runtime)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_display.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_display.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_display.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_display.c 2016-04-12 12:09:26.000000000 -0400
+@@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct
+ struct drm_crtc *crtc = &radeon_crtc->base;
+ unsigned long flags;
+ int r;
+- int vpos, hpos, stat, min_udelay;
++ int vpos, hpos, stat, min_udelay = 0;
++ unsigned repcnt = 4;
+ struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
+
+ down_read(&rdev->exclusive_lock);
+@@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct
+ * In practice this won't execute very often unless on very fast
+ * machines because the time window for this to happen is very small.
+ */
+- for (;;) {
++ while (radeon_crtc->enabled && --repcnt) {
+ /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
+ * start in hpos, and to the "fudged earlier" vblank start in
+ * vpos.
+@@ -470,12 +471,24 @@ static void radeon_flip_work_func(struct
+ break;
+
+ /* Sleep at least until estimated real start of hw vblank */
+- spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
++ if (min_udelay > vblank->framedur_ns / 2000) {
++ /* Don't wait ridiculously long - something is wrong */
++ repcnt = 0;
++ break;
++ }
++ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+ usleep_range(min_udelay, 2 * min_udelay);
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ };
+
++ if (!repcnt)
++ DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
++ "framedur %d, linedur %d, stat %d, vpos %d, "
++ "hpos %d\n", work->crtc_id, min_udelay,
++ vblank->framedur_ns / 1000,
++ vblank->linedur_ns / 1000, stat, vpos, hpos);
++
+ /* do the flip (mmio) */
+ radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon.h linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon.h
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon.h 2016-04-12 12:09:26.000000000 -0400
+@@ -268,6 +268,7 @@ struct radeon_clock {
+ uint32_t current_dispclk;
+ uint32_t dp_extclk;
+ uint32_t max_pixel_clock;
++ uint32_t vco_freq;
+ };
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_object.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_object.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_object.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_object.c 2016-04-12 12:09:26.000000000 -0400
+@@ -33,6 +33,7 @@
+ #include <linux/slab.h>
+ #include <drm/drmP.h>
+ #include <drm/radeon_drm.h>
++#include <drm/drm_cache.h>
+ #include "radeon.h"
+ #include "radeon_trace.h"
+
+@@ -245,6 +246,12 @@ int radeon_bo_create(struct radeon_devic
+ DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
+ "better performance thanks to write-combining\n");
+ bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
++#else
++ /* For architectures that don't support WC memory,
++ * mask out the WC flag from the BO
++ */
++ if (!drm_arch_can_wc_memory())
++ bo->flags &= ~RADEON_GEM_GTT_WC;
+ #endif
+
+ radeon_ttm_placement_from_domain(bo, domain);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_pm.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_pm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_pm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1078,10 +1078,6 @@ force:
+ /* update displays */
+ radeon_dpm_display_configuration_changed(rdev);
+
+- rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
+- rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
+- rdev->pm.dpm.single_display = single_display;
+-
+ /* wait for the rings to drain */
+ for (i = 0; i < RADEON_NUM_RINGS; i++) {
+ struct radeon_ring *ring = &rdev->ring[i];
+@@ -1097,6 +1093,10 @@ force:
+
+ radeon_dpm_post_set_power_state(rdev);
+
++ rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
++ rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
++ rdev->pm.dpm.single_display = single_display;
++
+ if (rdev->asic->dpm.force_performance_level) {
+ if (rdev->pm.dpm.thermal_active) {
+ enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_sa.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_sa.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_sa.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_sa.c 2016-04-12 12:09:26.000000000 -0400
+@@ -349,8 +349,13 @@ int radeon_sa_bo_new(struct radeon_devic
+ /* see if we can skip over some allocations */
+ } while (radeon_sa_bo_next_hole(sa_manager, fences, tries));
+
++ for (i = 0; i < RADEON_NUM_RINGS; ++i)
++ radeon_fence_ref(fences[i]);
++
+ spin_unlock(&sa_manager->wq.lock);
+ r = radeon_fence_wait_any(rdev, fences, false);
++ for (i = 0; i < RADEON_NUM_RINGS; ++i)
++ radeon_fence_unref(&fences[i]);
+ spin_lock(&sa_manager->wq.lock);
+ /* if we have nothing to wait for block */
+ if (r == -ENOENT) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_ttm.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_ttm.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_ttm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_ttm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -758,7 +758,7 @@ static int radeon_ttm_tt_populate(struct
+ 0, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) {
+- while (--i) {
++ while (i--) {
+ pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i],
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ gtt->ttm.dma_address[i] = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_vm.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_vm.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/radeon_vm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/radeon_vm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -455,15 +455,15 @@ int radeon_vm_bo_set_addr(struct radeon_
+
+ if (soffset) {
+ /* make sure object fit at this offset */
+- eoffset = soffset + size;
++ eoffset = soffset + size - 1;
+ if (soffset >= eoffset) {
+ r = -EINVAL;
+ goto error_unreserve;
+ }
+
+ last_pfn = eoffset / RADEON_GPU_PAGE_SIZE;
+- if (last_pfn > rdev->vm_manager.max_pfn) {
+- dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n",
++ if (last_pfn >= rdev->vm_manager.max_pfn) {
++ dev_err(rdev->dev, "va above limit (0x%08X >= 0x%08X)\n",
+ last_pfn, rdev->vm_manager.max_pfn);
+ r = -EINVAL;
+ goto error_unreserve;
+@@ -478,7 +478,7 @@ int radeon_vm_bo_set_addr(struct radeon_
+ eoffset /= RADEON_GPU_PAGE_SIZE;
+ if (soffset || eoffset) {
+ struct interval_tree_node *it;
+- it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
++ it = interval_tree_iter_first(&vm->va, soffset, eoffset);
+ if (it && it != &bo_va->it) {
+ struct radeon_bo_va *tmp;
+ tmp = container_of(it, struct radeon_bo_va, it);
+@@ -518,7 +518,7 @@ int radeon_vm_bo_set_addr(struct radeon_
+ if (soffset || eoffset) {
+ spin_lock(&vm->status_lock);
+ bo_va->it.start = soffset;
+- bo_va->it.last = eoffset - 1;
++ bo_va->it.last = eoffset;
+ list_add(&bo_va->vm_status, &vm->cleared);
+ spin_unlock(&vm->status_lock);
+ interval_tree_insert(&bo_va->it, &vm->va);
+@@ -888,7 +888,7 @@ static void radeon_vm_fence_pts(struct r
+ unsigned i;
+
+ start >>= radeon_vm_block_size;
+- end >>= radeon_vm_block_size;
++ end = (end - 1) >> radeon_vm_block_size;
+
+ for (i = start; i <= end; ++i)
+ radeon_bo_fence(vm->page_tables[i].bo, fence, true);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/sid.h linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/sid.h
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/sid.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/sid.h 2016-04-12 12:09:26.000000000 -0400
+@@ -915,6 +915,11 @@
+ #define DCCG_AUDIO_DTO1_PHASE 0x05c0
+ #define DCCG_AUDIO_DTO1_MODULE 0x05c4
+
++#define DENTIST_DISPCLK_CNTL 0x0490
++# define DENTIST_DPREFCLK_WDIVIDER(x) (((x) & 0x7f) << 24)
++# define DENTIST_DPREFCLK_WDIVIDER_MASK (0x7f << 24)
++# define DENTIST_DPREFCLK_WDIVIDER_SHIFT 24
++
+ #define AFMT_AUDIO_SRC_CONTROL 0x713c
+ #define AFMT_AUDIO_SRC_SELECT(x) (((x) & 7) << 0)
+ /* AFMT_AUDIO_SRC_SELECT
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/radeon/vce_v1_0.c linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/vce_v1_0.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/radeon/vce_v1_0.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/radeon/vce_v1_0.c 2016-04-12 12:09:26.000000000 -0400
+@@ -178,12 +178,12 @@ int vce_v1_0_load_fw(struct radeon_devic
+ return -EINVAL;
+ }
+
+- for (i = 0; i < sign->num; ++i) {
+- if (sign->val[i].chip_id == chip_id)
++ for (i = 0; i < le32_to_cpu(sign->num); ++i) {
++ if (le32_to_cpu(sign->val[i].chip_id) == chip_id)
+ break;
+ }
+
+- if (i == sign->num)
++ if (i == le32_to_cpu(sign->num))
+ return -EINVAL;
+
+ data += (256 - 64) / 4;
+@@ -191,18 +191,18 @@ int vce_v1_0_load_fw(struct radeon_devic
+ data[1] = sign->val[i].nonce[1];
+ data[2] = sign->val[i].nonce[2];
+ data[3] = sign->val[i].nonce[3];
+- data[4] = sign->len + 64;
++ data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64);
+
+ memset(&data[5], 0, 44);
+ memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign));
+
+- data += data[4] / 4;
++ data += le32_to_cpu(data[4]) / 4;
+ data[0] = sign->val[i].sigval[0];
+ data[1] = sign->val[i].sigval[1];
+ data[2] = sign->val[i].sigval[2];
+ data[3] = sign->val[i].sigval[3];
+
+- rdev->vce.keyselect = sign->val[i].keyselect;
++ rdev->vce.keyselect = le32_to_cpu(sign->val[i].keyselect);
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c linux-libre-4.4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c 2016-04-12 12:09:26.000000000 -0400
+@@ -247,7 +247,7 @@ static void __vmw_cmdbuf_header_free(str
+ {
+ struct vmw_cmdbuf_man *man = header->man;
+
+- BUG_ON(!spin_is_locked(&man->lock));
++ lockdep_assert_held_once(&man->lock);
+
+ if (header->inline_space) {
+ vmw_cmdbuf_header_inline_free(header);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c linux-libre-4.4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -25,6 +25,7 @@
+ *
+ **************************************************************************/
+ #include <linux/module.h>
++#include <linux/console.h>
+
+ #include <drm/drmP.h>
+ #include "vmwgfx_drv.h"
+@@ -1538,6 +1539,12 @@ static int vmw_probe(struct pci_dev *pde
+ static int __init vmwgfx_init(void)
+ {
+ int ret;
++
++#ifdef CONFIG_VGA_CONSOLE
++ if (vgacon_text_force())
++ return -EINVAL;
++#endif
++
+ ret = drm_pci_init(&driver, &vmw_pci_driver);
+ if (ret)
+ DRM_ERROR("Failed initializing DRM.\n");
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c linux-libre-4.4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+--- linux-libre-4.4-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 2016-04-12 12:09:26.000000000 -0400
+@@ -763,21 +763,25 @@ static int vmw_create_dmabuf_proxy(struc
+ uint32_t format;
+ struct drm_vmw_size content_base_size;
+ struct vmw_resource *res;
++ unsigned int bytes_pp;
+ int ret;
+
+ switch (mode_cmd->depth) {
+ case 32:
+ case 24:
+ format = SVGA3D_X8R8G8B8;
++ bytes_pp = 4;
+ break;
+
+ case 16:
+ case 15:
+ format = SVGA3D_R5G6B5;
++ bytes_pp = 2;
+ break;
+
+ case 8:
+ format = SVGA3D_P8;
++ bytes_pp = 1;
+ break;
+
+ default:
+@@ -785,7 +789,7 @@ static int vmw_create_dmabuf_proxy(struc
+ return -EINVAL;
+ }
+
+- content_base_size.width = mode_cmd->width;
++ content_base_size.width = mode_cmd->pitch / bytes_pp;
+ content_base_size.height = mode_cmd->height;
+ content_base_size.depth = 1;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/gpu/ipu-v3/ipu-common.c linux-libre-4.4.7-gnu/drivers/gpu/ipu-v3/ipu-common.c
+--- linux-libre-4.4-gnu/drivers/gpu/ipu-v3/ipu-common.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/gpu/ipu-v3/ipu-common.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1050,6 +1050,17 @@ static int ipu_add_client_devices(struct
+ for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
+ const struct ipu_platform_reg *reg = &client_reg[i];
+ struct platform_device *pdev;
++ struct device_node *of_node;
++
++ /* Associate subdevice with the corresponding port node */
++ of_node = of_graph_get_port_by_id(dev->of_node, i);
++ if (!of_node) {
++ dev_info(dev,
++ "no port@%d node in %s, not using %s%d\n",
++ i, dev->of_node->full_name,
++ (i / 2) ? "DI" : "CSI", i % 2);
++ continue;
++ }
+
+ pdev = platform_device_alloc(reg->name, id++);
+ if (!pdev) {
+@@ -1057,17 +1068,9 @@ static int ipu_add_client_devices(struct
+ goto err_register;
+ }
+
++ pdev->dev.of_node = of_node;
+ pdev->dev.parent = dev;
+
+- /* Associate subdevice with the corresponding port node */
+- pdev->dev.of_node = of_graph_get_port_by_id(dev->of_node, i);
+- if (!pdev->dev.of_node) {
+- dev_err(dev, "missing port@%d node in %s\n", i,
+- dev->of_node->full_name);
+- ret = -ENODEV;
+- goto err_register;
+- }
+-
+ ret = platform_device_add_data(pdev, &reg->pdata,
+ sizeof(reg->pdata));
+ if (!ret)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hid/hid-core.c linux-libre-4.4.7-gnu/drivers/hid/hid-core.c
+--- linux-libre-4.4-gnu/drivers/hid/hid-core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hid/hid-core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1897,6 +1897,7 @@ static const struct hid_device_id hid_ha
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
+@@ -2615,9 +2616,10 @@ int hid_add_device(struct hid_device *hd
+ /*
+ * Scan generic devices for group information
+ */
+- if (hid_ignore_special_drivers ||
+- (!hdev->group &&
+- !hid_match_id(hdev, hid_have_special_driver))) {
++ if (hid_ignore_special_drivers) {
++ hdev->group = HID_GROUP_GENERIC;
++ } else if (!hdev->group &&
++ !hid_match_id(hdev, hid_have_special_driver)) {
+ ret = hid_scan_report(hdev);
+ if (ret)
+ hid_warn(hdev, "bad device descriptor (%d)\n", ret);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hid/hid-multitouch.c linux-libre-4.4.7-gnu/drivers/hid/hid-multitouch.c
+--- linux-libre-4.4-gnu/drivers/hid/hid-multitouch.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hid/hid-multitouch.c 2016-04-12 12:09:26.000000000 -0400
+@@ -357,8 +357,19 @@ static void mt_feature_mapping(struct hi
+ break;
+ }
+
+- td->inputmode = field->report->id;
+- td->inputmode_index = usage->usage_index;
++ if (td->inputmode < 0) {
++ td->inputmode = field->report->id;
++ td->inputmode_index = usage->usage_index;
++ } else {
++ /*
++ * Some elan panels wrongly declare 2 input mode
++ * features, and silently ignore when we set the
++ * value in the second field. Skip the second feature
++ * and hope for the best.
++ */
++ dev_info(&hdev->dev,
++ "Ignoring the extra HID_DG_INPUTMODE\n");
++ }
+
+ break;
+ case HID_DG_CONTACTMAX:
+@@ -385,6 +396,11 @@ static void mt_feature_mapping(struct hi
+ td->is_buttonpad = true;
+
+ break;
++ case 0xff0000c5:
++ /* Retrieve the Win8 blob once to enable some devices */
++ if (usage->usage_index == 0)
++ mt_get_feature(hdev, field->report);
++ break;
+ }
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hid/i2c-hid/i2c-hid.c linux-libre-4.4.7-gnu/drivers/hid/i2c-hid/i2c-hid.c
+--- linux-libre-4.4-gnu/drivers/hid/i2c-hid/i2c-hid.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hid/i2c-hid/i2c-hid.c 2016-04-12 12:09:26.000000000 -0400
+@@ -282,17 +282,21 @@ static int i2c_hid_set_or_send_report(st
+ u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister);
+ u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister);
+ u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength);
++ u16 size;
++ int args_len;
++ int index = 0;
+
+- /* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */
+- u16 size = 2 /* size */ +
++ i2c_hid_dbg(ihid, "%s\n", __func__);
++
++ if (data_len > ihid->bufsize)
++ return -EINVAL;
++
++ size = 2 /* size */ +
+ (reportID ? 1 : 0) /* reportID */ +
+ data_len /* buf */;
+- int args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
++ args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ +
+ 2 /* dataRegister */ +
+ size /* args */;
+- int index = 0;
+-
+- i2c_hid_dbg(ihid, "%s\n", __func__);
+
+ if (!use_data && maxOutputLength == 0)
+ return -ENOSYS;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hid/usbhid/hid-core.c linux-libre-4.4.7-gnu/drivers/hid/usbhid/hid-core.c
+--- linux-libre-4.4-gnu/drivers/hid/usbhid/hid-core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hid/usbhid/hid-core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -477,8 +477,6 @@ static void hid_ctrl(struct urb *urb)
+ struct usbhid_device *usbhid = hid->driver_data;
+ int unplug = 0, status = urb->status;
+
+- spin_lock(&usbhid->lock);
+-
+ switch (status) {
+ case 0: /* success */
+ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+@@ -498,6 +496,8 @@ static void hid_ctrl(struct urb *urb)
+ hid_warn(urb->dev, "ctrl urb status %d received\n", status);
+ }
+
++ spin_lock(&usbhid->lock);
++
+ if (unplug) {
+ usbhid->ctrltail = usbhid->ctrlhead;
+ } else {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hv/channel.c linux-libre-4.4.7-gnu/drivers/hv/channel.c
+--- linux-libre-4.4-gnu/drivers/hv/channel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hv/channel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -630,10 +630,19 @@ int vmbus_sendpacket_ctl(struct vmbus_ch
+ * on the ring. We will not signal if more data is
+ * to be placed.
+ *
++ * Based on the channel signal state, we will decide
++ * which signaling policy will be applied.
++ *
+ * If we cannot write to the ring-buffer; signal the host
+ * even if we may not have written anything. This is a rare
+ * enough condition that it should not matter.
+ */
++
++ if (channel->signal_policy)
++ signal = true;
++ else
++ kick_q = true;
++
+ if (((ret == 0) && kick_q && signal) || (ret))
+ vmbus_setevent(channel);
+
+@@ -733,10 +742,19 @@ int vmbus_sendpacket_pagebuffer_ctl(stru
+ * on the ring. We will not signal if more data is
+ * to be placed.
+ *
++ * Based on the channel signal state, we will decide
++ * which signaling policy will be applied.
++ *
+ * If we cannot write to the ring-buffer; signal the host
+ * even if we may not have written anything. This is a rare
+ * enough condition that it should not matter.
+ */
++
++ if (channel->signal_policy)
++ signal = true;
++ else
++ kick_q = true;
++
+ if (((ret == 0) && kick_q && signal) || (ret))
+ vmbus_setevent(channel);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hwmon/ads1015.c linux-libre-4.4.7-gnu/drivers/hwmon/ads1015.c
+--- linux-libre-4.4-gnu/drivers/hwmon/ads1015.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hwmon/ads1015.c 2016-04-12 12:09:26.000000000 -0400
+@@ -126,7 +126,7 @@ static int ads1015_reg_to_mv(struct i2c_
+ struct ads1015_data *data = i2c_get_clientdata(client);
+ unsigned int pga = data->channel_data[channel].pga;
+ int fullscale = fullscale_table[pga];
+- const unsigned mask = data->id == ads1115 ? 0x7fff : 0x7ff0;
++ const int mask = data->id == ads1115 ? 0x7fff : 0x7ff0;
+
+ return DIV_ROUND_CLOSEST(reg * fullscale, mask);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hwmon/dell-smm-hwmon.c linux-libre-4.4.7-gnu/drivers/hwmon/dell-smm-hwmon.c
+--- linux-libre-4.4-gnu/drivers/hwmon/dell-smm-hwmon.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hwmon/dell-smm-hwmon.c 2016-04-12 12:09:26.000000000 -0400
+@@ -932,6 +932,17 @@ MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
+ static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
+ {
+ /*
++ * CPU fan speed going up and down on Dell Studio XPS 8000
++ * for unknown reasons.
++ */
++ .ident = "Dell Studio XPS 8000",
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8000"),
++ },
++ },
++ {
++ /*
+ * CPU fan speed going up and down on Dell Studio XPS 8100
+ * for unknown reasons.
+ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hwmon/gpio-fan.c linux-libre-4.4.7-gnu/drivers/hwmon/gpio-fan.c
+--- linux-libre-4.4-gnu/drivers/hwmon/gpio-fan.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hwmon/gpio-fan.c 2016-04-12 12:09:26.000000000 -0400
+@@ -406,16 +406,11 @@ static int gpio_fan_get_cur_state(struct
+ unsigned long *state)
+ {
+ struct gpio_fan_data *fan_data = cdev->devdata;
+- int r;
+
+ if (!fan_data)
+ return -EINVAL;
+
+- r = get_fan_speed_index(fan_data);
+- if (r < 0)
+- return r;
+-
+- *state = r;
++ *state = fan_data->speed_index;
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hwspinlock/hwspinlock_core.c linux-libre-4.4.7-gnu/drivers/hwspinlock/hwspinlock_core.c
+--- linux-libre-4.4-gnu/drivers/hwspinlock/hwspinlock_core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hwspinlock/hwspinlock_core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -313,6 +313,10 @@ int of_hwspin_lock_get_id(struct device_
+ hwlock = radix_tree_deref_slot(slot);
+ if (unlikely(!hwlock))
+ continue;
++ if (radix_tree_is_indirect_ptr(hwlock)) {
++ slot = radix_tree_iter_retry(&iter);
++ continue;
++ }
+
+ if (hwlock->bank->dev->of_node == args.np) {
+ ret = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/hwtracing/coresight/coresight.c linux-libre-4.4.7-gnu/drivers/hwtracing/coresight/coresight.c
+--- linux-libre-4.4-gnu/drivers/hwtracing/coresight/coresight.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/hwtracing/coresight/coresight.c 2016-04-12 12:09:26.000000000 -0400
+@@ -548,7 +548,7 @@ static int coresight_name_match(struct d
+ to_match = data;
+ i_csdev = to_coresight_device(dev);
+
+- if (!strcmp(to_match, dev_name(&i_csdev->dev)))
++ if (to_match && !strcmp(to_match, dev_name(&i_csdev->dev)))
+ return 1;
+
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/i2c/busses/i2c-brcmstb.c linux-libre-4.4.7-gnu/drivers/i2c/busses/i2c-brcmstb.c
+--- linux-libre-4.4-gnu/drivers/i2c/busses/i2c-brcmstb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/i2c/busses/i2c-brcmstb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -562,8 +562,7 @@ static int brcmstb_i2c_probe(struct plat
+ if (!dev)
+ return -ENOMEM;
+
+- dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(struct bsc_regs *),
+- GFP_KERNEL);
++ dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(*dev->bsc_regmap), GFP_KERNEL);
+ if (!dev->bsc_regmap)
+ return -ENOMEM;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/i2c/busses/i2c-i801.c linux-libre-4.4.7-gnu/drivers/i2c/busses/i2c-i801.c
+--- linux-libre-4.4-gnu/drivers/i2c/busses/i2c-i801.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/i2c/busses/i2c-i801.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1271,6 +1271,8 @@ static int i801_probe(struct pci_dev *de
+ switch (dev->device) {
+ case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS:
+ case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS:
++ case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS:
++ case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS:
+ case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
+ priv->features |= FEATURE_I2C_BLOCK_READ;
+ priv->features |= FEATURE_IRQ;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/idle/intel_idle.c linux-libre-4.4.7-gnu/drivers/idle/intel_idle.c
+--- linux-libre-4.4-gnu/drivers/idle/intel_idle.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/idle/intel_idle.c 2016-04-12 12:09:26.000000000 -0400
+@@ -65,7 +65,7 @@
+ #include <asm/mwait.h>
+ #include <asm/msr.h>
+
+-#define INTEL_IDLE_VERSION "0.4"
++#define INTEL_IDLE_VERSION "0.4.1"
+ #define PREFIX "intel_idle: "
+
+ static struct cpuidle_driver intel_idle_driver = {
+@@ -994,36 +994,92 @@ static void intel_idle_cpuidle_devices_u
+ }
+
+ /*
+- * intel_idle_state_table_update()
+- *
+- * Update the default state_table for this CPU-id
++ * ivt_idle_state_table_update(void)
+ *
+- * Currently used to access tuned IVT multi-socket targets
++ * Tune IVT multi-socket targets
+ * Assumption: num_sockets == (max_package_num + 1)
+ */
+-void intel_idle_state_table_update(void)
++static void ivt_idle_state_table_update(void)
+ {
+ /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */
+- if (boot_cpu_data.x86_model == 0x3e) { /* IVT */
+- int cpu, package_num, num_sockets = 1;
++ int cpu, package_num, num_sockets = 1;
+
+- for_each_online_cpu(cpu) {
+- package_num = topology_physical_package_id(cpu);
+- if (package_num + 1 > num_sockets) {
+- num_sockets = package_num + 1;
++ for_each_online_cpu(cpu) {
++ package_num = topology_physical_package_id(cpu);
++ if (package_num + 1 > num_sockets) {
++ num_sockets = package_num + 1;
+
+- if (num_sockets > 4) {
+- cpuidle_state_table = ivt_cstates_8s;
+- return;
+- }
++ if (num_sockets > 4) {
++ cpuidle_state_table = ivt_cstates_8s;
++ return;
+ }
+ }
++ }
+
+- if (num_sockets > 2)
+- cpuidle_state_table = ivt_cstates_4s;
+- /* else, 1 and 2 socket systems use default ivt_cstates */
++ if (num_sockets > 2)
++ cpuidle_state_table = ivt_cstates_4s;
++
++ /* else, 1 and 2 socket systems use default ivt_cstates */
++}
++/*
++ * sklh_idle_state_table_update(void)
++ *
++ * On SKL-H (model 0x5e) disable C8 and C9 if:
++ * C10 is enabled and SGX disabled
++ */
++static void sklh_idle_state_table_update(void)
++{
++ unsigned long long msr;
++ unsigned int eax, ebx, ecx, edx;
++
++
++ /* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */
++ if (max_cstate <= 7)
++ return;
++
++ /* if PC10 not present in CPUID.MWAIT.EDX */
++ if ((mwait_substates & (0xF << 28)) == 0)
++ return;
++
++ rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr);
++
++ /* PC10 is not enabled in PKG C-state limit */
++ if ((msr & 0xF) != 8)
++ return;
++
++ ecx = 0;
++ cpuid(7, &eax, &ebx, &ecx, &edx);
++
++ /* if SGX is present */
++ if (ebx & (1 << 2)) {
++
++ rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
++
++ /* if SGX is enabled */
++ if (msr & (1 << 18))
++ return;
++ }
++
++ skl_cstates[5].disabled = 1; /* C8-SKL */
++ skl_cstates[6].disabled = 1; /* C9-SKL */
++}
++/*
++ * intel_idle_state_table_update()
++ *
++ * Update the default state_table for this CPU-id
++ */
++
++static void intel_idle_state_table_update(void)
++{
++ switch (boot_cpu_data.x86_model) {
++
++ case 0x3e: /* IVT */
++ ivt_idle_state_table_update();
++ break;
++ case 0x5e: /* SKL-H */
++ sklh_idle_state_table_update();
++ break;
+ }
+- return;
+ }
+
+ /*
+@@ -1063,6 +1119,14 @@ static int __init intel_idle_cpuidle_dri
+ if (num_substates == 0)
+ continue;
+
++ /* if state marked as disabled, skip it */
++ if (cpuidle_state_table[cstate].disabled != 0) {
++ pr_debug(PREFIX "state %s is disabled",
++ cpuidle_state_table[cstate].name);
++ continue;
++ }
++
++
+ if (((mwait_cstate + 1) > 2) &&
+ !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+ mark_tsc_unstable("TSC halts in idle"
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/accel/Kconfig linux-libre-4.4.7-gnu/drivers/iio/accel/Kconfig
+--- linux-libre-4.4-gnu/drivers/iio/accel/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/accel/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -173,6 +173,7 @@ config STK8312
+ config STK8BA50
+ tristate "Sensortek STK8BA50 3-Axis Accelerometer Driver"
+ depends on I2C
++ depends on IIO_TRIGGER
+ help
+ Say yes here to get support for the Sensortek STK8BA50 3-axis
+ accelerometer.
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/adc/Kconfig linux-libre-4.4.7-gnu/drivers/iio/adc/Kconfig
+--- linux-libre-4.4-gnu/drivers/iio/adc/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/adc/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -372,6 +372,7 @@ config TWL6030_GPADC
+ config VF610_ADC
+ tristate "Freescale vf610 ADC driver"
+ depends on OF
++ depends on HAS_IOMEM
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/adc/ti_am335x_adc.c linux-libre-4.4.7-gnu/drivers/iio/adc/ti_am335x_adc.c
+--- linux-libre-4.4-gnu/drivers/iio/adc/ti_am335x_adc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/adc/ti_am335x_adc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -289,7 +289,7 @@ static int tiadc_iio_buffered_hardware_s
+ goto error_kfifo_free;
+
+ indio_dev->setup_ops = setup_ops;
+- indio_dev->modes |= INDIO_BUFFER_HARDWARE;
++ indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
+
+ return 0;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/dac/mcp4725.c linux-libre-4.4.7-gnu/drivers/iio/dac/mcp4725.c
+--- linux-libre-4.4-gnu/drivers/iio/dac/mcp4725.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/dac/mcp4725.c 2016-04-12 12:09:26.000000000 -0400
+@@ -300,6 +300,7 @@ static int mcp4725_probe(struct i2c_clie
+ data->client = client;
+
+ indio_dev->dev.parent = &client->dev;
++ indio_dev->name = id->name;
+ indio_dev->info = &mcp4725_info;
+ indio_dev->channels = &mcp4725_channel;
+ indio_dev->num_channels = 1;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/imu/adis_buffer.c linux-libre-4.4.7-gnu/drivers/iio/imu/adis_buffer.c
+--- linux-libre-4.4-gnu/drivers/iio/imu/adis_buffer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/imu/adis_buffer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -43,7 +43,7 @@ int adis_update_scan_mode(struct iio_dev
+ return -ENOMEM;
+
+ rx = adis->buffer;
+- tx = rx + indio_dev->scan_bytes;
++ tx = rx + scan_count;
+
+ spi_message_init(&adis->msg);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/inkern.c linux-libre-4.4.7-gnu/drivers/iio/inkern.c
+--- linux-libre-4.4-gnu/drivers/iio/inkern.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/inkern.c 2016-04-12 12:09:26.000000000 -0400
+@@ -351,6 +351,8 @@ EXPORT_SYMBOL_GPL(iio_channel_get);
+
+ void iio_channel_release(struct iio_channel *channel)
+ {
++ if (!channel)
++ return;
+ iio_device_put(channel->indio_dev);
+ kfree(channel);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/light/acpi-als.c linux-libre-4.4.7-gnu/drivers/iio/light/acpi-als.c
+--- linux-libre-4.4-gnu/drivers/iio/light/acpi-als.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/light/acpi-als.c 2016-04-12 12:09:26.000000000 -0400
+@@ -54,7 +54,9 @@ static const struct iio_chan_spec acpi_a
+ .realbits = 32,
+ .storagebits = 32,
+ },
+- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
++ /* _RAW is here for backward ABI compatibility */
++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
++ BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+ };
+
+@@ -152,7 +154,7 @@ static int acpi_als_read_raw(struct iio_
+ s32 temp_val;
+ int ret;
+
+- if (mask != IIO_CHAN_INFO_RAW)
++ if ((mask != IIO_CHAN_INFO_PROCESSED) && (mask != IIO_CHAN_INFO_RAW))
+ return -EINVAL;
+
+ /* we support only illumination (_ALI) so far. */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/light/ltr501.c linux-libre-4.4.7-gnu/drivers/iio/light/ltr501.c
+--- linux-libre-4.4-gnu/drivers/iio/light/ltr501.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/light/ltr501.c 2016-04-12 12:09:26.000000000 -0400
+@@ -180,7 +180,7 @@ static const struct ltr501_samp_table lt
+ {500000, 2000000}
+ };
+
+-static unsigned int ltr501_match_samp_freq(const struct ltr501_samp_table *tab,
++static int ltr501_match_samp_freq(const struct ltr501_samp_table *tab,
+ int len, int val, int val2)
+ {
+ int i, freq;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iio/pressure/mpl115.c linux-libre-4.4.7-gnu/drivers/iio/pressure/mpl115.c
+--- linux-libre-4.4-gnu/drivers/iio/pressure/mpl115.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iio/pressure/mpl115.c 2016-04-12 12:09:26.000000000 -0400
+@@ -117,7 +117,7 @@ static int mpl115_read_raw(struct iio_de
+ *val = ret >> 6;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_OFFSET:
+- *val = 605;
++ *val = -605;
+ *val2 = 750000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SCALE:
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/core/cma.c linux-libre-4.4.7-gnu/drivers/infiniband/core/cma.c
+--- linux-libre-4.4-gnu/drivers/infiniband/core/cma.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/core/cma.c 2016-04-12 12:09:26.000000000 -0400
+@@ -453,7 +453,7 @@ static inline int cma_validate_port(stru
+ if ((dev_type != ARPHRD_INFINIBAND) && rdma_protocol_ib(device, port))
+ return ret;
+
+- if (dev_type == ARPHRD_ETHER)
++ if (dev_type == ARPHRD_ETHER && rdma_protocol_roce(device, port))
+ ndev = dev_get_by_index(&init_net, bound_if_index);
+
+ ret = ib_find_cached_gid_by_port(device, gid, port, ndev, NULL);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/core/cm.c linux-libre-4.4.7-gnu/drivers/infiniband/core/cm.c
+--- linux-libre-4.4-gnu/drivers/infiniband/core/cm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/core/cm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -782,11 +782,11 @@ static void cm_enter_timewait(struct cm_
+ wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);
+
+ /* Check if the device started its remove_one */
+- spin_lock_irq(&cm.lock);
++ spin_lock_irqsave(&cm.lock, flags);
+ if (!cm_dev->going_down)
+ queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
+ msecs_to_jiffies(wait_time));
+- spin_unlock_irq(&cm.lock);
++ spin_unlock_irqrestore(&cm.lock, flags);
+
+ cm_id_priv->timewait_info = NULL;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c linux-libre-4.4.7-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c
+--- linux-libre-4.4-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -149,7 +149,7 @@ static int iwch_l2t_send(struct t3cdev *
+ error = l2t_send(tdev, skb, l2e);
+ if (error < 0)
+ kfree_skb(skb);
+- return error;
++ return error < 0 ? error : 0;
+ }
+
+ int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb)
+@@ -165,7 +165,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *
+ error = cxgb3_ofld_send(tdev, skb);
+ if (error < 0)
+ kfree_skb(skb);
+- return error;
++ return error < 0 ? error : 0;
+ }
+
+ static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/hw/mlx5/cq.c linux-libre-4.4.7-gnu/drivers/infiniband/hw/mlx5/cq.c
+--- linux-libre-4.4-gnu/drivers/infiniband/hw/mlx5/cq.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/hw/mlx5/cq.c 2016-04-12 12:09:26.000000000 -0400
+@@ -756,7 +756,7 @@ struct ib_cq *mlx5_ib_create_cq(struct i
+ int uninitialized_var(index);
+ int uninitialized_var(inlen);
+ int cqe_size;
+- int irqn;
++ unsigned int irqn;
+ int eqn;
+ int err;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/hw/mlx5/main.c linux-libre-4.4.7-gnu/drivers/infiniband/hw/mlx5/main.c
+--- linux-libre-4.4-gnu/drivers/infiniband/hw/mlx5/main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/hw/mlx5/main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -275,7 +275,7 @@ static int mlx5_ib_query_device(struct i
+ props->max_sge = min(max_rq_sg, max_sq_sg);
+ props->max_sge_rd = props->max_sge;
+ props->max_cq = 1 << MLX5_CAP_GEN(mdev, log_max_cq);
+- props->max_cqe = (1 << MLX5_CAP_GEN(mdev, log_max_eq_sz)) - 1;
++ props->max_cqe = (1 << MLX5_CAP_GEN(mdev, log_max_cq_sz)) - 1;
+ props->max_mr = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
+ props->max_pd = 1 << MLX5_CAP_GEN(mdev, log_max_pd);
+ props->max_qp_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_req_qp);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/hw/qib/qib_qp.c linux-libre-4.4.7-gnu/drivers/infiniband/hw/qib/qib_qp.c
+--- linux-libre-4.4-gnu/drivers/infiniband/hw/qib/qib_qp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/hw/qib/qib_qp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -100,9 +100,10 @@ static u32 credit_table[31] = {
+ 32768 /* 1E */
+ };
+
+-static void get_map_page(struct qib_qpn_table *qpt, struct qpn_map *map)
++static void get_map_page(struct qib_qpn_table *qpt, struct qpn_map *map,
++ gfp_t gfp)
+ {
+- unsigned long page = get_zeroed_page(GFP_KERNEL);
++ unsigned long page = get_zeroed_page(gfp);
+
+ /*
+ * Free the page if someone raced with us installing it.
+@@ -121,7 +122,7 @@ static void get_map_page(struct qib_qpn_
+ * zero/one for QP type IB_QPT_SMI/IB_QPT_GSI.
+ */
+ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt,
+- enum ib_qp_type type, u8 port)
++ enum ib_qp_type type, u8 port, gfp_t gfp)
+ {
+ u32 i, offset, max_scan, qpn;
+ struct qpn_map *map;
+@@ -151,7 +152,7 @@ static int alloc_qpn(struct qib_devdata
+ max_scan = qpt->nmaps - !offset;
+ for (i = 0;;) {
+ if (unlikely(!map->page)) {
+- get_map_page(qpt, map);
++ get_map_page(qpt, map, gfp);
+ if (unlikely(!map->page))
+ break;
+ }
+@@ -983,13 +984,21 @@ struct ib_qp *qib_create_qp(struct ib_pd
+ size_t sz;
+ size_t sg_list_sz;
+ struct ib_qp *ret;
++ gfp_t gfp;
++
+
+ if (init_attr->cap.max_send_sge > ib_qib_max_sges ||
+ init_attr->cap.max_send_wr > ib_qib_max_qp_wrs ||
+- init_attr->create_flags) {
+- ret = ERR_PTR(-EINVAL);
+- goto bail;
+- }
++ init_attr->create_flags & ~(IB_QP_CREATE_USE_GFP_NOIO))
++ return ERR_PTR(-EINVAL);
++
++ /* GFP_NOIO is applicable in RC QPs only */
++ if (init_attr->create_flags & IB_QP_CREATE_USE_GFP_NOIO &&
++ init_attr->qp_type != IB_QPT_RC)
++ return ERR_PTR(-EINVAL);
++
++ gfp = init_attr->create_flags & IB_QP_CREATE_USE_GFP_NOIO ?
++ GFP_NOIO : GFP_KERNEL;
+
+ /* Check receive queue parameters if no SRQ is specified. */
+ if (!init_attr->srq) {
+@@ -1021,7 +1030,8 @@ struct ib_qp *qib_create_qp(struct ib_pd
+ sz = sizeof(struct qib_sge) *
+ init_attr->cap.max_send_sge +
+ sizeof(struct qib_swqe);
+- swq = vmalloc((init_attr->cap.max_send_wr + 1) * sz);
++ swq = __vmalloc((init_attr->cap.max_send_wr + 1) * sz,
++ gfp, PAGE_KERNEL);
+ if (swq == NULL) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail;
+@@ -1037,13 +1047,13 @@ struct ib_qp *qib_create_qp(struct ib_pd
+ } else if (init_attr->cap.max_recv_sge > 1)
+ sg_list_sz = sizeof(*qp->r_sg_list) *
+ (init_attr->cap.max_recv_sge - 1);
+- qp = kzalloc(sz + sg_list_sz, GFP_KERNEL);
++ qp = kzalloc(sz + sg_list_sz, gfp);
+ if (!qp) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail_swq;
+ }
+ RCU_INIT_POINTER(qp->next, NULL);
+- qp->s_hdr = kzalloc(sizeof(*qp->s_hdr), GFP_KERNEL);
++ qp->s_hdr = kzalloc(sizeof(*qp->s_hdr), gfp);
+ if (!qp->s_hdr) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail_qp;
+@@ -1058,8 +1068,16 @@ struct ib_qp *qib_create_qp(struct ib_pd
+ qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
+ sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) +
+ sizeof(struct qib_rwqe);
+- qp->r_rq.wq = vmalloc_user(sizeof(struct qib_rwq) +
+- qp->r_rq.size * sz);
++ if (gfp != GFP_NOIO)
++ qp->r_rq.wq = vmalloc_user(
++ sizeof(struct qib_rwq) +
++ qp->r_rq.size * sz);
++ else
++ qp->r_rq.wq = __vmalloc(
++ sizeof(struct qib_rwq) +
++ qp->r_rq.size * sz,
++ gfp, PAGE_KERNEL);
++
+ if (!qp->r_rq.wq) {
+ ret = ERR_PTR(-ENOMEM);
+ goto bail_qp;
+@@ -1090,7 +1108,7 @@ struct ib_qp *qib_create_qp(struct ib_pd
+ dev = to_idev(ibpd->device);
+ dd = dd_from_dev(dev);
+ err = alloc_qpn(dd, &dev->qpn_table, init_attr->qp_type,
+- init_attr->port_num);
++ init_attr->port_num, gfp);
+ if (err < 0) {
+ ret = ERR_PTR(err);
+ vfree(qp->r_rq.wq);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/hw/qib/qib_verbs_mcast.c linux-libre-4.4.7-gnu/drivers/infiniband/hw/qib/qib_verbs_mcast.c
+--- linux-libre-4.4-gnu/drivers/infiniband/hw/qib/qib_verbs_mcast.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/hw/qib/qib_verbs_mcast.c 2016-04-12 12:09:26.000000000 -0400
+@@ -286,15 +286,13 @@ int qib_multicast_detach(struct ib_qp *i
+ struct qib_ibdev *dev = to_idev(ibqp->device);
+ struct qib_ibport *ibp = to_iport(ibqp->device, qp->port_num);
+ struct qib_mcast *mcast = NULL;
+- struct qib_mcast_qp *p, *tmp;
++ struct qib_mcast_qp *p, *tmp, *delp = NULL;
+ struct rb_node *n;
+ int last = 0;
+ int ret;
+
+- if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET) {
+- ret = -EINVAL;
+- goto bail;
+- }
++ if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET)
++ return -EINVAL;
+
+ spin_lock_irq(&ibp->lock);
+
+@@ -303,8 +301,7 @@ int qib_multicast_detach(struct ib_qp *i
+ while (1) {
+ if (n == NULL) {
+ spin_unlock_irq(&ibp->lock);
+- ret = -EINVAL;
+- goto bail;
++ return -EINVAL;
+ }
+
+ mcast = rb_entry(n, struct qib_mcast, rb_node);
+@@ -328,6 +325,7 @@ int qib_multicast_detach(struct ib_qp *i
+ */
+ list_del_rcu(&p->list);
+ mcast->n_attached--;
++ delp = p;
+
+ /* If this was the last attached QP, remove the GID too. */
+ if (list_empty(&mcast->qp_list)) {
+@@ -338,15 +336,16 @@ int qib_multicast_detach(struct ib_qp *i
+ }
+
+ spin_unlock_irq(&ibp->lock);
++ /* QP not attached */
++ if (!delp)
++ return -EINVAL;
++ /*
++ * Wait for any list walkers to finish before freeing the
++ * list element.
++ */
++ wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
++ qib_mcast_qp_free(delp);
+
+- if (p) {
+- /*
+- * Wait for any list walkers to finish before freeing the
+- * list element.
+- */
+- wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
+- qib_mcast_qp_free(p);
+- }
+ if (last) {
+ atomic_dec(&mcast->refcount);
+ wait_event(mcast->wait, !atomic_read(&mcast->refcount));
+@@ -355,11 +354,7 @@ int qib_multicast_detach(struct ib_qp *i
+ dev->n_mcast_grps_allocated--;
+ spin_unlock_irq(&dev->n_mcast_grps_lock);
+ }
+-
+- ret = 0;
+-
+-bail:
+- return ret;
++ return 0;
+ }
+
+ int qib_mcast_tree_empty(struct qib_ibport *ibp)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-libre-4.4.7-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+--- linux-libre-4.4-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2016-04-12 12:09:26.000000000 -0400
+@@ -456,7 +456,10 @@ out_locked:
+ return status;
+ }
+
+-static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
++/*
++ * Caller must hold 'priv->lock'
++ */
++static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
+ {
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+ struct ib_sa_multicast *multicast;
+@@ -466,6 +469,10 @@ static void ipoib_mcast_join(struct net_
+ ib_sa_comp_mask comp_mask;
+ int ret = 0;
+
++ if (!priv->broadcast ||
++ !test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
++ return -EINVAL;
++
+ ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw);
+
+ rec.mgid = mcast->mcmember.mgid;
+@@ -525,20 +532,23 @@ static void ipoib_mcast_join(struct net_
+ rec.join_state = 4;
+ #endif
+ }
++ spin_unlock_irq(&priv->lock);
+
+ multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
+ &rec, comp_mask, GFP_KERNEL,
+ ipoib_mcast_join_complete, mcast);
++ spin_lock_irq(&priv->lock);
+ if (IS_ERR(multicast)) {
+ ret = PTR_ERR(multicast);
+ ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
+- spin_lock_irq(&priv->lock);
+ /* Requeue this join task with a backoff delay */
+ __ipoib_mcast_schedule_join_thread(priv, mcast, 1);
+ clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+ spin_unlock_irq(&priv->lock);
+ complete(&mcast->done);
++ spin_lock_irq(&priv->lock);
+ }
++ return 0;
+ }
+
+ void ipoib_mcast_join_task(struct work_struct *work)
+@@ -620,9 +630,10 @@ void ipoib_mcast_join_task(struct work_s
+ /* Found the next unjoined group */
+ init_completion(&mcast->done);
+ set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+- spin_unlock_irq(&priv->lock);
+- ipoib_mcast_join(dev, mcast);
+- spin_lock_irq(&priv->lock);
++ if (ipoib_mcast_join(dev, mcast)) {
++ spin_unlock_irq(&priv->lock);
++ return;
++ }
+ } else if (!delay_until ||
+ time_before(mcast->delay_until, delay_until))
+ delay_until = mcast->delay_until;
+@@ -641,10 +652,9 @@ out:
+ if (mcast) {
+ init_completion(&mcast->done);
+ set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
++ ipoib_mcast_join(dev, mcast);
+ }
+ spin_unlock_irq(&priv->lock);
+- if (mcast)
+- ipoib_mcast_join(dev, mcast);
+ }
+
+ int ipoib_mcast_start_thread(struct net_device *dev)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/ulp/isert/ib_isert.c linux-libre-4.4.7-gnu/drivers/infiniband/ulp/isert/ib_isert.c
+--- linux-libre-4.4-gnu/drivers/infiniband/ulp/isert/ib_isert.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/ulp/isert/ib_isert.c 2016-04-12 12:09:26.000000000 -0400
+@@ -66,6 +66,7 @@ isert_rdma_accept(struct isert_conn *ise
+ struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np);
+
+ static void isert_release_work(struct work_struct *work);
++static void isert_wait4flush(struct isert_conn *isert_conn);
+
+ static inline bool
+ isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
+@@ -815,12 +816,31 @@ isert_put_conn(struct isert_conn *isert_
+ kref_put(&isert_conn->kref, isert_release_kref);
+ }
+
++static void
++isert_handle_unbound_conn(struct isert_conn *isert_conn)
++{
++ struct isert_np *isert_np = isert_conn->cm_id->context;
++
++ mutex_lock(&isert_np->mutex);
++ if (!list_empty(&isert_conn->node)) {
++ /*
++ * This means iscsi doesn't know this connection
++ * so schedule a cleanup ourselves
++ */
++ list_del_init(&isert_conn->node);
++ isert_put_conn(isert_conn);
++ complete(&isert_conn->wait);
++ queue_work(isert_release_wq, &isert_conn->release_work);
++ }
++ mutex_unlock(&isert_np->mutex);
++}
++
+ /**
+ * isert_conn_terminate() - Initiate connection termination
+ * @isert_conn: isert connection struct
+ *
+ * Notes:
+- * In case the connection state is FULL_FEATURE, move state
++ * In case the connection state is BOUND, move state
+ * to TEMINATING and start teardown sequence (rdma_disconnect).
+ * In case the connection state is UP, complete flush as well.
+ *
+@@ -832,23 +852,19 @@ isert_conn_terminate(struct isert_conn *
+ {
+ int err;
+
+- switch (isert_conn->state) {
+- case ISER_CONN_TERMINATING:
+- break;
+- case ISER_CONN_UP:
+- case ISER_CONN_FULL_FEATURE: /* FALLTHRU */
+- isert_info("Terminating conn %p state %d\n",
+- isert_conn, isert_conn->state);
+- isert_conn->state = ISER_CONN_TERMINATING;
+- err = rdma_disconnect(isert_conn->cm_id);
+- if (err)
+- isert_warn("Failed rdma_disconnect isert_conn %p\n",
+- isert_conn);
+- break;
+- default:
+- isert_warn("conn %p teminating in state %d\n",
+- isert_conn, isert_conn->state);
+- }
++ if (isert_conn->state >= ISER_CONN_TERMINATING)
++ return;
++
++ isert_info("Terminating conn %p state %d\n",
++ isert_conn, isert_conn->state);
++ isert_conn->state = ISER_CONN_TERMINATING;
++ err = rdma_disconnect(isert_conn->cm_id);
++ if (err)
++ isert_warn("Failed rdma_disconnect isert_conn %p\n",
++ isert_conn);
++
++ isert_info("conn %p completing wait\n", isert_conn);
++ complete(&isert_conn->wait);
+ }
+
+ static int
+@@ -882,35 +898,27 @@ static int
+ isert_disconnected_handler(struct rdma_cm_id *cma_id,
+ enum rdma_cm_event_type event)
+ {
+- struct isert_np *isert_np = cma_id->context;
+- struct isert_conn *isert_conn;
+- bool terminating = false;
+-
+- if (isert_np->cm_id == cma_id)
+- return isert_np_cma_handler(cma_id->context, event);
+-
+- isert_conn = cma_id->qp->qp_context;
++ struct isert_conn *isert_conn = cma_id->qp->qp_context;
+
+ mutex_lock(&isert_conn->mutex);
+- terminating = (isert_conn->state == ISER_CONN_TERMINATING);
+- isert_conn_terminate(isert_conn);
+- mutex_unlock(&isert_conn->mutex);
+-
+- isert_info("conn %p completing wait\n", isert_conn);
+- complete(&isert_conn->wait);
+-
+- if (terminating)
+- goto out;
+-
+- mutex_lock(&isert_np->mutex);
+- if (!list_empty(&isert_conn->node)) {
+- list_del_init(&isert_conn->node);
+- isert_put_conn(isert_conn);
+- queue_work(isert_release_wq, &isert_conn->release_work);
++ switch (isert_conn->state) {
++ case ISER_CONN_TERMINATING:
++ break;
++ case ISER_CONN_UP:
++ isert_conn_terminate(isert_conn);
++ isert_wait4flush(isert_conn);
++ isert_handle_unbound_conn(isert_conn);
++ break;
++ case ISER_CONN_BOUND:
++ case ISER_CONN_FULL_FEATURE: /* FALLTHRU */
++ iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
++ break;
++ default:
++ isert_warn("conn %p teminating in state %d\n",
++ isert_conn, isert_conn->state);
+ }
+- mutex_unlock(&isert_np->mutex);
++ mutex_unlock(&isert_conn->mutex);
+
+-out:
+ return 0;
+ }
+
+@@ -929,12 +937,16 @@ isert_connect_error(struct rdma_cm_id *c
+ static int
+ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+ {
++ struct isert_np *isert_np = cma_id->context;
+ int ret = 0;
+
+ isert_info("%s (%d): status %d id %p np %p\n",
+ rdma_event_msg(event->event), event->event,
+ event->status, cma_id, cma_id->context);
+
++ if (isert_np->cm_id == cma_id)
++ return isert_np_cma_handler(cma_id->context, event->event);
++
+ switch (event->event) {
+ case RDMA_CM_EVENT_CONNECT_REQUEST:
+ ret = isert_connect_request(cma_id, event);
+@@ -980,13 +992,10 @@ isert_post_recvm(struct isert_conn *iser
+ rx_wr--;
+ rx_wr->next = NULL; /* mark end of work requests list */
+
+- isert_conn->post_recv_buf_count += count;
+ ret = ib_post_recv(isert_conn->qp, isert_conn->rx_wr,
+ &rx_wr_failed);
+- if (ret) {
++ if (ret)
+ isert_err("ib_post_recv() failed with ret: %d\n", ret);
+- isert_conn->post_recv_buf_count -= count;
+- }
+
+ return ret;
+ }
+@@ -1002,12 +1011,9 @@ isert_post_recv(struct isert_conn *isert
+ rx_wr.num_sge = 1;
+ rx_wr.next = NULL;
+
+- isert_conn->post_recv_buf_count++;
+ ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_failed);
+- if (ret) {
++ if (ret)
+ isert_err("ib_post_recv() failed with ret: %d\n", ret);
+- isert_conn->post_recv_buf_count--;
+- }
+
+ return ret;
+ }
+@@ -1120,12 +1126,9 @@ isert_rdma_post_recvl(struct isert_conn
+ rx_wr.sg_list = &sge;
+ rx_wr.num_sge = 1;
+
+- isert_conn->post_recv_buf_count++;
+ ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_fail);
+- if (ret) {
++ if (ret)
+ isert_err("ib_post_recv() failed: %d\n", ret);
+- isert_conn->post_recv_buf_count--;
+- }
+
+ return ret;
+ }
+@@ -1620,7 +1623,6 @@ isert_rcv_completion(struct iser_rx_desc
+ ib_dma_sync_single_for_device(ib_dev, rx_dma, rx_buflen,
+ DMA_FROM_DEVICE);
+
+- isert_conn->post_recv_buf_count--;
+ }
+
+ static int
+@@ -2035,7 +2037,8 @@ is_isert_tx_desc(struct isert_conn *iser
+ void *start = isert_conn->rx_descs;
+ int len = ISERT_QP_MAX_RECV_DTOS * sizeof(*isert_conn->rx_descs);
+
+- if (wr_id >= start && wr_id < start + len)
++ if ((wr_id >= start && wr_id < start + len) ||
++ (wr_id == isert_conn->login_req_buf))
+ return false;
+
+ return true;
+@@ -2059,10 +2062,6 @@ isert_cq_comp_err(struct isert_conn *ise
+ isert_unmap_tx_desc(desc, ib_dev);
+ else
+ isert_completion_put(desc, isert_cmd, ib_dev, true);
+- } else {
+- isert_conn->post_recv_buf_count--;
+- if (!isert_conn->post_recv_buf_count)
+- iscsit_cause_connection_reinstatement(isert_conn->conn, 0);
+ }
+ }
+
+@@ -3193,6 +3192,7 @@ accept_wait:
+
+ conn->context = isert_conn;
+ isert_conn->conn = conn;
++ isert_conn->state = ISER_CONN_BOUND;
+
+ isert_set_conn_info(np, conn, isert_conn);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/ulp/isert/ib_isert.h linux-libre-4.4.7-gnu/drivers/infiniband/ulp/isert/ib_isert.h
+--- linux-libre-4.4-gnu/drivers/infiniband/ulp/isert/ib_isert.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/ulp/isert/ib_isert.h 2016-04-12 12:09:26.000000000 -0400
+@@ -50,6 +50,7 @@ enum iser_ib_op_code {
+ enum iser_conn_state {
+ ISER_CONN_INIT,
+ ISER_CONN_UP,
++ ISER_CONN_BOUND,
+ ISER_CONN_FULL_FEATURE,
+ ISER_CONN_TERMINATING,
+ ISER_CONN_DOWN,
+@@ -144,7 +145,6 @@ struct isert_device;
+
+ struct isert_conn {
+ enum iser_conn_state state;
+- int post_recv_buf_count;
+ u32 responder_resources;
+ u32 initiator_depth;
+ bool pi_support;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c linux-libre-4.4.7-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c
+--- linux-libre-4.4-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1737,47 +1737,6 @@ send_sense:
+ return -1;
+ }
+
+-/**
+- * srpt_rx_mgmt_fn_tag() - Process a task management function by tag.
+- * @ch: RDMA channel of the task management request.
+- * @fn: Task management function to perform.
+- * @req_tag: Tag of the SRP task management request.
+- * @mgmt_ioctx: I/O context of the task management request.
+- *
+- * Returns zero if the target core will process the task management
+- * request asynchronously.
+- *
+- * Note: It is assumed that the initiator serializes tag-based task management
+- * requests.
+- */
+-static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag)
+-{
+- struct srpt_device *sdev;
+- struct srpt_rdma_ch *ch;
+- struct srpt_send_ioctx *target;
+- int ret, i;
+-
+- ret = -EINVAL;
+- ch = ioctx->ch;
+- BUG_ON(!ch);
+- BUG_ON(!ch->sport);
+- sdev = ch->sport->sdev;
+- BUG_ON(!sdev);
+- spin_lock_irq(&sdev->spinlock);
+- for (i = 0; i < ch->rq_size; ++i) {
+- target = ch->ioctx_ring[i];
+- if (target->cmd.se_lun == ioctx->cmd.se_lun &&
+- target->cmd.tag == tag &&
+- srpt_get_cmd_state(target) != SRPT_STATE_DONE) {
+- ret = 0;
+- /* now let the target core abort &target->cmd; */
+- break;
+- }
+- }
+- spin_unlock_irq(&sdev->spinlock);
+- return ret;
+-}
+-
+ static int srp_tmr_to_tcm(int fn)
+ {
+ switch (fn) {
+@@ -1812,7 +1771,6 @@ static void srpt_handle_tsk_mgmt(struct
+ struct se_cmd *cmd;
+ struct se_session *sess = ch->sess;
+ uint64_t unpacked_lun;
+- uint32_t tag = 0;
+ int tcm_tmr;
+ int rc;
+
+@@ -1828,25 +1786,10 @@ static void srpt_handle_tsk_mgmt(struct
+ srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT);
+ send_ioctx->cmd.tag = srp_tsk->tag;
+ tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);
+- if (tcm_tmr < 0) {
+- send_ioctx->cmd.se_tmr_req->response =
+- TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
+- goto fail;
+- }
+ unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,
+ sizeof(srp_tsk->lun));
+-
+- if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) {
+- rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);
+- if (rc < 0) {
+- send_ioctx->cmd.se_tmr_req->response =
+- TMR_TASK_DOES_NOT_EXIST;
+- goto fail;
+- }
+- tag = srp_tsk->task_tag;
+- }
+ rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun,
+- srp_tsk, tcm_tmr, GFP_KERNEL, tag,
++ srp_tsk, tcm_tmr, GFP_KERNEL, srp_tsk->task_tag,
+ TARGET_SCF_ACK_KREF);
+ if (rc != 0) {
+ send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/input/misc/ati_remote2.c linux-libre-4.4.7-gnu/drivers/input/misc/ati_remote2.c
+--- linux-libre-4.4-gnu/drivers/input/misc/ati_remote2.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/input/misc/ati_remote2.c 2016-04-12 12:09:26.000000000 -0400
+@@ -817,26 +817,49 @@ static int ati_remote2_probe(struct usb_
+
+ ar2->udev = udev;
+
++ /* Sanity check, first interface must have an endpoint */
++ if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) {
++ dev_err(&interface->dev,
++ "%s(): interface 0 must have an endpoint\n", __func__);
++ r = -ENODEV;
++ goto fail1;
++ }
+ ar2->intf[0] = interface;
+ ar2->ep[0] = &alt->endpoint[0].desc;
+
++ /* Sanity check, the device must have two interfaces */
+ ar2->intf[1] = usb_ifnum_to_if(udev, 1);
++ if ((udev->actconfig->desc.bNumInterfaces < 2) || !ar2->intf[1]) {
++ dev_err(&interface->dev, "%s(): need 2 interfaces, found %d\n",
++ __func__, udev->actconfig->desc.bNumInterfaces);
++ r = -ENODEV;
++ goto fail1;
++ }
++
+ r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2);
+ if (r)
+ goto fail1;
++
++ /* Sanity check, second interface must have an endpoint */
+ alt = ar2->intf[1]->cur_altsetting;
++ if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) {
++ dev_err(&interface->dev,
++ "%s(): interface 1 must have an endpoint\n", __func__);
++ r = -ENODEV;
++ goto fail2;
++ }
+ ar2->ep[1] = &alt->endpoint[0].desc;
+
+ r = ati_remote2_urb_init(ar2);
+ if (r)
+- goto fail2;
++ goto fail3;
+
+ ar2->channel_mask = channel_mask;
+ ar2->mode_mask = mode_mask;
+
+ r = ati_remote2_setup(ar2, ar2->channel_mask);
+ if (r)
+- goto fail2;
++ goto fail3;
+
+ usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
+ strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
+@@ -845,11 +868,11 @@ static int ati_remote2_probe(struct usb_
+
+ r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group);
+ if (r)
+- goto fail2;
++ goto fail3;
+
+ r = ati_remote2_input_init(ar2);
+ if (r)
+- goto fail3;
++ goto fail4;
+
+ usb_set_intfdata(interface, ar2);
+
+@@ -857,10 +880,11 @@ static int ati_remote2_probe(struct usb_
+
+ return 0;
+
+- fail3:
++ fail4:
+ sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group);
+- fail2:
++ fail3:
+ ati_remote2_urb_cleanup(ar2);
++ fail2:
+ usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
+ fail1:
+ kfree(ar2);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/input/misc/ims-pcu.c linux-libre-4.4.7-gnu/drivers/input/misc/ims-pcu.c
+--- linux-libre-4.4-gnu/drivers/input/misc/ims-pcu.c 2016-01-10 21:13:24.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/input/misc/ims-pcu.c 2016-04-12 21:29:44.000000000 -0400
+@@ -1663,6 +1663,8 @@ static int ims_pcu_parse_cdc_data(struct
+
+ pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev,
+ union_desc->bMasterInterface0);
++ if (!pcu->ctrl_intf)
++ return -EINVAL;
+
+ alt = pcu->ctrl_intf->cur_altsetting;
+ pcu->ep_ctrl = &alt->endpoint[0].desc;
+@@ -1670,6 +1672,8 @@ static int ims_pcu_parse_cdc_data(struct
+
+ pcu->data_intf = usb_ifnum_to_if(pcu->udev,
+ union_desc->bSlaveInterface0);
++ if (!pcu->data_intf)
++ return -EINVAL;
+
+ alt = pcu->data_intf->cur_altsetting;
+ if (alt->desc.bNumEndpoints != 2) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/input/misc/powermate.c linux-libre-4.4.7-gnu/drivers/input/misc/powermate.c
+--- linux-libre-4.4-gnu/drivers/input/misc/powermate.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/input/misc/powermate.c 2016-04-12 12:09:26.000000000 -0400
+@@ -307,6 +307,9 @@ static int powermate_probe(struct usb_in
+ int error = -ENOMEM;
+
+ interface = intf->cur_altsetting;
++ if (interface->desc.bNumEndpoints < 1)
++ return -EINVAL;
++
+ endpoint = &interface->endpoint[0].desc;
+ if (!usb_endpoint_is_int_in(endpoint))
+ return -EIO;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/input/mouse/elantech.c linux-libre-4.4.7-gnu/drivers/input/mouse/elantech.c
+--- linux-libre-4.4-gnu/drivers/input/mouse/elantech.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/input/mouse/elantech.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1222,7 +1222,7 @@ static int elantech_set_input_params(str
+ input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
+ ETP_WMAX_V2, 0, 0);
+ }
+- input_mt_init_slots(dev, 2, 0);
++ input_mt_init_slots(dev, 2, INPUT_MT_SEMI_MT);
+ input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+ input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+ break;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/input/mouse/synaptics.c linux-libre-4.4.7-gnu/drivers/input/mouse/synaptics.c
+--- linux-libre-4.4-gnu/drivers/input/mouse/synaptics.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/input/mouse/synaptics.c 2016-04-12 12:09:26.000000000 -0400
+@@ -862,8 +862,9 @@ static void synaptics_report_ext_buttons
+ if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
+ return;
+
+- /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */
+- if (SYN_ID_FULL(priv->identity) == 0x801 &&
++ /* Bug in FW 8.1 & 8.2, buttons are reported only when ExtBit is 1 */
++ if ((SYN_ID_FULL(priv->identity) == 0x801 ||
++ SYN_ID_FULL(priv->identity) == 0x802) &&
+ !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02))
+ return;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/input/mouse/vmmouse.c linux-libre-4.4.7-gnu/drivers/input/mouse/vmmouse.c
+--- linux-libre-4.4-gnu/drivers/input/mouse/vmmouse.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/input/mouse/vmmouse.c 2016-04-12 12:09:26.000000000 -0400
+@@ -458,8 +458,6 @@ int vmmouse_init(struct psmouse *psmouse
+ priv->abs_dev = abs_dev;
+ psmouse->private = priv;
+
+- input_set_capability(rel_dev, EV_REL, REL_WHEEL);
+-
+ /* Set up and register absolute device */
+ snprintf(priv->phys, sizeof(priv->phys), "%s/input1",
+ psmouse->ps2dev.serio->phys);
+@@ -475,10 +473,6 @@ int vmmouse_init(struct psmouse *psmouse
+ abs_dev->id.version = psmouse->model;
+ abs_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+
+- error = input_register_device(priv->abs_dev);
+- if (error)
+- goto init_fail;
+-
+ /* Set absolute device capabilities */
+ input_set_capability(abs_dev, EV_KEY, BTN_LEFT);
+ input_set_capability(abs_dev, EV_KEY, BTN_RIGHT);
+@@ -488,6 +482,13 @@ int vmmouse_init(struct psmouse *psmouse
+ input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0);
+ input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0);
+
++ error = input_register_device(priv->abs_dev);
++ if (error)
++ goto init_fail;
++
++ /* Add wheel capability to the relative device */
++ input_set_capability(rel_dev, EV_REL, REL_WHEEL);
++
+ psmouse->protocol_handler = vmmouse_process_byte;
+ psmouse->disconnect = vmmouse_disconnect;
+ psmouse->reconnect = vmmouse_reconnect;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/input/serio/i8042-x86ia64io.h linux-libre-4.4.7-gnu/drivers/input/serio/i8042-x86ia64io.h
+--- linux-libre-4.4-gnu/drivers/input/serio/i8042-x86ia64io.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/input/serio/i8042-x86ia64io.h 2016-04-12 12:09:26.000000000 -0400
+@@ -258,6 +258,13 @@ static const struct dmi_system_id __init
+ },
+ },
+ {
++ /* Fujitsu Lifebook U745 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
++ },
++ },
++ {
+ /* Fujitsu T70H */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iommu/amd_iommu.c linux-libre-4.4.7-gnu/drivers/iommu/amd_iommu.c
+--- linux-libre-4.4-gnu/drivers/iommu/amd_iommu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iommu/amd_iommu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1905,7 +1905,7 @@ static void do_attach(struct iommu_dev_d
+ /* Update device table */
+ set_dte_entry(dev_data->devid, domain, ats);
+ if (alias != dev_data->devid)
+- set_dte_entry(dev_data->devid, domain, ats);
++ set_dte_entry(alias, domain, ats);
+
+ device_flush_dte(dev_data);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iommu/amd_iommu_init.c linux-libre-4.4.7-gnu/drivers/iommu/amd_iommu_init.c
+--- linux-libre-4.4-gnu/drivers/iommu/amd_iommu_init.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iommu/amd_iommu_init.c 2016-04-12 12:09:26.000000000 -0400
+@@ -228,6 +228,10 @@ static int amd_iommu_enable_interrupts(v
+ static int __init iommu_go_to_state(enum iommu_init_state state);
+ static void init_device_table_dma(void);
+
++static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
++ u8 bank, u8 cntr, u8 fxn,
++ u64 *value, bool is_write);
++
+ static inline void update_last_devid(u16 devid)
+ {
+ if (devid > amd_iommu_last_bdf)
+@@ -1016,6 +1020,34 @@ static void amd_iommu_erratum_746_workar
+ }
+
+ /*
++ * Family15h Model 30h-3fh (IOMMU Mishandles ATS Write Permission)
++ * Workaround:
++ * BIOS should enable ATS write permission check by setting
++ * L2_DEBUG_3[AtsIgnoreIWDis](D0F2xF4_x47[0]) = 1b
++ */
++static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu)
++{
++ u32 value;
++
++ if ((boot_cpu_data.x86 != 0x15) ||
++ (boot_cpu_data.x86_model < 0x30) ||
++ (boot_cpu_data.x86_model > 0x3f))
++ return;
++
++ /* Test L2_DEBUG_3[AtsIgnoreIWDis] == 1 */
++ value = iommu_read_l2(iommu, 0x47);
++
++ if (value & BIT(0))
++ return;
++
++ /* Set L2_DEBUG_3[AtsIgnoreIWDis] = 1 */
++ iommu_write_l2(iommu, 0x47, value | BIT(0));
++
++ pr_info("AMD-Vi: Applying ATS write check workaround for IOMMU at %s\n",
++ dev_name(&iommu->dev->dev));
++}
++
++/*
+ * This function clues the initialization function for one IOMMU
+ * together and also allocates the command buffer and programs the
+ * hardware. It does NOT enable the IOMMU. This is done afterwards.
+@@ -1142,8 +1174,8 @@ static void init_iommu_perf_ctr(struct a
+ amd_iommu_pc_present = true;
+
+ /* Check if the performance counters can be written to */
+- if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) ||
+- (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) ||
++ if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) ||
++ (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) ||
+ (val != val2)) {
+ pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n");
+ amd_iommu_pc_present = false;
+@@ -1284,6 +1316,7 @@ static int iommu_init_pci(struct amd_iom
+ }
+
+ amd_iommu_erratum_746_workaround(iommu);
++ amd_iommu_ats_write_check_workaround(iommu);
+
+ iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
+ amd_iommu_groups, "ivhd%d",
+@@ -2283,22 +2316,15 @@ u8 amd_iommu_pc_get_max_counters(u16 dev
+ }
+ EXPORT_SYMBOL(amd_iommu_pc_get_max_counters);
+
+-int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
++static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
++ u8 bank, u8 cntr, u8 fxn,
+ u64 *value, bool is_write)
+ {
+- struct amd_iommu *iommu;
+ u32 offset;
+ u32 max_offset_lim;
+
+- /* Make sure the IOMMU PC resource is available */
+- if (!amd_iommu_pc_present)
+- return -ENODEV;
+-
+- /* Locate the iommu associated with the device ID */
+- iommu = amd_iommu_rlookup_table[devid];
+-
+ /* Check for valid iommu and pc register indexing */
+- if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7)))
++ if (WARN_ON((fxn > 0x28) || (fxn & 7)))
+ return -ENODEV;
+
+ offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn);
+@@ -2322,3 +2348,16 @@ int amd_iommu_pc_get_set_reg_val(u16 dev
+ return 0;
+ }
+ EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
++
++int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
++ u64 *value, bool is_write)
++{
++ struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
++
++ /* Make sure the IOMMU PC resource is available */
++ if (!amd_iommu_pc_present || iommu == NULL)
++ return -ENODEV;
++
++ return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn,
++ value, is_write);
++}
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iommu/dmar.c linux-libre-4.4.7-gnu/drivers/iommu/dmar.c
+--- linux-libre-4.4-gnu/drivers/iommu/dmar.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iommu/dmar.c 2016-04-12 12:09:26.000000000 -0400
+@@ -329,7 +329,8 @@ static int dmar_pci_bus_notifier(struct
+ /* Only care about add/remove events for physical functions */
+ if (pdev->is_virtfn)
+ return NOTIFY_DONE;
+- if (action != BUS_NOTIFY_ADD_DEVICE && action != BUS_NOTIFY_DEL_DEVICE)
++ if (action != BUS_NOTIFY_ADD_DEVICE &&
++ action != BUS_NOTIFY_REMOVED_DEVICE)
+ return NOTIFY_DONE;
+
+ info = dmar_alloc_pci_notify_info(pdev, action);
+@@ -339,7 +340,7 @@ static int dmar_pci_bus_notifier(struct
+ down_write(&dmar_global_lock);
+ if (action == BUS_NOTIFY_ADD_DEVICE)
+ dmar_pci_bus_add_dev(info);
+- else if (action == BUS_NOTIFY_DEL_DEVICE)
++ else if (action == BUS_NOTIFY_REMOVED_DEVICE)
+ dmar_pci_bus_del_dev(info);
+ up_write(&dmar_global_lock);
+
+@@ -1347,7 +1348,7 @@ void dmar_disable_qi(struct intel_iommu
+
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
+
+- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
++ sts = readl(iommu->reg + DMAR_GSTS_REG);
+ if (!(sts & DMA_GSTS_QIES))
+ goto end;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iommu/intel-iommu.c linux-libre-4.4.7-gnu/drivers/iommu/intel-iommu.c
+--- linux-libre-4.4-gnu/drivers/iommu/intel-iommu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iommu/intel-iommu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1489,7 +1489,7 @@ static void iommu_disable_dev_iotlb(stru
+ {
+ struct pci_dev *pdev;
+
+- if (dev_is_pci(info->dev))
++ if (!dev_is_pci(info->dev))
+ return;
+
+ pdev = to_pci_dev(info->dev);
+@@ -4367,7 +4367,7 @@ int dmar_iommu_notify_scope_dev(struct d
+ rmrru->devices_cnt);
+ if(ret < 0)
+ return ret;
+- } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
++ } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
+ dmar_remove_dev_scope(info, rmrr->segment,
+ rmrru->devices, rmrru->devices_cnt);
+ }
+@@ -4387,7 +4387,7 @@ int dmar_iommu_notify_scope_dev(struct d
+ break;
+ else if(ret < 0)
+ return ret;
+- } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
++ } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
+ if (dmar_remove_dev_scope(info, atsr->segment,
+ atsru->devices, atsru->devices_cnt))
+ break;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iommu/intel_irq_remapping.c linux-libre-4.4.7-gnu/drivers/iommu/intel_irq_remapping.c
+--- linux-libre-4.4-gnu/drivers/iommu/intel_irq_remapping.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iommu/intel_irq_remapping.c 2016-04-12 12:09:26.000000000 -0400
+@@ -629,7 +629,7 @@ static void iommu_disable_irq_remapping(
+
+ raw_spin_lock_irqsave(&iommu->register_lock, flags);
+
+- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
++ sts = readl(iommu->reg + DMAR_GSTS_REG);
+ if (!(sts & DMA_GSTS_IRES))
+ goto end;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iommu/intel-svm.c linux-libre-4.4.7-gnu/drivers/iommu/intel-svm.c
+--- linux-libre-4.4-gnu/drivers/iommu/intel-svm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iommu/intel-svm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -249,12 +249,30 @@ static void intel_flush_pasid_dev(struct
+ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
+ {
+ struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
++ struct intel_svm_dev *sdev;
+
++ /* This might end up being called from exit_mmap(), *before* the page
++ * tables are cleared. And __mmu_notifier_release() will delete us from
++ * the list of notifiers so that our invalidate_range() callback doesn't
++ * get called when the page tables are cleared. So we need to protect
++ * against hardware accessing those page tables.
++ *
++ * We do it by clearing the entry in the PASID table and then flushing
++ * the IOTLB and the PASID table caches. This might upset hardware;
++ * perhaps we'll want to point the PASID to a dummy PGD (like the zero
++ * page) so that we end up taking a fault that the hardware really
++ * *has* to handle gracefully without affecting other processes.
++ */
+ svm->iommu->pasid_table[svm->pasid].val = 0;
++ wmb();
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(sdev, &svm->devs, list) {
++ intel_flush_pasid_dev(svm, sdev, svm->pasid);
++ intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
++ }
++ rcu_read_unlock();
+
+- /* There's no need to do any flush because we can't get here if there
+- * are any devices left anyway. */
+- WARN_ON(!list_empty(&svm->devs));
+ }
+
+ static const struct mmu_notifier_ops intel_mmuops = {
+@@ -379,7 +397,6 @@ int intel_svm_bind_mm(struct device *dev
+ goto out;
+ }
+ iommu->pasid_table[svm->pasid].val = (u64)__pa(mm->pgd) | 1;
+- mm = NULL;
+ } else
+ iommu->pasid_table[svm->pasid].val = (u64)__pa(init_mm.pgd) | 1 | (1ULL << 11);
+ wmb();
+@@ -442,11 +459,11 @@ int intel_svm_unbind_mm(struct device *d
+ kfree_rcu(sdev, rcu);
+
+ if (list_empty(&svm->devs)) {
+- mmu_notifier_unregister(&svm->notifier, svm->mm);
+
+ idr_remove(&svm->iommu->pasid_idr, svm->pasid);
+ if (svm->mm)
+- mmput(svm->mm);
++ mmu_notifier_unregister(&svm->notifier, svm->mm);
++
+ /* We mandate that no page faults may be outstanding
+ * for the PASID when intel_svm_unbind_mm() is called.
+ * If that is not obeyed, subtle errors will happen.
+@@ -507,6 +524,10 @@ static irqreturn_t prq_event_thread(int
+ struct intel_svm *svm = NULL;
+ int head, tail, handled = 0;
+
++ /* Clear PPR bit before reading head/tail registers, to
++ * ensure that we get a new interrupt if needed. */
++ writel(DMA_PRS_PPR, iommu->reg + DMAR_PRS_REG);
++
+ tail = dmar_readq(iommu->reg + DMAR_PQT_REG) & PRQ_RING_MASK;
+ head = dmar_readq(iommu->reg + DMAR_PQH_REG) & PRQ_RING_MASK;
+ while (head != tail) {
+@@ -551,6 +572,9 @@ static irqreturn_t prq_event_thread(int
+ * any faults on kernel addresses. */
+ if (!svm->mm)
+ goto bad_req;
++ /* If the mm is already defunct, don't handle faults. */
++ if (!atomic_inc_not_zero(&svm->mm->mm_users))
++ goto bad_req;
+ down_read(&svm->mm->mmap_sem);
+ vma = find_extend_vma(svm->mm, address);
+ if (!vma || address < vma->vm_start)
+@@ -567,6 +591,7 @@ static irqreturn_t prq_event_thread(int
+ result = QI_RESP_SUCCESS;
+ invalid:
+ up_read(&svm->mm->mmap_sem);
++ mmput(svm->mm);
+ bad_req:
+ /* Accounting for major/minor faults? */
+ rcu_read_lock();
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/iommu/io-pgtable-arm.c linux-libre-4.4.7-gnu/drivers/iommu/io-pgtable-arm.c
+--- linux-libre-4.4-gnu/drivers/iommu/io-pgtable-arm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/iommu/io-pgtable-arm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -405,17 +405,18 @@ static void __arm_lpae_free_pgtable(stru
+ arm_lpae_iopte *start, *end;
+ unsigned long table_size;
+
+- /* Only leaf entries at the last level */
+- if (lvl == ARM_LPAE_MAX_LEVELS - 1)
+- return;
+-
+ if (lvl == ARM_LPAE_START_LVL(data))
+ table_size = data->pgd_size;
+ else
+ table_size = 1UL << data->pg_shift;
+
+ start = ptep;
+- end = (void *)ptep + table_size;
++
++ /* Only leaf entries at the last level */
++ if (lvl == ARM_LPAE_MAX_LEVELS - 1)
++ end = ptep;
++ else
++ end = (void *)ptep + table_size;
+
+ while (ptep != end) {
+ arm_lpae_iopte pte = *ptep++;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/irqchip/irq-atmel-aic-common.c linux-libre-4.4.7-gnu/drivers/irqchip/irq-atmel-aic-common.c
+--- linux-libre-4.4-gnu/drivers/irqchip/irq-atmel-aic-common.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/irqchip/irq-atmel-aic-common.c 2016-04-12 12:09:26.000000000 -0400
+@@ -86,7 +86,7 @@ int aic_common_set_priority(int priority
+ priority > AT91_AIC_IRQ_MAX_PRIORITY)
+ return -EINVAL;
+
+- *val &= AT91_AIC_PRIOR;
++ *val &= ~AT91_AIC_PRIOR;
+ *val |= priority;
+
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/irqchip/irq-gic-v3-its.c linux-libre-4.4.7-gnu/drivers/irqchip/irq-gic-v3-its.c
+--- linux-libre-4.4-gnu/drivers/irqchip/irq-gic-v3-its.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/irqchip/irq-gic-v3-its.c 2016-04-12 12:09:26.000000000 -0400
+@@ -597,11 +597,6 @@ static void its_unmask_irq(struct irq_da
+ lpi_set_config(d, true);
+ }
+
+-static void its_eoi_irq(struct irq_data *d)
+-{
+- gic_write_eoir(d->hwirq);
+-}
+-
+ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
+ bool force)
+ {
+@@ -638,7 +633,7 @@ static struct irq_chip its_irq_chip = {
+ .name = "ITS",
+ .irq_mask = its_mask_irq,
+ .irq_unmask = its_unmask_irq,
+- .irq_eoi = its_eoi_irq,
++ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_affinity = its_set_affinity,
+ .irq_compose_msi_msg = its_irq_compose_msi_msg,
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/irqchip/irq-mxs.c linux-libre-4.4.7-gnu/drivers/irqchip/irq-mxs.c
+--- linux-libre-4.4-gnu/drivers/irqchip/irq-mxs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/irqchip/irq-mxs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -241,6 +241,7 @@ static int __init asm9260_of_init(struct
+ writel(0, icoll_priv.intr + i);
+
+ icoll_add_domain(np, ASM9260_NUM_IRQS);
++ set_handle_irq(icoll_handle_irq);
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/irqchip/irq-omap-intc.c linux-libre-4.4.7-gnu/drivers/irqchip/irq-omap-intc.c
+--- linux-libre-4.4-gnu/drivers/irqchip/irq-omap-intc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/irqchip/irq-omap-intc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -47,6 +47,7 @@
+ #define INTC_ILR0 0x0100
+
+ #define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */
++#define SPURIOUSIRQ_MASK (0x1ffffff << 7)
+ #define INTCPS_NR_ILR_REGS 128
+ #define INTCPS_NR_MIR_REGS 4
+
+@@ -330,11 +331,35 @@ static int __init omap_init_irq(u32 base
+ static asmlinkage void __exception_irq_entry
+ omap_intc_handle_irq(struct pt_regs *regs)
+ {
++ extern unsigned long irq_err_count;
+ u32 irqnr;
+
+ irqnr = intc_readl(INTC_SIR);
++
++ /*
++ * A spurious IRQ can result if interrupt that triggered the
++ * sorting is no longer active during the sorting (10 INTC
++ * functional clock cycles after interrupt assertion). Or a
++ * change in interrupt mask affected the result during sorting
++ * time. There is no special handling required except ignoring
++ * the SIR register value just read and retrying.
++ * See section 6.2.5 of AM335x TRM Literature Number: SPRUH73K
++ *
++ * Many a times, a spurious interrupt situation has been fixed
++ * by adding a flush for the posted write acking the IRQ in
++ * the device driver. Typically, this is going be the device
++ * driver whose interrupt was handled just before the spurious
++ * IRQ occurred. Pay attention to those device drivers if you
++ * run into hitting the spurious IRQ condition below.
++ */
++ if (unlikely((irqnr & SPURIOUSIRQ_MASK) == SPURIOUSIRQ_MASK)) {
++ pr_err_once("%s: spurious irq!\n", __func__);
++ irq_err_count++;
++ omap_ack_irq(NULL);
++ return;
++ }
++
+ irqnr &= ACTIVEIRQ_MASK;
+- WARN_ONCE(!irqnr, "Spurious IRQ ?\n");
+ handle_domain_irq(domain, irqnr, regs);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/bcache/btree.c linux-libre-4.4.7-gnu/drivers/md/bcache/btree.c
+--- linux-libre-4.4-gnu/drivers/md/bcache/btree.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/bcache/btree.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1741,6 +1741,7 @@ static void bch_btree_gc(struct cache_se
+ do {
+ ret = btree_root(gc_root, c, &op, &writes, &stats);
+ closure_sync(&writes);
++ cond_resched();
+
+ if (ret && ret != -EAGAIN)
+ pr_warn("gc failed!");
+@@ -2162,8 +2163,10 @@ int bch_btree_insert_check_key(struct bt
+ rw_lock(true, b, b->level);
+
+ if (b->key.ptr[0] != btree_ptr ||
+- b->seq != seq + 1)
++ b->seq != seq + 1) {
++ op->lock = b->level;
+ goto out;
++ }
+ }
+
+ SET_KEY_PTRS(check_key, 1);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/bcache/super.c linux-libre-4.4.7-gnu/drivers/md/bcache/super.c
+--- linux-libre-4.4-gnu/drivers/md/bcache/super.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/bcache/super.c 2016-04-12 12:09:26.000000000 -0400
+@@ -685,6 +685,8 @@ static void bcache_device_link(struct bc
+ WARN(sysfs_create_link(&d->kobj, &c->kobj, "cache") ||
+ sysfs_create_link(&c->kobj, &d->kobj, d->name),
+ "Couldn't create device <-> cache set symlinks");
++
++ clear_bit(BCACHE_DEV_UNLINK_DONE, &d->flags);
+ }
+
+ static void bcache_device_detach(struct bcache_device *d)
+@@ -847,8 +849,11 @@ void bch_cached_dev_run(struct cached_de
+ buf[SB_LABEL_SIZE] = '\0';
+ env[2] = kasprintf(GFP_KERNEL, "CACHED_LABEL=%s", buf);
+
+- if (atomic_xchg(&dc->running, 1))
++ if (atomic_xchg(&dc->running, 1)) {
++ kfree(env[1]);
++ kfree(env[2]);
+ return;
++ }
+
+ if (!d->c &&
+ BDEV_STATE(&dc->sb) != BDEV_STATE_NONE) {
+@@ -1010,8 +1015,12 @@ int bch_cached_dev_attach(struct cached_
+ */
+ atomic_set(&dc->count, 1);
+
+- if (bch_cached_dev_writeback_start(dc))
++ /* Block writeback thread, but spawn it */
++ down_write(&dc->writeback_lock);
++ if (bch_cached_dev_writeback_start(dc)) {
++ up_write(&dc->writeback_lock);
+ return -ENOMEM;
++ }
+
+ if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
+ bch_sectors_dirty_init(dc);
+@@ -1023,6 +1032,9 @@ int bch_cached_dev_attach(struct cached_
+ bch_cached_dev_run(dc);
+ bcache_device_link(&dc->disk, c, "bdev");
+
++ /* Allow the writeback thread to proceed */
++ up_write(&dc->writeback_lock);
++
+ pr_info("Caching %s as %s on set %pU",
+ bdevname(dc->bdev, buf), dc->disk.disk->disk_name,
+ dc->disk.c->sb.set_uuid);
+@@ -1361,6 +1373,9 @@ static void cache_set_flush(struct closu
+ struct btree *b;
+ unsigned i;
+
++ if (!c)
++ closure_return(cl);
++
+ bch_cache_accounting_destroy(&c->accounting);
+
+ kobject_put(&c->internal);
+@@ -1823,11 +1838,12 @@ static int cache_alloc(struct cache_sb *
+ return 0;
+ }
+
+-static void register_cache(struct cache_sb *sb, struct page *sb_page,
++static int register_cache(struct cache_sb *sb, struct page *sb_page,
+ struct block_device *bdev, struct cache *ca)
+ {
+ char name[BDEVNAME_SIZE];
+- const char *err = "cannot allocate memory";
++ const char *err = NULL;
++ int ret = 0;
+
+ memcpy(&ca->sb, sb, sizeof(struct cache_sb));
+ ca->bdev = bdev;
+@@ -1842,27 +1858,35 @@ static void register_cache(struct cache_
+ if (blk_queue_discard(bdev_get_queue(ca->bdev)))
+ ca->discard = CACHE_DISCARD(&ca->sb);
+
+- if (cache_alloc(sb, ca) != 0)
++ ret = cache_alloc(sb, ca);
++ if (ret != 0)
+ goto err;
+
+- err = "error creating kobject";
+- if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache"))
+- goto err;
++ if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) {
++ err = "error calling kobject_add";
++ ret = -ENOMEM;
++ goto out;
++ }
+
+ mutex_lock(&bch_register_lock);
+ err = register_cache_set(ca);
+ mutex_unlock(&bch_register_lock);
+
+- if (err)
+- goto err;
++ if (err) {
++ ret = -ENODEV;
++ goto out;
++ }
+
+ pr_info("registered cache device %s", bdevname(bdev, name));
++
+ out:
+ kobject_put(&ca->kobj);
+- return;
++
+ err:
+- pr_notice("error opening %s: %s", bdevname(bdev, name), err);
+- goto out;
++ if (err)
++ pr_notice("error opening %s: %s", bdevname(bdev, name), err);
++
++ return ret;
+ }
+
+ /* Global interfaces/init */
+@@ -1933,6 +1957,8 @@ static ssize_t register_bcache(struct ko
+ else
+ err = "device busy";
+ mutex_unlock(&bch_register_lock);
++ if (attr == &ksysfs_register_quiet)
++ goto out;
+ }
+ goto err;
+ }
+@@ -1958,7 +1984,8 @@ static ssize_t register_bcache(struct ko
+ if (!ca)
+ goto err_close;
+
+- register_cache(sb, sb_page, bdev, ca);
++ if (register_cache(sb, sb_page, bdev, ca) != 0)
++ goto err_close;
+ }
+ out:
+ if (sb_page)
+@@ -1971,8 +1998,7 @@ out:
+ err_close:
+ blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+ err:
+- if (attr != &ksysfs_register_quiet)
+- pr_info("error opening %s: %s", path, err);
++ pr_info("error opening %s: %s", path, err);
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -2066,8 +2092,10 @@ static int __init bcache_init(void)
+ closure_debug_init();
+
+ bcache_major = register_blkdev(0, "bcache");
+- if (bcache_major < 0)
++ if (bcache_major < 0) {
++ unregister_reboot_notifier(&reboot);
+ return bcache_major;
++ }
+
+ if (!(bcache_wq = create_workqueue("bcache")) ||
+ !(bcache_kobj = kobject_create_and_add("bcache", fs_kobj)) ||
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/bcache/writeback.c linux-libre-4.4.7-gnu/drivers/md/bcache/writeback.c
+--- linux-libre-4.4-gnu/drivers/md/bcache/writeback.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/bcache/writeback.c 2016-04-12 12:09:26.000000000 -0400
+@@ -323,6 +323,10 @@ void bcache_dev_sectors_dirty_add(struct
+
+ static bool dirty_pred(struct keybuf *buf, struct bkey *k)
+ {
++ struct cached_dev *dc = container_of(buf, struct cached_dev, writeback_keys);
++
++ BUG_ON(KEY_INODE(k) != dc->disk.id);
++
+ return KEY_DIRTY(k);
+ }
+
+@@ -372,11 +376,24 @@ next:
+ }
+ }
+
++/*
++ * Returns true if we scanned the entire disk
++ */
+ static bool refill_dirty(struct cached_dev *dc)
+ {
+ struct keybuf *buf = &dc->writeback_keys;
++ struct bkey start = KEY(dc->disk.id, 0, 0);
+ struct bkey end = KEY(dc->disk.id, MAX_KEY_OFFSET, 0);
+- bool searched_from_start = false;
++ struct bkey start_pos;
++
++ /*
++ * make sure keybuf pos is inside the range for this disk - at bringup
++ * we might not be attached yet so this disk's inode nr isn't
++ * initialized then
++ */
++ if (bkey_cmp(&buf->last_scanned, &start) < 0 ||
++ bkey_cmp(&buf->last_scanned, &end) > 0)
++ buf->last_scanned = start;
+
+ if (dc->partial_stripes_expensive) {
+ refill_full_stripes(dc);
+@@ -384,14 +401,20 @@ static bool refill_dirty(struct cached_d
+ return false;
+ }
+
+- if (bkey_cmp(&buf->last_scanned, &end) >= 0) {
+- buf->last_scanned = KEY(dc->disk.id, 0, 0);
+- searched_from_start = true;
+- }
+-
++ start_pos = buf->last_scanned;
+ bch_refill_keybuf(dc->disk.c, buf, &end, dirty_pred);
+
+- return bkey_cmp(&buf->last_scanned, &end) >= 0 && searched_from_start;
++ if (bkey_cmp(&buf->last_scanned, &end) < 0)
++ return false;
++
++ /*
++ * If we get to the end start scanning again from the beginning, and
++ * only scan up to where we initially started scanning from:
++ */
++ buf->last_scanned = start;
++ bch_refill_keybuf(dc->disk.c, buf, &start_pos, dirty_pred);
++
++ return bkey_cmp(&buf->last_scanned, &start_pos) >= 0;
+ }
+
+ static int bch_writeback_thread(void *arg)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/bcache/writeback.h linux-libre-4.4.7-gnu/drivers/md/bcache/writeback.h
+--- linux-libre-4.4-gnu/drivers/md/bcache/writeback.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/bcache/writeback.h 2016-04-12 12:09:26.000000000 -0400
+@@ -63,7 +63,8 @@ static inline bool should_writeback(stru
+
+ static inline void bch_writeback_queue(struct cached_dev *dc)
+ {
+- wake_up_process(dc->writeback_thread);
++ if (!IS_ERR_OR_NULL(dc->writeback_thread))
++ wake_up_process(dc->writeback_thread);
+ }
+
+ static inline void bch_writeback_add(struct cached_dev *dc)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm.c linux-libre-4.4.7-gnu/drivers/md/dm.c
+--- linux-libre-4.4-gnu/drivers/md/dm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1109,12 +1109,8 @@ static void rq_completed(struct mapped_d
+ * back into ->request_fn() could deadlock attempting to grab the
+ * queue lock again.
+ */
+- if (run_queue) {
+- if (md->queue->mq_ops)
+- blk_mq_run_hw_queues(md->queue, true);
+- else
+- blk_run_queue_async(md->queue);
+- }
++ if (!md->queue->mq_ops && run_queue)
++ blk_run_queue_async(md->queue);
+
+ /*
+ * dm_put() must be at the end of this function. See the comment above
+@@ -1191,6 +1187,8 @@ static void dm_unprep_request(struct req
+
+ if (clone)
+ free_rq_clone(clone);
++ else if (!tio->md->queue->mq_ops)
++ free_rq_tio(tio);
+ }
+
+ /*
+@@ -1212,9 +1210,9 @@ static void dm_requeue_original_request(
+ {
+ int rw = rq_data_dir(rq);
+
++ rq_end_stats(md, rq);
+ dm_unprep_request(rq);
+
+- rq_end_stats(md, rq);
+ if (!rq->q->mq_ops)
+ old_requeue_request(rq);
+ else {
+@@ -1334,7 +1332,10 @@ static void dm_complete_request(struct r
+ struct dm_rq_target_io *tio = tio_from_request(rq);
+
+ tio->error = error;
+- blk_complete_request(rq);
++ if (!rq->q->mq_ops)
++ blk_complete_request(rq);
++ else
++ blk_mq_complete_request(rq, error);
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-cache-metadata.c linux-libre-4.4.7-gnu/drivers/md/dm-cache-metadata.c
+--- linux-libre-4.4-gnu/drivers/md/dm-cache-metadata.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-cache-metadata.c 2016-04-12 12:09:26.000000000 -0400
+@@ -867,19 +867,40 @@ static int blocks_are_unmapped_or_clean(
+ return 0;
+ }
+
+-#define WRITE_LOCK(cmd) \
+- if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \
++#define WRITE_LOCK(cmd) \
++ down_write(&cmd->root_lock); \
++ if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
++ up_write(&cmd->root_lock); \
+ return -EINVAL; \
+- down_write(&cmd->root_lock)
++ }
+
+ #define WRITE_LOCK_VOID(cmd) \
+- if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \
++ down_write(&cmd->root_lock); \
++ if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
++ up_write(&cmd->root_lock); \
+ return; \
+- down_write(&cmd->root_lock)
++ }
+
+ #define WRITE_UNLOCK(cmd) \
+ up_write(&cmd->root_lock)
+
++#define READ_LOCK(cmd) \
++ down_read(&cmd->root_lock); \
++ if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
++ up_read(&cmd->root_lock); \
++ return -EINVAL; \
++ }
++
++#define READ_LOCK_VOID(cmd) \
++ down_read(&cmd->root_lock); \
++ if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
++ up_read(&cmd->root_lock); \
++ return; \
++ }
++
++#define READ_UNLOCK(cmd) \
++ up_read(&cmd->root_lock)
++
+ int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size)
+ {
+ int r;
+@@ -1015,22 +1036,20 @@ int dm_cache_load_discards(struct dm_cac
+ {
+ int r;
+
+- down_read(&cmd->root_lock);
++ READ_LOCK(cmd);
+ r = __load_discards(cmd, fn, context);
+- up_read(&cmd->root_lock);
++ READ_UNLOCK(cmd);
+
+ return r;
+ }
+
+-dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd)
++int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result)
+ {
+- dm_cblock_t r;
+-
+- down_read(&cmd->root_lock);
+- r = cmd->cache_blocks;
+- up_read(&cmd->root_lock);
++ READ_LOCK(cmd);
++ *result = cmd->cache_blocks;
++ READ_UNLOCK(cmd);
+
+- return r;
++ return 0;
+ }
+
+ static int __remove(struct dm_cache_metadata *cmd, dm_cblock_t cblock)
+@@ -1188,9 +1207,9 @@ int dm_cache_load_mappings(struct dm_cac
+ {
+ int r;
+
+- down_read(&cmd->root_lock);
++ READ_LOCK(cmd);
+ r = __load_mappings(cmd, policy, fn, context);
+- up_read(&cmd->root_lock);
++ READ_UNLOCK(cmd);
+
+ return r;
+ }
+@@ -1215,18 +1234,18 @@ static int __dump_mappings(struct dm_cac
+
+ void dm_cache_dump(struct dm_cache_metadata *cmd)
+ {
+- down_read(&cmd->root_lock);
++ READ_LOCK_VOID(cmd);
+ __dump_mappings(cmd);
+- up_read(&cmd->root_lock);
++ READ_UNLOCK(cmd);
+ }
+
+ int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd)
+ {
+ int r;
+
+- down_read(&cmd->root_lock);
++ READ_LOCK(cmd);
+ r = cmd->changed;
+- up_read(&cmd->root_lock);
++ READ_UNLOCK(cmd);
+
+ return r;
+ }
+@@ -1276,9 +1295,9 @@ int dm_cache_set_dirty(struct dm_cache_m
+ void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd,
+ struct dm_cache_statistics *stats)
+ {
+- down_read(&cmd->root_lock);
++ READ_LOCK_VOID(cmd);
+ *stats = cmd->stats;
+- up_read(&cmd->root_lock);
++ READ_UNLOCK(cmd);
+ }
+
+ void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd,
+@@ -1312,9 +1331,9 @@ int dm_cache_get_free_metadata_block_cou
+ {
+ int r = -EINVAL;
+
+- down_read(&cmd->root_lock);
++ READ_LOCK(cmd);
+ r = dm_sm_get_nr_free(cmd->metadata_sm, result);
+- up_read(&cmd->root_lock);
++ READ_UNLOCK(cmd);
+
+ return r;
+ }
+@@ -1324,9 +1343,9 @@ int dm_cache_get_metadata_dev_size(struc
+ {
+ int r = -EINVAL;
+
+- down_read(&cmd->root_lock);
++ READ_LOCK(cmd);
+ r = dm_sm_get_nr_blocks(cmd->metadata_sm, result);
+- up_read(&cmd->root_lock);
++ READ_UNLOCK(cmd);
+
+ return r;
+ }
+@@ -1417,7 +1436,13 @@ int dm_cache_write_hints(struct dm_cache
+
+ int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result)
+ {
+- return blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result);
++ int r;
++
++ READ_LOCK(cmd);
++ r = blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result);
++ READ_UNLOCK(cmd);
++
++ return r;
+ }
+
+ void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd)
+@@ -1440,10 +1465,7 @@ int dm_cache_metadata_set_needs_check(st
+ struct dm_block *sblock;
+ struct cache_disk_superblock *disk_super;
+
+- /*
+- * We ignore fail_io for this function.
+- */
+- down_write(&cmd->root_lock);
++ WRITE_LOCK(cmd);
+ set_bit(NEEDS_CHECK, &cmd->flags);
+
+ r = superblock_lock(cmd, &sblock);
+@@ -1458,19 +1480,17 @@ int dm_cache_metadata_set_needs_check(st
+ dm_bm_unlock(sblock);
+
+ out:
+- up_write(&cmd->root_lock);
++ WRITE_UNLOCK(cmd);
+ return r;
+ }
+
+-bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd)
++int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result)
+ {
+- bool needs_check;
+-
+- down_read(&cmd->root_lock);
+- needs_check = !!test_bit(NEEDS_CHECK, &cmd->flags);
+- up_read(&cmd->root_lock);
++ READ_LOCK(cmd);
++ *result = !!test_bit(NEEDS_CHECK, &cmd->flags);
++ READ_UNLOCK(cmd);
+
+- return needs_check;
++ return 0;
+ }
+
+ int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-cache-metadata.h linux-libre-4.4.7-gnu/drivers/md/dm-cache-metadata.h
+--- linux-libre-4.4-gnu/drivers/md/dm-cache-metadata.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-cache-metadata.h 2016-04-12 12:09:26.000000000 -0400
+@@ -66,7 +66,7 @@ void dm_cache_metadata_close(struct dm_c
+ * origin blocks to map to.
+ */
+ int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size);
+-dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd);
++int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result);
+
+ int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
+ sector_t discard_block_size,
+@@ -137,7 +137,7 @@ int dm_cache_write_hints(struct dm_cache
+ */
+ int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result);
+
+-bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd);
++int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result);
+ int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd);
+ void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd);
+ void dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-cache-target.c linux-libre-4.4.7-gnu/drivers/md/dm-cache-target.c
+--- linux-libre-4.4-gnu/drivers/md/dm-cache-target.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-cache-target.c 2016-04-12 12:09:26.000000000 -0400
+@@ -987,9 +987,14 @@ static void notify_mode_switch(struct ca
+
+ static void set_cache_mode(struct cache *cache, enum cache_metadata_mode new_mode)
+ {
+- bool needs_check = dm_cache_metadata_needs_check(cache->cmd);
++ bool needs_check;
+ enum cache_metadata_mode old_mode = get_cache_mode(cache);
+
++ if (dm_cache_metadata_needs_check(cache->cmd, &needs_check)) {
++ DMERR("unable to read needs_check flag, setting failure mode");
++ new_mode = CM_FAIL;
++ }
++
+ if (new_mode == CM_WRITE && needs_check) {
+ DMERR("%s: unable to switch cache to write mode until repaired.",
+ cache_device_name(cache));
+@@ -3513,6 +3518,7 @@ static void cache_status(struct dm_targe
+ char buf[BDEVNAME_SIZE];
+ struct cache *cache = ti->private;
+ dm_cblock_t residency;
++ bool needs_check;
+
+ switch (type) {
+ case STATUSTYPE_INFO:
+@@ -3586,7 +3592,9 @@ static void cache_status(struct dm_targe
+ else
+ DMEMIT("rw ");
+
+- if (dm_cache_metadata_needs_check(cache->cmd))
++ r = dm_cache_metadata_needs_check(cache->cmd, &needs_check);
++
++ if (r || needs_check)
+ DMEMIT("needs_check ");
+ else
+ DMEMIT("- ");
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-exception-store.h linux-libre-4.4.7-gnu/drivers/md/dm-exception-store.h
+--- linux-libre-4.4-gnu/drivers/md/dm-exception-store.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-exception-store.h 2016-04-12 12:09:26.000000000 -0400
+@@ -69,7 +69,7 @@ struct dm_exception_store_type {
+ * Update the metadata with this exception.
+ */
+ void (*commit_exception) (struct dm_exception_store *store,
+- struct dm_exception *e,
++ struct dm_exception *e, int valid,
+ void (*callback) (void *, int success),
+ void *callback_context);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-snap.c linux-libre-4.4.7-gnu/drivers/md/dm-snap.c
+--- linux-libre-4.4-gnu/drivers/md/dm-snap.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-snap.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1106,6 +1106,7 @@ static int snapshot_ctr(struct dm_target
+ int i;
+ int r = -EINVAL;
+ char *origin_path, *cow_path;
++ dev_t origin_dev, cow_dev;
+ unsigned args_used, num_flush_bios = 1;
+ fmode_t origin_mode = FMODE_READ;
+
+@@ -1136,11 +1137,19 @@ static int snapshot_ctr(struct dm_target
+ ti->error = "Cannot get origin device";
+ goto bad_origin;
+ }
++ origin_dev = s->origin->bdev->bd_dev;
+
+ cow_path = argv[0];
+ argv++;
+ argc--;
+
++ cow_dev = dm_get_dev_t(cow_path);
++ if (cow_dev && cow_dev == origin_dev) {
++ ti->error = "COW device cannot be the same as origin device";
++ r = -EINVAL;
++ goto bad_cow;
++ }
++
+ r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow);
+ if (r) {
+ ti->error = "Cannot get COW device";
+@@ -1438,8 +1447,9 @@ static void __invalidate_snapshot(struct
+ dm_table_event(s->ti->table);
+ }
+
+-static void pending_complete(struct dm_snap_pending_exception *pe, int success)
++static void pending_complete(void *context, int success)
+ {
++ struct dm_snap_pending_exception *pe = context;
+ struct dm_exception *e;
+ struct dm_snapshot *s = pe->snap;
+ struct bio *origin_bios = NULL;
+@@ -1509,24 +1519,13 @@ out:
+ free_pending_exception(pe);
+ }
+
+-static void commit_callback(void *context, int success)
+-{
+- struct dm_snap_pending_exception *pe = context;
+-
+- pending_complete(pe, success);
+-}
+-
+ static void complete_exception(struct dm_snap_pending_exception *pe)
+ {
+ struct dm_snapshot *s = pe->snap;
+
+- if (unlikely(pe->copy_error))
+- pending_complete(pe, 0);
+-
+- else
+- /* Update the metadata if we are persistent */
+- s->store->type->commit_exception(s->store, &pe->e,
+- commit_callback, pe);
++ /* Update the metadata if we are persistent */
++ s->store->type->commit_exception(s->store, &pe->e, !pe->copy_error,
++ pending_complete, pe);
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-snap-persistent.c linux-libre-4.4.7-gnu/drivers/md/dm-snap-persistent.c
+--- linux-libre-4.4-gnu/drivers/md/dm-snap-persistent.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-snap-persistent.c 2016-04-12 12:09:26.000000000 -0400
+@@ -695,7 +695,7 @@ static int persistent_prepare_exception(
+ }
+
+ static void persistent_commit_exception(struct dm_exception_store *store,
+- struct dm_exception *e,
++ struct dm_exception *e, int valid,
+ void (*callback) (void *, int success),
+ void *callback_context)
+ {
+@@ -704,6 +704,9 @@ static void persistent_commit_exception(
+ struct core_exception ce;
+ struct commit_callback *cb;
+
++ if (!valid)
++ ps->valid = 0;
++
+ ce.old_chunk = e->old_chunk;
+ ce.new_chunk = e->new_chunk;
+ write_exception(ps, ps->current_committed++, &ce);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-snap-transient.c linux-libre-4.4.7-gnu/drivers/md/dm-snap-transient.c
+--- linux-libre-4.4-gnu/drivers/md/dm-snap-transient.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-snap-transient.c 2016-04-12 12:09:26.000000000 -0400
+@@ -52,12 +52,12 @@ static int transient_prepare_exception(s
+ }
+
+ static void transient_commit_exception(struct dm_exception_store *store,
+- struct dm_exception *e,
++ struct dm_exception *e, int valid,
+ void (*callback) (void *, int success),
+ void *callback_context)
+ {
+ /* Just succeed */
+- callback(callback_context, 1);
++ callback(callback_context, valid);
+ }
+
+ static void transient_usage(struct dm_exception_store *store,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-table.c linux-libre-4.4.7-gnu/drivers/md/dm-table.c
+--- linux-libre-4.4-gnu/drivers/md/dm-table.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-table.c 2016-04-12 12:09:26.000000000 -0400
+@@ -365,6 +365,26 @@ static int upgrade_mode(struct dm_dev_in
+ }
+
+ /*
++ * Convert the path to a device
++ */
++dev_t dm_get_dev_t(const char *path)
++{
++ dev_t uninitialized_var(dev);
++ struct block_device *bdev;
++
++ bdev = lookup_bdev(path);
++ if (IS_ERR(bdev))
++ dev = name_to_dev_t(path);
++ else {
++ dev = bdev->bd_dev;
++ bdput(bdev);
++ }
++
++ return dev;
++}
++EXPORT_SYMBOL_GPL(dm_get_dev_t);
++
++/*
+ * Add a device to the list, or just increment the usage count if
+ * it's already present.
+ */
+@@ -372,23 +392,15 @@ int dm_get_device(struct dm_target *ti,
+ struct dm_dev **result)
+ {
+ int r;
+- dev_t uninitialized_var(dev);
++ dev_t dev;
+ struct dm_dev_internal *dd;
+ struct dm_table *t = ti->table;
+- struct block_device *bdev;
+
+ BUG_ON(!t);
+
+- /* convert the path to a device */
+- bdev = lookup_bdev(path);
+- if (IS_ERR(bdev)) {
+- dev = name_to_dev_t(path);
+- if (!dev)
+- return -ENODEV;
+- } else {
+- dev = bdev->bd_dev;
+- bdput(bdev);
+- }
++ dev = dm_get_dev_t(path);
++ if (!dev)
++ return -ENODEV;
+
+ dd = find_device(&t->devices, dev);
+ if (!dd) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-thin.c linux-libre-4.4.7-gnu/drivers/md/dm-thin.c
+--- linux-libre-4.4-gnu/drivers/md/dm-thin.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-thin.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3453,8 +3453,8 @@ static void pool_postsuspend(struct dm_t
+ struct pool_c *pt = ti->private;
+ struct pool *pool = pt->pool;
+
+- cancel_delayed_work(&pool->waker);
+- cancel_delayed_work(&pool->no_space_timeout);
++ cancel_delayed_work_sync(&pool->waker);
++ cancel_delayed_work_sync(&pool->no_space_timeout);
+ flush_workqueue(pool->wq);
+ (void) commit(pool);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/dm-thin-metadata.c linux-libre-4.4.7-gnu/drivers/md/dm-thin-metadata.c
+--- linux-libre-4.4-gnu/drivers/md/dm-thin-metadata.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/dm-thin-metadata.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1943,5 +1943,8 @@ bool dm_pool_metadata_needs_check(struct
+
+ void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd)
+ {
+- dm_tm_issue_prefetches(pmd->tm);
++ down_read(&pmd->root_lock);
++ if (!pmd->fail_io)
++ dm_tm_issue_prefetches(pmd->tm);
++ up_read(&pmd->root_lock);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/md.c linux-libre-4.4.7-gnu/drivers/md/md.c
+--- linux-libre-4.4-gnu/drivers/md/md.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/md.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2017,28 +2017,32 @@ int md_integrity_register(struct mddev *
+ }
+ EXPORT_SYMBOL(md_integrity_register);
+
+-/* Disable data integrity if non-capable/non-matching disk is being added */
+-void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
++/*
++ * Attempt to add an rdev, but only if it is consistent with the current
++ * integrity profile
++ */
++int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
+ {
+ struct blk_integrity *bi_rdev;
+ struct blk_integrity *bi_mddev;
++ char name[BDEVNAME_SIZE];
+
+ if (!mddev->gendisk)
+- return;
++ return 0;
+
+ bi_rdev = bdev_get_integrity(rdev->bdev);
+ bi_mddev = blk_get_integrity(mddev->gendisk);
+
+ if (!bi_mddev) /* nothing to do */
+- return;
+- if (rdev->raid_disk < 0) /* skip spares */
+- return;
+- if (bi_rdev && blk_integrity_compare(mddev->gendisk,
+- rdev->bdev->bd_disk) >= 0)
+- return;
+- WARN_ON_ONCE(!mddev->suspended);
+- printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
+- blk_integrity_unregister(mddev->gendisk);
++ return 0;
++
++ if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
++ printk(KERN_NOTICE "%s: incompatible integrity profile for %s\n",
++ mdname(mddev), bdevname(rdev->bdev, name));
++ return -ENXIO;
++ }
++
++ return 0;
+ }
+ EXPORT_SYMBOL(md_integrity_add_rdev);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/md.h linux-libre-4.4.7-gnu/drivers/md/md.h
+--- linux-libre-4.4-gnu/drivers/md/md.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/md.h 2016-04-12 12:09:26.000000000 -0400
+@@ -657,7 +657,7 @@ extern void md_wait_for_blocked_rdev(str
+ extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
+ extern int md_check_no_bitmap(struct mddev *mddev);
+ extern int md_integrity_register(struct mddev *mddev);
+-extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
++extern int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
+ extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
+
+ extern void mddev_init(struct mddev *mddev);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/multipath.c linux-libre-4.4.7-gnu/drivers/md/multipath.c
+--- linux-libre-4.4-gnu/drivers/md/multipath.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/multipath.c 2016-04-12 12:09:26.000000000 -0400
+@@ -129,7 +129,9 @@ static void multipath_make_request(struc
+ }
+ multipath = conf->multipaths + mp_bh->path;
+
+- mp_bh->bio = *bio;
++ bio_init(&mp_bh->bio);
++ __bio_clone_fast(&mp_bh->bio, bio);
++
+ mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset;
+ mp_bh->bio.bi_bdev = multipath->rdev->bdev;
+ mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT;
+@@ -257,6 +259,9 @@ static int multipath_add_disk(struct mdd
+ disk_stack_limits(mddev->gendisk, rdev->bdev,
+ rdev->data_offset << 9);
+
++ err = md_integrity_add_rdev(rdev, mddev);
++ if (err)
++ break;
+ spin_lock_irq(&conf->device_lock);
+ mddev->degraded--;
+ rdev->raid_disk = path;
+@@ -264,9 +269,6 @@ static int multipath_add_disk(struct mdd
+ spin_unlock_irq(&conf->device_lock);
+ rcu_assign_pointer(p->rdev, rdev);
+ err = 0;
+- mddev_suspend(mddev);
+- md_integrity_add_rdev(rdev, mddev);
+- mddev_resume(mddev);
+ break;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/persistent-data/dm-space-map-metadata.c linux-libre-4.4.7-gnu/drivers/md/persistent-data/dm-space-map-metadata.c
+--- linux-libre-4.4-gnu/drivers/md/persistent-data/dm-space-map-metadata.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/persistent-data/dm-space-map-metadata.c 2016-04-12 12:09:26.000000000 -0400
+@@ -152,12 +152,9 @@ static int brb_peek(struct bop_ring_buff
+
+ static int brb_pop(struct bop_ring_buffer *brb)
+ {
+- struct block_op *bop;
+-
+ if (brb_empty(brb))
+ return -ENODATA;
+
+- bop = brb->bops + brb->begin;
+ brb->begin = brb_next(brb, brb->begin);
+
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/raid10.c linux-libre-4.4.7-gnu/drivers/md/raid10.c
+--- linux-libre-4.4-gnu/drivers/md/raid10.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/raid10.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1698,6 +1698,9 @@ static int raid10_add_disk(struct mddev
+ if (rdev->saved_raid_disk < 0 && !_enough(conf, 1, -1))
+ return -EINVAL;
+
++ if (md_integrity_add_rdev(rdev, mddev))
++ return -ENXIO;
++
+ if (rdev->raid_disk >= 0)
+ first = last = rdev->raid_disk;
+
+@@ -1739,9 +1742,6 @@ static int raid10_add_disk(struct mddev
+ rcu_assign_pointer(p->rdev, rdev);
+ break;
+ }
+- mddev_suspend(mddev);
+- md_integrity_add_rdev(rdev, mddev);
+- mddev_resume(mddev);
+ if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+
+@@ -2664,6 +2664,7 @@ static void handle_write_completed(struc
+ if (fail) {
+ spin_lock_irq(&conf->device_lock);
+ list_add(&r10_bio->retry_list, &conf->bio_end_io_list);
++ conf->nr_queued++;
+ spin_unlock_irq(&conf->device_lock);
+ md_wakeup_thread(conf->mddev->thread);
+ } else {
+@@ -2691,8 +2692,10 @@ static void raid10d(struct md_thread *th
+ LIST_HEAD(tmp);
+ spin_lock_irqsave(&conf->device_lock, flags);
+ if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+- list_add(&tmp, &conf->bio_end_io_list);
+- list_del_init(&conf->bio_end_io_list);
++ while (!list_empty(&conf->bio_end_io_list)) {
++ list_move(conf->bio_end_io_list.prev, &tmp);
++ conf->nr_queued--;
++ }
+ }
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ while (!list_empty(&tmp)) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/raid1.c linux-libre-4.4.7-gnu/drivers/md/raid1.c
+--- linux-libre-4.4-gnu/drivers/md/raid1.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/raid1.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1589,6 +1589,9 @@ static int raid1_add_disk(struct mddev *
+ if (mddev->recovery_disabled == conf->recovery_disabled)
+ return -EBUSY;
+
++ if (md_integrity_add_rdev(rdev, mddev))
++ return -ENXIO;
++
+ if (rdev->raid_disk >= 0)
+ first = last = rdev->raid_disk;
+
+@@ -1632,9 +1635,6 @@ static int raid1_add_disk(struct mddev *
+ break;
+ }
+ }
+- mddev_suspend(mddev);
+- md_integrity_add_rdev(rdev, mddev);
+- mddev_resume(mddev);
+ if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+ print_conf(conf);
+@@ -2274,6 +2274,7 @@ static void handle_write_finished(struct
+ if (fail) {
+ spin_lock_irq(&conf->device_lock);
+ list_add(&r1_bio->retry_list, &conf->bio_end_io_list);
++ conf->nr_queued++;
+ spin_unlock_irq(&conf->device_lock);
+ md_wakeup_thread(conf->mddev->thread);
+ } else {
+@@ -2391,8 +2392,10 @@ static void raid1d(struct md_thread *thr
+ LIST_HEAD(tmp);
+ spin_lock_irqsave(&conf->device_lock, flags);
+ if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+- list_add(&tmp, &conf->bio_end_io_list);
+- list_del_init(&conf->bio_end_io_list);
++ while (!list_empty(&conf->bio_end_io_list)) {
++ list_move(conf->bio_end_io_list.prev, &tmp);
++ conf->nr_queued--;
++ }
+ }
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ while (!list_empty(&tmp)) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/raid5.c linux-libre-4.4.7-gnu/drivers/md/raid5.c
+--- linux-libre-4.4-gnu/drivers/md/raid5.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/raid5.c 2016-04-12 12:09:26.000000000 -0400
+@@ -340,8 +340,7 @@ static void release_inactive_stripe_list
+ int hash)
+ {
+ int size;
+- unsigned long do_wakeup = 0;
+- int i = 0;
++ bool do_wakeup = false;
+ unsigned long flags;
+
+ if (hash == NR_STRIPE_HASH_LOCKS) {
+@@ -362,19 +361,15 @@ static void release_inactive_stripe_list
+ !list_empty(list))
+ atomic_dec(&conf->empty_inactive_list_nr);
+ list_splice_tail_init(list, conf->inactive_list + hash);
+- do_wakeup |= 1 << hash;
++ do_wakeup = true;
+ spin_unlock_irqrestore(conf->hash_locks + hash, flags);
+ }
+ size--;
+ hash--;
+ }
+
+- for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) {
+- if (do_wakeup & (1 << i))
+- wake_up(&conf->wait_for_stripe[i]);
+- }
+-
+ if (do_wakeup) {
++ wake_up(&conf->wait_for_stripe);
+ if (atomic_read(&conf->active_stripes) == 0)
+ wake_up(&conf->wait_for_quiescent);
+ if (conf->retry_read_aligned)
+@@ -687,15 +682,14 @@ raid5_get_active_stripe(struct r5conf *c
+ if (!sh) {
+ set_bit(R5_INACTIVE_BLOCKED,
+ &conf->cache_state);
+- wait_event_exclusive_cmd(
+- conf->wait_for_stripe[hash],
++ wait_event_lock_irq(
++ conf->wait_for_stripe,
+ !list_empty(conf->inactive_list + hash) &&
+ (atomic_read(&conf->active_stripes)
+ < (conf->max_nr_stripes * 3 / 4)
+ || !test_bit(R5_INACTIVE_BLOCKED,
+ &conf->cache_state)),
+- spin_unlock_irq(conf->hash_locks + hash),
+- spin_lock_irq(conf->hash_locks + hash));
++ *(conf->hash_locks + hash));
+ clear_bit(R5_INACTIVE_BLOCKED,
+ &conf->cache_state);
+ } else {
+@@ -720,9 +714,6 @@ raid5_get_active_stripe(struct r5conf *c
+ }
+ } while (sh == NULL);
+
+- if (!list_empty(conf->inactive_list + hash))
+- wake_up(&conf->wait_for_stripe[hash]);
+-
+ spin_unlock_irq(conf->hash_locks + hash);
+ return sh;
+ }
+@@ -2091,6 +2082,14 @@ static int resize_chunks(struct r5conf *
+ unsigned long cpu;
+ int err = 0;
+
++ /*
++ * Never shrink. And mddev_suspend() could deadlock if this is called
++ * from raid5d. In that case, scribble_disks and scribble_sectors
++ * should equal to new_disks and new_sectors
++ */
++ if (conf->scribble_disks >= new_disks &&
++ conf->scribble_sectors >= new_sectors)
++ return 0;
+ mddev_suspend(conf->mddev);
+ get_online_cpus();
+ for_each_present_cpu(cpu) {
+@@ -2112,6 +2111,10 @@ static int resize_chunks(struct r5conf *
+ }
+ put_online_cpus();
+ mddev_resume(conf->mddev);
++ if (!err) {
++ conf->scribble_disks = new_disks;
++ conf->scribble_sectors = new_sectors;
++ }
+ return err;
+ }
+
+@@ -2192,7 +2195,7 @@ static int resize_stripes(struct r5conf
+ cnt = 0;
+ list_for_each_entry(nsh, &newstripes, lru) {
+ lock_device_hash_lock(conf, hash);
+- wait_event_exclusive_cmd(conf->wait_for_stripe[hash],
++ wait_event_cmd(conf->wait_for_stripe,
+ !list_empty(conf->inactive_list + hash),
+ unlock_device_hash_lock(conf, hash),
+ lock_device_hash_lock(conf, hash));
+@@ -4238,7 +4241,6 @@ static void break_stripe_batch_list(stru
+ WARN_ON_ONCE(sh->state & ((1 << STRIPE_ACTIVE) |
+ (1 << STRIPE_SYNCING) |
+ (1 << STRIPE_REPLACED) |
+- (1 << STRIPE_PREREAD_ACTIVE) |
+ (1 << STRIPE_DELAYED) |
+ (1 << STRIPE_BIT_DELAY) |
+ (1 << STRIPE_FULL_WRITE) |
+@@ -4253,6 +4255,7 @@ static void break_stripe_batch_list(stru
+ (1 << STRIPE_REPLACED)));
+
+ set_mask_bits(&sh->state, ~(STRIPE_EXPAND_SYNC_FLAGS |
++ (1 << STRIPE_PREREAD_ACTIVE) |
+ (1 << STRIPE_DEGRADED)),
+ head_sh->state & (1 << STRIPE_INSYNC));
+
+@@ -6414,6 +6417,12 @@ static int raid5_alloc_percpu(struct r5c
+ }
+ put_online_cpus();
+
++ if (!err) {
++ conf->scribble_disks = max(conf->raid_disks,
++ conf->previous_raid_disks);
++ conf->scribble_sectors = max(conf->chunk_sectors,
++ conf->prev_chunk_sectors);
++ }
+ return err;
+ }
+
+@@ -6504,9 +6513,7 @@ static struct r5conf *setup_conf(struct
+ seqcount_init(&conf->gen_lock);
+ mutex_init(&conf->cache_size_mutex);
+ init_waitqueue_head(&conf->wait_for_quiescent);
+- for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) {
+- init_waitqueue_head(&conf->wait_for_stripe[i]);
+- }
++ init_waitqueue_head(&conf->wait_for_stripe);
+ init_waitqueue_head(&conf->wait_for_overlap);
+ INIT_LIST_HEAD(&conf->handle_list);
+ INIT_LIST_HEAD(&conf->hold_list);
+@@ -7015,8 +7022,8 @@ static int run(struct mddev *mddev)
+ }
+
+ if (discard_supported &&
+- mddev->queue->limits.max_discard_sectors >= stripe &&
+- mddev->queue->limits.discard_granularity >= stripe)
++ mddev->queue->limits.max_discard_sectors >= (stripe >> 9) &&
++ mddev->queue->limits.discard_granularity >= stripe)
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+ mddev->queue);
+ else
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/md/raid5.h linux-libre-4.4.7-gnu/drivers/md/raid5.h
+--- linux-libre-4.4-gnu/drivers/md/raid5.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/md/raid5.h 2016-04-12 12:09:26.000000000 -0400
+@@ -510,6 +510,8 @@ struct r5conf {
+ * conversions
+ */
+ } __percpu *percpu;
++ int scribble_disks;
++ int scribble_sectors;
+ #ifdef CONFIG_HOTPLUG_CPU
+ struct notifier_block cpu_notify;
+ #endif
+@@ -522,7 +524,7 @@ struct r5conf {
+ atomic_t empty_inactive_list_nr;
+ struct llist_head released_stripes;
+ wait_queue_head_t wait_for_quiescent;
+- wait_queue_head_t wait_for_stripe[NR_STRIPE_HASH_LOCKS];
++ wait_queue_head_t wait_for_stripe;
+ wait_queue_head_t wait_for_overlap;
+ unsigned long cache_state;
+ #define R5_INACTIVE_BLOCKED 1 /* release of inactive stripes blocked,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/dvb-core/dvb_frontend.c linux-libre-4.4.7-gnu/drivers/media/dvb-core/dvb_frontend.c
+--- linux-libre-4.4-gnu/drivers/media/dvb-core/dvb_frontend.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/dvb-core/dvb_frontend.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2313,9 +2313,9 @@ static int dvb_frontend_ioctl_legacy(str
+ dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n",
+ __func__, c->delivery_system, fe->ops.info.type);
+
+- /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
+- * do it, it is done for it. */
+- info->caps |= FE_CAN_INVERSION_AUTO;
++ /* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */
++ if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT))
++ info->caps |= FE_CAN_INVERSION_AUTO;
+ err = 0;
+ break;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/dvb-frontends/tda1004x.c linux-libre-4.4.7-gnu/drivers/media/dvb-frontends/tda1004x.c
+--- linux-libre-4.4-gnu/drivers/media/dvb-frontends/tda1004x.c 2016-01-10 21:00:52.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/dvb-frontends/tda1004x.c 2016-04-12 21:18:17.000000000 -0400
+@@ -895,9 +895,18 @@ static int tda1004x_get_fe(struct dvb_fr
+ {
+ struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
+ struct tda1004x_state* state = fe->demodulator_priv;
++ int status;
+
+ dprintk("%s\n", __func__);
+
++ status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
++ if (status == -1)
++ return -EIO;
++
++ /* Only update the properties cache if device is locked */
++ if (!(status & 8))
++ return 0;
++
+ // inversion status
+ fe_params->inversion = INVERSION_OFF;
+ if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/i2c/adv7511.c linux-libre-4.4.7-gnu/drivers/media/i2c/adv7511.c
+--- linux-libre-4.4-gnu/drivers/media/i2c/adv7511.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/i2c/adv7511.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1161,12 +1161,23 @@ static void adv7511_dbg_dump_edid(int lv
+ }
+ }
+
++static void adv7511_notify_no_edid(struct v4l2_subdev *sd)
++{
++ struct adv7511_state *state = get_adv7511_state(sd);
++ struct adv7511_edid_detect ed;
++
++ /* We failed to read the EDID, so send an event for this. */
++ ed.present = false;
++ ed.segment = adv7511_rd(sd, 0xc4);
++ v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
++ v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0);
++}
++
+ static void adv7511_edid_handler(struct work_struct *work)
+ {
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct adv7511_state *state = container_of(dwork, struct adv7511_state, edid_handler);
+ struct v4l2_subdev *sd = &state->sd;
+- struct adv7511_edid_detect ed;
+
+ v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+@@ -1191,9 +1202,7 @@ static void adv7511_edid_handler(struct
+ }
+
+ /* We failed to read the EDID, so send an event for this. */
+- ed.present = false;
+- ed.segment = adv7511_rd(sd, 0xc4);
+- v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
++ adv7511_notify_no_edid(sd);
+ v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__);
+ }
+
+@@ -1264,7 +1273,6 @@ static void adv7511_check_monitor_presen
+ /* update read only ctrls */
+ v4l2_ctrl_s_ctrl(state->hotplug_ctrl, adv7511_have_hotplug(sd) ? 0x1 : 0x0);
+ v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, adv7511_have_rx_sense(sd) ? 0x1 : 0x0);
+- v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
+
+ if ((status & MASK_ADV7511_HPD_DETECT) && ((status & MASK_ADV7511_MSEN_DETECT) || state->edid.segments)) {
+ v4l2_dbg(1, debug, sd, "%s: hotplug and (rx-sense or edid)\n", __func__);
+@@ -1294,6 +1302,7 @@ static void adv7511_check_monitor_presen
+ }
+ adv7511_s_power(sd, false);
+ memset(&state->edid, 0, sizeof(struct adv7511_state_edid));
++ adv7511_notify_no_edid(sd);
+ }
+ }
+
+@@ -1370,6 +1379,7 @@ static bool adv7511_check_edid_status(st
+ }
+ /* one more segment read ok */
+ state->edid.segments = segment + 1;
++ v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x1);
+ if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) {
+ /* Request next EDID segment */
+ v4l2_dbg(1, debug, sd, "%s: request segment %d\n", __func__, state->edid.segments);
+@@ -1389,7 +1399,6 @@ static bool adv7511_check_edid_status(st
+ ed.present = true;
+ ed.segment = 0;
+ state->edid_detect_counter++;
+- v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
+ v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
+ return ed.present;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/i2c/adv7604.c linux-libre-4.4.7-gnu/drivers/media/i2c/adv7604.c
+--- linux-libre-4.4-gnu/drivers/media/i2c/adv7604.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/i2c/adv7604.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1960,10 +1960,9 @@ static int adv76xx_isr(struct v4l2_subde
+ }
+
+ /* tx 5v detect */
+- tx_5v = io_read(sd, 0x70) & info->cable_det_mask;
++ tx_5v = irq_reg_0x70 & info->cable_det_mask;
+ if (tx_5v) {
+ v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
+- io_write(sd, 0x71, tx_5v);
+ adv76xx_s_detect_tx_5v_ctrl(sd);
+ if (handled)
+ *handled = true;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/i2c/ir-kbd-i2c.c linux-libre-4.4.7-gnu/drivers/media/i2c/ir-kbd-i2c.c
+--- linux-libre-4.4-gnu/drivers/media/i2c/ir-kbd-i2c.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/i2c/ir-kbd-i2c.c 2016-04-12 12:09:26.000000000 -0400
+@@ -478,7 +478,6 @@ static const struct i2c_device_id ir_kbd
+ { "ir_rx_z8f0811_hdpvr", 0 },
+ { }
+ };
+-MODULE_DEVICE_TABLE(i2c, ir_kbd_id);
+
+ static struct i2c_driver ir_kbd_driver = {
+ .driver = {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/pci/bt8xx/bttv-driver.c linux-libre-4.4.7-gnu/drivers/media/pci/bt8xx/bttv-driver.c
+--- linux-libre-4.4-gnu/drivers/media/pci/bt8xx/bttv-driver.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/pci/bt8xx/bttv-driver.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2334,6 +2334,19 @@ static int bttv_g_fmt_vid_overlay(struct
+ return 0;
+ }
+
++static void bttv_get_width_mask_vid_cap(const struct bttv_format *fmt,
++ unsigned int *width_mask,
++ unsigned int *width_bias)
++{
++ if (fmt->flags & FORMAT_FLAGS_PLANAR) {
++ *width_mask = ~15; /* width must be a multiple of 16 pixels */
++ *width_bias = 8; /* nearest */
++ } else {
++ *width_mask = ~3; /* width must be a multiple of 4 pixels */
++ *width_bias = 2; /* nearest */
++ }
++}
++
+ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+ {
+@@ -2343,6 +2356,7 @@ static int bttv_try_fmt_vid_cap(struct f
+ enum v4l2_field field;
+ __s32 width, height;
+ __s32 height2;
++ unsigned int width_mask, width_bias;
+ int rc;
+
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+@@ -2375,9 +2389,9 @@ static int bttv_try_fmt_vid_cap(struct f
+ width = f->fmt.pix.width;
+ height = f->fmt.pix.height;
+
++ bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias);
+ rc = limit_scaled_size_lock(fh, &width, &height, field,
+- /* width_mask: 4 pixels */ ~3,
+- /* width_bias: nearest */ 2,
++ width_mask, width_bias,
+ /* adjust_size */ 1,
+ /* adjust_crop */ 0);
+ if (0 != rc)
+@@ -2410,6 +2424,7 @@ static int bttv_s_fmt_vid_cap(struct fil
+ struct bttv_fh *fh = priv;
+ struct bttv *btv = fh->btv;
+ __s32 width, height;
++ unsigned int width_mask, width_bias;
+ enum v4l2_field field;
+
+ retval = bttv_switch_type(fh, f->type);
+@@ -2424,9 +2439,10 @@ static int bttv_s_fmt_vid_cap(struct fil
+ height = f->fmt.pix.height;
+ field = f->fmt.pix.field;
+
++ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
++ bttv_get_width_mask_vid_cap(fmt, &width_mask, &width_bias);
+ retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
+- /* width_mask: 4 pixels */ ~3,
+- /* width_bias: nearest */ 2,
++ width_mask, width_bias,
+ /* adjust_size */ 1,
+ /* adjust_crop */ 1);
+ if (0 != retval)
+@@ -2434,8 +2450,6 @@ static int bttv_s_fmt_vid_cap(struct fil
+
+ f->fmt.pix.field = field;
+
+- fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+-
+ /* update our state informations */
+ fh->fmt = fmt;
+ fh->cap.field = f->fmt.pix.field;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/pci/saa7134/saa7134-alsa.c linux-libre-4.4.7-gnu/drivers/media/pci/saa7134/saa7134-alsa.c
+--- linux-libre-4.4-gnu/drivers/media/pci/saa7134/saa7134-alsa.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/pci/saa7134/saa7134-alsa.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1211,6 +1211,8 @@ static int alsa_device_init(struct saa71
+
+ static int alsa_device_exit(struct saa7134_dev *dev)
+ {
++ if (!snd_saa7134_cards[dev->nr])
++ return 1;
+
+ snd_card_free(snd_saa7134_cards[dev->nr]);
+ snd_saa7134_cards[dev->nr] = NULL;
+@@ -1260,7 +1262,8 @@ static void saa7134_alsa_exit(void)
+ int idx;
+
+ for (idx = 0; idx < SNDRV_CARDS; idx++) {
+- snd_card_free(snd_saa7134_cards[idx]);
++ if (snd_saa7134_cards[idx])
++ snd_card_free(snd_saa7134_cards[idx]);
+ }
+
+ saa7134_dmasound_init = NULL;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/pci/saa7134/saa7134-video.c linux-libre-4.4.7-gnu/drivers/media/pci/saa7134/saa7134-video.c
+--- linux-libre-4.4-gnu/drivers/media/pci/saa7134/saa7134-video.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/pci/saa7134/saa7134-video.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1219,10 +1219,13 @@ static int saa7134_g_fmt_vid_cap(struct
+ f->fmt.pix.height = dev->height;
+ f->fmt.pix.field = dev->field;
+ f->fmt.pix.pixelformat = dev->fmt->fourcc;
+- f->fmt.pix.bytesperline =
+- (f->fmt.pix.width * dev->fmt->depth) >> 3;
++ if (dev->fmt->planar)
++ f->fmt.pix.bytesperline = f->fmt.pix.width;
++ else
++ f->fmt.pix.bytesperline =
++ (f->fmt.pix.width * dev->fmt->depth) / 8;
+ f->fmt.pix.sizeimage =
+- f->fmt.pix.height * f->fmt.pix.bytesperline;
++ (f->fmt.pix.height * f->fmt.pix.width * dev->fmt->depth) / 8;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return 0;
+ }
+@@ -1298,10 +1301,13 @@ static int saa7134_try_fmt_vid_cap(struc
+ if (f->fmt.pix.height > maxh)
+ f->fmt.pix.height = maxh;
+ f->fmt.pix.width &= ~0x03;
+- f->fmt.pix.bytesperline =
+- (f->fmt.pix.width * fmt->depth) >> 3;
++ if (fmt->planar)
++ f->fmt.pix.bytesperline = f->fmt.pix.width;
++ else
++ f->fmt.pix.bytesperline =
++ (f->fmt.pix.width * fmt->depth) / 8;
+ f->fmt.pix.sizeimage =
+- f->fmt.pix.height * f->fmt.pix.bytesperline;
++ (f->fmt.pix.height * f->fmt.pix.width * fmt->depth) / 8;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/platform/coda/coda-bit.c linux-libre-4.4.7-gnu/drivers/media/platform/coda/coda-bit.c
+--- linux-libre-4.4-gnu/drivers/media/platform/coda/coda-bit.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/platform/coda/coda-bit.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1342,7 +1342,7 @@ static void coda_finish_encode(struct co
+
+ /* Calculate bytesused field */
+ if (dst_buf->sequence == 0) {
+- vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr +
+ ctx->vpu_header_size[0] +
+ ctx->vpu_header_size[1] +
+ ctx->vpu_header_size[2]);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/rc/sunxi-cir.c linux-libre-4.4.7-gnu/drivers/media/rc/sunxi-cir.c
+--- linux-libre-4.4-gnu/drivers/media/rc/sunxi-cir.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/rc/sunxi-cir.c 2016-04-12 12:09:26.000000000 -0400
+@@ -153,6 +153,8 @@ static int sunxi_ir_probe(struct platfor
+ if (!ir)
+ return -ENOMEM;
+
++ spin_lock_init(&ir->ir_lock);
++
+ if (of_device_is_compatible(dn, "allwinner,sun5i-a13-ir"))
+ ir->fifo_size = 64;
+ else
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/tuners/si2157.c linux-libre-4.4.7-gnu/drivers/media/tuners/si2157.c
+--- linux-libre-4.4-gnu/drivers/media/tuners/si2157.c 2016-01-10 20:58:24.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/tuners/si2157.c 2016-04-12 21:15:52.000000000 -0400
+@@ -168,6 +168,7 @@ static int si2157_init(struct dvb_fronte
+ len = fw->data[fw->size - remaining];
+ if (len > SI2157_ARGLEN) {
+ dev_err(&client->dev, "Bad firmware length\n");
++ ret = -EINVAL;
+ goto err_release_firmware;
+ }
+ memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/usb/gspca/ov534.c linux-libre-4.4.7-gnu/drivers/media/usb/gspca/ov534.c
+--- linux-libre-4.4-gnu/drivers/media/usb/gspca/ov534.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/usb/gspca/ov534.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1491,8 +1491,13 @@ static void sd_set_streamparm(struct gsp
+ struct v4l2_fract *tpf = &cp->timeperframe;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+- /* Set requested framerate */
+- sd->frame_rate = tpf->denominator / tpf->numerator;
++ if (tpf->numerator == 0 || tpf->denominator == 0)
++ /* Set default framerate */
++ sd->frame_rate = 30;
++ else
++ /* Set requested framerate */
++ sd->frame_rate = tpf->denominator / tpf->numerator;
++
+ if (gspca_dev->streaming)
+ set_frame_rate(gspca_dev);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/usb/gspca/topro.c linux-libre-4.4.7-gnu/drivers/media/usb/gspca/topro.c
+--- linux-libre-4.4-gnu/drivers/media/usb/gspca/topro.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/usb/gspca/topro.c 2016-04-12 12:09:26.000000000 -0400
+@@ -4802,7 +4802,11 @@ static void sd_set_streamparm(struct gsp
+ struct v4l2_fract *tpf = &cp->timeperframe;
+ int fr, i;
+
+- sd->framerate = tpf->denominator / tpf->numerator;
++ if (tpf->numerator == 0 || tpf->denominator == 0)
++ sd->framerate = 30;
++ else
++ sd->framerate = tpf->denominator / tpf->numerator;
++
+ if (gspca_dev->streaming)
+ setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/usb/pwc/pwc-if.c linux-libre-4.4.7-gnu/drivers/media/usb/pwc/pwc-if.c
+--- linux-libre-4.4-gnu/drivers/media/usb/pwc/pwc-if.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/usb/pwc/pwc-if.c 2016-04-12 12:09:26.000000000 -0400
+@@ -91,6 +91,7 @@ static const struct usb_device_id pwc_de
+ { USB_DEVICE(0x0471, 0x0312) },
+ { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
+ { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
++ { USB_DEVICE(0x0471, 0x032C) }, /* Philips SPC 880NC PC Camera */
+ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
+ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
+@@ -811,6 +812,11 @@ static int usb_pwc_probe(struct usb_inte
+ name = "Philips SPC 900NC webcam";
+ type_id = 740;
+ break;
++ case 0x032C:
++ PWC_INFO("Philips SPC 880NC USB webcam detected.\n");
++ name = "Philips SPC 880NC webcam";
++ type_id = 740;
++ break;
+ default:
+ return -ENODEV;
+ break;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c linux-libre-4.4.7-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+--- linux-libre-4.4-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 2016-04-12 12:09:26.000000000 -0400
+@@ -415,7 +415,8 @@ static int get_v4l2_buffer32(struct v4l2
+ get_user(kp->index, &up->index) ||
+ get_user(kp->type, &up->type) ||
+ get_user(kp->flags, &up->flags) ||
+- get_user(kp->memory, &up->memory))
++ get_user(kp->memory, &up->memory) ||
++ get_user(kp->length, &up->length))
+ return -EFAULT;
+
+ if (V4L2_TYPE_IS_OUTPUT(kp->type))
+@@ -427,9 +428,6 @@ static int get_v4l2_buffer32(struct v4l2
+ return -EFAULT;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+- if (get_user(kp->length, &up->length))
+- return -EFAULT;
+-
+ num_planes = kp->length;
+ if (num_planes == 0) {
+ kp->m.planes = NULL;
+@@ -462,16 +460,14 @@ static int get_v4l2_buffer32(struct v4l2
+ } else {
+ switch (kp->memory) {
+ case V4L2_MEMORY_MMAP:
+- if (get_user(kp->length, &up->length) ||
+- get_user(kp->m.offset, &up->m.offset))
++ if (get_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_USERPTR:
+ {
+ compat_long_t tmp;
+
+- if (get_user(kp->length, &up->length) ||
+- get_user(tmp, &up->m.userptr))
++ if (get_user(tmp, &up->m.userptr))
+ return -EFAULT;
+
+ kp->m.userptr = (unsigned long)compat_ptr(tmp);
+@@ -513,7 +509,8 @@ static int put_v4l2_buffer32(struct v4l2
+ copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
+ put_user(kp->sequence, &up->sequence) ||
+ put_user(kp->reserved2, &up->reserved2) ||
+- put_user(kp->reserved, &up->reserved))
++ put_user(kp->reserved, &up->reserved) ||
++ put_user(kp->length, &up->length))
+ return -EFAULT;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+@@ -536,13 +533,11 @@ static int put_v4l2_buffer32(struct v4l2
+ } else {
+ switch (kp->memory) {
+ case V4L2_MEMORY_MMAP:
+- if (put_user(kp->length, &up->length) ||
+- put_user(kp->m.offset, &up->m.offset))
++ if (put_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_USERPTR:
+- if (put_user(kp->length, &up->length) ||
+- put_user(kp->m.userptr, &up->m.userptr))
++ if (put_user(kp->m.userptr, &up->m.userptr))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_OVERLAY:
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c linux-libre-4.4.7-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c
+--- linux-libre-4.4-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c 2016-04-12 12:09:26.000000000 -0400
+@@ -822,10 +822,10 @@ unsigned int vb2_poll(struct vb2_queue *
+ return res | POLLERR;
+
+ /*
+- * For output streams you can write as long as there are fewer buffers
+- * queued than there are buffers available.
++ * For output streams you can call write() as long as there are fewer
++ * buffers queued than there are buffers available.
+ */
+- if (q->is_output && q->queued_count < q->num_buffers)
++ if (q->is_output && q->fileio && q->queued_count < q->num_buffers)
+ return res | POLLOUT | POLLWRNORM;
+
+ if (list_empty(&q->done_list)) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/misc/cxl/pci.c linux-libre-4.4.7-gnu/drivers/misc/cxl/pci.c
+--- linux-libre-4.4-gnu/drivers/misc/cxl/pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/misc/cxl/pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -414,7 +414,7 @@ static int cxl_setup_psl_timebase(struct
+ delta = mftb() - psl_tb;
+ if (delta < 0)
+ delta = -delta;
+- } while (cputime_to_usecs(delta) > 16);
++ } while (tb_to_ns(delta) > 16000);
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/misc/cxl/vphb.c linux-libre-4.4.7-gnu/drivers/misc/cxl/vphb.c
+--- linux-libre-4.4-gnu/drivers/misc/cxl/vphb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/misc/cxl/vphb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -203,7 +203,7 @@ static int cxl_pcie_write_config(struct
+ mask <<= shift;
+ val <<= shift;
+
+- v = (in_le32(ioaddr) & ~mask) || (val & mask);
++ v = (in_le32(ioaddr) & ~mask) | (val & mask);
+
+ out_le32(ioaddr, v);
+ return PCIBIOS_SUCCESSFUL;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/misc/mei/bus.c linux-libre-4.4.7-gnu/drivers/misc/mei/bus.c
+--- linux-libre-4.4-gnu/drivers/misc/mei/bus.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/misc/mei/bus.c 2016-04-12 12:09:26.000000000 -0400
+@@ -53,6 +53,11 @@ ssize_t __mei_cl_send(struct mei_cl *cl,
+ bus = cl->dev;
+
+ mutex_lock(&bus->device_lock);
++ if (bus->dev_state != MEI_DEV_ENABLED) {
++ rets = -ENODEV;
++ goto out;
++ }
++
+ if (!mei_cl_is_connected(cl)) {
+ rets = -ENODEV;
+ goto out;
+@@ -109,6 +114,10 @@ ssize_t __mei_cl_recv(struct mei_cl *cl,
+ bus = cl->dev;
+
+ mutex_lock(&bus->device_lock);
++ if (bus->dev_state != MEI_DEV_ENABLED) {
++ rets = -ENODEV;
++ goto out;
++ }
+
+ cb = mei_cl_read_cb(cl, NULL);
+ if (cb)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/misc/mei/main.c linux-libre-4.4.7-gnu/drivers/misc/mei/main.c
+--- linux-libre-4.4-gnu/drivers/misc/mei/main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/misc/mei/main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -458,7 +458,11 @@ static int mei_ioctl_client_notify_reque
+ {
+ struct mei_cl *cl = file->private_data;
+
+- return mei_cl_notify_request(cl, file, request);
++ if (request != MEI_HBM_NOTIFICATION_START &&
++ request != MEI_HBM_NOTIFICATION_STOP)
++ return -EINVAL;
++
++ return mei_cl_notify_request(cl, file, (u8)request);
+ }
+
+ /**
+@@ -657,7 +661,9 @@ out:
+ * @file: pointer to file structure
+ * @band: band bitmap
+ *
+- * Return: poll mask
++ * Return: negative on error,
++ * 0 if it did no changes,
++ * and positive a process was added or deleted
+ */
+ static int mei_fasync(int fd, struct file *file, int band)
+ {
+@@ -665,7 +671,7 @@ static int mei_fasync(int fd, struct fil
+ struct mei_cl *cl = file->private_data;
+
+ if (!mei_cl_is_connected(cl))
+- return POLLERR;
++ return -ENODEV;
+
+ return fasync_helper(fd, file, band, &cl->ev_async);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/card/block.c linux-libre-4.4.7-gnu/drivers/mmc/card/block.c
+--- linux-libre-4.4-gnu/drivers/mmc/card/block.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/card/block.c 2016-04-12 12:09:26.000000000 -0400
+@@ -596,6 +596,14 @@ static int mmc_blk_ioctl_cmd(struct bloc
+ struct mmc_card *card;
+ int err = 0, ioc_err = 0;
+
++ /*
++ * The caller must have CAP_SYS_RAWIO, and must be calling this on the
++ * whole block device, not on a partition. This prevents overspray
++ * between sibling partitions.
++ */
++ if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
++ return -EPERM;
++
+ idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
+ if (IS_ERR(idata))
+ return PTR_ERR(idata);
+@@ -638,6 +646,14 @@ static int mmc_blk_ioctl_multi_cmd(struc
+ int i, err = 0, ioc_err = 0;
+ __u64 num_of_cmds;
+
++ /*
++ * The caller must have CAP_SYS_RAWIO, and must be calling this on the
++ * whole block device, not on a partition. This prevents overspray
++ * between sibling partitions.
++ */
++ if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
++ return -EPERM;
++
+ if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
+ sizeof(num_of_cmds)))
+ return -EFAULT;
+@@ -693,14 +709,6 @@ cmd_err:
+ static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
+ {
+- /*
+- * The caller must have CAP_SYS_RAWIO, and must be calling this on the
+- * whole block device, not on a partition. This prevents overspray
+- * between sibling partitions.
+- */
+- if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
+- return -EPERM;
+-
+ switch (cmd) {
+ case MMC_IOC_CMD:
+ return mmc_blk_ioctl_cmd(bdev,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/core/mmc.c linux-libre-4.4.7-gnu/drivers/mmc/core/mmc.c
+--- linux-libre-4.4-gnu/drivers/mmc/core/mmc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/core/mmc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1076,8 +1076,7 @@ static int mmc_select_hs400(struct mmc_c
+ mmc_set_clock(host, max_dtr);
+
+ /* Switch card to HS mode */
+- val = EXT_CSD_TIMING_HS |
+- card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
++ val = EXT_CSD_TIMING_HS;
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, val,
+ card->ext_csd.generic_cmd6_time,
+@@ -1160,8 +1159,7 @@ int mmc_hs400_to_hs200(struct mmc_card *
+ mmc_set_clock(host, max_dtr);
+
+ /* Switch HS400 to HS DDR */
+- val = EXT_CSD_TIMING_HS |
+- card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
++ val = EXT_CSD_TIMING_HS;
+ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
+ val, card->ext_csd.generic_cmd6_time,
+ true, send_status, true);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/core/sd.c linux-libre-4.4.7-gnu/drivers/mmc/core/sd.c
+--- linux-libre-4.4-gnu/drivers/mmc/core/sd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/core/sd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -626,9 +626,9 @@ static int mmc_sd_init_uhs_card(struct m
+ * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
+ */
+ if (!mmc_host_is_spi(card->host) &&
+- (card->sd_bus_speed == UHS_SDR50_BUS_SPEED ||
+- card->sd_bus_speed == UHS_DDR50_BUS_SPEED ||
+- card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) {
++ (card->host->ios.timing == MMC_TIMING_UHS_SDR50 ||
++ card->host->ios.timing == MMC_TIMING_UHS_DDR50 ||
++ card->host->ios.timing == MMC_TIMING_UHS_SDR104)) {
+ err = mmc_execute_tuning(card);
+
+ /*
+@@ -638,7 +638,7 @@ static int mmc_sd_init_uhs_card(struct m
+ * difference between v3.00 and 3.01 spec means that CMD19
+ * tuning is also available for DDR50 mode.
+ */
+- if (err && card->sd_bus_speed == UHS_DDR50_BUS_SPEED) {
++ if (err && card->host->ios.timing == MMC_TIMING_UHS_DDR50) {
+ pr_warn("%s: ddr50 tuning failed\n",
+ mmc_hostname(card->host));
+ err = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/core/sdio.c linux-libre-4.4.7-gnu/drivers/mmc/core/sdio.c
+--- linux-libre-4.4-gnu/drivers/mmc/core/sdio.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/core/sdio.c 2016-04-12 12:09:26.000000000 -0400
+@@ -535,8 +535,8 @@ static int mmc_sdio_init_uhs_card(struct
+ * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
+ */
+ if (!mmc_host_is_spi(card->host) &&
+- ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) ||
+- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)))
++ ((card->host->ios.timing == MMC_TIMING_UHS_SDR50) ||
++ (card->host->ios.timing == MMC_TIMING_UHS_SDR104)))
+ err = mmc_execute_tuning(card);
+ out:
+ return err;
+@@ -630,7 +630,7 @@ try_again:
+ */
+ if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
+ err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
+- ocr);
++ ocr_card);
+ if (err == -EAGAIN) {
+ sdio_reset(host);
+ mmc_go_idle(host);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/mmci.c linux-libre-4.4.7-gnu/drivers/mmc/host/mmci.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/mmci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/mmci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1886,7 +1886,7 @@ static struct amba_id mmci_ids[] = {
+ {
+ .id = 0x00280180,
+ .mask = 0x00ffffff,
+- .data = &variant_u300,
++ .data = &variant_nomadik,
+ },
+ {
+ .id = 0x00480180,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/mmc_spi.c linux-libre-4.4.7-gnu/drivers/mmc/host/mmc_spi.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/mmc_spi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/mmc_spi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1436,6 +1436,12 @@ static int mmc_spi_probe(struct spi_devi
+ host->pdata->cd_debounce);
+ if (status != 0)
+ goto fail_add_host;
++
++ /* The platform has a CD GPIO signal that may support
++ * interrupts, so let mmc_gpiod_request_cd_irq() decide
++ * if polling is needed or not.
++ */
++ mmc->caps &= ~MMC_CAP_NEEDS_POLL;
+ mmc_gpiod_request_cd_irq(mmc);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/pxamci.c linux-libre-4.4.7-gnu/drivers/mmc/host/pxamci.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/pxamci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/pxamci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -804,7 +804,7 @@ static int pxamci_probe(struct platform_
+ dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
+ goto out;
+ } else {
+- mmc->caps |= host->pdata->gpio_card_ro_invert ?
++ mmc->caps2 |= host->pdata->gpio_card_ro_invert ?
+ 0 : MMC_CAP2_RO_ACTIVE_HIGH;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/sdhci-acpi.c linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci-acpi.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/sdhci-acpi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci-acpi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -146,6 +146,33 @@ static const struct sdhci_acpi_chip sdhc
+ .ops = &sdhci_acpi_ops_int,
+ };
+
++static int bxt_get_cd(struct mmc_host *mmc)
++{
++ int gpio_cd = mmc_gpio_get_cd(mmc);
++ struct sdhci_host *host = mmc_priv(mmc);
++ unsigned long flags;
++ int ret = 0;
++
++ if (!gpio_cd)
++ return 0;
++
++ pm_runtime_get_sync(mmc->parent);
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->flags & SDHCI_DEVICE_DEAD)
++ goto out;
++
++ ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
++out:
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ pm_runtime_mark_last_busy(mmc->parent);
++ pm_runtime_put_autosuspend(mmc->parent);
++
++ return ret;
++}
++
+ static int sdhci_acpi_emmc_probe_slot(struct platform_device *pdev,
+ const char *hid, const char *uid)
+ {
+@@ -196,6 +223,9 @@ static int sdhci_acpi_sd_probe_slot(stru
+
+ /* Platform specific code during sd probe slot goes here */
+
++ if (hid && !strcmp(hid, "80865ACA"))
++ host->mmc_host_ops.get_cd = bxt_get_cd;
++
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/sdhci.c linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/sdhci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -540,9 +540,12 @@ static int sdhci_adma_table_pre(struct s
+
+ BUG_ON(len > 65536);
+
+- /* tran, valid */
+- sdhci_adma_write_desc(host, desc, addr, len, ADMA2_TRAN_VALID);
+- desc += host->desc_sz;
++ if (len) {
++ /* tran, valid */
++ sdhci_adma_write_desc(host, desc, addr, len,
++ ADMA2_TRAN_VALID);
++ desc += host->desc_sz;
++ }
+
+ /*
+ * If this triggers then we have a calculation bug
+@@ -663,9 +666,20 @@ static u8 sdhci_calc_timeout(struct sdhc
+ if (!data)
+ target_timeout = cmd->busy_timeout * 1000;
+ else {
+- target_timeout = data->timeout_ns / 1000;
+- if (host->clock)
+- target_timeout += data->timeout_clks / host->clock;
++ target_timeout = DIV_ROUND_UP(data->timeout_ns, 1000);
++ if (host->clock && data->timeout_clks) {
++ unsigned long long val;
++
++ /*
++ * data->timeout_clks is in units of clock cycles.
++ * host->clock is in Hz. target_timeout is in us.
++ * Hence, us = 1000000 * cycles / Hz. Round up.
++ */
++ val = 1000000 * data->timeout_clks;
++ if (do_div(val, host->clock))
++ target_timeout++;
++ target_timeout += val;
++ }
+ }
+
+ /*
+@@ -1364,7 +1378,7 @@ static void sdhci_request(struct mmc_hos
+ sdhci_runtime_pm_get(host);
+
+ /* Firstly check card presence */
+- present = sdhci_do_get_cd(host);
++ present = mmc->ops->get_cd(mmc);
+
+ spin_lock_irqsave(&host->lock, flags);
+
+@@ -2760,7 +2774,7 @@ static int sdhci_runtime_pm_put(struct s
+
+ static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
+ {
+- if (host->runtime_suspended || host->bus_on)
++ if (host->bus_on)
+ return;
+ host->bus_on = true;
+ pm_runtime_get_noresume(host->mmc->parent);
+@@ -2768,7 +2782,7 @@ static void sdhci_runtime_pm_bus_on(stru
+
+ static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
+ {
+- if (host->runtime_suspended || !host->bus_on)
++ if (!host->bus_on)
+ return;
+ host->bus_on = false;
+ pm_runtime_put_noidle(host->mmc->parent);
+@@ -2861,6 +2875,8 @@ struct sdhci_host *sdhci_alloc_host(stru
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
++ host->mmc_host_ops = sdhci_ops;
++ mmc->ops = &host->mmc_host_ops;
+
+ return host;
+ }
+@@ -3057,7 +3073,6 @@ int sdhci_add_host(struct sdhci_host *ho
+ /*
+ * Set host parameters.
+ */
+- mmc->ops = &sdhci_ops;
+ max_clk = host->max_clk;
+
+ if (host->ops->get_min_clock)
+@@ -3091,14 +3106,14 @@ int sdhci_add_host(struct sdhci_host *ho
+ if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
+ host->timeout_clk *= 1000;
+
++ if (override_timeout_clk)
++ host->timeout_clk = override_timeout_clk;
++
+ mmc->max_busy_timeout = host->ops->get_max_timeout_count ?
+ host->ops->get_max_timeout_count(host) : 1 << 27;
+ mmc->max_busy_timeout /= host->timeout_clk;
+ }
+
+- if (override_timeout_clk)
+- host->timeout_clk = override_timeout_clk;
+-
+ mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
+ mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/sdhci.h linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci.h
+--- linux-libre-4.4-gnu/drivers/mmc/host/sdhci.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci.h 2016-04-12 12:09:26.000000000 -0400
+@@ -425,6 +425,7 @@ struct sdhci_host {
+
+ /* Internal data */
+ struct mmc_host *mmc; /* MMC structure */
++ struct mmc_host_ops mmc_host_ops; /* MMC host ops */
+ u64 dma_mask; /* custom DMA mask */
+
+ #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/sdhci-pci-core.c linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci-pci-core.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/sdhci-pci-core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/sdhci-pci-core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -277,7 +277,7 @@ static int spt_select_drive_strength(str
+ if (sdhci_pci_spt_drive_strength > 0)
+ drive_strength = sdhci_pci_spt_drive_strength & 0xf;
+ else
+- drive_strength = 1; /* 33-ohm */
++ drive_strength = 0; /* Default 50-ohm */
+
+ if ((mmc_driver_type_mask(drive_strength) & card_drv) == 0)
+ drive_strength = 0; /* Default 50-ohm */
+@@ -330,6 +330,33 @@ static void spt_read_drive_strength(stru
+ sdhci_pci_spt_drive_strength = 0x10 | ((val >> 12) & 0xf);
+ }
+
++static int bxt_get_cd(struct mmc_host *mmc)
++{
++ int gpio_cd = mmc_gpio_get_cd(mmc);
++ struct sdhci_host *host = mmc_priv(mmc);
++ unsigned long flags;
++ int ret = 0;
++
++ if (!gpio_cd)
++ return 0;
++
++ pm_runtime_get_sync(mmc->parent);
++
++ spin_lock_irqsave(&host->lock, flags);
++
++ if (host->flags & SDHCI_DEVICE_DEAD)
++ goto out;
++
++ ret = !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
++out:
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ pm_runtime_mark_last_busy(mmc->parent);
++ pm_runtime_put_autosuspend(mmc->parent);
++
++ return ret;
++}
++
+ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
+ {
+ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
+@@ -362,6 +389,10 @@ static int byt_sd_probe_slot(struct sdhc
+ slot->cd_con_id = NULL;
+ slot->cd_idx = 0;
+ slot->cd_override_level = true;
++ if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXT_SD ||
++ slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD)
++ slot->host->mmc_host_ops.get_cd = bxt_get_cd;
++
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/sh_mmcif.c linux-libre-4.4.7-gnu/drivers/mmc/host/sh_mmcif.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/sh_mmcif.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/sh_mmcif.c 2016-04-12 12:09:26.000000000 -0400
+@@ -397,38 +397,26 @@ static void sh_mmcif_start_dma_tx(struct
+ }
+
+ static struct dma_chan *
+-sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
+- struct sh_mmcif_plat_data *pdata,
+- enum dma_transfer_direction direction)
++sh_mmcif_request_dma_pdata(struct sh_mmcif_host *host, uintptr_t slave_id)
+ {
+- struct dma_slave_config cfg = { 0, };
+- struct dma_chan *chan;
+- void *slave_data = NULL;
+- struct resource *res;
+- struct device *dev = sh_mmcif_host_to_dev(host);
+ dma_cap_mask_t mask;
+- int ret;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
++ if (slave_id <= 0)
++ return NULL;
+
+- if (pdata)
+- slave_data = direction == DMA_MEM_TO_DEV ?
+- (void *)pdata->slave_id_tx :
+- (void *)pdata->slave_id_rx;
+-
+- chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+- slave_data, dev,
+- direction == DMA_MEM_TO_DEV ? "tx" : "rx");
+-
+- dev_dbg(dev, "%s: %s: got channel %p\n", __func__,
+- direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan);
++ return dma_request_channel(mask, shdma_chan_filter, (void *)slave_id);
++}
+
+- if (!chan)
+- return NULL;
++static int sh_mmcif_dma_slave_config(struct sh_mmcif_host *host,
++ struct dma_chan *chan,
++ enum dma_transfer_direction direction)
++{
++ struct resource *res;
++ struct dma_slave_config cfg = { 0, };
+
+ res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);
+-
+ cfg.direction = direction;
+
+ if (direction == DMA_DEV_TO_MEM) {
+@@ -439,38 +427,42 @@ sh_mmcif_request_dma_one(struct sh_mmcif
+ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ }
+
+- ret = dmaengine_slave_config(chan, &cfg);
+- if (ret < 0) {
+- dma_release_channel(chan);
+- return NULL;
+- }
+-
+- return chan;
++ return dmaengine_slave_config(chan, &cfg);
+ }
+
+-static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
+- struct sh_mmcif_plat_data *pdata)
++static void sh_mmcif_request_dma(struct sh_mmcif_host *host)
+ {
+ struct device *dev = sh_mmcif_host_to_dev(host);
+ host->dma_active = false;
+
+- if (pdata) {
+- if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+- return;
+- } else if (!dev->of_node) {
+- return;
++ /* We can only either use DMA for both Tx and Rx or not use it at all */
++ if (IS_ENABLED(CONFIG_SUPERH) && dev->platform_data) {
++ struct sh_mmcif_plat_data *pdata = dev->platform_data;
++
++ host->chan_tx = sh_mmcif_request_dma_pdata(host,
++ pdata->slave_id_tx);
++ host->chan_rx = sh_mmcif_request_dma_pdata(host,
++ pdata->slave_id_rx);
++ } else {
++ host->chan_tx = dma_request_slave_channel(dev, "tx");
++ host->chan_rx = dma_request_slave_channel(dev, "rx");
+ }
++ dev_dbg(dev, "%s: got channel TX %p RX %p\n", __func__, host->chan_tx,
++ host->chan_rx);
+
+- /* We can only either use DMA for both Tx and Rx or not use it at all */
+- host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV);
+- if (!host->chan_tx)
+- return;
++ if (!host->chan_tx || !host->chan_rx ||
++ sh_mmcif_dma_slave_config(host, host->chan_tx, DMA_MEM_TO_DEV) ||
++ sh_mmcif_dma_slave_config(host, host->chan_rx, DMA_DEV_TO_MEM))
++ goto error;
+
+- host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM);
+- if (!host->chan_rx) {
++ return;
++
++error:
++ if (host->chan_tx)
+ dma_release_channel(host->chan_tx);
+- host->chan_tx = NULL;
+- }
++ if (host->chan_rx)
++ dma_release_channel(host->chan_rx);
++ host->chan_tx = host->chan_rx = NULL;
+ }
+
+ static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
+@@ -1102,7 +1094,7 @@ static void sh_mmcif_set_ios(struct mmc_
+ if (ios->power_mode == MMC_POWER_UP) {
+ if (!host->card_present) {
+ /* See if we also get DMA */
+- sh_mmcif_request_dma(host, dev->platform_data);
++ sh_mmcif_request_dma(host);
+ host->card_present = true;
+ }
+ sh_mmcif_set_power(host, ios);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mmc/host/usdhi6rol0.c linux-libre-4.4.7-gnu/drivers/mmc/host/usdhi6rol0.c
+--- linux-libre-4.4-gnu/drivers/mmc/host/usdhi6rol0.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mmc/host/usdhi6rol0.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1634,7 +1634,7 @@ static void usdhi6_timeout_work(struct w
+ struct usdhi6_host *host = container_of(d, struct usdhi6_host, timeout_work);
+ struct mmc_request *mrq = host->mrq;
+ struct mmc_data *data = mrq ? mrq->data : NULL;
+- struct scatterlist *sg = host->sg ?: data->sg;
++ struct scatterlist *sg;
+
+ dev_warn(mmc_dev(host->mmc),
+ "%s timeout wait %u CMD%d: IRQ 0x%08x:0x%08x, last IRQ 0x%08x\n",
+@@ -1666,6 +1666,7 @@ static void usdhi6_timeout_work(struct w
+ case USDHI6_WAIT_FOR_MWRITE:
+ case USDHI6_WAIT_FOR_READ:
+ case USDHI6_WAIT_FOR_WRITE:
++ sg = host->sg ?: data->sg;
+ dev_dbg(mmc_dev(host->mmc),
+ "%c: page #%u @ +0x%zx %ux%u in SG%u. Current SG %u bytes @ %u\n",
+ data->flags & MMC_DATA_READ ? 'R' : 'W', host->page_idx,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mtd/nand/nand_base.c linux-libre-4.4.7-gnu/drivers/mtd/nand/nand_base.c
+--- linux-libre-4.4-gnu/drivers/mtd/nand/nand_base.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mtd/nand/nand_base.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3995,6 +3995,9 @@ int nand_scan_ident(struct mtd_info *mtd
+ return ret;
+ }
+
++ if (!mtd->name && mtd->dev.parent)
++ mtd->name = dev_name(mtd->dev.parent);
++
+ /* Set the default functions */
+ nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mtd/onenand/onenand_base.c linux-libre-4.4.7-gnu/drivers/mtd/onenand/onenand_base.c
+--- linux-libre-4.4-gnu/drivers/mtd/onenand/onenand_base.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mtd/onenand/onenand_base.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2599,6 +2599,7 @@ static int onenand_default_block_markbad
+ */
+ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
+ {
++ struct onenand_chip *this = mtd->priv;
+ int ret;
+
+ ret = onenand_block_isbad(mtd, ofs);
+@@ -2610,7 +2611,7 @@ static int onenand_block_markbad(struct
+ }
+
+ onenand_get_device(mtd, FL_WRITING);
+- ret = mtd_block_markbad(mtd, ofs);
++ ret = this->block_markbad(mtd, ofs);
+ onenand_release_device(mtd);
+ return ret;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/mtd/ubi/upd.c linux-libre-4.4.7-gnu/drivers/mtd/ubi/upd.c
+--- linux-libre-4.4-gnu/drivers/mtd/ubi/upd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/mtd/ubi/upd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_devi
+ vol->changing_leb = 1;
+ vol->ch_lnum = req->lnum;
+
+- vol->upd_buf = vmalloc(req->bytes);
++ vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
+ if (!vol->upd_buf)
+ return -ENOMEM;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/bonding/bond_main.c linux-libre-4.4.7-gnu/drivers/net/bonding/bond_main.c
+--- linux-libre-4.4-gnu/drivers/net/bonding/bond_main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/bonding/bond_main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -214,6 +214,8 @@ static void bond_uninit(struct net_devic
+ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
+ struct rtnl_link_stats64 *stats);
+ static void bond_slave_arr_handler(struct work_struct *work);
++static bool bond_time_in_interval(struct bonding *bond, unsigned long last_act,
++ int mod);
+
+ /*---------------------------- General routines -----------------------------*/
+
+@@ -1207,7 +1209,6 @@ static int bond_master_upper_dev_link(st
+ err = netdev_master_upper_dev_link_private(slave_dev, bond_dev, slave);
+ if (err)
+ return err;
+- slave_dev->flags |= IFF_SLAVE;
+ rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE, GFP_KERNEL);
+ return 0;
+ }
+@@ -1465,6 +1466,9 @@ int bond_enslave(struct net_device *bond
+ }
+ }
+
++ /* set slave flag before open to prevent IPv6 addrconf */
++ slave_dev->flags |= IFF_SLAVE;
++
+ /* open the slave since the application closed it */
+ res = dev_open(slave_dev);
+ if (res) {
+@@ -1725,6 +1729,7 @@ err_close:
+ dev_close(slave_dev);
+
+ err_restore_mac:
++ slave_dev->flags &= ~IFF_SLAVE;
+ if (!bond->params.fail_over_mac ||
+ BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
+ /* XXX TODO - fom follow mode needs to change master's
+@@ -2415,7 +2420,7 @@ int bond_arp_rcv(const struct sk_buff *s
+ struct slave *slave)
+ {
+ struct arphdr *arp = (struct arphdr *)skb->data;
+- struct slave *curr_active_slave;
++ struct slave *curr_active_slave, *curr_arp_slave;
+ unsigned char *arp_ptr;
+ __be32 sip, tip;
+ int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
+@@ -2462,26 +2467,41 @@ int bond_arp_rcv(const struct sk_buff *s
+ &sip, &tip);
+
+ curr_active_slave = rcu_dereference(bond->curr_active_slave);
++ curr_arp_slave = rcu_dereference(bond->current_arp_slave);
+
+- /* Backup slaves won't see the ARP reply, but do come through
+- * here for each ARP probe (so we swap the sip/tip to validate
+- * the probe). In a "redundant switch, common router" type of
+- * configuration, the ARP probe will (hopefully) travel from
+- * the active, through one switch, the router, then the other
+- * switch before reaching the backup.
++ /* We 'trust' the received ARP enough to validate it if:
+ *
+- * We 'trust' the arp requests if there is an active slave and
+- * it received valid arp reply(s) after it became active. This
+- * is done to avoid endless looping when we can't reach the
++ * (a) the slave receiving the ARP is active (which includes the
++ * current ARP slave, if any), or
++ *
++ * (b) the receiving slave isn't active, but there is a currently
++ * active slave and it received valid arp reply(s) after it became
++ * the currently active slave, or
++ *
++ * (c) there is an ARP slave that sent an ARP during the prior ARP
++ * interval, and we receive an ARP reply on any slave. We accept
++ * these because switch FDB update delays may deliver the ARP
++ * reply to a slave other than the sender of the ARP request.
++ *
++ * Note: for (b), backup slaves are receiving the broadcast ARP
++ * request, not a reply. This request passes from the sending
++ * slave through the L2 switch(es) to the receiving slave. Since
++ * this is checking the request, sip/tip are swapped for
++ * validation.
++ *
++ * This is done to avoid endless looping when we can't reach the
+ * arp_ip_target and fool ourselves with our own arp requests.
+ */
+-
+ if (bond_is_active_slave(slave))
+ bond_validate_arp(bond, slave, sip, tip);
+ else if (curr_active_slave &&
+ time_after(slave_last_rx(bond, curr_active_slave),
+ curr_active_slave->last_link_up))
+ bond_validate_arp(bond, slave, tip, sip);
++ else if (curr_arp_slave && (arp->ar_op == htons(ARPOP_REPLY)) &&
++ bond_time_in_interval(bond,
++ dev_trans_start(curr_arp_slave->dev), 1))
++ bond_validate_arp(bond, slave, sip, tip);
+
+ out_unlock:
+ if (arp != (struct arphdr *)skb->data)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/can/usb/ems_usb.c linux-libre-4.4.7-gnu/drivers/net/can/usb/ems_usb.c
+--- linux-libre-4.4-gnu/drivers/net/can/usb/ems_usb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/can/usb/ems_usb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -117,6 +117,9 @@ MODULE_LICENSE("GPL v2");
+ */
+ #define EMS_USB_ARM7_CLOCK 8000000
+
++#define CPC_TX_QUEUE_TRIGGER_LOW 25
++#define CPC_TX_QUEUE_TRIGGER_HIGH 35
++
+ /*
+ * CAN-Message representation in a CPC_MSG. Message object type is
+ * CPC_MSG_TYPE_CAN_FRAME or CPC_MSG_TYPE_RTR_FRAME or
+@@ -278,6 +281,11 @@ static void ems_usb_read_interrupt_callb
+ switch (urb->status) {
+ case 0:
+ dev->free_slots = dev->intr_in_buffer[1];
++ if(dev->free_slots > CPC_TX_QUEUE_TRIGGER_HIGH){
++ if (netif_queue_stopped(netdev)){
++ netif_wake_queue(netdev);
++ }
++ }
+ break;
+
+ case -ECONNRESET: /* unlink */
+@@ -526,8 +534,6 @@ static void ems_usb_write_bulk_callback(
+ /* Release context */
+ context->echo_index = MAX_TX_URBS;
+
+- if (netif_queue_stopped(netdev))
+- netif_wake_queue(netdev);
+ }
+
+ /*
+@@ -587,7 +593,7 @@ static int ems_usb_start(struct ems_usb
+ int err, i;
+
+ dev->intr_in_buffer[0] = 0;
+- dev->free_slots = 15; /* initial size */
++ dev->free_slots = 50; /* initial size */
+
+ for (i = 0; i < MAX_RX_URBS; i++) {
+ struct urb *urb = NULL;
+@@ -835,7 +841,7 @@ static netdev_tx_t ems_usb_start_xmit(st
+
+ /* Slow down tx path */
+ if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
+- dev->free_slots < 5) {
++ dev->free_slots < CPC_TX_QUEUE_TRIGGER_LOW) {
+ netif_stop_queue(netdev);
+ }
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/can/usb/gs_usb.c linux-libre-4.4.7-gnu/drivers/net/can/usb/gs_usb.c
+--- linux-libre-4.4-gnu/drivers/net/can/usb/gs_usb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/can/usb/gs_usb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -826,9 +826,8 @@ static struct gs_can *gs_make_candev(uns
+ static void gs_destroy_candev(struct gs_can *dev)
+ {
+ unregister_candev(dev->netdev);
+- free_candev(dev->netdev);
+ usb_kill_anchored_urbs(&dev->tx_submitted);
+- kfree(dev);
++ free_candev(dev->netdev);
+ }
+
+ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+@@ -913,12 +912,15 @@ static int gs_usb_probe(struct usb_inter
+ for (i = 0; i < icount; i++) {
+ dev->canch[i] = gs_make_candev(i, intf);
+ if (IS_ERR_OR_NULL(dev->canch[i])) {
++ /* save error code to return later */
++ rc = PTR_ERR(dev->canch[i]);
++
+ /* on failure destroy previously created candevs */
+ icount = i;
+- for (i = 0; i < icount; i++) {
++ for (i = 0; i < icount; i++)
+ gs_destroy_candev(dev->canch[i]);
+- dev->canch[i] = NULL;
+- }
++
++ usb_kill_anchored_urbs(&dev->rx_submitted);
+ kfree(dev);
+ return rc;
+ }
+@@ -939,16 +941,12 @@ static void gs_usb_disconnect(struct usb
+ return;
+ }
+
+- for (i = 0; i < GS_MAX_INTF; i++) {
+- struct gs_can *can = dev->canch[i];
+-
+- if (!can)
+- continue;
+-
+- gs_destroy_candev(can);
+- }
++ for (i = 0; i < GS_MAX_INTF; i++)
++ if (dev->canch[i])
++ gs_destroy_candev(dev->canch[i]);
+
+ usb_kill_anchored_urbs(&dev->rx_submitted);
++ kfree(dev);
+ }
+
+ static const struct usb_device_id gs_usb_table[] = {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/dsa/mv88e6xxx.c linux-libre-4.4.7-gnu/drivers/net/dsa/mv88e6xxx.c
+--- linux-libre-4.4-gnu/drivers/net/dsa/mv88e6xxx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/dsa/mv88e6xxx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1519,7 +1519,7 @@ int mv88e6xxx_port_vlan_add(struct dsa_s
+
+ /* no PVID with ranges, otherwise it's a bug */
+ if (pvid)
+- err = _mv88e6xxx_port_pvid_set(ds, port, vid);
++ err = _mv88e6xxx_port_pvid_set(ds, port, vlan->vid_end);
+ unlock:
+ mutex_unlock(&ps->smi_mutex);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/broadcom/tg3.c linux-libre-4.4.7-gnu/drivers/net/ethernet/broadcom/tg3.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/broadcom/tg3.c 2016-01-10 21:05:42.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/broadcom/tg3.c 2016-04-12 21:22:39.000000000 -0400
+@@ -7824,6 +7824,14 @@ static int tigon3_dma_hwbug_workaround(s
+ return ret;
+ }
+
++static bool tg3_tso_bug_gso_check(struct tg3_napi *tnapi, struct sk_buff *skb)
++{
++ /* Check if we will never have enough descriptors,
++ * as gso_segs can be more than current ring size
++ */
++ return skb_shinfo(skb)->gso_segs < tnapi->tx_pending / 3;
++}
++
+ static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
+
+ /* Use GSO to workaround all TSO packets that meet HW bug conditions
+@@ -7927,14 +7935,19 @@ static netdev_tx_t tg3_start_xmit(struct
+ * vlan encapsulated.
+ */
+ if (skb->protocol == htons(ETH_P_8021Q) ||
+- skb->protocol == htons(ETH_P_8021AD))
+- return tg3_tso_bug(tp, tnapi, txq, skb);
++ skb->protocol == htons(ETH_P_8021AD)) {
++ if (tg3_tso_bug_gso_check(tnapi, skb))
++ return tg3_tso_bug(tp, tnapi, txq, skb);
++ goto drop;
++ }
+
+ if (!skb_is_gso_v6(skb)) {
+ if (unlikely((ETH_HLEN + hdr_len) > 80) &&
+- tg3_flag(tp, TSO_BUG))
+- return tg3_tso_bug(tp, tnapi, txq, skb);
+-
++ tg3_flag(tp, TSO_BUG)) {
++ if (tg3_tso_bug_gso_check(tnapi, skb))
++ return tg3_tso_bug(tp, tnapi, txq, skb);
++ goto drop;
++ }
+ ip_csum = iph->check;
+ ip_tot_len = iph->tot_len;
+ iph->check = 0;
+@@ -8066,7 +8079,7 @@ static netdev_tx_t tg3_start_xmit(struct
+ if (would_hit_hwbug) {
+ tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, i);
+
+- if (mss) {
++ if (mss && tg3_tso_bug_gso_check(tnapi, skb)) {
+ /* If it's a TSO packet, do GSO instead of
+ * allocating and copying to a large linear SKB
+ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/cisco/enic/enic.h linux-libre-4.4.7-gnu/drivers/net/ethernet/cisco/enic/enic.h
+--- linux-libre-4.4-gnu/drivers/net/ethernet/cisco/enic/enic.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/cisco/enic/enic.h 2016-04-12 12:09:26.000000000 -0400
+@@ -33,7 +33,7 @@
+
+ #define DRV_NAME "enic"
+ #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
+-#define DRV_VERSION "2.3.0.12"
++#define DRV_VERSION "2.3.0.20"
+ #define DRV_COPYRIGHT "Copyright 2008-2013 Cisco Systems, Inc"
+
+ #define ENIC_BARS_MAX 6
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c linux-libre-4.4.7-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/cisco/enic/vnic_dev.c 2016-04-12 12:09:26.000000000 -0400
+@@ -298,7 +298,8 @@ static int _vnic_dev_cmd2(struct vnic_de
+ int wait)
+ {
+ struct devcmd2_controller *dc2c = vdev->devcmd2;
+- struct devcmd2_result *result = dc2c->result + dc2c->next_result;
++ struct devcmd2_result *result;
++ u8 color;
+ unsigned int i;
+ int delay, err;
+ u32 fetch_index, new_posted;
+@@ -336,13 +337,17 @@ static int _vnic_dev_cmd2(struct vnic_de
+ if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
+ return 0;
+
++ result = dc2c->result + dc2c->next_result;
++ color = dc2c->color;
++
++ dc2c->next_result++;
++ if (dc2c->next_result == dc2c->result_size) {
++ dc2c->next_result = 0;
++ dc2c->color = dc2c->color ? 0 : 1;
++ }
++
+ for (delay = 0; delay < wait; delay++) {
+- if (result->color == dc2c->color) {
+- dc2c->next_result++;
+- if (dc2c->next_result == dc2c->result_size) {
+- dc2c->next_result = 0;
+- dc2c->color = dc2c->color ? 0 : 1;
+- }
++ if (result->color == color) {
+ if (result->error) {
+ err = result->error;
+ if (err != ERR_ECMDUNKNOWN ||
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/marvell/mvneta.c linux-libre-4.4.7-gnu/drivers/net/ethernet/marvell/mvneta.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/marvell/mvneta.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/marvell/mvneta.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3404,7 +3404,7 @@ static int mvneta_probe(struct platform_
+ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
+ dev->hw_features |= dev->features;
+ dev->vlan_features |= dev->features;
+- dev->priv_flags |= IFF_UNICAST_FLT;
++ dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE;
+ dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;
+
+ err = register_netdev(dev);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c 2016-04-12 12:09:26.000000000 -0400
+@@ -236,6 +236,24 @@ static const struct ptp_clock_info mlx4_
+ .enable = mlx4_en_phc_enable,
+ };
+
++#define MLX4_EN_WRAP_AROUND_SEC 10ULL
++
++/* This function calculates the max shift that enables the user range
++ * of MLX4_EN_WRAP_AROUND_SEC values in the cycles register.
++ */
++static u32 freq_to_shift(u16 freq)
++{
++ u32 freq_khz = freq * 1000;
++ u64 max_val_cycles = freq_khz * 1000 * MLX4_EN_WRAP_AROUND_SEC;
++ u64 max_val_cycles_rounded = is_power_of_2(max_val_cycles + 1) ?
++ max_val_cycles : roundup_pow_of_two(max_val_cycles) - 1;
++ /* calculate max possible multiplier in order to fit in 64bit */
++ u64 max_mul = div_u64(0xffffffffffffffffULL, max_val_cycles_rounded);
++
++ /* This comes from the reverse of clocksource_khz2mult */
++ return ilog2(div_u64(max_mul * freq_khz, 1000000));
++}
++
+ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
+ {
+ struct mlx4_dev *dev = mdev->dev;
+@@ -254,12 +272,7 @@ void mlx4_en_init_timestamp(struct mlx4_
+ memset(&mdev->cycles, 0, sizeof(mdev->cycles));
+ mdev->cycles.read = mlx4_en_read_clock;
+ mdev->cycles.mask = CLOCKSOURCE_MASK(48);
+- /* Using shift to make calculation more accurate. Since current HW
+- * clock frequency is 427 MHz, and cycles are given using a 48 bits
+- * register, the biggest shift when calculating using u64, is 14
+- * (max_cycles * multiplier < 2^64)
+- */
+- mdev->cycles.shift = 14;
++ mdev->cycles.shift = freq_to_shift(dev->caps.hca_core_clock);
+ mdev->cycles.mult =
+ clocksource_khz2mult(1000 * dev->caps.hca_core_clock, mdev->cycles.shift);
+ mdev->nominal_c_mult = mdev->cycles.mult;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2381,8 +2381,6 @@ out:
+ /* set offloads */
+ priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+ NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL;
+- priv->dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+- priv->dev->features |= NETIF_F_GSO_UDP_TUNNEL;
+ }
+
+ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
+@@ -2393,8 +2391,6 @@ static void mlx4_en_del_vxlan_offloads(s
+ /* unset offloads */
+ priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+ NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL);
+- priv->dev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL;
+- priv->dev->features &= ~NETIF_F_GSO_UDP_TUNNEL;
+
+ ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port,
+ VXLAN_STEER_BY_OUTER_MAC, 0);
+@@ -3020,6 +3016,11 @@ int mlx4_en_init_netdev(struct mlx4_en_d
+ priv->rss_hash_fn = ETH_RSS_HASH_TOP;
+ }
+
++ if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
++ dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
++ dev->features |= NETIF_F_GSO_UDP_TUNNEL;
++ }
++
+ mdev->pndev[port] = dev;
+ mdev->upper[port] = NULL;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c 2016-04-12 12:09:26.000000000 -0400
+@@ -238,11 +238,11 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_e
+ stats->collisions = 0;
+ stats->rx_dropped = be32_to_cpu(mlx4_en_stats->RDROP);
+ stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
+- stats->rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
++ stats->rx_over_errors = 0;
+ stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
+ stats->rx_frame_errors = 0;
+ stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+- stats->rx_missed_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
++ stats->rx_missed_errors = 0;
+ stats->tx_aborted_errors = 0;
+ stats->tx_carrier_errors = 0;
+ stats->tx_fifo_errors = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -746,7 +746,7 @@ static int mlx5e_create_cq(struct mlx5e_
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct mlx5_core_cq *mcq = &cq->mcq;
+ int eqn_not_used;
+- int irqn;
++ unsigned int irqn;
+ int err;
+ u32 i;
+
+@@ -800,7 +800,7 @@ static int mlx5e_enable_cq(struct mlx5e_
+ void *in;
+ void *cqc;
+ int inlen;
+- int irqn_not_used;
++ unsigned int irqn_not_used;
+ int eqn;
+ int err;
+
+@@ -1504,7 +1504,7 @@ static int mlx5e_create_drop_cq(struct m
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct mlx5_core_cq *mcq = &cq->mcq;
+ int eqn_not_used;
+- int irqn;
++ unsigned int irqn;
+ int err;
+
+ err = mlx5_cqwq_create(mdev, &param->wq, param->cqc, &cq->wq,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -568,7 +568,8 @@ static void mlx5_irq_clear_affinity_hint
+ mlx5_irq_clear_affinity_hint(mdev, i);
+ }
+
+-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn)
++int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
++ unsigned int *irqn)
+ {
+ struct mlx5_eq_table *table = &dev->priv.eq_table;
+ struct mlx5_eq *eq, *n;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 2016-04-12 12:09:26.000000000 -0400
+@@ -45,6 +45,7 @@
+ #include <linux/if_bridge.h>
+ #include <linux/workqueue.h>
+ #include <linux/jiffies.h>
++#include <linux/rtnetlink.h>
+ #include <net/switchdev.h>
+
+ #include "spectrum.h"
+@@ -812,6 +813,7 @@ static void mlxsw_sp_fdb_notify_work(str
+
+ mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work);
+
++ rtnl_lock();
+ do {
+ mlxsw_reg_sfn_pack(sfn_pl);
+ err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
+@@ -824,6 +826,7 @@ static void mlxsw_sp_fdb_notify_work(str
+ mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
+
+ } while (num_rec);
++ rtnl_unlock();
+
+ kfree(sfn_pl);
+ mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/rocker/rocker.c linux-libre-4.4.7-gnu/drivers/net/ethernet/rocker/rocker.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/rocker/rocker.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/rocker/rocker.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3531,12 +3531,14 @@ static void rocker_port_fdb_learn_work(s
+ info.addr = lw->addr;
+ info.vid = lw->vid;
+
++ rtnl_lock();
+ if (learned && removing)
+ call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
+ lw->rocker_port->dev, &info.info);
+ else if (learned && !removing)
+ call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
+ lw->rocker_port->dev, &info.info);
++ rtnl_unlock();
+
+ rocker_port_kfree(lw->trans, work);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ethernet/synopsys/dwc_eth_qos.c linux-libre-4.4.7-gnu/drivers/net/ethernet/synopsys/dwc_eth_qos.c
+--- linux-libre-4.4-gnu/drivers/net/ethernet/synopsys/dwc_eth_qos.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ethernet/synopsys/dwc_eth_qos.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2107,7 +2107,7 @@ static int dwceqos_tx_frags(struct sk_bu
+ dd = &lp->tx_descs[lp->tx_next];
+
+ /* Set DMA Descriptor fields */
+- dd->des0 = dma_handle;
++ dd->des0 = dma_handle + consumed_size;
+ dd->des1 = 0;
+ dd->des2 = dma_size;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/irda/irtty-sir.c linux-libre-4.4.7-gnu/drivers/net/irda/irtty-sir.c
+--- linux-libre-4.4-gnu/drivers/net/irda/irtty-sir.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/irda/irtty-sir.c 2016-04-12 12:09:26.000000000 -0400
+@@ -430,16 +430,6 @@ static int irtty_open(struct tty_struct
+
+ /* Module stuff handled via irda_ldisc.owner - Jean II */
+
+- /* First make sure we're not already connected. */
+- if (tty->disc_data != NULL) {
+- priv = tty->disc_data;
+- if (priv && priv->magic == IRTTY_MAGIC) {
+- ret = -EEXIST;
+- goto out;
+- }
+- tty->disc_data = NULL; /* ### */
+- }
+-
+ /* stop the underlying driver */
+ irtty_stop_receiver(tty, TRUE);
+ if (tty->ops->stop)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/phy/dp83640.c linux-libre-4.4.7-gnu/drivers/net/phy/dp83640.c
+--- linux-libre-4.4-gnu/drivers/net/phy/dp83640.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/phy/dp83640.c 2016-04-12 12:09:26.000000000 -0400
+@@ -845,6 +845,11 @@ static void decode_rxts(struct dp83640_p
+ struct skb_shared_hwtstamps *shhwtstamps = NULL;
+ struct sk_buff *skb;
+ unsigned long flags;
++ u8 overflow;
++
++ overflow = (phy_rxts->ns_hi >> 14) & 0x3;
++ if (overflow)
++ pr_debug("rx timestamp queue overflow, count %d\n", overflow);
+
+ spin_lock_irqsave(&dp83640->rx_lock, flags);
+
+@@ -887,6 +892,7 @@ static void decode_txts(struct dp83640_p
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct sk_buff *skb;
+ u64 ns;
++ u8 overflow;
+
+ /* We must already have the skb that triggered this. */
+
+@@ -896,6 +902,17 @@ static void decode_txts(struct dp83640_p
+ pr_debug("have timestamp but tx_queue empty\n");
+ return;
+ }
++
++ overflow = (phy_txts->ns_hi >> 14) & 0x3;
++ if (overflow) {
++ pr_debug("tx timestamp queue overflow, count %d\n", overflow);
++ while (skb) {
++ skb_complete_tx_timestamp(skb, NULL);
++ skb = skb_dequeue(&dp83640->tx_queue);
++ }
++ return;
++ }
++
+ ns = phy2txts(phy_txts);
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ppp/pppoe.c linux-libre-4.4.7-gnu/drivers/net/ppp/pppoe.c
+--- linux-libre-4.4-gnu/drivers/net/ppp/pppoe.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ppp/pppoe.c 2016-04-12 12:09:26.000000000 -0400
+@@ -395,6 +395,8 @@ static int pppoe_rcv_core(struct sock *s
+
+ if (!__pppoe_xmit(sk_pppox(relay_po), skb))
+ goto abort_put;
++
++ sock_put(sk_pppox(relay_po));
+ } else {
+ if (sock_queue_rcv_skb(sk, skb))
+ goto abort_kfree;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/ppp/pptp.c linux-libre-4.4.7-gnu/drivers/net/ppp/pptp.c
+--- linux-libre-4.4-gnu/drivers/net/ppp/pptp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/ppp/pptp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -129,24 +129,27 @@ static int lookup_chan_dst(u16 call_id,
+ return i < MAX_CALLID;
+ }
+
+-static int add_chan(struct pppox_sock *sock)
++static int add_chan(struct pppox_sock *sock,
++ struct pptp_addr *sa)
+ {
+ static int call_id;
+
+ spin_lock(&chan_lock);
+- if (!sock->proto.pptp.src_addr.call_id) {
++ if (!sa->call_id) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
+ if (call_id == MAX_CALLID) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
+ if (call_id == MAX_CALLID)
+ goto out_err;
+ }
+- sock->proto.pptp.src_addr.call_id = call_id;
+- } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
++ sa->call_id = call_id;
++ } else if (test_bit(sa->call_id, callid_bitmap)) {
+ goto out_err;
++ }
+
+- set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+- rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
++ sock->proto.pptp.src_addr = *sa;
++ set_bit(sa->call_id, callid_bitmap);
++ rcu_assign_pointer(callid_sock[sa->call_id], sock);
+ spin_unlock(&chan_lock);
+
+ return 0;
+@@ -416,7 +419,6 @@ static int pptp_bind(struct socket *sock
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+- struct pptp_opt *opt = &po->proto.pptp;
+ int error = 0;
+
+ if (sockaddr_len < sizeof(struct sockaddr_pppox))
+@@ -424,10 +426,22 @@ static int pptp_bind(struct socket *sock
+
+ lock_sock(sk);
+
+- opt->src_addr = sp->sa_addr.pptp;
+- if (add_chan(po))
++ if (sk->sk_state & PPPOX_DEAD) {
++ error = -EALREADY;
++ goto out;
++ }
++
++ if (sk->sk_state & PPPOX_BOUND) {
+ error = -EBUSY;
++ goto out;
++ }
+
++ if (add_chan(po, &sp->sa_addr.pptp))
++ error = -EBUSY;
++ else
++ sk->sk_state |= PPPOX_BOUND;
++
++out:
+ release_sock(sk);
+ return error;
+ }
+@@ -498,7 +512,7 @@ static int pptp_connect(struct socket *s
+ }
+
+ opt->dst_addr = sp->sa_addr.pptp;
+- sk->sk_state = PPPOX_CONNECTED;
++ sk->sk_state |= PPPOX_CONNECTED;
+
+ end:
+ release_sock(sk);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/rionet.c linux-libre-4.4.7-gnu/drivers/net/rionet.c
+--- linux-libre-4.4-gnu/drivers/net/rionet.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/rionet.c 2016-04-12 12:09:26.000000000 -0400
+@@ -280,7 +280,7 @@ static void rionet_outb_msg_event(struct
+ struct net_device *ndev = dev_id;
+ struct rionet_private *rnet = netdev_priv(ndev);
+
+- spin_lock(&rnet->lock);
++ spin_lock(&rnet->tx_lock);
+
+ if (netif_msg_intr(rnet))
+ printk(KERN_INFO
+@@ -299,7 +299,7 @@ static void rionet_outb_msg_event(struct
+ if (rnet->tx_cnt < RIONET_TX_RING_SIZE)
+ netif_wake_queue(ndev);
+
+- spin_unlock(&rnet->lock);
++ spin_unlock(&rnet->tx_lock);
+ }
+
+ static int rionet_open(struct net_device *ndev)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/team/team.c linux-libre-4.4.7-gnu/drivers/net/team/team.c
+--- linux-libre-4.4-gnu/drivers/net/team/team.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/team/team.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1845,10 +1845,10 @@ static int team_vlan_rx_kill_vid(struct
+ struct team *team = netdev_priv(dev);
+ struct team_port *port;
+
+- rcu_read_lock();
+- list_for_each_entry_rcu(port, &team->port_list, list)
++ mutex_lock(&team->lock);
++ list_for_each_entry(port, &team->port_list, list)
+ vlan_vid_del(port->dev, proto, vid);
+- rcu_read_unlock();
++ mutex_unlock(&team->lock);
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/usb/qmi_wwan.c linux-libre-4.4.7-gnu/drivers/net/usb/qmi_wwan.c
+--- linux-libre-4.4-gnu/drivers/net/usb/qmi_wwan.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/usb/qmi_wwan.c 2016-04-12 12:09:26.000000000 -0400
+@@ -492,6 +492,7 @@ static const struct usb_device_id produc
+
+ /* 3. Combined interface devices matching on interface number */
+ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */
++ {QMI_FIXED_INTF(0x05c6, 0x6001, 3)}, /* 4G LTE usb-modem U901 */
+ {QMI_FIXED_INTF(0x05c6, 0x7000, 0)},
+ {QMI_FIXED_INTF(0x05c6, 0x7001, 1)},
+ {QMI_FIXED_INTF(0x05c6, 0x7002, 1)},
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/vxlan.c linux-libre-4.4.7-gnu/drivers/net/vxlan.c
+--- linux-libre-4.4-gnu/drivers/net/vxlan.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/vxlan.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1984,11 +1984,6 @@ static void vxlan_xmit_one(struct sk_buf
+ vxlan->cfg.port_max, true);
+
+ if (info) {
+- if (info->key.tun_flags & TUNNEL_CSUM)
+- flags |= VXLAN_F_UDP_CSUM;
+- else
+- flags &= ~VXLAN_F_UDP_CSUM;
+-
+ ttl = info->key.ttl;
+ tos = info->key.tos;
+
+@@ -2003,8 +1998,15 @@ static void vxlan_xmit_one(struct sk_buf
+ goto drop;
+ sk = vxlan->vn4_sock->sock->sk;
+
+- if (info && (info->key.tun_flags & TUNNEL_DONT_FRAGMENT))
+- df = htons(IP_DF);
++ if (info) {
++ if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)
++ df = htons(IP_DF);
++
++ if (info->key.tun_flags & TUNNEL_CSUM)
++ flags |= VXLAN_F_UDP_CSUM;
++ else
++ flags &= ~VXLAN_F_UDP_CSUM;
++ }
+
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0;
+@@ -2102,6 +2104,13 @@ static void vxlan_xmit_one(struct sk_buf
+ return;
+ }
+
++ if (info) {
++ if (info->key.tun_flags & TUNNEL_CSUM)
++ flags &= ~VXLAN_F_UDP_ZERO_CSUM6_TX;
++ else
++ flags |= VXLAN_F_UDP_ZERO_CSUM6_TX;
++ }
++
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr,
+ 0, ttl, src_port, dst_port, htonl(vni << 8), md,
+@@ -2751,7 +2760,7 @@ static int vxlan_dev_configure(struct ne
+ struct vxlan_config *conf)
+ {
+ struct vxlan_net *vn = net_generic(src_net, vxlan_net_id);
+- struct vxlan_dev *vxlan = netdev_priv(dev);
++ struct vxlan_dev *vxlan = netdev_priv(dev), *tmp;
+ struct vxlan_rdst *dst = &vxlan->default_dst;
+ unsigned short needed_headroom = ETH_HLEN;
+ int err;
+@@ -2817,9 +2826,15 @@ static int vxlan_dev_configure(struct ne
+ if (!vxlan->cfg.age_interval)
+ vxlan->cfg.age_interval = FDB_AGE_DEFAULT;
+
+- if (vxlan_find_vni(src_net, conf->vni, use_ipv6 ? AF_INET6 : AF_INET,
+- vxlan->cfg.dst_port, vxlan->flags))
++ list_for_each_entry(tmp, &vn->vxlan_list, next) {
++ if (tmp->cfg.vni == conf->vni &&
++ (tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 ||
++ tmp->cfg.saddr.sa.sa_family == AF_INET6) == use_ipv6 &&
++ tmp->cfg.dst_port == vxlan->cfg.dst_port &&
++ (tmp->flags & VXLAN_F_RCV_FLAGS) ==
++ (vxlan->flags & VXLAN_F_RCV_FLAGS))
+ return -EEXIST;
++ }
+
+ dev->ethtool_ops = &vxlan_ethtool_ops;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/dvm/lib.c linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/dvm/lib.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/dvm/lib.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/dvm/lib.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1154,6 +1154,9 @@ int iwlagn_suspend(struct iwl_priv *priv
+
+ priv->ucode_loaded = false;
+ iwl_trans_stop_device(priv->trans);
++ ret = iwl_trans_start_hw(priv->trans);
++ if (ret)
++ goto out;
+
+ priv->wowlan = true;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/fw.c linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/fw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/fw.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/fw.c 2016-04-12 12:09:26.000000000 -0400
+@@ -106,7 +106,7 @@ static int iwl_send_tx_ant_cfg(struct iw
+ sizeof(tx_ant_cmd), &tx_ant_cmd);
+ }
+
+-static void iwl_free_fw_paging(struct iwl_mvm *mvm)
++void iwl_free_fw_paging(struct iwl_mvm *mvm)
+ {
+ int i;
+
+@@ -126,6 +126,8 @@ static void iwl_free_fw_paging(struct iw
+ get_order(mvm->fw_paging_db[i].fw_paging_size));
+ }
+ kfree(mvm->trans->paging_download_buf);
++ mvm->trans->paging_download_buf = NULL;
++
+ memset(mvm->fw_paging_db, 0, sizeof(mvm->fw_paging_db));
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/mvm.h 2016-04-12 12:09:26.000000000 -0400
+@@ -1190,6 +1190,9 @@ void iwl_mvm_rx_umac_scan_complete_notif
+ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_cmd_buffer *rxb);
+
++/* Paging */
++void iwl_free_fw_paging(struct iwl_mvm *mvm);
++
+ /* MVM debugfs */
+ #ifdef CONFIG_IWLWIFI_DEBUGFS
+ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/ops.c 2016-04-12 12:09:26.000000000 -0400
+@@ -645,6 +645,8 @@ static void iwl_op_mode_mvm_stop(struct
+ for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++)
+ kfree(mvm->nvm_sections[i].data);
+
++ iwl_free_fw_paging(mvm);
++
+ iwl_mvm_tof_clean(mvm);
+
+ ieee80211_free_hw(mvm->hw);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/scan.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1267,6 +1267,10 @@ int iwl_mvm_sched_scan_start(struct iwl_
+ return -EBUSY;
+ }
+
++ /* we don't support "match all" in the firmware */
++ if (!req->n_match_sets)
++ return -EOPNOTSUPP;
++
+ ret = iwl_mvm_check_running_scans(mvm, type);
+ if (ret)
+ return ret;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/mvm/tx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -421,6 +421,15 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
+ return -1;
+ }
+
++ /*
++ * Increase the pending frames counter, so that later when a reply comes
++ * in and the counter is decreased - we don't start getting negative
++ * values.
++ * Note that we don't need to make sure it isn't agg'd, since we're
++ * TXing non-sta
++ */
++ atomic_inc(&mvm->pending_frames[sta_id]);
++
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/pcie/drv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -384,6 +384,7 @@ static const struct pci_device_id iwl_hw
+ {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_n_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
++ {IWL_PCI_DEVICE(0x095A, 0x5C10, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5412, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
+@@ -401,10 +402,10 @@ static const struct pci_device_id iwl_hw
+ {IWL_PCI_DEVICE(0x095A, 0x900A, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
+- {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
++ {IWL_PCI_DEVICE(0x095B, 0x9210, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x9200, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
+- {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
++ {IWL_PCI_DEVICE(0x095B, 0x9310, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/iwlwifi/pcie/trans.c 2016-04-12 12:09:26.000000000 -0400
+@@ -7,6 +7,7 @@
+ *
+ * Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
++ * Copyright(c) 2016 Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+@@ -33,6 +34,7 @@
+ *
+ * Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
++ * Copyright(c) 2016 Intel Deutschland GmbH
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+@@ -924,9 +926,16 @@ monitor:
+ if (dest->monitor_mode == EXTERNAL_MODE && trans_pcie->fw_mon_size) {
+ iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
+ trans_pcie->fw_mon_phys >> dest->base_shift);
+- iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
+- (trans_pcie->fw_mon_phys +
+- trans_pcie->fw_mon_size) >> dest->end_shift);
++ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
++ iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
++ (trans_pcie->fw_mon_phys +
++ trans_pcie->fw_mon_size - 256) >>
++ dest->end_shift);
++ else
++ iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
++ (trans_pcie->fw_mon_phys +
++ trans_pcie->fw_mon_size) >>
++ dest->end_shift);
+ }
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -801,7 +801,9 @@ static void _rtl_pci_rx_interrupt(struct
+ hw_queue);
+ if (rx_remained_cnt == 0)
+ return;
+-
++ buffer_desc = &rtlpci->rx_ring[rxring_idx].buffer_desc[
++ rtlpci->rx_ring[rxring_idx].idx];
++ pdesc = (struct rtl_rx_desc *)skb->data;
+ } else { /* rx descriptor */
+ pdesc = &rtlpci->rx_ring[rxring_idx].desc[
+ rtlpci->rx_ring[rxring_idx].idx];
+@@ -824,13 +826,6 @@ static void _rtl_pci_rx_interrupt(struct
+ new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
+ if (unlikely(!new_skb))
+ goto no_new;
+- if (rtlpriv->use_new_trx_flow) {
+- buffer_desc =
+- &rtlpci->rx_ring[rxring_idx].buffer_desc
+- [rtlpci->rx_ring[rxring_idx].idx];
+- /*means rx wifi info*/
+- pdesc = (struct rtl_rx_desc *)skb->data;
+- }
+ memset(&rx_status , 0 , sizeof(rx_status));
+ rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
+ &rx_status, (u8 *)pdesc, skb);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/regd.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/regd.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/regd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/regd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -351,7 +351,6 @@ static const struct ieee80211_regdomain
+ case COUNTRY_CODE_SPAIN:
+ case COUNTRY_CODE_FRANCE:
+ case COUNTRY_CODE_ISRAEL:
+- case COUNTRY_CODE_WORLD_WIDE_13:
+ return &rtl_regdom_12_13;
+ case COUNTRY_CODE_MKK:
+ case COUNTRY_CODE_MKK1:
+@@ -360,6 +359,7 @@ static const struct ieee80211_regdomain
+ return &rtl_regdom_14_60_64;
+ case COUNTRY_CODE_GLOBAL_DOMAIN:
+ return &rtl_regdom_14;
++ case COUNTRY_CODE_WORLD_WIDE_13:
+ case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
+ return &rtl_regdom_12_13_5g_all;
+ default:
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c 2016-01-10 21:10:21.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c 2016-04-12 21:26:48.000000000 -0400
+@@ -88,8 +88,6 @@ int rtl88e_init_sw_vars(struct ieee80211
+ u8 tid;
+
+ rtl8188ee_bt_reg_init(hw);
+- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+-
+ rtlpriv->dm.dm_initialgain_enable = 1;
+ rtlpriv->dm.dm_flag = 0;
+ rtlpriv->dm.disable_framebursting = 0;
+@@ -138,6 +136,11 @@ int rtl88e_init_sw_vars(struct ieee80211
+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+ 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;
++ rtlpriv->cfg->mod_params->sw_crypto =
++ rtlpriv->cfg->mod_params->sw_crypto;
++ rtlpriv->cfg->mod_params->disable_watchdog =
++ rtlpriv->cfg->mod_params->disable_watchdog;
+ if (rtlpriv->cfg->mod_params->disable_watchdog)
+ pr_info("watchdog disabled\n");
+ if (!rtlpriv->psc.inactiveps)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c 2016-01-10 21:10:29.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c 2016-04-12 21:26:56.000000000 -0400
+@@ -139,6 +139,8 @@ int rtl92c_init_sw_vars(struct ieee80211
+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+ rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+ rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
++ rtlpriv->cfg->mod_params->sw_crypto =
++ rtlpriv->cfg->mod_params->sw_crypto;
+ if (!rtlpriv->psc.inactiveps)
+ pr_info("rtl8192ce: Power Save off (module option)\n");
+ if (!rtlpriv->psc.fwctrl_lps)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c 2016-01-10 21:10:31.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c 2016-04-12 21:26:58.000000000 -0400
+@@ -62,6 +62,8 @@ static int rtl92cu_init_sw_vars(struct i
+ rtlpriv->dm.disable_framebursting = false;
+ rtlpriv->dm.thermalvalue = 0;
+ rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
++ rtlpriv->cfg->mod_params->sw_crypto =
++ rtlpriv->cfg->mod_params->sw_crypto;
+
+ /* for firmware buf */
+ rtlpriv->rtlhal.pfirmware = vzalloc(0x4000);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c 2016-01-10 21:10:33.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c 2016-04-12 21:27:00.000000000 -0400
+@@ -376,8 +376,8 @@ module_param_named(swlps, rtl92de_mod_pa
+ module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, 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");
+-MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
++MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n");
++MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n");
+ MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
+ static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c 2016-01-10 21:10:36.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c 2016-04-12 21:27:03.000000000 -0400
+@@ -187,6 +187,8 @@ static int rtl92s_init_sw_vars(struct ie
+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+ rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
+ rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
++ rtlpriv->cfg->mod_params->sw_crypto =
++ rtlpriv->cfg->mod_params->sw_crypto;
+ if (!rtlpriv->psc.inactiveps)
+ pr_info("Power Save off (module option)\n");
+ if (!rtlpriv->psc.fwctrl_lps)
+@@ -425,8 +427,8 @@ module_param_named(swlps, rtl92se_mod_pa
+ module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, 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");
+-MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
++MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n");
++MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n");
+ MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
+
+ static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c 2016-01-10 21:10:51.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c 2016-04-12 21:27:19.000000000 -0400
+@@ -150,6 +150,11 @@ int rtl8723e_init_sw_vars(struct ieee802
+ rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
+ 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;
++ rtlpriv->cfg->mod_params->sw_crypto =
++ rtlpriv->cfg->mod_params->sw_crypto;
++ rtlpriv->cfg->mod_params->disable_watchdog =
++ rtlpriv->cfg->mod_params->disable_watchdog;
+ if (rtlpriv->cfg->mod_params->disable_watchdog)
+ pr_info("watchdog disabled\n");
+ rtlpriv->psc.reg_fwctrl_lps = 3;
+@@ -267,6 +272,8 @@ static struct rtl_mod_params rtl8723e_mo
+ .swctrl_lps = false,
+ .fwctrl_lps = true,
+ .debug = DBG_EMERG,
++ .msi_support = false,
++ .disable_watchdog = false,
+ };
+
+ static struct rtl_hal_cfg rtl8723e_hal_cfg = {
+@@ -383,12 +390,14 @@ module_param_named(debug, rtl8723e_mod_p
+ module_param_named(ips, rtl8723e_mod_params.inactiveps, bool, 0444);
+ module_param_named(swlps, rtl8723e_mod_params.swctrl_lps, bool, 0444);
+ module_param_named(fwlps, rtl8723e_mod_params.fwctrl_lps, bool, 0444);
++module_param_named(msi, rtl8723e_mod_params.msi_support, bool, 0444);
+ module_param_named(disable_watchdog, rtl8723e_mod_params.disable_watchdog,
+ 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");
+ MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
++MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\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");
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c 2016-01-10 21:11:00.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c 2016-04-12 21:27:27.000000000 -0400
+@@ -93,7 +93,6 @@ int rtl8723be_init_sw_vars(struct ieee80
+ struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+ rtl8723be_bt_reg_init(hw);
+- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
+
+ rtlpriv->dm.dm_initialgain_enable = 1;
+@@ -151,6 +150,10 @@ int rtl8723be_init_sw_vars(struct ieee80
+ 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;
++ rtlpriv->cfg->mod_params->sw_crypto =
++ rtlpriv->cfg->mod_params->sw_crypto;
++ rtlpriv->cfg->mod_params->disable_watchdog =
++ rtlpriv->cfg->mod_params->disable_watchdog;
+ if (rtlpriv->cfg->mod_params->disable_watchdog)
+ pr_info("watchdog disabled\n");
+ rtlpriv->psc.reg_fwctrl_lps = 3;
+@@ -267,6 +270,9 @@ static struct rtl_mod_params rtl8723be_m
+ .inactiveps = true,
+ .swctrl_lps = false,
+ .fwctrl_lps = true,
++ .msi_support = false,
++ .disable_watchdog = false,
++ .debug = DBG_EMERG,
+ };
+
+ static struct rtl_hal_cfg rtl8723be_hal_cfg = {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c 2016-01-10 21:11:02.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c 2016-04-12 21:27:29.000000000 -0400
+@@ -95,8 +95,6 @@ int rtl8821ae_init_sw_vars(struct ieee80
+ struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+ 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;
+@@ -168,12 +166,15 @@ int rtl8821ae_init_sw_vars(struct ieee80
+ 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;
++ rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
++ rtlpriv->cfg->mod_params->sw_crypto =
++ rtlpriv->cfg->mod_params->sw_crypto;
++ rtlpriv->cfg->mod_params->disable_watchdog =
++ rtlpriv->cfg->mod_params->disable_watchdog;
+ if (rtlpriv->cfg->mod_params->disable_watchdog)
+ pr_info("watchdog disabled\n");
+ rtlpriv->psc.reg_fwctrl_lps = 3;
+ rtlpriv->psc.reg_max_lps_awakeintvl = 5;
+- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+
+ /* for ASPM, you can close aspm through
+ * set const_support_pciaspm = 0
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/realtek/rtlwifi/usb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -531,6 +531,8 @@ static void _rtl_usb_rx_process_noagg(st
+ ieee80211_rx(hw, skb);
+ else
+ dev_kfree_skb_any(skb);
++ } else {
++ dev_kfree_skb_any(skb);
+ }
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/ti/wlcore/io.h linux-libre-4.4.7-gnu/drivers/net/wireless/ti/wlcore/io.h
+--- linux-libre-4.4-gnu/drivers/net/wireless/ti/wlcore/io.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/ti/wlcore/io.h 2016-04-12 12:09:26.000000000 -0400
+@@ -207,19 +207,23 @@ static inline int __must_check wlcore_wr
+
+ static inline void wl1271_power_off(struct wl1271 *wl)
+ {
+- int ret;
++ int ret = 0;
+
+ if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags))
+ return;
+
+- ret = wl->if_ops->power(wl->dev, false);
++ if (wl->if_ops->power)
++ ret = wl->if_ops->power(wl->dev, false);
+ if (!ret)
+ clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+ }
+
+ static inline int wl1271_power_on(struct wl1271 *wl)
+ {
+- int ret = wl->if_ops->power(wl->dev, true);
++ int ret = 0;
++
++ if (wl->if_ops->power)
++ ret = wl->if_ops->power(wl->dev, true);
+ if (ret == 0)
+ set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/net/wireless/ti/wlcore/spi.c linux-libre-4.4.7-gnu/drivers/net/wireless/ti/wlcore/spi.c
+--- linux-libre-4.4-gnu/drivers/net/wireless/ti/wlcore/spi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/net/wireless/ti/wlcore/spi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -73,7 +73,10 @@
+ */
+ #define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
+
+-#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
++/* Maximum number of SPI write chunks */
++#define WSPI_MAX_NUM_OF_CHUNKS \
++ ((SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1)
++
+
+ struct wl12xx_spi_glue {
+ struct device *dev;
+@@ -268,9 +271,10 @@ static int __must_check wl12xx_spi_raw_w
+ void *buf, size_t len, bool fixed)
+ {
+ struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
+- struct spi_transfer t[2 * (WSPI_MAX_NUM_OF_CHUNKS + 1)];
++ /* SPI write buffers - 2 for each chunk */
++ struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
+ struct spi_message m;
+- u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
++ u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */
+ u32 *cmd;
+ u32 chunk_len;
+ int i;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/nvdimm/bus.c linux-libre-4.4.7-gnu/drivers/nvdimm/bus.c
+--- linux-libre-4.4-gnu/drivers/nvdimm/bus.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/nvdimm/bus.c 2016-04-12 12:09:26.000000000 -0400
+@@ -513,10 +513,10 @@ static int __nd_ioctl(struct nvdimm_bus
+
+ /* fail write commands (when read-only) */
+ if (read_only)
+- switch (ioctl_cmd) {
+- case ND_IOCTL_VENDOR:
+- case ND_IOCTL_SET_CONFIG_DATA:
+- case ND_IOCTL_ARS_START:
++ switch (cmd) {
++ case ND_CMD_VENDOR:
++ case ND_CMD_SET_CONFIG_DATA:
++ case ND_CMD_ARS_START:
+ dev_dbg(&nvdimm_bus->dev, "'%s' command while read-only.\n",
+ nvdimm ? nvdimm_cmd_name(cmd)
+ : nvdimm_bus_cmd_name(cmd));
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/nvdimm/namespace_devs.c linux-libre-4.4.7-gnu/drivers/nvdimm/namespace_devs.c
+--- linux-libre-4.4-gnu/drivers/nvdimm/namespace_devs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/nvdimm/namespace_devs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -77,6 +77,59 @@ static bool is_namespace_io(struct devic
+ return dev ? dev->type == &namespace_io_device_type : false;
+ }
+
++static int is_uuid_busy(struct device *dev, void *data)
++{
++ u8 *uuid1 = data, *uuid2 = NULL;
++
++ if (is_namespace_pmem(dev)) {
++ struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
++
++ uuid2 = nspm->uuid;
++ } else if (is_namespace_blk(dev)) {
++ struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
++
++ uuid2 = nsblk->uuid;
++ } else if (is_nd_btt(dev)) {
++ struct nd_btt *nd_btt = to_nd_btt(dev);
++
++ uuid2 = nd_btt->uuid;
++ } else if (is_nd_pfn(dev)) {
++ struct nd_pfn *nd_pfn = to_nd_pfn(dev);
++
++ uuid2 = nd_pfn->uuid;
++ }
++
++ if (uuid2 && memcmp(uuid1, uuid2, NSLABEL_UUID_LEN) == 0)
++ return -EBUSY;
++
++ return 0;
++}
++
++static int is_namespace_uuid_busy(struct device *dev, void *data)
++{
++ if (is_nd_pmem(dev) || is_nd_blk(dev))
++ return device_for_each_child(dev, data, is_uuid_busy);
++ return 0;
++}
++
++/**
++ * nd_is_uuid_unique - verify that no other namespace has @uuid
++ * @dev: any device on a nvdimm_bus
++ * @uuid: uuid to check
++ */
++bool nd_is_uuid_unique(struct device *dev, u8 *uuid)
++{
++ struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
++
++ if (!nvdimm_bus)
++ return false;
++ WARN_ON_ONCE(!is_nvdimm_bus_locked(&nvdimm_bus->dev));
++ if (device_for_each_child(&nvdimm_bus->dev, uuid,
++ is_namespace_uuid_busy) != 0)
++ return false;
++ return true;
++}
++
+ bool pmem_should_map_pages(struct device *dev)
+ {
+ struct nd_region *nd_region = to_nd_region(dev->parent);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/nvdimm/region_devs.c linux-libre-4.4.7-gnu/drivers/nvdimm/region_devs.c
+--- linux-libre-4.4-gnu/drivers/nvdimm/region_devs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/nvdimm/region_devs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -134,62 +134,6 @@ int nd_region_to_nstype(struct nd_region
+ }
+ EXPORT_SYMBOL(nd_region_to_nstype);
+
+-static int is_uuid_busy(struct device *dev, void *data)
+-{
+- struct nd_region *nd_region = to_nd_region(dev->parent);
+- u8 *uuid = data;
+-
+- switch (nd_region_to_nstype(nd_region)) {
+- case ND_DEVICE_NAMESPACE_PMEM: {
+- struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
+-
+- if (!nspm->uuid)
+- break;
+- if (memcmp(uuid, nspm->uuid, NSLABEL_UUID_LEN) == 0)
+- return -EBUSY;
+- break;
+- }
+- case ND_DEVICE_NAMESPACE_BLK: {
+- struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
+-
+- if (!nsblk->uuid)
+- break;
+- if (memcmp(uuid, nsblk->uuid, NSLABEL_UUID_LEN) == 0)
+- return -EBUSY;
+- break;
+- }
+- default:
+- break;
+- }
+-
+- return 0;
+-}
+-
+-static int is_namespace_uuid_busy(struct device *dev, void *data)
+-{
+- if (is_nd_pmem(dev) || is_nd_blk(dev))
+- return device_for_each_child(dev, data, is_uuid_busy);
+- return 0;
+-}
+-
+-/**
+- * nd_is_uuid_unique - verify that no other namespace has @uuid
+- * @dev: any device on a nvdimm_bus
+- * @uuid: uuid to check
+- */
+-bool nd_is_uuid_unique(struct device *dev, u8 *uuid)
+-{
+- struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
+-
+- if (!nvdimm_bus)
+- return false;
+- WARN_ON_ONCE(!is_nvdimm_bus_locked(&nvdimm_bus->dev));
+- if (device_for_each_child(&nvdimm_bus->dev, uuid,
+- is_namespace_uuid_busy) != 0)
+- return false;
+- return true;
+-}
+-
+ static ssize_t size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/of/irq.c linux-libre-4.4.7-gnu/drivers/of/irq.c
+--- linux-libre-4.4-gnu/drivers/of/irq.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/of/irq.c 2016-04-12 12:09:26.000000000 -0400
+@@ -636,6 +636,13 @@ static u32 __of_msi_map_rid(struct devic
+ msi_base = be32_to_cpup(msi_map + 2);
+ rid_len = be32_to_cpup(msi_map + 3);
+
++ if (rid_base & ~map_mask) {
++ dev_err(parent_dev,
++ "Invalid msi-map translation - msi-map-mask (0x%x) ignores rid-base (0x%x)\n",
++ map_mask, rid_base);
++ return rid_out;
++ }
++
+ msi_controller_node = of_find_node_by_phandle(phandle);
+
+ matched = (masked_rid >= rid_base &&
+@@ -655,7 +662,7 @@ static u32 __of_msi_map_rid(struct devic
+ if (!matched)
+ return rid_out;
+
+- rid_out = masked_rid + msi_base;
++ rid_out = masked_rid - rid_base + msi_base;
+ dev_dbg(dev,
+ "msi-map at: %s, using mask %08x, rid-base: %08x, msi-base: %08x, length: %08x, rid: %08x -> %08x\n",
+ dev_name(parent_dev), map_mask, rid_base, msi_base,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/of/of_reserved_mem.c linux-libre-4.4.7-gnu/drivers/of/of_reserved_mem.c
+--- linux-libre-4.4-gnu/drivers/of/of_reserved_mem.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/of/of_reserved_mem.c 2016-04-12 12:09:26.000000000 -0400
+@@ -32,11 +32,13 @@ int __init __weak early_init_dt_alloc_re
+ phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
+ phys_addr_t *res_base)
+ {
++ phys_addr_t base;
+ /*
+ * We use __memblock_alloc_base() because memblock_alloc_base()
+ * panic()s on allocation failure.
+ */
+- phys_addr_t base = __memblock_alloc_base(size, align, end);
++ end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
++ base = __memblock_alloc_base(size, align, end);
+ if (!base)
+ return -ENOMEM;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/bus.c linux-libre-4.4.7-gnu/drivers/pci/bus.c
+--- linux-libre-4.4-gnu/drivers/pci/bus.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/bus.c 2016-04-12 12:09:26.000000000 -0400
+@@ -140,6 +140,8 @@ static int pci_bus_alloc_from_region(str
+ type_mask |= IORESOURCE_TYPE_BITS;
+
+ pci_bus_for_each_resource(bus, r, i) {
++ resource_size_t min_used = min;
++
+ if (!r)
+ continue;
+
+@@ -163,12 +165,12 @@ static int pci_bus_alloc_from_region(str
+ * overrides "min".
+ */
+ if (avail.start)
+- min = avail.start;
++ min_used = avail.start;
+
+ max = avail.end;
+
+ /* Ok, try it out.. */
+- ret = allocate_resource(r, res, size, min, max,
++ ret = allocate_resource(r, res, size, min_used, max,
+ align, alignf, alignf_data);
+ if (ret == 0)
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pci-dra7xx.c linux-libre-4.4.7-gnu/drivers/pci/host/pci-dra7xx.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pci-dra7xx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pci-dra7xx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -302,7 +302,8 @@ static int __init dra7xx_add_pcie_port(s
+ }
+
+ ret = devm_request_irq(&pdev->dev, pp->irq,
+- dra7xx_pcie_msi_irq_handler, IRQF_SHARED,
++ dra7xx_pcie_msi_irq_handler,
++ IRQF_SHARED | IRQF_NO_THREAD,
+ "dra7-pcie-msi", pp);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request irq\n");
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pcie-rcar.c linux-libre-4.4.7-gnu/drivers/pci/host/pcie-rcar.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pcie-rcar.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pcie-rcar.c 2016-04-12 12:09:26.000000000 -0400
+@@ -720,14 +720,16 @@ static int rcar_pcie_enable_msi(struct r
+
+ /* Two irqs are for MSI, but they are also used for non-MSI irqs */
+ err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq,
+- IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
++ IRQF_SHARED | IRQF_NO_THREAD,
++ rcar_msi_irq_chip.name, pcie);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
+ goto err;
+ }
+
+ err = devm_request_irq(&pdev->dev, msi->irq2, rcar_pcie_msi_irq,
+- IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
++ IRQF_SHARED | IRQF_NO_THREAD,
++ rcar_msi_irq_chip.name, pcie);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
+ goto err;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pcie-spear13xx.c linux-libre-4.4.7-gnu/drivers/pci/host/pcie-spear13xx.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pcie-spear13xx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pcie-spear13xx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -279,7 +279,8 @@ static int spear13xx_add_pcie_port(struc
+ return -ENODEV;
+ }
+ ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
+- IRQF_SHARED, "spear1340-pcie", pp);
++ IRQF_SHARED | IRQF_NO_THREAD,
++ "spear1340-pcie", pp);
+ if (ret) {
+ dev_err(dev, "failed to request irq %d\n", pp->irq);
+ return ret;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pcie-xilinx.c linux-libre-4.4.7-gnu/drivers/pci/host/pcie-xilinx.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pcie-xilinx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pcie-xilinx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -781,7 +781,8 @@ static int xilinx_pcie_parse_dt(struct x
+
+ port->irq = irq_of_parse_and_map(node, 0);
+ err = devm_request_irq(dev, port->irq, xilinx_pcie_intr_handler,
+- IRQF_SHARED, "xilinx-pcie", port);
++ IRQF_SHARED | IRQF_NO_THREAD,
++ "xilinx-pcie", port);
+ if (err) {
+ dev_err(dev, "unable to request irq %d\n", port->irq);
+ return err;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pci-exynos.c linux-libre-4.4.7-gnu/drivers/pci/host/pci-exynos.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pci-exynos.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pci-exynos.c 2016-04-12 12:09:26.000000000 -0400
+@@ -522,7 +522,8 @@ static int __init exynos_add_pcie_port(s
+
+ ret = devm_request_irq(&pdev->dev, pp->msi_irq,
+ exynos_pcie_msi_irq_handler,
+- IRQF_SHARED, "exynos-pcie", pp);
++ IRQF_SHARED | IRQF_NO_THREAD,
++ "exynos-pcie", pp);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request msi irq\n");
+ return ret;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pci-imx6.c linux-libre-4.4.7-gnu/drivers/pci/host/pci-imx6.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pci-imx6.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pci-imx6.c 2016-04-12 12:09:26.000000000 -0400
+@@ -537,7 +537,8 @@ static int __init imx6_add_pcie_port(str
+
+ ret = devm_request_irq(&pdev->dev, pp->msi_irq,
+ imx6_pcie_msi_handler,
+- IRQF_SHARED, "mx6-pcie-msi", pp);
++ IRQF_SHARED | IRQF_NO_THREAD,
++ "mx6-pcie-msi", pp);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request MSI irq\n");
+ return ret;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pci-keystone-dw.c linux-libre-4.4.7-gnu/drivers/pci/host/pci-keystone-dw.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pci-keystone-dw.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pci-keystone-dw.c 2016-04-12 12:09:26.000000000 -0400
+@@ -58,11 +58,6 @@
+
+ #define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
+
+-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
+-{
+- return sys->private_data;
+-}
+-
+ static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
+ u32 *bit_pos)
+ {
+@@ -108,7 +103,7 @@ static void ks_dw_pcie_msi_irq_ack(struc
+ struct pcie_port *pp;
+
+ msi = irq_data_get_msi_desc(d);
+- pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
++ pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
+ ks_pcie = to_keystone_pcie(pp);
+ offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
+ update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
+@@ -146,7 +141,7 @@ static void ks_dw_pcie_msi_irq_mask(stru
+ u32 offset;
+
+ msi = irq_data_get_msi_desc(d);
+- pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
++ pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
+ ks_pcie = to_keystone_pcie(pp);
+ offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
+
+@@ -167,7 +162,7 @@ static void ks_dw_pcie_msi_irq_unmask(st
+ u32 offset;
+
+ msi = irq_data_get_msi_desc(d);
+- pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
++ pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
+ ks_pcie = to_keystone_pcie(pp);
+ offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/host/pci-tegra.c linux-libre-4.4.7-gnu/drivers/pci/host/pci-tegra.c
+--- linux-libre-4.4-gnu/drivers/pci/host/pci-tegra.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/host/pci-tegra.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1288,7 +1288,7 @@ static int tegra_pcie_enable_msi(struct
+
+ msi->irq = err;
+
+- err = request_irq(msi->irq, tegra_pcie_msi_irq, 0,
++ err = request_irq(msi->irq, tegra_pcie_msi_irq, IRQF_NO_THREAD,
+ tegra_msi_irq_chip.name, pcie);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/hotplug/acpiphp_glue.c linux-libre-4.4.7-gnu/drivers/pci/hotplug/acpiphp_glue.c
+--- linux-libre-4.4-gnu/drivers/pci/hotplug/acpiphp_glue.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/hotplug/acpiphp_glue.c 2016-04-12 12:09:26.000000000 -0400
+@@ -953,8 +953,10 @@ int acpiphp_enable_slot(struct acpiphp_s
+ {
+ pci_lock_rescan_remove();
+
+- if (slot->flags & SLOT_IS_GOING_AWAY)
++ if (slot->flags & SLOT_IS_GOING_AWAY) {
++ pci_unlock_rescan_remove();
+ return -ENODEV;
++ }
+
+ /* configure all functions */
+ if (!(slot->flags & SLOT_ENABLED))
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/pci.c linux-libre-4.4.7-gnu/drivers/pci/pci.c
+--- linux-libre-4.4-gnu/drivers/pci/pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -4772,8 +4772,10 @@ int pci_get_new_domain_nr(void)
+ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+ {
+ static int use_dt_domains = -1;
+- int domain = of_get_pci_domain_nr(parent->of_node);
++ int domain = -1;
+
++ if (parent)
++ domain = of_get_pci_domain_nr(parent->of_node);
+ /*
+ * Check DT domain and use_dt_domains values.
+ *
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/pcie/aer/aerdrv.c linux-libre-4.4.7-gnu/drivers/pci/pcie/aer/aerdrv.c
+--- linux-libre-4.4-gnu/drivers/pci/pcie/aer/aerdrv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/pcie/aer/aerdrv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -262,7 +262,6 @@ static struct aer_rpc *aer_alloc_rpc(str
+ rpc->rpd = dev;
+ INIT_WORK(&rpc->dpc_handler, aer_isr);
+ mutex_init(&rpc->rpc_mutex);
+- init_waitqueue_head(&rpc->wait_release);
+
+ /* Use PCIe bus function to store rpc into PCIe device */
+ set_service_data(dev, rpc);
+@@ -285,8 +284,7 @@ static void aer_remove(struct pcie_devic
+ if (rpc->isr)
+ free_irq(dev->irq, dev);
+
+- wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
+-
++ flush_work(&rpc->dpc_handler);
+ aer_disable_rootport(rpc);
+ kfree(rpc);
+ set_service_data(dev, NULL);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/pcie/aer/aerdrv_core.c linux-libre-4.4.7-gnu/drivers/pci/pcie/aer/aerdrv_core.c
+--- linux-libre-4.4-gnu/drivers/pci/pcie/aer/aerdrv_core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/pcie/aer/aerdrv_core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -811,8 +811,6 @@ void aer_isr(struct work_struct *work)
+ while (get_e_source(rpc, &e_src))
+ aer_isr_one_error(p_device, &e_src);
+ mutex_unlock(&rpc->rpc_mutex);
+-
+- wake_up(&rpc->wait_release);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/pcie/aer/aerdrv.h linux-libre-4.4.7-gnu/drivers/pci/pcie/aer/aerdrv.h
+--- linux-libre-4.4-gnu/drivers/pci/pcie/aer/aerdrv.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/pcie/aer/aerdrv.h 2016-04-12 12:09:26.000000000 -0400
+@@ -72,7 +72,6 @@ struct aer_rpc {
+ * recovery on the same
+ * root port hierarchy
+ */
+- wait_queue_head_t wait_release;
+ };
+
+ struct aer_broadcast_data {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/probe.c linux-libre-4.4.7-gnu/drivers/pci/probe.c
+--- linux-libre-4.4-gnu/drivers/pci/probe.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/probe.c 2016-04-12 12:09:26.000000000 -0400
+@@ -179,6 +179,9 @@ int __pci_read_base(struct pci_dev *dev,
+ u16 orig_cmd;
+ struct pci_bus_region region, inverted_region;
+
++ if (dev->non_compliant_bars)
++ return 0;
++
+ mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
+
+ /* No printks while decoding is disabled! */
+@@ -1174,6 +1177,7 @@ void pci_msi_setup_pci_dev(struct pci_de
+ int pci_setup_device(struct pci_dev *dev)
+ {
+ u32 class;
++ u16 cmd;
+ u8 hdr_type;
+ int pos = 0;
+ struct pci_bus_region region;
+@@ -1219,6 +1223,16 @@ int pci_setup_device(struct pci_dev *dev
+ /* device class may be changed after fixup */
+ class = dev->class >> 8;
+
++ if (dev->non_compliant_bars) {
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
++ dev_info(&dev->dev, "device has non-compliant BARs; disabling IO/MEM decoding\n");
++ cmd &= ~PCI_COMMAND_IO;
++ cmd &= ~PCI_COMMAND_MEMORY;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ }
++ }
++
+ switch (dev->hdr_type) { /* header type */
+ case PCI_HEADER_TYPE_NORMAL: /* standard header */
+ if (class == PCI_CLASS_BRIDGE_PCI)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pci/xen-pcifront.c linux-libre-4.4.7-gnu/drivers/pci/xen-pcifront.c
+--- linux-libre-4.4-gnu/drivers/pci/xen-pcifront.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pci/xen-pcifront.c 2016-04-12 12:09:26.000000000 -0400
+@@ -53,7 +53,7 @@ struct pcifront_device {
+ };
+
+ struct pcifront_sd {
+- int domain;
++ struct pci_sysdata sd;
+ struct pcifront_device *pdev;
+ };
+
+@@ -67,7 +67,9 @@ static inline void pcifront_init_sd(stru
+ unsigned int domain, unsigned int bus,
+ struct pcifront_device *pdev)
+ {
+- sd->domain = domain;
++ /* Because we do not expose that information via XenBus. */
++ sd->sd.node = first_online_node;
++ sd->sd.domain = domain;
+ sd->pdev = pdev;
+ }
+
+@@ -468,8 +470,8 @@ static int pcifront_scan_root(struct pci
+ dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
+ domain, bus);
+
+- bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
+- sd = kmalloc(sizeof(*sd), GFP_KERNEL);
++ bus_entry = kzalloc(sizeof(*bus_entry), GFP_KERNEL);
++ sd = kzalloc(sizeof(*sd), GFP_KERNEL);
+ if (!bus_entry || !sd) {
+ err = -ENOMEM;
+ goto err_out;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/phy/phy-core.c linux-libre-4.4.7-gnu/drivers/phy/phy-core.c
+--- linux-libre-4.4-gnu/drivers/phy/phy-core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/phy/phy-core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -275,20 +275,21 @@ EXPORT_SYMBOL_GPL(phy_exit);
+
+ int phy_power_on(struct phy *phy)
+ {
+- int ret;
++ int ret = 0;
+
+ if (!phy)
+- return 0;
++ goto out;
+
+ if (phy->pwr) {
+ ret = regulator_enable(phy->pwr);
+ if (ret)
+- return ret;
++ goto out;
+ }
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+- return ret;
++ goto err_pm_sync;
++
+ ret = 0; /* Override possible ret == -ENOTSUPP */
+
+ mutex_lock(&phy->mutex);
+@@ -296,19 +297,20 @@ int phy_power_on(struct phy *phy)
+ ret = phy->ops->power_on(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
+- goto out;
++ goto err_pwr_on;
+ }
+ }
+ ++phy->power_count;
+ mutex_unlock(&phy->mutex);
+ return 0;
+
+-out:
++err_pwr_on:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put_sync(phy);
++err_pm_sync:
+ if (phy->pwr)
+ regulator_disable(phy->pwr);
+-
++out:
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(phy_power_on);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/phy/phy-twl4030-usb.c linux-libre-4.4.7-gnu/drivers/phy/phy-twl4030-usb.c
+--- linux-libre-4.4-gnu/drivers/phy/phy-twl4030-usb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/phy/phy-twl4030-usb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -715,6 +715,7 @@ static int twl4030_usb_probe(struct plat
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+ pm_runtime_enable(&pdev->dev);
++ pm_runtime_get_sync(&pdev->dev);
+
+ /* Our job is to use irqs and status from the power module
+ * to keep the transceiver disabled when nothing's connected.
+@@ -750,6 +751,7 @@ static int twl4030_usb_remove(struct pla
+ struct twl4030_usb *twl = platform_get_drvdata(pdev);
+ int val;
+
++ usb_remove_phy(&twl->phy);
+ pm_runtime_get_sync(twl->dev);
+ cancel_delayed_work(&twl->id_workaround_work);
+ device_remove_file(twl->dev, &dev_attr_vbus);
+@@ -757,6 +759,13 @@ static int twl4030_usb_remove(struct pla
+ /* set transceiver mode to power on defaults */
+ twl4030_usb_set_mode(twl, -1);
+
++ /* idle ulpi before powering off */
++ if (cable_present(twl->linkstat))
++ pm_runtime_put_noidle(twl->dev);
++ pm_runtime_mark_last_busy(twl->dev);
++ pm_runtime_put_sync_suspend(twl->dev);
++ pm_runtime_disable(twl->dev);
++
+ /* autogate 60MHz ULPI clock,
+ * clear dpll clock request for i2c access,
+ * disable 32KHz
+@@ -771,11 +780,6 @@ static int twl4030_usb_remove(struct pla
+ /* disable complete OTG block */
+ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
+
+- if (cable_present(twl->linkstat))
+- pm_runtime_put_noidle(twl->dev);
+- pm_runtime_mark_last_busy(twl->dev);
+- pm_runtime_put(twl->dev);
+-
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/pinctrl/bcm/pinctrl-bcm2835.c linux-libre-4.4.7-gnu/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+--- linux-libre-4.4-gnu/drivers/pinctrl/bcm/pinctrl-bcm2835.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/pinctrl/bcm/pinctrl-bcm2835.c 2016-04-12 12:09:26.000000000 -0400
+@@ -779,7 +779,7 @@ static int bcm2835_pctl_dt_node_to_map(s
+ }
+ if (num_pulls) {
+ err = of_property_read_u32_index(np, "brcm,pull",
+- (num_funcs > 1) ? i : 0, &pull);
++ (num_pulls > 1) ? i : 0, &pull);
+ if (err)
+ goto out;
+ err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/platform/x86/ideapad-laptop.c linux-libre-4.4.7-gnu/drivers/platform/x86/ideapad-laptop.c
+--- linux-libre-4.4-gnu/drivers/platform/x86/ideapad-laptop.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/platform/x86/ideapad-laptop.c 2016-04-12 12:09:26.000000000 -0400
+@@ -865,6 +865,27 @@ static const struct dmi_system_id no_hw_
+ },
+ },
+ {
++ .ident = "Lenovo ideapad Y700-15ISK",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ISK"),
++ },
++ },
++ {
++ .ident = "Lenovo ideapad Y700 Touch-15ISK",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700 Touch-15ISK"),
++ },
++ },
++ {
++ .ident = "Lenovo ideapad Y700-17ISK",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"),
++ },
++ },
++ {
+ .ident = "Lenovo Yoga 2 11 / 13 / Pro",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+@@ -893,6 +914,13 @@ static const struct dmi_system_id no_hw_
+ },
+ },
+ {
++ .ident = "Lenovo Yoga 700",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 700"),
++ },
++ },
++ {
+ .ident = "Lenovo Yoga 900",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/platform/x86/intel_scu_ipcutil.c linux-libre-4.4.7-gnu/drivers/platform/x86/intel_scu_ipcutil.c
+--- linux-libre-4.4-gnu/drivers/platform/x86/intel_scu_ipcutil.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/platform/x86/intel_scu_ipcutil.c 2016-04-12 12:09:26.000000000 -0400
+@@ -49,7 +49,7 @@ struct scu_ipc_data {
+
+ static int scu_reg_access(u32 cmd, struct scu_ipc_data *data)
+ {
+- int count = data->count;
++ unsigned int count = data->count;
+
+ if (count == 0 || count == 3 || count > 4)
+ return -EINVAL;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/platform/x86/toshiba_acpi.c linux-libre-4.4.7-gnu/drivers/platform/x86/toshiba_acpi.c
+--- linux-libre-4.4-gnu/drivers/platform/x86/toshiba_acpi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/platform/x86/toshiba_acpi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2484,6 +2484,14 @@ static int toshiba_acpi_setup_backlight(
+ brightness = __get_lcd_brightness(dev);
+ if (brightness < 0)
+ return 0;
++ /*
++ * If transflective backlight is supported and the brightness is zero
++ * (lowest brightness level), the set_lcd_brightness function will
++ * activate the transflective backlight, making the LCD appear to be
++ * turned off, simply increment the brightness level to avoid that.
++ */
++ if (dev->tr_backlight_supported && brightness == 0)
++ brightness++;
+ ret = set_lcd_brightness(dev, brightness);
+ if (ret) {
+ pr_debug("Backlight method is read-only, disabling backlight support\n");
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/regulator/axp20x-regulator.c linux-libre-4.4.7-gnu/drivers/regulator/axp20x-regulator.c
+--- linux-libre-4.4-gnu/drivers/regulator/axp20x-regulator.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/regulator/axp20x-regulator.c 2016-04-12 12:09:26.000000000 -0400
+@@ -27,8 +27,8 @@
+ #define AXP20X_IO_ENABLED 0x03
+ #define AXP20X_IO_DISABLED 0x07
+
+-#define AXP22X_IO_ENABLED 0x04
+-#define AXP22X_IO_DISABLED 0x03
++#define AXP22X_IO_ENABLED 0x03
++#define AXP22X_IO_DISABLED 0x04
+
+ #define AXP20X_WORKMODE_DCDC2_MASK BIT(2)
+ #define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/regulator/core.c linux-libre-4.4.7-gnu/drivers/regulator/core.c
+--- linux-libre-4.4-gnu/drivers/regulator/core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/regulator/core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -132,24 +132,24 @@ static bool have_full_constraints(void)
+ return has_full_constraints || of_have_populated_dt();
+ }
+
++static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev)
++{
++ if (rdev && rdev->supply)
++ return rdev->supply->rdev;
++
++ return NULL;
++}
++
+ /**
+ * regulator_lock_supply - lock a regulator and its supplies
+ * @rdev: regulator source
+ */
+ static void regulator_lock_supply(struct regulator_dev *rdev)
+ {
+- struct regulator *supply;
+- int i = 0;
+-
+- while (1) {
+- mutex_lock_nested(&rdev->mutex, i++);
+- supply = rdev->supply;
+-
+- if (!rdev->supply)
+- return;
++ int i;
+
+- rdev = supply->rdev;
+- }
++ for (i = 0; rdev->supply; rdev = rdev_get_supply(rdev), i++)
++ mutex_lock_nested(&rdev->mutex, i);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/regulator/Kconfig linux-libre-4.4.7-gnu/drivers/regulator/Kconfig
+--- linux-libre-4.4-gnu/drivers/regulator/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/regulator/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -446,6 +446,7 @@ config REGULATOR_MC13892
+ config REGULATOR_MT6311
+ tristate "MediaTek MT6311 PMIC"
+ depends on I2C
++ select REGMAP_I2C
+ help
+ Say y here to select this option to enable the power regulator of
+ MediaTek MT6311 PMIC.
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/s390/block/dasd_alias.c linux-libre-4.4.7-gnu/drivers/s390/block/dasd_alias.c
+--- linux-libre-4.4-gnu/drivers/s390/block/dasd_alias.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/s390/block/dasd_alias.c 2016-04-12 12:09:26.000000000 -0400
+@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_l
+ spin_unlock_irqrestore(&lcu->lock, flags);
+ cancel_work_sync(&lcu->suc_data.worker);
+ spin_lock_irqsave(&lcu->lock, flags);
+- if (device == lcu->suc_data.device)
++ if (device == lcu->suc_data.device) {
++ dasd_put_device(device);
+ lcu->suc_data.device = NULL;
++ }
+ }
+ was_pending = 0;
+ if (device == lcu->ruac_data.device) {
+@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_l
+ was_pending = 1;
+ cancel_delayed_work_sync(&lcu->ruac_data.dwork);
+ spin_lock_irqsave(&lcu->lock, flags);
+- if (device == lcu->ruac_data.device)
++ if (device == lcu->ruac_data.device) {
++ dasd_put_device(device);
+ lcu->ruac_data.device = NULL;
++ }
+ }
+ private->lcu = NULL;
+ spin_unlock_irqrestore(&lcu->lock, flags);
+@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_
+ if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
+ DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
+ " alias data in lcu (rc = %d), retry later", rc);
+- schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
++ if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ))
++ dasd_put_device(device);
+ } else {
++ dasd_put_device(device);
+ lcu->ruac_data.device = NULL;
+ lcu->flags &= ~UPDATE_PENDING;
+ }
+@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct a
+ */
+ if (!usedev)
+ return -EINVAL;
++ dasd_get_device(usedev);
+ lcu->ruac_data.device = usedev;
+- schedule_delayed_work(&lcu->ruac_data.dwork, 0);
++ if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0))
++ dasd_put_device(usedev);
+ return 0;
+ }
+
+@@ -723,7 +731,7 @@ static int reset_summary_unit_check(stru
+ ASCEBC((char *) &cqr->magic, 4);
+ ccw = cqr->cpaddr;
+ ccw->cmd_code = DASD_ECKD_CCW_RSCK;
+- ccw->flags = 0 ;
++ ccw->flags = CCW_FLAG_SLI;
+ ccw->count = 16;
+ ccw->cda = (__u32)(addr_t) cqr->data;
+ ((char *)cqr->data)[0] = reason;
+@@ -930,6 +938,7 @@ static void summary_unit_check_handling_
+ /* 3. read new alias configuration */
+ _schedule_lcu_update(lcu, device);
+ lcu->suc_data.device = NULL;
++ dasd_put_device(device);
+ spin_unlock_irqrestore(&lcu->lock, flags);
+ }
+
+@@ -989,6 +998,8 @@ void dasd_alias_handle_summary_unit_chec
+ }
+ lcu->suc_data.reason = reason;
+ lcu->suc_data.device = device;
++ dasd_get_device(device);
+ spin_unlock(&lcu->lock);
+- schedule_work(&lcu->suc_data.worker);
++ if (!schedule_work(&lcu->suc_data.worker))
++ dasd_put_device(device);
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/s390/block/dasd.c linux-libre-4.4.7-gnu/drivers/s390/block/dasd.c
+--- linux-libre-4.4-gnu/drivers/s390/block/dasd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/s390/block/dasd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3031,6 +3031,7 @@ static void dasd_setup_queue(struct dasd
+ max = block->base->discipline->max_blocks << block->s2b_shift;
+ }
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue);
++ block->request_queue->limits.max_dev_sectors = max;
+ blk_queue_logical_block_size(block->request_queue,
+ block->bp_block);
+ blk_queue_max_hw_sectors(block->request_queue, max);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/s390/block/dasd_diag.c linux-libre-4.4.7-gnu/drivers/s390/block/dasd_diag.c
+--- linux-libre-4.4-gnu/drivers/s390/block/dasd_diag.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/s390/block/dasd_diag.c 2016-04-12 12:09:26.000000000 -0400
+@@ -67,7 +67,7 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc
+ * and function code cmd.
+ * In case of an exception return 3. Otherwise return result of bitwise OR of
+ * resulting condition code and DIAG return code. */
+-static inline int dia250(void *iob, int cmd)
++static inline int __dia250(void *iob, int cmd)
+ {
+ register unsigned long reg2 asm ("2") = (unsigned long) iob;
+ typedef union {
+@@ -77,7 +77,6 @@ static inline int dia250(void *iob, int
+ int rc;
+
+ rc = 3;
+- diag_stat_inc(DIAG_STAT_X250);
+ asm volatile(
+ " diag 2,%2,0x250\n"
+ "0: ipm %0\n"
+@@ -91,6 +90,12 @@ static inline int dia250(void *iob, int
+ return rc;
+ }
+
++static inline int dia250(void *iob, int cmd)
++{
++ diag_stat_inc(DIAG_STAT_X250);
++ return __dia250(iob, cmd);
++}
++
+ /* Initialize block I/O to DIAG device using the specified blocksize and
+ * block offset. On success, return zero and set end_block to contain the
+ * number of blocks on the device minus the specified offset. Return non-zero
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/aacraid/aacraid.h linux-libre-4.4.7-gnu/drivers/scsi/aacraid/aacraid.h
+--- linux-libre-4.4-gnu/drivers/scsi/aacraid/aacraid.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/aacraid/aacraid.h 2016-04-12 12:09:26.000000000 -0400
+@@ -944,6 +944,7 @@ struct fib {
+ */
+ struct list_head fiblink;
+ void *data;
++ u32 vector_no;
+ struct hw_fib *hw_fib_va; /* Actual shared object */
+ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/
+ };
+@@ -2113,6 +2114,7 @@ static inline unsigned int cap_to_cyls(s
+ int aac_acquire_irq(struct aac_dev *dev);
+ void aac_free_irq(struct aac_dev *dev);
+ const char *aac_driverinfo(struct Scsi_Host *);
++void aac_fib_vector_assign(struct aac_dev *dev);
+ struct fib *aac_fib_alloc(struct aac_dev *dev);
+ int aac_fib_setup(struct aac_dev *dev);
+ void aac_fib_map_free(struct aac_dev *dev);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/aacraid/commsup.c linux-libre-4.4.7-gnu/drivers/scsi/aacraid/commsup.c
+--- linux-libre-4.4-gnu/drivers/scsi/aacraid/commsup.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/aacraid/commsup.c 2016-04-12 12:09:26.000000000 -0400
+@@ -83,13 +83,38 @@ static int fib_map_alloc(struct aac_dev
+
+ void aac_fib_map_free(struct aac_dev *dev)
+ {
+- pci_free_consistent(dev->pdev,
+- dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
+- dev->hw_fib_va, dev->hw_fib_pa);
++ if (dev->hw_fib_va && dev->max_fib_size) {
++ pci_free_consistent(dev->pdev,
++ (dev->max_fib_size *
++ (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)),
++ dev->hw_fib_va, dev->hw_fib_pa);
++ }
+ dev->hw_fib_va = NULL;
+ dev->hw_fib_pa = 0;
+ }
+
++void aac_fib_vector_assign(struct aac_dev *dev)
++{
++ u32 i = 0;
++ u32 vector = 1;
++ struct fib *fibptr = NULL;
++
++ for (i = 0, fibptr = &dev->fibs[i];
++ i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
++ i++, fibptr++) {
++ if ((dev->max_msix == 1) ||
++ (i > ((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1)
++ - dev->vector_cap))) {
++ fibptr->vector_no = 0;
++ } else {
++ fibptr->vector_no = vector;
++ vector++;
++ if (vector == dev->max_msix)
++ vector = 1;
++ }
++ }
++}
++
+ /**
+ * aac_fib_setup - setup the fibs
+ * @dev: Adapter to set up
+@@ -151,6 +176,12 @@ int aac_fib_setup(struct aac_dev * dev)
+ hw_fib_pa = hw_fib_pa +
+ dev->max_fib_size + sizeof(struct aac_fib_xporthdr);
+ }
++
++ /*
++ *Assign vector numbers to fibs
++ */
++ aac_fib_vector_assign(dev);
++
+ /*
+ * Add the fib chain to the free list
+ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/aacraid/linit.c linux-libre-4.4.7-gnu/drivers/scsi/aacraid/linit.c
+--- linux-libre-4.4-gnu/drivers/scsi/aacraid/linit.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/aacraid/linit.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1404,8 +1404,18 @@ static int aac_acquire_resources(struct
+
+ aac_adapter_enable_int(dev);
+
+- if (!dev->sync_mode)
++ /*max msix may change after EEH
++ * Re-assign vectors to fibs
++ */
++ aac_fib_vector_assign(dev);
++
++ if (!dev->sync_mode) {
++ /* After EEH recovery or suspend resume, max_msix count
++ * may change, therfore updating in init as well.
++ */
+ aac_adapter_start(dev);
++ dev->init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix);
++ }
+ return 0;
+
+ error_iounmap:
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/aacraid/src.c linux-libre-4.4.7-gnu/drivers/scsi/aacraid/src.c
+--- linux-libre-4.4-gnu/drivers/scsi/aacraid/src.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/aacraid/src.c 2016-04-12 12:09:26.000000000 -0400
+@@ -156,8 +156,8 @@ static irqreturn_t aac_src_intr_message(
+ break;
+ if (dev->msi_enabled && dev->max_msix > 1)
+ atomic_dec(&dev->rrq_outstanding[vector_no]);
+- aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
+ dev->host_rrq[index++] = 0;
++ aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
+ if (index == (vector_no + 1) * dev->vector_cap)
+ index = vector_no * dev->vector_cap;
+ dev->host_rrq_idx[vector_no] = index;
+@@ -452,36 +452,20 @@ static int aac_src_deliver_message(struc
+ #endif
+
+ u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
++ u16 vector_no;
+
+ atomic_inc(&q->numpending);
+
+ if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest &&
+ dev->max_msix > 1) {
+- u_int16_t vector_no, first_choice = 0xffff;
+-
+- vector_no = dev->fibs_pushed_no % dev->max_msix;
+- do {
+- vector_no += 1;
+- if (vector_no == dev->max_msix)
+- vector_no = 1;
+- if (atomic_read(&dev->rrq_outstanding[vector_no]) <
+- dev->vector_cap)
+- break;
+- if (0xffff == first_choice)
+- first_choice = vector_no;
+- else if (vector_no == first_choice)
+- break;
+- } while (1);
+- if (vector_no == first_choice)
+- vector_no = 0;
+- atomic_inc(&dev->rrq_outstanding[vector_no]);
+- if (dev->fibs_pushed_no == 0xffffffff)
+- dev->fibs_pushed_no = 0;
+- else
+- dev->fibs_pushed_no++;
++ vector_no = fib->vector_no;
+ fib->hw_fib_va->header.Handle += (vector_no << 16);
++ } else {
++ vector_no = 0;
+ }
+
++ atomic_inc(&dev->rrq_outstanding[vector_no]);
++
+ if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
+ /* Calculate the amount to the fibsize bits */
+ fibsize = (hdr_size + 127) / 128 - 1;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-libre-4.4.7-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c
+--- linux-libre-4.4-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1336,6 +1336,7 @@ ahc_platform_set_tags(struct ahc_softc *
+ case AHC_DEV_Q_TAGGED:
+ scsi_change_queue_depth(sdev,
+ dev->openings + dev->active);
++ break;
+ default:
+ /*
+ * We allow the OS to queue 2 untagged transactions to
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/be2iscsi/be_main.c linux-libre-4.4.7-gnu/drivers/scsi/be2iscsi/be_main.c
+--- linux-libre-4.4-gnu/drivers/scsi/be2iscsi/be_main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/be2iscsi/be_main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -4470,6 +4470,7 @@ put_shost:
+ scsi_host_put(phba->shost);
+ free_kset:
+ iscsi_boot_destroy_kset(phba->boot_kset);
++ phba->boot_kset = NULL;
+ return -ENOMEM;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c linux-libre-4.4.7-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c
+--- linux-libre-4.4-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c 2016-04-12 12:09:26.000000000 -0400
+@@ -562,7 +562,7 @@ static int mode_select_handle_sense(stru
+ /*
+ * Command Lock contention
+ */
+- err = SCSI_DH_RETRY;
++ err = SCSI_DH_IMM_RETRY;
+ break;
+ default:
+ break;
+@@ -612,6 +612,8 @@ retry:
+ err = mode_select_handle_sense(sdev, h->sense);
+ if (err == SCSI_DH_RETRY && retry_cnt--)
+ goto retry;
++ if (err == SCSI_DH_IMM_RETRY)
++ goto retry;
+ }
+ if (err == SCSI_DH_OK) {
+ h->state = RDAC_STATE_ACTIVE;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/ipr.c linux-libre-4.4.7-gnu/drivers/scsi/ipr.c
+--- linux-libre-4.4-gnu/drivers/scsi/ipr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/ipr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -4003,13 +4003,17 @@ static ssize_t ipr_store_update_fw(struc
+ struct ipr_sglist *sglist;
+ char fname[100];
+ char *src;
+- int len, result, dnld_size;
++ char *endline;
++ int result, dnld_size;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+- len = snprintf(fname, 99, "%s", buf);
+- fname[len-1] = '\0';
++ snprintf(fname, sizeof(fname), "%s", buf);
++
++ endline = strchr(fname, '\n');
++ if (endline)
++ *endline = '\0';
+
+ if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) {
+ dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_init.c linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_init.c
+--- linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_init.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_init.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2192,7 +2192,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
+ /* Clear outstanding commands array. */
+ for (que = 0; que < ha->max_req_queues; que++) {
+ req = ha->req_q_map[que];
+- if (!req)
++ if (!req || !test_bit(que, ha->req_qid_map))
+ continue;
+ req->out_ptr = (void *)(req->ring + req->length);
+ *req->out_ptr = 0;
+@@ -2209,7 +2209,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
+
+ for (que = 0; que < ha->max_rsp_queues; que++) {
+ rsp = ha->rsp_q_map[que];
+- if (!rsp)
++ if (!rsp || !test_bit(que, ha->rsp_qid_map))
+ continue;
+ rsp->in_ptr = (void *)(rsp->ring + rsp->length);
+ *rsp->in_ptr = 0;
+@@ -4961,7 +4961,7 @@ qla25xx_init_queues(struct qla_hw_data *
+
+ for (i = 1; i < ha->max_rsp_queues; i++) {
+ rsp = ha->rsp_q_map[i];
+- if (rsp) {
++ if (rsp && test_bit(i, ha->rsp_qid_map)) {
+ rsp->options &= ~BIT_0;
+ ret = qla25xx_init_rsp_que(base_vha, rsp);
+ if (ret != QLA_SUCCESS)
+@@ -4976,8 +4976,8 @@ qla25xx_init_queues(struct qla_hw_data *
+ }
+ for (i = 1; i < ha->max_req_queues; i++) {
+ req = ha->req_q_map[i];
+- if (req) {
+- /* Clear outstanding commands array. */
++ if (req && test_bit(i, ha->req_qid_map)) {
++ /* Clear outstanding commands array. */
+ req->options &= ~BIT_0;
+ ret = qla25xx_init_req_que(base_vha, req);
+ if (ret != QLA_SUCCESS)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_isr.c linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_isr.c
+--- linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_isr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_isr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3018,9 +3018,9 @@ qla24xx_enable_msix(struct qla_hw_data *
+ "MSI-X: Failed to enable support "
+ "-- %d/%d\n Retry with %d vectors.\n",
+ ha->msix_count, ret, ret);
++ ha->msix_count = ret;
++ ha->max_rsp_queues = ha->msix_count - 1;
+ }
+- ha->msix_count = ret;
+- ha->max_rsp_queues = ha->msix_count - 1;
+ ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
+ ha->msix_count, GFP_KERNEL);
+ if (!ha->msix_entries) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_mid.c linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_mid.c
+--- linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_mid.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_mid.c 2016-04-12 12:09:26.000000000 -0400
+@@ -600,7 +600,7 @@ qla25xx_delete_queues(struct scsi_qla_ho
+ /* Delete request queues */
+ for (cnt = 1; cnt < ha->max_req_queues; cnt++) {
+ req = ha->req_q_map[cnt];
+- if (req) {
++ if (req && test_bit(cnt, ha->req_qid_map)) {
+ ret = qla25xx_delete_req_que(vha, req);
+ if (ret != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x00ea,
+@@ -614,7 +614,7 @@ qla25xx_delete_queues(struct scsi_qla_ho
+ /* Delete response queues */
+ for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) {
+ rsp = ha->rsp_q_map[cnt];
+- if (rsp) {
++ if (rsp && test_bit(cnt, ha->rsp_qid_map)) {
+ ret = qla25xx_delete_rsp_que(vha, rsp);
+ if (ret != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x00eb,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_os.c linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_os.c
+--- linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_os.c 2016-01-10 21:14:18.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_os.c 2016-04-12 21:30:38.000000000 -0400
+@@ -397,6 +397,9 @@ static void qla2x00_free_queues(struct q
+ int cnt;
+
+ for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
++ if (!test_bit(cnt, ha->req_qid_map))
++ continue;
++
+ req = ha->req_q_map[cnt];
+ qla2x00_free_req_que(ha, req);
+ }
+@@ -404,6 +407,9 @@ static void qla2x00_free_queues(struct q
+ ha->req_q_map = NULL;
+
+ for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
++ if (!test_bit(cnt, ha->rsp_qid_map))
++ continue;
++
+ rsp = ha->rsp_q_map[cnt];
+ qla2x00_free_rsp_que(ha, rsp);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_tmpl.c linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_tmpl.c
+--- linux-libre-4.4-gnu/drivers/scsi/qla2xxx/qla_tmpl.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/qla2xxx/qla_tmpl.c 2016-04-12 12:09:26.000000000 -0400
+@@ -395,6 +395,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_
+ if (ent->t263.queue_type == T263_QUEUE_TYPE_REQ) {
+ for (i = 0; i < vha->hw->max_req_queues; i++) {
+ struct req_que *req = vha->hw->req_q_map[i];
++
++ if (!test_bit(i, vha->hw->req_qid_map))
++ continue;
++
+ if (req || !buf) {
+ length = req ?
+ req->length : REQUEST_ENTRY_CNT_24XX;
+@@ -408,6 +412,10 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_
+ } else if (ent->t263.queue_type == T263_QUEUE_TYPE_RSP) {
+ for (i = 0; i < vha->hw->max_rsp_queues; i++) {
+ struct rsp_que *rsp = vha->hw->rsp_q_map[i];
++
++ if (!test_bit(i, vha->hw->rsp_qid_map))
++ continue;
++
+ if (rsp || !buf) {
+ length = rsp ?
+ rsp->length : RESPONSE_ENTRY_CNT_MQ;
+@@ -634,6 +642,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_
+ if (ent->t274.queue_type == T274_QUEUE_TYPE_REQ_SHAD) {
+ for (i = 0; i < vha->hw->max_req_queues; i++) {
+ struct req_que *req = vha->hw->req_q_map[i];
++
++ if (!test_bit(i, vha->hw->req_qid_map))
++ continue;
++
+ if (req || !buf) {
+ qla27xx_insert16(i, buf, len);
+ qla27xx_insert16(1, buf, len);
+@@ -645,6 +657,10 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_
+ } else if (ent->t274.queue_type == T274_QUEUE_TYPE_RSP_SHAD) {
+ for (i = 0; i < vha->hw->max_rsp_queues; i++) {
+ struct rsp_que *rsp = vha->hw->rsp_q_map[i];
++
++ if (!test_bit(i, vha->hw->rsp_qid_map))
++ continue;
++
+ if (rsp || !buf) {
+ qla27xx_insert16(i, buf, len);
+ qla27xx_insert16(1, buf, len);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/scsi_common.c linux-libre-4.4.7-gnu/drivers/scsi/scsi_common.c
+--- linux-libre-4.4-gnu/drivers/scsi/scsi_common.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/scsi_common.c 2016-04-12 12:09:26.000000000 -0400
+@@ -278,8 +278,16 @@ int scsi_set_sense_information(u8 *buf,
+ ucp[3] = 0;
+ put_unaligned_be64(info, &ucp[4]);
+ } else if ((buf[0] & 0x7f) == 0x70) {
+- buf[0] |= 0x80;
+- put_unaligned_be64(info, &buf[3]);
++ /*
++ * Only set the 'VALID' bit if we can represent the value
++ * correctly; otherwise just fill out the lower bytes and
++ * clear the 'VALID' flag.
++ */
++ if (info <= 0xffffffffUL)
++ buf[0] |= 0x80;
++ else
++ buf[0] &= 0x7f;
++ put_unaligned_be32((u32)info, &buf[3]);
+ }
+
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/scsi_devinfo.c linux-libre-4.4.7-gnu/drivers/scsi/scsi_devinfo.c
+--- linux-libre-4.4-gnu/drivers/scsi/scsi_devinfo.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/scsi_devinfo.c 2016-04-12 12:09:26.000000000 -0400
+@@ -205,6 +205,7 @@ static struct {
+ {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC},
+ {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+ {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
++ {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
+ {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
+ {"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+ {"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
+@@ -227,6 +228,7 @@ static struct {
+ {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
+ {"Promise", "", NULL, BLIST_SPARSELUN},
+ {"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
++ {"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024},
+ {"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
+ {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
+ {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/scsi_sysfs.c linux-libre-4.4.7-gnu/drivers/scsi/scsi_sysfs.c
+--- linux-libre-4.4-gnu/drivers/scsi/scsi_sysfs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/scsi_sysfs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1192,16 +1192,18 @@ static void __scsi_remove_target(struct
+ void scsi_remove_target(struct device *dev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev->parent);
+- struct scsi_target *starget;
++ struct scsi_target *starget, *last_target = NULL;
+ unsigned long flags;
+
+ restart:
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_for_each_entry(starget, &shost->__targets, siblings) {
+- if (starget->state == STARGET_DEL)
++ if (starget->state == STARGET_DEL ||
++ starget == last_target)
+ continue;
+ if (starget->dev.parent == dev || &starget->dev == dev) {
+ kref_get(&starget->reap_ref);
++ last_target = starget;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ __scsi_remove_target(starget);
+ scsi_target_reap(starget);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/sd.c linux-libre-4.4.7-gnu/drivers/scsi/sd.c
+--- linux-libre-4.4-gnu/drivers/scsi/sd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/sd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -648,7 +648,7 @@ static void sd_config_discard(struct scs
+ */
+ if (sdkp->lbprz) {
+ q->limits.discard_alignment = 0;
+- q->limits.discard_granularity = 1;
++ q->limits.discard_granularity = logical_block_size;
+ } else {
+ q->limits.discard_alignment = sdkp->unmap_alignment *
+ logical_block_size;
+@@ -2893,7 +2893,7 @@ static int sd_revalidate_disk(struct gen
+ sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS &&
+ sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE)
+ rw_max = q->limits.io_opt =
+- logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
++ sdkp->opt_xfer_blocks * sdp->sector_size;
+ else
+ rw_max = BLK_DEF_MAX_SECTORS;
+
+@@ -3268,8 +3268,8 @@ static int sd_suspend_common(struct devi
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ int ret = 0;
+
+- if (!sdkp)
+- return 0; /* this can happen */
++ if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
++ return 0;
+
+ if (sdkp->WCE && sdkp->media_present) {
+ sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+@@ -3308,6 +3308,9 @@ static int sd_resume(struct device *dev)
+ {
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
+
++ if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
++ return 0;
++
+ if (!sdkp->device->manage_start_stop)
+ return 0;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/sg.c linux-libre-4.4.7-gnu/drivers/scsi/sg.c
+--- linux-libre-4.4-gnu/drivers/scsi/sg.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/sg.c 2016-04-12 12:09:26.000000000 -0400
+@@ -652,7 +652,8 @@ sg_write(struct file *filp, const char _
+ else
+ hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV : SG_DXFER_NONE;
+ hp->dxfer_len = mxsize;
+- if (hp->dxfer_direction == SG_DXFER_TO_DEV)
++ if ((hp->dxfer_direction == SG_DXFER_TO_DEV) ||
++ (hp->dxfer_direction == SG_DXFER_TO_FROM_DEV))
+ hp->dxferp = (char __user *)buf + cmd_size;
+ else
+ hp->dxferp = NULL;
+@@ -1261,7 +1262,7 @@ sg_mmap(struct file *filp, struct vm_are
+ }
+
+ sfp->mmap_called = 1;
+- vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
++ vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_private_data = sfp;
+ vma->vm_ops = &sg_mmap_vm_ops;
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/sr.c linux-libre-4.4.7-gnu/drivers/scsi/sr.c
+--- linux-libre-4.4-gnu/drivers/scsi/sr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/sr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -144,6 +144,9 @@ static int sr_runtime_suspend(struct dev
+ {
+ struct scsi_cd *cd = dev_get_drvdata(dev);
+
++ if (!cd) /* E.g.: runtime suspend following sr_remove() */
++ return 0;
++
+ if (cd->media_present)
+ return -EBUSY;
+ else
+@@ -985,6 +988,7 @@ static int sr_remove(struct device *dev)
+ scsi_autopm_get_device(cd->device);
+
+ del_gendisk(cd->disk);
++ dev_set_drvdata(dev, NULL);
+
+ mutex_lock(&sr_ref_mutex);
+ kref_put(&cd->kref, sr_kref_release);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/scsi/storvsc_drv.c linux-libre-4.4.7-gnu/drivers/scsi/storvsc_drv.c
+--- linux-libre-4.4-gnu/drivers/scsi/storvsc_drv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/scsi/storvsc_drv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -889,8 +889,9 @@ static void storvsc_handle_error(struct
+ do_work = true;
+ process_err_fn = storvsc_remove_lun;
+ break;
+- case (SRB_STATUS_ABORTED | SRB_STATUS_AUTOSENSE_VALID):
+- if ((asc == 0x2a) && (ascq == 0x9)) {
++ case SRB_STATUS_ABORTED:
++ if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID &&
++ (asc == 0x2a) && (ascq == 0x9)) {
+ do_work = true;
+ process_err_fn = storvsc_device_scan;
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/sh/pm_runtime.c linux-libre-4.4.7-gnu/drivers/sh/pm_runtime.c
+--- linux-libre-4.4-gnu/drivers/sh/pm_runtime.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/sh/pm_runtime.c 2016-04-12 12:09:26.000000000 -0400
+@@ -34,7 +34,7 @@ static struct pm_clk_notifier_block plat
+
+ static int __init sh_pm_runtime_init(void)
+ {
+- if (IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
++ if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
+ if (!of_find_compatible_node(NULL, NULL,
+ "renesas,cpg-mstp-clocks"))
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/spi/spi-atmel.c linux-libre-4.4.7-gnu/drivers/spi/spi-atmel.c
+--- linux-libre-4.4-gnu/drivers/spi/spi-atmel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/spi/spi-atmel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1571,6 +1571,7 @@ static int atmel_spi_probe(struct platfo
+
+ as->use_cs_gpios = true;
+ if (atmel_spi_is_v2(as) &&
++ pdev->dev.of_node &&
+ !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) {
+ as->use_cs_gpios = false;
+ master->num_chipselect = 4;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/spi/spi-omap2-mcspi.c linux-libre-4.4.7-gnu/drivers/spi/spi-omap2-mcspi.c
+--- linux-libre-4.4-gnu/drivers/spi/spi-omap2-mcspi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/spi/spi-omap2-mcspi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1024,6 +1024,16 @@ static int omap2_mcspi_setup(struct spi_
+ spi->controller_state = cs;
+ /* Link this to context save list */
+ list_add_tail(&cs->node, &ctx->cs);
++
++ if (gpio_is_valid(spi->cs_gpio)) {
++ ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev));
++ if (ret) {
++ dev_err(&spi->dev, "failed to request gpio\n");
++ return ret;
++ }
++ gpio_direction_output(spi->cs_gpio,
++ !(spi->mode & SPI_CS_HIGH));
++ }
+ }
+
+ if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) {
+@@ -1032,15 +1042,6 @@ static int omap2_mcspi_setup(struct spi_
+ return ret;
+ }
+
+- if (gpio_is_valid(spi->cs_gpio)) {
+- ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev));
+- if (ret) {
+- dev_err(&spi->dev, "failed to request gpio\n");
+- return ret;
+- }
+- gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+- }
+-
+ ret = pm_runtime_get_sync(mcspi->dev);
+ if (ret < 0)
+ return ret;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/staging/android/ion/ion_test.c linux-libre-4.4.7-gnu/drivers/staging/android/ion/ion_test.c
+--- linux-libre-4.4-gnu/drivers/staging/android/ion/ion_test.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/staging/android/ion/ion_test.c 2016-04-12 12:09:26.000000000 -0400
+@@ -285,8 +285,8 @@ static int __init ion_test_init(void)
+ {
+ ion_test_pdev = platform_device_register_simple("ion-test",
+ -1, NULL, 0);
+- if (!ion_test_pdev)
+- return -ENODEV;
++ if (IS_ERR(ion_test_pdev))
++ return PTR_ERR(ion_test_pdev);
+
+ return platform_driver_probe(&ion_test_platform_driver, ion_test_probe);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/staging/comedi/drivers/ni_mio_common.c linux-libre-4.4.7-gnu/drivers/staging/comedi/drivers/ni_mio_common.c
+--- linux-libre-4.4-gnu/drivers/staging/comedi/drivers/ni_mio_common.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/staging/comedi/drivers/ni_mio_common.c 2016-04-12 12:09:26.000000000 -0400
+@@ -246,24 +246,24 @@ static void ni_writel(struct comedi_devi
+ {
+ if (dev->mmio)
+ writel(data, dev->mmio + reg);
+-
+- outl(data, dev->iobase + reg);
++ else
++ outl(data, dev->iobase + reg);
+ }
+
+ static void ni_writew(struct comedi_device *dev, uint16_t data, int reg)
+ {
+ if (dev->mmio)
+ writew(data, dev->mmio + reg);
+-
+- outw(data, dev->iobase + reg);
++ else
++ outw(data, dev->iobase + reg);
+ }
+
+ static void ni_writeb(struct comedi_device *dev, uint8_t data, int reg)
+ {
+ if (dev->mmio)
+ writeb(data, dev->mmio + reg);
+-
+- outb(data, dev->iobase + reg);
++ else
++ outb(data, dev->iobase + reg);
+ }
+
+ static uint32_t ni_readl(struct comedi_device *dev, int reg)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c linux-libre-4.4.7-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c
+--- linux-libre-4.4-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/staging/comedi/drivers/ni_tiocmd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -92,7 +92,7 @@ static int ni_tio_input_inttrig(struct c
+ unsigned long flags;
+ int ret = 0;
+
+- if (trig_num != cmd->start_src)
++ if (trig_num != cmd->start_arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&counter->lock, flags);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/staging/panel/panel.c linux-libre-4.4.7-gnu/drivers/staging/panel/panel.c
+--- linux-libre-4.4-gnu/drivers/staging/panel/panel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/staging/panel/panel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -825,8 +825,7 @@ static void lcd_write_cmd_s(int cmd)
+ lcd_send_serial(0x1F); /* R/W=W, RS=0 */
+ lcd_send_serial(cmd & 0x0F);
+ lcd_send_serial((cmd >> 4) & 0x0F);
+- /* the shortest command takes at least 40 us */
+- usleep_range(40, 100);
++ udelay(40); /* the shortest command takes at least 40 us */
+ spin_unlock_irq(&pprt_lock);
+ }
+
+@@ -837,8 +836,7 @@ static void lcd_write_data_s(int data)
+ lcd_send_serial(0x5F); /* R/W=W, RS=1 */
+ lcd_send_serial(data & 0x0F);
+ lcd_send_serial((data >> 4) & 0x0F);
+- /* the shortest data takes at least 40 us */
+- usleep_range(40, 100);
++ udelay(40); /* the shortest data takes at least 40 us */
+ spin_unlock_irq(&pprt_lock);
+ }
+
+@@ -848,20 +846,19 @@ static void lcd_write_cmd_p8(int cmd)
+ spin_lock_irq(&pprt_lock);
+ /* present the data to the data port */
+ w_dtr(pprt, cmd);
+- /* maintain the data during 20 us before the strobe */
+- usleep_range(20, 100);
++ udelay(20); /* maintain the data during 20 us before the strobe */
+
+ bits.e = BIT_SET;
+ bits.rs = BIT_CLR;
+ bits.rw = BIT_CLR;
+ set_ctrl_bits();
+
+- usleep_range(40, 100); /* maintain the strobe during 40 us */
++ udelay(40); /* maintain the strobe during 40 us */
+
+ bits.e = BIT_CLR;
+ set_ctrl_bits();
+
+- usleep_range(120, 500); /* the shortest command takes at least 120 us */
++ udelay(120); /* the shortest command takes at least 120 us */
+ spin_unlock_irq(&pprt_lock);
+ }
+
+@@ -871,20 +868,19 @@ static void lcd_write_data_p8(int data)
+ spin_lock_irq(&pprt_lock);
+ /* present the data to the data port */
+ w_dtr(pprt, data);
+- /* maintain the data during 20 us before the strobe */
+- usleep_range(20, 100);
++ udelay(20); /* maintain the data during 20 us before the strobe */
+
+ bits.e = BIT_SET;
+ bits.rs = BIT_SET;
+ bits.rw = BIT_CLR;
+ set_ctrl_bits();
+
+- usleep_range(40, 100); /* maintain the strobe during 40 us */
++ udelay(40); /* maintain the strobe during 40 us */
+
+ bits.e = BIT_CLR;
+ set_ctrl_bits();
+
+- usleep_range(45, 100); /* the shortest data takes at least 45 us */
++ udelay(45); /* the shortest data takes at least 45 us */
+ spin_unlock_irq(&pprt_lock);
+ }
+
+@@ -894,7 +890,7 @@ static void lcd_write_cmd_tilcd(int cmd)
+ spin_lock_irq(&pprt_lock);
+ /* present the data to the control port */
+ w_ctr(pprt, cmd);
+- usleep_range(60, 120);
++ udelay(60);
+ spin_unlock_irq(&pprt_lock);
+ }
+
+@@ -904,7 +900,7 @@ static void lcd_write_data_tilcd(int dat
+ spin_lock_irq(&pprt_lock);
+ /* present the data to the data port */
+ w_dtr(pprt, data);
+- usleep_range(60, 120);
++ udelay(60);
+ spin_unlock_irq(&pprt_lock);
+ }
+
+@@ -947,7 +943,7 @@ static void lcd_clear_fast_s(void)
+ lcd_send_serial(0x5F); /* R/W=W, RS=1 */
+ lcd_send_serial(' ' & 0x0F);
+ lcd_send_serial((' ' >> 4) & 0x0F);
+- usleep_range(40, 100); /* the shortest data takes at least 40 us */
++ udelay(40); /* the shortest data takes at least 40 us */
+ }
+ spin_unlock_irq(&pprt_lock);
+
+@@ -971,7 +967,7 @@ static void lcd_clear_fast_p8(void)
+ w_dtr(pprt, ' ');
+
+ /* maintain the data during 20 us before the strobe */
+- usleep_range(20, 100);
++ udelay(20);
+
+ bits.e = BIT_SET;
+ bits.rs = BIT_SET;
+@@ -979,13 +975,13 @@ static void lcd_clear_fast_p8(void)
+ set_ctrl_bits();
+
+ /* maintain the strobe during 40 us */
+- usleep_range(40, 100);
++ udelay(40);
+
+ bits.e = BIT_CLR;
+ set_ctrl_bits();
+
+ /* the shortest data takes at least 45 us */
+- usleep_range(45, 100);
++ udelay(45);
+ }
+ spin_unlock_irq(&pprt_lock);
+
+@@ -1007,7 +1003,7 @@ static void lcd_clear_fast_tilcd(void)
+ for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) {
+ /* present the data to the data port */
+ w_dtr(pprt, ' ');
+- usleep_range(60, 120);
++ udelay(60);
+ }
+
+ spin_unlock_irq(&pprt_lock);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/staging/speakup/selection.c linux-libre-4.4.7-gnu/drivers/staging/speakup/selection.c
+--- linux-libre-4.4-gnu/drivers/staging/speakup/selection.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/staging/speakup/selection.c 2016-04-12 12:09:26.000000000 -0400
+@@ -142,7 +142,9 @@ static void __speakup_paste_selection(st
+ struct tty_ldisc *ld;
+ DECLARE_WAITQUEUE(wait, current);
+
+- ld = tty_ldisc_ref_wait(tty);
++ ld = tty_ldisc_ref(tty);
++ if (!ld)
++ goto tty_unref;
+ tty_buffer_lock_exclusive(&vc->port);
+
+ add_wait_queue(&vc->paste_wait, &wait);
+@@ -162,6 +164,7 @@ static void __speakup_paste_selection(st
+
+ tty_buffer_unlock_exclusive(&vc->port);
+ tty_ldisc_deref(ld);
++tty_unref:
+ tty_kref_put(tty);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/staging/speakup/serialio.c linux-libre-4.4.7-gnu/drivers/staging/speakup/serialio.c
+--- linux-libre-4.4-gnu/drivers/staging/speakup/serialio.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/staging/speakup/serialio.c 2016-04-12 12:09:26.000000000 -0400
+@@ -6,6 +6,11 @@
+ #include "spk_priv.h"
+ #include "serialio.h"
+
++#include <linux/serial_core.h>
++/* WARNING: Do not change this to <linux/serial.h> without testing that
++ * SERIAL_PORT_DFNS does get defined to the appropriate value. */
++#include <asm/serial.h>
++
+ #ifndef SERIAL_PORT_DFNS
+ #define SERIAL_PORT_DFNS
+ #endif
+@@ -23,9 +28,15 @@ const struct old_serial_port *spk_serial
+ int baud = 9600, quot = 0;
+ unsigned int cval = 0;
+ int cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8;
+- const struct old_serial_port *ser = rs_table + index;
++ const struct old_serial_port *ser;
+ int err;
+
++ if (index >= ARRAY_SIZE(rs_table)) {
++ pr_info("no port info for ttyS%d\n", index);
++ return NULL;
++ }
++ ser = rs_table + index;
++
+ /* Divisor, bytesize and parity */
+ quot = ser->baud_base / baud;
+ cval = cflag & (CSIZE | CSTOPB);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/target/iscsi/iscsi_target_configfs.c linux-libre-4.4.7-gnu/drivers/target/iscsi/iscsi_target_configfs.c
+--- linux-libre-4.4-gnu/drivers/target/iscsi/iscsi_target_configfs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/target/iscsi/iscsi_target_configfs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1593,7 +1593,8 @@ static int lio_tpg_check_prot_fabric_onl
+ }
+
+ /*
+- * Called with spin_lock_bh(struct se_portal_group->session_lock) held..
++ * Called with spin_lock_irq(struct se_portal_group->session_lock) held
++ * or not held.
+ *
+ * Also, this function calls iscsit_inc_session_usage_count() on the
+ * struct iscsi_session in question.
+@@ -1601,19 +1602,32 @@ static int lio_tpg_check_prot_fabric_onl
+ static int lio_tpg_shutdown_session(struct se_session *se_sess)
+ {
+ struct iscsi_session *sess = se_sess->fabric_sess_ptr;
++ struct se_portal_group *se_tpg = se_sess->se_tpg;
++ bool local_lock = false;
++
++ if (!spin_is_locked(&se_tpg->session_lock)) {
++ spin_lock_irq(&se_tpg->session_lock);
++ local_lock = true;
++ }
+
+ spin_lock(&sess->conn_lock);
+ if (atomic_read(&sess->session_fall_back_to_erl0) ||
+ atomic_read(&sess->session_logout) ||
+ (sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
+ spin_unlock(&sess->conn_lock);
++ if (local_lock)
++ spin_unlock_irq(&sess->conn_lock);
+ return 0;
+ }
+ atomic_set(&sess->session_reinstatement, 1);
+ spin_unlock(&sess->conn_lock);
+
+ iscsit_stop_time2retain_timer(sess);
++ spin_unlock_irq(&se_tpg->session_lock);
++
+ iscsit_stop_session(sess, 1, 1);
++ if (!local_lock)
++ spin_lock_irq(&se_tpg->session_lock);
+
+ return 1;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/target/target_core_device.c linux-libre-4.4.7-gnu/drivers/target/target_core_device.c
+--- linux-libre-4.4-gnu/drivers/target/target_core_device.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/target/target_core_device.c 2016-04-12 12:09:26.000000000 -0400
+@@ -826,6 +826,49 @@ struct se_device *target_alloc_device(st
+ return dev;
+ }
+
++/*
++ * Check if the underlying struct block_device request_queue supports
++ * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
++ * in ATA and we need to set TPE=1
++ */
++bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
++ struct request_queue *q, int block_size)
++{
++ if (!blk_queue_discard(q))
++ return false;
++
++ attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) /
++ block_size;
++ /*
++ * Currently hardcoded to 1 in Linux/SCSI code..
++ */
++ attrib->max_unmap_block_desc_count = 1;
++ attrib->unmap_granularity = q->limits.discard_granularity / block_size;
++ attrib->unmap_granularity_alignment = q->limits.discard_alignment /
++ block_size;
++ return true;
++}
++EXPORT_SYMBOL(target_configure_unmap_from_queue);
++
++/*
++ * Convert from blocksize advertised to the initiator to the 512 byte
++ * units unconditionally used by the Linux block layer.
++ */
++sector_t target_to_linux_sector(struct se_device *dev, sector_t lb)
++{
++ switch (dev->dev_attrib.block_size) {
++ case 4096:
++ return lb << 3;
++ case 2048:
++ return lb << 2;
++ case 1024:
++ return lb << 1;
++ default:
++ return lb;
++ }
++}
++EXPORT_SYMBOL(target_to_linux_sector);
++
+ int target_configure_device(struct se_device *dev)
+ {
+ struct se_hba *hba = dev->se_hba;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/target/target_core_file.c linux-libre-4.4.7-gnu/drivers/target/target_core_file.c
+--- linux-libre-4.4-gnu/drivers/target/target_core_file.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/target/target_core_file.c 2016-04-12 12:09:26.000000000 -0400
+@@ -160,25 +160,11 @@ static int fd_configure_device(struct se
+ " block_device blocks: %llu logical_block_size: %d\n",
+ dev_size, div_u64(dev_size, fd_dev->fd_block_size),
+ fd_dev->fd_block_size);
+- /*
+- * Check if the underlying struct block_device request_queue supports
+- * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
+- * in ATA and we need to set TPE=1
+- */
+- if (blk_queue_discard(q)) {
+- dev->dev_attrib.max_unmap_lba_count =
+- q->limits.max_discard_sectors;
+- /*
+- * Currently hardcoded to 1 in Linux/SCSI code..
+- */
+- dev->dev_attrib.max_unmap_block_desc_count = 1;
+- dev->dev_attrib.unmap_granularity =
+- q->limits.discard_granularity >> 9;
+- dev->dev_attrib.unmap_granularity_alignment =
+- q->limits.discard_alignment;
++
++ if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
++ fd_dev->fd_block_size))
+ pr_debug("IFILE: BLOCK Discard support available,"
+- " disabled by default\n");
+- }
++ " disabled by default\n");
+ /*
+ * Enable write same emulation for IBLOCK and use 0xFFFF as
+ * the smaller WRITE_SAME(10) only has a two-byte block count.
+@@ -490,9 +476,12 @@ fd_execute_unmap(struct se_cmd *cmd, sec
+ if (S_ISBLK(inode->i_mode)) {
+ /* The backend is block device, use discard */
+ struct block_device *bdev = inode->i_bdev;
++ struct se_device *dev = cmd->se_dev;
+
+- ret = blkdev_issue_discard(bdev, lba,
+- nolb, GFP_KERNEL, 0);
++ ret = blkdev_issue_discard(bdev,
++ target_to_linux_sector(dev, lba),
++ target_to_linux_sector(dev, nolb),
++ GFP_KERNEL, 0);
+ if (ret < 0) {
+ pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n",
+ ret);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/target/target_core_iblock.c linux-libre-4.4.7-gnu/drivers/target/target_core_iblock.c
+--- linux-libre-4.4-gnu/drivers/target/target_core_iblock.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/target/target_core_iblock.c 2016-04-12 12:09:26.000000000 -0400
+@@ -121,27 +121,11 @@ static int iblock_configure_device(struc
+ dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
+ dev->dev_attrib.hw_queue_depth = q->nr_requests;
+
+- /*
+- * Check if the underlying struct block_device request_queue supports
+- * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM
+- * in ATA and we need to set TPE=1
+- */
+- if (blk_queue_discard(q)) {
+- dev->dev_attrib.max_unmap_lba_count =
+- q->limits.max_discard_sectors;
+-
+- /*
+- * Currently hardcoded to 1 in Linux/SCSI code..
+- */
+- dev->dev_attrib.max_unmap_block_desc_count = 1;
+- dev->dev_attrib.unmap_granularity =
+- q->limits.discard_granularity >> 9;
+- dev->dev_attrib.unmap_granularity_alignment =
+- q->limits.discard_alignment;
+-
++ if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
++ dev->dev_attrib.hw_block_size))
+ pr_debug("IBLOCK: BLOCK Discard support available,"
+- " disabled by default\n");
+- }
++ " disabled by default\n");
++
+ /*
+ * Enable write same emulation for IBLOCK and use 0xFFFF as
+ * the smaller WRITE_SAME(10) only has a two-byte block count.
+@@ -413,9 +397,13 @@ static sense_reason_t
+ iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
+ {
+ struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
++ struct se_device *dev = cmd->se_dev;
+ int ret;
+
+- ret = blkdev_issue_discard(bdev, lba, nolb, GFP_KERNEL, 0);
++ ret = blkdev_issue_discard(bdev,
++ target_to_linux_sector(dev, lba),
++ target_to_linux_sector(dev, nolb),
++ GFP_KERNEL, 0);
+ if (ret < 0) {
+ pr_err("blkdev_issue_discard() failed: %d\n", ret);
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+@@ -431,8 +419,10 @@ iblock_execute_write_same(struct se_cmd
+ struct scatterlist *sg;
+ struct bio *bio;
+ struct bio_list list;
+- sector_t block_lba = cmd->t_task_lba;
+- sector_t sectors = sbc_get_write_same_sectors(cmd);
++ struct se_device *dev = cmd->se_dev;
++ sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba);
++ sector_t sectors = target_to_linux_sector(dev,
++ sbc_get_write_same_sectors(cmd));
+
+ if (cmd->prot_op) {
+ pr_err("WRITE_SAME: Protection information with IBLOCK"
+@@ -646,12 +636,12 @@ iblock_execute_rw(struct se_cmd *cmd, st
+ enum dma_data_direction data_direction)
+ {
+ struct se_device *dev = cmd->se_dev;
++ sector_t block_lba = target_to_linux_sector(dev, cmd->t_task_lba);
+ struct iblock_req *ibr;
+ struct bio *bio, *bio_start;
+ struct bio_list list;
+ struct scatterlist *sg;
+ u32 sg_num = sgl_nents;
+- sector_t block_lba;
+ unsigned bio_cnt;
+ int rw = 0;
+ int i;
+@@ -677,24 +667,6 @@ iblock_execute_rw(struct se_cmd *cmd, st
+ rw = READ;
+ }
+
+- /*
+- * Convert the blocksize advertised to the initiator to the 512 byte
+- * units unconditionally used by the Linux block layer.
+- */
+- if (dev->dev_attrib.block_size == 4096)
+- block_lba = (cmd->t_task_lba << 3);
+- else if (dev->dev_attrib.block_size == 2048)
+- block_lba = (cmd->t_task_lba << 2);
+- else if (dev->dev_attrib.block_size == 1024)
+- block_lba = (cmd->t_task_lba << 1);
+- else if (dev->dev_attrib.block_size == 512)
+- block_lba = cmd->t_task_lba;
+- else {
+- pr_err("Unsupported SCSI -> BLOCK LBA conversion:"
+- " %u\n", dev->dev_attrib.block_size);
+- return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+- }
+-
+ ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
+ if (!ibr)
+ goto fail;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/target/target_core_tmr.c linux-libre-4.4.7-gnu/drivers/target/target_core_tmr.c
+--- linux-libre-4.4-gnu/drivers/target/target_core_tmr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/target/target_core_tmr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -68,23 +68,25 @@ void core_tmr_release_req(struct se_tmr_
+
+ if (dev) {
+ spin_lock_irqsave(&dev->se_tmr_lock, flags);
+- list_del(&tmr->tmr_list);
++ list_del_init(&tmr->tmr_list);
+ spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
+ }
+
+ kfree(tmr);
+ }
+
+-static void core_tmr_handle_tas_abort(
+- struct se_node_acl *tmr_nacl,
+- struct se_cmd *cmd,
+- int tas)
++static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
+ {
+- bool remove = true;
++ unsigned long flags;
++ bool remove = true, send_tas;
+ /*
+ * TASK ABORTED status (TAS) bit support
+ */
+- if ((tmr_nacl && (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) {
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ send_tas = (cmd->transport_state & CMD_T_TAS);
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++
++ if (send_tas) {
+ remove = false;
+ transport_send_task_abort(cmd);
+ }
+@@ -107,6 +109,46 @@ static int target_check_cdb_and_preempt(
+ return 1;
+ }
+
++static bool __target_check_io_state(struct se_cmd *se_cmd,
++ struct se_session *tmr_sess, int tas)
++{
++ struct se_session *sess = se_cmd->se_sess;
++
++ assert_spin_locked(&sess->sess_cmd_lock);
++ WARN_ON_ONCE(!irqs_disabled());
++ /*
++ * If command already reached CMD_T_COMPLETE state within
++ * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown,
++ * this se_cmd has been passed to fabric driver and will
++ * not be aborted.
++ *
++ * Otherwise, obtain a local se_cmd->cmd_kref now for TMR
++ * ABORT_TASK + LUN_RESET for CMD_T_ABORTED processing as
++ * long as se_cmd->cmd_kref is still active unless zero.
++ */
++ spin_lock(&se_cmd->t_state_lock);
++ if (se_cmd->transport_state & (CMD_T_COMPLETE | CMD_T_FABRIC_STOP)) {
++ pr_debug("Attempted to abort io tag: %llu already complete or"
++ " fabric stop, skipping\n", se_cmd->tag);
++ spin_unlock(&se_cmd->t_state_lock);
++ return false;
++ }
++ if (sess->sess_tearing_down || se_cmd->cmd_wait_set) {
++ pr_debug("Attempted to abort io tag: %llu already shutdown,"
++ " skipping\n", se_cmd->tag);
++ spin_unlock(&se_cmd->t_state_lock);
++ return false;
++ }
++ se_cmd->transport_state |= CMD_T_ABORTED;
++
++ if ((tmr_sess != se_cmd->se_sess) && tas)
++ se_cmd->transport_state |= CMD_T_TAS;
++
++ spin_unlock(&se_cmd->t_state_lock);
++
++ return kref_get_unless_zero(&se_cmd->cmd_kref);
++}
++
+ void core_tmr_abort_task(
+ struct se_device *dev,
+ struct se_tmr_req *tmr,
+@@ -130,34 +172,21 @@ void core_tmr_abort_task(
+ if (tmr->ref_task_tag != ref_tag)
+ continue;
+
+- if (!kref_get_unless_zero(&se_cmd->cmd_kref))
+- continue;
+-
+ printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
+ se_cmd->se_tfo->get_fabric_name(), ref_tag);
+
+- spin_lock(&se_cmd->t_state_lock);
+- if (se_cmd->transport_state & CMD_T_COMPLETE) {
+- printk("ABORT_TASK: ref_tag: %llu already complete,"
+- " skipping\n", ref_tag);
+- spin_unlock(&se_cmd->t_state_lock);
++ if (!__target_check_io_state(se_cmd, se_sess, 0)) {
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+-
+- target_put_sess_cmd(se_cmd);
+-
+ goto out;
+ }
+- se_cmd->transport_state |= CMD_T_ABORTED;
+- spin_unlock(&se_cmd->t_state_lock);
+-
+ list_del_init(&se_cmd->se_cmd_list);
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+
+ cancel_work_sync(&se_cmd->work);
+ transport_wait_for_tasks(se_cmd);
+
+- target_put_sess_cmd(se_cmd);
+ transport_cmd_finish_abort(se_cmd, true);
++ target_put_sess_cmd(se_cmd);
+
+ printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
+ " ref_tag: %llu\n", ref_tag);
+@@ -178,9 +207,11 @@ static void core_tmr_drain_tmr_list(
+ struct list_head *preempt_and_abort_list)
+ {
+ LIST_HEAD(drain_tmr_list);
++ struct se_session *sess;
+ struct se_tmr_req *tmr_p, *tmr_pp;
+ struct se_cmd *cmd;
+ unsigned long flags;
++ bool rc;
+ /*
+ * Release all pending and outgoing TMRs aside from the received
+ * LUN_RESET tmr..
+@@ -206,17 +237,39 @@ static void core_tmr_drain_tmr_list(
+ if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
+ continue;
+
++ sess = cmd->se_sess;
++ if (WARN_ON_ONCE(!sess))
++ continue;
++
++ spin_lock(&sess->sess_cmd_lock);
+ spin_lock(&cmd->t_state_lock);
+- if (!(cmd->transport_state & CMD_T_ACTIVE)) {
++ if (!(cmd->transport_state & CMD_T_ACTIVE) ||
++ (cmd->transport_state & CMD_T_FABRIC_STOP)) {
+ spin_unlock(&cmd->t_state_lock);
++ spin_unlock(&sess->sess_cmd_lock);
+ continue;
+ }
+ if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) {
+ spin_unlock(&cmd->t_state_lock);
++ spin_unlock(&sess->sess_cmd_lock);
+ continue;
+ }
++ if (sess->sess_tearing_down || cmd->cmd_wait_set) {
++ spin_unlock(&cmd->t_state_lock);
++ spin_unlock(&sess->sess_cmd_lock);
++ continue;
++ }
++ cmd->transport_state |= CMD_T_ABORTED;
+ spin_unlock(&cmd->t_state_lock);
+
++ rc = kref_get_unless_zero(&cmd->cmd_kref);
++ if (!rc) {
++ printk("LUN_RESET TMR: non-zero kref_get_unless_zero\n");
++ spin_unlock(&sess->sess_cmd_lock);
++ continue;
++ }
++ spin_unlock(&sess->sess_cmd_lock);
++
+ list_move_tail(&tmr_p->tmr_list, &drain_tmr_list);
+ }
+ spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
+@@ -230,20 +283,26 @@ static void core_tmr_drain_tmr_list(
+ (preempt_and_abort_list) ? "Preempt" : "", tmr_p,
+ tmr_p->function, tmr_p->response, cmd->t_state);
+
++ cancel_work_sync(&cmd->work);
++ transport_wait_for_tasks(cmd);
++
+ transport_cmd_finish_abort(cmd, 1);
++ target_put_sess_cmd(cmd);
+ }
+ }
+
+ static void core_tmr_drain_state_list(
+ struct se_device *dev,
+ struct se_cmd *prout_cmd,
+- struct se_node_acl *tmr_nacl,
++ struct se_session *tmr_sess,
+ int tas,
+ struct list_head *preempt_and_abort_list)
+ {
+ LIST_HEAD(drain_task_list);
++ struct se_session *sess;
+ struct se_cmd *cmd, *next;
+ unsigned long flags;
++ int rc;
+
+ /*
+ * Complete outstanding commands with TASK_ABORTED SAM status.
+@@ -282,6 +341,16 @@ static void core_tmr_drain_state_list(
+ if (prout_cmd == cmd)
+ continue;
+
++ sess = cmd->se_sess;
++ if (WARN_ON_ONCE(!sess))
++ continue;
++
++ spin_lock(&sess->sess_cmd_lock);
++ rc = __target_check_io_state(cmd, tmr_sess, tas);
++ spin_unlock(&sess->sess_cmd_lock);
++ if (!rc)
++ continue;
++
+ list_move_tail(&cmd->state_list, &drain_task_list);
+ cmd->state_active = false;
+ }
+@@ -289,7 +358,7 @@ static void core_tmr_drain_state_list(
+
+ while (!list_empty(&drain_task_list)) {
+ cmd = list_entry(drain_task_list.next, struct se_cmd, state_list);
+- list_del(&cmd->state_list);
++ list_del_init(&cmd->state_list);
+
+ pr_debug("LUN_RESET: %s cmd: %p"
+ " ITT/CmdSN: 0x%08llx/0x%08x, i_state: %d, t_state: %d"
+@@ -313,16 +382,11 @@ static void core_tmr_drain_state_list(
+ * loop above, but we do it down here given that
+ * cancel_work_sync may block.
+ */
+- if (cmd->t_state == TRANSPORT_COMPLETE)
+- cancel_work_sync(&cmd->work);
+-
+- spin_lock_irqsave(&cmd->t_state_lock, flags);
+- target_stop_cmd(cmd, &flags);
+-
+- cmd->transport_state |= CMD_T_ABORTED;
+- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ cancel_work_sync(&cmd->work);
++ transport_wait_for_tasks(cmd);
+
+- core_tmr_handle_tas_abort(tmr_nacl, cmd, tas);
++ core_tmr_handle_tas_abort(cmd, tas);
++ target_put_sess_cmd(cmd);
+ }
+ }
+
+@@ -334,6 +398,7 @@ int core_tmr_lun_reset(
+ {
+ struct se_node_acl *tmr_nacl = NULL;
+ struct se_portal_group *tmr_tpg = NULL;
++ struct se_session *tmr_sess = NULL;
+ int tas;
+ /*
+ * TASK_ABORTED status bit, this is configurable via ConfigFS
+@@ -352,8 +417,9 @@ int core_tmr_lun_reset(
+ * or struct se_device passthrough..
+ */
+ if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) {
+- tmr_nacl = tmr->task_cmd->se_sess->se_node_acl;
+- tmr_tpg = tmr->task_cmd->se_sess->se_tpg;
++ tmr_sess = tmr->task_cmd->se_sess;
++ tmr_nacl = tmr_sess->se_node_acl;
++ tmr_tpg = tmr_sess->se_tpg;
+ if (tmr_nacl && tmr_tpg) {
+ pr_debug("LUN_RESET: TMR caller fabric: %s"
+ " initiator port %s\n",
+@@ -366,7 +432,7 @@ int core_tmr_lun_reset(
+ dev->transport->name, tas);
+
+ core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
+- core_tmr_drain_state_list(dev, prout_cmd, tmr_nacl, tas,
++ core_tmr_drain_state_list(dev, prout_cmd, tmr_sess, tas,
+ preempt_and_abort_list);
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/target/target_core_transport.c linux-libre-4.4.7-gnu/drivers/target/target_core_transport.c
+--- linux-libre-4.4-gnu/drivers/target/target_core_transport.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/target/target_core_transport.c 2016-04-12 12:09:26.000000000 -0400
+@@ -528,9 +528,6 @@ void transport_deregister_session(struct
+ }
+ EXPORT_SYMBOL(transport_deregister_session);
+
+-/*
+- * Called with cmd->t_state_lock held.
+- */
+ static void target_remove_from_state_list(struct se_cmd *cmd)
+ {
+ struct se_device *dev = cmd->se_dev;
+@@ -555,10 +552,6 @@ static int transport_cmd_check_stop(stru
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&cmd->t_state_lock, flags);
+- if (write_pending)
+- cmd->t_state = TRANSPORT_WRITE_PENDING;
+-
+ if (remove_from_lists) {
+ target_remove_from_state_list(cmd);
+
+@@ -568,6 +561,10 @@ static int transport_cmd_check_stop(stru
+ cmd->se_lun = NULL;
+ }
+
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ if (write_pending)
++ cmd->t_state = TRANSPORT_WRITE_PENDING;
++
+ /*
+ * Determine if frontend context caller is requesting the stopping of
+ * this command for frontend exceptions.
+@@ -621,6 +618,8 @@ static void transport_lun_remove_cmd(str
+
+ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
+ {
++ bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF);
++
+ if (cmd->se_cmd_flags & SCF_SE_LUN_CMD)
+ transport_lun_remove_cmd(cmd);
+ /*
+@@ -632,7 +631,7 @@ void transport_cmd_finish_abort(struct s
+
+ if (transport_cmd_check_stop_to_fabric(cmd))
+ return;
+- if (remove)
++ if (remove && ack_kref)
+ transport_put_cmd(cmd);
+ }
+
+@@ -700,7 +699,7 @@ void target_complete_cmd(struct se_cmd *
+ * Check for case where an explicit ABORT_TASK has been received
+ * and transport_wait_for_tasks() will be waiting for completion..
+ */
+- if (cmd->transport_state & CMD_T_ABORTED &&
++ if (cmd->transport_state & CMD_T_ABORTED ||
+ cmd->transport_state & CMD_T_STOP) {
+ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+ complete_all(&cmd->t_transport_stop_comp);
+@@ -1850,19 +1849,21 @@ static bool target_handle_task_attr(stru
+ return true;
+ }
+
++static int __transport_check_aborted_status(struct se_cmd *, int);
++
+ void target_execute_cmd(struct se_cmd *cmd)
+ {
+ /*
+- * If the received CDB has aleady been aborted stop processing it here.
+- */
+- if (transport_check_aborted_status(cmd, 1))
+- return;
+-
+- /*
+ * Determine if frontend context caller is requesting the stopping of
+ * this command for frontend exceptions.
++ *
++ * If the received CDB has aleady been aborted stop processing it here.
+ */
+ spin_lock_irq(&cmd->t_state_lock);
++ if (__transport_check_aborted_status(cmd, 1)) {
++ spin_unlock_irq(&cmd->t_state_lock);
++ return;
++ }
+ if (cmd->transport_state & CMD_T_STOP) {
+ pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n",
+ __func__, __LINE__, cmd->tag);
+@@ -2213,20 +2214,14 @@ static inline void transport_free_pages(
+ }
+
+ /**
+- * transport_release_cmd - free a command
+- * @cmd: command to free
++ * transport_put_cmd - release a reference to a command
++ * @cmd: command to release
+ *
+- * This routine unconditionally frees a command, and reference counting
+- * or list removal must be done in the caller.
++ * This routine releases our reference to the command and frees it if possible.
+ */
+-static int transport_release_cmd(struct se_cmd *cmd)
++static int transport_put_cmd(struct se_cmd *cmd)
+ {
+ BUG_ON(!cmd->se_tfo);
+-
+- if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
+- core_tmr_release_req(cmd->se_tmr_req);
+- if (cmd->t_task_cdb != cmd->__t_task_cdb)
+- kfree(cmd->t_task_cdb);
+ /*
+ * If this cmd has been setup with target_get_sess_cmd(), drop
+ * the kref and call ->release_cmd() in kref callback.
+@@ -2234,18 +2229,6 @@ static int transport_release_cmd(struct
+ return target_put_sess_cmd(cmd);
+ }
+
+-/**
+- * transport_put_cmd - release a reference to a command
+- * @cmd: command to release
+- *
+- * This routine releases our reference to the command and frees it if possible.
+- */
+-static int transport_put_cmd(struct se_cmd *cmd)
+-{
+- transport_free_pages(cmd);
+- return transport_release_cmd(cmd);
+-}
+-
+ void *transport_kmap_data_sg(struct se_cmd *cmd)
+ {
+ struct scatterlist *sg = cmd->t_data_sg;
+@@ -2441,34 +2424,58 @@ static void transport_write_pending_qf(s
+ }
+ }
+
+-int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
++static bool
++__transport_wait_for_tasks(struct se_cmd *, bool, bool *, bool *,
++ unsigned long *flags);
++
++static void target_wait_free_cmd(struct se_cmd *cmd, bool *aborted, bool *tas)
+ {
+ unsigned long flags;
++
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ __transport_wait_for_tasks(cmd, true, aborted, tas, &flags);
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++}
++
++int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
++{
+ int ret = 0;
++ bool aborted = false, tas = false;
+
+ if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
+ if (wait_for_tasks && (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
+- transport_wait_for_tasks(cmd);
++ target_wait_free_cmd(cmd, &aborted, &tas);
+
+- ret = transport_release_cmd(cmd);
++ if (!aborted || tas)
++ ret = transport_put_cmd(cmd);
+ } else {
+ if (wait_for_tasks)
+- transport_wait_for_tasks(cmd);
++ target_wait_free_cmd(cmd, &aborted, &tas);
+ /*
+ * Handle WRITE failure case where transport_generic_new_cmd()
+ * has already added se_cmd to state_list, but fabric has
+ * failed command before I/O submission.
+ */
+- if (cmd->state_active) {
+- spin_lock_irqsave(&cmd->t_state_lock, flags);
++ if (cmd->state_active)
+ target_remove_from_state_list(cmd);
+- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+- }
+
+ if (cmd->se_lun)
+ transport_lun_remove_cmd(cmd);
+
+- ret = transport_put_cmd(cmd);
++ if (!aborted || tas)
++ ret = transport_put_cmd(cmd);
++ }
++ /*
++ * If the task has been internally aborted due to TMR ABORT_TASK
++ * or LUN_RESET, target_core_tmr.c is responsible for performing
++ * the remaining calls to target_put_sess_cmd(), and not the
++ * callers of this function.
++ */
++ if (aborted) {
++ pr_debug("Detected CMD_T_ABORTED for ITT: %llu\n", cmd->tag);
++ wait_for_completion(&cmd->cmd_wait_comp);
++ cmd->se_tfo->release_cmd(cmd);
++ ret = 1;
+ }
+ return ret;
+ }
+@@ -2508,26 +2515,46 @@ out:
+ }
+ EXPORT_SYMBOL(target_get_sess_cmd);
+
++static void target_free_cmd_mem(struct se_cmd *cmd)
++{
++ transport_free_pages(cmd);
++
++ if (cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
++ core_tmr_release_req(cmd->se_tmr_req);
++ if (cmd->t_task_cdb != cmd->__t_task_cdb)
++ kfree(cmd->t_task_cdb);
++}
++
+ static void target_release_cmd_kref(struct kref *kref)
+ {
+ struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
+ struct se_session *se_sess = se_cmd->se_sess;
+ unsigned long flags;
++ bool fabric_stop;
+
+ spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
+ if (list_empty(&se_cmd->se_cmd_list)) {
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
++ target_free_cmd_mem(se_cmd);
+ se_cmd->se_tfo->release_cmd(se_cmd);
+ return;
+ }
+- if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
++
++ spin_lock(&se_cmd->t_state_lock);
++ fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP);
++ spin_unlock(&se_cmd->t_state_lock);
++
++ if (se_cmd->cmd_wait_set || fabric_stop) {
++ list_del_init(&se_cmd->se_cmd_list);
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
++ target_free_cmd_mem(se_cmd);
+ complete(&se_cmd->cmd_wait_comp);
+ return;
+ }
+- list_del(&se_cmd->se_cmd_list);
++ list_del_init(&se_cmd->se_cmd_list);
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+
++ target_free_cmd_mem(se_cmd);
+ se_cmd->se_tfo->release_cmd(se_cmd);
+ }
+
+@@ -2539,6 +2566,7 @@ int target_put_sess_cmd(struct se_cmd *s
+ struct se_session *se_sess = se_cmd->se_sess;
+
+ if (!se_sess) {
++ target_free_cmd_mem(se_cmd);
+ se_cmd->se_tfo->release_cmd(se_cmd);
+ return 1;
+ }
+@@ -2555,6 +2583,7 @@ void target_sess_cmd_list_set_waiting(st
+ {
+ struct se_cmd *se_cmd;
+ unsigned long flags;
++ int rc;
+
+ spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
+ if (se_sess->sess_tearing_down) {
+@@ -2564,8 +2593,15 @@ void target_sess_cmd_list_set_waiting(st
+ se_sess->sess_tearing_down = 1;
+ list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
+
+- list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list)
+- se_cmd->cmd_wait_set = 1;
++ list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) {
++ rc = kref_get_unless_zero(&se_cmd->cmd_kref);
++ if (rc) {
++ se_cmd->cmd_wait_set = 1;
++ spin_lock(&se_cmd->t_state_lock);
++ se_cmd->transport_state |= CMD_T_FABRIC_STOP;
++ spin_unlock(&se_cmd->t_state_lock);
++ }
++ }
+
+ spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+ }
+@@ -2578,15 +2614,23 @@ void target_wait_for_sess_cmds(struct se
+ {
+ struct se_cmd *se_cmd, *tmp_cmd;
+ unsigned long flags;
++ bool tas;
+
+ list_for_each_entry_safe(se_cmd, tmp_cmd,
+ &se_sess->sess_wait_list, se_cmd_list) {
+- list_del(&se_cmd->se_cmd_list);
+-
+ pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:"
+ " %d\n", se_cmd, se_cmd->t_state,
+ se_cmd->se_tfo->get_cmd_state(se_cmd));
+
++ spin_lock_irqsave(&se_cmd->t_state_lock, flags);
++ tas = (se_cmd->transport_state & CMD_T_TAS);
++ spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
++
++ if (!target_put_sess_cmd(se_cmd)) {
++ if (tas)
++ target_put_sess_cmd(se_cmd);
++ }
++
+ wait_for_completion(&se_cmd->cmd_wait_comp);
+ pr_debug("After cmd_wait_comp: se_cmd: %p t_state: %d"
+ " fabric state: %d\n", se_cmd, se_cmd->t_state,
+@@ -2608,53 +2652,75 @@ void transport_clear_lun_ref(struct se_l
+ wait_for_completion(&lun->lun_ref_comp);
+ }
+
+-/**
+- * transport_wait_for_tasks - wait for completion to occur
+- * @cmd: command to wait
+- *
+- * Called from frontend fabric context to wait for storage engine
+- * to pause and/or release frontend generated struct se_cmd.
+- */
+-bool transport_wait_for_tasks(struct se_cmd *cmd)
++static bool
++__transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop,
++ bool *aborted, bool *tas, unsigned long *flags)
++ __releases(&cmd->t_state_lock)
++ __acquires(&cmd->t_state_lock)
+ {
+- unsigned long flags;
+
+- spin_lock_irqsave(&cmd->t_state_lock, flags);
++ assert_spin_locked(&cmd->t_state_lock);
++ WARN_ON_ONCE(!irqs_disabled());
++
++ if (fabric_stop)
++ cmd->transport_state |= CMD_T_FABRIC_STOP;
++
++ if (cmd->transport_state & CMD_T_ABORTED)
++ *aborted = true;
++
++ if (cmd->transport_state & CMD_T_TAS)
++ *tas = true;
++
+ if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD) &&
+- !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) {
+- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
+ return false;
+- }
+
+ if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) &&
+- !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) {
+- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
+ return false;
+- }
+
+- if (!(cmd->transport_state & CMD_T_ACTIVE)) {
+- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ if (!(cmd->transport_state & CMD_T_ACTIVE))
++ return false;
++
++ if (fabric_stop && *aborted)
+ return false;
+- }
+
+ cmd->transport_state |= CMD_T_STOP;
+
+- pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d, t_state: %d, CMD_T_STOP\n",
+- cmd, cmd->tag, cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
++ pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d,"
++ " t_state: %d, CMD_T_STOP\n", cmd, cmd->tag,
++ cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
+
+- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ spin_unlock_irqrestore(&cmd->t_state_lock, *flags);
+
+ wait_for_completion(&cmd->t_transport_stop_comp);
+
+- spin_lock_irqsave(&cmd->t_state_lock, flags);
++ spin_lock_irqsave(&cmd->t_state_lock, *flags);
+ cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP);
+
+- pr_debug("wait_for_tasks: Stopped wait_for_completion(&cmd->t_transport_stop_comp) for ITT: 0x%08llx\n",
+- cmd->tag);
++ pr_debug("wait_for_tasks: Stopped wait_for_completion(&cmd->"
++ "t_transport_stop_comp) for ITT: 0x%08llx\n", cmd->tag);
++
++ return true;
++}
+
++/**
++ * transport_wait_for_tasks - wait for completion to occur
++ * @cmd: command to wait
++ *
++ * Called from frontend fabric context to wait for storage engine
++ * to pause and/or release frontend generated struct se_cmd.
++ */
++bool transport_wait_for_tasks(struct se_cmd *cmd)
++{
++ unsigned long flags;
++ bool ret, aborted = false, tas = false;
++
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ ret = __transport_wait_for_tasks(cmd, false, &aborted, &tas, &flags);
+ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
+- return true;
++ return ret;
+ }
+ EXPORT_SYMBOL(transport_wait_for_tasks);
+
+@@ -2836,28 +2902,49 @@ transport_send_check_condition_and_sense
+ }
+ EXPORT_SYMBOL(transport_send_check_condition_and_sense);
+
+-int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
++static int __transport_check_aborted_status(struct se_cmd *cmd, int send_status)
++ __releases(&cmd->t_state_lock)
++ __acquires(&cmd->t_state_lock)
+ {
++ assert_spin_locked(&cmd->t_state_lock);
++ WARN_ON_ONCE(!irqs_disabled());
++
+ if (!(cmd->transport_state & CMD_T_ABORTED))
+ return 0;
+-
+ /*
+ * If cmd has been aborted but either no status is to be sent or it has
+ * already been sent, just return
+ */
+- if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS))
++ if (!send_status || !(cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS)) {
++ if (send_status)
++ cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
+ return 1;
++ }
+
+- pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB: 0x%02x ITT: 0x%08llx\n",
+- cmd->t_task_cdb[0], cmd->tag);
++ pr_debug("Sending delayed SAM_STAT_TASK_ABORTED status for CDB:"
++ " 0x%02x ITT: 0x%08llx\n", cmd->t_task_cdb[0], cmd->tag);
+
+ cmd->se_cmd_flags &= ~SCF_SEND_DELAYED_TAS;
+ cmd->scsi_status = SAM_STAT_TASK_ABORTED;
+ trace_target_cmd_complete(cmd);
++
++ spin_unlock_irq(&cmd->t_state_lock);
+ cmd->se_tfo->queue_status(cmd);
++ spin_lock_irq(&cmd->t_state_lock);
+
+ return 1;
+ }
++
++int transport_check_aborted_status(struct se_cmd *cmd, int send_status)
++{
++ int ret;
++
++ spin_lock_irq(&cmd->t_state_lock);
++ ret = __transport_check_aborted_status(cmd, send_status);
++ spin_unlock_irq(&cmd->t_state_lock);
++
++ return ret;
++}
+ EXPORT_SYMBOL(transport_check_aborted_status);
+
+ void transport_send_task_abort(struct se_cmd *cmd)
+@@ -2879,11 +2966,17 @@ void transport_send_task_abort(struct se
+ */
+ if (cmd->data_direction == DMA_TO_DEVICE) {
+ if (cmd->se_tfo->write_pending_status(cmd) != 0) {
+- cmd->transport_state |= CMD_T_ABORTED;
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ if (cmd->se_cmd_flags & SCF_SEND_DELAYED_TAS) {
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ goto send_abort;
++ }
+ cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+ return;
+ }
+ }
++send_abort:
+ cmd->scsi_status = SAM_STAT_TASK_ABORTED;
+
+ transport_lun_remove_cmd(cmd);
+@@ -2900,8 +2993,17 @@ static void target_tmr_work(struct work_
+ struct se_cmd *cmd = container_of(work, struct se_cmd, work);
+ struct se_device *dev = cmd->se_dev;
+ struct se_tmr_req *tmr = cmd->se_tmr_req;
++ unsigned long flags;
+ int ret;
+
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ if (cmd->transport_state & CMD_T_ABORTED) {
++ tmr->response = TMR_FUNCTION_REJECTED;
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ goto check_stop;
++ }
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++
+ switch (tmr->function) {
+ case TMR_ABORT_TASK:
+ core_tmr_abort_task(dev, tmr, cmd->se_sess);
+@@ -2934,9 +3036,17 @@ static void target_tmr_work(struct work_
+ break;
+ }
+
++ spin_lock_irqsave(&cmd->t_state_lock, flags);
++ if (cmd->transport_state & CMD_T_ABORTED) {
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++ goto check_stop;
++ }
+ cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
++ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
++
+ cmd->se_tfo->queue_tm_rsp(cmd);
+
++check_stop:
+ transport_cmd_check_stop_to_fabric(cmd);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/thermal/cpu_cooling.c linux-libre-4.4.7-gnu/drivers/thermal/cpu_cooling.c
+--- linux-libre-4.4-gnu/drivers/thermal/cpu_cooling.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/thermal/cpu_cooling.c 2016-04-12 12:09:26.000000000 -0400
+@@ -377,26 +377,28 @@ static u32 cpu_power_to_freq(struct cpuf
+ * get_load() - get load for a cpu since last updated
+ * @cpufreq_device: &struct cpufreq_cooling_device for this cpu
+ * @cpu: cpu number
++ * @cpu_idx: index of the cpu in cpufreq_device->allowed_cpus
+ *
+ * Return: The average load of cpu @cpu in percentage since this
+ * function was last called.
+ */
+-static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu)
++static u32 get_load(struct cpufreq_cooling_device *cpufreq_device, int cpu,
++ int cpu_idx)
+ {
+ u32 load;
+ u64 now, now_idle, delta_time, delta_idle;
+
+ now_idle = get_cpu_idle_time(cpu, &now, 0);
+- delta_idle = now_idle - cpufreq_device->time_in_idle[cpu];
+- delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu];
++ delta_idle = now_idle - cpufreq_device->time_in_idle[cpu_idx];
++ delta_time = now - cpufreq_device->time_in_idle_timestamp[cpu_idx];
+
+ if (delta_time <= delta_idle)
+ load = 0;
+ else
+ load = div64_u64(100 * (delta_time - delta_idle), delta_time);
+
+- cpufreq_device->time_in_idle[cpu] = now_idle;
+- cpufreq_device->time_in_idle_timestamp[cpu] = now;
++ cpufreq_device->time_in_idle[cpu_idx] = now_idle;
++ cpufreq_device->time_in_idle_timestamp[cpu_idx] = now;
+
+ return load;
+ }
+@@ -598,7 +600,7 @@ static int cpufreq_get_requested_power(s
+ u32 load;
+
+ if (cpu_online(cpu))
+- load = get_load(cpufreq_device, cpu);
++ load = get_load(cpufreq_device, cpu, i);
+ else
+ load = 0;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/thermal/step_wise.c linux-libre-4.4.7-gnu/drivers/thermal/step_wise.c
+--- linux-libre-4.4-gnu/drivers/thermal/step_wise.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/thermal/step_wise.c 2016-04-12 12:09:26.000000000 -0400
+@@ -63,6 +63,19 @@ static unsigned long get_target_state(st
+ next_target = instance->target;
+ dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
+
++ if (!instance->initialized) {
++ if (throttle) {
++ next_target = (cur_state + 1) >= instance->upper ?
++ instance->upper :
++ ((cur_state + 1) < instance->lower ?
++ instance->lower : (cur_state + 1));
++ } else {
++ next_target = THERMAL_NO_TARGET;
++ }
++
++ return next_target;
++ }
++
+ switch (trend) {
+ case THERMAL_TREND_RAISING:
+ if (throttle) {
+@@ -149,7 +162,7 @@ static void thermal_zone_trip_update(str
+ dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
+ old_target, (int)instance->target);
+
+- if (old_target == instance->target)
++ if (instance->initialized && old_target == instance->target)
+ continue;
+
+ /* Activate a passive thermal instance */
+@@ -161,7 +174,7 @@ static void thermal_zone_trip_update(str
+ instance->target == THERMAL_NO_TARGET)
+ update_passive_instance(tz, trip_type, -1);
+
+-
++ instance->initialized = true;
+ instance->cdev->updated = false; /* cdev needs update */
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/thermal/thermal_core.c linux-libre-4.4.7-gnu/drivers/thermal/thermal_core.c
+--- linux-libre-4.4-gnu/drivers/thermal/thermal_core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/thermal/thermal_core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -37,6 +37,7 @@
+ #include <linux/of.h>
+ #include <net/netlink.h>
+ #include <net/genetlink.h>
++#include <linux/suspend.h>
+
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/thermal.h>
+@@ -59,6 +60,8 @@ static LIST_HEAD(thermal_governor_list);
+ static DEFINE_MUTEX(thermal_list_lock);
+ static DEFINE_MUTEX(thermal_governor_lock);
+
++static atomic_t in_suspend;
++
+ static struct thermal_governor *def_governor;
+
+ static struct thermal_governor *__find_governor(const char *name)
+@@ -451,6 +454,10 @@ static void handle_thermal_trip(struct t
+ {
+ enum thermal_trip_type type;
+
++ /* Ignore disabled trip points */
++ if (test_bit(trip, &tz->trips_disabled))
++ return;
++
+ tz->ops->get_trip_type(tz, trip, &type);
+
+ if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
+@@ -532,14 +539,31 @@ static void update_temperature(struct th
+ mutex_unlock(&tz->lock);
+
+ trace_thermal_temperature(tz);
+- dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
+- tz->last_temperature, tz->temperature);
++ if (tz->last_temperature == THERMAL_TEMP_INVALID)
++ dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n",
++ tz->temperature);
++ else
++ dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
++ tz->last_temperature, tz->temperature);
++}
++
++static void thermal_zone_device_reset(struct thermal_zone_device *tz)
++{
++ struct thermal_instance *pos;
++
++ tz->temperature = THERMAL_TEMP_INVALID;
++ tz->passive = 0;
++ list_for_each_entry(pos, &tz->thermal_instances, tz_node)
++ pos->initialized = false;
+ }
+
+ void thermal_zone_device_update(struct thermal_zone_device *tz)
+ {
+ int count;
+
++ if (atomic_read(&in_suspend))
++ return;
++
+ if (!tz->ops->get_temp)
+ return;
+
+@@ -1321,6 +1345,7 @@ int thermal_zone_bind_cooling_device(str
+ if (!result) {
+ list_add_tail(&dev->tz_node, &tz->thermal_instances);
+ list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
++ atomic_set(&tz->need_update, 1);
+ }
+ mutex_unlock(&cdev->lock);
+ mutex_unlock(&tz->lock);
+@@ -1430,6 +1455,7 @@ __thermal_cooling_device_register(struct
+ const struct thermal_cooling_device_ops *ops)
+ {
+ struct thermal_cooling_device *cdev;
++ struct thermal_zone_device *pos = NULL;
+ int result;
+
+ if (type && strlen(type) >= THERMAL_NAME_LENGTH)
+@@ -1474,6 +1500,12 @@ __thermal_cooling_device_register(struct
+ /* Update binding information for 'this' new cdev */
+ bind_cdev(cdev);
+
++ mutex_lock(&thermal_list_lock);
++ list_for_each_entry(pos, &thermal_tz_list, node)
++ if (atomic_cmpxchg(&pos->need_update, 1, 0))
++ thermal_zone_device_update(pos);
++ mutex_unlock(&thermal_list_lock);
++
+ return cdev;
+ }
+
+@@ -1768,6 +1800,7 @@ struct thermal_zone_device *thermal_zone
+ {
+ struct thermal_zone_device *tz;
+ enum thermal_trip_type trip_type;
++ int trip_temp;
+ int result;
+ int count;
+ int passive = 0;
+@@ -1806,6 +1839,8 @@ struct thermal_zone_device *thermal_zone
+ tz->trips = trips;
+ tz->passive_delay = passive_delay;
+ tz->polling_delay = polling_delay;
++ /* A new thermal zone needs to be updated anyway. */
++ atomic_set(&tz->need_update, 1);
+
+ dev_set_name(&tz->device, "thermal_zone%d", tz->id);
+ result = device_register(&tz->device);
+@@ -1837,9 +1872,15 @@ struct thermal_zone_device *thermal_zone
+ goto unregister;
+
+ for (count = 0; count < trips; count++) {
+- tz->ops->get_trip_type(tz, count, &trip_type);
++ if (tz->ops->get_trip_type(tz, count, &trip_type))
++ set_bit(count, &tz->trips_disabled);
+ if (trip_type == THERMAL_TRIP_PASSIVE)
+ passive = 1;
++ if (tz->ops->get_trip_temp(tz, count, &trip_temp))
++ set_bit(count, &tz->trips_disabled);
++ /* Check for bogus trip points */
++ if (trip_temp == 0)
++ set_bit(count, &tz->trips_disabled);
+ }
+
+ if (!passive) {
+@@ -1900,7 +1941,10 @@ struct thermal_zone_device *thermal_zone
+
+ INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check);
+
+- thermal_zone_device_update(tz);
++ thermal_zone_device_reset(tz);
++ /* Update the new thermal zone and mark it as already updated. */
++ if (atomic_cmpxchg(&tz->need_update, 1, 0))
++ thermal_zone_device_update(tz);
+
+ return tz;
+
+@@ -2140,6 +2184,36 @@ static void thermal_unregister_governors
+ thermal_gov_power_allocator_unregister();
+ }
+
++static int thermal_pm_notify(struct notifier_block *nb,
++ unsigned long mode, void *_unused)
++{
++ struct thermal_zone_device *tz;
++
++ switch (mode) {
++ case PM_HIBERNATION_PREPARE:
++ case PM_RESTORE_PREPARE:
++ case PM_SUSPEND_PREPARE:
++ atomic_set(&in_suspend, 1);
++ break;
++ case PM_POST_HIBERNATION:
++ case PM_POST_RESTORE:
++ case PM_POST_SUSPEND:
++ atomic_set(&in_suspend, 0);
++ list_for_each_entry(tz, &thermal_tz_list, node) {
++ thermal_zone_device_reset(tz);
++ thermal_zone_device_update(tz);
++ }
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++
++static struct notifier_block thermal_pm_nb = {
++ .notifier_call = thermal_pm_notify,
++};
++
+ static int __init thermal_init(void)
+ {
+ int result;
+@@ -2160,6 +2234,11 @@ static int __init thermal_init(void)
+ if (result)
+ goto exit_netlink;
+
++ result = register_pm_notifier(&thermal_pm_nb);
++ if (result)
++ pr_warn("Thermal: Can not register suspend notifier, return %d\n",
++ result);
++
+ return 0;
+
+ exit_netlink:
+@@ -2179,6 +2258,7 @@ error:
+
+ static void __exit thermal_exit(void)
+ {
++ unregister_pm_notifier(&thermal_pm_nb);
+ of_thermal_destroy_zones();
+ genetlink_exit();
+ class_unregister(&thermal_class);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/thermal/thermal_core.h linux-libre-4.4.7-gnu/drivers/thermal/thermal_core.h
+--- linux-libre-4.4-gnu/drivers/thermal/thermal_core.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/thermal/thermal_core.h 2016-04-12 12:09:26.000000000 -0400
+@@ -41,6 +41,7 @@ struct thermal_instance {
+ struct thermal_zone_device *tz;
+ struct thermal_cooling_device *cdev;
+ int trip;
++ bool initialized;
+ unsigned long upper; /* Highest cooling state for this trip point */
+ unsigned long lower; /* Lowest cooling state for this trip point */
+ unsigned long target; /* expected cooling state */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/tty/n_tty.c linux-libre-4.4.7-gnu/drivers/tty/n_tty.c
+--- linux-libre-4.4-gnu/drivers/tty/n_tty.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/tty/n_tty.c 2016-04-12 12:09:26.000000000 -0400
+@@ -258,16 +258,13 @@ static void n_tty_check_throttle(struct
+
+ static void n_tty_check_unthrottle(struct tty_struct *tty)
+ {
+- if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+- tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) {
++ if (tty->driver->type == TTY_DRIVER_TYPE_PTY) {
+ if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
+ return;
+ if (!tty->count)
+ return;
+ n_tty_kick_worker(tty);
+- n_tty_write_wakeup(tty->link);
+- if (waitqueue_active(&tty->link->write_wait))
+- wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
++ tty_wakeup(tty->link);
+ return;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/tty/pty.c linux-libre-4.4.7-gnu/drivers/tty/pty.c
+--- linux-libre-4.4-gnu/drivers/tty/pty.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/tty/pty.c 2016-04-12 12:09:26.000000000 -0400
+@@ -681,7 +681,14 @@ static void pty_unix98_remove(struct tty
+ /* this is called once with whichever end is closed last */
+ static void pty_unix98_shutdown(struct tty_struct *tty)
+ {
+- devpts_kill_index(tty->driver_data, tty->index);
++ struct inode *ptmx_inode;
++
++ if (tty->driver->subtype == PTY_TYPE_MASTER)
++ ptmx_inode = tty->driver_data;
++ else
++ ptmx_inode = tty->link->driver_data;
++ devpts_kill_index(ptmx_inode, tty->index);
++ devpts_del_ref(ptmx_inode);
+ }
+
+ static const struct tty_operations ptm_unix98_ops = {
+@@ -773,6 +780,18 @@ static int ptmx_open(struct inode *inode
+ set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+ tty->driver_data = inode;
+
++ /*
++ * In the case where all references to ptmx inode are dropped and we
++ * still have /dev/tty opened pointing to the master/slave pair (ptmx
++ * is closed/released before /dev/tty), we must make sure that the inode
++ * is still valid when we call the final pty_unix98_shutdown, thus we
++ * hold an additional reference to the ptmx inode. For the same /dev/tty
++ * last close case, we also need to make sure the super_block isn't
++ * destroyed (devpts instance unmounted), before /dev/tty is closed and
++ * on its release devpts_kill_index is called.
++ */
++ devpts_add_ref(inode);
++
+ tty_add_file(tty, filp);
+
+ slave_inode = devpts_pty_new(inode,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/tty/serial/8250/8250_pci.c linux-libre-4.4.7-gnu/drivers/tty/serial/8250/8250_pci.c
+--- linux-libre-4.4-gnu/drivers/tty/serial/8250/8250_pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/tty/serial/8250/8250_pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1379,6 +1379,9 @@ ce4100_serial_setup(struct serial_privat
+ #define PCI_DEVICE_ID_INTEL_BSW_UART1 0x228a
+ #define PCI_DEVICE_ID_INTEL_BSW_UART2 0x228c
+
++#define PCI_DEVICE_ID_INTEL_BDW_UART1 0x9ce3
++#define PCI_DEVICE_ID_INTEL_BDW_UART2 0x9ce4
++
+ #define BYT_PRV_CLK 0x800
+ #define BYT_PRV_CLK_EN (1 << 0)
+ #define BYT_PRV_CLK_M_VAL_SHIFT 1
+@@ -1461,11 +1464,13 @@ byt_serial_setup(struct serial_private *
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_BYT_UART1:
+ case PCI_DEVICE_ID_INTEL_BSW_UART1:
++ case PCI_DEVICE_ID_INTEL_BDW_UART1:
+ rx_param->src_id = 3;
+ tx_param->dst_id = 2;
+ break;
+ case PCI_DEVICE_ID_INTEL_BYT_UART2:
+ case PCI_DEVICE_ID_INTEL_BSW_UART2:
++ case PCI_DEVICE_ID_INTEL_BDW_UART2:
+ rx_param->src_id = 5;
+ tx_param->dst_id = 4;
+ break;
+@@ -1936,6 +1941,7 @@ pci_wch_ch38x_setup(struct serial_privat
+ #define PCIE_VENDOR_ID_WCH 0x1c00
+ #define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
+ #define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
++#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253
+
+ #define PCI_VENDOR_ID_PERICOM 0x12D8
+ #define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
+@@ -2062,6 +2068,20 @@ static struct pci_serial_quirk pci_seria
+ .subdevice = PCI_ANY_ID,
+ .setup = byt_serial_setup,
+ },
++ {
++ .vendor = PCI_VENDOR_ID_INTEL,
++ .device = PCI_DEVICE_ID_INTEL_BDW_UART1,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = byt_serial_setup,
++ },
++ {
++ .vendor = PCI_VENDOR_ID_INTEL,
++ .device = PCI_DEVICE_ID_INTEL_BDW_UART2,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = byt_serial_setup,
++ },
+ /*
+ * ITE
+ */
+@@ -2618,6 +2638,14 @@ static struct pci_serial_quirk pci_seria
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_wch_ch353_setup,
+ },
++ /* WCH CH382 2S card (16850 clone) */
++ {
++ .vendor = PCIE_VENDOR_ID_WCH,
++ .device = PCIE_DEVICE_ID_WCH_CH382_2S,
++ .subvendor = PCI_ANY_ID,
++ .subdevice = PCI_ANY_ID,
++ .setup = pci_wch_ch38x_setup,
++ },
+ /* WCH CH382 2S1P card (16850 clone) */
+ {
+ .vendor = PCIE_VENDOR_ID_WCH,
+@@ -2936,6 +2964,7 @@ enum pci_board_num_t {
+ pbn_fintek_4,
+ pbn_fintek_8,
+ pbn_fintek_12,
++ pbn_wch382_2,
+ pbn_wch384_4,
+ pbn_pericom_PI7C9X7951,
+ pbn_pericom_PI7C9X7952,
+@@ -3756,6 +3785,13 @@ static struct pciserial_board pci_boards
+ .base_baud = 115200,
+ .first_offset = 0x40,
+ },
++ [pbn_wch382_2] = {
++ .flags = FL_BASE0,
++ .num_ports = 2,
++ .base_baud = 115200,
++ .uart_offset = 8,
++ .first_offset = 0xC0,
++ },
+ [pbn_wch384_4] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+@@ -5506,6 +5542,16 @@ static struct pci_device_id serial_pci_t
+ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
+ pbn_byt },
+
++ /* Intel Broadwell */
++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART1,
++ PCI_ANY_ID, PCI_ANY_ID,
++ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
++ pbn_byt },
++ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_UART2,
++ PCI_ANY_ID, PCI_ANY_ID,
++ PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
++ pbn_byt },
++
+ /*
+ * Intel Quark x1000
+ */
+@@ -5545,6 +5591,10 @@ static struct pci_device_id serial_pci_t
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, pbn_b0_bt_2_115200 },
+
++ { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0, pbn_wch382_2 },
++
+ { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, pbn_wch384_4 },
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/tty/serial/8250/8250_port.c linux-libre-4.4.7-gnu/drivers/tty/serial/8250/8250_port.c
+--- linux-libre-4.4-gnu/drivers/tty/serial/8250/8250_port.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/tty/serial/8250/8250_port.c 2016-04-12 12:09:26.000000000 -0400
+@@ -713,22 +713,16 @@ static int size_fifo(struct uart_8250_po
+ */
+ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
+ {
+- unsigned char old_dll, old_dlm, old_lcr;
+- unsigned int id;
++ unsigned char old_lcr;
++ unsigned int id, old_dl;
+
+ old_lcr = serial_in(p, UART_LCR);
+ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
++ old_dl = serial_dl_read(p);
++ serial_dl_write(p, 0);
++ id = serial_dl_read(p);
++ serial_dl_write(p, old_dl);
+
+- old_dll = serial_in(p, UART_DLL);
+- old_dlm = serial_in(p, UART_DLM);
+-
+- serial_out(p, UART_DLL, 0);
+- serial_out(p, UART_DLM, 0);
+-
+- id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
+-
+- serial_out(p, UART_DLL, old_dll);
+- serial_out(p, UART_DLM, old_dlm);
+ serial_out(p, UART_LCR, old_lcr);
+
+ return id;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/tty/serial/omap-serial.c linux-libre-4.4.7-gnu/drivers/tty/serial/omap-serial.c
+--- linux-libre-4.4-gnu/drivers/tty/serial/omap-serial.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/tty/serial/omap-serial.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1343,7 +1343,7 @@ static inline void serial_omap_add_conso
+
+ /* Enable or disable the rs485 support */
+ static int
+-serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
++serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
+ {
+ struct uart_omap_port *up = to_uart_omap_port(port);
+ unsigned int mode;
+@@ -1356,8 +1356,12 @@ serial_omap_config_rs485(struct uart_por
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+
++ /* Clamp the delays to [0, 100ms] */
++ rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U);
++ rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U);
++
+ /* store new config */
+- port->rs485 = *rs485conf;
++ port->rs485 = *rs485;
+
+ /*
+ * Just as a precaution, only allow rs485
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/tty/tty_io.c linux-libre-4.4.7-gnu/drivers/tty/tty_io.c
+--- linux-libre-4.4-gnu/drivers/tty/tty_io.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/tty/tty_io.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1462,13 +1462,13 @@ static int tty_reopen(struct tty_struct
+ {
+ struct tty_driver *driver = tty->driver;
+
+- if (!tty->count)
+- return -EIO;
+-
+ if (driver->type == TTY_DRIVER_TYPE_PTY &&
+ driver->subtype == PTY_TYPE_MASTER)
+ return -EIO;
+
++ if (!tty->count)
++ return -EAGAIN;
++
+ if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
+ return -EBUSY;
+
+@@ -2069,7 +2069,12 @@ retry_open:
+
+ if (tty) {
+ mutex_unlock(&tty_mutex);
+- tty_lock(tty);
++ retval = tty_lock_interruptible(tty);
++ if (retval) {
++ if (retval == -EINTR)
++ retval = -ERESTARTSYS;
++ goto err_unref;
++ }
+ /* safe to drop the kref from tty_driver_lookup_tty() */
+ tty_kref_put(tty);
+ retval = tty_reopen(tty);
+@@ -2087,7 +2092,11 @@ retry_open:
+
+ if (IS_ERR(tty)) {
+ retval = PTR_ERR(tty);
+- goto err_file;
++ if (retval != -EAGAIN || signal_pending(current))
++ goto err_file;
++ tty_free_file(filp);
++ schedule();
++ goto retry_open;
+ }
+
+ tty_add_file(tty, filp);
+@@ -2156,6 +2165,7 @@ retry_open:
+ return 0;
+ err_unlock:
+ mutex_unlock(&tty_mutex);
++err_unref:
+ /* after locks to avoid deadlock */
+ if (!IS_ERR_OR_NULL(driver))
+ tty_driver_kref_put(driver);
+@@ -2653,6 +2663,28 @@ static int tiocsetd(struct tty_struct *t
+ }
+
+ /**
++ * tiocgetd - get line discipline
++ * @tty: tty device
++ * @p: pointer to user data
++ *
++ * Retrieves the line discipline id directly from the ldisc.
++ *
++ * Locking: waits for ldisc reference (in case the line discipline
++ * is changing or the tty is being hungup)
++ */
++
++static int tiocgetd(struct tty_struct *tty, int __user *p)
++{
++ struct tty_ldisc *ld;
++ int ret;
++
++ ld = tty_ldisc_ref_wait(tty);
++ ret = put_user(ld->ops->num, p);
++ tty_ldisc_deref(ld);
++ return ret;
++}
++
++/**
+ * send_break - performed time break
+ * @tty: device to break on
+ * @duration: timeout in mS
+@@ -2878,7 +2910,7 @@ long tty_ioctl(struct file *file, unsign
+ case TIOCGSID:
+ return tiocgsid(tty, real_tty, p);
+ case TIOCGETD:
+- return put_user(tty->ldisc->ops->num, (int __user *)p);
++ return tiocgetd(tty, p);
+ case TIOCSETD:
+ return tiocsetd(tty, p);
+ case TIOCVHANGUP:
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/tty/tty_mutex.c linux-libre-4.4.7-gnu/drivers/tty/tty_mutex.c
+--- linux-libre-4.4-gnu/drivers/tty/tty_mutex.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/tty/tty_mutex.c 2016-04-12 12:09:26.000000000 -0400
+@@ -22,6 +22,14 @@ void __lockfunc tty_lock(struct tty_stru
+ }
+ EXPORT_SYMBOL(tty_lock);
+
++int tty_lock_interruptible(struct tty_struct *tty)
++{
++ if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
++ return -EIO;
++ tty_kref_get(tty);
++ return mutex_lock_interruptible(&tty->legacy_mutex);
++}
++
+ void __lockfunc tty_unlock(struct tty_struct *tty)
+ {
+ if (tty->magic != TTY_MAGIC) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/chipidea/otg.c linux-libre-4.4.7-gnu/drivers/usb/chipidea/otg.c
+--- linux-libre-4.4-gnu/drivers/usb/chipidea/otg.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/chipidea/otg.c 2016-04-12 12:09:26.000000000 -0400
+@@ -158,7 +158,7 @@ static void ci_otg_work(struct work_stru
+ int ci_hdrc_otg_init(struct ci_hdrc *ci)
+ {
+ INIT_WORK(&ci->work, ci_otg_work);
+- ci->wq = create_singlethread_workqueue("ci_otg");
++ ci->wq = create_freezable_workqueue("ci_otg");
+ if (!ci->wq) {
+ dev_err(ci->dev, "can't create workqueue\n");
+ return -ENODEV;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/class/cdc-acm.c linux-libre-4.4.7-gnu/drivers/usb/class/cdc-acm.c
+--- linux-libre-4.4-gnu/drivers/usb/class/cdc-acm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/class/cdc-acm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -428,7 +428,8 @@ static void acm_read_bulk_callback(struc
+ set_bit(rb->index, &acm->read_urbs_free);
+ dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
+ __func__, status);
+- return;
++ if ((status != -ENOENT) || (urb->actual_length == 0))
++ return;
+ }
+
+ usb_mark_last_busy(acm->dev);
+@@ -1113,6 +1114,9 @@ static int acm_probe(struct usb_interfac
+ if (quirks == NO_UNION_NORMAL) {
+ data_interface = usb_ifnum_to_if(usb_dev, 1);
+ control_interface = usb_ifnum_to_if(usb_dev, 0);
++ /* we would crash */
++ if (!data_interface || !control_interface)
++ return -ENODEV;
+ goto skip_normal_probe;
+ }
+
+@@ -1404,6 +1408,8 @@ made_compressed_probe:
+ usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+ NULL, acm->writesize, acm_write_bulk, snd);
+ snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++ if (quirks & SEND_ZERO_PACKET)
++ snd->urb->transfer_flags |= URB_ZERO_PACKET;
+ snd->instance = acm;
+ }
+
+@@ -1838,6 +1844,11 @@ static const struct usb_device_id acm_id
+ },
+ #endif
+
++ /*Samsung phone in firmware update mode */
++ { USB_DEVICE(0x04e8, 0x685d),
++ .driver_info = IGNORE_DEVICE,
++ },
++
+ /* Exclude Infineon Flash Loader utility */
+ { USB_DEVICE(0x058b, 0x0041),
+ .driver_info = IGNORE_DEVICE,
+@@ -1861,6 +1872,10 @@ static const struct usb_device_id acm_id
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_CDMA) },
+
++ { USB_DEVICE(0x1519, 0x0452), /* Intel 7260 modem */
++ .driver_info = SEND_ZERO_PACKET,
++ },
++
+ { }
+ };
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/class/cdc-acm.h linux-libre-4.4.7-gnu/drivers/usb/class/cdc-acm.h
+--- linux-libre-4.4-gnu/drivers/usb/class/cdc-acm.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/class/cdc-acm.h 2016-04-12 12:09:26.000000000 -0400
+@@ -134,3 +134,4 @@ struct acm {
+ #define IGNORE_DEVICE BIT(5)
+ #define QUIRK_CONTROL_LINE_STATE BIT(6)
+ #define CLEAR_HALT_CONDITIONS BIT(7)
++#define SEND_ZERO_PACKET BIT(8)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/core/driver.c linux-libre-4.4.7-gnu/drivers/usb/core/driver.c
+--- linux-libre-4.4-gnu/drivers/usb/core/driver.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/core/driver.c 2016-04-12 12:09:26.000000000 -0400
+@@ -502,11 +502,15 @@ static int usb_unbind_interface(struct d
+ int usb_driver_claim_interface(struct usb_driver *driver,
+ struct usb_interface *iface, void *priv)
+ {
+- struct device *dev = &iface->dev;
++ struct device *dev;
+ struct usb_device *udev;
+ int retval = 0;
+ int lpm_disable_error;
+
++ if (!iface)
++ return -ENODEV;
++
++ dev = &iface->dev;
+ if (dev->driver)
+ return -EBUSY;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/core/hub.c linux-libre-4.4.7-gnu/drivers/usb/core/hub.c
+--- linux-libre-4.4-gnu/drivers/usb/core/hub.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/core/hub.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3895,17 +3895,30 @@ static void usb_enable_link_state(struct
+ return;
+ }
+
+- if (usb_set_lpm_timeout(udev, state, timeout))
++ if (usb_set_lpm_timeout(udev, state, timeout)) {
+ /* If we can't set the parent hub U1/U2 timeout,
+ * device-initiated LPM won't be allowed either, so let the xHCI
+ * host know that this link state won't be enabled.
+ */
+ hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
++ } else {
++ /* Only a configured device will accept the Set Feature
++ * U1/U2_ENABLE
++ */
++ if (udev->actconfig)
++ usb_set_device_initiated_lpm(udev, state, true);
+
+- /* Only a configured device will accept the Set Feature U1/U2_ENABLE */
+- else if (udev->actconfig)
+- usb_set_device_initiated_lpm(udev, state, true);
+-
++ /* As soon as usb_set_lpm_timeout(timeout) returns 0, the
++ * hub-initiated LPM is enabled. Thus, LPM is enabled no
++ * matter the result of usb_set_device_initiated_lpm().
++ * The only difference is whether device is able to initiate
++ * LPM.
++ */
++ if (state == USB3_LPM_U1)
++ udev->usb3_lpm_u1_enabled = 1;
++ else if (state == USB3_LPM_U2)
++ udev->usb3_lpm_u2_enabled = 1;
++ }
+ }
+
+ /*
+@@ -3945,6 +3958,18 @@ static int usb_disable_link_state(struct
+ dev_warn(&udev->dev, "Could not disable xHCI %s timeout, "
+ "bus schedule bandwidth may be impacted.\n",
+ usb3_lpm_names[state]);
++
++ /* As soon as usb_set_lpm_timeout(0) return 0, hub initiated LPM
++ * is disabled. Hub will disallows link to enter U1/U2 as well,
++ * even device is initiating LPM. Hence LPM is disabled if hub LPM
++ * timeout set to 0, no matter device-initiated LPM is disabled or
++ * not.
++ */
++ if (state == USB3_LPM_U1)
++ udev->usb3_lpm_u1_enabled = 0;
++ else if (state == USB3_LPM_U2)
++ udev->usb3_lpm_u2_enabled = 0;
++
+ return 0;
+ }
+
+@@ -3979,8 +4004,6 @@ int usb_disable_lpm(struct usb_device *u
+ if (usb_disable_link_state(hcd, udev, USB3_LPM_U2))
+ goto enable_lpm;
+
+- udev->usb3_lpm_enabled = 0;
+-
+ return 0;
+
+ enable_lpm:
+@@ -4038,8 +4061,6 @@ void usb_enable_lpm(struct usb_device *u
+
+ usb_enable_link_state(hcd, udev, USB3_LPM_U1);
+ usb_enable_link_state(hcd, udev, USB3_LPM_U2);
+-
+- udev->usb3_lpm_enabled = 1;
+ }
+ EXPORT_SYMBOL_GPL(usb_enable_lpm);
+
+@@ -4256,7 +4277,7 @@ hub_port_init(struct usb_hub *hub, struc
+ {
+ struct usb_device *hdev = hub->hdev;
+ struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+- int i, j, retval;
++ int retries, operations, retval, i;
+ unsigned delay = HUB_SHORT_RESET_TIME;
+ enum usb_device_speed oldspeed = udev->speed;
+ const char *speed;
+@@ -4358,7 +4379,7 @@ hub_port_init(struct usb_hub *hub, struc
+ * first 8 bytes of the device descriptor to get the ep0 maxpacket
+ * value.
+ */
+- for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
++ for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) {
+ bool did_new_scheme = false;
+
+ if (use_new_scheme(udev, retry_counter)) {
+@@ -4385,7 +4406,7 @@ hub_port_init(struct usb_hub *hub, struc
+ * 255 is for WUSB devices, we actually need to use
+ * 512 (WUSB1.0[4.8.1]).
+ */
+- for (j = 0; j < 3; ++j) {
++ for (operations = 0; operations < 3; ++operations) {
+ buf->bMaxPacketSize0 = 0;
+ r = usb_control_msg(udev, usb_rcvaddr0pipe(),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+@@ -4405,7 +4426,13 @@ hub_port_init(struct usb_hub *hub, struc
+ r = -EPROTO;
+ break;
+ }
+- if (r == 0)
++ /*
++ * Some devices time out if they are powered on
++ * when already connected. They need a second
++ * reset. But only on the first attempt,
++ * lest we get into a time out/reset loop
++ */
++ if (r == 0 || (r == -ETIMEDOUT && retries == 0))
+ break;
+ }
+ udev->descriptor.bMaxPacketSize0 =
+@@ -4437,7 +4464,7 @@ hub_port_init(struct usb_hub *hub, struc
+ * authorization will assign the final address.
+ */
+ if (udev->wusb == 0) {
+- for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
++ for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) {
+ retval = hub_set_address(udev, devnum);
+ if (retval >= 0)
+ break;
+@@ -5365,7 +5392,6 @@ static int usb_reset_and_verify_device(s
+ }
+
+ bos = udev->bos;
+- udev->bos = NULL;
+
+ for (i = 0; i < SET_CONFIG_TRIES; ++i) {
+
+@@ -5458,8 +5484,11 @@ done:
+ usb_set_usb2_hardware_lpm(udev, 1);
+ usb_unlocked_enable_lpm(udev);
+ usb_enable_ltm(udev);
+- usb_release_bos_descriptor(udev);
+- udev->bos = bos;
++ /* release the new BOS descriptor allocated by hub_port_init() */
++ if (udev->bos != bos) {
++ usb_release_bos_descriptor(udev);
++ udev->bos = bos;
++ }
+ return 0;
+
+ re_enumerate:
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/core/sysfs.c linux-libre-4.4.7-gnu/drivers/usb/core/sysfs.c
+--- linux-libre-4.4-gnu/drivers/usb/core/sysfs.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/core/sysfs.c 2016-04-12 12:09:26.000000000 -0400
+@@ -531,7 +531,7 @@ static ssize_t usb2_lpm_besl_store(struc
+ }
+ static DEVICE_ATTR_RW(usb2_lpm_besl);
+
+-static ssize_t usb3_hardware_lpm_show(struct device *dev,
++static ssize_t usb3_hardware_lpm_u1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct usb_device *udev = to_usb_device(dev);
+@@ -539,7 +539,7 @@ static ssize_t usb3_hardware_lpm_show(st
+
+ usb_lock_device(udev);
+
+- if (udev->usb3_lpm_enabled)
++ if (udev->usb3_lpm_u1_enabled)
+ p = "enabled";
+ else
+ p = "disabled";
+@@ -548,7 +548,26 @@ static ssize_t usb3_hardware_lpm_show(st
+
+ return sprintf(buf, "%s\n", p);
+ }
+-static DEVICE_ATTR_RO(usb3_hardware_lpm);
++static DEVICE_ATTR_RO(usb3_hardware_lpm_u1);
++
++static ssize_t usb3_hardware_lpm_u2_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct usb_device *udev = to_usb_device(dev);
++ const char *p;
++
++ usb_lock_device(udev);
++
++ if (udev->usb3_lpm_u2_enabled)
++ p = "enabled";
++ else
++ p = "disabled";
++
++ usb_unlock_device(udev);
++
++ return sprintf(buf, "%s\n", p);
++}
++static DEVICE_ATTR_RO(usb3_hardware_lpm_u2);
+
+ static struct attribute *usb2_hardware_lpm_attr[] = {
+ &dev_attr_usb2_hardware_lpm.attr,
+@@ -562,7 +581,8 @@ static struct attribute_group usb2_hardw
+ };
+
+ static struct attribute *usb3_hardware_lpm_attr[] = {
+- &dev_attr_usb3_hardware_lpm.attr,
++ &dev_attr_usb3_hardware_lpm_u1.attr,
++ &dev_attr_usb3_hardware_lpm_u2.attr,
+ NULL,
+ };
+ static struct attribute_group usb3_hardware_lpm_attr_group = {
+@@ -592,7 +612,8 @@ static int add_power_attributes(struct d
+ if (udev->usb2_hw_lpm_capable == 1)
+ rc = sysfs_merge_group(&dev->kobj,
+ &usb2_hardware_lpm_attr_group);
+- if (udev->lpm_capable == 1)
++ if (udev->speed == USB_SPEED_SUPER &&
++ udev->lpm_capable == 1)
+ rc = sysfs_merge_group(&dev->kobj,
+ &usb3_hardware_lpm_attr_group);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/dwc3/core.h linux-libre-4.4.7-gnu/drivers/usb/dwc3/core.h
+--- linux-libre-4.4-gnu/drivers/usb/dwc3/core.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/dwc3/core.h 2016-04-12 12:09:26.000000000 -0400
+@@ -853,7 +853,6 @@ struct dwc3 {
+ unsigned pullups_connected:1;
+ unsigned resize_fifos:1;
+ unsigned setup_packet_pending:1;
+- unsigned start_config_issued:1;
+ unsigned three_stage_setup:1;
+ unsigned usb3_lpm_capable:1;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/dwc3/ep0.c linux-libre-4.4.7-gnu/drivers/usb/dwc3/ep0.c
+--- linux-libre-4.4-gnu/drivers/usb/dwc3/ep0.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/dwc3/ep0.c 2016-04-12 12:09:26.000000000 -0400
+@@ -555,7 +555,6 @@ static int dwc3_ep0_set_config(struct dw
+ int ret;
+ u32 reg;
+
+- dwc->start_config_issued = false;
+ cfg = le16_to_cpu(ctrl->wValue);
+
+ switch (state) {
+@@ -737,10 +736,6 @@ static int dwc3_ep0_std_request(struct d
+ dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
+ ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
+ break;
+- case USB_REQ_SET_INTERFACE:
+- dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE");
+- dwc->start_config_issued = false;
+- /* Fall through */
+ default:
+ dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
+ ret = dwc3_ep0_delegate_req(dwc, ctrl);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/dwc3/gadget.c linux-libre-4.4.7-gnu/drivers/usb/dwc3/gadget.c
+--- linux-libre-4.4-gnu/drivers/usb/dwc3/gadget.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/dwc3/gadget.c 2016-04-12 12:09:26.000000000 -0400
+@@ -388,24 +388,66 @@ static void dwc3_free_trb_pool(struct dw
+ dep->trb_pool_dma = 0;
+ }
+
++static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep);
++
++/**
++ * dwc3_gadget_start_config - Configure EP resources
++ * @dwc: pointer to our controller context structure
++ * @dep: endpoint that is being enabled
++ *
++ * The assignment of transfer resources cannot perfectly follow the
++ * data book due to the fact that the controller driver does not have
++ * all knowledge of the configuration in advance. It is given this
++ * information piecemeal by the composite gadget framework after every
++ * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook
++ * programming model in this scenario can cause errors. For two
++ * reasons:
++ *
++ * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION
++ * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of
++ * multiple interfaces.
++ *
++ * 2) The databook does not mention doing more DEPXFERCFG for new
++ * endpoint on alt setting (8.1.6).
++ *
++ * The following simplified method is used instead:
++ *
++ * All hardware endpoints can be assigned a transfer resource and this
++ * setting will stay persistent until either a core reset or
++ * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and
++ * do DEPXFERCFG for every hardware endpoint as well. We are
++ * guaranteed that there are as many transfer resources as endpoints.
++ *
++ * This function is called for each endpoint when it is being enabled
++ * but is triggered only when called for EP0-out, which always happens
++ * first, and which should only happen in one of the above conditions.
++ */
+ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
+ {
+ struct dwc3_gadget_ep_cmd_params params;
+ u32 cmd;
++ int i;
++ int ret;
++
++ if (dep->number)
++ return 0;
+
+ memset(&params, 0x00, sizeof(params));
++ cmd = DWC3_DEPCMD_DEPSTARTCFG;
+
+- if (dep->number != 1) {
+- cmd = DWC3_DEPCMD_DEPSTARTCFG;
+- /* XferRscIdx == 0 for ep0 and 2 for the remaining */
+- if (dep->number > 1) {
+- if (dwc->start_config_issued)
+- return 0;
+- dwc->start_config_issued = true;
+- cmd |= DWC3_DEPCMD_PARAM(2);
+- }
++ ret = dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
++ if (ret)
++ return ret;
+
+- return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
++ for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) {
++ struct dwc3_ep *dep = dwc->eps[i];
++
++ if (!dep)
++ continue;
++
++ ret = dwc3_gadget_set_xfer_resource(dwc, dep);
++ if (ret)
++ return ret;
+ }
+
+ return 0;
+@@ -519,10 +561,6 @@ static int __dwc3_gadget_ep_enable(struc
+ struct dwc3_trb *trb_st_hw;
+ struct dwc3_trb *trb_link;
+
+- ret = dwc3_gadget_set_xfer_resource(dwc, dep);
+- if (ret)
+- return ret;
+-
+ dep->endpoint.desc = desc;
+ dep->comp_desc = comp_desc;
+ dep->type = usb_endpoint_type(desc);
+@@ -1604,8 +1642,6 @@ static int dwc3_gadget_start(struct usb_
+ }
+ dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+- dwc->start_config_issued = false;
+-
+ /* Start with SuperSpeed Default */
+ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
+
+@@ -2202,7 +2238,6 @@ static void dwc3_gadget_disconnect_inter
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+ dwc3_disconnect_gadget(dwc);
+- dwc->start_config_issued = false;
+
+ dwc->gadget.speed = USB_SPEED_UNKNOWN;
+ dwc->setup_packet_pending = false;
+@@ -2253,7 +2288,6 @@ static void dwc3_gadget_reset_interrupt(
+
+ dwc3_stop_active_transfers(dwc);
+ dwc3_clear_stall_all_ep(dwc);
+- dwc->start_config_issued = false;
+
+ /* Reset device address to zero */
+ reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/host/xhci.c linux-libre-4.4.7-gnu/drivers/usb/host/xhci.c
+--- linux-libre-4.4-gnu/drivers/usb/host/xhci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/host/xhci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1549,7 +1549,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+ xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+ "HW died, freeing TD.");
+ urb_priv = urb->hcpriv;
+- for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
++ for (i = urb_priv->td_cnt;
++ i < urb_priv->length && xhci->devs[urb->dev->slot_id];
++ i++) {
+ td = urb_priv->td[i];
+ if (!list_empty(&td->td_list))
+ list_del_init(&td->td_list);
+@@ -5059,6 +5061,10 @@ static int __init xhci_hcd_init(void)
+ BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
+ /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
+ BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
++
++ if (usb_disabled())
++ return -ENODEV;
++
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/host/xhci-pci.c linux-libre-4.4.7-gnu/drivers/usb/host/xhci-pci.c
+--- linux-libre-4.4-gnu/drivers/usb/host/xhci-pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/host/xhci-pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -28,7 +28,9 @@
+ #include "xhci.h"
+ #include "xhci-trace.h"
+
+-#define PORT2_SSIC_CONFIG_REG2 0x883c
++#define SSIC_PORT_NUM 2
++#define SSIC_PORT_CFG2 0x880c
++#define SSIC_PORT_CFG2_OFFSET 0x30
+ #define PROG_DONE (1 << 30)
+ #define SSIC_PORT_UNUSED (1 << 31)
+
+@@ -45,6 +47,7 @@
+ #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
+ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
+ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f
++#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8
+
+ static const char hcd_name[] = "xhci_hcd";
+
+@@ -152,7 +155,8 @@ static void xhci_pci_quirks(struct devic
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
+- pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
++ pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
++ pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) {
+ xhci->quirks |= XHCI_PME_STUCK_QUIRK;
+ }
+ if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
+@@ -322,28 +326,36 @@ static void xhci_pme_quirk(struct usb_hc
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ u32 val;
+ void __iomem *reg;
++ int i;
+
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+
+- reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
++ for (i = 0; i < SSIC_PORT_NUM; i++) {
++ reg = (void __iomem *) xhci->cap_regs +
++ SSIC_PORT_CFG2 +
++ i * SSIC_PORT_CFG2_OFFSET;
+
+- /* Notify SSIC that SSIC profile programming is not done */
+- val = readl(reg) & ~PROG_DONE;
+- writel(val, reg);
++ /*
++ * Notify SSIC that SSIC profile programming
++ * is not done.
++ */
++ val = readl(reg) & ~PROG_DONE;
++ writel(val, reg);
+
+- /* Mark SSIC port as unused(suspend) or used(resume) */
+- val = readl(reg);
+- if (suspend)
+- val |= SSIC_PORT_UNUSED;
+- else
+- val &= ~SSIC_PORT_UNUSED;
+- writel(val, reg);
++ /* Mark SSIC port as unused(suspend) or used(resume) */
++ val = readl(reg);
++ if (suspend)
++ val |= SSIC_PORT_UNUSED;
++ else
++ val &= ~SSIC_PORT_UNUSED;
++ writel(val, reg);
+
+- /* Notify SSIC that SSIC profile programming is done */
+- val = readl(reg) | PROG_DONE;
+- writel(val, reg);
+- readl(reg);
++ /* Notify SSIC that SSIC profile programming is done */
++ val = readl(reg) | PROG_DONE;
++ writel(val, reg);
++ readl(reg);
++ }
+ }
+
+ reg = (void __iomem *) xhci->cap_regs + 0x80a4;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/host/xhci-ring.c linux-libre-4.4.7-gnu/drivers/usb/host/xhci-ring.c
+--- linux-libre-4.4-gnu/drivers/usb/host/xhci-ring.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/host/xhci-ring.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2192,10 +2192,6 @@ static int process_bulk_intr_td(struct x
+ }
+ /* 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 -
+@@ -2247,12 +2243,6 @@ static int process_bulk_intr_td(struct x
+ 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);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/misc/iowarrior.c linux-libre-4.4.7-gnu/drivers/usb/misc/iowarrior.c
+--- linux-libre-4.4-gnu/drivers/usb/misc/iowarrior.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/misc/iowarrior.c 2016-04-12 12:09:26.000000000 -0400
+@@ -787,6 +787,12 @@ static int iowarrior_probe(struct usb_in
+ iface_desc = interface->cur_altsetting;
+ dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
+
++ if (iface_desc->desc.bNumEndpoints < 1) {
++ dev_err(&interface->dev, "Invalid number of endpoints\n");
++ retval = -EINVAL;
++ goto error;
++ }
++
+ /* set up the endpoint information */
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/phy/phy-msm-usb.c linux-libre-4.4.7-gnu/drivers/usb/phy/phy-msm-usb.c
+--- linux-libre-4.4-gnu/drivers/usb/phy/phy-msm-usb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/phy/phy-msm-usb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1599,6 +1599,8 @@ static int msm_otg_read_dt(struct platfo
+ &motg->id.nb);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "register ID notifier failed\n");
++ extcon_unregister_notifier(motg->vbus.extcon,
++ EXTCON_USB, &motg->vbus.nb);
+ return ret;
+ }
+
+@@ -1660,15 +1662,6 @@ static int msm_otg_probe(struct platform
+ if (!motg)
+ return -ENOMEM;
+
+- pdata = dev_get_platdata(&pdev->dev);
+- if (!pdata) {
+- if (!np)
+- return -ENXIO;
+- ret = msm_otg_read_dt(pdev, motg);
+- if (ret)
+- return ret;
+- }
+-
+ motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
+ GFP_KERNEL);
+ if (!motg->phy.otg)
+@@ -1710,6 +1703,15 @@ static int msm_otg_probe(struct platform
+ if (!motg->regs)
+ return -ENOMEM;
+
++ pdata = dev_get_platdata(&pdev->dev);
++ if (!pdata) {
++ if (!np)
++ return -ENXIO;
++ ret = msm_otg_read_dt(pdev, motg);
++ if (ret)
++ return ret;
++ }
++
+ /*
+ * NOTE: The PHYs can be multiplexed between the chipidea controller
+ * and the dwc3 controller, using a single bit. It is important that
+@@ -1717,8 +1719,10 @@ static int msm_otg_probe(struct platform
+ */
+ if (motg->phy_number) {
+ phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
+- if (!phy_select)
+- return -ENOMEM;
++ if (!phy_select) {
++ ret = -ENOMEM;
++ goto unregister_extcon;
++ }
+ /* Enable second PHY with the OTG port */
+ writel(0x1, phy_select);
+ }
+@@ -1728,7 +1732,8 @@ static int msm_otg_probe(struct platform
+ motg->irq = platform_get_irq(pdev, 0);
+ if (motg->irq < 0) {
+ dev_err(&pdev->dev, "platform_get_irq failed\n");
+- return motg->irq;
++ ret = motg->irq;
++ goto unregister_extcon;
+ }
+
+ regs[0].supply = "vddcx";
+@@ -1737,7 +1742,7 @@ static int msm_otg_probe(struct platform
+
+ ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs);
+ if (ret)
+- return ret;
++ goto unregister_extcon;
+
+ motg->vddcx = regs[0].consumer;
+ motg->v3p3 = regs[1].consumer;
+@@ -1834,6 +1839,12 @@ disable_clks:
+ clk_disable_unprepare(motg->clk);
+ if (!IS_ERR(motg->core_clk))
+ clk_disable_unprepare(motg->core_clk);
++unregister_extcon:
++ extcon_unregister_notifier(motg->id.extcon,
++ EXTCON_USB_HOST, &motg->id.nb);
++ extcon_unregister_notifier(motg->vbus.extcon,
++ EXTCON_USB, &motg->vbus.nb);
++
+ return ret;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/cp210x.c linux-libre-4.4.7-gnu/drivers/usb/serial/cp210x.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/cp210x.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/cp210x.c 2016-04-12 12:09:26.000000000 -0400
+@@ -98,6 +98,7 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
+ { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
+ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
++ { USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */
+ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
+ { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
+ { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
+@@ -160,6 +161,11 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
+ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
+ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
++ { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
++ { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
++ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
++ { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */
++ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
+ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
+ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
+ { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/cypress_m8.c linux-libre-4.4.7-gnu/drivers/usb/serial/cypress_m8.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/cypress_m8.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/cypress_m8.c 2016-04-12 12:09:26.000000000 -0400
+@@ -447,6 +447,11 @@ static int cypress_generic_port_probe(st
+ struct usb_serial *serial = port->serial;
+ struct cypress_private *priv;
+
++ if (!port->interrupt_out_urb || !port->interrupt_in_urb) {
++ dev_err(&port->dev, "required endpoint is missing\n");
++ return -ENODEV;
++ }
++
+ priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+@@ -606,12 +611,6 @@ static int cypress_open(struct tty_struc
+ cypress_set_termios(tty, port, &priv->tmp_termios);
+
+ /* setup the port and start reading from the device */
+- if (!port->interrupt_in_urb) {
+- dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n",
+- __func__);
+- return -1;
+- }
+-
+ usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
+ usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
+ port->interrupt_in_urb->transfer_buffer,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/digi_acceleport.c linux-libre-4.4.7-gnu/drivers/usb/serial/digi_acceleport.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/digi_acceleport.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/digi_acceleport.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1251,8 +1251,27 @@ static int digi_port_init(struct usb_ser
+
+ static int digi_startup(struct usb_serial *serial)
+ {
++ struct device *dev = &serial->interface->dev;
+ struct digi_serial *serial_priv;
+ int ret;
++ int i;
++
++ /* check whether the device has the expected number of endpoints */
++ if (serial->num_port_pointers < serial->type->num_ports + 1) {
++ dev_err(dev, "OOB endpoints missing\n");
++ return -ENODEV;
++ }
++
++ for (i = 0; i < serial->type->num_ports + 1 ; i++) {
++ if (!serial->port[i]->read_urb) {
++ dev_err(dev, "bulk-in endpoint missing\n");
++ return -ENODEV;
++ }
++ if (!serial->port[i]->write_urb) {
++ dev_err(dev, "bulk-out endpoint missing\n");
++ return -ENODEV;
++ }
++ }
+
+ serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+ if (!serial_priv)
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/ftdi_sio.c linux-libre-4.4.7-gnu/drivers/usb/serial/ftdi_sio.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/ftdi_sio.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/ftdi_sio.c 2016-04-12 12:09:26.000000000 -0400
+@@ -824,6 +824,7 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
++ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
+ { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
+
+ /* Papouch devices based on FTDI chip */
+@@ -1003,6 +1004,10 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) },
+ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) },
+ { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) },
++ /* ICP DAS I-756xU devices */
++ { USB_DEVICE(ICPDAS_VID, ICPDAS_I7560U_PID) },
++ { USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) },
++ { USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) },
+ { } /* Terminating entry */
+ };
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/ftdi_sio_ids.h linux-libre-4.4.7-gnu/drivers/usb/serial/ftdi_sio_ids.h
+--- linux-libre-4.4-gnu/drivers/usb/serial/ftdi_sio_ids.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/ftdi_sio_ids.h 2016-04-12 12:09:26.000000000 -0400
+@@ -615,6 +615,7 @@
+ */
+ #define RATOC_VENDOR_ID 0x0584
+ #define RATOC_PRODUCT_ID_USB60F 0xb020
++#define RATOC_PRODUCT_ID_SCU18 0xb03a
+
+ /*
+ * Infineon Technologies
+@@ -871,6 +872,14 @@
+ #define NOVITUS_BONO_E_PID 0x6010
+
+ /*
++ * ICPDAS I-756*U devices
++ */
++#define ICPDAS_VID 0x1b5c
++#define ICPDAS_I7560U_PID 0x0103
++#define ICPDAS_I7561U_PID 0x0104
++#define ICPDAS_I7563U_PID 0x0105
++
++/*
+ * RT Systems programming cables for various ham radios
+ */
+ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/mct_u232.c linux-libre-4.4.7-gnu/drivers/usb/serial/mct_u232.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/mct_u232.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/mct_u232.c 2016-04-12 12:09:26.000000000 -0400
+@@ -376,14 +376,21 @@ static void mct_u232_msr_to_state(struct
+
+ static int mct_u232_port_probe(struct usb_serial_port *port)
+ {
++ struct usb_serial *serial = port->serial;
+ struct mct_u232_private *priv;
+
++ /* check first to simplify error handling */
++ if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) {
++ dev_err(&port->dev, "expected endpoint missing\n");
++ return -ENODEV;
++ }
++
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ /* Use second interrupt-in endpoint for reading. */
+- priv->read_urb = port->serial->port[1]->interrupt_in_urb;
++ priv->read_urb = serial->port[1]->interrupt_in_urb;
+ priv->read_urb->context = port;
+
+ spin_lock_init(&priv->lock);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/option.c linux-libre-4.4.7-gnu/drivers/usb/serial/option.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/option.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/option.c 2016-04-12 12:09:26.000000000 -0400
+@@ -268,6 +268,9 @@ static void option_instat_callback(struc
+ #define TELIT_PRODUCT_CC864_SINGLE 0x1006
+ #define TELIT_PRODUCT_DE910_DUAL 0x1010
+ #define TELIT_PRODUCT_UE910_V2 0x1012
++#define TELIT_PRODUCT_LE922_USBCFG0 0x1042
++#define TELIT_PRODUCT_LE922_USBCFG3 0x1043
++#define TELIT_PRODUCT_LE922_USBCFG5 0x1045
+ #define TELIT_PRODUCT_LE920 0x1200
+ #define TELIT_PRODUCT_LE910 0x1201
+
+@@ -313,6 +316,7 @@ static void option_instat_callback(struc
+ #define TOSHIBA_PRODUCT_G450 0x0d45
+
+ #define ALINK_VENDOR_ID 0x1e0e
++#define SIMCOM_PRODUCT_SIM7100E 0x9001 /* Yes, ALINK_VENDOR_ID */
+ #define ALINK_PRODUCT_PH300 0x9100
+ #define ALINK_PRODUCT_3GU 0x9200
+
+@@ -605,6 +609,10 @@ static const struct option_blacklist_inf
+ .reserved = BIT(3) | BIT(4),
+ };
+
++static const struct option_blacklist_info simcom_sim7100e_blacklist = {
++ .reserved = BIT(5) | BIT(6),
++};
++
+ static const struct option_blacklist_info telit_le910_blacklist = {
+ .sendsetup = BIT(0),
+ .reserved = BIT(1) | BIT(2),
+@@ -615,6 +623,16 @@ static const struct option_blacklist_inf
+ .reserved = BIT(1) | BIT(5),
+ };
+
++static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = {
++ .sendsetup = BIT(2),
++ .reserved = BIT(0) | BIT(1) | BIT(3),
++};
++
++static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = {
++ .sendsetup = BIT(0),
++ .reserved = BIT(1) | BIT(2) | BIT(3),
++};
++
+ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+@@ -1110,9 +1128,13 @@ static const struct usb_device_id option
+ { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
+ { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
++ { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, 0x6001, 0xff, 0xff, 0xff), /* 4G LTE usb-modem U901 */
++ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
+ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
++ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
+@@ -1160,6 +1182,12 @@ static const struct usb_device_id option
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff),
++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
+ .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
+@@ -1629,6 +1657,8 @@ static const struct usb_device_id option
+ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+ { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
++ { USB_DEVICE(ALINK_VENDOR_ID, SIMCOM_PRODUCT_SIM7100E),
++ .driver_info = (kernel_ulong_t)&simcom_sim7100e_blacklist },
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
+ .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
+ },
+@@ -1679,7 +1709,7 @@ static const struct usb_device_id option
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+- { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
++ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
+@@ -1788,6 +1818,8 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
++ { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */
++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
+ { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/qcserial.c linux-libre-4.4.7-gnu/drivers/usb/serial/qcserial.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/qcserial.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/qcserial.c 2016-04-12 12:09:26.000000000 -0400
+@@ -157,14 +157,17 @@ static const struct usb_device_id id_tab
+ {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */
+ {DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */
+- {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx/EM74xx */
+- {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx/EM74xx */
++ {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */
++ {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */
++ {DEVICE_SWI(0x1199, 0x9078)}, /* Sierra Wireless EM74xx */
++ {DEVICE_SWI(0x1199, 0x9079)}, /* Sierra Wireless EM74xx */
+ {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81b1)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
++ {DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
+
+ /* Huawei devices */
+ {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/serial/visor.c linux-libre-4.4.7-gnu/drivers/usb/serial/visor.c
+--- linux-libre-4.4-gnu/drivers/usb/serial/visor.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/serial/visor.c 2016-04-12 12:09:26.000000000 -0400
+@@ -544,6 +544,11 @@ static int treo_attach(struct usb_serial
+ (serial->num_interrupt_in == 0))
+ return 0;
+
++ if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
++ dev_err(&serial->interface->dev, "missing endpoints\n");
++ return -ENODEV;
++ }
++
+ /*
+ * It appears that Treos and Kyoceras want to use the
+ * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
+@@ -597,8 +602,10 @@ static int clie_5_attach(struct usb_seri
+ */
+
+ /* some sanity check */
+- if (serial->num_ports < 2)
+- return -1;
++ if (serial->num_bulk_out < 2) {
++ dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
++ return -ENODEV;
++ }
+
+ /* port 0 now uses the modified endpoint Address */
+ port = serial->port[0];
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/usb/storage/uas.c linux-libre-4.4.7-gnu/drivers/usb/storage/uas.c
+--- linux-libre-4.4-gnu/drivers/usb/storage/uas.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/usb/storage/uas.c 2016-04-12 12:09:26.000000000 -0400
+@@ -812,7 +812,7 @@ static struct scsi_host_template uas_hos
+ .slave_configure = uas_slave_configure,
+ .eh_abort_handler = uas_eh_abort_handler,
+ .eh_bus_reset_handler = uas_eh_bus_reset_handler,
+- .can_queue = 65536, /* Is there a limit on the _host_ ? */
++ .can_queue = MAX_CMNDS,
+ .this_id = -1,
+ .sg_tablesize = SG_NONE,
+ .skip_settle_delay = 1,
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/vfio/pci/vfio_pci.c linux-libre-4.4.7-gnu/drivers/vfio/pci/vfio_pci.c
+--- linux-libre-4.4-gnu/drivers/vfio/pci/vfio_pci.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/vfio/pci/vfio_pci.c 2016-04-12 12:09:26.000000000 -0400
+@@ -446,7 +446,8 @@ static long vfio_pci_ioctl(void *device_
+ info.num_regions = VFIO_PCI_NUM_REGIONS;
+ info.num_irqs = VFIO_PCI_NUM_IRQS;
+
+- return copy_to_user((void __user *)arg, &info, minsz);
++ return copy_to_user((void __user *)arg, &info, minsz) ?
++ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+ struct pci_dev *pdev = vdev->pdev;
+@@ -520,7 +521,8 @@ static long vfio_pci_ioctl(void *device_
+ return -EINVAL;
+ }
+
+- return copy_to_user((void __user *)arg, &info, minsz);
++ return copy_to_user((void __user *)arg, &info, minsz) ?
++ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+ struct vfio_irq_info info;
+@@ -555,7 +557,8 @@ static long vfio_pci_ioctl(void *device_
+ else
+ info.flags |= VFIO_IRQ_INFO_NORESIZE;
+
+- return copy_to_user((void __user *)arg, &info, minsz);
++ return copy_to_user((void __user *)arg, &info, minsz) ?
++ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_SET_IRQS) {
+ struct vfio_irq_set hdr;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/vfio/platform/vfio_platform_common.c linux-libre-4.4.7-gnu/drivers/vfio/platform/vfio_platform_common.c
+--- linux-libre-4.4-gnu/drivers/vfio/platform/vfio_platform_common.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/vfio/platform/vfio_platform_common.c 2016-04-12 12:09:26.000000000 -0400
+@@ -219,7 +219,8 @@ static long vfio_platform_ioctl(void *de
+ info.num_regions = vdev->num_regions;
+ info.num_irqs = vdev->num_irqs;
+
+- return copy_to_user((void __user *)arg, &info, minsz);
++ return copy_to_user((void __user *)arg, &info, minsz) ?
++ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+ struct vfio_region_info info;
+@@ -240,7 +241,8 @@ static long vfio_platform_ioctl(void *de
+ info.size = vdev->regions[info.index].size;
+ info.flags = vdev->regions[info.index].flags;
+
+- return copy_to_user((void __user *)arg, &info, minsz);
++ return copy_to_user((void __user *)arg, &info, minsz) ?
++ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+ struct vfio_irq_info info;
+@@ -259,7 +261,8 @@ static long vfio_platform_ioctl(void *de
+ info.flags = vdev->irqs[info.index].flags;
+ info.count = vdev->irqs[info.index].count;
+
+- return copy_to_user((void __user *)arg, &info, minsz);
++ return copy_to_user((void __user *)arg, &info, minsz) ?
++ -EFAULT : 0;
+
+ } else if (cmd == VFIO_DEVICE_SET_IRQS) {
+ struct vfio_irq_set hdr;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/vfio/vfio_iommu_type1.c linux-libre-4.4.7-gnu/drivers/vfio/vfio_iommu_type1.c
+--- linux-libre-4.4-gnu/drivers/vfio/vfio_iommu_type1.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/vfio/vfio_iommu_type1.c 2016-04-12 12:09:26.000000000 -0400
+@@ -999,7 +999,8 @@ static long vfio_iommu_type1_ioctl(void
+
+ info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
+
+- return copy_to_user((void __user *)arg, &info, minsz);
++ return copy_to_user((void __user *)arg, &info, minsz) ?
++ -EFAULT : 0;
+
+ } else if (cmd == VFIO_IOMMU_MAP_DMA) {
+ struct vfio_iommu_type1_dma_map map;
+@@ -1032,7 +1033,8 @@ static long vfio_iommu_type1_ioctl(void
+ if (ret)
+ return ret;
+
+- return copy_to_user((void __user *)arg, &unmap, minsz);
++ return copy_to_user((void __user *)arg, &unmap, minsz) ?
++ -EFAULT : 0;
+ }
+
+ return -ENOTTY;
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/video/console/fbcon.c linux-libre-4.4.7-gnu/drivers/video/console/fbcon.c
+--- linux-libre-4.4-gnu/drivers/video/console/fbcon.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/video/console/fbcon.c 2016-04-12 12:09:26.000000000 -0400
+@@ -709,6 +709,7 @@ static int con2fb_acquire_newinfo(struct
+ }
+
+ if (!err) {
++ ops->cur_blink_jiffies = HZ / 5;
+ info->fbcon_par = ops;
+
+ if (vc)
+@@ -956,6 +957,7 @@ static const char *fbcon_startup(void)
+ ops->currcon = -1;
+ ops->graphics = 1;
+ ops->cur_rotate = -1;
++ ops->cur_blink_jiffies = HZ / 5;
+ info->fbcon_par = ops;
+ p->con_rotate = initial_rotation;
+ set_blitting_type(vc, info);
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/virtio/virtio_balloon.c linux-libre-4.4.7-gnu/drivers/virtio/virtio_balloon.c
+--- linux-libre-4.4-gnu/drivers/virtio/virtio_balloon.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/virtio/virtio_balloon.c 2016-04-12 12:09:26.000000000 -0400
+@@ -209,8 +209,8 @@ static unsigned leak_balloon(struct virt
+ */
+ if (vb->num_pfns != 0)
+ tell_host(vb, vb->deflate_vq);
+- mutex_unlock(&vb->balloon_lock);
+ release_pages_balloon(vb);
++ mutex_unlock(&vb->balloon_lock);
+ return num_freed_pages;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/virtio/virtio_pci_common.c linux-libre-4.4.7-gnu/drivers/virtio/virtio_pci_common.c
+--- linux-libre-4.4-gnu/drivers/virtio/virtio_pci_common.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/virtio/virtio_pci_common.c 2016-04-12 12:09:26.000000000 -0400
+@@ -545,6 +545,7 @@ err_enable_device:
+ static void virtio_pci_remove(struct pci_dev *pci_dev)
+ {
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
++ struct device *dev = get_device(&vp_dev->vdev.dev);
+
+ unregister_virtio_device(&vp_dev->vdev);
+
+@@ -554,6 +555,7 @@ static void virtio_pci_remove(struct pci
+ virtio_pci_modern_remove(vp_dev);
+
+ pci_disable_device(pci_dev);
++ put_device(dev);
+ }
+
+ static struct pci_driver virtio_pci_driver = {
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/watchdog/rc32434_wdt.c linux-libre-4.4.7-gnu/drivers/watchdog/rc32434_wdt.c
+--- linux-libre-4.4-gnu/drivers/watchdog/rc32434_wdt.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/watchdog/rc32434_wdt.c 2016-04-12 12:09:26.000000000 -0400
+@@ -237,7 +237,7 @@ static long rc32434_wdt_ioctl(struct fil
+ return -EINVAL;
+ /* Fall through */
+ case WDIOC_GETTIMEOUT:
+- return copy_to_user(argp, &timeout, sizeof(int));
++ return copy_to_user(argp, &timeout, sizeof(int)) ? -EFAULT : 0;
+ default:
+ return -ENOTTY;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/xen/xen-pciback/pciback_ops.c linux-libre-4.4.7-gnu/drivers/xen/xen-pciback/pciback_ops.c
+--- linux-libre-4.4-gnu/drivers/xen/xen-pciback/pciback_ops.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/xen/xen-pciback/pciback_ops.c 2016-04-12 12:09:26.000000000 -0400
+@@ -227,8 +227,9 @@ int xen_pcibk_enable_msix(struct xen_pci
+ /*
+ * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able
+ * to access the BARs where the MSI-X entries reside.
++ * But VF devices are unique in which the PF needs to be checked.
+ */
+- pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ pci_read_config_word(pci_physfn(dev), PCI_COMMAND, &cmd);
+ if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY))
+ return -ENXIO;
+
+@@ -332,6 +333,9 @@ void xen_pcibk_do_op(struct work_struct
+ struct xen_pcibk_dev_data *dev_data = NULL;
+ struct xen_pci_op *op = &pdev->op;
+ int test_intx = 0;
++#ifdef CONFIG_PCI_MSI
++ unsigned int nr = 0;
++#endif
+
+ *op = pdev->sh_info->op;
+ barrier();
+@@ -360,6 +364,7 @@ void xen_pcibk_do_op(struct work_struct
+ op->err = xen_pcibk_disable_msi(pdev, dev, op);
+ break;
+ case XEN_PCI_OP_enable_msix:
++ nr = op->value;
+ op->err = xen_pcibk_enable_msix(pdev, dev, op);
+ break;
+ case XEN_PCI_OP_disable_msix:
+@@ -382,7 +387,7 @@ void xen_pcibk_do_op(struct work_struct
+ if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) {
+ unsigned int i;
+
+- for (i = 0; i < op->value; i++)
++ for (i = 0; i < nr; i++)
+ pdev->sh_info->op.msix_entries[i].vector =
+ op->msix_entries[i].vector;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/drivers/xen/xen-scsiback.c linux-libre-4.4.7-gnu/drivers/xen/xen-scsiback.c
+--- linux-libre-4.4-gnu/drivers/xen/xen-scsiback.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/drivers/xen/xen-scsiback.c 2016-04-12 12:09:26.000000000 -0400
+@@ -939,12 +939,12 @@ out:
+ spin_unlock_irqrestore(&info->v2p_lock, flags);
+
+ out_free:
+- mutex_lock(&tpg->tv_tpg_mutex);
+- tpg->tv_tpg_fe_count--;
+- mutex_unlock(&tpg->tv_tpg_mutex);
+-
+- if (err)
++ if (err) {
++ mutex_lock(&tpg->tv_tpg_mutex);
++ tpg->tv_tpg_fe_count--;
++ mutex_unlock(&tpg->tv_tpg_mutex);
+ kfree(new);
++ }
+
+ return err;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/async-thread.c linux-libre-4.4.7-gnu/fs/btrfs/async-thread.c
+--- linux-libre-4.4-gnu/fs/btrfs/async-thread.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/async-thread.c 2016-04-12 12:09:26.000000000 -0400
+@@ -328,8 +328,8 @@ static inline void __btrfs_queue_work(st
+ list_add_tail(&work->ordered_list, &wq->ordered_list);
+ spin_unlock_irqrestore(&wq->list_lock, flags);
+ }
+- queue_work(wq->normal_wq, &work->normal_work);
+ trace_btrfs_work_queued(work);
++ queue_work(wq->normal_wq, &work->normal_work);
+ }
+
+ void btrfs_queue_work(struct btrfs_workqueue *wq,
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/backref.c linux-libre-4.4.7-gnu/fs/btrfs/backref.c
+--- linux-libre-4.4-gnu/fs/btrfs/backref.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/backref.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1417,7 +1417,8 @@ char *btrfs_ref_to_path(struct btrfs_roo
+ read_extent_buffer(eb, dest + bytes_left,
+ name_off, name_len);
+ if (eb != eb_in) {
+- btrfs_tree_read_unlock_blocking(eb);
++ if (!path->skip_locking)
++ btrfs_tree_read_unlock_blocking(eb);
+ free_extent_buffer(eb);
+ }
+ ret = btrfs_find_item(fs_root, path, parent, 0,
+@@ -1437,9 +1438,10 @@ char *btrfs_ref_to_path(struct btrfs_roo
+ eb = path->nodes[0];
+ /* make sure we can use eb after releasing the path */
+ if (eb != eb_in) {
+- atomic_inc(&eb->refs);
+- btrfs_tree_read_lock(eb);
+- btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
++ if (!path->skip_locking)
++ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
++ path->nodes[0] = NULL;
++ path->locks[0] = 0;
+ }
+ btrfs_release_path(path);
+ iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/ctree.h linux-libre-4.4.7-gnu/fs/btrfs/ctree.h
+--- linux-libre-4.4-gnu/fs/btrfs/ctree.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/ctree.h 2016-04-12 12:09:26.000000000 -0400
+@@ -1572,7 +1572,7 @@ struct btrfs_fs_info {
+
+ spinlock_t delayed_iput_lock;
+ struct list_head delayed_iputs;
+- struct rw_semaphore delayed_iput_sem;
++ struct mutex cleaner_delayed_iput_mutex;
+
+ /* this protects tree_mod_seq_list */
+ spinlock_t tree_mod_seq_lock;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/delayed-inode.c linux-libre-4.4.7-gnu/fs/btrfs/delayed-inode.c
+--- linux-libre-4.4-gnu/fs/btrfs/delayed-inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/delayed-inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1694,7 +1694,7 @@ int btrfs_should_delete_dir_index(struct
+ *
+ */
+ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
+- struct list_head *ins_list)
++ struct list_head *ins_list, bool *emitted)
+ {
+ struct btrfs_dir_item *di;
+ struct btrfs_delayed_item *curr, *next;
+@@ -1738,6 +1738,7 @@ int btrfs_readdir_delayed_dir_index(stru
+
+ if (over)
+ return 1;
++ *emitted = true;
+ }
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/delayed-inode.h linux-libre-4.4.7-gnu/fs/btrfs/delayed-inode.h
+--- linux-libre-4.4-gnu/fs/btrfs/delayed-inode.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/delayed-inode.h 2016-04-12 12:09:26.000000000 -0400
+@@ -144,7 +144,7 @@ void btrfs_put_delayed_items(struct list
+ int btrfs_should_delete_dir_index(struct list_head *del_list,
+ u64 index);
+ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
+- struct list_head *ins_list);
++ struct list_head *ins_list, bool *emitted);
+
+ /* for init */
+ int __init btrfs_delayed_inode_init(void);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/disk-io.c linux-libre-4.4.7-gnu/fs/btrfs/disk-io.c
+--- linux-libre-4.4-gnu/fs/btrfs/disk-io.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/disk-io.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1582,8 +1582,23 @@ int btrfs_init_fs_root(struct btrfs_root
+ ret = get_anon_bdev(&root->anon_dev);
+ if (ret)
+ goto free_writers;
++
++ mutex_lock(&root->objectid_mutex);
++ ret = btrfs_find_highest_objectid(root,
++ &root->highest_objectid);
++ if (ret) {
++ mutex_unlock(&root->objectid_mutex);
++ goto free_root_dev;
++ }
++
++ ASSERT(root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);
++
++ mutex_unlock(&root->objectid_mutex);
++
+ return 0;
+
++free_root_dev:
++ free_anon_bdev(root->anon_dev);
+ free_writers:
+ btrfs_free_subvolume_writers(root->subv_writers);
+ fail:
+@@ -1762,7 +1777,6 @@ static int cleaner_kthread(void *arg)
+ int again;
+ struct btrfs_trans_handle *trans;
+
+- set_freezable();
+ do {
+ again = 0;
+
+@@ -1782,7 +1796,10 @@ static int cleaner_kthread(void *arg)
+ goto sleep;
+ }
+
++ mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex);
+ btrfs_run_delayed_iputs(root);
++ mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex);
++
+ again = btrfs_clean_one_deleted_snapshot(root);
+ mutex_unlock(&root->fs_info->cleaner_mutex);
+
+@@ -2542,8 +2559,8 @@ int open_ctree(struct super_block *sb,
+ mutex_init(&fs_info->delete_unused_bgs_mutex);
+ mutex_init(&fs_info->reloc_mutex);
+ mutex_init(&fs_info->delalloc_root_mutex);
++ mutex_init(&fs_info->cleaner_delayed_iput_mutex);
+ seqlock_init(&fs_info->profiles_lock);
+- init_rwsem(&fs_info->delayed_iput_sem);
+
+ INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
+ INIT_LIST_HEAD(&fs_info->space_info);
+@@ -2668,6 +2685,7 @@ int open_ctree(struct super_block *sb,
+ if (btrfs_check_super_csum(bh->b_data)) {
+ printk(KERN_ERR "BTRFS: superblock checksum mismatch\n");
+ err = -EINVAL;
++ brelse(bh);
+ goto fail_alloc;
+ }
+
+@@ -2900,6 +2918,18 @@ retry_root_backup:
+ tree_root->commit_root = btrfs_root_node(tree_root);
+ btrfs_set_root_refs(&tree_root->root_item, 1);
+
++ mutex_lock(&tree_root->objectid_mutex);
++ ret = btrfs_find_highest_objectid(tree_root,
++ &tree_root->highest_objectid);
++ if (ret) {
++ mutex_unlock(&tree_root->objectid_mutex);
++ goto recovery_tree_root;
++ }
++
++ ASSERT(tree_root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);
++
++ mutex_unlock(&tree_root->objectid_mutex);
++
+ ret = btrfs_read_roots(fs_info, tree_root);
+ if (ret)
+ goto recovery_tree_root;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/extent-tree.c linux-libre-4.4.7-gnu/fs/btrfs/extent-tree.c
+--- linux-libre-4.4-gnu/fs/btrfs/extent-tree.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/extent-tree.c 2016-04-12 12:09:26.000000000 -0400
+@@ -4086,8 +4086,10 @@ commit_trans:
+ !atomic_read(&root->fs_info->open_ioctl_trans)) {
+ need_commit--;
+
+- if (need_commit > 0)
++ if (need_commit > 0) {
++ btrfs_start_delalloc_roots(fs_info, 0, -1);
+ btrfs_wait_ordered_roots(fs_info, -1);
++ }
+
+ trans = btrfs_join_transaction(root);
+ if (IS_ERR(trans))
+@@ -4100,11 +4102,12 @@ commit_trans:
+ if (ret)
+ return ret;
+ /*
+- * make sure that all running delayed iput are
+- * done
++ * The cleaner kthread might still be doing iput
++ * operations. Wait for it to finish so that
++ * more space is released.
+ */
+- down_write(&root->fs_info->delayed_iput_sem);
+- up_write(&root->fs_info->delayed_iput_sem);
++ mutex_lock(&root->fs_info->cleaner_delayed_iput_mutex);
++ mutex_unlock(&root->fs_info->cleaner_delayed_iput_mutex);
+ goto again;
+ } else {
+ btrfs_end_transaction(trans, root);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/inode.c linux-libre-4.4.7-gnu/fs/btrfs/inode.c
+--- linux-libre-4.4-gnu/fs/btrfs/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3142,8 +3142,6 @@ void btrfs_run_delayed_iputs(struct btrf
+ if (empty)
+ return;
+
+- down_read(&fs_info->delayed_iput_sem);
+-
+ spin_lock(&fs_info->delayed_iput_lock);
+ list_splice_init(&fs_info->delayed_iputs, &list);
+ spin_unlock(&fs_info->delayed_iput_lock);
+@@ -3154,8 +3152,6 @@ void btrfs_run_delayed_iputs(struct btrf
+ iput(delayed->inode);
+ kfree(delayed);
+ }
+-
+- up_read(&root->fs_info->delayed_iput_sem);
+ }
+
+ /*
+@@ -5741,6 +5737,7 @@ static int btrfs_real_readdir(struct fil
+ char *name_ptr;
+ int name_len;
+ int is_curr = 0; /* ctx->pos points to the current index? */
++ bool emitted;
+
+ /* FIXME, use a real flag for deciding about the key type */
+ if (root->fs_info->tree_root == root)
+@@ -5769,6 +5766,7 @@ static int btrfs_real_readdir(struct fil
+ if (ret < 0)
+ goto err;
+
++ emitted = false;
+ while (1) {
+ leaf = path->nodes[0];
+ slot = path->slots[0];
+@@ -5848,6 +5846,7 @@ skip:
+
+ if (over)
+ goto nopos;
++ emitted = true;
+ di_len = btrfs_dir_name_len(leaf, di) +
+ btrfs_dir_data_len(leaf, di) + sizeof(*di);
+ di_cur += di_len;
+@@ -5860,11 +5859,20 @@ next:
+ if (key_type == BTRFS_DIR_INDEX_KEY) {
+ if (is_curr)
+ ctx->pos++;
+- ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
++ ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
+ if (ret)
+ goto nopos;
+ }
+
++ /*
++ * If we haven't emitted any dir entry, we must not touch ctx->pos as
++ * it was was set to the termination value in previous call. We assume
++ * that "." and ".." were emitted if we reach this point and set the
++ * termination value as well for an empty directory.
++ */
++ if (ctx->pos > 2 && !emitted)
++ goto nopos;
++
+ /* Reached end of directory/root. Bump pos past the last item. */
+ ctx->pos++;
+
+@@ -6481,7 +6489,7 @@ out_unlock_inode:
+ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+ {
+- struct btrfs_trans_handle *trans;
++ struct btrfs_trans_handle *trans = NULL;
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct inode *inode = d_inode(old_dentry);
+ u64 index;
+@@ -6507,6 +6515,7 @@ static int btrfs_link(struct dentry *old
+ trans = btrfs_start_transaction(root, 5);
+ if (IS_ERR(trans)) {
+ err = PTR_ERR(trans);
++ trans = NULL;
+ goto fail;
+ }
+
+@@ -6540,9 +6549,10 @@ static int btrfs_link(struct dentry *old
+ btrfs_log_new_name(trans, inode, NULL, parent);
+ }
+
+- btrfs_end_transaction(trans, root);
+ btrfs_balance_delayed_items(root);
+ fail:
++ if (trans)
++ btrfs_end_transaction(trans, root);
+ if (drop_inode) {
+ inode_dec_link_count(inode);
+ iput(inode);
+@@ -7985,6 +7995,7 @@ static void btrfs_endio_direct_read(stru
+
+ kfree(dip);
+
++ dio_bio->bi_error = bio->bi_error;
+ dio_end_io(dio_bio, bio->bi_error);
+
+ if (io_bio->end_io)
+@@ -8030,6 +8041,7 @@ out_test:
+
+ kfree(dip);
+
++ dio_bio->bi_error = bio->bi_error;
+ dio_end_io(dio_bio, bio->bi_error);
+ bio_put(bio);
+ }
+@@ -8534,15 +8546,28 @@ int btrfs_readpage(struct file *file, st
+ static int btrfs_writepage(struct page *page, struct writeback_control *wbc)
+ {
+ struct extent_io_tree *tree;
+-
++ struct inode *inode = page->mapping->host;
++ int ret;
+
+ if (current->flags & PF_MEMALLOC) {
+ redirty_page_for_writepage(wbc, page);
+ unlock_page(page);
+ return 0;
+ }
++
++ /*
++ * If we are under memory pressure we will call this directly from the
++ * VM, we need to make sure we have the inode referenced for the ordered
++ * extent. If not just return like we didn't do anything.
++ */
++ if (!igrab(inode)) {
++ redirty_page_for_writepage(wbc, page);
++ return AOP_WRITEPAGE_ACTIVATE;
++ }
+ tree = &BTRFS_I(page->mapping->host)->io_tree;
+- return extent_write_full_page(tree, page, btrfs_get_extent, wbc);
++ ret = extent_write_full_page(tree, page, btrfs_get_extent, wbc);
++ btrfs_add_delayed_iput(inode);
++ return ret;
+ }
+
+ static int btrfs_writepages(struct address_space *mapping,
+@@ -9636,9 +9661,11 @@ static int btrfs_symlink(struct inode *d
+ /*
+ * 2 items for inode item and ref
+ * 2 items for dir items
++ * 1 item for updating parent inode item
++ * 1 item for the inline extent item
+ * 1 item for xattr if selinux is on
+ */
+- trans = btrfs_start_transaction(root, 5);
++ trans = btrfs_start_transaction(root, 7);
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/inode-map.c linux-libre-4.4.7-gnu/fs/btrfs/inode-map.c
+--- linux-libre-4.4-gnu/fs/btrfs/inode-map.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/inode-map.c 2016-04-12 12:09:26.000000000 -0400
+@@ -515,7 +515,7 @@ out:
+ return ret;
+ }
+
+-static int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
++int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
+ {
+ struct btrfs_path *path;
+ int ret;
+@@ -555,13 +555,6 @@ int btrfs_find_free_objectid(struct btrf
+ int ret;
+ mutex_lock(&root->objectid_mutex);
+
+- if (unlikely(root->highest_objectid < BTRFS_FIRST_FREE_OBJECTID)) {
+- ret = btrfs_find_highest_objectid(root,
+- &root->highest_objectid);
+- if (ret)
+- goto out;
+- }
+-
+ if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) {
+ ret = -ENOSPC;
+ goto out;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/inode-map.h linux-libre-4.4.7-gnu/fs/btrfs/inode-map.h
+--- linux-libre-4.4-gnu/fs/btrfs/inode-map.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/inode-map.h 2016-04-12 12:09:26.000000000 -0400
+@@ -9,5 +9,6 @@ int btrfs_save_ino_cache(struct btrfs_ro
+ struct btrfs_trans_handle *trans);
+
+ int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid);
++int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid);
+
+ #endif
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/ioctl.c linux-libre-4.4.7-gnu/fs/btrfs/ioctl.c
+--- linux-libre-4.4-gnu/fs/btrfs/ioctl.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/ioctl.c 2016-04-12 12:09:26.000000000 -0400
+@@ -568,6 +568,10 @@ static noinline int create_subvol(struct
+ goto fail;
+ }
+
++ mutex_lock(&new_root->objectid_mutex);
++ new_root->highest_objectid = new_dirid;
++ mutex_unlock(&new_root->objectid_mutex);
++
+ /*
+ * insert the directory item
+ */
+@@ -2782,24 +2786,29 @@ out:
+ static struct page *extent_same_get_page(struct inode *inode, pgoff_t index)
+ {
+ struct page *page;
+- struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
+
+ page = grab_cache_page(inode->i_mapping, index);
+ if (!page)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ if (!PageUptodate(page)) {
+- if (extent_read_full_page_nolock(tree, page, btrfs_get_extent,
+- 0))
+- return NULL;
++ int ret;
++
++ ret = btrfs_readpage(NULL, page);
++ if (ret)
++ return ERR_PTR(ret);
+ lock_page(page);
+ if (!PageUptodate(page)) {
+ unlock_page(page);
+ page_cache_release(page);
+- return NULL;
++ return ERR_PTR(-EIO);
++ }
++ if (page->mapping != inode->i_mapping) {
++ unlock_page(page);
++ page_cache_release(page);
++ return ERR_PTR(-EAGAIN);
+ }
+ }
+- unlock_page(page);
+
+ return page;
+ }
+@@ -2811,17 +2820,31 @@ static int gather_extent_pages(struct in
+ pgoff_t index = off >> PAGE_CACHE_SHIFT;
+
+ for (i = 0; i < num_pages; i++) {
++again:
+ pages[i] = extent_same_get_page(inode, index + i);
+- if (!pages[i])
+- return -ENOMEM;
++ if (IS_ERR(pages[i])) {
++ int err = PTR_ERR(pages[i]);
++
++ if (err == -EAGAIN)
++ goto again;
++ pages[i] = NULL;
++ return err;
++ }
+ }
+ return 0;
+ }
+
+-static inline void lock_extent_range(struct inode *inode, u64 off, u64 len)
++static int lock_extent_range(struct inode *inode, u64 off, u64 len,
++ bool retry_range_locking)
+ {
+- /* do any pending delalloc/csum calc on src, one way or
+- another, and lock file content */
++ /*
++ * Do any pending delalloc/csum calculations on inode, one way or
++ * another, and lock file content.
++ * The locking order is:
++ *
++ * 1) pages
++ * 2) range in the inode's io tree
++ */
+ while (1) {
+ struct btrfs_ordered_extent *ordered;
+ lock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
+@@ -2839,8 +2862,11 @@ static inline void lock_extent_range(str
+ unlock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
+ if (ordered)
+ btrfs_put_ordered_extent(ordered);
++ if (!retry_range_locking)
++ return -EAGAIN;
+ btrfs_wait_ordered_range(inode, off, len);
+ }
++ return 0;
+ }
+
+ static void btrfs_double_inode_unlock(struct inode *inode1, struct inode *inode2)
+@@ -2865,15 +2891,24 @@ static void btrfs_double_extent_unlock(s
+ unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1);
+ }
+
+-static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
+- struct inode *inode2, u64 loff2, u64 len)
++static int btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
++ struct inode *inode2, u64 loff2, u64 len,
++ bool retry_range_locking)
+ {
++ int ret;
++
+ if (inode1 < inode2) {
+ swap(inode1, inode2);
+ swap(loff1, loff2);
+ }
+- lock_extent_range(inode1, loff1, len);
+- lock_extent_range(inode2, loff2, len);
++ ret = lock_extent_range(inode1, loff1, len, retry_range_locking);
++ if (ret)
++ return ret;
++ ret = lock_extent_range(inode2, loff2, len, retry_range_locking);
++ if (ret)
++ unlock_extent(&BTRFS_I(inode1)->io_tree, loff1,
++ loff1 + len - 1);
++ return ret;
+ }
+
+ struct cmp_pages {
+@@ -2889,11 +2924,15 @@ static void btrfs_cmp_data_free(struct c
+
+ for (i = 0; i < cmp->num_pages; i++) {
+ pg = cmp->src_pages[i];
+- if (pg)
++ if (pg) {
++ unlock_page(pg);
+ page_cache_release(pg);
++ }
+ pg = cmp->dst_pages[i];
+- if (pg)
++ if (pg) {
++ unlock_page(pg);
+ page_cache_release(pg);
++ }
+ }
+ kfree(cmp->src_pages);
+ kfree(cmp->dst_pages);
+@@ -2954,6 +2993,8 @@ static int btrfs_cmp_data(struct inode *
+
+ src_page = cmp->src_pages[i];
+ dst_page = cmp->dst_pages[i];
++ ASSERT(PageLocked(src_page));
++ ASSERT(PageLocked(dst_page));
+
+ addr = kmap_atomic(src_page);
+ dst_addr = kmap_atomic(dst_page);
+@@ -3066,14 +3107,46 @@ static int btrfs_extent_same(struct inod
+ goto out_unlock;
+ }
+
++again:
+ ret = btrfs_cmp_data_prepare(src, loff, dst, dst_loff, olen, &cmp);
+ if (ret)
+ goto out_unlock;
+
+ if (same_inode)
+- lock_extent_range(src, same_lock_start, same_lock_len);
++ ret = lock_extent_range(src, same_lock_start, same_lock_len,
++ false);
+ else
+- btrfs_double_extent_lock(src, loff, dst, dst_loff, len);
++ ret = btrfs_double_extent_lock(src, loff, dst, dst_loff, len,
++ false);
++ /*
++ * If one of the inodes has dirty pages in the respective range or
++ * ordered extents, we need to flush dellaloc and wait for all ordered
++ * extents in the range. We must unlock the pages and the ranges in the
++ * io trees to avoid deadlocks when flushing delalloc (requires locking
++ * pages) and when waiting for ordered extents to complete (they require
++ * range locking).
++ */
++ if (ret == -EAGAIN) {
++ /*
++ * Ranges in the io trees already unlocked. Now unlock all
++ * pages before waiting for all IO to complete.
++ */
++ btrfs_cmp_data_free(&cmp);
++ if (same_inode) {
++ btrfs_wait_ordered_range(src, same_lock_start,
++ same_lock_len);
++ } else {
++ btrfs_wait_ordered_range(src, loff, len);
++ btrfs_wait_ordered_range(dst, dst_loff, len);
++ }
++ goto again;
++ }
++ ASSERT(ret == 0);
++ if (WARN_ON(ret)) {
++ /* ranges in the io trees already unlocked */
++ btrfs_cmp_data_free(&cmp);
++ return ret;
++ }
+
+ /* pass original length for comparison so we stay within i_size */
+ ret = btrfs_cmp_data(src, loff, dst, dst_loff, olen, &cmp);
+@@ -3895,9 +3968,15 @@ static noinline long btrfs_ioctl_clone(s
+ u64 lock_start = min_t(u64, off, destoff);
+ u64 lock_len = max_t(u64, off, destoff) + len - lock_start;
+
+- lock_extent_range(src, lock_start, lock_len);
++ ret = lock_extent_range(src, lock_start, lock_len, true);
+ } else {
+- btrfs_double_extent_lock(src, off, inode, destoff, len);
++ ret = btrfs_double_extent_lock(src, off, inode, destoff, len,
++ true);
++ }
++ ASSERT(ret == 0);
++ if (WARN_ON(ret)) {
++ /* ranges in the io trees already unlocked */
++ goto out_unlock;
+ }
+
+ ret = btrfs_clone(src, inode, off, olen, len, destoff, 0);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/root-tree.c linux-libre-4.4.7-gnu/fs/btrfs/root-tree.c
+--- linux-libre-4.4-gnu/fs/btrfs/root-tree.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/root-tree.c 2016-04-12 12:09:26.000000000 -0400
+@@ -310,8 +310,16 @@ int btrfs_find_orphan_roots(struct btrfs
+ set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
+
+ err = btrfs_insert_fs_root(root->fs_info, root);
++ /*
++ * The root might have been inserted already, as before we look
++ * for orphan roots, log replay might have happened, which
++ * triggers a transaction commit and qgroup accounting, which
++ * in turn reads and inserts fs roots while doing backref
++ * walking.
++ */
++ if (err == -EEXIST)
++ err = 0;
+ if (err) {
+- BUG_ON(err == -EEXIST);
+ btrfs_free_fs_root(root);
+ break;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/send.c linux-libre-4.4.7-gnu/fs/btrfs/send.c
+--- linux-libre-4.4-gnu/fs/btrfs/send.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/send.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1469,7 +1469,21 @@ static int read_symlink(struct btrfs_roo
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0)
+ goto out;
+- BUG_ON(ret);
++ if (ret) {
++ /*
++ * An empty symlink inode. Can happen in rare error paths when
++ * creating a symlink (transaction committed before the inode
++ * eviction handler removed the symlink inode items and a crash
++ * happened in between or the subvol was snapshoted in between).
++ * Print an informative message to dmesg/syslog so that the user
++ * can delete the symlink.
++ */
++ btrfs_err(root->fs_info,
++ "Found empty symlink inode %llu at root %llu",
++ ino, root->root_key.objectid);
++ ret = -EIO;
++ goto out;
++ }
+
+ ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
+ struct btrfs_file_extent_item);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/super.c linux-libre-4.4.7-gnu/fs/btrfs/super.c
+--- linux-libre-4.4-gnu/fs/btrfs/super.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/super.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1956,6 +1956,8 @@ static int btrfs_calc_avail_data_space(s
+ * there are other factors that may change the result (like a new metadata
+ * chunk).
+ *
++ * If metadata is exhausted, f_bavail will be 0.
++ *
+ * FIXME: not accurate for mixed block groups, total and free/used are ok,
+ * available appears slightly larger.
+ */
+@@ -1967,11 +1969,13 @@ static int btrfs_statfs(struct dentry *d
+ struct btrfs_space_info *found;
+ u64 total_used = 0;
+ u64 total_free_data = 0;
++ u64 total_free_meta = 0;
+ int bits = dentry->d_sb->s_blocksize_bits;
+ __be32 *fsid = (__be32 *)fs_info->fsid;
+ unsigned factor = 1;
+ struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
+ int ret;
++ u64 thresh = 0;
+
+ /*
+ * holding chunk_muext to avoid allocating new chunks, holding
+@@ -1997,6 +2001,8 @@ static int btrfs_statfs(struct dentry *d
+ }
+ }
+ }
++ if (found->flags & BTRFS_BLOCK_GROUP_METADATA)
++ total_free_meta += found->disk_total - found->disk_used;
+
+ total_used += found->disk_used;
+ }
+@@ -2019,6 +2025,24 @@ static int btrfs_statfs(struct dentry *d
+ buf->f_bavail += div_u64(total_free_data, factor);
+ buf->f_bavail = buf->f_bavail >> bits;
+
++ /*
++ * We calculate the remaining metadata space minus global reserve. If
++ * this is (supposedly) smaller than zero, there's no space. But this
++ * does not hold in practice, the exhausted state happens where's still
++ * some positive delta. So we apply some guesswork and compare the
++ * delta to a 4M threshold. (Practically observed delta was ~2M.)
++ *
++ * We probably cannot calculate the exact threshold value because this
++ * depends on the internal reservations requested by various
++ * operations, so some operations that consume a few metadata will
++ * succeed even if the Avail is zero. But this is better than the other
++ * way around.
++ */
++ thresh = 4 * 1024 * 1024;
++
++ if (total_free_meta - thresh < block_rsv->size)
++ buf->f_bavail = 0;
++
+ buf->f_type = BTRFS_SUPER_MAGIC;
+ buf->f_bsize = dentry->d_sb->s_blocksize;
+ buf->f_namelen = BTRFS_NAME_LEN;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/btrfs/volumes.c linux-libre-4.4.7-gnu/fs/btrfs/volumes.c
+--- linux-libre-4.4-gnu/fs/btrfs/volumes.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/btrfs/volumes.c 2016-04-12 12:09:26.000000000 -0400
+@@ -232,6 +232,7 @@ static struct btrfs_device *__alloc_devi
+ spin_lock_init(&dev->reada_lock);
+ atomic_set(&dev->reada_in_flight, 0);
+ atomic_set(&dev->dev_stats_ccnt, 0);
++ btrfs_device_data_ordered_init(dev);
+ INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+ INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+
+@@ -1257,6 +1258,15 @@ int find_free_dev_extent_start(struct bt
+ int ret;
+ int slot;
+ struct extent_buffer *l;
++ u64 min_search_start;
++
++ /*
++ * We don't want to overwrite the superblock on the drive nor any area
++ * used by the boot loader (grub for example), so we make sure to start
++ * at an offset of at least 1MB.
++ */
++ min_search_start = max(root->fs_info->alloc_start, 1024ull * 1024);
++ search_start = max(search_start, min_search_start);
+
+ path = btrfs_alloc_path();
+ if (!path)
+@@ -1397,18 +1407,9 @@ int find_free_dev_extent(struct btrfs_tr
+ struct btrfs_device *device, u64 num_bytes,
+ u64 *start, u64 *len)
+ {
+- struct btrfs_root *root = device->dev_root;
+- u64 search_start;
+-
+ /* FIXME use last free of some kind */
+-
+- /*
+- * we don't want to overwrite the superblock on the drive,
+- * so we make sure to start at an offset of at least 1MB
+- */
+- search_start = max(root->fs_info->alloc_start, 1024ull * 1024);
+ return find_free_dev_extent_start(trans->transaction, device,
+- num_bytes, search_start, start, len);
++ num_bytes, 0, start, len);
+ }
+
+ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
+@@ -6512,6 +6513,14 @@ int btrfs_read_sys_array(struct btrfs_ro
+ goto out_short_read;
+
+ num_stripes = btrfs_chunk_num_stripes(sb, chunk);
++ if (!num_stripes) {
++ printk(KERN_ERR
++ "BTRFS: invalid number of stripes %u in sys_array at offset %u\n",
++ num_stripes, cur_offset);
++ ret = -EIO;
++ break;
++ }
++
+ len = btrfs_chunk_item_size(num_stripes);
+ if (cur_offset + len > array_size)
+ goto out_short_read;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/cifs_debug.c linux-libre-4.4.7-gnu/fs/cifs/cifs_debug.c
+--- linux-libre-4.4-gnu/fs/cifs/cifs_debug.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/cifs_debug.c 2016-04-12 12:09:26.000000000 -0400
+@@ -50,7 +50,7 @@ void cifs_vfs_err(const char *fmt, ...)
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+- pr_err("CIFS VFS: %pV", &vaf);
++ pr_err_ratelimited("CIFS VFS: %pV", &vaf);
+
+ va_end(args);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/cifs_debug.h linux-libre-4.4.7-gnu/fs/cifs/cifs_debug.h
+--- linux-libre-4.4-gnu/fs/cifs/cifs_debug.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/cifs_debug.h 2016-04-12 12:09:26.000000000 -0400
+@@ -51,14 +51,13 @@ __printf(1, 2) void cifs_vfs_err(const c
+ /* information message: e.g., configuration, major event */
+ #define cifs_dbg(type, fmt, ...) \
+ do { \
+- if (type == FYI) { \
+- if (cifsFYI & CIFS_INFO) { \
+- pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__); \
+- } \
++ if (type == FYI && cifsFYI & CIFS_INFO) { \
++ pr_debug_ratelimited("%s: " \
++ fmt, __FILE__, ##__VA_ARGS__); \
+ } else if (type == VFS) { \
+ cifs_vfs_err(fmt, ##__VA_ARGS__); \
+ } else if (type == NOISY && type != 0) { \
+- pr_debug(fmt, ##__VA_ARGS__); \
++ pr_debug_ratelimited(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/cifsencrypt.c linux-libre-4.4.7-gnu/fs/cifs/cifsencrypt.c
+--- linux-libre-4.4-gnu/fs/cifs/cifsencrypt.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/cifsencrypt.c 2016-04-12 12:09:26.000000000 -0400
+@@ -714,7 +714,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c
+
+ ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
+ if (!ses->auth_key.response) {
+- rc = ENOMEM;
++ rc = -ENOMEM;
+ ses->auth_key.len = 0;
+ goto setup_ntlmv2_rsp_ret;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/cifsfs.h linux-libre-4.4.7-gnu/fs/cifs/cifsfs.h
+--- linux-libre-4.4-gnu/fs/cifs/cifsfs.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/cifsfs.h 2016-04-12 12:09:26.000000000 -0400
+@@ -31,19 +31,15 @@
+ * so that it will fit. We use hash_64 to convert the value to 31 bits, and
+ * then add 1, to ensure that we don't end up with a 0 as the value.
+ */
+-#if BITS_PER_LONG == 64
+ static inline ino_t
+ cifs_uniqueid_to_ino_t(u64 fileid)
+ {
++ if ((sizeof(ino_t)) < (sizeof(u64)))
++ return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
++
+ return (ino_t)fileid;
++
+ }
+-#else
+-static inline ino_t
+-cifs_uniqueid_to_ino_t(u64 fileid)
+-{
+- return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
+-}
+-#endif
+
+ extern struct file_system_type cifs_fs_type;
+ extern const struct address_space_operations cifs_addr_ops;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/cifssmb.c linux-libre-4.4.7-gnu/fs/cifs/cifssmb.c
+--- linux-libre-4.4-gnu/fs/cifs/cifssmb.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/cifssmb.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1396,11 +1396,10 @@ openRetry:
+ * current bigbuf.
+ */
+ static int
+-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
++discard_remaining_data(struct TCP_Server_Info *server)
+ {
+ unsigned int rfclen = get_rfc1002_length(server->smallbuf);
+ int remaining = rfclen + 4 - server->total_read;
+- struct cifs_readdata *rdata = mid->callback_data;
+
+ while (remaining > 0) {
+ int length;
+@@ -1414,10 +1413,20 @@ cifs_readv_discard(struct TCP_Server_Inf
+ remaining -= length;
+ }
+
+- dequeue_mid(mid, rdata->result);
+ return 0;
+ }
+
++static int
++cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
++{
++ int length;
++ struct cifs_readdata *rdata = mid->callback_data;
++
++ length = discard_remaining_data(server);
++ dequeue_mid(mid, rdata->result);
++ return length;
++}
++
+ int
+ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+ {
+@@ -1446,6 +1455,12 @@ cifs_readv_receive(struct TCP_Server_Inf
+ return length;
+ server->total_read += length;
+
++ if (server->ops->is_status_pending &&
++ server->ops->is_status_pending(buf, server, 0)) {
++ discard_remaining_data(server);
++ return -1;
++ }
++
+ /* Was the SMB read successful? */
+ rdata->result = server->ops->map_error(buf, false);
+ if (rdata->result != 0) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/connect.c linux-libre-4.4.7-gnu/fs/cifs/connect.c
+--- linux-libre-4.4-gnu/fs/cifs/connect.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/connect.c 2016-04-12 12:09:26.000000000 -0400
+@@ -368,7 +368,6 @@ cifs_reconnect(struct TCP_Server_Info *s
+ server->session_key.response = NULL;
+ server->session_key.len = 0;
+ server->lstrp = jiffies;
+- mutex_unlock(&server->srv_mutex);
+
+ /* mark submitted MIDs for retry and issue callback */
+ INIT_LIST_HEAD(&retry_list);
+@@ -381,6 +380,7 @@ cifs_reconnect(struct TCP_Server_Info *s
+ list_move(&mid_entry->qhead, &retry_list);
+ }
+ spin_unlock(&GlobalMid_Lock);
++ mutex_unlock(&server->srv_mutex);
+
+ cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
+ list_for_each_safe(tmp, tmp2, &retry_list) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/readdir.c linux-libre-4.4.7-gnu/fs/cifs/readdir.c
+--- linux-libre-4.4-gnu/fs/cifs/readdir.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/readdir.c 2016-04-12 12:09:26.000000000 -0400
+@@ -847,6 +847,7 @@ int cifs_readdir(struct file *file, stru
+ * if buggy server returns . and .. late do we want to
+ * check for that here?
+ */
++ *tmp_buf = 0;
+ rc = cifs_filldir(current_entry, file, ctx,
+ tmp_buf, max_len);
+ if (rc) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/smb2pdu.c linux-libre-4.4.7-gnu/fs/cifs/smb2pdu.c
+--- linux-libre-4.4-gnu/fs/cifs/smb2pdu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/smb2pdu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1109,21 +1109,25 @@ parse_lease_state(struct TCP_Server_Info
+ {
+ char *data_offset;
+ struct create_context *cc;
+- unsigned int next = 0;
++ unsigned int next;
++ unsigned int remaining;
+ char *name;
+
+ data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
++ remaining = le32_to_cpu(rsp->CreateContextsLength);
+ cc = (struct create_context *)data_offset;
+- do {
+- cc = (struct create_context *)((char *)cc + next);
++ while (remaining >= sizeof(struct create_context)) {
+ name = le16_to_cpu(cc->NameOffset) + (char *)cc;
+- if (le16_to_cpu(cc->NameLength) != 4 ||
+- strncmp(name, "RqLs", 4)) {
+- next = le32_to_cpu(cc->Next);
+- continue;
+- }
+- return server->ops->parse_lease_buf(cc, epoch);
+- } while (next != 0);
++ if (le16_to_cpu(cc->NameLength) == 4 &&
++ strncmp(name, "RqLs", 4) == 0)
++ return server->ops->parse_lease_buf(cc, epoch);
++
++ next = le32_to_cpu(cc->Next);
++ if (!next)
++ break;
++ remaining -= next;
++ cc = (struct create_context *)((char *)cc + next);
++ }
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/cifs/transport.c linux-libre-4.4.7-gnu/fs/cifs/transport.c
+--- linux-libre-4.4-gnu/fs/cifs/transport.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/cifs/transport.c 2016-04-12 12:09:26.000000000 -0400
+@@ -576,14 +576,16 @@ cifs_call_async(struct TCP_Server_Info *
+ cifs_in_send_dec(server);
+ cifs_save_when_sent(mid);
+
+- if (rc < 0)
++ if (rc < 0) {
+ server->sequence_number -= 2;
++ cifs_delete_mid(mid);
++ }
++
+ mutex_unlock(&server->srv_mutex);
+
+ if (rc == 0)
+ return 0;
+
+- cifs_delete_mid(mid);
+ add_credits_and_wake_if(server, credits, optype);
+ return rc;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/coredump.c linux-libre-4.4.7-gnu/fs/coredump.c
+--- linux-libre-4.4-gnu/fs/coredump.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/coredump.c 2016-04-12 12:09:26.000000000 -0400
+@@ -32,6 +32,9 @@
+ #include <linux/pipe_fs_i.h>
+ #include <linux/oom.h>
+ #include <linux/compat.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/path.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/mmu_context.h>
+@@ -627,6 +630,8 @@ void do_coredump(const siginfo_t *siginf
+ }
+ } else {
+ struct inode *inode;
++ int open_flags = O_CREAT | O_RDWR | O_NOFOLLOW |
++ O_LARGEFILE | O_EXCL;
+
+ if (cprm.limit < binfmt->min_coredump)
+ goto fail_unlock;
+@@ -665,10 +670,27 @@ void do_coredump(const siginfo_t *siginf
+ * what matters is that at least one of the two processes
+ * writes its coredump successfully, not which one.
+ */
+- cprm.file = filp_open(cn.corename,
+- O_CREAT | 2 | O_NOFOLLOW |
+- O_LARGEFILE | O_EXCL,
+- 0600);
++ if (need_suid_safe) {
++ /*
++ * Using user namespaces, normal user tasks can change
++ * their current->fs->root to point to arbitrary
++ * directories. Since the intention of the "only dump
++ * with a fully qualified path" rule is to control where
++ * coredumps may be placed using root privileges,
++ * current->fs->root must not be used. Instead, use the
++ * root directory of init_task.
++ */
++ struct path root;
++
++ task_lock(&init_task);
++ get_fs_root(init_task.fs, &root);
++ task_unlock(&init_task);
++ cprm.file = file_open_root(root.dentry, root.mnt,
++ cn.corename, open_flags, 0600);
++ path_put(&root);
++ } else {
++ cprm.file = filp_open(cn.corename, open_flags, 0600);
++ }
+ if (IS_ERR(cprm.file))
+ goto fail_unlock;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/dcache.c linux-libre-4.4.7-gnu/fs/dcache.c
+--- linux-libre-4.4-gnu/fs/dcache.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/dcache.c 2016-04-12 12:09:26.000000000 -0400
+@@ -269,9 +269,6 @@ static inline int dname_external(const s
+ return dentry->d_name.name != dentry->d_iname;
+ }
+
+-/*
+- * Make sure other CPUs see the inode attached before the type is set.
+- */
+ static inline void __d_set_inode_and_type(struct dentry *dentry,
+ struct inode *inode,
+ unsigned type_flags)
+@@ -279,28 +276,18 @@ static inline void __d_set_inode_and_typ
+ unsigned flags;
+
+ dentry->d_inode = inode;
+- smp_wmb();
+ flags = READ_ONCE(dentry->d_flags);
+ flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
+ flags |= type_flags;
+ WRITE_ONCE(dentry->d_flags, flags);
+ }
+
+-/*
+- * Ideally, we want to make sure that other CPUs see the flags cleared before
+- * the inode is detached, but this is really a violation of RCU principles
+- * since the ordering suggests we should always set inode before flags.
+- *
+- * We should instead replace or discard the entire dentry - but that sucks
+- * performancewise on mass deletion/rename.
+- */
+ static inline void __d_clear_type_and_inode(struct dentry *dentry)
+ {
+ unsigned flags = READ_ONCE(dentry->d_flags);
+
+ flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
+ WRITE_ONCE(dentry->d_flags, flags);
+- smp_wmb();
+ dentry->d_inode = NULL;
+ }
+
+@@ -370,9 +357,11 @@ static void dentry_unlink_inode(struct d
+ __releases(dentry->d_inode->i_lock)
+ {
+ struct inode *inode = dentry->d_inode;
++
++ raw_write_seqcount_begin(&dentry->d_seq);
+ __d_clear_type_and_inode(dentry);
+ hlist_del_init(&dentry->d_u.d_alias);
+- dentry_rcuwalk_invalidate(dentry);
++ raw_write_seqcount_end(&dentry->d_seq);
+ spin_unlock(&dentry->d_lock);
+ spin_unlock(&inode->i_lock);
+ if (!inode->i_nlink)
+@@ -1757,8 +1746,9 @@ static void __d_instantiate(struct dentr
+ spin_lock(&dentry->d_lock);
+ if (inode)
+ hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
++ raw_write_seqcount_begin(&dentry->d_seq);
+ __d_set_inode_and_type(dentry, inode, add_flags);
+- dentry_rcuwalk_invalidate(dentry);
++ raw_write_seqcount_end(&dentry->d_seq);
+ spin_unlock(&dentry->d_lock);
+ fsnotify_d_instantiate(dentry, inode);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/devpts/inode.c linux-libre-4.4.7-gnu/fs/devpts/inode.c
+--- linux-libre-4.4-gnu/fs/devpts/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/devpts/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -575,6 +575,26 @@ void devpts_kill_index(struct inode *ptm
+ mutex_unlock(&allocated_ptys_lock);
+ }
+
++/*
++ * pty code needs to hold extra references in case of last /dev/tty close
++ */
++
++void devpts_add_ref(struct inode *ptmx_inode)
++{
++ struct super_block *sb = pts_sb_from_inode(ptmx_inode);
++
++ atomic_inc(&sb->s_active);
++ ihold(ptmx_inode);
++}
++
++void devpts_del_ref(struct inode *ptmx_inode)
++{
++ struct super_block *sb = pts_sb_from_inode(ptmx_inode);
++
++ iput(ptmx_inode);
++ deactivate_super(sb);
++}
++
+ /**
+ * devpts_pty_new -- create a new inode in /dev/pts/
+ * @ptmx_inode: inode of the master
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/direct-io.c linux-libre-4.4.7-gnu/fs/direct-io.c
+--- linux-libre-4.4-gnu/fs/direct-io.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/direct-io.c 2016-04-12 12:09:26.000000000 -0400
+@@ -472,8 +472,8 @@ static int dio_bio_complete(struct dio *
+ dio->io_error = -EIO;
+
+ if (dio->is_async && dio->rw == READ && dio->should_dirty) {
+- bio_check_pages_dirty(bio); /* transfers ownership */
+ err = bio->bi_error;
++ bio_check_pages_dirty(bio); /* transfers ownership */
+ } else {
+ bio_for_each_segment_all(bvec, bio, i) {
+ struct page *page = bvec->bv_page;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/efivarfs/file.c linux-libre-4.4.7-gnu/fs/efivarfs/file.c
+--- linux-libre-4.4-gnu/fs/efivarfs/file.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/efivarfs/file.c 2016-04-12 12:09:26.000000000 -0400
+@@ -10,6 +10,7 @@
+ #include <linux/efi.h>
+ #include <linux/fs.h>
+ #include <linux/slab.h>
++#include <linux/mount.h>
+
+ #include "internal.h"
+
+@@ -103,9 +104,78 @@ out_free:
+ return size;
+ }
+
++static int
++efivarfs_ioc_getxflags(struct file *file, void __user *arg)
++{
++ struct inode *inode = file->f_mapping->host;
++ unsigned int i_flags;
++ unsigned int flags = 0;
++
++ i_flags = inode->i_flags;
++ if (i_flags & S_IMMUTABLE)
++ flags |= FS_IMMUTABLE_FL;
++
++ if (copy_to_user(arg, &flags, sizeof(flags)))
++ return -EFAULT;
++ return 0;
++}
++
++static int
++efivarfs_ioc_setxflags(struct file *file, void __user *arg)
++{
++ struct inode *inode = file->f_mapping->host;
++ unsigned int flags;
++ unsigned int i_flags = 0;
++ int error;
++
++ if (!inode_owner_or_capable(inode))
++ return -EACCES;
++
++ if (copy_from_user(&flags, arg, sizeof(flags)))
++ return -EFAULT;
++
++ if (flags & ~FS_IMMUTABLE_FL)
++ return -EOPNOTSUPP;
++
++ if (!capable(CAP_LINUX_IMMUTABLE))
++ return -EPERM;
++
++ if (flags & FS_IMMUTABLE_FL)
++ i_flags |= S_IMMUTABLE;
++
++
++ error = mnt_want_write_file(file);
++ if (error)
++ return error;
++
++ mutex_lock(&inode->i_mutex);
++ inode_set_flags(inode, i_flags, S_IMMUTABLE);
++ mutex_unlock(&inode->i_mutex);
++
++ mnt_drop_write_file(file);
++
++ return 0;
++}
++
++long
++efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p)
++{
++ void __user *arg = (void __user *)p;
++
++ switch (cmd) {
++ case FS_IOC_GETFLAGS:
++ return efivarfs_ioc_getxflags(file, arg);
++ case FS_IOC_SETFLAGS:
++ return efivarfs_ioc_setxflags(file, arg);
++ }
++
++ return -ENOTTY;
++}
++
+ const struct file_operations efivarfs_file_operations = {
+ .open = simple_open,
+ .read = efivarfs_file_read,
+ .write = efivarfs_file_write,
+ .llseek = no_llseek,
++ .unlocked_ioctl = efivarfs_file_ioctl,
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/efivarfs/inode.c linux-libre-4.4.7-gnu/fs/efivarfs/inode.c
+--- linux-libre-4.4-gnu/fs/efivarfs/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/efivarfs/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -15,7 +15,8 @@
+ #include "internal.h"
+
+ struct inode *efivarfs_get_inode(struct super_block *sb,
+- const struct inode *dir, int mode, dev_t dev)
++ const struct inode *dir, int mode,
++ dev_t dev, bool is_removable)
+ {
+ struct inode *inode = new_inode(sb);
+
+@@ -23,6 +24,7 @@ struct inode *efivarfs_get_inode(struct
+ inode->i_ino = get_next_ino();
+ inode->i_mode = mode;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ inode->i_flags = is_removable ? 0 : S_IMMUTABLE;
+ switch (mode & S_IFMT) {
+ case S_IFREG:
+ inode->i_fop = &efivarfs_file_operations;
+@@ -102,22 +104,17 @@ static void efivarfs_hex_to_guid(const c
+ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
+ umode_t mode, bool excl)
+ {
+- struct inode *inode;
++ struct inode *inode = NULL;
+ struct efivar_entry *var;
+ int namelen, i = 0, err = 0;
++ bool is_removable = false;
+
+ if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
+ return -EINVAL;
+
+- inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
+- if (!inode)
+- return -ENOMEM;
+-
+ var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
+- if (!var) {
+- err = -ENOMEM;
+- goto out;
+- }
++ if (!var)
++ return -ENOMEM;
+
+ /* length of the variable name itself: remove GUID and separator */
+ namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1;
+@@ -125,6 +122,16 @@ static int efivarfs_create(struct inode
+ efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
+ &var->var.VendorGuid);
+
++ if (efivar_variable_is_removable(var->var.VendorGuid,
++ dentry->d_name.name, namelen))
++ is_removable = true;
++
++ inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0, is_removable);
++ if (!inode) {
++ err = -ENOMEM;
++ goto out;
++ }
++
+ for (i = 0; i < namelen; i++)
+ var->var.VariableName[i] = dentry->d_name.name[i];
+
+@@ -138,7 +145,8 @@ static int efivarfs_create(struct inode
+ out:
+ if (err) {
+ kfree(var);
+- iput(inode);
++ if (inode)
++ iput(inode);
+ }
+ return err;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/efivarfs/internal.h linux-libre-4.4.7-gnu/fs/efivarfs/internal.h
+--- linux-libre-4.4-gnu/fs/efivarfs/internal.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/efivarfs/internal.h 2016-04-12 12:09:26.000000000 -0400
+@@ -15,7 +15,8 @@ extern const struct file_operations efiv
+ extern const struct inode_operations efivarfs_dir_inode_operations;
+ extern bool efivarfs_valid_name(const char *str, int len);
+ extern struct inode *efivarfs_get_inode(struct super_block *sb,
+- const struct inode *dir, int mode, dev_t dev);
++ const struct inode *dir, int mode, dev_t dev,
++ bool is_removable);
+
+ extern struct list_head efivarfs_list;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/efivarfs/super.c linux-libre-4.4.7-gnu/fs/efivarfs/super.c
+--- linux-libre-4.4-gnu/fs/efivarfs/super.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/efivarfs/super.c 2016-04-12 12:09:26.000000000 -0400
+@@ -118,8 +118,9 @@ static int efivarfs_callback(efi_char16_
+ struct dentry *dentry, *root = sb->s_root;
+ unsigned long size = 0;
+ char *name;
+- int len, i;
++ int len;
+ int err = -ENOMEM;
++ bool is_removable = false;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+@@ -128,15 +129,17 @@ static int efivarfs_callback(efi_char16_
+ memcpy(entry->var.VariableName, name16, name_size);
+ memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
+
+- len = ucs2_strlen(entry->var.VariableName);
++ len = ucs2_utf8size(entry->var.VariableName);
+
+ /* name, plus '-', plus GUID, plus NUL*/
+ name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
+ if (!name)
+ goto fail;
+
+- for (i = 0; i < len; i++)
+- name[i] = entry->var.VariableName[i] & 0xFF;
++ ucs2_as_utf8(name, entry->var.VariableName, len);
++
++ if (efivar_variable_is_removable(entry->var.VendorGuid, name, len))
++ is_removable = true;
+
+ name[len] = '-';
+
+@@ -144,7 +147,8 @@ static int efivarfs_callback(efi_char16_
+
+ name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
+
+- inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0);
++ inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0,
++ is_removable);
+ if (!inode)
+ goto fail_name;
+
+@@ -200,7 +204,7 @@ static int efivarfs_fill_super(struct su
+ sb->s_d_op = &efivarfs_d_ops;
+ sb->s_time_gran = 1;
+
+- inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
++ inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true);
+ if (!inode)
+ return -ENOMEM;
+ inode->i_op = &efivarfs_dir_inode_operations;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ext4/balloc.c linux-libre-4.4.7-gnu/fs/ext4/balloc.c
+--- linux-libre-4.4-gnu/fs/ext4/balloc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ext4/balloc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -191,7 +191,6 @@ static int ext4_init_block_bitmap(struct
+ /* If checksum is bad mark all blocks used to prevent allocation
+ * essentially implementing a per-group read-only flag. */
+ if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
+- ext4_error(sb, "Checksum bad for group %u", block_group);
+ grp = ext4_get_group_info(sb, block_group);
+ if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
+ percpu_counter_sub(&sbi->s_freeclusters_counter,
+@@ -442,14 +441,16 @@ ext4_read_block_bitmap_nowait(struct sup
+ }
+ ext4_lock_group(sb, block_group);
+ if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
+-
+ err = ext4_init_block_bitmap(sb, bh, block_group, desc);
+ set_bitmap_uptodate(bh);
+ set_buffer_uptodate(bh);
+ ext4_unlock_group(sb, block_group);
+ unlock_buffer(bh);
+- if (err)
++ if (err) {
++ ext4_error(sb, "Failed to init block bitmap for group "
++ "%u: %d", block_group, err);
+ goto out;
++ }
+ goto verify;
+ }
+ ext4_unlock_group(sb, block_group);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ext4/crypto_key.c linux-libre-4.4.7-gnu/fs/ext4/crypto_key.c
+--- linux-libre-4.4-gnu/fs/ext4/crypto_key.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ext4/crypto_key.c 2016-04-12 12:09:26.000000000 -0400
+@@ -213,9 +213,11 @@ retry:
+ res = -ENOKEY;
+ goto out;
+ }
++ down_read(&keyring_key->sem);
+ ukp = user_key_payload(keyring_key);
+ if (ukp->datalen != sizeof(struct ext4_encryption_key)) {
+ res = -EINVAL;
++ up_read(&keyring_key->sem);
+ goto out;
+ }
+ master_key = (struct ext4_encryption_key *)ukp->data;
+@@ -226,10 +228,12 @@ retry:
+ "ext4: key size incorrect: %d\n",
+ master_key->size);
+ res = -ENOKEY;
++ up_read(&keyring_key->sem);
+ goto out;
+ }
+ res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
+ raw_key);
++ up_read(&keyring_key->sem);
+ if (res)
+ goto out;
+ got_key:
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ext4/ialloc.c linux-libre-4.4.7-gnu/fs/ext4/ialloc.c
+--- linux-libre-4.4-gnu/fs/ext4/ialloc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ext4/ialloc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -76,7 +76,6 @@ static int ext4_init_inode_bitmap(struct
+ /* If checksum is bad mark all blocks and inodes use to prevent
+ * allocation, essentially implementing a per-group read-only flag. */
+ if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
+- ext4_error(sb, "Checksum bad for group %u", block_group);
+ grp = ext4_get_group_info(sb, block_group);
+ if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
+ percpu_counter_sub(&sbi->s_freeclusters_counter,
+@@ -191,8 +190,11 @@ ext4_read_inode_bitmap(struct super_bloc
+ set_buffer_verified(bh);
+ ext4_unlock_group(sb, block_group);
+ unlock_buffer(bh);
+- if (err)
++ if (err) {
++ ext4_error(sb, "Failed to init inode bitmap for group "
++ "%u: %d", block_group, err);
+ goto out;
++ }
+ return bh;
+ }
+ ext4_unlock_group(sb, block_group);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ext4/inode.c linux-libre-4.4.7-gnu/fs/ext4/inode.c
+--- linux-libre-4.4-gnu/fs/ext4/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ext4/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -657,6 +657,34 @@ has_zeroout:
+ return retval;
+ }
+
++/*
++ * Update EXT4_MAP_FLAGS in bh->b_state. For buffer heads attached to pages
++ * we have to be careful as someone else may be manipulating b_state as well.
++ */
++static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags)
++{
++ unsigned long old_state;
++ unsigned long new_state;
++
++ flags &= EXT4_MAP_FLAGS;
++
++ /* Dummy buffer_head? Set non-atomically. */
++ if (!bh->b_page) {
++ bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | flags;
++ return;
++ }
++ /*
++ * Someone else may be modifying b_state. Be careful! This is ugly but
++ * once we get rid of using bh as a container for mapping information
++ * to pass to / from get_block functions, this can go away.
++ */
++ do {
++ old_state = READ_ONCE(bh->b_state);
++ new_state = (old_state & ~EXT4_MAP_FLAGS) | flags;
++ } while (unlikely(
++ cmpxchg(&bh->b_state, old_state, new_state) != old_state));
++}
++
+ /* Maximum number of blocks we map for direct IO at once. */
+ #define DIO_MAX_BLOCKS 4096
+
+@@ -693,7 +721,7 @@ static int _ext4_get_block(struct inode
+ ext4_io_end_t *io_end = ext4_inode_aio(inode);
+
+ map_bh(bh, inode->i_sb, map.m_pblk);
+- bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
++ ext4_update_bh_state(bh, map.m_flags);
+ if (IS_DAX(inode) && buffer_unwritten(bh)) {
+ /*
+ * dgc: I suspect unwritten conversion on ext4+DAX is
+@@ -1669,7 +1697,7 @@ int ext4_da_get_block_prep(struct inode
+ return ret;
+
+ map_bh(bh, inode->i_sb, map.m_pblk);
+- bh->b_state = (bh->b_state & ~EXT4_MAP_FLAGS) | map.m_flags;
++ ext4_update_bh_state(bh, map.m_flags);
+
+ if (buffer_unwritten(bh)) {
+ /* A delayed write to unwritten bh should be marked
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ext4/move_extent.c linux-libre-4.4.7-gnu/fs/ext4/move_extent.c
+--- linux-libre-4.4-gnu/fs/ext4/move_extent.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ext4/move_extent.c 2016-04-12 12:09:26.000000000 -0400
+@@ -265,11 +265,12 @@ move_extent_per_page(struct file *o_filp
+ ext4_lblk_t orig_blk_offset, donor_blk_offset;
+ unsigned long blocksize = orig_inode->i_sb->s_blocksize;
+ unsigned int tmp_data_size, data_size, replaced_size;
+- int err2, jblocks, retries = 0;
++ int i, err2, jblocks, retries = 0;
+ int replaced_count = 0;
+ int from = data_offset_in_page << orig_inode->i_blkbits;
+ int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
+ struct super_block *sb = orig_inode->i_sb;
++ struct buffer_head *bh = NULL;
+
+ /*
+ * It needs twice the amount of ordinary journal buffers because
+@@ -380,8 +381,16 @@ data_copy:
+ }
+ /* Perform all necessary steps similar write_begin()/write_end()
+ * but keeping in mind that i_size will not change */
+- *err = __block_write_begin(pagep[0], from, replaced_size,
+- ext4_get_block);
++ if (!page_has_buffers(pagep[0]))
++ create_empty_buffers(pagep[0], 1 << orig_inode->i_blkbits, 0);
++ bh = page_buffers(pagep[0]);
++ for (i = 0; i < data_offset_in_page; i++)
++ bh = bh->b_this_page;
++ for (i = 0; i < block_len_in_page; i++) {
++ *err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0);
++ if (*err < 0)
++ break;
++ }
+ if (!*err)
+ *err = block_commit_write(pagep[0], from, from + replaced_size);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ext4/resize.c linux-libre-4.4.7-gnu/fs/ext4/resize.c
+--- linux-libre-4.4-gnu/fs/ext4/resize.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ext4/resize.c 2016-04-12 12:09:26.000000000 -0400
+@@ -198,7 +198,7 @@ static struct ext4_new_flex_group_data *
+ if (flex_gd == NULL)
+ goto out3;
+
+- if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data))
++ if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_group_data))
+ goto out2;
+ flex_gd->count = flexbg_size;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/fhandle.c linux-libre-4.4.7-gnu/fs/fhandle.c
+--- linux-libre-4.4-gnu/fs/fhandle.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/fhandle.c 2016-04-12 12:09:26.000000000 -0400
+@@ -228,7 +228,7 @@ long do_handle_open(int mountdirfd,
+ path_put(&path);
+ return fd;
+ }
+- file = file_open_root(path.dentry, path.mnt, "", open_flag);
++ file = file_open_root(path.dentry, path.mnt, "", open_flag, 0);
+ if (IS_ERR(file)) {
+ put_unused_fd(fd);
+ retval = PTR_ERR(file);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/fs-writeback.c linux-libre-4.4.7-gnu/fs/fs-writeback.c
+--- linux-libre-4.4-gnu/fs/fs-writeback.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/fs-writeback.c 2016-04-12 12:09:26.000000000 -0400
+@@ -223,6 +223,9 @@ static void wb_wait_for_completion(struc
+ #define WB_FRN_HIST_MAX_SLOTS (WB_FRN_HIST_THR_SLOTS / 2 + 1)
+ /* one round can affect upto 5 slots */
+
++static atomic_t isw_nr_in_flight = ATOMIC_INIT(0);
++static struct workqueue_struct *isw_wq;
++
+ void __inode_attach_wb(struct inode *inode, struct page *page)
+ {
+ struct backing_dev_info *bdi = inode_to_bdi(inode);
+@@ -278,13 +281,15 @@ locked_inode_to_wb_and_lock_list(struct
+ wb_get(wb);
+ spin_unlock(&inode->i_lock);
+ spin_lock(&wb->list_lock);
+- wb_put(wb); /* not gonna deref it anymore */
+
+ /* i_wb may have changed inbetween, can't use inode_to_wb() */
+- if (likely(wb == inode->i_wb))
+- return wb; /* @inode already has ref */
++ if (likely(wb == inode->i_wb)) {
++ wb_put(wb); /* @inode already has ref */
++ return wb;
++ }
+
+ spin_unlock(&wb->list_lock);
++ wb_put(wb);
+ cpu_relax();
+ spin_lock(&inode->i_lock);
+ }
+@@ -424,6 +429,8 @@ skip_switch:
+
+ iput(inode);
+ kfree(isw);
++
++ atomic_dec(&isw_nr_in_flight);
+ }
+
+ static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head)
+@@ -433,7 +440,7 @@ static void inode_switch_wbs_rcu_fn(stru
+
+ /* needs to grab bh-unsafe locks, bounce to work item */
+ INIT_WORK(&isw->work, inode_switch_wbs_work_fn);
+- schedule_work(&isw->work);
++ queue_work(isw_wq, &isw->work);
+ }
+
+ /**
+@@ -469,7 +476,8 @@ static void inode_switch_wbs(struct inod
+
+ /* while holding I_WB_SWITCH, no one else can update the association */
+ spin_lock(&inode->i_lock);
+- if (inode->i_state & (I_WB_SWITCH | I_FREEING) ||
++ if (!(inode->i_sb->s_flags & MS_ACTIVE) ||
++ inode->i_state & (I_WB_SWITCH | I_FREEING) ||
+ inode_to_wb(inode) == isw->new_wb) {
+ spin_unlock(&inode->i_lock);
+ goto out_free;
+@@ -480,6 +488,8 @@ static void inode_switch_wbs(struct inod
+ ihold(inode);
+ isw->inode = inode;
+
++ atomic_inc(&isw_nr_in_flight);
++
+ /*
+ * In addition to synchronizing among switchers, I_WB_SWITCH tells
+ * the RCU protected stat update paths to grab the mapping's
+@@ -842,6 +852,33 @@ restart:
+ wb_put(last_wb);
+ }
+
++/**
++ * cgroup_writeback_umount - flush inode wb switches for umount
++ *
++ * This function is called when a super_block is about to be destroyed and
++ * flushes in-flight inode wb switches. An inode wb switch goes through
++ * RCU and then workqueue, so the two need to be flushed in order to ensure
++ * that all previously scheduled switches are finished. As wb switches are
++ * rare occurrences and synchronize_rcu() can take a while, perform
++ * flushing iff wb switches are in flight.
++ */
++void cgroup_writeback_umount(void)
++{
++ if (atomic_read(&isw_nr_in_flight)) {
++ synchronize_rcu();
++ flush_workqueue(isw_wq);
++ }
++}
++
++static int __init cgroup_writeback_init(void)
++{
++ isw_wq = alloc_workqueue("inode_switch_wbs", 0, 0);
++ if (!isw_wq)
++ return -ENOMEM;
++ return 0;
++}
++fs_initcall(cgroup_writeback_init);
++
+ #else /* CONFIG_CGROUP_WRITEBACK */
+
+ static struct bdi_writeback *
+@@ -1304,10 +1341,10 @@ __writeback_single_inode(struct inode *i
+ * we go e.g. from filesystem. Flusher thread uses __writeback_single_inode()
+ * and does more profound writeback list handling in writeback_sb_inodes().
+ */
+-static int
+-writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
+- struct writeback_control *wbc)
++static int writeback_single_inode(struct inode *inode,
++ struct writeback_control *wbc)
+ {
++ struct bdi_writeback *wb;
+ int ret = 0;
+
+ spin_lock(&inode->i_lock);
+@@ -1345,7 +1382,8 @@ writeback_single_inode(struct inode *ino
+ ret = __writeback_single_inode(inode, wbc);
+
+ wbc_detach_inode(wbc);
+- spin_lock(&wb->list_lock);
++
++ wb = inode_to_wb_and_lock_list(inode);
+ spin_lock(&inode->i_lock);
+ /*
+ * If inode is clean, remove it from writeback lists. Otherwise don't
+@@ -1420,6 +1458,7 @@ static long writeback_sb_inodes(struct s
+
+ while (!list_empty(&wb->b_io)) {
+ struct inode *inode = wb_inode(wb->b_io.prev);
++ struct bdi_writeback *tmp_wb;
+
+ if (inode->i_sb != sb) {
+ if (work->sb) {
+@@ -1510,15 +1549,23 @@ static long writeback_sb_inodes(struct s
+ cond_resched();
+ }
+
+-
+- spin_lock(&wb->list_lock);
++ /*
++ * Requeue @inode if still dirty. Be careful as @inode may
++ * have been switched to another wb in the meantime.
++ */
++ tmp_wb = inode_to_wb_and_lock_list(inode);
+ spin_lock(&inode->i_lock);
+ if (!(inode->i_state & I_DIRTY_ALL))
+ wrote++;
+- requeue_inode(inode, wb, &wbc);
++ requeue_inode(inode, tmp_wb, &wbc);
+ inode_sync_complete(inode);
+ spin_unlock(&inode->i_lock);
+
++ if (unlikely(tmp_wb != wb)) {
++ spin_unlock(&tmp_wb->list_lock);
++ spin_lock(&wb->list_lock);
++ }
++
+ /*
+ * bail out to wb_writeback() often enough to check
+ * background threshold and other termination conditions.
+@@ -2305,7 +2352,6 @@ EXPORT_SYMBOL(sync_inodes_sb);
+ */
+ int write_inode_now(struct inode *inode, int sync)
+ {
+- struct bdi_writeback *wb = &inode_to_bdi(inode)->wb;
+ struct writeback_control wbc = {
+ .nr_to_write = LONG_MAX,
+ .sync_mode = sync ? WB_SYNC_ALL : WB_SYNC_NONE,
+@@ -2317,7 +2363,7 @@ int write_inode_now(struct inode *inode,
+ wbc.nr_to_write = 0;
+
+ might_sleep();
+- return writeback_single_inode(inode, wb, &wbc);
++ return writeback_single_inode(inode, &wbc);
+ }
+ EXPORT_SYMBOL(write_inode_now);
+
+@@ -2334,7 +2380,7 @@ EXPORT_SYMBOL(write_inode_now);
+ */
+ int sync_inode(struct inode *inode, struct writeback_control *wbc)
+ {
+- return writeback_single_inode(inode, &inode_to_bdi(inode)->wb, wbc);
++ return writeback_single_inode(inode, wbc);
+ }
+ EXPORT_SYMBOL(sync_inode);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/fuse/cuse.c linux-libre-4.4.7-gnu/fs/fuse/cuse.c
+--- linux-libre-4.4-gnu/fs/fuse/cuse.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/fuse/cuse.c 2016-04-12 12:09:26.000000000 -0400
+@@ -90,7 +90,7 @@ static struct list_head *cuse_conntbl_he
+
+ static ssize_t cuse_read_iter(struct kiocb *kiocb, struct iov_iter *to)
+ {
+- struct fuse_io_priv io = { .async = 0, .file = kiocb->ki_filp };
++ struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp);
+ loff_t pos = 0;
+
+ return fuse_direct_io(&io, to, &pos, FUSE_DIO_CUSE);
+@@ -98,7 +98,7 @@ static ssize_t cuse_read_iter(struct kio
+
+ static ssize_t cuse_write_iter(struct kiocb *kiocb, struct iov_iter *from)
+ {
+- struct fuse_io_priv io = { .async = 0, .file = kiocb->ki_filp };
++ struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(kiocb->ki_filp);
+ loff_t pos = 0;
+ /*
+ * No locking or generic_write_checks(), the server is
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/fuse/file.c linux-libre-4.4.7-gnu/fs/fuse/file.c
+--- linux-libre-4.4-gnu/fs/fuse/file.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/fuse/file.c 2016-04-12 12:09:26.000000000 -0400
+@@ -528,6 +528,11 @@ static void fuse_release_user_pages(stru
+ }
+ }
+
++static void fuse_io_release(struct kref *kref)
++{
++ kfree(container_of(kref, struct fuse_io_priv, refcnt));
++}
++
+ static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
+ {
+ if (io->err)
+@@ -585,8 +590,9 @@ static void fuse_aio_complete(struct fus
+ }
+
+ io->iocb->ki_complete(io->iocb, res, 0);
+- kfree(io);
+ }
++
++ kref_put(&io->refcnt, fuse_io_release);
+ }
+
+ static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req)
+@@ -613,6 +619,7 @@ static size_t fuse_async_req_send(struct
+ size_t num_bytes, struct fuse_io_priv *io)
+ {
+ spin_lock(&io->lock);
++ kref_get(&io->refcnt);
+ io->size += num_bytes;
+ io->reqs++;
+ spin_unlock(&io->lock);
+@@ -691,7 +698,7 @@ static void fuse_short_read(struct fuse_
+
+ static int fuse_do_readpage(struct file *file, struct page *page)
+ {
+- struct fuse_io_priv io = { .async = 0, .file = file };
++ struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
+ struct inode *inode = page->mapping->host;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+@@ -984,7 +991,7 @@ static size_t fuse_send_write_pages(stru
+ size_t res;
+ unsigned offset;
+ unsigned i;
+- struct fuse_io_priv io = { .async = 0, .file = file };
++ struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
+
+ for (i = 0; i < req->num_pages; i++)
+ fuse_wait_on_page_writeback(inode, req->pages[i]->index);
+@@ -1398,7 +1405,7 @@ static ssize_t __fuse_direct_read(struct
+
+ static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ {
+- struct fuse_io_priv io = { .async = 0, .file = iocb->ki_filp };
++ struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb->ki_filp);
+ return __fuse_direct_read(&io, to, &iocb->ki_pos);
+ }
+
+@@ -1406,7 +1413,7 @@ static ssize_t fuse_direct_write_iter(st
+ {
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file_inode(file);
+- struct fuse_io_priv io = { .async = 0, .file = file };
++ struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(file);
+ ssize_t res;
+
+ if (is_bad_inode(inode))
+@@ -2786,6 +2793,7 @@ fuse_direct_IO(struct kiocb *iocb, struc
+ loff_t i_size;
+ size_t count = iov_iter_count(iter);
+ struct fuse_io_priv *io;
++ bool is_sync = is_sync_kiocb(iocb);
+
+ pos = offset;
+ inode = file->f_mapping->host;
+@@ -2806,6 +2814,7 @@ fuse_direct_IO(struct kiocb *iocb, struc
+ if (!io)
+ return -ENOMEM;
+ spin_lock_init(&io->lock);
++ kref_init(&io->refcnt);
+ io->reqs = 1;
+ io->bytes = -1;
+ io->size = 0;
+@@ -2825,12 +2834,18 @@ fuse_direct_IO(struct kiocb *iocb, struc
+ * to wait on real async I/O requests, so we must submit this request
+ * synchronously.
+ */
+- if (!is_sync_kiocb(iocb) && (offset + count > i_size) &&
++ if (!is_sync && (offset + count > i_size) &&
+ iov_iter_rw(iter) == WRITE)
+ io->async = false;
+
+- if (io->async && is_sync_kiocb(iocb))
++ if (io->async && is_sync) {
++ /*
++ * Additional reference to keep io around after
++ * calling fuse_aio_complete()
++ */
++ kref_get(&io->refcnt);
+ io->done = &wait;
++ }
+
+ if (iov_iter_rw(iter) == WRITE) {
+ ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
+@@ -2843,14 +2858,14 @@ fuse_direct_IO(struct kiocb *iocb, struc
+ fuse_aio_complete(io, ret < 0 ? ret : 0, -1);
+
+ /* we have a non-extending, async request, so return */
+- if (!is_sync_kiocb(iocb))
++ if (!is_sync)
+ return -EIOCBQUEUED;
+
+ wait_for_completion(&wait);
+ ret = fuse_get_res_by_io(io);
+ }
+
+- kfree(io);
++ kref_put(&io->refcnt, fuse_io_release);
+
+ if (iov_iter_rw(iter) == WRITE) {
+ if (ret > 0)
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/fuse/fuse_i.h linux-libre-4.4.7-gnu/fs/fuse/fuse_i.h
+--- linux-libre-4.4-gnu/fs/fuse/fuse_i.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/fuse/fuse_i.h 2016-04-12 12:09:26.000000000 -0400
+@@ -22,6 +22,7 @@
+ #include <linux/rbtree.h>
+ #include <linux/poll.h>
+ #include <linux/workqueue.h>
++#include <linux/kref.h>
+
+ /** Max number of pages that can be used in a single read request */
+ #define FUSE_MAX_PAGES_PER_REQ 32
+@@ -243,6 +244,7 @@ struct fuse_args {
+
+ /** The request IO state (for asynchronous processing) */
+ struct fuse_io_priv {
++ struct kref refcnt;
+ int async;
+ spinlock_t lock;
+ unsigned reqs;
+@@ -256,6 +258,13 @@ struct fuse_io_priv {
+ struct completion *done;
+ };
+
++#define FUSE_IO_PRIV_SYNC(f) \
++{ \
++ .refcnt = { ATOMIC_INIT(1) }, \
++ .async = 0, \
++ .file = f, \
++}
++
+ /**
+ * Request flags
+ *
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/hostfs/hostfs_kern.c linux-libre-4.4.7-gnu/fs/hostfs/hostfs_kern.c
+--- linux-libre-4.4-gnu/fs/hostfs/hostfs_kern.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/hostfs/hostfs_kern.c 2016-04-12 12:09:26.000000000 -0400
+@@ -730,15 +730,13 @@ static int hostfs_mknod(struct inode *di
+
+ init_special_inode(inode, mode, dev);
+ err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
+- if (!err)
++ if (err)
+ goto out_free;
+
+ err = read_name(inode, name);
+ __putname(name);
+ if (err)
+ goto out_put;
+- if (err)
+- goto out_put;
+
+ d_instantiate(dentry, inode);
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/hpfs/namei.c linux-libre-4.4.7-gnu/fs/hpfs/namei.c
+--- linux-libre-4.4-gnu/fs/hpfs/namei.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/hpfs/namei.c 2016-04-12 12:09:26.000000000 -0400
+@@ -375,12 +375,11 @@ static int hpfs_unlink(struct inode *dir
+ struct inode *inode = d_inode(dentry);
+ dnode_secno dno;
+ int r;
+- int rep = 0;
+ int err;
+
+ hpfs_lock(dir->i_sb);
+ hpfs_adjust_length(name, &len);
+-again:
++
+ err = -ENOENT;
+ de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
+ if (!de)
+@@ -400,33 +399,9 @@ again:
+ hpfs_error(dir->i_sb, "there was error when removing dirent");
+ err = -EFSERROR;
+ break;
+- case 2: /* no space for deleting, try to truncate file */
+-
++ case 2: /* no space for deleting */
+ err = -ENOSPC;
+- if (rep++)
+- break;
+-
+- dentry_unhash(dentry);
+- if (!d_unhashed(dentry)) {
+- hpfs_unlock(dir->i_sb);
+- return -ENOSPC;
+- }
+- if (generic_permission(inode, MAY_WRITE) ||
+- !S_ISREG(inode->i_mode) ||
+- get_write_access(inode)) {
+- d_rehash(dentry);
+- } else {
+- struct iattr newattrs;
+- /*pr_info("truncating file before delete.\n");*/
+- newattrs.ia_size = 0;
+- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+- err = notify_change(dentry, &newattrs, NULL);
+- put_write_access(inode);
+- if (!err)
+- goto again;
+- }
+- hpfs_unlock(dir->i_sb);
+- return -ENOSPC;
++ break;
+ default:
+ drop_nlink(inode);
+ err = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/hugetlbfs/inode.c linux-libre-4.4.7-gnu/fs/hugetlbfs/inode.c
+--- linux-libre-4.4-gnu/fs/hugetlbfs/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/hugetlbfs/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -463,6 +463,7 @@ hugetlb_vmdelete_list(struct rb_root *ro
+ */
+ vma_interval_tree_foreach(vma, root, start, end ? end : ULONG_MAX) {
+ unsigned long v_offset;
++ unsigned long v_end;
+
+ /*
+ * Can the expression below overflow on 32-bit arches?
+@@ -475,15 +476,17 @@ hugetlb_vmdelete_list(struct rb_root *ro
+ else
+ v_offset = 0;
+
+- if (end) {
+- end = ((end - start) << PAGE_SHIFT) +
+- vma->vm_start + v_offset;
+- if (end > vma->vm_end)
+- end = vma->vm_end;
+- } else
+- end = vma->vm_end;
++ if (!end)
++ v_end = vma->vm_end;
++ else {
++ v_end = ((end - vma->vm_pgoff) << PAGE_SHIFT)
++ + vma->vm_start;
++ if (v_end > vma->vm_end)
++ v_end = vma->vm_end;
++ }
+
+- unmap_hugepage_range(vma, vma->vm_start + v_offset, end, NULL);
++ unmap_hugepage_range(vma, vma->vm_start + v_offset, v_end,
++ NULL);
+ }
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/jbd2/journal.c linux-libre-4.4.7-gnu/fs/jbd2/journal.c
+--- linux-libre-4.4-gnu/fs/jbd2/journal.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/jbd2/journal.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1408,11 +1408,12 @@ out:
+ /**
+ * jbd2_mark_journal_empty() - Mark on disk journal as empty.
+ * @journal: The journal to update.
++ * @write_op: With which operation should we write the journal sb
+ *
+ * Update a journal's dynamic superblock fields to show that journal is empty.
+ * Write updated superblock to disk waiting for IO to complete.
+ */
+-static void jbd2_mark_journal_empty(journal_t *journal)
++static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
+ {
+ journal_superblock_t *sb = journal->j_superblock;
+
+@@ -1430,7 +1431,7 @@ static void jbd2_mark_journal_empty(jour
+ sb->s_start = cpu_to_be32(0);
+ read_unlock(&journal->j_state_lock);
+
+- jbd2_write_superblock(journal, WRITE_FUA);
++ jbd2_write_superblock(journal, write_op);
+
+ /* Log is no longer empty */
+ write_lock(&journal->j_state_lock);
+@@ -1716,7 +1717,13 @@ int jbd2_journal_destroy(journal_t *jour
+ if (journal->j_sb_buffer) {
+ if (!is_journal_aborted(journal)) {
+ mutex_lock(&journal->j_checkpoint_mutex);
+- jbd2_mark_journal_empty(journal);
++
++ write_lock(&journal->j_state_lock);
++ journal->j_tail_sequence =
++ ++journal->j_transaction_sequence;
++ write_unlock(&journal->j_state_lock);
++
++ jbd2_mark_journal_empty(journal, WRITE_FLUSH_FUA);
+ mutex_unlock(&journal->j_checkpoint_mutex);
+ } else
+ err = -EIO;
+@@ -1975,7 +1982,7 @@ int jbd2_journal_flush(journal_t *journa
+ * the magic code for a fully-recovered superblock. Any future
+ * commits of data to the journal will restore the current
+ * s_start value. */
+- jbd2_mark_journal_empty(journal);
++ jbd2_mark_journal_empty(journal, WRITE_FUA);
+ mutex_unlock(&journal->j_checkpoint_mutex);
+ write_lock(&journal->j_state_lock);
+ J_ASSERT(!journal->j_running_transaction);
+@@ -2021,7 +2028,7 @@ int jbd2_journal_wipe(journal_t *journal
+ if (write) {
+ /* Lock to make assertions happy... */
+ mutex_lock(&journal->j_checkpoint_mutex);
+- jbd2_mark_journal_empty(journal);
++ jbd2_mark_journal_empty(journal, WRITE_FUA);
+ mutex_unlock(&journal->j_checkpoint_mutex);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/jffs2/build.c linux-libre-4.4.7-gnu/fs/jffs2/build.c
+--- linux-libre-4.4-gnu/fs/jffs2/build.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/jffs2/build.c 2016-04-12 12:09:26.000000000 -0400
+@@ -49,7 +49,8 @@ next_inode(int *i, struct jffs2_inode_ca
+
+
+ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
+- struct jffs2_inode_cache *ic)
++ struct jffs2_inode_cache *ic,
++ int *dir_hardlinks)
+ {
+ struct jffs2_full_dirent *fd;
+
+@@ -68,19 +69,21 @@ static void jffs2_build_inode_pass1(stru
+ dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
+ fd->name, fd->ino, ic->ino);
+ jffs2_mark_node_obsolete(c, fd->raw);
++ /* Clear the ic/raw union so it doesn't cause problems later. */
++ fd->ic = NULL;
+ continue;
+ }
+
++ /* From this point, fd->raw is no longer used so we can set fd->ic */
++ fd->ic = child_ic;
++ child_ic->pino_nlink++;
++ /* If we appear (at this stage) to have hard-linked directories,
++ * set a flag to trigger a scan later */
+ if (fd->type == DT_DIR) {
+- if (child_ic->pino_nlink) {
+- JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
+- fd->name, fd->ino, ic->ino);
+- /* TODO: What do we do about it? */
+- } else {
+- child_ic->pino_nlink = ic->ino;
+- }
+- } else
+- child_ic->pino_nlink++;
++ child_ic->flags |= INO_FLAGS_IS_DIR;
++ if (child_ic->pino_nlink > 1)
++ *dir_hardlinks = 1;
++ }
+
+ dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
+ /* Can't free scan_dents so far. We might need them in pass 2 */
+@@ -94,8 +97,7 @@ static void jffs2_build_inode_pass1(stru
+ */
+ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
+ {
+- int ret;
+- int i;
++ int ret, i, dir_hardlinks = 0;
+ struct jffs2_inode_cache *ic;
+ struct jffs2_full_dirent *fd;
+ struct jffs2_full_dirent *dead_fds = NULL;
+@@ -119,7 +121,7 @@ static int jffs2_build_filesystem(struct
+ /* Now scan the directory tree, increasing nlink according to every dirent found. */
+ for_each_inode(i, c, ic) {
+ if (ic->scan_dents) {
+- jffs2_build_inode_pass1(c, ic);
++ jffs2_build_inode_pass1(c, ic, &dir_hardlinks);
+ cond_resched();
+ }
+ }
+@@ -155,6 +157,20 @@ static int jffs2_build_filesystem(struct
+ }
+
+ dbg_fsbuild("pass 2a complete\n");
++
++ if (dir_hardlinks) {
++ /* If we detected directory hardlinks earlier, *hopefully*
++ * they are gone now because some of the links were from
++ * dead directories which still had some old dirents lying
++ * around and not yet garbage-collected, but which have
++ * been discarded above. So clear the pino_nlink field
++ * in each directory, so that the final scan below can
++ * print appropriate warnings. */
++ for_each_inode(i, c, ic) {
++ if (ic->flags & INO_FLAGS_IS_DIR)
++ ic->pino_nlink = 0;
++ }
++ }
+ dbg_fsbuild("freeing temporary data structures\n");
+
+ /* Finally, we can scan again and free the dirent structs */
+@@ -162,6 +178,33 @@ static int jffs2_build_filesystem(struct
+ while(ic->scan_dents) {
+ fd = ic->scan_dents;
+ ic->scan_dents = fd->next;
++ /* We do use the pino_nlink field to count nlink of
++ * directories during fs build, so set it to the
++ * parent ino# now. Now that there's hopefully only
++ * one. */
++ if (fd->type == DT_DIR) {
++ if (!fd->ic) {
++ /* We'll have complained about it and marked the coresponding
++ raw node obsolete already. Just skip it. */
++ continue;
++ }
++
++ /* We *have* to have set this in jffs2_build_inode_pass1() */
++ BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR));
++
++ /* We clear ic->pino_nlink ∀ directories' ic *only* if dir_hardlinks
++ * is set. Otherwise, we know this should never trigger anyway, so
++ * we don't do the check. And ic->pino_nlink still contains the nlink
++ * value (which is 1). */
++ if (dir_hardlinks && fd->ic->pino_nlink) {
++ JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n",
++ fd->name, fd->ino, ic->ino, fd->ic->pino_nlink);
++ /* Should we unlink it from its previous parent? */
++ }
++
++ /* For directories, ic->pino_nlink holds that parent inode # */
++ fd->ic->pino_nlink = ic->ino;
++ }
+ jffs2_free_full_dirent(fd);
+ }
+ ic->scan_dents = NULL;
+@@ -240,11 +283,7 @@ static void jffs2_build_remove_unlinked_
+
+ /* Reduce nlink of the child. If it's now zero, stick it on the
+ dead_fds list to be cleaned up later. Else just free the fd */
+-
+- if (fd->type == DT_DIR)
+- child_ic->pino_nlink = 0;
+- else
+- child_ic->pino_nlink--;
++ child_ic->pino_nlink--;
+
+ if (!child_ic->pino_nlink) {
+ dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/jffs2/dir.c linux-libre-4.4.7-gnu/fs/jffs2/dir.c
+--- linux-libre-4.4-gnu/fs/jffs2/dir.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/jffs2/dir.c 2016-04-12 12:09:26.000000000 -0400
+@@ -843,9 +843,14 @@ static int jffs2_rename (struct inode *o
+
+ pr_notice("%s(): Link succeeded, unlink failed (err %d). You now have a hard link\n",
+ __func__, ret);
+- /* Might as well let the VFS know */
+- d_instantiate(new_dentry, d_inode(old_dentry));
+- ihold(d_inode(old_dentry));
++ /*
++ * We can't keep the target in dcache after that.
++ * For one thing, we can't afford dentry aliases for directories.
++ * For another, if there was a victim, we _can't_ set new inode
++ * for that sucker and we have to trigger mount eviction - the
++ * caller won't do it on its own since we are returning an error.
++ */
++ d_invalidate(new_dentry);
+ new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
+ return ret;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/jffs2/file.c linux-libre-4.4.7-gnu/fs/jffs2/file.c
+--- linux-libre-4.4-gnu/fs/jffs2/file.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/jffs2/file.c 2016-04-12 12:09:26.000000000 -0400
+@@ -137,39 +137,33 @@ static int jffs2_write_begin(struct file
+ struct page *pg;
+ struct inode *inode = mapping->host;
+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+- struct jffs2_raw_inode ri;
+- uint32_t alloc_len = 0;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ uint32_t pageofs = index << PAGE_CACHE_SHIFT;
+ int ret = 0;
+
+- jffs2_dbg(1, "%s()\n", __func__);
+-
+- if (pageofs > inode->i_size) {
+- ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+- ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+- if (ret)
+- return ret;
+- }
+-
+- mutex_lock(&f->sem);
+ pg = grab_cache_page_write_begin(mapping, index, flags);
+- if (!pg) {
+- if (alloc_len)
+- jffs2_complete_reservation(c);
+- mutex_unlock(&f->sem);
++ if (!pg)
+ return -ENOMEM;
+- }
+ *pagep = pg;
+
+- if (alloc_len) {
++ jffs2_dbg(1, "%s()\n", __func__);
++
++ if (pageofs > inode->i_size) {
+ /* Make new hole frag from old EOF to new page */
++ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
++ struct jffs2_raw_inode ri;
+ struct jffs2_full_dnode *fn;
++ uint32_t alloc_len;
+
+ jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
+ (unsigned int)inode->i_size, pageofs);
+
++ ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
++ ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
++ if (ret)
++ goto out_page;
++
++ mutex_lock(&f->sem);
+ memset(&ri, 0, sizeof(ri));
+
+ ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -196,6 +190,7 @@ static int jffs2_write_begin(struct file
+ if (IS_ERR(fn)) {
+ ret = PTR_ERR(fn);
+ jffs2_complete_reservation(c);
++ mutex_unlock(&f->sem);
+ goto out_page;
+ }
+ ret = jffs2_add_full_dnode_to_inode(c, f, fn);
+@@ -210,10 +205,12 @@ static int jffs2_write_begin(struct file
+ jffs2_mark_node_obsolete(c, fn->raw);
+ jffs2_free_full_dnode(fn);
+ jffs2_complete_reservation(c);
++ mutex_unlock(&f->sem);
+ goto out_page;
+ }
+ jffs2_complete_reservation(c);
+ inode->i_size = pageofs;
++ mutex_unlock(&f->sem);
+ }
+
+ /*
+@@ -222,18 +219,18 @@ static int jffs2_write_begin(struct file
+ * case of a short-copy.
+ */
+ if (!PageUptodate(pg)) {
++ mutex_lock(&f->sem);
+ ret = jffs2_do_readpage_nolock(inode, pg);
++ mutex_unlock(&f->sem);
+ if (ret)
+ goto out_page;
+ }
+- mutex_unlock(&f->sem);
+ jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
+ return ret;
+
+ out_page:
+ unlock_page(pg);
+ page_cache_release(pg);
+- mutex_unlock(&f->sem);
+ return ret;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/jffs2/gc.c linux-libre-4.4.7-gnu/fs/jffs2/gc.c
+--- linux-libre-4.4-gnu/fs/jffs2/gc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/jffs2/gc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(s
+ BUG_ON(start > orig_start);
+ }
+
+- /* First, use readpage() to read the appropriate page into the page cache */
+- /* Q: What happens if we actually try to GC the _same_ page for which commit_write()
+- * triggered garbage collection in the first place?
+- * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the
+- * page OK. We'll actually write it out again in commit_write, which is a little
+- * suboptimal, but at least we're correct.
+- */
++ /* The rules state that we must obtain the page lock *before* f->sem, so
++ * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's
++ * actually going to *change* so we're safe; we only allow reading.
++ *
++ * It is important to note that jffs2_write_begin() will ensure that its
++ * page is marked Uptodate before allocating space. That means that if we
++ * end up here trying to GC the *same* page that jffs2_write_begin() is
++ * trying to write out, read_cache_page() will not deadlock. */
++ mutex_unlock(&f->sem);
+ pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg);
++ mutex_lock(&f->sem);
+
+ if (IS_ERR(pg_ptr)) {
+ pr_warn("read_cache_page() returned error: %ld\n",
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/jffs2/nodelist.h linux-libre-4.4.7-gnu/fs/jffs2/nodelist.h
+--- linux-libre-4.4-gnu/fs/jffs2/nodelist.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/jffs2/nodelist.h 2016-04-12 12:09:26.000000000 -0400
+@@ -194,6 +194,7 @@ struct jffs2_inode_cache {
+ #define INO_STATE_CLEARING 6 /* In clear_inode() */
+
+ #define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */
++#define INO_FLAGS_IS_DIR 0x02 /* is a directory */
+
+ #define RAWNODE_CLASS_INODE_CACHE 0
+ #define RAWNODE_CLASS_XATTR_DATUM 1
+@@ -249,7 +250,10 @@ struct jffs2_readinode_info
+
+ struct jffs2_full_dirent
+ {
+- struct jffs2_raw_node_ref *raw;
++ union {
++ struct jffs2_raw_node_ref *raw;
++ struct jffs2_inode_cache *ic; /* Just during part of build */
++ };
+ struct jffs2_full_dirent *next;
+ uint32_t version;
+ uint32_t ino; /* == zero for unlink */
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/jffs2/README.Locking linux-libre-4.4.7-gnu/fs/jffs2/README.Locking
+--- linux-libre-4.4-gnu/fs/jffs2/README.Locking 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/jffs2/README.Locking 2016-04-12 12:09:26.000000000 -0400
+@@ -2,10 +2,6 @@
+ JFFS2 LOCKING DOCUMENTATION
+ ---------------------------
+
+-At least theoretically, JFFS2 does not require the Big Kernel Lock
+-(BKL), which was always helpfully obtained for it by Linux 2.4 VFS
+-code. It has its own locking, as described below.
+-
+ This document attempts to describe the existing locking rules for
+ JFFS2. It is not expected to remain perfectly up to date, but ought to
+ be fairly close.
+@@ -69,6 +65,7 @@ Ordering constraints:
+ any f->sem held.
+ 2. Never attempt to lock two file mutexes in one thread.
+ No ordering rules have been made for doing so.
++ 3. Never lock a page cache page with f->sem held.
+
+
+ erase_completion_lock spinlock
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/locks.c linux-libre-4.4.7-gnu/fs/locks.c
+--- linux-libre-4.4-gnu/fs/locks.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/locks.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2182,7 +2182,6 @@ int fcntl_setlk(unsigned int fd, struct
+ goto out;
+ }
+
+-again:
+ error = flock_to_posix_lock(filp, file_lock, &flock);
+ if (error)
+ goto out;
+@@ -2224,19 +2223,22 @@ again:
+ * Attempt to detect a close/fcntl race and recover by
+ * releasing the lock that was just acquired.
+ */
+- /*
+- * we need that spin_lock here - it prevents reordering between
+- * update of i_flctx->flc_posix and check for it done in close().
+- * rcu_read_lock() wouldn't do.
+- */
+- spin_lock(&current->files->file_lock);
+- f = fcheck(fd);
+- spin_unlock(&current->files->file_lock);
+- if (!error && f != filp && flock.l_type != F_UNLCK) {
+- flock.l_type = F_UNLCK;
+- goto again;
++ if (!error && file_lock->fl_type != F_UNLCK) {
++ /*
++ * We need that spin_lock here - it prevents reordering between
++ * update of i_flctx->flc_posix and check for it done in
++ * close(). rcu_read_lock() wouldn't do.
++ */
++ spin_lock(&current->files->file_lock);
++ f = fcheck(fd);
++ spin_unlock(&current->files->file_lock);
++ if (f != filp) {
++ file_lock->fl_type = F_UNLCK;
++ error = do_lock_file_wait(filp, cmd, file_lock);
++ WARN_ON_ONCE(error);
++ error = -EBADF;
++ }
+ }
+-
+ out:
+ locks_free_lock(file_lock);
+ return error;
+@@ -2322,7 +2324,6 @@ int fcntl_setlk64(unsigned int fd, struc
+ goto out;
+ }
+
+-again:
+ error = flock64_to_posix_lock(filp, file_lock, &flock);
+ if (error)
+ goto out;
+@@ -2364,14 +2365,22 @@ again:
+ * Attempt to detect a close/fcntl race and recover by
+ * releasing the lock that was just acquired.
+ */
+- spin_lock(&current->files->file_lock);
+- f = fcheck(fd);
+- spin_unlock(&current->files->file_lock);
+- if (!error && f != filp && flock.l_type != F_UNLCK) {
+- flock.l_type = F_UNLCK;
+- goto again;
++ if (!error && file_lock->fl_type != F_UNLCK) {
++ /*
++ * We need that spin_lock here - it prevents reordering between
++ * update of i_flctx->flc_posix and check for it done in
++ * close(). rcu_read_lock() wouldn't do.
++ */
++ spin_lock(&current->files->file_lock);
++ f = fcheck(fd);
++ spin_unlock(&current->files->file_lock);
++ if (f != filp) {
++ file_lock->fl_type = F_UNLCK;
++ error = do_lock_file_wait(filp, cmd, file_lock);
++ WARN_ON_ONCE(error);
++ error = -EBADF;
++ }
+ }
+-
+ out:
+ locks_free_lock(file_lock);
+ return error;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/namei.c linux-libre-4.4.7-gnu/fs/namei.c
+--- linux-libre-4.4-gnu/fs/namei.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/namei.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1711,6 +1711,11 @@ static inline int should_follow_link(str
+ return 0;
+ if (!follow)
+ return 0;
++ /* make sure that d_is_symlink above matches inode */
++ if (nd->flags & LOOKUP_RCU) {
++ if (read_seqcount_retry(&link->dentry->d_seq, seq))
++ return -ECHILD;
++ }
+ return pick_link(nd, link, inode, seq);
+ }
+
+@@ -1742,11 +1747,11 @@ static int walk_component(struct nameida
+ if (err < 0)
+ return err;
+
+- inode = d_backing_inode(path.dentry);
+ seq = 0; /* we are already out of RCU mode */
+ err = -ENOENT;
+ if (d_is_negative(path.dentry))
+ goto out_path_put;
++ inode = d_backing_inode(path.dentry);
+ }
+
+ if (flags & WALK_PUT)
+@@ -3130,12 +3135,12 @@ retry_lookup:
+ return error;
+
+ BUG_ON(nd->flags & LOOKUP_RCU);
+- inode = d_backing_inode(path.dentry);
+ seq = 0; /* out of RCU mode, so the value doesn't matter */
+ if (unlikely(d_is_negative(path.dentry))) {
+ path_to_nameidata(&path, nd);
+ return -ENOENT;
+ }
++ inode = d_backing_inode(path.dentry);
+ finish_lookup:
+ if (nd->depth)
+ put_link(nd);
+@@ -3144,11 +3149,6 @@ finish_lookup:
+ if (unlikely(error))
+ return error;
+
+- if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
+- path_to_nameidata(&path, nd);
+- return -ELOOP;
+- }
+-
+ if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
+ path_to_nameidata(&path, nd);
+ } else {
+@@ -3167,6 +3167,10 @@ finish_open:
+ return error;
+ }
+ audit_inode(nd->name, nd->path.dentry, 0);
++ if (unlikely(d_is_symlink(nd->path.dentry)) && !(open_flag & O_PATH)) {
++ error = -ELOOP;
++ goto out;
++ }
+ error = -EISDIR;
+ if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
+ goto out;
+@@ -3210,6 +3214,10 @@ opened:
+ goto exit_fput;
+ }
+ out:
++ if (unlikely(error > 0)) {
++ WARN_ON(1);
++ error = -EINVAL;
++ }
+ if (got_write)
+ mnt_drop_write(nd->path.mnt);
+ path_put(&save_parent);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ncpfs/dir.c linux-libre-4.4.7-gnu/fs/ncpfs/dir.c
+--- linux-libre-4.4-gnu/fs/ncpfs/dir.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ncpfs/dir.c 2016-04-12 12:09:26.000000000 -0400
+@@ -633,7 +633,7 @@ ncp_fill_cache(struct file *file, struct
+ d_rehash(newdent);
+ } else {
+ spin_lock(&dentry->d_lock);
+- NCP_FINFO(inode)->flags &= ~NCPI_DIR_CACHE;
++ NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE;
+ spin_unlock(&dentry->d_lock);
+ }
+ } else {
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/nfs/flexfilelayout/flexfilelayout.c linux-libre-4.4.7-gnu/fs/nfs/flexfilelayout/flexfilelayout.c
+--- linux-libre-4.4-gnu/fs/nfs/flexfilelayout/flexfilelayout.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/nfs/flexfilelayout/flexfilelayout.c 2016-04-12 12:09:26.000000000 -0400
+@@ -145,7 +145,7 @@ static bool ff_mirror_match_fh(const str
+ return false;
+ for (i = 0; i < m1->fh_versions_cnt; i++) {
+ bool found_fh = false;
+- for (j = 0; j < m2->fh_versions_cnt; i++) {
++ for (j = 0; j < m2->fh_versions_cnt; j++) {
+ if (nfs_compare_fh(&m1->fh_versions[i],
+ &m2->fh_versions[j]) == 0) {
+ found_fh = true;
+@@ -1859,11 +1859,9 @@ ff_layout_encode_layoutreturn(struct pnf
+ start = xdr_reserve_space(xdr, 4);
+ BUG_ON(!start);
+
+- if (ff_layout_encode_ioerr(flo, xdr, args))
+- goto out;
+-
++ ff_layout_encode_ioerr(flo, xdr, args);
+ ff_layout_encode_iostats(flo, xdr, args);
+-out:
++
+ *start = cpu_to_be32((xdr->p - start - 1) * 4);
+ dprintk("%s: Return\n", __func__);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/nfs/inode.c linux-libre-4.4.7-gnu/fs/nfs/inode.c
+--- linux-libre-4.4-gnu/fs/nfs/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/nfs/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1641,6 +1641,7 @@ static int nfs_update_inode(struct inode
+ unsigned long invalid = 0;
+ unsigned long now = jiffies;
+ unsigned long save_cache_validity;
++ bool cache_revalidated = true;
+
+ dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n",
+ __func__, inode->i_sb->s_id, inode->i_ino,
+@@ -1702,22 +1703,28 @@ static int nfs_update_inode(struct inode
+ nfs_force_lookup_revalidate(inode);
+ inode->i_version = fattr->change_attr;
+ }
+- } else
++ } else {
+ nfsi->cache_validity |= save_cache_validity;
++ cache_revalidated = false;
++ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
+ memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+- } else if (server->caps & NFS_CAP_MTIME)
++ } else if (server->caps & NFS_CAP_MTIME) {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATTR
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
+ memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+- } else if (server->caps & NFS_CAP_CTIME)
++ } else if (server->caps & NFS_CAP_CTIME) {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATTR
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+ /* Check if our cached file size is stale */
+ if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
+@@ -1737,19 +1744,23 @@ static int nfs_update_inode(struct inode
+ (long long)cur_isize,
+ (long long)new_isize);
+ }
+- } else
++ } else {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATTR
+ | NFS_INO_REVAL_PAGECACHE
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+
+ if (fattr->valid & NFS_ATTR_FATTR_ATIME)
+ memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
+- else if (server->caps & NFS_CAP_ATIME)
++ else if (server->caps & NFS_CAP_ATIME) {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATIME
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_MODE) {
+ if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) {
+@@ -1758,36 +1769,42 @@ static int nfs_update_inode(struct inode
+ inode->i_mode = newmode;
+ invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+ }
+- } else if (server->caps & NFS_CAP_MODE)
++ } else if (server->caps & NFS_CAP_MODE) {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATTR
+ | NFS_INO_INVALID_ACCESS
+ | NFS_INO_INVALID_ACL
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
+ if (!uid_eq(inode->i_uid, fattr->uid)) {
+ invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+ inode->i_uid = fattr->uid;
+ }
+- } else if (server->caps & NFS_CAP_OWNER)
++ } else if (server->caps & NFS_CAP_OWNER) {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATTR
+ | NFS_INO_INVALID_ACCESS
+ | NFS_INO_INVALID_ACL
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
+ if (!gid_eq(inode->i_gid, fattr->gid)) {
+ invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+ inode->i_gid = fattr->gid;
+ }
+- } else if (server->caps & NFS_CAP_OWNER_GROUP)
++ } else if (server->caps & NFS_CAP_OWNER_GROUP) {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATTR
+ | NFS_INO_INVALID_ACCESS
+ | NFS_INO_INVALID_ACL
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
+ if (inode->i_nlink != fattr->nlink) {
+@@ -1796,19 +1813,22 @@ static int nfs_update_inode(struct inode
+ invalid |= NFS_INO_INVALID_DATA;
+ set_nlink(inode, fattr->nlink);
+ }
+- } else if (server->caps & NFS_CAP_NLINK)
++ } else if (server->caps & NFS_CAP_NLINK) {
+ nfsi->cache_validity |= save_cache_validity &
+ (NFS_INO_INVALID_ATTR
+ | NFS_INO_REVAL_FORCED);
++ cache_revalidated = false;
++ }
+
+ if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
+ /*
+ * report the blocks in 512byte units
+ */
+ inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
+- }
+- if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
++ } else if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
+ inode->i_blocks = fattr->du.nfs2.blocks;
++ else
++ cache_revalidated = false;
+
+ /* Update attrtimeo value if we're out of the unstable period */
+ if (invalid & NFS_INO_INVALID_ATTR) {
+@@ -1818,9 +1838,13 @@ static int nfs_update_inode(struct inode
+ /* Set barrier to be more recent than all outstanding updates */
+ nfsi->attr_gencount = nfs_inc_attr_generation_counter();
+ } else {
+- if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
+- if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
+- nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
++ if (cache_revalidated) {
++ if (!time_in_range_open(now, nfsi->attrtimeo_timestamp,
++ nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
++ nfsi->attrtimeo <<= 1;
++ if (nfsi->attrtimeo > NFS_MAXATTRTIMEO(inode))
++ nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
++ }
+ nfsi->attrtimeo_timestamp = now;
+ }
+ /* Set the barrier to be more recent than this fattr */
+@@ -1829,7 +1853,7 @@ static int nfs_update_inode(struct inode
+ }
+
+ /* Don't declare attrcache up to date if there were no attrs! */
+- if (fattr->valid != 0)
++ if (cache_revalidated)
+ invalid &= ~NFS_INO_INVALID_ATTR;
+
+ /* Don't invalidate the data if we were to blame */
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/nfs/nfs4proc.c linux-libre-4.4.7-gnu/fs/nfs/nfs4proc.c
+--- linux-libre-4.4-gnu/fs/nfs/nfs4proc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/nfs/nfs4proc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1385,6 +1385,7 @@ static void __update_open_stateid(struct
+ * Protect the call to nfs4_state_set_mode_locked and
+ * serialise the stateid update
+ */
++ spin_lock(&state->owner->so_lock);
+ write_seqlock(&state->seqlock);
+ if (deleg_stateid != NULL) {
+ nfs4_stateid_copy(&state->stateid, deleg_stateid);
+@@ -1393,7 +1394,6 @@ static void __update_open_stateid(struct
+ if (open_stateid != NULL)
+ nfs_set_open_stateid_locked(state, open_stateid, fmode);
+ write_sequnlock(&state->seqlock);
+- spin_lock(&state->owner->so_lock);
+ update_open_stateflags(state, fmode);
+ spin_unlock(&state->owner->so_lock);
+ }
+@@ -2461,9 +2461,9 @@ static int _nfs4_open_and_get_state(stru
+ dentry = d_add_unique(dentry, igrab(state->inode));
+ if (dentry == NULL) {
+ dentry = opendata->dentry;
+- } else if (dentry != ctx->dentry) {
++ } else {
+ dput(ctx->dentry);
+- ctx->dentry = dget(dentry);
++ ctx->dentry = dentry;
+ }
+ nfs_set_verifier(dentry,
+ nfs_save_change_attribute(d_inode(opendata->dir)));
+@@ -8054,7 +8054,6 @@ static void nfs4_layoutreturn_release(vo
+ pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
+ pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range);
+ pnfs_clear_layoutreturn_waitbit(lo);
+- lo->plh_block_lgets--;
+ spin_unlock(&lo->plh_inode->i_lock);
+ pnfs_free_lseg_list(&freeme);
+ pnfs_put_layout_hdr(lrp->args.layout);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/nfsd/nfs4proc.c linux-libre-4.4.7-gnu/fs/nfsd/nfs4proc.c
+--- linux-libre-4.4-gnu/fs/nfsd/nfs4proc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/nfsd/nfs4proc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -877,6 +877,7 @@ nfsd4_secinfo(struct svc_rqst *rqstp, st
+ &exp, &dentry);
+ if (err)
+ return err;
++ fh_unlock(&cstate->current_fh);
+ if (d_really_is_negative(dentry)) {
+ exp_put(exp);
+ err = nfserr_noent;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/nfsd/nfs4xdr.c linux-libre-4.4.7-gnu/fs/nfsd/nfs4xdr.c
+--- linux-libre-4.4-gnu/fs/nfsd/nfs4xdr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/nfsd/nfs4xdr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1072,8 +1072,9 @@ nfsd4_decode_rename(struct nfsd4_compoun
+
+ READ_BUF(4);
+ rename->rn_snamelen = be32_to_cpup(p++);
+- READ_BUF(rename->rn_snamelen + 4);
++ READ_BUF(rename->rn_snamelen);
+ SAVEMEM(rename->rn_sname, rename->rn_snamelen);
++ READ_BUF(4);
+ rename->rn_tnamelen = be32_to_cpup(p++);
+ READ_BUF(rename->rn_tnamelen);
+ SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
+@@ -1155,13 +1156,14 @@ nfsd4_decode_setclientid(struct nfsd4_co
+ READ_BUF(8);
+ setclientid->se_callback_prog = be32_to_cpup(p++);
+ setclientid->se_callback_netid_len = be32_to_cpup(p++);
+-
+- READ_BUF(setclientid->se_callback_netid_len + 4);
++ READ_BUF(setclientid->se_callback_netid_len);
+ SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
++ READ_BUF(4);
+ setclientid->se_callback_addr_len = be32_to_cpup(p++);
+
+- READ_BUF(setclientid->se_callback_addr_len + 4);
++ READ_BUF(setclientid->se_callback_addr_len);
+ SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
++ READ_BUF(4);
+ setclientid->se_callback_ident = be32_to_cpup(p++);
+
+ DECODE_TAIL;
+@@ -1815,8 +1817,9 @@ nfsd4_decode_compound(struct nfsd4_compo
+
+ READ_BUF(4);
+ argp->taglen = be32_to_cpup(p++);
+- READ_BUF(argp->taglen + 8);
++ READ_BUF(argp->taglen);
+ SAVEMEM(argp->tag, argp->taglen);
++ READ_BUF(8);
+ argp->minorversion = be32_to_cpup(p++);
+ argp->opcnt = be32_to_cpup(p++);
+ max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ocfs2/aops.c linux-libre-4.4.7-gnu/fs/ocfs2/aops.c
+--- linux-libre-4.4-gnu/fs/ocfs2/aops.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ocfs2/aops.c 2016-04-12 12:09:26.000000000 -0400
+@@ -956,6 +956,7 @@ clean_orphan:
+ tmp_ret = ocfs2_del_inode_from_orphan(osb, inode, di_bh,
+ update_isize, end);
+ if (tmp_ret < 0) {
++ ocfs2_inode_unlock(inode, 1);
+ ret = tmp_ret;
+ mlog_errno(ret);
+ brelse(di_bh);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ocfs2/dlm/dlmconvert.c linux-libre-4.4.7-gnu/fs/ocfs2/dlm/dlmconvert.c
+--- linux-libre-4.4-gnu/fs/ocfs2/dlm/dlmconvert.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ocfs2/dlm/dlmconvert.c 2016-04-12 12:09:26.000000000 -0400
+@@ -262,6 +262,7 @@ enum dlm_status dlmconvert_remote(struct
+ struct dlm_lock *lock, int flags, int type)
+ {
+ enum dlm_status status;
++ u8 old_owner = res->owner;
+
+ mlog(0, "type=%d, convert_type=%d, busy=%d\n", lock->ml.type,
+ lock->ml.convert_type, res->state & DLM_LOCK_RES_IN_PROGRESS);
+@@ -287,6 +288,19 @@ enum dlm_status dlmconvert_remote(struct
+ status = DLM_DENIED;
+ goto bail;
+ }
++
++ if (lock->ml.type == type && lock->ml.convert_type == LKM_IVMODE) {
++ mlog(0, "last convert request returned DLM_RECOVERING, but "
++ "owner has already queued and sent ast to me. res %.*s, "
++ "(cookie=%u:%llu, type=%d, conv=%d)\n",
++ res->lockname.len, res->lockname.name,
++ dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)),
++ dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)),
++ lock->ml.type, lock->ml.convert_type);
++ status = DLM_NORMAL;
++ goto bail;
++ }
++
+ res->state |= DLM_LOCK_RES_IN_PROGRESS;
+ /* move lock to local convert queue */
+ /* do not alter lock refcount. switching lists. */
+@@ -316,11 +330,19 @@ enum dlm_status dlmconvert_remote(struct
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ lock->convert_pending = 0;
+- /* if it failed, move it back to granted queue */
++ /* if it failed, move it back to granted queue.
++ * if master returns DLM_NORMAL and then down before sending ast,
++ * it may have already been moved to granted queue, reset to
++ * DLM_RECOVERING and retry convert */
+ if (status != DLM_NORMAL) {
+ if (status != DLM_NOTQUEUED)
+ dlm_error(status);
+ dlm_revert_pending_convert(res, lock);
++ } else if ((res->state & DLM_LOCK_RES_RECOVERING) ||
++ (old_owner != res->owner)) {
++ mlog(0, "res %.*s is in recovering or has been recovered.\n",
++ res->lockname.len, res->lockname.name);
++ status = DLM_RECOVERING;
+ }
+ bail:
+ spin_unlock(&res->spinlock);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ocfs2/dlm/dlmmaster.c linux-libre-4.4.7-gnu/fs/ocfs2/dlm/dlmmaster.c
+--- linux-libre-4.4-gnu/fs/ocfs2/dlm/dlmmaster.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ocfs2/dlm/dlmmaster.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2519,6 +2519,11 @@ static int dlm_migrate_lockres(struct dl
+ spin_lock(&dlm->master_lock);
+ ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name,
+ namelen, target, dlm->node_num);
++ /* get an extra reference on the mle.
++ * otherwise the assert_master from the new
++ * master will destroy this.
++ */
++ dlm_get_mle_inuse(mle);
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+@@ -2554,6 +2559,7 @@ fail:
+ if (mle_added) {
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
++ dlm_put_mle_inuse(mle);
+ } else if (mle) {
+ kmem_cache_free(dlm_mle_cache, mle);
+ mle = NULL;
+@@ -2571,17 +2577,6 @@ fail:
+ * ensure that all assert_master work is flushed. */
+ flush_workqueue(dlm->dlm_worker);
+
+- /* get an extra reference on the mle.
+- * otherwise the assert_master from the new
+- * master will destroy this.
+- * also, make sure that all callers of dlm_get_mle
+- * take both dlm->spinlock and dlm->master_lock */
+- spin_lock(&dlm->spinlock);
+- spin_lock(&dlm->master_lock);
+- dlm_get_mle_inuse(mle);
+- spin_unlock(&dlm->master_lock);
+- spin_unlock(&dlm->spinlock);
+-
+ /* notify new node and send all lock state */
+ /* call send_one_lockres with migration flag.
+ * this serves as notice to the target node that a
+@@ -3312,6 +3307,15 @@ top:
+ mle->new_master != dead_node)
+ continue;
+
++ if (mle->new_master == dead_node && mle->inuse) {
++ mlog(ML_NOTICE, "%s: target %u died during "
++ "migration from %u, the MLE is "
++ "still keep used, ignore it!\n",
++ dlm->name, dead_node,
++ mle->master);
++ continue;
++ }
++
+ /* If we have reached this point, this mle needs to be
+ * removed from the list and freed. */
+ dlm_clean_migration_mle(dlm, mle);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ocfs2/dlm/dlmrecovery.c linux-libre-4.4.7-gnu/fs/ocfs2/dlm/dlmrecovery.c
+--- linux-libre-4.4-gnu/fs/ocfs2/dlm/dlmrecovery.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ocfs2/dlm/dlmrecovery.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2064,7 +2064,6 @@ void dlm_move_lockres_to_recovery_list(s
+ dlm_lock_get(lock);
+ if (lock->convert_pending) {
+ /* move converting lock back to granted */
+- BUG_ON(i != DLM_CONVERTING_LIST);
+ mlog(0, "node died with convert pending "
+ "on %.*s. move back to granted list.\n",
+ res->lockname.len, res->lockname.name);
+@@ -2360,6 +2359,8 @@ static void dlm_do_local_recovery_cleanu
+ break;
+ }
+ }
++ dlm_lockres_clear_refmap_bit(dlm, res,
++ dead_node);
+ spin_unlock(&res->spinlock);
+ continue;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/ocfs2/dlmglue.c linux-libre-4.4.7-gnu/fs/ocfs2/dlmglue.c
+--- linux-libre-4.4-gnu/fs/ocfs2/dlmglue.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/ocfs2/dlmglue.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1390,6 +1390,7 @@ static int __ocfs2_cluster_lock(struct o
+ unsigned int gen;
+ int noqueue_attempted = 0;
+ int dlm_locked = 0;
++ int kick_dc = 0;
+
+ if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED)) {
+ mlog_errno(-EINVAL);
+@@ -1524,7 +1525,12 @@ update_holders:
+ unlock:
+ lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
+
++ /* ocfs2_unblock_lock reques on seeing OCFS2_LOCK_UPCONVERT_FINISHING */
++ kick_dc = (lockres->l_flags & OCFS2_LOCK_BLOCKED);
++
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
++ if (kick_dc)
++ ocfs2_wake_downconvert_thread(osb);
+ out:
+ /*
+ * This is helping work around a lock inversion between the page lock
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/open.c linux-libre-4.4.7-gnu/fs/open.c
+--- linux-libre-4.4-gnu/fs/open.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/open.c 2016-04-12 12:09:26.000000000 -0400
+@@ -995,14 +995,12 @@ struct file *filp_open(const char *filen
+ EXPORT_SYMBOL(filp_open);
+
+ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
+- const char *filename, int flags)
++ const char *filename, int flags, umode_t mode)
+ {
+ struct open_flags op;
+- int err = build_open_flags(flags, 0, &op);
++ int err = build_open_flags(flags, mode, &op);
+ if (err)
+ return ERR_PTR(err);
+- if (flags & O_CREAT)
+- return ERR_PTR(-EINVAL);
+ return do_file_open_root(dentry, mnt, filename, &op);
+ }
+ EXPORT_SYMBOL(file_open_root);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/overlayfs/copy_up.c linux-libre-4.4.7-gnu/fs/overlayfs/copy_up.c
+--- linux-libre-4.4-gnu/fs/overlayfs/copy_up.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/overlayfs/copy_up.c 2016-04-12 12:09:26.000000000 -0400
+@@ -22,9 +22,9 @@
+
+ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
+ {
+- ssize_t list_size, size;
+- char *buf, *name, *value;
+- int error;
++ ssize_t list_size, size, value_size = 0;
++ char *buf, *name, *value = NULL;
++ int uninitialized_var(error);
+
+ if (!old->d_inode->i_op->getxattr ||
+ !new->d_inode->i_op->getxattr)
+@@ -41,29 +41,40 @@ int ovl_copy_xattr(struct dentry *old, s
+ if (!buf)
+ return -ENOMEM;
+
+- error = -ENOMEM;
+- value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
+- if (!value)
+- goto out;
+-
+ list_size = vfs_listxattr(old, buf, list_size);
+ if (list_size <= 0) {
+ error = list_size;
+- goto out_free_value;
++ goto out;
+ }
+
+ for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
+- size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX);
+- if (size <= 0) {
++retry:
++ size = vfs_getxattr(old, name, value, value_size);
++ if (size == -ERANGE)
++ size = vfs_getxattr(old, name, NULL, 0);
++
++ if (size < 0) {
+ error = size;
+- goto out_free_value;
++ break;
++ }
++
++ if (size > value_size) {
++ void *new;
++
++ new = krealloc(value, size, GFP_KERNEL);
++ if (!new) {
++ error = -ENOMEM;
++ break;
++ }
++ value = new;
++ value_size = size;
++ goto retry;
+ }
++
+ error = vfs_setxattr(new, name, value, size, 0);
+ if (error)
+- goto out_free_value;
++ break;
+ }
+-
+-out_free_value:
+ kfree(value);
+ out:
+ kfree(buf);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/overlayfs/dir.c linux-libre-4.4.7-gnu/fs/overlayfs/dir.c
+--- linux-libre-4.4-gnu/fs/overlayfs/dir.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/overlayfs/dir.c 2016-04-12 12:09:26.000000000 -0400
+@@ -618,7 +618,8 @@ static int ovl_remove_upper(struct dentr
+ * sole user of this dentry. Too tricky... Just unhash for
+ * now.
+ */
+- d_drop(dentry);
++ if (!err)
++ d_drop(dentry);
+ mutex_unlock(&dir->i_mutex);
+
+ return err;
+@@ -903,6 +904,13 @@ static int ovl_rename2(struct inode *old
+ if (!overwrite && new_is_dir && !old_opaque && new_opaque)
+ ovl_remove_opaque(newdentry);
+
++ /*
++ * Old dentry now lives in different location. Dentries in
++ * lowerstack are stale. We cannot drop them here because
++ * access to them is lockless. This could be only pure upper
++ * or opaque directory - numlower is zero. Or upper non-dir
++ * entry - its pureness is tracked by flag opaque.
++ */
+ if (old_opaque != new_opaque) {
+ ovl_dentry_set_opaque(old, new_opaque);
+ if (!overwrite)
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/overlayfs/inode.c linux-libre-4.4.7-gnu/fs/overlayfs/inode.c
+--- linux-libre-4.4-gnu/fs/overlayfs/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/overlayfs/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -42,6 +42,19 @@ int ovl_setattr(struct dentry *dentry, s
+ int err;
+ struct dentry *upperdentry;
+
++ /*
++ * Check for permissions before trying to copy-up. This is redundant
++ * since it will be rechecked later by ->setattr() on upper dentry. But
++ * without this, copy-up can be triggered by just about anybody.
++ *
++ * We don't initialize inode->size, which just means that
++ * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not
++ * check for a swapfile (which this won't be anyway).
++ */
++ err = inode_change_ok(dentry->d_inode, attr);
++ if (err)
++ return err;
++
+ err = ovl_want_write(dentry);
+ if (err)
+ goto out;
+@@ -52,6 +65,8 @@ int ovl_setattr(struct dentry *dentry, s
+
+ mutex_lock(&upperdentry->d_inode->i_mutex);
+ err = notify_change(upperdentry, attr, NULL);
++ if (!err)
++ ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
+ mutex_unlock(&upperdentry->d_inode->i_mutex);
+ }
+ ovl_drop_write(dentry);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/overlayfs/readdir.c linux-libre-4.4.7-gnu/fs/overlayfs/readdir.c
+--- linux-libre-4.4-gnu/fs/overlayfs/readdir.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/overlayfs/readdir.c 2016-04-12 12:09:26.000000000 -0400
+@@ -571,7 +571,8 @@ void ovl_cleanup_whiteouts(struct dentry
+ (int) PTR_ERR(dentry));
+ continue;
+ }
+- ovl_cleanup(upper->d_inode, dentry);
++ if (dentry->d_inode)
++ ovl_cleanup(upper->d_inode, dentry);
+ dput(dentry);
+ }
+ mutex_unlock(&upper->d_inode->i_mutex);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/overlayfs/super.c linux-libre-4.4.7-gnu/fs/overlayfs/super.c
+--- linux-libre-4.4-gnu/fs/overlayfs/super.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/overlayfs/super.c 2016-04-12 12:09:26.000000000 -0400
+@@ -9,6 +9,7 @@
+
+ #include <linux/fs.h>
+ #include <linux/namei.h>
++#include <linux/pagemap.h>
+ #include <linux/xattr.h>
+ #include <linux/security.h>
+ #include <linux/mount.h>
+@@ -75,12 +76,14 @@ enum ovl_path_type ovl_path_type(struct
+ if (oe->__upperdentry) {
+ type = __OVL_PATH_UPPER;
+
+- if (oe->numlower) {
+- if (S_ISDIR(dentry->d_inode->i_mode))
+- type |= __OVL_PATH_MERGE;
+- } else if (!oe->opaque) {
++ /*
++ * Non-dir dentry can hold lower dentry from previous
++ * location. Its purity depends only on opaque flag.
++ */
++ if (oe->numlower && S_ISDIR(dentry->d_inode->i_mode))
++ type |= __OVL_PATH_MERGE;
++ else if (!oe->opaque)
+ type |= __OVL_PATH_PURE;
+- }
+ } else {
+ if (oe->numlower > 1)
+ type |= __OVL_PATH_MERGE;
+@@ -321,6 +324,7 @@ static const struct dentry_operations ov
+
+ static const struct dentry_operations ovl_reval_dentry_operations = {
+ .d_release = ovl_dentry_release,
++ .d_select_inode = ovl_d_select_inode,
+ .d_revalidate = ovl_dentry_revalidate,
+ .d_weak_revalidate = ovl_dentry_weak_revalidate,
+ };
+@@ -910,6 +914,7 @@ static int ovl_fill_super(struct super_b
+ }
+
+ sb->s_stack_depth = 0;
++ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ if (ufs->config.upperdir) {
+ if (!ufs->config.workdir) {
+ pr_err("overlayfs: missing 'workdir'\n");
+@@ -1053,6 +1058,9 @@ static int ovl_fill_super(struct super_b
+
+ root_dentry->d_fsdata = oe;
+
++ ovl_copyattr(ovl_dentry_real(root_dentry)->d_inode,
++ root_dentry->d_inode);
++
+ sb->s_magic = OVERLAYFS_SUPER_MAGIC;
+ sb->s_op = &ovl_super_operations;
+ sb->s_root = root_dentry;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/proc/array.c linux-libre-4.4.7-gnu/fs/proc/array.c
+--- linux-libre-4.4-gnu/fs/proc/array.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/proc/array.c 2016-04-12 12:09:26.000000000 -0400
+@@ -395,7 +395,7 @@ static int do_task_stat(struct seq_file
+
+ state = *get_task_state(task);
+ vsize = eip = esp = 0;
+- permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
++ permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT);
+ mm = get_task_mm(task);
+ if (mm) {
+ vsize = task_vsize(mm);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/proc/base.c linux-libre-4.4.7-gnu/fs/proc/base.c
+--- linux-libre-4.4-gnu/fs/proc/base.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/proc/base.c 2016-04-12 12:09:26.000000000 -0400
+@@ -403,7 +403,7 @@ static const struct file_operations proc
+ static int proc_pid_auxv(struct seq_file *m, struct pid_namespace *ns,
+ struct pid *pid, struct task_struct *task)
+ {
+- struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ);
++ struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
+ if (mm && !IS_ERR(mm)) {
+ unsigned int nwords = 0;
+ do {
+@@ -430,7 +430,8 @@ static int proc_pid_wchan(struct seq_fil
+
+ wchan = get_wchan(task);
+
+- if (wchan && ptrace_may_access(task, PTRACE_MODE_READ) && !lookup_symbol_name(wchan, symname))
++ if (wchan && ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)
++ && !lookup_symbol_name(wchan, symname))
+ seq_printf(m, "%s", symname);
+ else
+ seq_putc(m, '0');
+@@ -444,7 +445,7 @@ static int lock_trace(struct task_struct
+ int err = mutex_lock_killable(&task->signal->cred_guard_mutex);
+ if (err)
+ return err;
+- if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
++ if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) {
+ mutex_unlock(&task->signal->cred_guard_mutex);
+ return -EPERM;
+ }
+@@ -697,7 +698,7 @@ static int proc_fd_access_allowed(struct
+ */
+ task = get_proc_task(inode);
+ if (task) {
+- allowed = ptrace_may_access(task, PTRACE_MODE_READ);
++ allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
+ put_task_struct(task);
+ }
+ return allowed;
+@@ -732,7 +733,7 @@ static bool has_pid_permissions(struct p
+ return true;
+ if (in_group_p(pid->pid_gid))
+ return true;
+- return ptrace_may_access(task, PTRACE_MODE_READ);
++ return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
+ }
+
+
+@@ -809,7 +810,7 @@ struct mm_struct *proc_mem_open(struct i
+ struct mm_struct *mm = ERR_PTR(-ESRCH);
+
+ if (task) {
+- mm = mm_access(task, mode);
++ mm = mm_access(task, mode | PTRACE_MODE_FSCREDS);
+ put_task_struct(task);
+
+ if (!IS_ERR_OR_NULL(mm)) {
+@@ -1856,7 +1857,7 @@ static int map_files_d_revalidate(struct
+ if (!task)
+ goto out_notask;
+
+- mm = mm_access(task, PTRACE_MODE_READ);
++ mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
+ if (IS_ERR_OR_NULL(mm))
+ goto out;
+
+@@ -2007,7 +2008,7 @@ static struct dentry *proc_map_files_loo
+ goto out;
+
+ result = -EACCES;
+- if (!ptrace_may_access(task, PTRACE_MODE_READ))
++ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+ goto out_put_task;
+
+ result = -ENOENT;
+@@ -2060,7 +2061,7 @@ proc_map_files_readdir(struct file *file
+ goto out;
+
+ ret = -EACCES;
+- if (!ptrace_may_access(task, PTRACE_MODE_READ))
++ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
+ goto out_put_task;
+
+ ret = 0;
+@@ -2530,7 +2531,7 @@ static int do_io_accounting(struct task_
+ if (result)
+ return result;
+
+- if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
++ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
+ result = -EACCES;
+ goto out_unlock;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/proc/namespaces.c linux-libre-4.4.7-gnu/fs/proc/namespaces.c
+--- linux-libre-4.4-gnu/fs/proc/namespaces.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/proc/namespaces.c 2016-04-12 12:09:26.000000000 -0400
+@@ -42,7 +42,7 @@ static const char *proc_ns_follow_link(s
+ if (!task)
+ return error;
+
+- if (ptrace_may_access(task, PTRACE_MODE_READ)) {
++ if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
+ error = ns_get_path(&ns_path, task, ns_ops);
+ if (!error)
+ nd_jump_link(&ns_path);
+@@ -63,7 +63,7 @@ static int proc_ns_readlink(struct dentr
+ if (!task)
+ return res;
+
+- if (ptrace_may_access(task, PTRACE_MODE_READ)) {
++ if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
+ res = ns_get_name(name, sizeof(name), task, ns_ops);
+ if (res >= 0)
+ res = readlink_copy(buffer, buflen, name);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/proc/task_mmu.c linux-libre-4.4.7-gnu/fs/proc/task_mmu.c
+--- linux-libre-4.4-gnu/fs/proc/task_mmu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/proc/task_mmu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1473,18 +1473,19 @@ static int gather_pte_stats(pmd_t *pmd,
+ static int gather_hugetlb_stats(pte_t *pte, unsigned long hmask,
+ unsigned long addr, unsigned long end, struct mm_walk *walk)
+ {
++ pte_t huge_pte = huge_ptep_get(pte);
+ struct numa_maps *md;
+ struct page *page;
+
+- if (!pte_present(*pte))
++ if (!pte_present(huge_pte))
+ return 0;
+
+- page = pte_page(*pte);
++ page = pte_page(huge_pte);
+ if (!page)
+ return 0;
+
+ md = walk->private;
+- gather_stats(page, md, pte_dirty(*pte), 1);
++ gather_stats(page, md, pte_dirty(huge_pte), 1);
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/proc_namespace.c linux-libre-4.4.7-gnu/fs/proc_namespace.c
+--- linux-libre-4.4-gnu/fs/proc_namespace.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/proc_namespace.c 2016-04-12 12:09:26.000000000 -0400
+@@ -197,6 +197,8 @@ static int show_vfsstat(struct seq_file
+ if (sb->s_op->show_devname) {
+ seq_puts(m, "device ");
+ err = sb->s_op->show_devname(m, mnt_path.dentry);
++ if (err)
++ goto out;
+ } else {
+ if (r->mnt_devname) {
+ seq_puts(m, "device ");
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/quota/dquot.c linux-libre-4.4.7-gnu/fs/quota/dquot.c
+--- linux-libre-4.4-gnu/fs/quota/dquot.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/quota/dquot.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1398,7 +1398,7 @@ static int dquot_active(const struct ino
+ static int __dquot_initialize(struct inode *inode, int type)
+ {
+ int cnt, init_needed = 0;
+- struct dquot **dquots, *got[MAXQUOTAS];
++ struct dquot **dquots, *got[MAXQUOTAS] = {};
+ struct super_block *sb = inode->i_sb;
+ qsize_t rsv;
+ int ret = 0;
+@@ -1415,7 +1415,6 @@ static int __dquot_initialize(struct ino
+ int rc;
+ struct dquot *dquot;
+
+- got[cnt] = NULL;
+ if (type != -1 && cnt != type)
+ continue;
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/splice.c linux-libre-4.4.7-gnu/fs/splice.c
+--- linux-libre-4.4-gnu/fs/splice.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/splice.c 2016-04-12 12:09:26.000000000 -0400
+@@ -185,6 +185,9 @@ ssize_t splice_to_pipe(struct pipe_inode
+ unsigned int spd_pages = spd->nr_pages;
+ int ret, do_wakeup, page_nr;
+
++ if (!spd_pages)
++ return 0;
++
+ ret = 0;
+ do_wakeup = 0;
+ page_nr = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/super.c linux-libre-4.4.7-gnu/fs/super.c
+--- linux-libre-4.4-gnu/fs/super.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/super.c 2016-04-12 12:09:26.000000000 -0400
+@@ -415,6 +415,7 @@ void generic_shutdown_super(struct super
+ sb->s_flags &= ~MS_ACTIVE;
+
+ fsnotify_unmount_inodes(sb);
++ cgroup_writeback_umount();
+
+ evict_inodes(sb);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/timerfd.c linux-libre-4.4.7-gnu/fs/timerfd.c
+--- linux-libre-4.4-gnu/fs/timerfd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/timerfd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -153,7 +153,7 @@ static ktime_t timerfd_get_remaining(str
+ if (isalarm(ctx))
+ remaining = alarm_expires_remaining(&ctx->t.alarm);
+ else
+- remaining = hrtimer_expires_remaining(&ctx->t.tmr);
++ remaining = hrtimer_expires_remaining_adjusted(&ctx->t.tmr);
+
+ return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/udf/inode.c linux-libre-4.4.7-gnu/fs/udf/inode.c
+--- linux-libre-4.4-gnu/fs/udf/inode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/udf/inode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2047,14 +2047,29 @@ void udf_write_aext(struct inode *inode,
+ epos->offset += adsize;
+ }
+
++/*
++ * Only 1 indirect extent in a row really makes sense but allow upto 16 in case
++ * someone does some weird stuff.
++ */
++#define UDF_MAX_INDIR_EXTS 16
++
+ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
+ struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
+ {
+ int8_t etype;
++ unsigned int indirections = 0;
+
+ while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
+ (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
+ int block;
++
++ if (++indirections > UDF_MAX_INDIR_EXTS) {
++ udf_err(inode->i_sb,
++ "too many indirect extents in inode %lu\n",
++ inode->i_ino);
++ return -1;
++ }
++
+ epos->block = *eloc;
+ epos->offset = sizeof(struct allocExtDesc);
+ brelse(epos->bh);
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/udf/unicode.c linux-libre-4.4.7-gnu/fs/udf/unicode.c
+--- linux-libre-4.4-gnu/fs/udf/unicode.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/udf/unicode.c 2016-04-12 12:09:26.000000000 -0400
+@@ -128,11 +128,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, co
+ if (c < 0x80U)
+ utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
+ else if (c < 0x800U) {
++ if (utf_o->u_len > (UDF_NAME_LEN - 4))
++ break;
+ utf_o->u_name[utf_o->u_len++] =
+ (uint8_t)(0xc0 | (c >> 6));
+ utf_o->u_name[utf_o->u_len++] =
+ (uint8_t)(0x80 | (c & 0x3f));
+ } else {
++ if (utf_o->u_len > (UDF_NAME_LEN - 5))
++ break;
+ utf_o->u_name[utf_o->u_len++] =
+ (uint8_t)(0xe0 | (c >> 12));
+ utf_o->u_name[utf_o->u_len++] =
+@@ -173,17 +177,22 @@ int udf_CS0toUTF8(struct ustr *utf_o, co
+ static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
+ {
+ unsigned c, i, max_val, utf_char;
+- int utf_cnt, u_len;
++ int utf_cnt, u_len, u_ch;
+
+ memset(ocu, 0, sizeof(dstring) * length);
+ ocu[0] = 8;
+ max_val = 0xffU;
++ u_ch = 1;
+
+ try_again:
+ u_len = 0U;
+ utf_char = 0U;
+ utf_cnt = 0U;
+ for (i = 0U; i < utf->u_len; i++) {
++ /* Name didn't fit? */
++ if (u_len + 1 + u_ch >= length)
++ return 0;
++
+ c = (uint8_t)utf->u_name[i];
+
+ /* Complete a multi-byte UTF-8 character */
+@@ -225,6 +234,7 @@ try_again:
+ if (max_val == 0xffU) {
+ max_val = 0xffffU;
+ ocu[0] = (uint8_t)0x10U;
++ u_ch = 2;
+ goto try_again;
+ }
+ goto error_out;
+@@ -277,7 +287,7 @@ static int udf_CS0toNLS(struct nls_table
+ c = (c << 8) | ocu[i++];
+
+ len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len],
+- UDF_NAME_LEN - utf_o->u_len);
++ UDF_NAME_LEN - 2 - utf_o->u_len);
+ /* Valid character? */
+ if (len >= 0)
+ utf_o->u_len += len;
+@@ -295,15 +305,19 @@ static int udf_NLStoCS0(struct nls_table
+ int len;
+ unsigned i, max_val;
+ uint16_t uni_char;
+- int u_len;
++ int u_len, u_ch;
+
+ memset(ocu, 0, sizeof(dstring) * length);
+ ocu[0] = 8;
+ max_val = 0xffU;
++ u_ch = 1;
+
+ try_again:
+ u_len = 0U;
+ for (i = 0U; i < uni->u_len; i++) {
++ /* Name didn't fit? */
++ if (u_len + 1 + u_ch >= length)
++ return 0;
+ len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char);
+ if (!len)
+ continue;
+@@ -316,6 +330,7 @@ try_again:
+ if (uni_char > max_val) {
+ max_val = 0xffffU;
+ ocu[0] = (uint8_t)0x10U;
++ u_ch = 2;
+ goto try_again;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/userfaultfd.c linux-libre-4.4.7-gnu/fs/userfaultfd.c
+--- linux-libre-4.4-gnu/fs/userfaultfd.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/userfaultfd.c 2016-04-12 12:09:26.000000000 -0400
+@@ -287,6 +287,12 @@ int handle_userfault(struct vm_area_stru
+ goto out;
+
+ /*
++ * We don't do userfault handling for the final child pid update.
++ */
++ if (current->flags & PF_EXITING)
++ goto out;
++
++ /*
+ * Check that we can return VM_FAULT_RETRY.
+ *
+ * NOTE: it should become possible to return VM_FAULT_RETRY
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/xfs/libxfs/xfs_format.h linux-libre-4.4.7-gnu/fs/xfs/libxfs/xfs_format.h
+--- linux-libre-4.4-gnu/fs/xfs/libxfs/xfs_format.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/xfs/libxfs/xfs_format.h 2016-04-12 12:09:26.000000000 -0400
+@@ -786,7 +786,7 @@ typedef struct xfs_agfl {
+ __be64 agfl_lsn;
+ __be32 agfl_crc;
+ __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */
+-} xfs_agfl_t;
++} __attribute__((packed)) xfs_agfl_t;
+
+ #define XFS_AGFL_CRC_OFF offsetof(struct xfs_agfl, agfl_crc)
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/xfs/libxfs/xfs_inode_buf.c linux-libre-4.4.7-gnu/fs/xfs/libxfs/xfs_inode_buf.c
+--- linux-libre-4.4-gnu/fs/xfs/libxfs/xfs_inode_buf.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/xfs/libxfs/xfs_inode_buf.c 2016-04-12 12:09:26.000000000 -0400
+@@ -62,11 +62,12 @@ xfs_inobp_check(
+ * has not had the inode cores stamped into it. Hence for readahead, the buffer
+ * may be potentially invalid.
+ *
+- * If the readahead buffer is invalid, we don't want to mark it with an error,
+- * but we do want to clear the DONE status of the buffer so that a followup read
+- * will re-read it from disk. This will ensure that we don't get an unnecessary
+- * warnings during log recovery and we don't get unnecssary panics on debug
+- * kernels.
++ * If the readahead buffer is invalid, we need to mark it with an error and
++ * clear the DONE status of the buffer so that a followup read will re-read it
++ * from disk. We don't report the error otherwise to avoid warnings during log
++ * recovery and we don't get unnecssary panics on debug kernels. We use EIO here
++ * because all we want to do is say readahead failed; there is no-one to report
++ * the error to, so this will distinguish it from a non-ra verifier failure.
+ */
+ static void
+ xfs_inode_buf_verify(
+@@ -93,6 +94,7 @@ xfs_inode_buf_verify(
+ XFS_RANDOM_ITOBP_INOTOBP))) {
+ if (readahead) {
+ bp->b_flags &= ~XBF_DONE;
++ xfs_buf_ioerror(bp, -EIO);
+ return;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/xfs/xfs_attr_list.c linux-libre-4.4.7-gnu/fs/xfs/xfs_attr_list.c
+--- linux-libre-4.4-gnu/fs/xfs/xfs_attr_list.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/xfs/xfs_attr_list.c 2016-04-12 12:09:26.000000000 -0400
+@@ -202,8 +202,10 @@ xfs_attr_shortform_list(xfs_attr_list_co
+ sbp->namelen,
+ sbp->valuelen,
+ &sbp->name[sbp->namelen]);
+- if (error)
++ if (error) {
++ kmem_free(sbuf);
+ return error;
++ }
+ if (context->seen_enough)
+ break;
+ cursor->offset++;
+@@ -454,14 +456,13 @@ xfs_attr3_leaf_list_int(
+ args.rmtblkcnt = xfs_attr3_rmt_blocks(
+ args.dp->i_mount, valuelen);
+ retval = xfs_attr_rmtval_get(&args);
+- if (retval)
+- return retval;
+- retval = context->put_listent(context,
+- entry->flags,
+- name_rmt->name,
+- (int)name_rmt->namelen,
+- valuelen,
+- args.value);
++ if (!retval)
++ retval = context->put_listent(context,
++ entry->flags,
++ name_rmt->name,
++ (int)name_rmt->namelen,
++ valuelen,
++ args.value);
+ kmem_free(args.value);
+ } else {
+ retval = context->put_listent(context,
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/xfs/xfs_buf.c linux-libre-4.4.7-gnu/fs/xfs/xfs_buf.c
+--- linux-libre-4.4-gnu/fs/xfs/xfs_buf.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/xfs/xfs_buf.c 2016-04-12 12:09:26.000000000 -0400
+@@ -604,6 +604,13 @@ found:
+ }
+ }
+
++ /*
++ * Clear b_error if this is a lookup from a caller that doesn't expect
++ * valid data to be found in the buffer.
++ */
++ if (!(flags & XBF_READ))
++ xfs_buf_ioerror(bp, 0);
++
+ XFS_STATS_INC(target->bt_mount, xb_get);
+ trace_xfs_buf_get(bp, flags, _RET_IP_);
+ return bp;
+@@ -1520,6 +1527,16 @@ xfs_wait_buftarg(
+ LIST_HEAD(dispose);
+ int loop = 0;
+
++ /*
++ * We need to flush the buffer workqueue to ensure that all IO
++ * completion processing is 100% done. Just waiting on buffer locks is
++ * not sufficient for async IO as the reference count held over IO is
++ * not released until after the buffer lock is dropped. Hence we need to
++ * ensure here that all reference counts have been dropped before we
++ * start walking the LRU list.
++ */
++ drain_workqueue(btp->bt_mount->m_buf_workqueue);
++
+ /* loop until there is nothing left on the lru list. */
+ while (list_lru_count(&btp->bt_lru)) {
+ list_lru_walk(&btp->bt_lru, xfs_buftarg_wait_rele,
+diff -druNp --no-dereference linux-libre-4.4-gnu/fs/xfs/xfs_trans_ail.c linux-libre-4.4.7-gnu/fs/xfs/xfs_trans_ail.c
+--- linux-libre-4.4-gnu/fs/xfs/xfs_trans_ail.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/fs/xfs/xfs_trans_ail.c 2016-04-12 12:09:26.000000000 -0400
+@@ -497,7 +497,6 @@ xfsaild(
+ long tout = 0; /* milliseconds */
+
+ current->flags |= PF_MEMALLOC;
+- set_freezable();
+
+ while (!kthread_should_stop()) {
+ if (tout && tout <= 20)
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/asm-generic/bitops/lock.h linux-libre-4.4.7-gnu/include/asm-generic/bitops/lock.h
+--- linux-libre-4.4-gnu/include/asm-generic/bitops/lock.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/asm-generic/bitops/lock.h 2016-04-12 12:09:26.000000000 -0400
+@@ -29,16 +29,16 @@ do { \
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+- * This operation is like clear_bit_unlock, however it is not atomic.
+- * It does provide release barrier semantics so it can be used to unlock
+- * a bit lock, however it would only be used if no other CPU can modify
+- * any bits in the memory until the lock is released (a good example is
+- * if the bit lock itself protects access to the other bits in the word).
++ * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
++ * the bits in the word are protected by this lock some archs can use weaker
++ * ops to safely unlock.
++ *
++ * See for example x86's implementation.
+ */
+ #define __clear_bit_unlock(nr, addr) \
+ do { \
+- smp_mb(); \
+- __clear_bit(nr, addr); \
++ smp_mb__before_atomic(); \
++ clear_bit(nr, addr); \
+ } while (0)
+
+ #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/asm-generic/cputime_nsecs.h linux-libre-4.4.7-gnu/include/asm-generic/cputime_nsecs.h
+--- linux-libre-4.4-gnu/include/asm-generic/cputime_nsecs.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/asm-generic/cputime_nsecs.h 2016-04-12 12:09:26.000000000 -0400
+@@ -75,7 +75,7 @@ typedef u64 __nocast cputime64_t;
+ */
+ static inline cputime_t timespec_to_cputime(const struct timespec *val)
+ {
+- u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
++ u64 ret = (u64)val->tv_sec * NSEC_PER_SEC + val->tv_nsec;
+ return (__force cputime_t) ret;
+ }
+ static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val)
+@@ -91,7 +91,8 @@ static inline void cputime_to_timespec(c
+ */
+ static inline cputime_t timeval_to_cputime(const struct timeval *val)
+ {
+- u64 ret = val->tv_sec * NSEC_PER_SEC + val->tv_usec * NSEC_PER_USEC;
++ u64 ret = (u64)val->tv_sec * NSEC_PER_SEC +
++ val->tv_usec * NSEC_PER_USEC;
+ return (__force cputime_t) ret;
+ }
+ static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val)
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/crypto/hash.h linux-libre-4.4.7-gnu/include/crypto/hash.h
+--- linux-libre-4.4-gnu/include/crypto/hash.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/crypto/hash.h 2016-04-12 12:09:26.000000000 -0400
+@@ -204,6 +204,7 @@ struct crypto_ahash {
+ unsigned int keylen);
+
+ unsigned int reqsize;
++ bool has_setkey;
+ struct crypto_tfm base;
+ };
+
+@@ -375,6 +376,11 @@ static inline void *ahash_request_ctx(st
+ int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int keylen);
+
++static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm)
++{
++ return tfm->has_setkey;
++}
++
+ /**
+ * crypto_ahash_finup() - update and finalize message digest
+ * @req: reference to the ahash_request handle that holds all information
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/crypto/if_alg.h linux-libre-4.4.7-gnu/include/crypto/if_alg.h
+--- linux-libre-4.4-gnu/include/crypto/if_alg.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/crypto/if_alg.h 2016-04-12 12:09:26.000000000 -0400
+@@ -30,6 +30,9 @@ struct alg_sock {
+
+ struct sock *parent;
+
++ unsigned int refcnt;
++ unsigned int nokey_refcnt;
++
+ const struct af_alg_type *type;
+ void *private;
+ };
+@@ -50,9 +53,11 @@ struct af_alg_type {
+ void (*release)(void *private);
+ int (*setkey)(void *private, const u8 *key, unsigned int keylen);
+ int (*accept)(void *private, struct sock *sk);
++ int (*accept_nokey)(void *private, struct sock *sk);
+ int (*setauthsize)(void *private, unsigned int authsize);
+
+ struct proto_ops *ops;
++ struct proto_ops *ops_nokey;
+ struct module *owner;
+ char name[14];
+ };
+@@ -67,6 +72,7 @@ int af_alg_register_type(const struct af
+ int af_alg_unregister_type(const struct af_alg_type *type);
+
+ int af_alg_release(struct socket *sock);
++void af_alg_release_parent(struct sock *sk);
+ int af_alg_accept(struct sock *sk, struct socket *newsock);
+
+ int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len);
+@@ -83,11 +89,6 @@ static inline struct alg_sock *alg_sk(st
+ return (struct alg_sock *)sk;
+ }
+
+-static inline void af_alg_release_parent(struct sock *sk)
+-{
+- sock_put(alg_sk(sk)->parent);
+-}
+-
+ static inline void af_alg_init_completion(struct af_alg_completion *completion)
+ {
+ init_completion(&completion->completion);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/crypto/skcipher.h linux-libre-4.4.7-gnu/include/crypto/skcipher.h
+--- linux-libre-4.4-gnu/include/crypto/skcipher.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/crypto/skcipher.h 2016-04-12 12:09:26.000000000 -0400
+@@ -61,6 +61,8 @@ struct crypto_skcipher {
+ unsigned int ivsize;
+ unsigned int reqsize;
+
++ bool has_setkey;
++
+ struct crypto_tfm base;
+ };
+
+@@ -305,6 +307,11 @@ static inline int crypto_skcipher_setkey
+ return tfm->setkey(tfm, key, keylen);
+ }
+
++static inline bool crypto_skcipher_has_setkey(struct crypto_skcipher *tfm)
++{
++ return tfm->has_setkey;
++}
++
+ /**
+ * crypto_skcipher_reqtfm() - obtain cipher handle from request
+ * @req: skcipher_request out of which the cipher handle is to be obtained
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/drm/drm_cache.h linux-libre-4.4.7-gnu/include/drm/drm_cache.h
+--- linux-libre-4.4-gnu/include/drm/drm_cache.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/drm/drm_cache.h 2016-04-12 12:09:26.000000000 -0400
+@@ -35,4 +35,13 @@
+
+ void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
+
++static inline bool drm_arch_can_wc_memory(void)
++{
++#if defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
++ return false;
++#else
++ return true;
++#endif
++}
++
+ #endif
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/drm/drm_dp_mst_helper.h linux-libre-4.4.7-gnu/include/drm/drm_dp_mst_helper.h
+--- linux-libre-4.4-gnu/include/drm/drm_dp_mst_helper.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/drm/drm_dp_mst_helper.h 2016-04-12 12:09:26.000000000 -0400
+@@ -44,8 +44,6 @@ struct drm_dp_vcpi {
+ /**
+ * struct drm_dp_mst_port - MST port
+ * @kref: reference count for this port.
+- * @guid_valid: for DP 1.2 devices if we have validated the GUID.
+- * @guid: guid for DP 1.2 device on this port.
+ * @port_num: port number
+ * @input: if this port is an input port.
+ * @mcs: message capability status - DP 1.2 spec.
+@@ -70,10 +68,6 @@ struct drm_dp_vcpi {
+ struct drm_dp_mst_port {
+ struct kref kref;
+
+- /* if dpcd 1.2 device is on this port - its GUID info */
+- bool guid_valid;
+- u8 guid[16];
+-
+ u8 port_num;
+ bool input;
+ bool mcs;
+@@ -109,10 +103,12 @@ struct drm_dp_mst_port {
+ * @tx_slots: transmission slots for this device.
+ * @last_seqno: last sequence number used to talk to this.
+ * @link_address_sent: if a link address message has been sent to this device yet.
++ * @guid: guid for DP 1.2 branch device. port under this branch can be
++ * identified by port #.
+ *
+ * This structure represents an MST branch device, there is one
+- * primary branch device at the root, along with any others connected
+- * to downstream ports
++ * primary branch device at the root, along with any other branches connected
++ * to downstream port of parent branches.
+ */
+ struct drm_dp_mst_branch {
+ struct kref kref;
+@@ -131,6 +127,9 @@ struct drm_dp_mst_branch {
+ struct drm_dp_sideband_msg_tx *tx_slots[2];
+ int last_seqno;
+ bool link_address_sent;
++
++ /* global unique identifier to identify branch devices */
++ u8 guid[16];
+ };
+
+
+@@ -405,11 +404,9 @@ struct drm_dp_payload {
+ * @conn_base_id: DRM connector ID this mgr is connected to.
+ * @down_rep_recv: msg receiver state for down replies.
+ * @up_req_recv: msg receiver state for up requests.
+- * @lock: protects mst state, primary, guid, dpcd.
++ * @lock: protects mst state, primary, dpcd.
+ * @mst_state: if this manager is enabled for an MST capable port.
+ * @mst_primary: pointer to the primary branch device.
+- * @guid_valid: GUID valid for the primary branch device.
+- * @guid: GUID for primary port.
+ * @dpcd: cache of DPCD for primary port.
+ * @pbn_div: PBN to slots divisor.
+ *
+@@ -431,13 +428,11 @@ struct drm_dp_mst_topology_mgr {
+ struct drm_dp_sideband_msg_rx up_req_recv;
+
+ /* pointer to info about the initial MST device */
+- struct mutex lock; /* protects mst_state + primary + guid + dpcd */
++ struct mutex lock; /* protects mst_state + primary + dpcd */
+
+ bool mst_state;
+ struct drm_dp_mst_branch *mst_primary;
+- /* primary MST device GUID */
+- bool guid_valid;
+- u8 guid[16];
++
+ u8 dpcd[DP_RECEIVER_CAP_SIZE];
+ u8 sink_count;
+ int pbn_div;
+@@ -450,9 +445,7 @@ struct drm_dp_mst_topology_mgr {
+ the mstb tx_slots and txmsg->state once they are queued */
+ struct mutex qlock;
+ struct list_head tx_msg_downq;
+- struct list_head tx_msg_upq;
+ bool tx_down_in_progress;
+- bool tx_up_in_progress;
+
+ /* payload info + lock for it */
+ struct mutex payload_lock;
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/drm/drm_fixed.h linux-libre-4.4.7-gnu/include/drm/drm_fixed.h
+--- linux-libre-4.4-gnu/include/drm/drm_fixed.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/drm/drm_fixed.h 2016-04-12 12:09:26.000000000 -0400
+@@ -73,18 +73,28 @@ static inline u32 dfixed_div(fixed20_12
+ #define DRM_FIXED_ONE (1ULL << DRM_FIXED_POINT)
+ #define DRM_FIXED_DECIMAL_MASK (DRM_FIXED_ONE - 1)
+ #define DRM_FIXED_DIGITS_MASK (~DRM_FIXED_DECIMAL_MASK)
++#define DRM_FIXED_EPSILON 1LL
++#define DRM_FIXED_ALMOST_ONE (DRM_FIXED_ONE - DRM_FIXED_EPSILON)
+
+ static inline s64 drm_int2fixp(int a)
+ {
+ return ((s64)a) << DRM_FIXED_POINT;
+ }
+
+-static inline int drm_fixp2int(int64_t a)
++static inline int drm_fixp2int(s64 a)
+ {
+ return ((s64)a) >> DRM_FIXED_POINT;
+ }
+
+-static inline unsigned drm_fixp_msbset(int64_t a)
++static inline int drm_fixp2int_ceil(s64 a)
++{
++ if (a > 0)
++ return drm_fixp2int(a + DRM_FIXED_ALMOST_ONE);
++ else
++ return drm_fixp2int(a - DRM_FIXED_ALMOST_ONE);
++}
++
++static inline unsigned drm_fixp_msbset(s64 a)
+ {
+ unsigned shift, sign = (a >> 63) & 1;
+
+@@ -136,6 +146,45 @@ static inline s64 drm_fixp_div(s64 a, s6
+ return result;
+ }
+
++static inline s64 drm_fixp_from_fraction(s64 a, s64 b)
++{
++ s64 res;
++ bool a_neg = a < 0;
++ bool b_neg = b < 0;
++ u64 a_abs = a_neg ? -a : a;
++ u64 b_abs = b_neg ? -b : b;
++ u64 rem;
++
++ /* determine integer part */
++ u64 res_abs = div64_u64_rem(a_abs, b_abs, &rem);
++
++ /* determine fractional part */
++ {
++ u32 i = DRM_FIXED_POINT;
++
++ do {
++ rem <<= 1;
++ res_abs <<= 1;
++ if (rem >= b_abs) {
++ res_abs |= 1;
++ rem -= b_abs;
++ }
++ } while (--i != 0);
++ }
++
++ /* round up LSB */
++ {
++ u64 summand = (rem << 1) >= b_abs;
++
++ res_abs += summand;
++ }
++
++ res = (s64) res_abs;
++ if (a_neg ^ b_neg)
++ res = -res;
++ return res;
++}
++
+ static inline s64 drm_fixp_exp(s64 x)
+ {
+ s64 tolerance = div64_s64(DRM_FIXED_ONE, 1000000);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/ata.h linux-libre-4.4.7-gnu/include/linux/ata.h
+--- linux-libre-4.4-gnu/include/linux/ata.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/ata.h 2016-04-12 12:09:26.000000000 -0400
+@@ -487,8 +487,8 @@ enum ata_tf_protocols {
+ };
+
+ enum ata_ioctls {
+- ATA_IOC_GET_IO32 = 0x309,
+- ATA_IOC_SET_IO32 = 0x324,
++ ATA_IOC_GET_IO32 = 0x309, /* HDIO_GET_32BIT */
++ ATA_IOC_SET_IO32 = 0x324, /* HDIO_SET_32BIT */
+ };
+
+ /* core structures */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/bio.h linux-libre-4.4.7-gnu/include/linux/bio.h
+--- linux-libre-4.4-gnu/include/linux/bio.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/bio.h 2016-04-12 12:09:26.000000000 -0400
+@@ -310,6 +310,38 @@ static inline void bio_clear_flag(struct
+ bio->bi_flags &= ~(1U << bit);
+ }
+
++static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv)
++{
++ *bv = bio_iovec(bio);
++}
++
++static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
++{
++ struct bvec_iter iter = bio->bi_iter;
++ int idx;
++
++ if (unlikely(!bio_multiple_segments(bio))) {
++ *bv = bio_iovec(bio);
++ return;
++ }
++
++ bio_advance_iter(bio, &iter, iter.bi_size);
++
++ if (!iter.bi_bvec_done)
++ idx = iter.bi_idx - 1;
++ else /* in the middle of bvec */
++ idx = iter.bi_idx;
++
++ *bv = bio->bi_io_vec[idx];
++
++ /*
++ * iter.bi_bvec_done records actual length of the last bvec
++ * if this bio ends in the middle of one io vector
++ */
++ if (iter.bi_bvec_done)
++ bv->bv_len = iter.bi_bvec_done;
++}
++
+ enum bip_flags {
+ BIP_BLOCK_INTEGRITY = 1 << 0, /* block layer owns integrity data */
+ BIP_MAPPED_INTEGRITY = 1 << 1, /* ref tag has been remapped */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/blkdev.h linux-libre-4.4.7-gnu/include/linux/blkdev.h
+--- linux-libre-4.4-gnu/include/linux/blkdev.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/blkdev.h 2016-04-12 12:09:26.000000000 -0400
+@@ -1367,6 +1367,13 @@ static inline void put_dev_sector(Sector
+ page_cache_release(p.v);
+ }
+
++static inline bool __bvec_gap_to_prev(struct request_queue *q,
++ struct bio_vec *bprv, unsigned int offset)
++{
++ return offset ||
++ ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
++}
++
+ /*
+ * Check if adding a bio_vec after bprv with offset would create a gap in
+ * the SG list. Most drivers don't care about this, but some do.
+@@ -1376,18 +1383,22 @@ static inline bool bvec_gap_to_prev(stru
+ {
+ if (!queue_virt_boundary(q))
+ return false;
+- return offset ||
+- ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
++ return __bvec_gap_to_prev(q, bprv, offset);
+ }
+
+ static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
+ struct bio *next)
+ {
+- if (!bio_has_data(prev))
+- return false;
++ if (bio_has_data(prev) && queue_virt_boundary(q)) {
++ struct bio_vec pb, nb;
+
+- return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1],
+- next->bi_io_vec[0].bv_offset);
++ bio_get_last_bvec(prev, &pb);
++ bio_get_first_bvec(next, &nb);
++
++ return __bvec_gap_to_prev(q, &pb, nb.bv_offset);
++ }
++
++ return false;
+ }
+
+ static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/ceph/messenger.h linux-libre-4.4.7-gnu/include/linux/ceph/messenger.h
+--- linux-libre-4.4-gnu/include/linux/ceph/messenger.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/ceph/messenger.h 2016-04-12 12:09:26.000000000 -0400
+@@ -220,6 +220,7 @@ struct ceph_connection {
+ struct ceph_entity_addr actual_peer_addr;
+
+ /* message out temps */
++ struct ceph_msg_header out_hdr;
+ struct ceph_msg *out_msg; /* sending message (== tail of
+ out_sent) */
+ bool out_msg_done;
+@@ -229,7 +230,6 @@ struct ceph_connection {
+ int out_kvec_left; /* kvec's left in out_kvec */
+ int out_skip; /* skip this many bytes */
+ int out_kvec_bytes; /* total bytes left */
+- bool out_kvec_is_msg; /* kvec refers to out_msg */
+ int out_more; /* there is more data after the kvecs */
+ __le64 out_temp_ack; /* for writing an ack */
+ struct ceph_timespec out_temp_keepalive2; /* for writing keepalive2
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/cgroup-defs.h linux-libre-4.4.7-gnu/include/linux/cgroup-defs.h
+--- linux-libre-4.4-gnu/include/linux/cgroup-defs.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/cgroup-defs.h 2016-04-12 12:09:26.000000000 -0400
+@@ -133,6 +133,12 @@ struct cgroup_subsys_state {
+ */
+ u64 serial_nr;
+
++ /*
++ * Incremented by online self and children. Used to guarantee that
++ * parents are not offlined before their children.
++ */
++ atomic_t online_cnt;
++
+ /* percpu_ref killing and RCU release */
+ struct rcu_head rcu_head;
+ struct work_struct destroy_work;
+@@ -210,6 +216,9 @@ struct css_set {
+ /* all css_task_iters currently walking this cset */
+ struct list_head task_iters;
+
++ /* dead and being drained, ignore for migration */
++ bool dead;
++
+ /* For RCU-protected deletion */
+ struct rcu_head rcu_head;
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/compiler.h linux-libre-4.4.7-gnu/include/linux/compiler.h
+--- linux-libre-4.4-gnu/include/linux/compiler.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/compiler.h 2016-04-12 12:09:26.000000000 -0400
+@@ -144,7 +144,7 @@ void ftrace_likely_update(struct ftrace_
+ */
+ #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
+ #define __trace_if(cond) \
+- if (__builtin_constant_p((cond)) ? !!(cond) : \
++ if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
+ ({ \
+ int ______r; \
+ static struct ftrace_branch_data \
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/console.h linux-libre-4.4.7-gnu/include/linux/console.h
+--- linux-libre-4.4-gnu/include/linux/console.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/console.h 2016-04-12 12:09:26.000000000 -0400
+@@ -150,6 +150,7 @@ extern int console_trylock(void);
+ extern void console_unlock(void);
+ extern void console_conditional_schedule(void);
+ extern void console_unblank(void);
++extern void console_flush_on_panic(void);
+ extern struct tty_driver *console_device(int *);
+ extern void console_stop(struct console *);
+ extern void console_start(struct console *);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/cpuset.h linux-libre-4.4.7-gnu/include/linux/cpuset.h
+--- linux-libre-4.4-gnu/include/linux/cpuset.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/cpuset.h 2016-04-12 12:09:26.000000000 -0400
+@@ -137,6 +137,8 @@ static inline void set_mems_allowed(node
+ task_unlock(current);
+ }
+
++extern void cpuset_post_attach_flush(void);
++
+ #else /* !CONFIG_CPUSETS */
+
+ static inline bool cpusets_enabled(void) { return false; }
+@@ -243,6 +245,10 @@ static inline bool read_mems_allowed_ret
+ return false;
+ }
+
++static inline void cpuset_post_attach_flush(void)
++{
++}
++
+ #endif /* !CONFIG_CPUSETS */
+
+ #endif /* _LINUX_CPUSET_H */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/dcache.h linux-libre-4.4.7-gnu/include/linux/dcache.h
+--- linux-libre-4.4-gnu/include/linux/dcache.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/dcache.h 2016-04-12 12:09:26.000000000 -0400
+@@ -409,9 +409,7 @@ static inline bool d_mountpoint(const st
+ */
+ static inline unsigned __d_entry_type(const struct dentry *dentry)
+ {
+- unsigned type = READ_ONCE(dentry->d_flags);
+- smp_rmb();
+- return type & DCACHE_ENTRY_TYPE;
++ return dentry->d_flags & DCACHE_ENTRY_TYPE;
+ }
+
+ static inline bool d_is_miss(const struct dentry *dentry)
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/device-mapper.h linux-libre-4.4.7-gnu/include/linux/device-mapper.h
+--- linux-libre-4.4-gnu/include/linux/device-mapper.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/device-mapper.h 2016-04-12 12:09:26.000000000 -0400
+@@ -124,6 +124,8 @@ struct dm_dev {
+ char name[16];
+ };
+
++dev_t dm_get_dev_t(const char *path);
++
+ /*
+ * Constructors should call these functions to ensure destination devices
+ * are opened/closed correctly.
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/devpts_fs.h linux-libre-4.4.7-gnu/include/linux/devpts_fs.h
+--- linux-libre-4.4-gnu/include/linux/devpts_fs.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/devpts_fs.h 2016-04-12 12:09:26.000000000 -0400
+@@ -19,6 +19,8 @@
+
+ int devpts_new_index(struct inode *ptmx_inode);
+ void devpts_kill_index(struct inode *ptmx_inode, int idx);
++void devpts_add_ref(struct inode *ptmx_inode);
++void devpts_del_ref(struct inode *ptmx_inode);
+ /* mknod in devpts */
+ struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
+ void *priv);
+@@ -32,6 +34,8 @@ void devpts_pty_kill(struct inode *inode
+ /* Dummy stubs in the no-pty case */
+ static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
+ static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
++static inline void devpts_add_ref(struct inode *ptmx_inode) { }
++static inline void devpts_del_ref(struct inode *ptmx_inode) { }
+ static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
+ dev_t device, int index, void *priv)
+ {
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/efi.h linux-libre-4.4.7-gnu/include/linux/efi.h
+--- linux-libre-4.4-gnu/include/linux/efi.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/efi.h 2016-04-12 12:09:26.000000000 -0400
+@@ -1199,7 +1199,10 @@ int efivar_entry_iter(int (*func)(struct
+ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
+ struct list_head *head, bool remove);
+
+-bool efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len);
++bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
++ unsigned long data_size);
++bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
++ size_t len);
+
+ extern struct work_struct efivar_work;
+ void efivar_run_worker(void);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/fs.h linux-libre-4.4.7-gnu/include/linux/fs.h
+--- linux-libre-4.4-gnu/include/linux/fs.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/fs.h 2016-04-12 12:09:26.000000000 -0400
+@@ -2217,7 +2217,7 @@ extern long do_sys_open(int dfd, const c
+ extern struct file *file_open_name(struct filename *, int, umode_t);
+ extern struct file *filp_open(const char *, int, umode_t);
+ extern struct file *file_open_root(struct dentry *, struct vfsmount *,
+- const char *, int);
++ const char *, int, umode_t);
+ extern struct file * dentry_open(const struct path *, int, const struct cred *);
+ extern int filp_close(struct file *, fl_owner_t id);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/hrtimer.h linux-libre-4.4.7-gnu/include/linux/hrtimer.h
+--- linux-libre-4.4-gnu/include/linux/hrtimer.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/hrtimer.h 2016-04-12 12:09:26.000000000 -0400
+@@ -87,7 +87,8 @@ enum hrtimer_restart {
+ * @function: timer expiry callback function
+ * @base: pointer to the timer base (per cpu and per clock)
+ * @state: state information (See bit values above)
+- * @start_pid: timer statistics field to store the pid of the task which
++ * @is_rel: Set if the timer was armed relative
++ * @start_pid: timer statistics field to store the pid of the task which
+ * started the timer
+ * @start_site: timer statistics field to store the site where the timer
+ * was started
+@@ -101,7 +102,8 @@ struct hrtimer {
+ ktime_t _softexpires;
+ enum hrtimer_restart (*function)(struct hrtimer *);
+ struct hrtimer_clock_base *base;
+- unsigned long state;
++ u8 state;
++ u8 is_rel;
+ #ifdef CONFIG_TIMER_STATS
+ int start_pid;
+ void *start_site;
+@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed
+
+ #endif
+
++static inline ktime_t
++__hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t now)
++{
++ ktime_t rem = ktime_sub(timer->node.expires, now);
++
++ /*
++ * Adjust relative timers for the extra we added in
++ * hrtimer_start_range_ns() to prevent short timeouts.
++ */
++ if (IS_ENABLED(CONFIG_TIME_LOW_RES) && timer->is_rel)
++ rem.tv64 -= hrtimer_resolution;
++ return rem;
++}
++
++static inline ktime_t
++hrtimer_expires_remaining_adjusted(const struct hrtimer *timer)
++{
++ return __hrtimer_expires_remaining_adjusted(timer,
++ timer->base->get_time());
++}
++
+ extern void clock_was_set(void);
+ #ifdef CONFIG_TIMERFD
+ extern void timerfd_clock_was_set(void);
+@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struc
+ }
+
+ /* Query timers: */
+-extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
++extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust);
++
++static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
++{
++ return __hrtimer_get_remaining(timer, false);
++}
+
+ extern u64 hrtimer_get_next_event(void);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/hyperv.h linux-libre-4.4.7-gnu/include/linux/hyperv.h
+--- linux-libre-4.4-gnu/include/linux/hyperv.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/hyperv.h 2016-04-12 12:09:26.000000000 -0400
+@@ -630,6 +630,11 @@ struct hv_input_signal_event_buffer {
+ struct hv_input_signal_event event;
+ };
+
++enum hv_signal_policy {
++ HV_SIGNAL_POLICY_DEFAULT = 0,
++ HV_SIGNAL_POLICY_EXPLICIT,
++};
++
+ struct vmbus_channel {
+ /* Unique channel id */
+ int id;
+@@ -757,8 +762,21 @@ struct vmbus_channel {
+ * link up channels based on their CPU affinity.
+ */
+ struct list_head percpu_list;
++ /*
++ * Host signaling policy: The default policy will be
++ * based on the ring buffer state. We will also support
++ * a policy where the client driver can have explicit
++ * signaling control.
++ */
++ enum hv_signal_policy signal_policy;
+ };
+
++static inline void set_channel_signal_state(struct vmbus_channel *c,
++ enum hv_signal_policy policy)
++{
++ c->signal_policy = policy;
++}
++
+ static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
+ {
+ c->batched_reading = state;
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/intel-iommu.h linux-libre-4.4.7-gnu/include/linux/intel-iommu.h
+--- linux-libre-4.4-gnu/include/linux/intel-iommu.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/intel-iommu.h 2016-04-12 12:09:26.000000000 -0400
+@@ -235,6 +235,9 @@ static inline void dmar_writeq(void __io
+ /* low 64 bit */
+ #define dma_frcd_page_addr(d) (d & (((u64)-1) << PAGE_SHIFT))
+
++/* PRS_REG */
++#define DMA_PRS_PPR ((u32)1)
++
+ #define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
+ do { \
+ cycles_t start_time = get_cycles(); \
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/kernel.h linux-libre-4.4.7-gnu/include/linux/kernel.h
+--- linux-libre-4.4-gnu/include/linux/kernel.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/kernel.h 2016-04-12 12:09:26.000000000 -0400
+@@ -607,7 +607,7 @@ do { \
+
+ #define do_trace_printk(fmt, args...) \
+ do { \
+- static const char *trace_printk_fmt \
++ static const char *trace_printk_fmt __used \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(fmt) ? fmt : NULL; \
+ \
+@@ -651,7 +651,7 @@ int __trace_printk(unsigned long ip, con
+ */
+
+ #define trace_puts(str) ({ \
+- static const char *trace_printk_fmt \
++ static const char *trace_printk_fmt __used \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(str) ? str : NULL; \
+ \
+@@ -673,7 +673,7 @@ extern void trace_dump_stack(int skip);
+ #define ftrace_vprintk(fmt, vargs) \
+ do { \
+ if (__builtin_constant_p(fmt)) { \
+- static const char *trace_printk_fmt \
++ static const char *trace_printk_fmt __used \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(fmt) ? fmt : NULL; \
+ \
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/libata.h linux-libre-4.4.7-gnu/include/linux/libata.h
+--- linux-libre-4.4-gnu/include/linux/libata.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/libata.h 2016-04-12 12:09:26.000000000 -0400
+@@ -718,7 +718,7 @@ struct ata_device {
+ union {
+ u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+ u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
+- };
++ } ____cacheline_aligned;
+
+ /* DEVSLP Timing Variables from Identify Device Data Log */
+ u8 devslp_timing[ATA_LOG_DEVSLP_SIZE];
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/mlx5/cq.h linux-libre-4.4.7-gnu/include/linux/mlx5/cq.h
+--- linux-libre-4.4-gnu/include/linux/mlx5/cq.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/mlx5/cq.h 2016-04-12 12:09:26.000000000 -0400
+@@ -45,7 +45,7 @@ struct mlx5_core_cq {
+ atomic_t refcount;
+ struct completion free;
+ unsigned vector;
+- int irqn;
++ unsigned int irqn;
+ void (*comp) (struct mlx5_core_cq *);
+ void (*event) (struct mlx5_core_cq *, enum mlx5_event);
+ struct mlx5_uar *uar;
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/mlx5/driver.h linux-libre-4.4.7-gnu/include/linux/mlx5/driver.h
+--- linux-libre-4.4-gnu/include/linux/mlx5/driver.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/mlx5/driver.h 2016-04-12 12:09:26.000000000 -0400
+@@ -303,7 +303,7 @@ struct mlx5_eq {
+ u32 cons_index;
+ struct mlx5_buf buf;
+ int size;
+- u8 irqn;
++ unsigned int irqn;
+ u8 eqn;
+ int nent;
+ u64 mask;
+@@ -762,7 +762,8 @@ int mlx5_create_map_eq(struct mlx5_core_
+ int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq);
+ int mlx5_start_eqs(struct mlx5_core_dev *dev);
+ int mlx5_stop_eqs(struct mlx5_core_dev *dev);
+-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn);
++int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
++ unsigned int *irqn);
+ int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn);
+ int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/module.h linux-libre-4.4.7-gnu/include/linux/module.h
+--- linux-libre-4.4-gnu/include/linux/module.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/module.h 2016-04-12 12:09:26.000000000 -0400
+@@ -302,6 +302,12 @@ struct mod_tree_node {
+ struct latch_tree_node node;
+ };
+
++struct mod_kallsyms {
++ Elf_Sym *symtab;
++ unsigned int num_symtab;
++ char *strtab;
++};
++
+ struct module {
+ enum module_state state;
+
+@@ -411,14 +417,9 @@ struct module {
+ #endif
+
+ #ifdef CONFIG_KALLSYMS
+- /*
+- * We keep the symbol and string tables for kallsyms.
+- * The core_* fields below are temporary, loader-only (they
+- * could really be discarded after module init).
+- */
+- Elf_Sym *symtab, *core_symtab;
+- unsigned int num_symtab, core_num_syms;
+- char *strtab, *core_strtab;
++ /* Protected by RCU and/or module_mutex: use rcu_dereference() */
++ struct mod_kallsyms *kallsyms;
++ struct mod_kallsyms core_kallsyms;
+
+ /* Section attributes */
+ struct module_sect_attrs *sect_attrs;
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/nfs_fs.h linux-libre-4.4.7-gnu/include/linux/nfs_fs.h
+--- linux-libre-4.4-gnu/include/linux/nfs_fs.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/nfs_fs.h 2016-04-12 12:09:26.000000000 -0400
+@@ -544,9 +544,7 @@ extern int nfs_readpage_async(struct nf
+
+ static inline loff_t nfs_size_to_loff_t(__u64 size)
+ {
+- if (size > (__u64) OFFSET_MAX - 1)
+- return OFFSET_MAX - 1;
+- return (loff_t) size;
++ return min_t(u64, size, OFFSET_MAX);
+ }
+
+ static inline ino_t
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/pci.h linux-libre-4.4.7-gnu/include/linux/pci.h
+--- linux-libre-4.4-gnu/include/linux/pci.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/pci.h 2016-04-12 12:09:26.000000000 -0400
+@@ -359,6 +359,7 @@ struct pci_dev {
+ unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */
+ unsigned int irq_managed:1;
+ unsigned int has_secondary_link:1;
++ unsigned int non_compliant_bars:1; /* broken BARs; ignore them */
+ pci_dev_flags_t dev_flags;
+ atomic_t enable_cnt; /* pci_enable_device has been called */
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/platform_data/asoc-s3c.h linux-libre-4.4.7-gnu/include/linux/platform_data/asoc-s3c.h
+--- linux-libre-4.4-gnu/include/linux/platform_data/asoc-s3c.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/platform_data/asoc-s3c.h 2016-04-12 12:09:26.000000000 -0400
+@@ -39,6 +39,10 @@ struct samsung_i2s {
+ */
+ struct s3c_audio_pdata {
+ int (*cfg_gpio)(struct platform_device *);
++ void *dma_playback;
++ void *dma_capture;
++ void *dma_play_sec;
++ void *dma_capture_mic;
+ union {
+ struct samsung_i2s i2s;
+ } type;
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/ptrace.h linux-libre-4.4.7-gnu/include/linux/ptrace.h
+--- linux-libre-4.4-gnu/include/linux/ptrace.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/ptrace.h 2016-04-12 12:09:26.000000000 -0400
+@@ -57,7 +57,29 @@ extern void exit_ptrace(struct task_stru
+ #define PTRACE_MODE_READ 0x01
+ #define PTRACE_MODE_ATTACH 0x02
+ #define PTRACE_MODE_NOAUDIT 0x04
+-/* Returns true on success, false on denial. */
++#define PTRACE_MODE_FSCREDS 0x08
++#define PTRACE_MODE_REALCREDS 0x10
++
++/* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
++#define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
++#define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
++#define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
++#define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
++
++/**
++ * ptrace_may_access - check whether the caller is permitted to access
++ * a target task.
++ * @task: target task
++ * @mode: selects type of access and caller credentials
++ *
++ * Returns true on success, false on denial.
++ *
++ * One of the flags PTRACE_MODE_FSCREDS and PTRACE_MODE_REALCREDS must
++ * be set in @mode to specify whether the access was requested through
++ * a filesystem syscall (should use effective capabilities and fsuid
++ * of the caller) or through an explicit syscall such as
++ * process_vm_writev or ptrace (and should use the real credentials).
++ */
+ extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
+
+ static inline int ptrace_reparented(struct task_struct *child)
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/radix-tree.h linux-libre-4.4.7-gnu/include/linux/radix-tree.h
+--- linux-libre-4.4-gnu/include/linux/radix-tree.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/radix-tree.h 2016-04-12 12:09:26.000000000 -0400
+@@ -370,12 +370,28 @@ void **radix_tree_next_chunk(struct radi
+ struct radix_tree_iter *iter, unsigned flags);
+
+ /**
++ * radix_tree_iter_retry - retry this chunk of the iteration
++ * @iter: iterator state
++ *
++ * If we iterate over a tree protected only by the RCU lock, a race
++ * against deletion or creation may result in seeing a slot for which
++ * radix_tree_deref_retry() returns true. If so, call this function
++ * and continue the iteration.
++ */
++static inline __must_check
++void **radix_tree_iter_retry(struct radix_tree_iter *iter)
++{
++ iter->next_index = iter->index;
++ return NULL;
++}
++
++/**
+ * radix_tree_chunk_size - get current chunk size
+ *
+ * @iter: pointer to radix tree iterator
+ * Returns: current chunk size
+ */
+-static __always_inline unsigned
++static __always_inline long
+ radix_tree_chunk_size(struct radix_tree_iter *iter)
+ {
+ return iter->next_index - iter->index;
+@@ -409,9 +425,9 @@ radix_tree_next_slot(void **slot, struct
+ return slot + offset + 1;
+ }
+ } else {
+- unsigned size = radix_tree_chunk_size(iter) - 1;
++ long size = radix_tree_chunk_size(iter);
+
+- while (size--) {
++ while (--size > 0) {
+ slot++;
+ iter->index++;
+ if (likely(*slot))
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/rmap.h linux-libre-4.4.7-gnu/include/linux/rmap.h
+--- linux-libre-4.4-gnu/include/linux/rmap.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/rmap.h 2016-04-12 12:09:26.000000000 -0400
+@@ -108,20 +108,6 @@ static inline void put_anon_vma(struct a
+ __put_anon_vma(anon_vma);
+ }
+
+-static inline void vma_lock_anon_vma(struct vm_area_struct *vma)
+-{
+- struct anon_vma *anon_vma = vma->anon_vma;
+- if (anon_vma)
+- down_write(&anon_vma->root->rwsem);
+-}
+-
+-static inline void vma_unlock_anon_vma(struct vm_area_struct *vma)
+-{
+- struct anon_vma *anon_vma = vma->anon_vma;
+- if (anon_vma)
+- up_write(&anon_vma->root->rwsem);
+-}
+-
+ static inline void anon_vma_lock_write(struct anon_vma *anon_vma)
+ {
+ down_write(&anon_vma->root->rwsem);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/sched.h linux-libre-4.4.7-gnu/include/linux/sched.h
+--- linux-libre-4.4-gnu/include/linux/sched.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/sched.h 2016-04-12 12:09:26.000000000 -0400
+@@ -830,6 +830,7 @@ struct user_struct {
+ unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
+ #endif
+ unsigned long locked_shm; /* How many pages of mlocked shm ? */
++ unsigned long unix_inflight; /* How many files in flight in unix sockets */
+
+ #ifdef CONFIG_KEYS
+ struct key *uid_keyring; /* UID specific keyring */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/shmem_fs.h linux-libre-4.4.7-gnu/include/linux/shmem_fs.h
+--- linux-libre-4.4-gnu/include/linux/shmem_fs.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/shmem_fs.h 2016-04-12 12:09:26.000000000 -0400
+@@ -15,10 +15,7 @@ struct shmem_inode_info {
+ unsigned int seals; /* shmem seals */
+ unsigned long flags;
+ unsigned long alloced; /* data pages alloced to file */
+- union {
+- unsigned long swapped; /* subtotal assigned to swap */
+- char *symlink; /* unswappable short symlink */
+- };
++ unsigned long swapped; /* subtotal assigned to swap */
+ struct shared_policy policy; /* NUMA memory alloc policy */
+ struct list_head swaplist; /* chain of maybes on swap */
+ struct simple_xattrs xattrs; /* list of xattrs */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/skbuff.h linux-libre-4.4.7-gnu/include/linux/skbuff.h
+--- linux-libre-4.4-gnu/include/linux/skbuff.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/skbuff.h 2016-04-12 12:09:26.000000000 -0400
+@@ -219,6 +219,7 @@ struct sk_buff;
+ #else
+ #define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1)
+ #endif
++extern int sysctl_max_skb_frags;
+
+ typedef struct skb_frag_struct skb_frag_t;
+
+@@ -3446,7 +3447,8 @@ struct skb_gso_cb {
+ int encap_level;
+ __u16 csum_start;
+ };
+-#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb)
++#define SKB_SGO_CB_OFFSET 32
++#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_SGO_CB_OFFSET))
+
+ static inline int skb_tnl_header_len(const struct sk_buff *inner_skb)
+ {
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/thermal.h linux-libre-4.4.7-gnu/include/linux/thermal.h
+--- linux-libre-4.4-gnu/include/linux/thermal.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/thermal.h 2016-04-12 12:09:26.000000000 -0400
+@@ -43,6 +43,9 @@
+ /* Default weight of a bound cooling device */
+ #define THERMAL_WEIGHT_DEFAULT 0
+
++/* use value, which < 0K, to indicate an invalid/uninitialized temperature */
++#define THERMAL_TEMP_INVALID -274000
++
+ /* Unit conversion macros */
+ #define DECI_KELVIN_TO_CELSIUS(t) ({ \
+ long _t = (t); \
+@@ -153,6 +156,7 @@ struct thermal_attr {
+ * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis
+ * @devdata: private pointer for device private data
+ * @trips: number of trip points the thermal zone supports
++ * @trips_disabled; bitmap for disabled trips
+ * @passive_delay: number of milliseconds to wait between polls when
+ * performing passive cooling.
+ * @polling_delay: number of milliseconds to wait between polls when
+@@ -167,6 +171,7 @@ struct thermal_attr {
+ * @forced_passive: If > 0, temperature at which to switch on all ACPI
+ * processor cooling devices. Currently only used by the
+ * step-wise governor.
++ * @need_update: if equals 1, thermal_zone_device_update needs to be invoked.
+ * @ops: operations this &thermal_zone_device supports
+ * @tzp: thermal zone parameters
+ * @governor: pointer to the governor for this thermal zone
+@@ -187,6 +192,7 @@ struct thermal_zone_device {
+ struct thermal_attr *trip_hyst_attrs;
+ void *devdata;
+ int trips;
++ unsigned long trips_disabled; /* bitmap for disabled trips */
+ int passive_delay;
+ int polling_delay;
+ int temperature;
+@@ -194,6 +200,7 @@ struct thermal_zone_device {
+ int emul_temperature;
+ int passive;
+ unsigned int forced_passive;
++ atomic_t need_update;
+ struct thermal_zone_device_ops *ops;
+ struct thermal_zone_params *tzp;
+ struct thermal_governor *governor;
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/trace_events.h linux-libre-4.4.7-gnu/include/linux/trace_events.h
+--- linux-libre-4.4-gnu/include/linux/trace_events.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/trace_events.h 2016-04-12 12:09:26.000000000 -0400
+@@ -568,6 +568,8 @@ enum {
+ FILTER_DYN_STRING,
+ FILTER_PTR_STRING,
+ FILTER_TRACE_FN,
++ FILTER_COMM,
++ FILTER_CPU,
+ };
+
+ extern int trace_event_raw_init(struct trace_event_call *call);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/tracepoint.h linux-libre-4.4.7-gnu/include/linux/tracepoint.h
+--- linux-libre-4.4-gnu/include/linux/tracepoint.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/tracepoint.h 2016-04-12 12:09:26.000000000 -0400
+@@ -14,8 +14,10 @@
+ * See the file COPYING for more details.
+ */
+
++#include <linux/smp.h>
+ #include <linux/errno.h>
+ #include <linux/types.h>
++#include <linux/cpumask.h>
+ #include <linux/rcupdate.h>
+ #include <linux/static_key.h>
+
+@@ -352,15 +354,19 @@ extern void syscall_unregfunc(void);
+ * "void *__data, proto" as the callback prototype.
+ */
+ #define DECLARE_TRACE_NOARGS(name) \
+- __DECLARE_TRACE(name, void, , 1, void *__data, __data)
++ __DECLARE_TRACE(name, void, , \
++ cpu_online(raw_smp_processor_id()), \
++ void *__data, __data)
+
+ #define DECLARE_TRACE(name, proto, args) \
+- __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1, \
+- PARAMS(void *__data, proto), \
+- PARAMS(__data, args))
++ __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \
++ cpu_online(raw_smp_processor_id()), \
++ PARAMS(void *__data, proto), \
++ PARAMS(__data, args))
+
+ #define DECLARE_TRACE_CONDITION(name, proto, args, cond) \
+- __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \
++ __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \
++ cpu_online(raw_smp_processor_id()) && (PARAMS(cond)), \
+ PARAMS(void *__data, proto), \
+ PARAMS(__data, args))
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/tty.h linux-libre-4.4.7-gnu/include/linux/tty.h
+--- linux-libre-4.4-gnu/include/linux/tty.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/tty.h 2016-04-12 12:09:26.000000000 -0400
+@@ -594,7 +594,7 @@ static inline int tty_ldisc_receive_buf(
+ count = ld->ops->receive_buf2(ld->tty, p, f, count);
+ else {
+ count = min_t(int, count, ld->tty->receive_room);
+- if (count)
++ if (count && ld->ops->receive_buf)
+ ld->ops->receive_buf(ld->tty, p, f, count);
+ }
+ return count;
+@@ -654,6 +654,7 @@ extern long vt_compat_ioctl(struct tty_s
+ /* tty_mutex.c */
+ /* functions for preparation of BKL removal */
+ extern void __lockfunc tty_lock(struct tty_struct *tty);
++extern int tty_lock_interruptible(struct tty_struct *tty);
+ extern void __lockfunc tty_unlock(struct tty_struct *tty);
+ extern void __lockfunc tty_lock_slave(struct tty_struct *tty);
+ extern void __lockfunc tty_unlock_slave(struct tty_struct *tty);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/ucs2_string.h linux-libre-4.4.7-gnu/include/linux/ucs2_string.h
+--- linux-libre-4.4-gnu/include/linux/ucs2_string.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/ucs2_string.h 2016-04-12 12:09:26.000000000 -0400
+@@ -11,4 +11,8 @@ unsigned long ucs2_strlen(const ucs2_cha
+ unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
+ int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
+
++unsigned long ucs2_utf8size(const ucs2_char_t *src);
++unsigned long ucs2_as_utf8(u8 *dest, const ucs2_char_t *src,
++ unsigned long maxlength);
++
+ #endif /* _LINUX_UCS2_STRING_H_ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/usb.h linux-libre-4.4.7-gnu/include/linux/usb.h
+--- linux-libre-4.4-gnu/include/linux/usb.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/usb.h 2016-04-12 12:09:26.000000000 -0400
+@@ -511,6 +511,8 @@ struct usb3_lpm_parameters {
+ * @usb2_hw_lpm_enabled: USB2 hardware LPM is enabled
+ * @usb2_hw_lpm_allowed: Userspace allows USB 2.0 LPM to be enabled
+ * @usb3_lpm_enabled: USB3 hardware LPM enabled
++ * @usb3_lpm_u1_enabled: USB3 hardware U1 LPM enabled
++ * @usb3_lpm_u2_enabled: USB3 hardware U2 LPM enabled
+ * @string_langid: language ID for strings
+ * @product: iProduct string, if present (static)
+ * @manufacturer: iManufacturer string, if present (static)
+@@ -584,6 +586,8 @@ struct usb_device {
+ unsigned usb2_hw_lpm_enabled:1;
+ unsigned usb2_hw_lpm_allowed:1;
+ unsigned usb3_lpm_enabled:1;
++ unsigned usb3_lpm_u1_enabled:1;
++ unsigned usb3_lpm_u2_enabled:1;
+ int string_langid;
+
+ /* static strings from the device */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/linux/writeback.h linux-libre-4.4.7-gnu/include/linux/writeback.h
+--- linux-libre-4.4-gnu/include/linux/writeback.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/linux/writeback.h 2016-04-12 12:09:26.000000000 -0400
+@@ -198,6 +198,7 @@ void wbc_attach_and_unlock_inode(struct
+ void wbc_detach_inode(struct writeback_control *wbc);
+ void wbc_account_io(struct writeback_control *wbc, struct page *page,
+ size_t bytes);
++void cgroup_writeback_umount(void);
+
+ /**
+ * inode_attach_wb - associate an inode with its wb
+@@ -301,6 +302,10 @@ static inline void wbc_account_io(struct
+ {
+ }
+
++static inline void cgroup_writeback_umount(void)
++{
++}
++
+ #endif /* CONFIG_CGROUP_WRITEBACK */
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/af_unix.h linux-libre-4.4.7-gnu/include/net/af_unix.h
+--- linux-libre-4.4-gnu/include/net/af_unix.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/af_unix.h 2016-04-12 12:09:26.000000000 -0400
+@@ -6,8 +6,8 @@
+ #include <linux/mutex.h>
+ #include <net/sock.h>
+
+-void unix_inflight(struct file *fp);
+-void unix_notinflight(struct file *fp);
++void unix_inflight(struct user_struct *user, struct file *fp);
++void unix_notinflight(struct user_struct *user, struct file *fp);
+ void unix_gc(void);
+ void wait_for_unix_gc(void);
+ struct sock *unix_get_socket(struct file *filp);
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/dst_metadata.h linux-libre-4.4.7-gnu/include/net/dst_metadata.h
+--- linux-libre-4.4-gnu/include/net/dst_metadata.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/dst_metadata.h 2016-04-12 12:09:26.000000000 -0400
+@@ -44,6 +44,24 @@ static inline bool skb_valid_dst(const s
+ return dst && !(dst->flags & DST_METADATA);
+ }
+
++static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
++ const struct sk_buff *skb_b)
++{
++ const struct metadata_dst *a, *b;
++
++ if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
++ return 0;
++
++ a = (const struct metadata_dst *) skb_dst(skb_a);
++ b = (const struct metadata_dst *) skb_dst(skb_b);
++
++ if (!a != !b || a->u.tun_info.options_len != b->u.tun_info.options_len)
++ return 1;
++
++ return memcmp(&a->u.tun_info, &b->u.tun_info,
++ sizeof(a->u.tun_info) + a->u.tun_info.options_len);
++}
++
+ struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags);
+ struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/inet_connection_sock.h linux-libre-4.4.7-gnu/include/net/inet_connection_sock.h
+--- linux-libre-4.4-gnu/include/net/inet_connection_sock.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/inet_connection_sock.h 2016-04-12 12:09:26.000000000 -0400
+@@ -270,8 +270,9 @@ struct dst_entry *inet_csk_route_child_s
+ struct sock *newsk,
+ const struct request_sock *req);
+
+-void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req,
+- struct sock *child);
++struct sock *inet_csk_reqsk_queue_add(struct sock *sk,
++ struct request_sock *req,
++ struct sock *child);
+ void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
+ unsigned long timeout);
+ struct sock *inet_csk_complete_hashdance(struct sock *sk, struct sock *child,
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/inet_ecn.h linux-libre-4.4.7-gnu/include/net/inet_ecn.h
+--- linux-libre-4.4-gnu/include/net/inet_ecn.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/inet_ecn.h 2016-04-12 12:09:26.000000000 -0400
+@@ -111,11 +111,24 @@ static inline void ipv4_copy_dscp(unsign
+
+ struct ipv6hdr;
+
+-static inline int IP6_ECN_set_ce(struct ipv6hdr *iph)
++/* Note:
++ * IP_ECN_set_ce() has to tweak IPV4 checksum when setting CE,
++ * meaning both changes have no effect on skb->csum if/when CHECKSUM_COMPLETE
++ * In IPv6 case, no checksum compensates the change in IPv6 header,
++ * so we have to update skb->csum.
++ */
++static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph)
+ {
++ __be32 from, to;
++
+ if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
+ return 0;
+- *(__be32*)iph |= htonl(INET_ECN_CE << 20);
++
++ from = *(__be32 *)iph;
++ to = from | htonl(INET_ECN_CE << 20);
++ *(__be32 *)iph = to;
++ if (skb->ip_summed == CHECKSUM_COMPLETE)
++ skb->csum = csum_add(csum_sub(skb->csum, from), to);
+ return 1;
+ }
+
+@@ -142,7 +155,7 @@ static inline int INET_ECN_set_ce(struct
+ case cpu_to_be16(ETH_P_IPV6):
+ if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
+ skb_tail_pointer(skb))
+- return IP6_ECN_set_ce(ipv6_hdr(skb));
++ return IP6_ECN_set_ce(skb, ipv6_hdr(skb));
+ break;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/ip6_route.h linux-libre-4.4.7-gnu/include/net/ip6_route.h
+--- linux-libre-4.4-gnu/include/net/ip6_route.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/ip6_route.h 2016-04-12 12:09:26.000000000 -0400
+@@ -64,8 +64,16 @@ static inline bool rt6_need_strict(const
+
+ void ip6_route_input(struct sk_buff *skb);
+
+-struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
+- struct flowi6 *fl6);
++struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
++ struct flowi6 *fl6, int flags);
++
++static inline struct dst_entry *ip6_route_output(struct net *net,
++ const struct sock *sk,
++ struct flowi6 *fl6)
++{
++ return ip6_route_output_flags(net, sk, fl6, 0);
++}
++
+ struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
+ int flags);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/ip_fib.h linux-libre-4.4.7-gnu/include/net/ip_fib.h
+--- linux-libre-4.4-gnu/include/net/ip_fib.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/ip_fib.h 2016-04-12 12:09:26.000000000 -0400
+@@ -61,6 +61,7 @@ struct fib_nh_exception {
+ struct rtable __rcu *fnhe_rth_input;
+ struct rtable __rcu *fnhe_rth_output;
+ unsigned long fnhe_stamp;
++ struct rcu_head rcu;
+ };
+
+ struct fnhe_hash_bucket {
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/iw_handler.h linux-libre-4.4.7-gnu/include/net/iw_handler.h
+--- linux-libre-4.4-gnu/include/net/iw_handler.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/iw_handler.h 2016-04-12 12:09:26.000000000 -0400
+@@ -439,6 +439,12 @@ int dev_get_wireless_info(char *buffer,
+ /* Send a single event to user space */
+ void wireless_send_event(struct net_device *dev, unsigned int cmd,
+ union iwreq_data *wrqu, const char *extra);
++#ifdef CONFIG_WEXT_CORE
++/* flush all previous wext events - if work is done from netdev notifiers */
++void wireless_nlevent_flush(void);
++#else
++static inline void wireless_nlevent_flush(void) {}
++#endif
+
+ /* We may need a function to send a stream of events to user space.
+ * More on that later... */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/scm.h linux-libre-4.4.7-gnu/include/net/scm.h
+--- linux-libre-4.4-gnu/include/net/scm.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/scm.h 2016-04-12 12:09:26.000000000 -0400
+@@ -21,6 +21,7 @@ struct scm_creds {
+ struct scm_fp_list {
+ short count;
+ short max;
++ struct user_struct *user;
+ struct file *fp[SCM_MAX_FD];
+ };
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/net/tcp.h linux-libre-4.4.7-gnu/include/net/tcp.h
+--- linux-libre-4.4-gnu/include/net/tcp.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/net/tcp.h 2016-04-12 12:09:26.000000000 -0400
+@@ -449,7 +449,7 @@ const u8 *tcp_parse_md5sig_option(const
+
+ void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
+ void tcp_v4_mtu_reduced(struct sock *sk);
+-void tcp_req_err(struct sock *sk, u32 seq);
++void tcp_req_err(struct sock *sk, u32 seq, bool abort);
+ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
+ struct sock *tcp_create_openreq_child(const struct sock *sk,
+ struct request_sock *req,
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/sound/rawmidi.h linux-libre-4.4.7-gnu/include/sound/rawmidi.h
+--- linux-libre-4.4-gnu/include/sound/rawmidi.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/sound/rawmidi.h 2016-04-12 12:09:26.000000000 -0400
+@@ -167,6 +167,10 @@ int snd_rawmidi_transmit_peek(struct snd
+ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
+ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count);
++int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++ unsigned char *buffer, int count);
++int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
++ int count);
+
+ /* main midi functions */
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/target/target_core_backend.h linux-libre-4.4.7-gnu/include/target/target_core_backend.h
+--- linux-libre-4.4-gnu/include/target/target_core_backend.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/target/target_core_backend.h 2016-04-12 12:09:26.000000000 -0400
+@@ -94,5 +94,8 @@ sense_reason_t passthrough_parse_cdb(str
+ sense_reason_t (*exec_cmd)(struct se_cmd *cmd));
+
+ bool target_sense_desc_format(struct se_device *dev);
++sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
++bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
++ struct request_queue *q, int block_size);
+
+ #endif /* TARGET_CORE_BACKEND_H */
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/target/target_core_base.h linux-libre-4.4.7-gnu/include/target/target_core_base.h
+--- linux-libre-4.4-gnu/include/target/target_core_base.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/target/target_core_base.h 2016-04-12 12:09:26.000000000 -0400
+@@ -138,6 +138,7 @@ enum se_cmd_flags_table {
+ SCF_COMPARE_AND_WRITE = 0x00080000,
+ SCF_COMPARE_AND_WRITE_POST = 0x00100000,
+ SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000,
++ SCF_ACK_KREF = 0x00400000,
+ };
+
+ /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
+@@ -490,6 +491,8 @@ struct se_cmd {
+ #define CMD_T_DEV_ACTIVE (1 << 7)
+ #define CMD_T_REQUEST_STOP (1 << 8)
+ #define CMD_T_BUSY (1 << 9)
++#define CMD_T_TAS (1 << 10)
++#define CMD_T_FABRIC_STOP (1 << 11)
+ spinlock_t t_state_lock;
+ struct kref cmd_kref;
+ struct completion t_transport_stop_comp;
+diff -druNp --no-dereference linux-libre-4.4-gnu/include/uapi/linux/Kbuild linux-libre-4.4.7-gnu/include/uapi/linux/Kbuild
+--- linux-libre-4.4-gnu/include/uapi/linux/Kbuild 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/include/uapi/linux/Kbuild 2016-04-12 12:09:26.000000000 -0400
+@@ -307,7 +307,7 @@ header-y += nfs_mount.h
+ header-y += nl80211.h
+ header-y += n_r3964.h
+ header-y += nubus.h
+-header-y += nvme.h
++header-y += nvme_ioctl.h
+ header-y += nvram.h
+ header-y += omap3isp.h
+ header-y += omapfb.h
+diff -druNp --no-dereference linux-libre-4.4-gnu/ipc/shm.c linux-libre-4.4.7-gnu/ipc/shm.c
+--- linux-libre-4.4-gnu/ipc/shm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/ipc/shm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -156,11 +156,12 @@ static inline struct shmid_kernel *shm_l
+ struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
+
+ /*
+- * We raced in the idr lookup or with shm_destroy(). Either way, the
+- * ID is busted.
++ * Callers of shm_lock() must validate the status of the returned ipc
++ * object pointer (as returned by ipc_lock()), and error out as
++ * appropriate.
+ */
+- WARN_ON(IS_ERR(ipcp));
+-
++ if (IS_ERR(ipcp))
++ return (void *)ipcp;
+ return container_of(ipcp, struct shmid_kernel, shm_perm);
+ }
+
+@@ -186,18 +187,33 @@ static inline void shm_rmid(struct ipc_n
+ }
+
+
+-/* This is called by fork, once for every shm attach. */
+-static void shm_open(struct vm_area_struct *vma)
++static int __shm_open(struct vm_area_struct *vma)
+ {
+ struct file *file = vma->vm_file;
+ struct shm_file_data *sfd = shm_file_data(file);
+ struct shmid_kernel *shp;
+
+ shp = shm_lock(sfd->ns, sfd->id);
++
++ if (IS_ERR(shp))
++ return PTR_ERR(shp);
++
+ shp->shm_atim = get_seconds();
+ shp->shm_lprid = task_tgid_vnr(current);
+ shp->shm_nattch++;
+ shm_unlock(shp);
++ return 0;
++}
++
++/* This is called by fork, once for every shm attach. */
++static void shm_open(struct vm_area_struct *vma)
++{
++ int err = __shm_open(vma);
++ /*
++ * We raced in the idr lookup or with shm_destroy().
++ * Either way, the ID is busted.
++ */
++ WARN_ON_ONCE(err);
+ }
+
+ /*
+@@ -260,6 +276,14 @@ static void shm_close(struct vm_area_str
+ down_write(&shm_ids(ns).rwsem);
+ /* remove from the list of attaches of the shm segment */
+ shp = shm_lock(ns, sfd->id);
++
++ /*
++ * We raced in the idr lookup or with shm_destroy().
++ * Either way, the ID is busted.
++ */
++ if (WARN_ON_ONCE(IS_ERR(shp)))
++ goto done; /* no-op */
++
+ shp->shm_lprid = task_tgid_vnr(current);
+ shp->shm_dtim = get_seconds();
+ shp->shm_nattch--;
+@@ -267,6 +291,7 @@ static void shm_close(struct vm_area_str
+ shm_destroy(ns, shp);
+ else
+ shm_unlock(shp);
++done:
+ up_write(&shm_ids(ns).rwsem);
+ }
+
+@@ -388,17 +413,25 @@ static int shm_mmap(struct file *file, s
+ struct shm_file_data *sfd = shm_file_data(file);
+ int ret;
+
++ /*
++ * In case of remap_file_pages() emulation, the file can represent
++ * removed IPC ID: propogate shm_lock() error to caller.
++ */
++ ret =__shm_open(vma);
++ if (ret)
++ return ret;
++
+ ret = sfd->file->f_op->mmap(sfd->file, vma);
+- if (ret != 0)
++ if (ret) {
++ shm_close(vma);
+ return ret;
++ }
+ sfd->vm_ops = vma->vm_ops;
+ #ifdef CONFIG_MMU
+ WARN_ON(!sfd->vm_ops->fault);
+ #endif
+ vma->vm_ops = &shm_vm_ops;
+- shm_open(vma);
+-
+- return ret;
++ return 0;
+ }
+
+ static int shm_release(struct inode *ino, struct file *file)
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/bpf/verifier.c linux-libre-4.4.7-gnu/kernel/bpf/verifier.c
+--- linux-libre-4.4-gnu/kernel/bpf/verifier.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/bpf/verifier.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1121,6 +1121,16 @@ static int check_alu_op(struct verifier_
+ return -EINVAL;
+ }
+
++ if ((opcode == BPF_LSH || opcode == BPF_RSH ||
++ opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) {
++ int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32;
++
++ if (insn->imm < 0 || insn->imm >= size) {
++ verbose("invalid shift %d\n", insn->imm);
++ return -EINVAL;
++ }
++ }
++
+ /* pattern match 'bpf_add Rx, imm' instruction */
+ if (opcode == BPF_ADD && BPF_CLASS(insn->code) == BPF_ALU64 &&
+ regs[insn->dst_reg].type == FRAME_PTR &&
+@@ -2072,7 +2082,7 @@ static void adjust_branches(struct bpf_p
+ /* adjust offset of jmps if necessary */
+ if (i < pos && i + insn->off + 1 > pos)
+ insn->off += delta;
+- else if (i > pos && i + insn->off + 1 < pos)
++ else if (i > pos + delta && i + insn->off + 1 <= pos + delta)
+ insn->off -= delta;
+ }
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/cgroup.c linux-libre-4.4.7-gnu/kernel/cgroup.c
+--- linux-libre-4.4-gnu/kernel/cgroup.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/cgroup.c 2016-04-12 12:09:26.000000000 -0400
+@@ -57,7 +57,7 @@
+ #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
+ #include <linux/kthread.h>
+ #include <linux/delay.h>
+-
++#include <linux/cpuset.h>
+ #include <linux/atomic.h>
+
+ /*
+@@ -2498,6 +2498,14 @@ static void cgroup_migrate_add_src(struc
+ lockdep_assert_held(&cgroup_mutex);
+ lockdep_assert_held(&css_set_lock);
+
++ /*
++ * If ->dead, @src_set is associated with one or more dead cgroups
++ * and doesn't contain any migratable tasks. Ignore it early so
++ * that the rest of migration path doesn't get confused by it.
++ */
++ if (src_cset->dead)
++ return;
++
+ src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
+
+ if (!list_empty(&src_cset->mg_preload_node))
+@@ -2764,6 +2772,7 @@ out_unlock_rcu:
+ out_unlock_threadgroup:
+ percpu_up_write(&cgroup_threadgroup_rwsem);
+ cgroup_kn_unlock(of->kn);
++ cpuset_post_attach_flush();
+ return ret ?: nbytes;
+ }
+
+@@ -4783,6 +4792,7 @@ static void init_and_link_css(struct cgr
+ INIT_LIST_HEAD(&css->sibling);
+ INIT_LIST_HEAD(&css->children);
+ css->serial_nr = css_serial_nr_next++;
++ atomic_set(&css->online_cnt, 0);
+
+ if (cgroup_parent(cgrp)) {
+ css->parent = cgroup_css(cgroup_parent(cgrp), ss);
+@@ -4805,6 +4815,10 @@ static int online_css(struct cgroup_subs
+ if (!ret) {
+ css->flags |= CSS_ONLINE;
+ rcu_assign_pointer(css->cgroup->subsys[ss->id], css);
++
++ atomic_inc(&css->online_cnt);
++ if (css->parent)
++ atomic_inc(&css->parent->online_cnt);
+ }
+ return ret;
+ }
+@@ -5036,10 +5050,15 @@ static void css_killed_work_fn(struct wo
+ container_of(work, struct cgroup_subsys_state, destroy_work);
+
+ mutex_lock(&cgroup_mutex);
+- offline_css(css);
+- mutex_unlock(&cgroup_mutex);
+
+- css_put(css);
++ do {
++ offline_css(css);
++ css_put(css);
++ /* @css can't go away while we're holding cgroup_mutex */
++ css = css->parent;
++ } while (css && atomic_dec_and_test(&css->online_cnt));
++
++ mutex_unlock(&cgroup_mutex);
+ }
+
+ /* css kill confirmation processing requires process context, bounce */
+@@ -5048,8 +5067,10 @@ static void css_killed_ref_fn(struct per
+ struct cgroup_subsys_state *css =
+ container_of(ref, struct cgroup_subsys_state, refcnt);
+
+- INIT_WORK(&css->destroy_work, css_killed_work_fn);
+- queue_work(cgroup_destroy_wq, &css->destroy_work);
++ if (atomic_dec_and_test(&css->online_cnt)) {
++ INIT_WORK(&css->destroy_work, css_killed_work_fn);
++ queue_work(cgroup_destroy_wq, &css->destroy_work);
++ }
+ }
+
+ /**
+@@ -5118,6 +5139,7 @@ static int cgroup_destroy_locked(struct
+ __releases(&cgroup_mutex) __acquires(&cgroup_mutex)
+ {
+ struct cgroup_subsys_state *css;
++ struct cgrp_cset_link *link;
+ int ssid;
+
+ lockdep_assert_held(&cgroup_mutex);
+@@ -5138,11 +5160,18 @@ static int cgroup_destroy_locked(struct
+ return -EBUSY;
+
+ /*
+- * Mark @cgrp dead. This prevents further task migration and child
+- * creation by disabling cgroup_lock_live_group().
++ * Mark @cgrp and the associated csets dead. The former prevents
++ * further task migration and child creation by disabling
++ * cgroup_lock_live_group(). The latter makes the csets ignored by
++ * the migration path.
+ */
+ cgrp->self.flags &= ~CSS_ONLINE;
+
++ spin_lock_bh(&css_set_lock);
++ list_for_each_entry(link, &cgrp->cset_links, cset_link)
++ link->cset->dead = true;
++ spin_unlock_bh(&css_set_lock);
++
+ /* initiate massacre of all css's */
+ for_each_css(css, ssid, cgrp)
+ kill_css(css);
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/cpuset.c linux-libre-4.4.7-gnu/kernel/cpuset.c
+--- linux-libre-4.4-gnu/kernel/cpuset.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/cpuset.c 2016-04-12 12:09:26.000000000 -0400
+@@ -286,6 +286,8 @@ static struct cpuset top_cpuset = {
+ static DEFINE_MUTEX(cpuset_mutex);
+ static DEFINE_SPINLOCK(callback_lock);
+
++static struct workqueue_struct *cpuset_migrate_mm_wq;
++
+ /*
+ * CPU / memory hotplug is handled asynchronously.
+ */
+@@ -971,31 +973,51 @@ static int update_cpumask(struct cpuset
+ }
+
+ /*
+- * cpuset_migrate_mm
+- *
+- * Migrate memory region from one set of nodes to another.
+- *
+- * Temporarilly set tasks mems_allowed to target nodes of migration,
+- * so that the migration code can allocate pages on these nodes.
+- *
+- * While the mm_struct we are migrating is typically from some
+- * other task, the task_struct mems_allowed that we are hacking
+- * is for our current task, which must allocate new pages for that
+- * migrating memory region.
++ * Migrate memory region from one set of nodes to another. This is
++ * performed asynchronously as it can be called from process migration path
++ * holding locks involved in process management. All mm migrations are
++ * performed in the queued order and can be waited for by flushing
++ * cpuset_migrate_mm_wq.
+ */
+
++struct cpuset_migrate_mm_work {
++ struct work_struct work;
++ struct mm_struct *mm;
++ nodemask_t from;
++ nodemask_t to;
++};
++
++static void cpuset_migrate_mm_workfn(struct work_struct *work)
++{
++ struct cpuset_migrate_mm_work *mwork =
++ container_of(work, struct cpuset_migrate_mm_work, work);
++
++ /* on a wq worker, no need to worry about %current's mems_allowed */
++ do_migrate_pages(mwork->mm, &mwork->from, &mwork->to, MPOL_MF_MOVE_ALL);
++ mmput(mwork->mm);
++ kfree(mwork);
++}
++
+ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
+ const nodemask_t *to)
+ {
+- struct task_struct *tsk = current;
+-
+- tsk->mems_allowed = *to;
++ struct cpuset_migrate_mm_work *mwork;
+
+- do_migrate_pages(mm, from, to, MPOL_MF_MOVE_ALL);
++ mwork = kzalloc(sizeof(*mwork), GFP_KERNEL);
++ if (mwork) {
++ mwork->mm = mm;
++ mwork->from = *from;
++ mwork->to = *to;
++ INIT_WORK(&mwork->work, cpuset_migrate_mm_workfn);
++ queue_work(cpuset_migrate_mm_wq, &mwork->work);
++ } else {
++ mmput(mm);
++ }
++}
+
+- rcu_read_lock();
+- guarantee_online_mems(task_cs(tsk), &tsk->mems_allowed);
+- rcu_read_unlock();
++void cpuset_post_attach_flush(void)
++{
++ flush_workqueue(cpuset_migrate_mm_wq);
+ }
+
+ /*
+@@ -1096,7 +1118,8 @@ static void update_tasks_nodemask(struct
+ mpol_rebind_mm(mm, &cs->mems_allowed);
+ if (migrate)
+ cpuset_migrate_mm(mm, &cs->old_mems_allowed, &newmems);
+- mmput(mm);
++ else
++ mmput(mm);
+ }
+ css_task_iter_end(&it);
+
+@@ -1541,11 +1564,11 @@ static void cpuset_attach(struct cgroup_
+ * @old_mems_allowed is the right nodesets that we
+ * migrate mm from.
+ */
+- if (is_memory_migrate(cs)) {
++ if (is_memory_migrate(cs))
+ cpuset_migrate_mm(mm, &oldcs->old_mems_allowed,
+ &cpuset_attach_nodemask_to);
+- }
+- mmput(mm);
++ else
++ mmput(mm);
+ }
+ }
+
+@@ -1710,6 +1733,7 @@ out_unlock:
+ mutex_unlock(&cpuset_mutex);
+ kernfs_unbreak_active_protection(of->kn);
+ css_put(&cs->css);
++ flush_workqueue(cpuset_migrate_mm_wq);
+ return retval ?: nbytes;
+ }
+
+@@ -2355,6 +2379,9 @@ void __init cpuset_init_smp(void)
+ top_cpuset.effective_mems = node_states[N_MEMORY];
+
+ register_hotmemory_notifier(&cpuset_track_online_nodes_nb);
++
++ cpuset_migrate_mm_wq = alloc_ordered_workqueue("cpuset_migrate_mm", 0);
++ BUG_ON(!cpuset_migrate_mm_wq);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/events/core.c linux-libre-4.4.7-gnu/kernel/events/core.c
+--- linux-libre-4.4-gnu/kernel/events/core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/events/core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3434,7 +3434,7 @@ find_lively_task_by_vpid(pid_t vpid)
+
+ /* Reuse ptrace permission checks for now. */
+ err = -EACCES;
+- if (!ptrace_may_access(task, PTRACE_MODE_READ))
++ if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
+ goto errout;
+
+ return task;
+@@ -7979,6 +7979,9 @@ perf_event_alloc(struct perf_event_attr
+ }
+ }
+
++ /* symmetric to unaccount_event() in _free_event() */
++ account_event(event);
++
+ return event;
+
+ err_per_task:
+@@ -8342,8 +8345,6 @@ SYSCALL_DEFINE5(perf_event_open,
+ }
+ }
+
+- account_event(event);
+-
+ /*
+ * Special case software events and allow them to be part of
+ * any hardware group.
+@@ -8626,8 +8627,6 @@ perf_event_create_kernel_counter(struct
+ /* Mark owner so we could distinguish it from user events. */
+ event->owner = EVENT_OWNER_KERNEL;
+
+- account_event(event);
+-
+ ctx = find_get_context(event->pmu, task, event);
+ if (IS_ERR(ctx)) {
+ err = PTR_ERR(ctx);
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/futex.c linux-libre-4.4.7-gnu/kernel/futex.c
+--- linux-libre-4.4-gnu/kernel/futex.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/futex.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2755,6 +2755,11 @@ static int futex_wait_requeue_pi(u32 __u
+ if (q.pi_state && (q.pi_state->owner != current)) {
+ spin_lock(q.lock_ptr);
+ ret = fixup_pi_state_owner(uaddr2, &q, current);
++ /*
++ * Drop the reference to the pi state which
++ * the requeue_pi() code acquired for us.
++ */
++ free_pi_state(q.pi_state);
+ spin_unlock(q.lock_ptr);
+ }
+ } else {
+@@ -2881,7 +2886,7 @@ SYSCALL_DEFINE3(get_robust_list, int, pi
+ }
+
+ ret = -EPERM;
+- if (!ptrace_may_access(p, PTRACE_MODE_READ))
++ if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
+ goto err_unlock;
+
+ head = p->robust_list;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/futex_compat.c linux-libre-4.4.7-gnu/kernel/futex_compat.c
+--- linux-libre-4.4-gnu/kernel/futex_compat.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/futex_compat.c 2016-04-12 12:09:26.000000000 -0400
+@@ -155,7 +155,7 @@ COMPAT_SYSCALL_DEFINE3(get_robust_list,
+ }
+
+ ret = -EPERM;
+- if (!ptrace_may_access(p, PTRACE_MODE_READ))
++ if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
+ goto err_unlock;
+
+ head = p->compat_robust_list;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/irq/handle.c linux-libre-4.4.7-gnu/kernel/irq/handle.c
+--- linux-libre-4.4-gnu/kernel/irq/handle.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/irq/handle.c 2016-04-12 12:09:26.000000000 -0400
+@@ -138,7 +138,8 @@ irqreturn_t handle_irq_event_percpu(stru
+ unsigned int flags = 0, irq = desc->irq_data.irq;
+ struct irqaction *action = desc->action;
+
+- do {
++ /* action might have become NULL since we dropped the lock */
++ while (action) {
+ irqreturn_t res;
+
+ trace_irq_handler_entry(irq, action);
+@@ -173,7 +174,7 @@ irqreturn_t handle_irq_event_percpu(stru
+
+ retval |= res;
+ action = action->next;
+- } while (action);
++ }
+
+ add_interrupt_randomness(irq, flags);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/kcmp.c linux-libre-4.4.7-gnu/kernel/kcmp.c
+--- linux-libre-4.4-gnu/kernel/kcmp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/kcmp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -122,8 +122,8 @@ SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t
+ &task2->signal->cred_guard_mutex);
+ if (ret)
+ goto err;
+- if (!ptrace_may_access(task1, PTRACE_MODE_READ) ||
+- !ptrace_may_access(task2, PTRACE_MODE_READ)) {
++ if (!ptrace_may_access(task1, PTRACE_MODE_READ_REALCREDS) ||
++ !ptrace_may_access(task2, PTRACE_MODE_READ_REALCREDS)) {
+ ret = -EPERM;
+ goto err_unlock;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/memremap.c linux-libre-4.4.7-gnu/kernel/memremap.c
+--- linux-libre-4.4-gnu/kernel/memremap.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/memremap.c 2016-04-12 12:09:26.000000000 -0400
+@@ -111,7 +111,7 @@ EXPORT_SYMBOL(memunmap);
+
+ static void devm_memremap_release(struct device *dev, void *res)
+ {
+- memunmap(res);
++ memunmap(*(void **)res);
+ }
+
+ static int devm_memremap_match(struct device *dev, void *res, void *match_data)
+@@ -133,8 +133,10 @@ void *devm_memremap(struct device *dev,
+ if (addr) {
+ *ptr = addr;
+ devres_add(dev, ptr);
+- } else
++ } else {
+ devres_free(ptr);
++ return ERR_PTR(-ENXIO);
++ }
+
+ return addr;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/module.c linux-libre-4.4.7-gnu/kernel/module.c
+--- linux-libre-4.4-gnu/kernel/module.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/module.c 2016-04-12 12:09:26.000000000 -0400
+@@ -327,6 +327,9 @@ struct load_info {
+ struct _ddebug *debug;
+ unsigned int num_debug;
+ bool sig_ok;
++#ifdef CONFIG_KALLSYMS
++ unsigned long mod_kallsyms_init_off;
++#endif
+ struct {
+ unsigned int sym, str, mod, vers, info, pcpu;
+ } index;
+@@ -2492,10 +2495,21 @@ static void layout_symtab(struct module
+ strsect->sh_flags |= SHF_ALLOC;
+ strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
+ info->index.str) | INIT_OFFSET_MASK;
+- mod->init_size = debug_align(mod->init_size);
+ pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
++
++ /* We'll tack temporary mod_kallsyms on the end. */
++ mod->init_size = ALIGN(mod->init_size,
++ __alignof__(struct mod_kallsyms));
++ info->mod_kallsyms_init_off = mod->init_size;
++ mod->init_size += sizeof(struct mod_kallsyms);
++ mod->init_size = debug_align(mod->init_size);
+ }
+
++/*
++ * We use the full symtab and strtab which layout_symtab arranged to
++ * be appended to the init section. Later we switch to the cut-down
++ * core-only ones.
++ */
+ static void add_kallsyms(struct module *mod, const struct load_info *info)
+ {
+ unsigned int i, ndst;
+@@ -2504,28 +2518,33 @@ static void add_kallsyms(struct module *
+ char *s;
+ Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
+
+- mod->symtab = (void *)symsec->sh_addr;
+- mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
++ /* Set up to point into init section. */
++ mod->kallsyms = mod->module_init + info->mod_kallsyms_init_off;
++
++ mod->kallsyms->symtab = (void *)symsec->sh_addr;
++ mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
+ /* Make sure we get permanent strtab: don't use info->strtab. */
+- mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
++ mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
+
+ /* Set types up while we still have access to sections. */
+- for (i = 0; i < mod->num_symtab; i++)
+- mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
++ for (i = 0; i < mod->kallsyms->num_symtab; i++)
++ mod->kallsyms->symtab[i].st_info
++ = elf_type(&mod->kallsyms->symtab[i], info);
+
+- mod->core_symtab = dst = mod->module_core + info->symoffs;
+- mod->core_strtab = s = mod->module_core + info->stroffs;
+- src = mod->symtab;
+- for (ndst = i = 0; i < mod->num_symtab; i++) {
++ /* Now populate the cut down core kallsyms for after init. */
++ mod->core_kallsyms.symtab = dst = mod->module_core + info->symoffs;
++ mod->core_kallsyms.strtab = s = mod->module_core + info->stroffs;
++ src = mod->kallsyms->symtab;
++ for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
+ if (i == 0 ||
+ is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+ dst[ndst] = src[i];
+- dst[ndst++].st_name = s - mod->core_strtab;
+- s += strlcpy(s, &mod->strtab[src[i].st_name],
++ dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
++ s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
+ KSYM_NAME_LEN) + 1;
+ }
+ }
+- mod->core_num_syms = ndst;
++ mod->core_kallsyms.num_symtab = ndst;
+ }
+ #else
+ static inline void layout_symtab(struct module *mod, struct load_info *info)
+@@ -3274,9 +3293,8 @@ static noinline int do_init_module(struc
+ module_put(mod);
+ trim_init_extable(mod);
+ #ifdef CONFIG_KALLSYMS
+- mod->num_symtab = mod->core_num_syms;
+- mod->symtab = mod->core_symtab;
+- mod->strtab = mod->core_strtab;
++ /* Switch to core kallsyms now init is done: kallsyms may be walking! */
++ rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
+ #endif
+ mod_tree_remove_init(mod);
+ unset_module_init_ro_nx(mod);
+@@ -3515,7 +3533,7 @@ static int load_module(struct load_info
+
+ /* Module is ready to execute: parsing args may do that. */
+ after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
+- -32768, 32767, NULL,
++ -32768, 32767, mod,
+ unknown_module_param_cb);
+ if (IS_ERR(after_dashes)) {
+ err = PTR_ERR(after_dashes);
+@@ -3646,6 +3664,11 @@ static inline int is_arm_mapping_symbol(
+ && (str[2] == '\0' || str[2] == '.');
+ }
+
++static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum)
++{
++ return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
++}
++
+ static const char *get_ksymbol(struct module *mod,
+ unsigned long addr,
+ unsigned long *size,
+@@ -3653,6 +3676,7 @@ static const char *get_ksymbol(struct mo
+ {
+ unsigned int i, best = 0;
+ unsigned long nextval;
++ struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
+
+ /* At worse, next value is at end of module */
+ if (within_module_init(addr, mod))
+@@ -3662,32 +3686,32 @@ static const char *get_ksymbol(struct mo
+
+ /* Scan for closest preceding symbol, and next symbol. (ELF
+ starts real symbols at 1). */
+- for (i = 1; i < mod->num_symtab; i++) {
+- if (mod->symtab[i].st_shndx == SHN_UNDEF)
++ for (i = 1; i < kallsyms->num_symtab; i++) {
++ if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
+ continue;
+
+ /* We ignore unnamed symbols: they're uninformative
+ * and inserted at a whim. */
+- if (mod->symtab[i].st_value <= addr
+- && mod->symtab[i].st_value > mod->symtab[best].st_value
+- && *(mod->strtab + mod->symtab[i].st_name) != '\0'
+- && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
++ if (*symname(kallsyms, i) == '\0'
++ || is_arm_mapping_symbol(symname(kallsyms, i)))
++ continue;
++
++ if (kallsyms->symtab[i].st_value <= addr
++ && kallsyms->symtab[i].st_value > kallsyms->symtab[best].st_value)
+ best = i;
+- if (mod->symtab[i].st_value > addr
+- && mod->symtab[i].st_value < nextval
+- && *(mod->strtab + mod->symtab[i].st_name) != '\0'
+- && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
+- nextval = mod->symtab[i].st_value;
++ if (kallsyms->symtab[i].st_value > addr
++ && kallsyms->symtab[i].st_value < nextval)
++ nextval = kallsyms->symtab[i].st_value;
+ }
+
+ if (!best)
+ return NULL;
+
+ if (size)
+- *size = nextval - mod->symtab[best].st_value;
++ *size = nextval - kallsyms->symtab[best].st_value;
+ if (offset)
+- *offset = addr - mod->symtab[best].st_value;
+- return mod->strtab + mod->symtab[best].st_name;
++ *offset = addr - kallsyms->symtab[best].st_value;
++ return symname(kallsyms, best);
+ }
+
+ /* For kallsyms to ask for address resolution. NULL means not found. Careful
+@@ -3777,19 +3801,21 @@ int module_get_kallsym(unsigned int symn
+
+ preempt_disable();
+ list_for_each_entry_rcu(mod, &modules, list) {
++ struct mod_kallsyms *kallsyms;
++
+ if (mod->state == MODULE_STATE_UNFORMED)
+ continue;
+- if (symnum < mod->num_symtab) {
+- *value = mod->symtab[symnum].st_value;
+- *type = mod->symtab[symnum].st_info;
+- strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
+- KSYM_NAME_LEN);
++ kallsyms = rcu_dereference_sched(mod->kallsyms);
++ if (symnum < kallsyms->num_symtab) {
++ *value = kallsyms->symtab[symnum].st_value;
++ *type = kallsyms->symtab[symnum].st_info;
++ strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN);
+ strlcpy(module_name, mod->name, MODULE_NAME_LEN);
+ *exported = is_exported(name, *value, mod);
+ preempt_enable();
+ return 0;
+ }
+- symnum -= mod->num_symtab;
++ symnum -= kallsyms->num_symtab;
+ }
+ preempt_enable();
+ return -ERANGE;
+@@ -3798,11 +3824,12 @@ int module_get_kallsym(unsigned int symn
+ static unsigned long mod_find_symname(struct module *mod, const char *name)
+ {
+ unsigned int i;
++ struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
+
+- for (i = 0; i < mod->num_symtab; i++)
+- if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0 &&
+- mod->symtab[i].st_info != 'U')
+- return mod->symtab[i].st_value;
++ for (i = 0; i < kallsyms->num_symtab; i++)
++ if (strcmp(name, symname(kallsyms, i)) == 0 &&
++ kallsyms->symtab[i].st_info != 'U')
++ return kallsyms->symtab[i].st_value;
+ return 0;
+ }
+
+@@ -3841,11 +3868,14 @@ int module_kallsyms_on_each_symbol(int (
+ module_assert_mutex();
+
+ list_for_each_entry(mod, &modules, list) {
++ /* We hold module_mutex: no need for rcu_dereference_sched */
++ struct mod_kallsyms *kallsyms = mod->kallsyms;
++
+ if (mod->state == MODULE_STATE_UNFORMED)
+ continue;
+- for (i = 0; i < mod->num_symtab; i++) {
+- ret = fn(data, mod->strtab + mod->symtab[i].st_name,
+- mod, mod->symtab[i].st_value);
++ for (i = 0; i < kallsyms->num_symtab; i++) {
++ ret = fn(data, symname(kallsyms, i),
++ mod, kallsyms->symtab[i].st_value);
+ if (ret != 0)
+ return ret;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/panic.c linux-libre-4.4.7-gnu/kernel/panic.c
+--- linux-libre-4.4-gnu/kernel/panic.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/panic.c 2016-04-12 12:09:26.000000000 -0400
+@@ -157,8 +157,7 @@ void panic(const char *fmt, ...)
+ * panic() is not being callled from OOPS.
+ */
+ debug_locks_off();
+- console_trylock();
+- console_unlock();
++ console_flush_on_panic();
+
+ if (!panic_blink)
+ panic_blink = no_blink;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/power/hibernate.c linux-libre-4.4.7-gnu/kernel/power/hibernate.c
+--- linux-libre-4.4-gnu/kernel/power/hibernate.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/power/hibernate.c 2016-04-12 12:09:26.000000000 -0400
+@@ -339,6 +339,7 @@ int hibernation_snapshot(int platform_mo
+ pm_message_t msg;
+ int error;
+
++ pm_suspend_clear_flags();
+ error = platform_begin(platform_mode);
+ if (error)
+ goto Close;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/printk/printk.c linux-libre-4.4.7-gnu/kernel/printk/printk.c
+--- linux-libre-4.4-gnu/kernel/printk/printk.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/printk/printk.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2233,13 +2233,24 @@ void console_unlock(void)
+ static u64 seen_seq;
+ unsigned long flags;
+ bool wake_klogd = false;
+- bool retry;
++ bool do_cond_resched, retry;
+
+ if (console_suspended) {
+ up_console_sem();
+ return;
+ }
+
++ /*
++ * Console drivers are called under logbuf_lock, so
++ * @console_may_schedule should be cleared before; however, we may
++ * end up dumping a lot of lines, for example, if called from
++ * console registration path, and should invoke cond_resched()
++ * between lines if allowable. Not doing so can cause a very long
++ * scheduling stall on a slow console leading to RCU stall and
++ * softlockup warnings which exacerbate the issue with more
++ * messages practically incapacitating the system.
++ */
++ do_cond_resched = console_may_schedule;
+ console_may_schedule = 0;
+
+ /* flush buffered message fragment immediately to console */
+@@ -2311,6 +2322,9 @@ skip:
+ call_console_drivers(level, ext_text, ext_len, text, len);
+ start_critical_timings();
+ local_irq_restore(flags);
++
++ if (do_cond_resched)
++ cond_resched();
+ }
+ console_locked = 0;
+
+@@ -2378,6 +2392,25 @@ void console_unblank(void)
+ console_unlock();
+ }
+
++/**
++ * console_flush_on_panic - flush console content on panic
++ *
++ * Immediately output all pending messages no matter what.
++ */
++void console_flush_on_panic(void)
++{
++ /*
++ * If someone else is holding the console lock, trylock will fail
++ * and may_schedule may be set. Ignore and proceed to unlock so
++ * that messages are flushed out. As this can be called from any
++ * context and we don't want to get preempted while flushing,
++ * ensure may_schedule is cleared.
++ */
++ console_trylock();
++ console_may_schedule = 0;
++ console_unlock();
++}
++
+ /*
+ * Return the console tty driver structure and its associated index
+ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/ptrace.c linux-libre-4.4.7-gnu/kernel/ptrace.c
+--- linux-libre-4.4-gnu/kernel/ptrace.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/ptrace.c 2016-04-12 12:09:26.000000000 -0400
+@@ -219,6 +219,14 @@ static int ptrace_has_cap(struct user_na
+ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
+ {
+ const struct cred *cred = current_cred(), *tcred;
++ int dumpable = 0;
++ kuid_t caller_uid;
++ kgid_t caller_gid;
++
++ if (!(mode & PTRACE_MODE_FSCREDS) == !(mode & PTRACE_MODE_REALCREDS)) {
++ WARN(1, "denying ptrace access check without PTRACE_MODE_*CREDS\n");
++ return -EPERM;
++ }
+
+ /* May we inspect the given task?
+ * This check is used both for attaching with ptrace
+@@ -228,18 +236,33 @@ static int __ptrace_may_access(struct ta
+ * because setting up the necessary parent/child relationship
+ * or halting the specified task is impossible.
+ */
+- int dumpable = 0;
++
+ /* Don't let security modules deny introspection */
+ if (same_thread_group(task, current))
+ return 0;
+ rcu_read_lock();
++ if (mode & PTRACE_MODE_FSCREDS) {
++ caller_uid = cred->fsuid;
++ caller_gid = cred->fsgid;
++ } else {
++ /*
++ * Using the euid would make more sense here, but something
++ * in userland might rely on the old behavior, and this
++ * shouldn't be a security problem since
++ * PTRACE_MODE_REALCREDS implies that the caller explicitly
++ * used a syscall that requests access to another process
++ * (and not a filesystem syscall to procfs).
++ */
++ caller_uid = cred->uid;
++ caller_gid = cred->gid;
++ }
+ tcred = __task_cred(task);
+- if (uid_eq(cred->uid, tcred->euid) &&
+- uid_eq(cred->uid, tcred->suid) &&
+- uid_eq(cred->uid, tcred->uid) &&
+- gid_eq(cred->gid, tcred->egid) &&
+- gid_eq(cred->gid, tcred->sgid) &&
+- gid_eq(cred->gid, tcred->gid))
++ if (uid_eq(caller_uid, tcred->euid) &&
++ uid_eq(caller_uid, tcred->suid) &&
++ uid_eq(caller_uid, tcred->uid) &&
++ gid_eq(caller_gid, tcred->egid) &&
++ gid_eq(caller_gid, tcred->sgid) &&
++ gid_eq(caller_gid, tcred->gid))
+ goto ok;
+ if (ptrace_has_cap(tcred->user_ns, mode))
+ goto ok;
+@@ -306,7 +329,7 @@ static int ptrace_attach(struct task_str
+ goto out;
+
+ task_lock(task);
+- retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
++ retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS);
+ task_unlock(task);
+ if (retval)
+ goto unlock_creds;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/resource.c linux-libre-4.4.7-gnu/kernel/resource.c
+--- linux-libre-4.4-gnu/kernel/resource.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/resource.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1083,9 +1083,10 @@ struct resource * __request_region(struc
+ if (!conflict)
+ break;
+ if (conflict != parent) {
+- parent = conflict;
+- if (!(conflict->flags & IORESOURCE_BUSY))
++ if (!(conflict->flags & IORESOURCE_BUSY)) {
++ parent = conflict;
+ continue;
++ }
+ }
+ if (conflict->flags & flags & IORESOURCE_MUXED) {
+ add_wait_queue(&muxed_resource_wait, &wait);
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/sched/core.c linux-libre-4.4.7-gnu/kernel/sched/core.c
+--- linux-libre-4.4-gnu/kernel/sched/core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/sched/core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -5525,6 +5525,7 @@ migration_call(struct notifier_block *nf
+
+ case CPU_UP_PREPARE:
+ rq->calc_load_update = calc_load_update;
++ account_reset_rq(rq);
+ break;
+
+ case CPU_ONLINE:
+@@ -6738,7 +6739,7 @@ static void sched_init_numa(void)
+
+ sched_domains_numa_masks[i][j] = mask;
+
+- for (k = 0; k < nr_node_ids; k++) {
++ for_each_node(k) {
+ if (node_distance(j, k) > sched_domains_numa_distance[i])
+ continue;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/sched/cputime.c linux-libre-4.4.7-gnu/kernel/sched/cputime.c
+--- linux-libre-4.4-gnu/kernel/sched/cputime.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/sched/cputime.c 2016-04-12 12:09:26.000000000 -0400
+@@ -259,21 +259,21 @@ static __always_inline bool steal_accoun
+ #ifdef CONFIG_PARAVIRT
+ if (static_key_false(&paravirt_steal_enabled)) {
+ u64 steal;
+- cputime_t steal_ct;
++ unsigned long steal_jiffies;
+
+ steal = paravirt_steal_clock(smp_processor_id());
+ steal -= this_rq()->prev_steal_time;
+
+ /*
+- * cputime_t may be less precise than nsecs (eg: if it's
+- * based on jiffies). Lets cast the result to cputime
++ * steal is in nsecs but our caller is expecting steal
++ * time in jiffies. Lets cast the result to jiffies
+ * granularity and account the rest on the next rounds.
+ */
+- steal_ct = nsecs_to_cputime(steal);
+- this_rq()->prev_steal_time += cputime_to_nsecs(steal_ct);
++ steal_jiffies = nsecs_to_jiffies(steal);
++ this_rq()->prev_steal_time += jiffies_to_nsecs(steal_jiffies);
+
+- account_steal_time(steal_ct);
+- return steal_ct;
++ account_steal_time(jiffies_to_cputime(steal_jiffies));
++ return steal_jiffies;
+ }
+ #endif
+ return false;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/sched/sched.h linux-libre-4.4.7-gnu/kernel/sched/sched.h
+--- linux-libre-4.4-gnu/kernel/sched/sched.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/sched/sched.h 2016-04-12 12:09:26.000000000 -0400
+@@ -1770,3 +1770,16 @@ static inline u64 irq_time_read(int cpu)
+ }
+ #endif /* CONFIG_64BIT */
+ #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
++
++static inline void account_reset_rq(struct rq *rq)
++{
++#ifdef CONFIG_IRQ_TIME_ACCOUNTING
++ rq->prev_irq_time = 0;
++#endif
++#ifdef CONFIG_PARAVIRT
++ rq->prev_steal_time = 0;
++#endif
++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
++ rq->prev_steal_time_rq = 0;
++#endif
++}
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/seccomp.c linux-libre-4.4.7-gnu/kernel/seccomp.c
+--- linux-libre-4.4-gnu/kernel/seccomp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/seccomp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -316,24 +316,24 @@ static inline void seccomp_sync_threads(
+ put_seccomp_filter(thread);
+ smp_store_release(&thread->seccomp.filter,
+ caller->seccomp.filter);
++
++ /*
++ * Don't let an unprivileged task work around
++ * the no_new_privs restriction by creating
++ * a thread that sets it up, enters seccomp,
++ * then dies.
++ */
++ if (task_no_new_privs(caller))
++ task_set_no_new_privs(thread);
++
+ /*
+ * Opt the other thread into seccomp if needed.
+ * As threads are considered to be trust-realm
+ * equivalent (see ptrace_may_access), it is safe to
+ * allow one thread to transition the other.
+ */
+- if (thread->seccomp.mode == SECCOMP_MODE_DISABLED) {
+- /*
+- * Don't let an unprivileged task work around
+- * the no_new_privs restriction by creating
+- * a thread that sets it up, enters seccomp,
+- * then dies.
+- */
+- if (task_no_new_privs(caller))
+- task_set_no_new_privs(thread);
+-
++ if (thread->seccomp.mode == SECCOMP_MODE_DISABLED)
+ seccomp_assign_mode(thread, SECCOMP_MODE_FILTER);
+- }
+ }
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/sys.c linux-libre-4.4.7-gnu/kernel/sys.c
+--- linux-libre-4.4-gnu/kernel/sys.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/sys.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1853,11 +1853,13 @@ static int prctl_set_mm_map(int opt, con
+ user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL;
+ }
+
+- if (prctl_map.exe_fd != (u32)-1)
++ if (prctl_map.exe_fd != (u32)-1) {
+ error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd);
+- down_read(&mm->mmap_sem);
+- if (error)
+- goto out;
++ if (error)
++ return error;
++ }
++
++ down_write(&mm->mmap_sem);
+
+ /*
+ * We don't validate if these members are pointing to
+@@ -1894,10 +1896,8 @@ static int prctl_set_mm_map(int opt, con
+ if (prctl_map.auxv_size)
+ memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv));
+
+- error = 0;
+-out:
+- up_read(&mm->mmap_sem);
+- return error;
++ up_write(&mm->mmap_sem);
++ return 0;
+ }
+ #endif /* CONFIG_CHECKPOINT_RESTORE */
+
+@@ -1963,7 +1963,7 @@ static int prctl_set_mm(int opt, unsigne
+
+ error = -EINVAL;
+
+- down_read(&mm->mmap_sem);
++ down_write(&mm->mmap_sem);
+ vma = find_vma(mm, addr);
+
+ prctl_map.start_code = mm->start_code;
+@@ -2056,7 +2056,7 @@ static int prctl_set_mm(int opt, unsigne
+
+ error = 0;
+ out:
+- up_read(&mm->mmap_sem);
++ up_write(&mm->mmap_sem);
+ return error;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/sysctl_binary.c linux-libre-4.4.7-gnu/kernel/sysctl_binary.c
+--- linux-libre-4.4-gnu/kernel/sysctl_binary.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/sysctl_binary.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1321,7 +1321,7 @@ static ssize_t binary_sysctl(const int *
+ }
+
+ mnt = task_active_pid_ns(current)->proc_mnt;
+- file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
++ file = file_open_root(mnt->mnt_root, mnt, pathname, flags, 0);
+ result = PTR_ERR(file);
+ if (IS_ERR(file))
+ goto out_putname;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/time/hrtimer.c linux-libre-4.4.7-gnu/kernel/time/hrtimer.c
+--- linux-libre-4.4-gnu/kernel/time/hrtimer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/time/hrtimer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtime
+ */
+ static void __remove_hrtimer(struct hrtimer *timer,
+ struct hrtimer_clock_base *base,
+- unsigned long newstate, int reprogram)
++ u8 newstate, int reprogram)
+ {
+ struct hrtimer_cpu_base *cpu_base = base->cpu_base;
+- unsigned int state = timer->state;
++ u8 state = timer->state;
+
+ timer->state = newstate;
+ if (!(state & HRTIMER_STATE_ENQUEUED))
+@@ -930,7 +930,7 @@ static inline int
+ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart)
+ {
+ if (hrtimer_is_queued(timer)) {
+- unsigned long state = timer->state;
++ u8 state = timer->state;
+ int reprogram;
+
+ /*
+@@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, st
+ return 0;
+ }
+
++static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
++ const enum hrtimer_mode mode)
++{
++#ifdef CONFIG_TIME_LOW_RES
++ /*
++ * CONFIG_TIME_LOW_RES indicates that the system has no way to return
++ * granular time values. For relative timers we add hrtimer_resolution
++ * (i.e. one jiffie) to prevent short timeouts.
++ */
++ timer->is_rel = mode & HRTIMER_MODE_REL;
++ if (timer->is_rel)
++ tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
++#endif
++ return tim;
++}
++
+ /**
+ * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
+ * @timer: the timer to be added
+@@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtim
+ /* Remove an active timer from the queue: */
+ remove_hrtimer(timer, base, true);
+
+- if (mode & HRTIMER_MODE_REL) {
++ if (mode & HRTIMER_MODE_REL)
+ tim = ktime_add_safe(tim, base->get_time());
+- /*
+- * CONFIG_TIME_LOW_RES is a temporary way for architectures
+- * to signal that they simply return xtime in
+- * do_gettimeoffset(). In this case we want to round up by
+- * resolution when starting a relative timer, to avoid short
+- * timeouts. This will go away with the GTOD framework.
+- */
+-#ifdef CONFIG_TIME_LOW_RES
+- tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
+-#endif
+- }
++
++ tim = hrtimer_update_lowres(timer, tim, mode);
+
+ hrtimer_set_expires_range_ns(timer, tim, delta_ns);
+
+@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
+ /**
+ * hrtimer_get_remaining - get remaining time for the timer
+ * @timer: the timer to read
++ * @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y
+ */
+-ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
++ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust)
+ {
+ unsigned long flags;
+ ktime_t rem;
+
+ lock_hrtimer_base(timer, &flags);
+- rem = hrtimer_expires_remaining(timer);
++ if (IS_ENABLED(CONFIG_TIME_LOW_RES) && adjust)
++ rem = hrtimer_expires_remaining_adjusted(timer);
++ else
++ rem = hrtimer_expires_remaining(timer);
+ unlock_hrtimer_base(timer, &flags);
+
+ return rem;
+ }
+-EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
++EXPORT_SYMBOL_GPL(__hrtimer_get_remaining);
+
+ #ifdef CONFIG_NO_HZ_COMMON
+ /**
+@@ -1220,6 +1231,14 @@ static void __run_hrtimer(struct hrtimer
+ fn = timer->function;
+
+ /*
++ * Clear the 'is relative' flag for the TIME_LOW_RES case. If the
++ * timer is restarted with a period then it becomes an absolute
++ * timer. If its not restarted it does not matter.
++ */
++ if (IS_ENABLED(CONFIG_TIME_LOW_RES))
++ timer->is_rel = false;
++
++ /*
+ * Because we run timers from hardirq context, there is no chance
+ * they get migrated to another cpu, therefore its safe to unlock
+ * the timer base.
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/time/itimer.c linux-libre-4.4.7-gnu/kernel/time/itimer.c
+--- linux-libre-4.4-gnu/kernel/time/itimer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/time/itimer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -26,7 +26,7 @@
+ */
+ static struct timeval itimer_get_remtime(struct hrtimer *timer)
+ {
+- ktime_t rem = hrtimer_get_remaining(timer);
++ ktime_t rem = __hrtimer_get_remaining(timer, true);
+
+ /*
+ * Racy but safe: if the itimer expires after the above
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/time/posix-clock.c linux-libre-4.4.7-gnu/kernel/time/posix-clock.c
+--- linux-libre-4.4-gnu/kernel/time/posix-clock.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/time/posix-clock.c 2016-04-12 12:09:26.000000000 -0400
+@@ -69,10 +69,10 @@ static ssize_t posix_clock_read(struct f
+ static unsigned int posix_clock_poll(struct file *fp, poll_table *wait)
+ {
+ struct posix_clock *clk = get_posix_clock(fp);
+- int result = 0;
++ unsigned int result = 0;
+
+ if (!clk)
+- return -ENODEV;
++ return POLLERR;
+
+ if (clk->ops.poll)
+ result = clk->ops.poll(clk, fp, wait);
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/time/posix-timers.c linux-libre-4.4.7-gnu/kernel/time/posix-timers.c
+--- linux-libre-4.4-gnu/kernel/time/posix-timers.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/time/posix-timers.c 2016-04-12 12:09:26.000000000 -0400
+@@ -760,7 +760,7 @@ common_timer_get(struct k_itimer *timr,
+ (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+ timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
+
+- remaining = ktime_sub(hrtimer_get_expires(timer), now);
++ remaining = __hrtimer_expires_remaining_adjusted(timer, now);
+ /* Return 0 only, when the timer is expired and not pending */
+ if (remaining.tv64 <= 0) {
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/time/tick-sched.c linux-libre-4.4.7-gnu/kernel/time/tick-sched.c
+--- linux-libre-4.4-gnu/kernel/time/tick-sched.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/time/tick-sched.c 2016-04-12 12:09:26.000000000 -0400
+@@ -977,9 +977,9 @@ static void tick_nohz_switch_to_nohz(voi
+ /* Get the next period */
+ next = tick_init_jiffy_update();
+
+- hrtimer_forward_now(&ts->sched_timer, tick_period);
+ hrtimer_set_expires(&ts->sched_timer, next);
+- tick_program_event(next, 1);
++ hrtimer_forward_now(&ts->sched_timer, tick_period);
++ tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
+ tick_nohz_activate(ts, NOHZ_MODE_LOWRES);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/time/timekeeping.c linux-libre-4.4.7-gnu/kernel/time/timekeeping.c
+--- linux-libre-4.4-gnu/kernel/time/timekeeping.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/time/timekeeping.c 2016-04-12 12:09:26.000000000 -0400
+@@ -305,8 +305,7 @@ static inline s64 timekeeping_get_ns(str
+
+ delta = timekeeping_get_delta(tkr);
+
+- nsec = delta * tkr->mult + tkr->xtime_nsec;
+- nsec >>= tkr->shift;
++ nsec = (delta * tkr->mult + tkr->xtime_nsec) >> tkr->shift;
+
+ /* If arch requires, add in get_arch_timeoffset() */
+ return nsec + arch_gettimeoffset();
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/time/timer_list.c linux-libre-4.4.7-gnu/kernel/time/timer_list.c
+--- linux-libre-4.4-gnu/kernel/time/timer_list.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/time/timer_list.c 2016-04-12 12:09:26.000000000 -0400
+@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct h
+ print_name_offset(m, taddr);
+ SEQ_printf(m, ", ");
+ print_name_offset(m, timer->function);
+- SEQ_printf(m, ", S:%02lx", timer->state);
++ SEQ_printf(m, ", S:%02x", timer->state);
+ #ifdef CONFIG_TIMER_STATS
+ SEQ_printf(m, ", ");
+ print_name_offset(m, timer->start_site);
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/trace/trace.c linux-libre-4.4.7-gnu/kernel/trace/trace.c
+--- linux-libre-4.4-gnu/kernel/trace/trace.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/trace/trace.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1751,7 +1751,7 @@ void trace_buffer_unlock_commit_regs(str
+ {
+ __buffer_unlock_commit(buffer, event);
+
+- ftrace_trace_stack(tr, buffer, flags, 6, pc, regs);
++ ftrace_trace_stack(tr, buffer, flags, 0, pc, regs);
+ ftrace_trace_userstack(buffer, flags, pc);
+ }
+ EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit_regs);
+@@ -4949,7 +4949,10 @@ static ssize_t tracing_splice_read_pipe(
+
+ spd.nr_pages = i;
+
+- ret = splice_to_pipe(pipe, &spd);
++ if (i)
++ ret = splice_to_pipe(pipe, &spd);
++ else
++ ret = 0;
+ out:
+ splice_shrink_spd(&spd);
+ return ret;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/trace/trace_events.c linux-libre-4.4.7-gnu/kernel/trace/trace_events.c
+--- linux-libre-4.4-gnu/kernel/trace/trace_events.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/trace/trace_events.c 2016-04-12 12:09:26.000000000 -0400
+@@ -97,16 +97,16 @@ trace_find_event_field(struct trace_even
+ struct ftrace_event_field *field;
+ struct list_head *head;
+
+- field = __find_event_field(&ftrace_generic_fields, name);
++ head = trace_get_fields(call);
++ field = __find_event_field(head, name);
+ if (field)
+ return field;
+
+- field = __find_event_field(&ftrace_common_fields, name);
++ field = __find_event_field(&ftrace_generic_fields, name);
+ if (field)
+ return field;
+
+- head = trace_get_fields(call);
+- return __find_event_field(head, name);
++ return __find_event_field(&ftrace_common_fields, name);
+ }
+
+ static int __trace_define_field(struct list_head *head, const char *type,
+@@ -171,8 +171,10 @@ static int trace_define_generic_fields(v
+ {
+ int ret;
+
+- __generic_field(int, cpu, FILTER_OTHER);
+- __generic_field(char *, comm, FILTER_PTR_STRING);
++ __generic_field(int, CPU, FILTER_CPU);
++ __generic_field(int, cpu, FILTER_CPU);
++ __generic_field(char *, COMM, FILTER_COMM);
++ __generic_field(char *, comm, FILTER_COMM);
+
+ return ret;
+ }
+@@ -869,7 +871,8 @@ t_next(struct seq_file *m, void *v, loff
+ * The ftrace subsystem is for showing formats only.
+ * They can not be enabled or disabled via the event files.
+ */
+- if (call->class && call->class->reg)
++ if (call->class && call->class->reg &&
++ !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
+ return file;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/trace/trace_events_filter.c linux-libre-4.4.7-gnu/kernel/trace/trace_events_filter.c
+--- linux-libre-4.4-gnu/kernel/trace/trace_events_filter.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/trace/trace_events_filter.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1043,13 +1043,14 @@ static int init_pred(struct filter_parse
+ return -EINVAL;
+ }
+
+- if (is_string_field(field)) {
++ if (field->filter_type == FILTER_COMM) {
++ filter_build_regex(pred);
++ fn = filter_pred_comm;
++ pred->regex.field_len = TASK_COMM_LEN;
++ } else if (is_string_field(field)) {
+ filter_build_regex(pred);
+
+- if (!strcmp(field->name, "comm")) {
+- fn = filter_pred_comm;
+- pred->regex.field_len = TASK_COMM_LEN;
+- } else if (field->filter_type == FILTER_STATIC_STRING) {
++ if (field->filter_type == FILTER_STATIC_STRING) {
+ fn = filter_pred_string;
+ pred->regex.field_len = field->size;
+ } else if (field->filter_type == FILTER_DYN_STRING)
+@@ -1072,7 +1073,7 @@ static int init_pred(struct filter_parse
+ }
+ pred->val = val;
+
+- if (!strcmp(field->name, "cpu"))
++ if (field->filter_type == FILTER_CPU)
+ fn = filter_pred_cpu;
+ else
+ fn = select_comparison_fn(pred->op, field->size,
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/trace/trace_irqsoff.c linux-libre-4.4.7-gnu/kernel/trace/trace_irqsoff.c
+--- linux-libre-4.4-gnu/kernel/trace/trace_irqsoff.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/trace/trace_irqsoff.c 2016-04-12 12:09:26.000000000 -0400
+@@ -109,8 +109,12 @@ static int func_prolog_dec(struct trace_
+ return 0;
+
+ local_save_flags(*flags);
+- /* slight chance to get a false positive on tracing_cpu */
+- if (!irqs_disabled_flags(*flags))
++ /*
++ * Slight chance to get a false positive on tracing_cpu,
++ * although I'm starting to think there isn't a chance.
++ * Leave this for now just to be paranoid.
++ */
++ if (!irqs_disabled_flags(*flags) && !preempt_count())
+ return 0;
+
+ *data = per_cpu_ptr(tr->trace_buffer.data, cpu);
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/trace/trace_printk.c linux-libre-4.4.7-gnu/kernel/trace/trace_printk.c
+--- linux-libre-4.4-gnu/kernel/trace/trace_printk.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/trace/trace_printk.c 2016-04-12 12:09:26.000000000 -0400
+@@ -296,6 +296,9 @@ static int t_show(struct seq_file *m, vo
+ const char *str = *fmt;
+ int i;
+
++ if (!*fmt)
++ return 0;
++
+ seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt);
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/trace/trace_stack.c linux-libre-4.4.7-gnu/kernel/trace/trace_stack.c
+--- linux-libre-4.4-gnu/kernel/trace/trace_stack.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/trace/trace_stack.c 2016-04-12 12:09:26.000000000 -0400
+@@ -126,6 +126,13 @@ check_stack(unsigned long ip, unsigned l
+ }
+
+ /*
++ * Some archs may not have the passed in ip in the dump.
++ * If that happens, we need to show everything.
++ */
++ if (i == stack_trace_max.nr_entries)
++ i = 0;
++
++ /*
+ * Now find where in the stack these are.
+ */
+ x = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/watchdog.c linux-libre-4.4.7-gnu/kernel/watchdog.c
+--- linux-libre-4.4-gnu/kernel/watchdog.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/watchdog.c 2016-04-12 12:09:26.000000000 -0400
+@@ -907,6 +907,9 @@ static int proc_watchdog_common(int whic
+ * both lockup detectors are disabled if proc_watchdog_update()
+ * returns an error.
+ */
++ if (old == new)
++ goto out;
++
+ err = proc_watchdog_update();
+ }
+ out:
+@@ -951,7 +954,7 @@ int proc_soft_watchdog(struct ctl_table
+ int proc_watchdog_thresh(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+- int err, old;
++ int err, old, new;
+
+ get_online_cpus();
+ mutex_lock(&watchdog_proc_mutex);
+@@ -971,6 +974,10 @@ int proc_watchdog_thresh(struct ctl_tabl
+ /*
+ * Update the sample period. Restore on failure.
+ */
++ new = ACCESS_ONCE(watchdog_thresh);
++ if (old == new)
++ goto out;
++
+ set_sample_period();
+ err = proc_watchdog_update();
+ if (err) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/kernel/workqueue.c linux-libre-4.4.7-gnu/kernel/workqueue.c
+--- linux-libre-4.4-gnu/kernel/workqueue.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/kernel/workqueue.c 2016-04-12 12:09:26.000000000 -0400
+@@ -568,6 +568,16 @@ static struct pool_workqueue *unbound_pw
+ int node)
+ {
+ assert_rcu_or_wq_mutex_or_pool_mutex(wq);
++
++ /*
++ * XXX: @node can be NUMA_NO_NODE if CPU goes offline while a
++ * delayed item is pending. The plan is to keep CPU -> NODE
++ * mapping valid and stable across CPU on/offlines. Once that
++ * happens, this workaround can be removed.
++ */
++ if (unlikely(node == NUMA_NO_NODE))
++ return wq->dfl_pwq;
++
+ return rcu_dereference_raw(wq->numa_pwq_tbl[node]);
+ }
+
+@@ -1458,13 +1468,13 @@ static void __queue_delayed_work(int cpu
+ 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;
+
+- add_timer_on(timer, cpu);
++ if (unlikely(cpu != WORK_CPU_UNBOUND))
++ add_timer_on(timer, cpu);
++ else
++ add_timer(timer);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/dma-debug.c linux-libre-4.4.7-gnu/lib/dma-debug.c
+--- linux-libre-4.4-gnu/lib/dma-debug.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/dma-debug.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1181,7 +1181,7 @@ static inline bool overlap(void *addr, u
+
+ static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len)
+ {
+- if (overlap(addr, len, _text, _etext) ||
++ if (overlap(addr, len, _stext, _etext) ||
+ overlap(addr, len, __start_rodata, __end_rodata))
+ err_printk(dev, NULL, "DMA-API: device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/dump_stack.c linux-libre-4.4.7-gnu/lib/dump_stack.c
+--- linux-libre-4.4-gnu/lib/dump_stack.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/dump_stack.c 2016-04-12 12:09:26.000000000 -0400
+@@ -25,6 +25,7 @@ static atomic_t dump_lock = ATOMIC_INIT(
+
+ asmlinkage __visible void dump_stack(void)
+ {
++ unsigned long flags;
+ int was_locked;
+ int old;
+ int cpu;
+@@ -33,9 +34,8 @@ asmlinkage __visible void dump_stack(voi
+ * Permit this cpu to perform nested stack dumps while serialising
+ * against other CPUs
+ */
+- preempt_disable();
+-
+ retry:
++ local_irq_save(flags);
+ cpu = smp_processor_id();
+ old = atomic_cmpxchg(&dump_lock, -1, cpu);
+ if (old == -1) {
+@@ -43,6 +43,7 @@ retry:
+ } else if (old == cpu) {
+ was_locked = 1;
+ } else {
++ local_irq_restore(flags);
+ cpu_relax();
+ goto retry;
+ }
+@@ -52,7 +53,7 @@ retry:
+ if (!was_locked)
+ atomic_set(&dump_lock, -1);
+
+- preempt_enable();
++ local_irq_restore(flags);
+ }
+ #else
+ asmlinkage __visible void dump_stack(void)
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/Kconfig linux-libre-4.4.7-gnu/lib/Kconfig
+--- linux-libre-4.4-gnu/lib/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -210,9 +210,11 @@ config RANDOM32_SELFTEST
+ # compression support is select'ed if needed
+ #
+ config 842_COMPRESS
++ select CRC32
+ tristate
+
+ config 842_DECOMPRESS
++ select CRC32
+ tristate
+
+ config ZLIB_INFLATE
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/klist.c linux-libre-4.4.7-gnu/lib/klist.c
+--- linux-libre-4.4-gnu/lib/klist.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/klist.c 2016-04-12 12:09:26.000000000 -0400
+@@ -282,9 +282,9 @@ void klist_iter_init_node(struct klist *
+ struct klist_node *n)
+ {
+ i->i_klist = k;
+- i->i_cur = n;
+- if (n)
+- kref_get(&n->n_ref);
++ i->i_cur = NULL;
++ if (n && kref_get_unless_zero(&n->n_ref))
++ i->i_cur = n;
+ }
+ EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/libcrc32c.c linux-libre-4.4.7-gnu/lib/libcrc32c.c
+--- linux-libre-4.4-gnu/lib/libcrc32c.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/libcrc32c.c 2016-04-12 12:09:26.000000000 -0400
+@@ -74,3 +74,4 @@ module_exit(libcrc32c_mod_fini);
+ MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
+ MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
+ MODULE_LICENSE("GPL");
++MODULE_SOFTDEP("pre: crc32c");
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/radix-tree.c linux-libre-4.4.7-gnu/lib/radix-tree.c
+--- linux-libre-4.4-gnu/lib/radix-tree.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/radix-tree.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1019,9 +1019,13 @@ radix_tree_gang_lookup(struct radix_tree
+ return 0;
+
+ radix_tree_for_each_slot(slot, root, &iter, first_index) {
+- results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
++ results[ret] = rcu_dereference_raw(*slot);
+ if (!results[ret])
+ continue;
++ if (radix_tree_is_indirect_ptr(results[ret])) {
++ slot = radix_tree_iter_retry(&iter);
++ continue;
++ }
+ if (++ret == max_items)
+ break;
+ }
+@@ -1098,9 +1102,13 @@ radix_tree_gang_lookup_tag(struct radix_
+ return 0;
+
+ radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) {
+- results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
++ results[ret] = rcu_dereference_raw(*slot);
+ if (!results[ret])
+ continue;
++ if (radix_tree_is_indirect_ptr(results[ret])) {
++ slot = radix_tree_iter_retry(&iter);
++ continue;
++ }
+ if (++ret == max_items)
+ break;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/string_helpers.c linux-libre-4.4.7-gnu/lib/string_helpers.c
+--- linux-libre-4.4-gnu/lib/string_helpers.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/string_helpers.c 2016-04-12 12:09:26.000000000 -0400
+@@ -43,50 +43,73 @@ void string_get_size(u64 size, u64 blk_s
+ [STRING_UNITS_10] = 1000,
+ [STRING_UNITS_2] = 1024,
+ };
+- int i, j;
+- u32 remainder = 0, sf_cap, exp;
++ static const unsigned int rounding[] = { 500, 50, 5 };
++ int i = 0, j;
++ u32 remainder = 0, sf_cap;
+ char tmp[8];
+ const char *unit;
+
+ tmp[0] = '\0';
+- i = 0;
+- if (!size)
++
++ if (blk_size == 0)
++ size = 0;
++ if (size == 0)
+ goto out;
+
+- while (blk_size >= divisor[units]) {
+- remainder = do_div(blk_size, divisor[units]);
++ /* This is Napier's algorithm. Reduce the original block size to
++ *
++ * coefficient * divisor[units]^i
++ *
++ * we do the reduction so both coefficients are just under 32 bits so
++ * that multiplying them together won't overflow 64 bits and we keep
++ * as much precision as possible in the numbers.
++ *
++ * Note: it's safe to throw away the remainders here because all the
++ * precision is in the coefficients.
++ */
++ while (blk_size >> 32) {
++ do_div(blk_size, divisor[units]);
+ i++;
+ }
+
+- exp = divisor[units] / (u32)blk_size;
+- /*
+- * size must be strictly greater than exp here to ensure that remainder
+- * is greater than divisor[units] coming out of the if below.
+- */
+- if (size > exp) {
+- remainder = do_div(size, divisor[units]);
+- remainder *= blk_size;
++ while (size >> 32) {
++ do_div(size, divisor[units]);
+ i++;
+- } else {
+- remainder *= size;
+ }
+
++ /* now perform the actual multiplication keeping i as the sum of the
++ * two logarithms */
+ size *= blk_size;
+- size += remainder / divisor[units];
+- remainder %= divisor[units];
+
++ /* and logarithmically reduce it until it's just under the divisor */
+ while (size >= divisor[units]) {
+ remainder = do_div(size, divisor[units]);
+ i++;
+ }
+
++ /* work out in j how many digits of precision we need from the
++ * remainder */
+ sf_cap = size;
+ for (j = 0; sf_cap*10 < 1000; j++)
+ sf_cap *= 10;
+
+- if (j) {
++ if (units == STRING_UNITS_2) {
++ /* express the remainder as a decimal. It's currently the
++ * numerator of a fraction whose denominator is
++ * divisor[units], which is 1 << 10 for STRING_UNITS_2 */
+ remainder *= 1000;
+- remainder /= divisor[units];
++ remainder >>= 10;
++ }
++
++ /* add a 5 to the digit below what will be printed to ensure
++ * an arithmetical round up and carry it through to size */
++ remainder += rounding[j];
++ if (remainder >= 1000) {
++ remainder -= 1000;
++ size += 1;
++ }
++
++ if (j) {
+ snprintf(tmp, sizeof(tmp), ".%03u", remainder);
+ tmp[j+1] = '\0';
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/lib/ucs2_string.c linux-libre-4.4.7-gnu/lib/ucs2_string.c
+--- linux-libre-4.4-gnu/lib/ucs2_string.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/lib/ucs2_string.c 2016-04-12 12:09:26.000000000 -0400
+@@ -49,3 +49,65 @@ ucs2_strncmp(const ucs2_char_t *a, const
+ }
+ }
+ EXPORT_SYMBOL(ucs2_strncmp);
++
++unsigned long
++ucs2_utf8size(const ucs2_char_t *src)
++{
++ unsigned long i;
++ unsigned long j = 0;
++
++ for (i = 0; i < ucs2_strlen(src); i++) {
++ u16 c = src[i];
++
++ if (c >= 0x800)
++ j += 3;
++ else if (c >= 0x80)
++ j += 2;
++ else
++ j += 1;
++ }
++
++ return j;
++}
++EXPORT_SYMBOL(ucs2_utf8size);
++
++/*
++ * copy at most maxlength bytes of whole utf8 characters to dest from the
++ * ucs2 string src.
++ *
++ * The return value is the number of characters copied, not including the
++ * final NUL character.
++ */
++unsigned long
++ucs2_as_utf8(u8 *dest, const ucs2_char_t *src, unsigned long maxlength)
++{
++ unsigned int i;
++ unsigned long j = 0;
++ unsigned long limit = ucs2_strnlen(src, maxlength);
++
++ for (i = 0; maxlength && i < limit; i++) {
++ u16 c = src[i];
++
++ if (c >= 0x800) {
++ if (maxlength < 3)
++ break;
++ maxlength -= 3;
++ dest[j++] = 0xe0 | (c & 0xf000) >> 12;
++ dest[j++] = 0x80 | (c & 0x0fc0) >> 6;
++ dest[j++] = 0x80 | (c & 0x003f);
++ } else if (c >= 0x80) {
++ if (maxlength < 2)
++ break;
++ maxlength -= 2;
++ dest[j++] = 0xc0 | (c & 0x7c0) >> 6;
++ dest[j++] = 0x80 | (c & 0x03f);
++ } else {
++ maxlength -= 1;
++ dest[j++] = c & 0x7f;
++ }
++ }
++ if (maxlength)
++ dest[j] = '\0';
++ return j;
++}
++EXPORT_SYMBOL(ucs2_as_utf8);
+diff -druNp --no-dereference linux-libre-4.4-gnu/MAINTAINERS linux-libre-4.4.7-gnu/MAINTAINERS
+--- linux-libre-4.4-gnu/MAINTAINERS 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/MAINTAINERS 2016-04-12 12:09:26.000000000 -0400
+@@ -230,13 +230,13 @@ F: kernel/sys_ni.c
+
+ ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
+ M: Hans de Goede <hdegoede@redhat.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/abituguru.c
+
+ ABIT UGURU 3 HARDWARE MONITOR DRIVER
+ M: Alistair John Strachan <alistair@devzero.co.uk>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/abituguru3.c
+
+@@ -373,14 +373,14 @@ S: Maintained
+
+ ADM1025 HARDWARE MONITOR DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/adm1025
+ F: drivers/hwmon/adm1025.c
+
+ ADM1029 HARDWARE MONITOR DRIVER
+ M: Corentin Labbe <clabbe.montjoie@gmail.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/adm1029.c
+
+@@ -425,7 +425,7 @@ F: drivers/video/backlight/adp8860_bl.c
+
+ ADS1015 HARDWARE MONITOR DRIVER
+ M: Dirk Eibach <eibach@gdsys.de>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/ads1015
+ F: drivers/hwmon/ads1015.c
+@@ -438,7 +438,7 @@ F: drivers/macintosh/therm_adt746x.c
+
+ ADT7475 HARDWARE MONITOR DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/adt7475
+ F: drivers/hwmon/adt7475.c
+@@ -615,7 +615,7 @@ F: include/linux/ccp.h
+
+ AMD FAM15H PROCESSOR POWER MONITORING DRIVER
+ M: Andreas Herrmann <herrmann.der.user@googlemail.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/fam15h_power
+ F: drivers/hwmon/fam15h_power.c
+@@ -779,7 +779,7 @@ F: drivers/input/mouse/bcm5974.c
+
+ APPLE SMC DRIVER
+ M: Henrik Rydberg <rydberg@bitmath.org>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Odd fixes
+ F: drivers/hwmon/applesmc.c
+
+@@ -1777,7 +1777,7 @@ F: include/media/as3645a.h
+
+ ASC7621 HARDWARE MONITOR DRIVER
+ M: George Joseph <george.joseph@fairview5.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/asc7621
+ F: drivers/hwmon/asc7621.c
+@@ -1864,7 +1864,7 @@ F: drivers/net/wireless/ath/carl9170/
+
+ ATK0110 HWMON DRIVER
+ M: Luca Tettamanti <kronos.it@gmail.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/asus_atk0110.c
+
+@@ -2984,7 +2984,7 @@ F: mm/swap_cgroup.c
+
+ CORETEMP HARDWARE MONITORING DRIVER
+ M: Fenghua Yu <fenghua.yu@intel.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/coretemp
+ F: drivers/hwmon/coretemp.c
+@@ -3549,7 +3549,7 @@ T: git git://git.infradead.org/users/vko
+
+ DME1737 HARDWARE MONITOR DRIVER
+ M: Juerg Haefliger <juergh@gmail.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/dme1737
+ F: drivers/hwmon/dme1737.c
+@@ -4262,7 +4262,7 @@ F: include/video/exynos_mipi*
+
+ F71805F HARDWARE MONITORING DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/f71805f
+ F: drivers/hwmon/f71805f.c
+@@ -4341,7 +4341,7 @@ F: fs/*
+
+ FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
+ M: Riku Voipio <riku.voipio@iki.fi>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/f75375s.c
+ F: include/linux/f75375s.h
+@@ -4883,8 +4883,8 @@ F: drivers/media/usb/hackrf/
+ HARDWARE MONITORING
+ M: Jean Delvare <jdelvare@suse.com>
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
+-W: http://www.lm-sensors.org/
++L: linux-hwmon@vger.kernel.org
++W: http://hwmon.wiki.kernel.org/
+ T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
+ S: Maintained
+@@ -5393,7 +5393,7 @@ F: drivers/usb/atm/ueagle-atm.c
+
+ INA209 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/ina209
+ F: Documentation/devicetree/bindings/i2c/ina209.txt
+@@ -5401,7 +5401,7 @@ F: drivers/hwmon/ina209.c
+
+ INA2XX HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/ina2xx
+ F: drivers/hwmon/ina2xx.c
+@@ -5884,7 +5884,7 @@ F: drivers/isdn/hardware/eicon/
+
+ IT87 HARDWARE MONITORING DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/it87
+ F: drivers/hwmon/it87.c
+@@ -5920,7 +5920,7 @@ F: drivers/media/dvb-frontends/ix2505v*
+
+ JC42.4 TEMPERATURE SENSOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/jc42.c
+ F: Documentation/hwmon/jc42
+@@ -5970,14 +5970,14 @@ F: drivers/tty/serial/jsm/
+
+ K10TEMP HARDWARE MONITORING DRIVER
+ M: Clemens Ladisch <clemens@ladisch.de>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/k10temp
+ F: drivers/hwmon/k10temp.c
+
+ K8TEMP HARDWARE MONITORING DRIVER
+ M: Rudolf Marek <r.marek@assembler.cz>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/k8temp
+ F: drivers/hwmon/k8temp.c
+@@ -6485,27 +6485,27 @@ F: net/llc/
+
+ LM73 HARDWARE MONITOR DRIVER
+ M: Guillaume Ligneul <guillaume.ligneul@gmail.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/lm73.c
+
+ LM78 HARDWARE MONITOR DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/lm78
+ F: drivers/hwmon/lm78.c
+
+ LM83 HARDWARE MONITOR DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/lm83
+ F: drivers/hwmon/lm83.c
+
+ LM90 HARDWARE MONITOR DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/lm90
+ F: Documentation/devicetree/bindings/hwmon/lm90.txt
+@@ -6513,7 +6513,7 @@ F: drivers/hwmon/lm90.c
+
+ LM95234 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/lm95234
+ F: drivers/hwmon/lm95234.c
+@@ -6580,7 +6580,7 @@ F: drivers/scsi/sym53c8xx_2/
+
+ LTC4261 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/ltc4261
+ F: drivers/hwmon/ltc4261.c
+@@ -6749,28 +6749,28 @@ F: include/uapi/linux/matroxfb.h
+
+ MAX16065 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/max16065
+ F: drivers/hwmon/max16065.c
+
+ MAX20751 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/max20751
+ F: drivers/hwmon/max20751.c
+
+ MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
+ M: "Hans J. Koch" <hjk@hansjkoch.de>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/max6650
+ F: drivers/hwmon/max6650.c
+
+ MAX6697 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/max6697
+ F: Documentation/devicetree/bindings/i2c/max6697.txt
+@@ -7303,7 +7303,7 @@ F: drivers/scsi/NCR_D700.*
+
+ NCT6775 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/nct6775
+ F: drivers/hwmon/nct6775.c
+@@ -8064,7 +8064,7 @@ F: drivers/video/logo/logo_parisc*
+
+ PC87360 HARDWARE MONITORING DRIVER
+ M: Jim Cromie <jim.cromie@gmail.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/pc87360
+ F: drivers/hwmon/pc87360.c
+@@ -8076,7 +8076,7 @@ F: drivers/char/pc8736x_gpio.c
+
+ PC87427 HARDWARE MONITORING DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/pc87427
+ F: drivers/hwmon/pc87427.c
+@@ -8415,8 +8415,8 @@ F: drivers/rtc/rtc-puv3.c
+
+ PMBUS HARDWARE MONITORING DRIVERS
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
+-W: http://www.lm-sensors.org/
++L: linux-hwmon@vger.kernel.org
++W: http://hwmon.wiki.kernel.org/
+ W: http://www.roeck-us.net/linux/drivers/
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
+ S: Maintained
+@@ -8610,7 +8610,7 @@ F: drivers/media/usb/pwc/*
+
+ PWM FAN DRIVER
+ M: Kamil Debski <k.debski@samsung.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Supported
+ F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
+ F: Documentation/hwmon/pwm-fan
+@@ -9882,28 +9882,28 @@ F: Documentation/devicetree/bindings/med
+
+ SMM665 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/smm665
+ F: drivers/hwmon/smm665.c
+
+ SMSC EMC2103 HARDWARE MONITOR DRIVER
+ M: Steve Glendinning <steve.glendinning@shawell.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/emc2103
+ F: drivers/hwmon/emc2103.c
+
+ SMSC SCH5627 HARDWARE MONITOR DRIVER
+ M: Hans de Goede <hdegoede@redhat.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Supported
+ F: Documentation/hwmon/sch5627
+ F: drivers/hwmon/sch5627.c
+
+ SMSC47B397 HARDWARE MONITOR DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/smsc47b397
+ F: drivers/hwmon/smsc47b397.c
+@@ -10289,9 +10289,11 @@ S: Maintained
+ F: drivers/net/ethernet/dlink/sundance.c
+
+ SUPERH
++M: Yoshinori Sato <ysato@users.sourceforge.jp>
++M: Rich Felker <dalias@libc.org>
+ L: linux-sh@vger.kernel.org
+ Q: http://patchwork.kernel.org/project/linux-sh/list/
+-S: Orphan
++S: Maintained
+ F: Documentation/sh/
+ F: arch/sh/
+ F: drivers/sh/
+@@ -10828,7 +10830,7 @@ F: include/linux/mmc/sh_mobile_sdhi.h
+
+ TMP401 HARDWARE MONITOR DRIVER
+ M: Guenter Roeck <linux@roeck-us.net>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/tmp401
+ F: drivers/hwmon/tmp401.c
+@@ -11562,14 +11564,14 @@ F: Documentation/networking/vrf.txt
+
+ VT1211 HARDWARE MONITOR DRIVER
+ M: Juerg Haefliger <juergh@gmail.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/vt1211
+ F: drivers/hwmon/vt1211.c
+
+ VT8231 HARDWARE MONITOR DRIVER
+ M: Roger Lucas <vt8231@hiddenengine.co.uk>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/vt8231.c
+
+@@ -11588,21 +11590,21 @@ F: drivers/w1/
+
+ W83791D HARDWARE MONITORING DRIVER
+ M: Marc Hulsman <m.hulsman@tudelft.nl>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/w83791d
+ F: drivers/hwmon/w83791d.c
+
+ W83793 HARDWARE MONITORING DRIVER
+ M: Rudolf Marek <r.marek@assembler.cz>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: Documentation/hwmon/w83793
+ F: drivers/hwmon/w83793.c
+
+ W83795 HARDWARE MONITORING DRIVER
+ M: Jean Delvare <jdelvare@suse.com>
+-L: lm-sensors@lm-sensors.org
++L: linux-hwmon@vger.kernel.org
+ S: Maintained
+ F: drivers/hwmon/w83795.c
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/Makefile linux-libre-4.4.7-gnu/Makefile
+--- linux-libre-4.4-gnu/Makefile 2016-01-10 20:54:53.000000000 -0500
++++ linux-libre-4.4.7-gnu/Makefile 2016-04-12 21:10:38.000000000 -0400
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 4
+-SUBLEVEL = 0
++SUBLEVEL = 7
+ EXTRAVERSION = -gnu
+ NAME = Blurry Fish Butt
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/backing-dev.c linux-libre-4.4.7-gnu/mm/backing-dev.c
+--- linux-libre-4.4-gnu/mm/backing-dev.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/backing-dev.c 2016-04-12 12:09:26.000000000 -0400
+@@ -989,7 +989,7 @@ long wait_iff_congested(struct zone *zon
+ * here rather than calling cond_resched().
+ */
+ if (current->flags & PF_WQ_WORKER)
+- schedule_timeout(1);
++ schedule_timeout_uninterruptible(1);
+ else
+ cond_resched();
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/balloon_compaction.c linux-libre-4.4.7-gnu/mm/balloon_compaction.c
+--- linux-libre-4.4-gnu/mm/balloon_compaction.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/balloon_compaction.c 2016-04-12 12:09:26.000000000 -0400
+@@ -61,6 +61,7 @@ struct page *balloon_page_dequeue(struct
+ bool dequeued_page;
+
+ dequeued_page = false;
++ spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+ list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
+ /*
+ * Block others from accessing the 'page' while we get around
+@@ -75,15 +76,14 @@ struct page *balloon_page_dequeue(struct
+ continue;
+ }
+ #endif
+- spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+ balloon_page_delete(page);
+ __count_vm_event(BALLOON_DEFLATE);
+- spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+ unlock_page(page);
+ dequeued_page = true;
+ break;
+ }
+ }
++ spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+
+ if (!dequeued_page) {
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/memcontrol.c linux-libre-4.4.7-gnu/mm/memcontrol.c
+--- linux-libre-4.4-gnu/mm/memcontrol.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/memcontrol.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1332,7 +1332,7 @@ static unsigned long mem_cgroup_get_limi
+ return limit;
+ }
+
+-static void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
++static bool mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
+ int order)
+ {
+ struct oom_control oc = {
+@@ -1410,6 +1410,7 @@ static void mem_cgroup_out_of_memory(str
+ }
+ unlock:
+ mutex_unlock(&oom_lock);
++ return chosen;
+ }
+
+ #if MAX_NUMNODES > 1
+@@ -3522,16 +3523,17 @@ static void __mem_cgroup_usage_unregiste
+ swap_buffers:
+ /* Swap primary and spare array */
+ thresholds->spare = thresholds->primary;
+- /* If all events are unregistered, free the spare array */
+- if (!new) {
+- kfree(thresholds->spare);
+- thresholds->spare = NULL;
+- }
+
+ rcu_assign_pointer(thresholds->primary, new);
+
+ /* To be sure that nobody uses thresholds */
+ synchronize_rcu();
++
++ /* If all events are unregistered, free the spare array */
++ if (!new) {
++ kfree(thresholds->spare);
++ thresholds->spare = NULL;
++ }
+ unlock:
+ mutex_unlock(&memcg->thresholds_lock);
+ }
+@@ -5120,6 +5122,7 @@ static ssize_t memory_high_write(struct
+ char *buf, size_t nbytes, loff_t off)
+ {
+ struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
++ unsigned long nr_pages;
+ unsigned long high;
+ int err;
+
+@@ -5130,6 +5133,11 @@ static ssize_t memory_high_write(struct
+
+ memcg->high = high;
+
++ nr_pages = page_counter_read(&memcg->memory);
++ if (nr_pages > high)
++ try_to_free_mem_cgroup_pages(memcg, nr_pages - high,
++ GFP_KERNEL, true);
++
+ memcg_wb_domain_size_changed(memcg);
+ return nbytes;
+ }
+@@ -5151,6 +5159,8 @@ static ssize_t memory_max_write(struct k
+ char *buf, size_t nbytes, loff_t off)
+ {
+ struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
++ unsigned int nr_reclaims = MEM_CGROUP_RECLAIM_RETRIES;
++ bool drained = false;
+ unsigned long max;
+ int err;
+
+@@ -5159,9 +5169,36 @@ static ssize_t memory_max_write(struct k
+ if (err)
+ return err;
+
+- err = mem_cgroup_resize_limit(memcg, max);
+- if (err)
+- return err;
++ xchg(&memcg->memory.limit, max);
++
++ for (;;) {
++ unsigned long nr_pages = page_counter_read(&memcg->memory);
++
++ if (nr_pages <= max)
++ break;
++
++ if (signal_pending(current)) {
++ err = -EINTR;
++ break;
++ }
++
++ if (!drained) {
++ drain_all_stock(memcg);
++ drained = true;
++ continue;
++ }
++
++ if (nr_reclaims) {
++ if (!try_to_free_mem_cgroup_pages(memcg, nr_pages - max,
++ GFP_KERNEL, true))
++ nr_reclaims--;
++ continue;
++ }
++
++ mem_cgroup_events(memcg, MEMCG_OOM, 1);
++ if (!mem_cgroup_out_of_memory(memcg, GFP_KERNEL, 0))
++ break;
++ }
+
+ memcg_wb_domain_size_changed(memcg);
+ return nbytes;
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/memory.c linux-libre-4.4.7-gnu/mm/memory.c
+--- linux-libre-4.4-gnu/mm/memory.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/memory.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3399,8 +3399,18 @@ static int __handle_mm_fault(struct mm_s
+ if (unlikely(pmd_none(*pmd)) &&
+ unlikely(__pte_alloc(mm, vma, pmd, address)))
+ return VM_FAULT_OOM;
+- /* if an huge pmd materialized from under us just retry later */
+- if (unlikely(pmd_trans_huge(*pmd)))
++ /*
++ * If a huge pmd materialized under us just retry later. Use
++ * pmd_trans_unstable() instead of pmd_trans_huge() to ensure the pmd
++ * didn't become pmd_trans_huge under us and then back to pmd_none, as
++ * a result of MADV_DONTNEED running immediately after a huge pmd fault
++ * in a different thread of this mm, in turn leading to a misleading
++ * pmd_trans_huge() retval. All we have to ensure is that it is a
++ * regular pmd that we can walk with pte_offset_map() and we can do that
++ * through an atomic read in C, which is what pmd_trans_unstable()
++ * provides.
++ */
++ if (unlikely(pmd_trans_unstable(pmd)))
+ return 0;
+ /*
+ * A regular pmd is established and it can't morph into a huge pmd
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/memory-failure.c linux-libre-4.4.7-gnu/mm/memory-failure.c
+--- linux-libre-4.4-gnu/mm/memory-failure.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/memory-failure.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1572,7 +1572,7 @@ static int get_any_page(struct page *pag
+ * Did it turn free?
+ */
+ ret = __get_any_page(page, pfn, 0);
+- if (!PageLRU(page)) {
++ if (ret == 1 && !PageLRU(page)) {
+ /* Drop page reference which is from __get_any_page() */
+ put_hwpoison_page(page);
+ pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n",
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/migrate.c linux-libre-4.4.7-gnu/mm/migrate.c
+--- linux-libre-4.4-gnu/mm/migrate.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/migrate.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1578,7 +1578,7 @@ static struct page *alloc_misplaced_dst_
+ (GFP_HIGHUSER_MOVABLE |
+ __GFP_THISNODE | __GFP_NOMEMALLOC |
+ __GFP_NORETRY | __GFP_NOWARN) &
+- ~(__GFP_IO | __GFP_FS), 0);
++ ~__GFP_RECLAIM, 0);
+
+ return newpage;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/mlock.c linux-libre-4.4.7-gnu/mm/mlock.c
+--- linux-libre-4.4-gnu/mm/mlock.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/mlock.c 2016-04-12 12:09:26.000000000 -0400
+@@ -172,7 +172,7 @@ static void __munlock_isolation_failed(s
+ */
+ unsigned int munlock_vma_page(struct page *page)
+ {
+- unsigned int nr_pages;
++ int nr_pages;
+ struct zone *zone = page_zone(page);
+
+ /* For try_to_munlock() and to serialize with page migration */
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/mmap.c linux-libre-4.4.7-gnu/mm/mmap.c
+--- linux-libre-4.4-gnu/mm/mmap.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/mmap.c 2016-04-12 12:09:26.000000000 -0400
+@@ -441,12 +441,16 @@ static void validate_mm(struct mm_struct
+ struct vm_area_struct *vma = mm->mmap;
+
+ while (vma) {
++ struct anon_vma *anon_vma = vma->anon_vma;
+ struct anon_vma_chain *avc;
+
+- vma_lock_anon_vma(vma);
+- list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+- anon_vma_interval_tree_verify(avc);
+- vma_unlock_anon_vma(vma);
++ if (anon_vma) {
++ anon_vma_lock_read(anon_vma);
++ list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
++ anon_vma_interval_tree_verify(avc);
++ anon_vma_unlock_read(anon_vma);
++ }
++
+ highest_address = vma->vm_end;
+ vma = vma->vm_next;
+ i++;
+@@ -2147,32 +2151,27 @@ static int acct_stack_growth(struct vm_a
+ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
+ {
+ struct mm_struct *mm = vma->vm_mm;
+- int error;
++ int error = 0;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+
+- /*
+- * We must make sure the anon_vma is allocated
+- * so that the anon_vma locking is not a noop.
+- */
++ /* Guard against wrapping around to address 0. */
++ if (address < PAGE_ALIGN(address+4))
++ address = PAGE_ALIGN(address+4);
++ else
++ return -ENOMEM;
++
++ /* We must make sure the anon_vma is allocated. */
+ if (unlikely(anon_vma_prepare(vma)))
+ return -ENOMEM;
+- vma_lock_anon_vma(vma);
+
+ /*
+ * vma->vm_start/vm_end cannot change under us because the caller
+ * is required to hold the mmap_sem in read mode. We need the
+ * anon_vma lock to serialize against concurrent expand_stacks.
+- * Also guard against wrapping around to address 0.
+ */
+- if (address < PAGE_ALIGN(address+4))
+- address = PAGE_ALIGN(address+4);
+- else {
+- vma_unlock_anon_vma(vma);
+- return -ENOMEM;
+- }
+- error = 0;
++ anon_vma_lock_write(vma->anon_vma);
+
+ /* Somebody else might have raced and expanded it already */
+ if (address > vma->vm_end) {
+@@ -2190,7 +2189,7 @@ int expand_upwards(struct vm_area_struct
+ * updates, but we only hold a shared mmap_sem
+ * lock here, so we need to protect against
+ * concurrent vma expansions.
+- * vma_lock_anon_vma() doesn't help here, as
++ * anon_vma_lock_write() doesn't help here, as
+ * we don't guarantee that all growable vmas
+ * in a mm share the same root anon vma.
+ * So, we reuse mm->page_table_lock to guard
+@@ -2214,7 +2213,7 @@ int expand_upwards(struct vm_area_struct
+ }
+ }
+ }
+- vma_unlock_anon_vma(vma);
++ anon_vma_unlock_write(vma->anon_vma);
+ khugepaged_enter_vma_merge(vma, vma->vm_flags);
+ validate_mm(mm);
+ return error;
+@@ -2230,25 +2229,21 @@ int expand_downwards(struct vm_area_stru
+ struct mm_struct *mm = vma->vm_mm;
+ int error;
+
+- /*
+- * We must make sure the anon_vma is allocated
+- * so that the anon_vma locking is not a noop.
+- */
+- if (unlikely(anon_vma_prepare(vma)))
+- return -ENOMEM;
+-
+ address &= PAGE_MASK;
+ error = security_mmap_addr(address);
+ if (error)
+ return error;
+
+- vma_lock_anon_vma(vma);
++ /* We must make sure the anon_vma is allocated. */
++ if (unlikely(anon_vma_prepare(vma)))
++ return -ENOMEM;
+
+ /*
+ * vma->vm_start/vm_end cannot change under us because the caller
+ * is required to hold the mmap_sem in read mode. We need the
+ * anon_vma lock to serialize against concurrent expand_stacks.
+ */
++ anon_vma_lock_write(vma->anon_vma);
+
+ /* Somebody else might have raced and expanded it already */
+ if (address < vma->vm_start) {
+@@ -2266,7 +2261,7 @@ int expand_downwards(struct vm_area_stru
+ * updates, but we only hold a shared mmap_sem
+ * lock here, so we need to protect against
+ * concurrent vma expansions.
+- * vma_lock_anon_vma() doesn't help here, as
++ * anon_vma_lock_write() doesn't help here, as
+ * we don't guarantee that all growable vmas
+ * in a mm share the same root anon vma.
+ * So, we reuse mm->page_table_lock to guard
+@@ -2288,7 +2283,7 @@ int expand_downwards(struct vm_area_stru
+ }
+ }
+ }
+- vma_unlock_anon_vma(vma);
++ anon_vma_unlock_write(vma->anon_vma);
+ khugepaged_enter_vma_merge(vma, vma->vm_flags);
+ validate_mm(mm);
+ return error;
+@@ -2673,12 +2668,29 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
+ if (!vma || !(vma->vm_flags & VM_SHARED))
+ goto out;
+
+- if (start < vma->vm_start || start + size > vma->vm_end)
++ if (start < vma->vm_start)
+ goto out;
+
+- if (pgoff == linear_page_index(vma, start)) {
+- ret = 0;
+- goto out;
++ if (start + size > vma->vm_end) {
++ struct vm_area_struct *next;
++
++ for (next = vma->vm_next; next; next = next->vm_next) {
++ /* hole between vmas ? */
++ if (next->vm_start != next->vm_prev->vm_end)
++ goto out;
++
++ if (next->vm_file != vma->vm_file)
++ goto out;
++
++ if (next->vm_flags != vma->vm_flags)
++ goto out;
++
++ if (start + size <= next->vm_end)
++ break;
++ }
++
++ if (!next)
++ goto out;
+ }
+
+ prot |= vma->vm_flags & VM_READ ? PROT_READ : 0;
+@@ -2688,9 +2700,16 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
+ flags &= MAP_NONBLOCK;
+ flags |= MAP_SHARED | MAP_FIXED | MAP_POPULATE;
+ if (vma->vm_flags & VM_LOCKED) {
++ struct vm_area_struct *tmp;
+ flags |= MAP_LOCKED;
++
+ /* drop PG_Mlocked flag for over-mapped range */
+- munlock_vma_pages_range(vma, start, start + size);
++ for (tmp = vma; tmp->vm_start >= start + size;
++ tmp = tmp->vm_next) {
++ munlock_vma_pages_range(tmp,
++ max(tmp->vm_start, start),
++ min(tmp->vm_end, start + size));
++ }
+ }
+
+ file = get_file(vma->vm_file);
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/page_alloc.c linux-libre-4.4.7-gnu/mm/page_alloc.c
+--- linux-libre-4.4-gnu/mm/page_alloc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/page_alloc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -662,34 +662,28 @@ static inline void __free_one_page(struc
+ unsigned long combined_idx;
+ unsigned long uninitialized_var(buddy_idx);
+ struct page *buddy;
+- unsigned int max_order = MAX_ORDER;
++ unsigned int max_order;
++
++ max_order = min_t(unsigned int, MAX_ORDER, pageblock_order + 1);
+
+ VM_BUG_ON(!zone_is_initialized(zone));
+ VM_BUG_ON_PAGE(page->flags & PAGE_FLAGS_CHECK_AT_PREP, page);
+
+ VM_BUG_ON(migratetype == -1);
+- if (is_migrate_isolate(migratetype)) {
+- /*
+- * We restrict max order of merging to prevent merge
+- * between freepages on isolate pageblock and normal
+- * pageblock. Without this, pageblock isolation
+- * could cause incorrect freepage accounting.
+- */
+- max_order = min_t(unsigned int, MAX_ORDER, pageblock_order + 1);
+- } else {
++ if (likely(!is_migrate_isolate(migratetype)))
+ __mod_zone_freepage_state(zone, 1 << order, migratetype);
+- }
+
+- page_idx = pfn & ((1 << max_order) - 1);
++ page_idx = pfn & ((1 << MAX_ORDER) - 1);
+
+ VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page);
+ VM_BUG_ON_PAGE(bad_range(zone, page), page);
+
++continue_merging:
+ while (order < max_order - 1) {
+ buddy_idx = __find_buddy_index(page_idx, order);
+ buddy = page + (buddy_idx - page_idx);
+ if (!page_is_buddy(page, buddy, order))
+- break;
++ goto done_merging;
+ /*
+ * Our buddy is free or it is CONFIG_DEBUG_PAGEALLOC guard page,
+ * merge with it and move up one order.
+@@ -706,6 +700,32 @@ static inline void __free_one_page(struc
+ page_idx = combined_idx;
+ order++;
+ }
++ if (max_order < MAX_ORDER) {
++ /* If we are here, it means order is >= pageblock_order.
++ * We want to prevent merge between freepages on isolate
++ * pageblock and normal pageblock. Without this, pageblock
++ * isolation could cause incorrect freepage or CMA accounting.
++ *
++ * We don't want to hit this code for the more frequent
++ * low-order merging.
++ */
++ if (unlikely(has_isolate_pageblock(zone))) {
++ int buddy_mt;
++
++ buddy_idx = __find_buddy_index(page_idx, order);
++ buddy = page + (buddy_idx - page_idx);
++ buddy_mt = get_pageblock_migratetype(buddy);
++
++ if (migratetype != buddy_mt
++ && (is_migrate_isolate(migratetype) ||
++ is_migrate_isolate(buddy_mt)))
++ goto done_merging;
++ }
++ max_order++;
++ goto continue_merging;
++ }
++
++done_merging:
+ set_page_order(page, order);
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/pgtable-generic.c linux-libre-4.4.7-gnu/mm/pgtable-generic.c
+--- linux-libre-4.4-gnu/mm/pgtable-generic.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/pgtable-generic.c 2016-04-12 12:09:26.000000000 -0400
+@@ -210,7 +210,9 @@ pmd_t pmdp_collapse_flush(struct vm_area
+ VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+ VM_BUG_ON(pmd_trans_huge(*pmdp));
+ pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
+- flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
++
++ /* collapse entails shooting down ptes not pmd */
++ flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+ return pmd;
+ }
+ #endif
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/process_vm_access.c linux-libre-4.4.7-gnu/mm/process_vm_access.c
+--- linux-libre-4.4-gnu/mm/process_vm_access.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/process_vm_access.c 2016-04-12 12:09:26.000000000 -0400
+@@ -194,7 +194,7 @@ static ssize_t process_vm_rw_core(pid_t
+ goto free_proc_pages;
+ }
+
+- mm = mm_access(task, PTRACE_MODE_ATTACH);
++ mm = mm_access(task, PTRACE_MODE_ATTACH_REALCREDS);
+ if (!mm || IS_ERR(mm)) {
+ rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/shmem.c linux-libre-4.4.7-gnu/mm/shmem.c
+--- linux-libre-4.4-gnu/mm/shmem.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/shmem.c 2016-04-12 12:09:26.000000000 -0400
+@@ -620,8 +620,7 @@ static void shmem_evict_inode(struct ino
+ list_del_init(&info->swaplist);
+ mutex_unlock(&shmem_swaplist_mutex);
+ }
+- } else
+- kfree(info->symlink);
++ }
+
+ simple_xattrs_free(&info->xattrs);
+ WARN_ON(inode->i_blocks);
+@@ -2462,13 +2461,12 @@ static int shmem_symlink(struct inode *d
+ info = SHMEM_I(inode);
+ inode->i_size = len-1;
+ if (len <= SHORT_SYMLINK_LEN) {
+- info->symlink = kmemdup(symname, len, GFP_KERNEL);
+- if (!info->symlink) {
++ inode->i_link = kmemdup(symname, len, GFP_KERNEL);
++ if (!inode->i_link) {
+ iput(inode);
+ return -ENOMEM;
+ }
+ inode->i_op = &shmem_short_symlink_operations;
+- inode->i_link = info->symlink;
+ } else {
+ error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
+ if (error) {
+@@ -3083,6 +3081,7 @@ static struct inode *shmem_alloc_inode(s
+ static void shmem_destroy_callback(struct rcu_head *head)
+ {
+ struct inode *inode = container_of(head, struct inode, i_rcu);
++ kfree(inode->i_link);
+ kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/mm/zsmalloc.c linux-libre-4.4.7-gnu/mm/zsmalloc.c
+--- linux-libre-4.4-gnu/mm/zsmalloc.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/mm/zsmalloc.c 2016-04-12 12:09:26.000000000 -0400
+@@ -309,7 +309,12 @@ static void free_handle(struct zs_pool *
+
+ static void record_obj(unsigned long handle, unsigned long obj)
+ {
+- *(unsigned long *)handle = obj;
++ /*
++ * lsb of @obj represents handle lock while other bits
++ * represent object value the handle is pointing so
++ * updating shouldn't do store tearing.
++ */
++ WRITE_ONCE(*(unsigned long *)handle, obj);
+ }
+
+ /* zpool driver */
+@@ -1635,6 +1640,13 @@ static int migrate_zspage(struct zs_pool
+ free_obj = obj_malloc(d_page, class, handle);
+ zs_object_copy(free_obj, used_obj, class);
+ index++;
++ /*
++ * record_obj updates handle's value to free_obj and it will
++ * invalidate lock bit(ie, HANDLE_PIN_BIT) of handle, which
++ * breaks synchronization using pin_tag(e,g, zs_free) so
++ * let's keep the lock bit.
++ */
++ free_obj |= BIT(HANDLE_PIN_BIT);
+ record_obj(handle, free_obj);
+ unpin_tag(handle);
+ obj_free(pool, class, used_obj);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/batman-adv/bridge_loop_avoidance.c linux-libre-4.4.7-gnu/net/batman-adv/bridge_loop_avoidance.c
+--- linux-libre-4.4-gnu/net/batman-adv/bridge_loop_avoidance.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/batman-adv/bridge_loop_avoidance.c 2016-04-12 12:09:26.000000000 -0400
+@@ -127,21 +127,17 @@ batadv_backbone_gw_free_ref(struct batad
+ }
+
+ /* finally deinitialize the claim */
+-static void batadv_claim_free_rcu(struct rcu_head *rcu)
++static void batadv_claim_release(struct batadv_bla_claim *claim)
+ {
+- struct batadv_bla_claim *claim;
+-
+- claim = container_of(rcu, struct batadv_bla_claim, rcu);
+-
+ batadv_backbone_gw_free_ref(claim->backbone_gw);
+- kfree(claim);
++ kfree_rcu(claim, rcu);
+ }
+
+ /* free a claim, call claim_free_rcu if its the last reference */
+ static void batadv_claim_free_ref(struct batadv_bla_claim *claim)
+ {
+ if (atomic_dec_and_test(&claim->refcount))
+- call_rcu(&claim->rcu, batadv_claim_free_rcu);
++ batadv_claim_release(claim);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/batman-adv/hard-interface.h linux-libre-4.4.7-gnu/net/batman-adv/hard-interface.h
+--- linux-libre-4.4-gnu/net/batman-adv/hard-interface.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/batman-adv/hard-interface.h 2016-04-12 12:09:26.000000000 -0400
+@@ -75,18 +75,6 @@ batadv_hardif_free_ref(struct batadv_har
+ call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu);
+ }
+
+-/**
+- * batadv_hardif_free_ref_now - decrement the hard interface refcounter and
+- * possibly free it (without rcu callback)
+- * @hard_iface: the hard interface to free
+- */
+-static inline void
+-batadv_hardif_free_ref_now(struct batadv_hard_iface *hard_iface)
+-{
+- if (atomic_dec_and_test(&hard_iface->refcount))
+- batadv_hardif_free_rcu(&hard_iface->rcu);
+-}
+-
+ static inline struct batadv_hard_iface *
+ batadv_primary_if_get_selected(struct batadv_priv *bat_priv)
+ {
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/batman-adv/network-coding.c linux-libre-4.4.7-gnu/net/batman-adv/network-coding.c
+--- linux-libre-4.4-gnu/net/batman-adv/network-coding.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/batman-adv/network-coding.c 2016-04-12 12:09:26.000000000 -0400
+@@ -203,28 +203,25 @@ void batadv_nc_init_orig(struct batadv_o
+ }
+
+ /**
+- * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove
+- * its refcount on the orig_node
+- * @rcu: rcu pointer of the nc node
++ * batadv_nc_node_release - release nc_node from lists and queue for free after
++ * rcu grace period
++ * @nc_node: the nc node to free
+ */
+-static void batadv_nc_node_free_rcu(struct rcu_head *rcu)
++static void batadv_nc_node_release(struct batadv_nc_node *nc_node)
+ {
+- struct batadv_nc_node *nc_node;
+-
+- nc_node = container_of(rcu, struct batadv_nc_node, rcu);
+ batadv_orig_node_free_ref(nc_node->orig_node);
+- kfree(nc_node);
++ kfree_rcu(nc_node, rcu);
+ }
+
+ /**
+- * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly
+- * frees it
++ * batadv_nc_node_free_ref - decrement the nc node refcounter and possibly
++ * release it
+ * @nc_node: the nc node to free
+ */
+ static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node)
+ {
+ if (atomic_dec_and_test(&nc_node->refcount))
+- call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu);
++ batadv_nc_node_release(nc_node);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/batman-adv/originator.c linux-libre-4.4.7-gnu/net/batman-adv/originator.c
+--- linux-libre-4.4-gnu/net/batman-adv/originator.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/batman-adv/originator.c 2016-04-12 12:09:26.000000000 -0400
+@@ -163,92 +163,66 @@ err:
+ }
+
+ /**
+- * batadv_neigh_ifinfo_free_rcu - free the neigh_ifinfo object
+- * @rcu: rcu pointer of the neigh_ifinfo object
+- */
+-static void batadv_neigh_ifinfo_free_rcu(struct rcu_head *rcu)
+-{
+- struct batadv_neigh_ifinfo *neigh_ifinfo;
+-
+- neigh_ifinfo = container_of(rcu, struct batadv_neigh_ifinfo, rcu);
+-
+- if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
+- batadv_hardif_free_ref_now(neigh_ifinfo->if_outgoing);
+-
+- kfree(neigh_ifinfo);
+-}
+-
+-/**
+- * batadv_neigh_ifinfo_free_now - decrement the refcounter and possibly free
+- * the neigh_ifinfo (without rcu callback)
++ * batadv_neigh_ifinfo_release - release neigh_ifinfo from lists and queue for
++ * free after rcu grace period
+ * @neigh_ifinfo: the neigh_ifinfo object to release
+ */
+ static void
+-batadv_neigh_ifinfo_free_ref_now(struct batadv_neigh_ifinfo *neigh_ifinfo)
++batadv_neigh_ifinfo_release(struct batadv_neigh_ifinfo *neigh_ifinfo)
+ {
+- if (atomic_dec_and_test(&neigh_ifinfo->refcount))
+- batadv_neigh_ifinfo_free_rcu(&neigh_ifinfo->rcu);
++ if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
++ batadv_hardif_free_ref(neigh_ifinfo->if_outgoing);
++
++ kfree_rcu(neigh_ifinfo, rcu);
+ }
+
+ /**
+- * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly free
++ * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly release
+ * the neigh_ifinfo
+ * @neigh_ifinfo: the neigh_ifinfo object to release
+ */
+ void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo)
+ {
+ if (atomic_dec_and_test(&neigh_ifinfo->refcount))
+- call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu);
++ batadv_neigh_ifinfo_release(neigh_ifinfo);
+ }
+
+ /**
+ * batadv_neigh_node_free_rcu - free the neigh_node
+- * @rcu: rcu pointer of the neigh_node
++ * batadv_neigh_node_release - release neigh_node from lists and queue for
++ * free after rcu grace period
++ * @neigh_node: neigh neighbor to free
+ */
+-static void batadv_neigh_node_free_rcu(struct rcu_head *rcu)
++static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node)
+ {
+ struct hlist_node *node_tmp;
+- struct batadv_neigh_node *neigh_node;
+ struct batadv_neigh_ifinfo *neigh_ifinfo;
+ struct batadv_algo_ops *bao;
+
+- neigh_node = container_of(rcu, struct batadv_neigh_node, rcu);
+ bao = neigh_node->orig_node->bat_priv->bat_algo_ops;
+
+ hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
+ &neigh_node->ifinfo_list, list) {
+- batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo);
++ batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
+ }
+
+ if (bao->bat_neigh_free)
+ bao->bat_neigh_free(neigh_node);
+
+- batadv_hardif_free_ref_now(neigh_node->if_incoming);
+-
+- kfree(neigh_node);
+-}
++ batadv_hardif_free_ref(neigh_node->if_incoming);
+
+-/**
+- * batadv_neigh_node_free_ref_now - decrement the neighbors refcounter
+- * and possibly free it (without rcu callback)
+- * @neigh_node: neigh neighbor to free
+- */
+-static void
+-batadv_neigh_node_free_ref_now(struct batadv_neigh_node *neigh_node)
+-{
+- if (atomic_dec_and_test(&neigh_node->refcount))
+- batadv_neigh_node_free_rcu(&neigh_node->rcu);
++ kfree_rcu(neigh_node, rcu);
+ }
+
+ /**
+ * batadv_neigh_node_free_ref - decrement the neighbors refcounter
+- * and possibly free it
++ * and possibly release it
+ * @neigh_node: neigh neighbor to free
+ */
+ void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node)
+ {
+ if (atomic_dec_and_test(&neigh_node->refcount))
+- call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu);
++ batadv_neigh_node_release(neigh_node);
+ }
+
+ /**
+@@ -532,108 +506,99 @@ out:
+ }
+
+ /**
+- * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object
+- * @rcu: rcu pointer of the orig_ifinfo object
++ * batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for
++ * free after rcu grace period
++ * @orig_ifinfo: the orig_ifinfo object to release
+ */
+-static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu)
++static void batadv_orig_ifinfo_release(struct batadv_orig_ifinfo *orig_ifinfo)
+ {
+- struct batadv_orig_ifinfo *orig_ifinfo;
+ struct batadv_neigh_node *router;
+
+- orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu);
+-
+ if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
+- batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing);
++ batadv_hardif_free_ref(orig_ifinfo->if_outgoing);
+
+ /* this is the last reference to this object */
+ router = rcu_dereference_protected(orig_ifinfo->router, true);
+ if (router)
+- batadv_neigh_node_free_ref_now(router);
+- kfree(orig_ifinfo);
++ batadv_neigh_node_free_ref(router);
++
++ kfree_rcu(orig_ifinfo, rcu);
+ }
+
+ /**
+- * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free
+- * the orig_ifinfo (without rcu callback)
++ * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly release
++ * the orig_ifinfo
+ * @orig_ifinfo: the orig_ifinfo object to release
+ */
+-static void
+-batadv_orig_ifinfo_free_ref_now(struct batadv_orig_ifinfo *orig_ifinfo)
++void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo)
+ {
+ if (atomic_dec_and_test(&orig_ifinfo->refcount))
+- batadv_orig_ifinfo_free_rcu(&orig_ifinfo->rcu);
++ batadv_orig_ifinfo_release(orig_ifinfo);
+ }
+
+ /**
+- * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free
+- * the orig_ifinfo
+- * @orig_ifinfo: the orig_ifinfo object to release
++ * batadv_orig_node_free_rcu - free the orig_node
++ * @rcu: rcu pointer of the orig_node
+ */
+-void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo)
++static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
+ {
+- if (atomic_dec_and_test(&orig_ifinfo->refcount))
+- call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu);
++ struct batadv_orig_node *orig_node;
++
++ orig_node = container_of(rcu, struct batadv_orig_node, rcu);
++
++ batadv_mcast_purge_orig(orig_node);
++
++ batadv_frag_purge_orig(orig_node, NULL);
++
++ if (orig_node->bat_priv->bat_algo_ops->bat_orig_free)
++ orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node);
++
++ kfree(orig_node->tt_buff);
++ kfree(orig_node);
+ }
+
+-static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
++/**
++ * batadv_orig_node_release - release orig_node from lists and queue for
++ * free after rcu grace period
++ * @orig_node: the orig node to free
++ */
++static void batadv_orig_node_release(struct batadv_orig_node *orig_node)
+ {
+ struct hlist_node *node_tmp;
+ struct batadv_neigh_node *neigh_node;
+- struct batadv_orig_node *orig_node;
+ struct batadv_orig_ifinfo *orig_ifinfo;
+
+- orig_node = container_of(rcu, struct batadv_orig_node, rcu);
+-
+ spin_lock_bh(&orig_node->neigh_list_lock);
+
+ /* for all neighbors towards this originator ... */
+ hlist_for_each_entry_safe(neigh_node, node_tmp,
+ &orig_node->neigh_list, list) {
+ hlist_del_rcu(&neigh_node->list);
+- batadv_neigh_node_free_ref_now(neigh_node);
++ batadv_neigh_node_free_ref(neigh_node);
+ }
+
+ hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
+ &orig_node->ifinfo_list, list) {
+ hlist_del_rcu(&orig_ifinfo->list);
+- batadv_orig_ifinfo_free_ref_now(orig_ifinfo);
++ batadv_orig_ifinfo_free_ref(orig_ifinfo);
+ }
+ spin_unlock_bh(&orig_node->neigh_list_lock);
+
+- batadv_mcast_purge_orig(orig_node);
+-
+ /* Free nc_nodes */
+ batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
+
+- batadv_frag_purge_orig(orig_node, NULL);
+-
+- if (orig_node->bat_priv->bat_algo_ops->bat_orig_free)
+- orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node);
+-
+- kfree(orig_node->tt_buff);
+- kfree(orig_node);
++ call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
+ }
+
+ /**
+ * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly
+- * schedule an rcu callback for freeing it
++ * release it
+ * @orig_node: the orig node to free
+ */
+ void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node)
+ {
+ if (atomic_dec_and_test(&orig_node->refcount))
+- call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
+-}
+-
+-/**
+- * batadv_orig_node_free_ref_now - decrement the orig node refcounter and
+- * possibly free it (without rcu callback)
+- * @orig_node: the orig node to free
+- */
+-void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node)
+-{
+- if (atomic_dec_and_test(&orig_node->refcount))
+- batadv_orig_node_free_rcu(&orig_node->rcu);
++ batadv_orig_node_release(orig_node);
+ }
+
+ void batadv_originator_free(struct batadv_priv *bat_priv)
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/batman-adv/originator.h linux-libre-4.4.7-gnu/net/batman-adv/originator.h
+--- linux-libre-4.4-gnu/net/batman-adv/originator.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/batman-adv/originator.h 2016-04-12 12:09:26.000000000 -0400
+@@ -38,7 +38,6 @@ int batadv_originator_init(struct batadv
+ void batadv_originator_free(struct batadv_priv *bat_priv);
+ void batadv_purge_orig_ref(struct batadv_priv *bat_priv);
+ void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node);
+-void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node);
+ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
+ const u8 *addr);
+ struct batadv_neigh_node *
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/batman-adv/translation-table.c linux-libre-4.4.7-gnu/net/batman-adv/translation-table.c
+--- linux-libre-4.4-gnu/net/batman-adv/translation-table.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/batman-adv/translation-table.c 2016-04-12 12:09:26.000000000 -0400
+@@ -240,20 +240,6 @@ int batadv_tt_global_hash_count(struct b
+ return count;
+ }
+
+-static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
+-{
+- struct batadv_tt_orig_list_entry *orig_entry;
+-
+- orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
+-
+- /* We are in an rcu callback here, therefore we cannot use
+- * batadv_orig_node_free_ref() and its call_rcu():
+- * An rcu_barrier() wouldn't wait for that to finish
+- */
+- batadv_orig_node_free_ref_now(orig_entry->orig_node);
+- kfree(orig_entry);
+-}
+-
+ /**
+ * batadv_tt_local_size_mod - change the size by v of the local table identified
+ * by vid
+@@ -349,13 +335,25 @@ static void batadv_tt_global_size_dec(st
+ batadv_tt_global_size_mod(orig_node, vid, -1);
+ }
+
++/**
++ * batadv_tt_orig_list_entry_release - release tt orig entry from lists and
++ * queue for free after rcu grace period
++ * @orig_entry: tt orig entry to be free'd
++ */
++static void
++batadv_tt_orig_list_entry_release(struct batadv_tt_orig_list_entry *orig_entry)
++{
++ batadv_orig_node_free_ref(orig_entry->orig_node);
++ kfree_rcu(orig_entry, rcu);
++}
++
+ static void
+ batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
+ {
+ if (!atomic_dec_and_test(&orig_entry->refcount))
+ return;
+
+- call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
++ batadv_tt_orig_list_entry_release(orig_entry);
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/bluetooth/6lowpan.c linux-libre-4.4.7-gnu/net/bluetooth/6lowpan.c
+--- linux-libre-4.4-gnu/net/bluetooth/6lowpan.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/bluetooth/6lowpan.c 2016-04-12 12:09:26.000000000 -0400
+@@ -307,6 +307,9 @@ static int recv_pkt(struct sk_buff *skb,
+
+ /* check that it's our buffer */
+ if (lowpan_is_ipv6(*skb_network_header(skb))) {
++ /* Pull off the 1-byte of 6lowpan header. */
++ skb_pull(skb, 1);
++
+ /* Copy the packet so that the IPv6 header is
+ * properly aligned.
+ */
+@@ -317,6 +320,7 @@ static int recv_pkt(struct sk_buff *skb,
+
+ local_skb->protocol = htons(ETH_P_IPV6);
+ local_skb->pkt_type = PACKET_HOST;
++ local_skb->dev = dev;
+
+ skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
+
+@@ -335,6 +339,8 @@ static int recv_pkt(struct sk_buff *skb,
+ if (!local_skb)
+ goto drop;
+
++ local_skb->dev = dev;
++
+ ret = iphc_decompress(local_skb, dev, chan);
+ if (ret < 0) {
+ kfree_skb(local_skb);
+@@ -343,7 +349,6 @@ static int recv_pkt(struct sk_buff *skb,
+
+ local_skb->protocol = htons(ETH_P_IPV6);
+ local_skb->pkt_type = PACKET_HOST;
+- local_skb->dev = dev;
+
+ if (give_skb_to_upper(local_skb, dev)
+ != NET_RX_SUCCESS) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/bluetooth/hci_conn.c linux-libre-4.4.7-gnu/net/bluetooth/hci_conn.c
+--- linux-libre-4.4-gnu/net/bluetooth/hci_conn.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/bluetooth/hci_conn.c 2016-04-12 12:09:26.000000000 -0400
+@@ -722,8 +722,12 @@ static void hci_req_add_le_create_conn(s
+ if (hci_update_random_address(req, false, &own_addr_type))
+ return;
+
++ /* Set window to be the same value as the interval to enable
++ * continuous scanning.
++ */
+ cp.scan_interval = cpu_to_le16(hdev->le_scan_interval);
+- cp.scan_window = cpu_to_le16(hdev->le_scan_window);
++ cp.scan_window = cp.scan_interval;
++
+ bacpy(&cp.peer_addr, &conn->dst);
+ cp.peer_addr_type = conn->dst_type;
+ cp.own_address_type = own_addr_type;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/bluetooth/hci_request.c linux-libre-4.4.7-gnu/net/bluetooth/hci_request.c
+--- linux-libre-4.4-gnu/net/bluetooth/hci_request.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/bluetooth/hci_request.c 2016-04-12 12:09:26.000000000 -0400
+@@ -175,21 +175,29 @@ static u8 update_white_list(struct hci_r
+ * command to remove it from the controller.
+ */
+ list_for_each_entry(b, &hdev->le_white_list, list) {
+- struct hci_cp_le_del_from_white_list cp;
++ /* If the device is neither in pend_le_conns nor
++ * pend_le_reports then remove it from the whitelist.
++ */
++ if (!hci_pend_le_action_lookup(&hdev->pend_le_conns,
++ &b->bdaddr, b->bdaddr_type) &&
++ !hci_pend_le_action_lookup(&hdev->pend_le_reports,
++ &b->bdaddr, b->bdaddr_type)) {
++ struct hci_cp_le_del_from_white_list cp;
+
+- if (hci_pend_le_action_lookup(&hdev->pend_le_conns,
+- &b->bdaddr, b->bdaddr_type) ||
+- hci_pend_le_action_lookup(&hdev->pend_le_reports,
+- &b->bdaddr, b->bdaddr_type)) {
+- white_list_entries++;
++ cp.bdaddr_type = b->bdaddr_type;
++ bacpy(&cp.bdaddr, &b->bdaddr);
++
++ hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST,
++ sizeof(cp), &cp);
+ continue;
+ }
+
+- cp.bdaddr_type = b->bdaddr_type;
+- bacpy(&cp.bdaddr, &b->bdaddr);
++ if (hci_find_irk_by_addr(hdev, &b->bdaddr, b->bdaddr_type)) {
++ /* White list can not be used with RPAs */
++ return 0x00;
++ }
+
+- hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST,
+- sizeof(cp), &cp);
++ white_list_entries++;
+ }
+
+ /* Since all no longer valid white list entries have been
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/bluetooth/mgmt.c linux-libre-4.4.7-gnu/net/bluetooth/mgmt.c
+--- linux-libre-4.4-gnu/net/bluetooth/mgmt.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/bluetooth/mgmt.c 2016-04-12 12:09:26.000000000 -0400
+@@ -7155,6 +7155,10 @@ static int add_advertising(struct sock *
+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
+ status);
+
++ if (data_len != sizeof(*cp) + cp->adv_data_len + cp->scan_rsp_len)
++ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
++ MGMT_STATUS_INVALID_PARAMS);
++
+ flags = __le32_to_cpu(cp->flags);
+ timeout = __le16_to_cpu(cp->timeout);
+ duration = __le16_to_cpu(cp->duration);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/bluetooth/smp.c linux-libre-4.4.7-gnu/net/bluetooth/smp.c
+--- linux-libre-4.4-gnu/net/bluetooth/smp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/bluetooth/smp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1072,22 +1072,6 @@ static void smp_notify_keys(struct l2cap
+ hcon->dst_type = smp->remote_irk->addr_type;
+ queue_work(hdev->workqueue, &conn->id_addr_update_work);
+ }
+-
+- /* When receiving an indentity resolving key for
+- * a remote device that does not use a resolvable
+- * private address, just remove the key so that
+- * it is possible to use the controller white
+- * list for scanning.
+- *
+- * Userspace will have been told to not store
+- * this key at this point. So it is safe to
+- * just remove it.
+- */
+- if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) {
+- list_del_rcu(&smp->remote_irk->list);
+- kfree_rcu(smp->remote_irk, rcu);
+- smp->remote_irk = NULL;
+- }
+ }
+
+ if (smp->csrk) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/bridge/br.c linux-libre-4.4.7-gnu/net/bridge/br.c
+--- linux-libre-4.4-gnu/net/bridge/br.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/bridge/br.c 2016-04-12 12:09:26.000000000 -0400
+@@ -121,6 +121,7 @@ static struct notifier_block br_device_n
+ .notifier_call = br_device_event
+ };
+
++/* called with RTNL */
+ static int br_switchdev_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+ {
+@@ -130,7 +131,6 @@ static int br_switchdev_event(struct not
+ struct switchdev_notifier_fdb_info *fdb_info;
+ int err = NOTIFY_DONE;
+
+- rtnl_lock();
+ p = br_port_get_rtnl(dev);
+ if (!p)
+ goto out;
+@@ -155,7 +155,6 @@ static int br_switchdev_event(struct not
+ }
+
+ out:
+- rtnl_unlock();
+ return err;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/bridge/br_device.c linux-libre-4.4.7-gnu/net/bridge/br_device.c
+--- linux-libre-4.4-gnu/net/bridge/br_device.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/bridge/br_device.c 2016-04-12 12:09:26.000000000 -0400
+@@ -28,6 +28,8 @@
+ const struct nf_br_ops __rcu *nf_br_ops __read_mostly;
+ EXPORT_SYMBOL_GPL(nf_br_ops);
+
++static struct lock_class_key bridge_netdev_addr_lock_key;
++
+ /* net device transmit always called with BH disabled */
+ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+@@ -87,6 +89,11 @@ out:
+ return NETDEV_TX_OK;
+ }
+
++static void br_set_lockdep_class(struct net_device *dev)
++{
++ lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key);
++}
++
+ static int br_dev_init(struct net_device *dev)
+ {
+ struct net_bridge *br = netdev_priv(dev);
+@@ -99,6 +106,7 @@ static int br_dev_init(struct net_device
+ err = br_vlan_init(br);
+ if (err)
+ free_percpu(br->stats);
++ br_set_lockdep_class(dev);
+
+ return err;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ceph/messenger.c linux-libre-4.4.7-gnu/net/ceph/messenger.c
+--- linux-libre-4.4-gnu/net/ceph/messenger.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ceph/messenger.c 2016-04-12 12:09:26.000000000 -0400
+@@ -672,6 +672,8 @@ static void reset_connection(struct ceph
+ }
+ con->in_seq = 0;
+ con->in_seq_acked = 0;
++
++ con->out_skip = 0;
+ }
+
+ /*
+@@ -771,6 +773,8 @@ static u32 get_global_seq(struct ceph_me
+
+ static void con_out_kvec_reset(struct ceph_connection *con)
+ {
++ BUG_ON(con->out_skip);
++
+ con->out_kvec_left = 0;
+ con->out_kvec_bytes = 0;
+ con->out_kvec_cur = &con->out_kvec[0];
+@@ -779,9 +783,9 @@ static void con_out_kvec_reset(struct ce
+ static void con_out_kvec_add(struct ceph_connection *con,
+ size_t size, void *data)
+ {
+- int index;
++ int index = con->out_kvec_left;
+
+- index = con->out_kvec_left;
++ BUG_ON(con->out_skip);
+ BUG_ON(index >= ARRAY_SIZE(con->out_kvec));
+
+ con->out_kvec[index].iov_len = size;
+@@ -790,6 +794,27 @@ static void con_out_kvec_add(struct ceph
+ con->out_kvec_bytes += size;
+ }
+
++/*
++ * Chop off a kvec from the end. Return residual number of bytes for
++ * that kvec, i.e. how many bytes would have been written if the kvec
++ * hadn't been nuked.
++ */
++static int con_out_kvec_skip(struct ceph_connection *con)
++{
++ int off = con->out_kvec_cur - con->out_kvec;
++ int skip = 0;
++
++ if (con->out_kvec_bytes > 0) {
++ skip = con->out_kvec[off + con->out_kvec_left - 1].iov_len;
++ BUG_ON(con->out_kvec_bytes < skip);
++ BUG_ON(!con->out_kvec_left);
++ con->out_kvec_bytes -= skip;
++ con->out_kvec_left--;
++ }
++
++ return skip;
++}
++
+ #ifdef CONFIG_BLOCK
+
+ /*
+@@ -1175,6 +1200,13 @@ static bool ceph_msg_data_advance(struct
+ return new_piece;
+ }
+
++static size_t sizeof_footer(struct ceph_connection *con)
++{
++ return (con->peer_features & CEPH_FEATURE_MSG_AUTH) ?
++ sizeof(struct ceph_msg_footer) :
++ sizeof(struct ceph_msg_footer_old);
++}
++
+ static void prepare_message_data(struct ceph_msg *msg, u32 data_len)
+ {
+ BUG_ON(!msg);
+@@ -1197,7 +1229,6 @@ static void prepare_write_message_footer
+ m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE;
+
+ dout("prepare_write_message_footer %p\n", con);
+- con->out_kvec_is_msg = true;
+ con->out_kvec[v].iov_base = &m->footer;
+ if (con->peer_features & CEPH_FEATURE_MSG_AUTH) {
+ if (con->ops->sign_message)
+@@ -1225,7 +1256,6 @@ static void prepare_write_message(struct
+ u32 crc;
+
+ con_out_kvec_reset(con);
+- con->out_kvec_is_msg = true;
+ con->out_msg_done = false;
+
+ /* Sneak an ack in there first? If we can get it into the same
+@@ -1265,18 +1295,19 @@ static void prepare_write_message(struct
+
+ /* tag + hdr + front + middle */
+ con_out_kvec_add(con, sizeof (tag_msg), &tag_msg);
+- con_out_kvec_add(con, sizeof (m->hdr), &m->hdr);
++ con_out_kvec_add(con, sizeof(con->out_hdr), &con->out_hdr);
+ con_out_kvec_add(con, m->front.iov_len, m->front.iov_base);
+
+ if (m->middle)
+ con_out_kvec_add(con, m->middle->vec.iov_len,
+ m->middle->vec.iov_base);
+
+- /* fill in crc (except data pages), footer */
++ /* fill in hdr crc and finalize hdr */
+ crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc));
+ con->out_msg->hdr.crc = cpu_to_le32(crc);
+- con->out_msg->footer.flags = 0;
++ memcpy(&con->out_hdr, &con->out_msg->hdr, sizeof(con->out_hdr));
+
++ /* fill in front and middle crc, footer */
+ crc = crc32c(0, m->front.iov_base, m->front.iov_len);
+ con->out_msg->footer.front_crc = cpu_to_le32(crc);
+ if (m->middle) {
+@@ -1288,6 +1319,7 @@ static void prepare_write_message(struct
+ dout("%s front_crc %u middle_crc %u\n", __func__,
+ le32_to_cpu(con->out_msg->footer.front_crc),
+ le32_to_cpu(con->out_msg->footer.middle_crc));
++ con->out_msg->footer.flags = 0;
+
+ /* is there a data payload? */
+ con->out_msg->footer.data_crc = 0;
+@@ -1492,7 +1524,6 @@ static int write_partial_kvec(struct cep
+ }
+ }
+ con->out_kvec_left = 0;
+- con->out_kvec_is_msg = false;
+ ret = 1;
+ out:
+ dout("write_partial_kvec %p %d left in %d kvecs ret = %d\n", con,
+@@ -1584,6 +1615,7 @@ static int write_partial_skip(struct cep
+ {
+ int ret;
+
++ dout("%s %p %d left\n", __func__, con, con->out_skip);
+ while (con->out_skip > 0) {
+ size_t size = min(con->out_skip, (int) PAGE_CACHE_SIZE);
+
+@@ -2313,9 +2345,9 @@ static int read_partial_message(struct c
+ ceph_pr_addr(&con->peer_addr.in_addr),
+ seq, con->in_seq + 1);
+ con->in_base_pos = -front_len - middle_len - data_len -
+- sizeof(m->footer);
++ sizeof_footer(con);
+ con->in_tag = CEPH_MSGR_TAG_READY;
+- return 0;
++ return 1;
+ } else if ((s64)seq - (s64)con->in_seq > 1) {
+ pr_err("read_partial_message bad seq %lld expected %lld\n",
+ seq, con->in_seq + 1);
+@@ -2338,10 +2370,10 @@ static int read_partial_message(struct c
+ /* skip this message */
+ dout("alloc_msg said skip message\n");
+ con->in_base_pos = -front_len - middle_len - data_len -
+- sizeof(m->footer);
++ sizeof_footer(con);
+ con->in_tag = CEPH_MSGR_TAG_READY;
+ con->in_seq++;
+- return 0;
++ return 1;
+ }
+
+ BUG_ON(!con->in_msg);
+@@ -2506,13 +2538,13 @@ more:
+
+ more_kvec:
+ /* kvec data queued? */
+- if (con->out_skip) {
+- ret = write_partial_skip(con);
++ if (con->out_kvec_left) {
++ ret = write_partial_kvec(con);
+ if (ret <= 0)
+ goto out;
+ }
+- if (con->out_kvec_left) {
+- ret = write_partial_kvec(con);
++ if (con->out_skip) {
++ ret = write_partial_skip(con);
+ if (ret <= 0)
+ goto out;
+ }
+@@ -3050,16 +3082,31 @@ void ceph_msg_revoke(struct ceph_msg *ms
+ ceph_msg_put(msg);
+ }
+ if (con->out_msg == msg) {
+- dout("%s %p msg %p - was sending\n", __func__, con, msg);
+- con->out_msg = NULL;
+- if (con->out_kvec_is_msg) {
+- con->out_skip = con->out_kvec_bytes;
+- con->out_kvec_is_msg = false;
++ BUG_ON(con->out_skip);
++ /* footer */
++ if (con->out_msg_done) {
++ con->out_skip += con_out_kvec_skip(con);
++ } else {
++ BUG_ON(!msg->data_length);
++ if (con->peer_features & CEPH_FEATURE_MSG_AUTH)
++ con->out_skip += sizeof(msg->footer);
++ else
++ con->out_skip += sizeof(msg->old_footer);
+ }
+- msg->hdr.seq = 0;
++ /* data, middle, front */
++ if (msg->data_length)
++ con->out_skip += msg->cursor.total_resid;
++ if (msg->middle)
++ con->out_skip += con_out_kvec_skip(con);
++ con->out_skip += con_out_kvec_skip(con);
+
++ dout("%s %p msg %p - was sending, will write %d skip %d\n",
++ __func__, con, msg, con->out_kvec_bytes, con->out_skip);
++ msg->hdr.seq = 0;
++ con->out_msg = NULL;
+ ceph_msg_put(msg);
+ }
++
+ mutex_unlock(&con->mutex);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ceph/osd_client.c linux-libre-4.4.7-gnu/net/ceph/osd_client.c
+--- linux-libre-4.4-gnu/net/ceph/osd_client.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ceph/osd_client.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2843,8 +2843,8 @@ static struct ceph_msg *get_reply(struct
+ mutex_lock(&osdc->request_mutex);
+ req = __lookup_request(osdc, tid);
+ if (!req) {
+- pr_warn("%s osd%d tid %llu unknown, skipping\n",
+- __func__, osd->o_osd, tid);
++ dout("%s osd%d tid %llu unknown, skipping\n", __func__,
++ osd->o_osd, tid);
+ m = NULL;
+ *skip = 1;
+ goto out;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/core/dev.c linux-libre-4.4.7-gnu/net/core/dev.c
+--- linux-libre-4.4-gnu/net/core/dev.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/core/dev.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2542,6 +2542,8 @@ static inline bool skb_needs_check(struc
+ *
+ * It may return NULL if the skb requires no segmentation. This is
+ * only possible when GSO is used for verifying header integrity.
++ *
++ * Segmentation preserves SKB_SGO_CB_OFFSET bytes of previous skb cb.
+ */
+ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
+ netdev_features_t features, bool tx_path)
+@@ -2556,6 +2558,9 @@ struct sk_buff *__skb_gso_segment(struct
+ return ERR_PTR(err);
+ }
+
++ BUILD_BUG_ON(SKB_SGO_CB_OFFSET +
++ sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb));
++
+ SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb);
+ SKB_GSO_CB(skb)->encap_level = 0;
+
+@@ -4140,6 +4145,7 @@ static void gro_list_prepare(struct napi
+
+ diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
+ diffs |= p->vlan_tci ^ skb->vlan_tci;
++ diffs |= skb_metadata_dst_cmp(p, skb);
+ if (maclen == ETH_HLEN)
+ diffs |= compare_ether_header(skb_mac_header(p),
+ skb_mac_header(skb));
+@@ -4337,10 +4343,12 @@ static gro_result_t napi_skb_finish(gro_
+ break;
+
+ case GRO_MERGED_FREE:
+- if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
++ if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
++ skb_dst_drop(skb);
+ kmem_cache_free(skbuff_head_cache, skb);
+- else
++ } else {
+ __kfree_skb(skb);
++ }
+ break;
+
+ case GRO_HELD:
+@@ -7120,8 +7128,10 @@ struct net_device *alloc_netdev_mqs(int
+ dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
+ setup(dev);
+
+- if (!dev->tx_queue_len)
++ if (!dev->tx_queue_len) {
+ dev->priv_flags |= IFF_NO_QUEUE;
++ dev->tx_queue_len = 1;
++ }
+
+ dev->num_tx_queues = txqs;
+ dev->real_num_tx_queues = txqs;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/core/filter.c linux-libre-4.4.7-gnu/net/core/filter.c
+--- linux-libre-4.4-gnu/net/core/filter.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/core/filter.c 2016-04-12 12:09:26.000000000 -0400
+@@ -777,6 +777,11 @@ static int bpf_check_classic(const struc
+ if (ftest->k == 0)
+ return -EINVAL;
+ break;
++ case BPF_ALU | BPF_LSH | BPF_K:
++ case BPF_ALU | BPF_RSH | BPF_K:
++ if (ftest->k >= 32)
++ return -EINVAL;
++ break;
+ case BPF_LD | BPF_MEM:
+ case BPF_LDX | BPF_MEM:
+ case BPF_ST:
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/core/flow_dissector.c linux-libre-4.4.7-gnu/net/core/flow_dissector.c
+--- linux-libre-4.4-gnu/net/core/flow_dissector.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/core/flow_dissector.c 2016-04-12 12:09:26.000000000 -0400
+@@ -208,7 +208,6 @@ ip:
+ case htons(ETH_P_IPV6): {
+ const struct ipv6hdr *iph;
+ struct ipv6hdr _iph;
+- __be32 flow_label;
+
+ ipv6:
+ iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
+@@ -230,8 +229,12 @@ ipv6:
+ key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
+ }
+
+- flow_label = ip6_flowlabel(iph);
+- if (flow_label) {
++ if ((dissector_uses_key(flow_dissector,
++ FLOW_DISSECTOR_KEY_FLOW_LABEL) ||
++ (flags & FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL)) &&
++ ip6_flowlabel(iph)) {
++ __be32 flow_label = ip6_flowlabel(iph);
++
+ if (dissector_uses_key(flow_dissector,
+ FLOW_DISSECTOR_KEY_FLOW_LABEL)) {
+ key_tags = skb_flow_dissector_target(flow_dissector,
+@@ -396,6 +399,13 @@ ip_proto_again:
+ goto out_bad;
+ proto = eth->h_proto;
+ nhoff += sizeof(*eth);
++
++ /* Cap headers that we access via pointers at the
++ * end of the Ethernet header as our maximum alignment
++ * at that point is only 2 bytes.
++ */
++ if (NET_IP_ALIGN)
++ hlen = nhoff;
+ }
+
+ key_control->flags |= FLOW_DIS_ENCAPSULATION;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/core/pktgen.c linux-libre-4.4.7-gnu/net/core/pktgen.c
+--- linux-libre-4.4-gnu/net/core/pktgen.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/core/pktgen.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2787,7 +2787,9 @@ static struct sk_buff *pktgen_alloc_skb(
+ } else {
+ skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT);
+ }
+- skb_reserve(skb, LL_RESERVED_SPACE(dev));
++
++ if (likely(skb))
++ skb_reserve(skb, LL_RESERVED_SPACE(dev));
+
+ return skb;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/core/scm.c linux-libre-4.4.7-gnu/net/core/scm.c
+--- linux-libre-4.4-gnu/net/core/scm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/core/scm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -87,6 +87,7 @@ static int scm_fp_copy(struct cmsghdr *c
+ *fplp = fpl;
+ fpl->count = 0;
+ fpl->max = SCM_MAX_FD;
++ fpl->user = NULL;
+ }
+ fpp = &fpl->fp[fpl->count];
+
+@@ -107,6 +108,10 @@ static int scm_fp_copy(struct cmsghdr *c
+ *fpp++ = file;
+ fpl->count++;
+ }
++
++ if (!fpl->user)
++ fpl->user = get_uid(current_user());
++
+ return num;
+ }
+
+@@ -119,6 +124,7 @@ void __scm_destroy(struct scm_cookie *sc
+ scm->fp = NULL;
+ for (i=fpl->count-1; i>=0; i--)
+ fput(fpl->fp[i]);
++ free_uid(fpl->user);
+ kfree(fpl);
+ }
+ }
+@@ -336,6 +342,7 @@ struct scm_fp_list *scm_fp_dup(struct sc
+ for (i = 0; i < fpl->count; i++)
+ get_file(fpl->fp[i]);
+ new_fpl->max = new_fpl->count;
++ new_fpl->user = get_uid(fpl->user);
+ }
+ return new_fpl;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/core/skbuff.c linux-libre-4.4.7-gnu/net/core/skbuff.c
+--- linux-libre-4.4-gnu/net/core/skbuff.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/core/skbuff.c 2016-04-12 12:09:26.000000000 -0400
+@@ -79,6 +79,8 @@
+
+ struct kmem_cache *skbuff_head_cache __read_mostly;
+ static struct kmem_cache *skbuff_fclone_cache __read_mostly;
++int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
++EXPORT_SYMBOL(sysctl_max_skb_frags);
+
+ /**
+ * skb_panic - private function for out-of-line support
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/core/sysctl_net_core.c linux-libre-4.4.7-gnu/net/core/sysctl_net_core.c
+--- linux-libre-4.4-gnu/net/core/sysctl_net_core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/core/sysctl_net_core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -26,6 +26,7 @@ static int zero = 0;
+ static int one = 1;
+ static int min_sndbuf = SOCK_MIN_SNDBUF;
+ static int min_rcvbuf = SOCK_MIN_RCVBUF;
++static int max_skb_frags = MAX_SKB_FRAGS;
+
+ static int net_msg_warn; /* Unused, but still a sysctl */
+
+@@ -392,6 +393,15 @@ static struct ctl_table net_core_table[]
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
++ {
++ .procname = "max_skb_frags",
++ .data = &sysctl_max_skb_frags,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = &one,
++ .extra2 = &max_skb_frags,
++ },
+ { }
+ };
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/dccp/ipv4.c linux-libre-4.4.7-gnu/net/dccp/ipv4.c
+--- linux-libre-4.4-gnu/net/dccp/ipv4.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/dccp/ipv4.c 2016-04-12 12:09:26.000000000 -0400
+@@ -824,26 +824,26 @@ lookup:
+
+ if (sk->sk_state == DCCP_NEW_SYN_RECV) {
+ struct request_sock *req = inet_reqsk(sk);
+- struct sock *nsk = NULL;
++ struct sock *nsk;
+
+ sk = req->rsk_listener;
+- if (likely(sk->sk_state == DCCP_LISTEN)) {
+- nsk = dccp_check_req(sk, skb, req);
+- } else {
++ if (unlikely(sk->sk_state != DCCP_LISTEN)) {
+ inet_csk_reqsk_queue_drop_and_put(sk, req);
+ goto lookup;
+ }
++ sock_hold(sk);
++ nsk = dccp_check_req(sk, skb, req);
+ if (!nsk) {
+ reqsk_put(req);
+- goto discard_it;
++ goto discard_and_relse;
+ }
+ if (nsk == sk) {
+- sock_hold(sk);
+ reqsk_put(req);
+ } else if (dccp_child_process(sk, nsk, skb)) {
+ dccp_v4_ctl_send_reset(sk, skb);
+- goto discard_it;
++ goto discard_and_relse;
+ } else {
++ sock_put(sk);
+ return 0;
+ }
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/dccp/ipv6.c linux-libre-4.4.7-gnu/net/dccp/ipv6.c
+--- linux-libre-4.4-gnu/net/dccp/ipv6.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/dccp/ipv6.c 2016-04-12 12:09:26.000000000 -0400
+@@ -691,26 +691,26 @@ lookup:
+
+ if (sk->sk_state == DCCP_NEW_SYN_RECV) {
+ struct request_sock *req = inet_reqsk(sk);
+- struct sock *nsk = NULL;
++ struct sock *nsk;
+
+ sk = req->rsk_listener;
+- if (likely(sk->sk_state == DCCP_LISTEN)) {
+- nsk = dccp_check_req(sk, skb, req);
+- } else {
++ if (unlikely(sk->sk_state != DCCP_LISTEN)) {
+ inet_csk_reqsk_queue_drop_and_put(sk, req);
+ goto lookup;
+ }
++ sock_hold(sk);
++ nsk = dccp_check_req(sk, skb, req);
+ if (!nsk) {
+ reqsk_put(req);
+- goto discard_it;
++ goto discard_and_relse;
+ }
+ if (nsk == sk) {
+- sock_hold(sk);
+ reqsk_put(req);
+ } else if (dccp_child_process(sk, nsk, skb)) {
+ dccp_v6_ctl_send_reset(sk, skb);
+- goto discard_it;
++ goto discard_and_relse;
+ } else {
++ sock_put(sk);
+ return 0;
+ }
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/devinet.c linux-libre-4.4.7-gnu/net/ipv4/devinet.c
+--- linux-libre-4.4-gnu/net/ipv4/devinet.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/devinet.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1847,7 +1847,7 @@ static int inet_netconf_get_devconf(stru
+ if (err < 0)
+ goto errout;
+
+- err = EINVAL;
++ err = -EINVAL;
+ if (!tb[NETCONFA_IFINDEX])
+ goto errout;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/inet_connection_sock.c linux-libre-4.4.7-gnu/net/ipv4/inet_connection_sock.c
+--- linux-libre-4.4-gnu/net/ipv4/inet_connection_sock.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/inet_connection_sock.c 2016-04-12 12:09:26.000000000 -0400
+@@ -789,14 +789,16 @@ static void inet_child_forget(struct soc
+ reqsk_put(req);
+ }
+
+-void inet_csk_reqsk_queue_add(struct sock *sk, struct request_sock *req,
+- struct sock *child)
++struct sock *inet_csk_reqsk_queue_add(struct sock *sk,
++ struct request_sock *req,
++ struct sock *child)
+ {
+ struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
+
+ spin_lock(&queue->rskq_lock);
+ if (unlikely(sk->sk_state != TCP_LISTEN)) {
+ inet_child_forget(sk, req, child);
++ child = NULL;
+ } else {
+ req->sk = child;
+ req->dl_next = NULL;
+@@ -808,6 +810,7 @@ void inet_csk_reqsk_queue_add(struct soc
+ sk_acceptq_added(sk);
+ }
+ spin_unlock(&queue->rskq_lock);
++ return child;
+ }
+ EXPORT_SYMBOL(inet_csk_reqsk_queue_add);
+
+@@ -817,11 +820,8 @@ struct sock *inet_csk_complete_hashdance
+ if (own_req) {
+ inet_csk_reqsk_queue_drop(sk, req);
+ reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
+- inet_csk_reqsk_queue_add(sk, req, child);
+- /* Warning: caller must not call reqsk_put(req);
+- * child stole last reference on it.
+- */
+- return child;
++ if (inet_csk_reqsk_queue_add(sk, req, child))
++ return child;
+ }
+ /* Too bad, another child took ownership of the request, undo. */
+ bh_unlock_sock(child);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/ip_fragment.c linux-libre-4.4.7-gnu/net/ipv4/ip_fragment.c
+--- linux-libre-4.4-gnu/net/ipv4/ip_fragment.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/ip_fragment.c 2016-04-12 12:09:26.000000000 -0400
+@@ -661,6 +661,7 @@ int ip_defrag(struct net *net, struct sk
+ struct ipq *qp;
+
+ IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
++ skb_orphan(skb);
+
+ /* Lookup (or create) queue header */
+ qp = ip_find(net, ip_hdr(skb), user, vif);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/ip_output.c linux-libre-4.4.7-gnu/net/ipv4/ip_output.c
+--- linux-libre-4.4-gnu/net/ipv4/ip_output.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/ip_output.c 2016-04-12 12:09:26.000000000 -0400
+@@ -240,6 +240,7 @@ static int ip_finish_output_gso(struct n
+ * from host network stack.
+ */
+ features = netif_skb_features(skb);
++ BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET);
+ segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+ if (IS_ERR_OR_NULL(segs)) {
+ kfree_skb(skb);
+@@ -921,7 +922,7 @@ static int __ip_append_data(struct sock
+ if (((length > mtu) || (skb && skb_is_gso(skb))) &&
+ (sk->sk_protocol == IPPROTO_UDP) &&
+ (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len &&
+- (sk->sk_type == SOCK_DGRAM)) {
++ (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) {
+ err = ip_ufo_append_data(sk, queue, getfrag, from, length,
+ hh_len, fragheaderlen, transhdrlen,
+ maxfraglen, flags);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/ip_sockglue.c linux-libre-4.4.7-gnu/net/ipv4/ip_sockglue.c
+--- linux-libre-4.4-gnu/net/ipv4/ip_sockglue.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/ip_sockglue.c 2016-04-12 12:09:26.000000000 -0400
+@@ -249,6 +249,8 @@ int ip_cmsg_send(struct net *net, struct
+ switch (cmsg->cmsg_type) {
+ case IP_RETOPTS:
+ err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
++
++ /* Our caller is responsible for freeing ipc->opt */
+ err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg),
+ err < 40 ? err : 40);
+ if (err)
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/netfilter/nf_defrag_ipv4.c linux-libre-4.4.7-gnu/net/ipv4/netfilter/nf_defrag_ipv4.c
+--- linux-libre-4.4-gnu/net/ipv4/netfilter/nf_defrag_ipv4.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/netfilter/nf_defrag_ipv4.c 2016-04-12 12:09:26.000000000 -0400
+@@ -27,8 +27,6 @@ static int nf_ct_ipv4_gather_frags(struc
+ {
+ int err;
+
+- skb_orphan(skb);
+-
+ local_bh_disable();
+ err = ip_defrag(net, skb, user);
+ local_bh_enable();
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/ping.c linux-libre-4.4.7-gnu/net/ipv4/ping.c
+--- linux-libre-4.4-gnu/net/ipv4/ping.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/ping.c 2016-04-12 12:09:26.000000000 -0400
+@@ -746,8 +746,10 @@ static int ping_v4_sendmsg(struct sock *
+
+ if (msg->msg_controllen) {
+ err = ip_cmsg_send(sock_net(sk), msg, &ipc, false);
+- if (err)
++ if (unlikely(err)) {
++ kfree(ipc.opt);
+ return err;
++ }
+ if (ipc.opt)
+ free = 1;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/raw.c linux-libre-4.4.7-gnu/net/ipv4/raw.c
+--- linux-libre-4.4-gnu/net/ipv4/raw.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/raw.c 2016-04-12 12:09:26.000000000 -0400
+@@ -547,8 +547,10 @@ static int raw_sendmsg(struct sock *sk,
+
+ if (msg->msg_controllen) {
+ err = ip_cmsg_send(net, msg, &ipc, false);
+- if (err)
++ if (unlikely(err)) {
++ kfree(ipc.opt);
+ goto out;
++ }
+ if (ipc.opt)
+ free = 1;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/route.c linux-libre-4.4.7-gnu/net/ipv4/route.c
+--- linux-libre-4.4-gnu/net/ipv4/route.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/route.c 2016-04-12 12:09:26.000000000 -0400
+@@ -129,6 +129,7 @@ static int ip_rt_mtu_expires __read_most
+ static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20;
+ static int ip_rt_min_advmss __read_mostly = 256;
+
++static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT;
+ /*
+ * Interface to generic destination cache.
+ */
+@@ -755,7 +756,7 @@ static void __ip_do_redirect(struct rtab
+ struct fib_nh *nh = &FIB_RES_NH(res);
+
+ update_or_create_fnhe(nh, fl4->daddr, new_gw,
+- 0, 0);
++ 0, jiffies + ip_rt_gc_timeout);
+ }
+ if (kill_route)
+ rt->dst.obsolete = DST_OBSOLETE_KILL;
+@@ -1556,6 +1557,36 @@ static void ip_handle_martian_source(str
+ #endif
+ }
+
++static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
++{
++ struct fnhe_hash_bucket *hash;
++ struct fib_nh_exception *fnhe, __rcu **fnhe_p;
++ u32 hval = fnhe_hashfun(daddr);
++
++ spin_lock_bh(&fnhe_lock);
++
++ hash = rcu_dereference_protected(nh->nh_exceptions,
++ lockdep_is_held(&fnhe_lock));
++ hash += hval;
++
++ fnhe_p = &hash->chain;
++ fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock));
++ while (fnhe) {
++ if (fnhe->fnhe_daddr == daddr) {
++ rcu_assign_pointer(*fnhe_p, rcu_dereference_protected(
++ fnhe->fnhe_next, lockdep_is_held(&fnhe_lock)));
++ fnhe_flush_routes(fnhe);
++ kfree_rcu(fnhe, rcu);
++ break;
++ }
++ fnhe_p = &fnhe->fnhe_next;
++ fnhe = rcu_dereference_protected(fnhe->fnhe_next,
++ lockdep_is_held(&fnhe_lock));
++ }
++
++ spin_unlock_bh(&fnhe_lock);
++}
++
+ /* called in rcu_read_lock() section */
+ static int __mkroute_input(struct sk_buff *skb,
+ const struct fib_result *res,
+@@ -1609,11 +1640,20 @@ static int __mkroute_input(struct sk_buf
+
+ fnhe = find_exception(&FIB_RES_NH(*res), daddr);
+ if (do_cache) {
+- if (fnhe)
++ if (fnhe) {
+ rth = rcu_dereference(fnhe->fnhe_rth_input);
+- else
+- rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
++ if (rth && rth->dst.expires &&
++ time_after(jiffies, rth->dst.expires)) {
++ ip_del_fnhe(&FIB_RES_NH(*res), daddr);
++ fnhe = NULL;
++ } else {
++ goto rt_cache;
++ }
++ }
++
++ rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+
++rt_cache:
+ if (rt_cache_valid(rth)) {
+ skb_dst_set_noref(skb, &rth->dst);
+ goto out;
+@@ -2014,19 +2054,29 @@ static struct rtable *__mkroute_output(c
+ struct fib_nh *nh = &FIB_RES_NH(*res);
+
+ fnhe = find_exception(nh, fl4->daddr);
+- if (fnhe)
++ if (fnhe) {
+ prth = &fnhe->fnhe_rth_output;
+- else {
+- if (unlikely(fl4->flowi4_flags &
+- FLOWI_FLAG_KNOWN_NH &&
+- !(nh->nh_gw &&
+- nh->nh_scope == RT_SCOPE_LINK))) {
+- do_cache = false;
+- goto add;
++ rth = rcu_dereference(*prth);
++ if (rth && rth->dst.expires &&
++ time_after(jiffies, rth->dst.expires)) {
++ ip_del_fnhe(nh, fl4->daddr);
++ fnhe = NULL;
++ } else {
++ goto rt_cache;
+ }
+- prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ }
++
++ if (unlikely(fl4->flowi4_flags &
++ FLOWI_FLAG_KNOWN_NH &&
++ !(nh->nh_gw &&
++ nh->nh_scope == RT_SCOPE_LINK))) {
++ do_cache = false;
++ goto add;
++ }
++ prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ rth = rcu_dereference(*prth);
++
++rt_cache:
+ if (rt_cache_valid(rth)) {
+ dst_hold(&rth->dst);
+ return rth;
+@@ -2569,7 +2619,6 @@ void ip_rt_multicast_event(struct in_dev
+ }
+
+ #ifdef CONFIG_SYSCTL
+-static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT;
+ static int ip_rt_gc_interval __read_mostly = 60 * HZ;
+ static int ip_rt_gc_min_interval __read_mostly = HZ / 2;
+ static int ip_rt_gc_elasticity __read_mostly = 8;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/tcp.c linux-libre-4.4.7-gnu/net/ipv4/tcp.c
+--- linux-libre-4.4-gnu/net/ipv4/tcp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/tcp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -279,6 +279,7 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/ioctls.h>
++#include <asm/unaligned.h>
+ #include <net/busy_poll.h>
+
+ int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT;
+@@ -938,7 +939,7 @@ new_segment:
+
+ i = skb_shinfo(skb)->nr_frags;
+ can_coalesce = skb_can_coalesce(skb, i, page, offset);
+- if (!can_coalesce && i >= MAX_SKB_FRAGS) {
++ if (!can_coalesce && i >= sysctl_max_skb_frags) {
+ tcp_mark_push(tp, skb);
+ goto new_segment;
+ }
+@@ -1211,7 +1212,7 @@ new_segment:
+
+ if (!skb_can_coalesce(skb, i, pfrag->page,
+ pfrag->offset)) {
+- if (i == MAX_SKB_FRAGS || !sg) {
++ if (i == sysctl_max_skb_frags || !sg) {
+ tcp_mark_push(tp, skb);
+ goto new_segment;
+ }
+@@ -2637,6 +2638,7 @@ void tcp_get_info(struct sock *sk, struc
+ const struct inet_connection_sock *icsk = inet_csk(sk);
+ u32 now = tcp_time_stamp;
+ unsigned int start;
++ u64 rate64;
+ u32 rate;
+
+ memset(info, 0, sizeof(*info));
+@@ -2702,15 +2704,17 @@ void tcp_get_info(struct sock *sk, struc
+ info->tcpi_total_retrans = tp->total_retrans;
+
+ rate = READ_ONCE(sk->sk_pacing_rate);
+- info->tcpi_pacing_rate = rate != ~0U ? rate : ~0ULL;
++ rate64 = rate != ~0U ? rate : ~0ULL;
++ put_unaligned(rate64, &info->tcpi_pacing_rate);
+
+ rate = READ_ONCE(sk->sk_max_pacing_rate);
+- info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL;
++ rate64 = rate != ~0U ? rate : ~0ULL;
++ put_unaligned(rate64, &info->tcpi_max_pacing_rate);
+
+ do {
+ start = u64_stats_fetch_begin_irq(&tp->syncp);
+- info->tcpi_bytes_acked = tp->bytes_acked;
+- info->tcpi_bytes_received = tp->bytes_received;
++ put_unaligned(tp->bytes_acked, &info->tcpi_bytes_acked);
++ put_unaligned(tp->bytes_received, &info->tcpi_bytes_received);
+ } while (u64_stats_fetch_retry_irq(&tp->syncp, start));
+ info->tcpi_segs_out = tp->segs_out;
+ info->tcpi_segs_in = tp->segs_in;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/tcp_ipv4.c linux-libre-4.4.7-gnu/net/ipv4/tcp_ipv4.c
+--- linux-libre-4.4-gnu/net/ipv4/tcp_ipv4.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/tcp_ipv4.c 2016-04-12 12:09:26.000000000 -0400
+@@ -312,7 +312,7 @@ static void do_redirect(struct sk_buff *
+
+
+ /* handle ICMP messages on TCP_NEW_SYN_RECV request sockets */
+-void tcp_req_err(struct sock *sk, u32 seq)
++void tcp_req_err(struct sock *sk, u32 seq, bool abort)
+ {
+ struct request_sock *req = inet_reqsk(sk);
+ struct net *net = sock_net(sk);
+@@ -324,7 +324,7 @@ void tcp_req_err(struct sock *sk, u32 se
+
+ if (seq != tcp_rsk(req)->snt_isn) {
+ NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
+- } else {
++ } else if (abort) {
+ /*
+ * Still in SYN_RECV, just remove it silently.
+ * There is no good way to pass the error to the newly
+@@ -384,7 +384,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb
+ }
+ seq = ntohl(th->seq);
+ if (sk->sk_state == TCP_NEW_SYN_RECV)
+- return tcp_req_err(sk, seq);
++ return tcp_req_err(sk, seq,
++ type == ICMP_PARAMETERPROB ||
++ type == ICMP_TIME_EXCEEDED ||
++ (type == ICMP_DEST_UNREACH &&
++ (code == ICMP_NET_UNREACH ||
++ code == ICMP_HOST_UNREACH)));
+
+ bh_lock_sock(sk);
+ /* If too many ICMPs get dropped on busy
+@@ -705,7 +710,8 @@ release_sk1:
+ outside socket context is ugly, certainly. What can I do?
+ */
+
+-static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
++static void tcp_v4_send_ack(struct net *net,
++ struct sk_buff *skb, u32 seq, u32 ack,
+ u32 win, u32 tsval, u32 tsecr, int oif,
+ struct tcp_md5sig_key *key,
+ int reply_flags, u8 tos)
+@@ -720,7 +726,6 @@ static void tcp_v4_send_ack(struct sk_bu
+ ];
+ } rep;
+ struct ip_reply_arg arg;
+- struct net *net = dev_net(skb_dst(skb)->dev);
+
+ memset(&rep.th, 0, sizeof(struct tcphdr));
+ memset(&arg, 0, sizeof(arg));
+@@ -782,7 +787,8 @@ static void tcp_v4_timewait_ack(struct s
+ struct inet_timewait_sock *tw = inet_twsk(sk);
+ struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
+
+- tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
++ tcp_v4_send_ack(sock_net(sk), skb,
++ tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+ tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
+ tcp_time_stamp + tcptw->tw_ts_offset,
+ tcptw->tw_ts_recent,
+@@ -801,8 +807,10 @@ static void tcp_v4_reqsk_send_ack(const
+ /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
+ * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
+ */
+- tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ?
+- tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
++ u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 :
++ tcp_sk(sk)->snd_nxt;
++
++ tcp_v4_send_ack(sock_net(sk), skb, seq,
+ tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd,
+ tcp_time_stamp,
+ req->ts_recent,
+@@ -1586,28 +1594,30 @@ process:
+
+ if (sk->sk_state == TCP_NEW_SYN_RECV) {
+ struct request_sock *req = inet_reqsk(sk);
+- struct sock *nsk = NULL;
++ struct sock *nsk;
+
+ sk = req->rsk_listener;
+- if (tcp_v4_inbound_md5_hash(sk, skb))
+- goto discard_and_relse;
+- if (likely(sk->sk_state == TCP_LISTEN)) {
+- nsk = tcp_check_req(sk, skb, req, false);
+- } else {
++ if (unlikely(tcp_v4_inbound_md5_hash(sk, skb))) {
++ reqsk_put(req);
++ goto discard_it;
++ }
++ if (unlikely(sk->sk_state != TCP_LISTEN)) {
+ inet_csk_reqsk_queue_drop_and_put(sk, req);
+ goto lookup;
+ }
++ sock_hold(sk);
++ nsk = tcp_check_req(sk, skb, req, false);
+ if (!nsk) {
+ reqsk_put(req);
+- goto discard_it;
++ goto discard_and_relse;
+ }
+ if (nsk == sk) {
+- sock_hold(sk);
+ reqsk_put(req);
+ } else if (tcp_child_process(sk, nsk, skb)) {
+ tcp_v4_send_reset(nsk, skb);
+- goto discard_it;
++ goto discard_and_relse;
+ } else {
++ sock_put(sk);
+ return 0;
+ }
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/tcp_yeah.c linux-libre-4.4.7-gnu/net/ipv4/tcp_yeah.c
+--- linux-libre-4.4-gnu/net/ipv4/tcp_yeah.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/tcp_yeah.c 2016-04-12 12:09:26.000000000 -0400
+@@ -219,7 +219,7 @@ static u32 tcp_yeah_ssthresh(struct sock
+ yeah->fast_count = 0;
+ yeah->reno_count = max(yeah->reno_count>>1, 2U);
+
+- return tp->snd_cwnd - reduction;
++ return max_t(int, tp->snd_cwnd - reduction, 2);
+ }
+
+ static struct tcp_congestion_ops tcp_yeah __read_mostly = {
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv4/udp.c linux-libre-4.4.7-gnu/net/ipv4/udp.c
+--- linux-libre-4.4-gnu/net/ipv4/udp.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv4/udp.c 2016-04-12 12:09:26.000000000 -0400
+@@ -966,8 +966,10 @@ int udp_sendmsg(struct sock *sk, struct
+ if (msg->msg_controllen) {
+ err = ip_cmsg_send(sock_net(sk), msg, &ipc,
+ sk->sk_family == AF_INET6);
+- if (err)
++ if (unlikely(err)) {
++ kfree(ipc.opt);
+ return err;
++ }
+ if (ipc.opt)
+ free = 1;
+ connected = 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv6/addrconf.c linux-libre-4.4.7-gnu/net/ipv6/addrconf.c
+--- linux-libre-4.4-gnu/net/ipv6/addrconf.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv6/addrconf.c 2016-04-12 12:09:26.000000000 -0400
+@@ -583,7 +583,7 @@ static int inet6_netconf_get_devconf(str
+ if (err < 0)
+ goto errout;
+
+- err = EINVAL;
++ err = -EINVAL;
+ if (!tb[NETCONFA_IFINDEX])
+ goto errout;
+
+@@ -3506,6 +3506,7 @@ static void addrconf_dad_begin(struct in
+ {
+ struct inet6_dev *idev = ifp->idev;
+ struct net_device *dev = idev->dev;
++ bool notify = false;
+
+ addrconf_join_solict(dev, &ifp->addr);
+
+@@ -3551,7 +3552,7 @@ static void addrconf_dad_begin(struct in
+ /* Because optimistic nodes can use this address,
+ * notify listeners. If DAD fails, RTM_DELADDR is sent.
+ */
+- ipv6_ifa_notify(RTM_NEWADDR, ifp);
++ notify = true;
+ }
+ }
+
+@@ -3559,6 +3560,8 @@ static void addrconf_dad_begin(struct in
+ out:
+ spin_unlock(&ifp->lock);
+ read_unlock_bh(&idev->lock);
++ if (notify)
++ ipv6_ifa_notify(RTM_NEWADDR, ifp);
+ }
+
+ static void addrconf_dad_start(struct inet6_ifaddr *ifp)
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv6/datagram.c linux-libre-4.4.7-gnu/net/ipv6/datagram.c
+--- linux-libre-4.4-gnu/net/ipv6/datagram.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv6/datagram.c 2016-04-12 12:09:26.000000000 -0400
+@@ -162,6 +162,9 @@ ipv4_connected:
+ fl6.fl6_dport = inet->inet_dport;
+ fl6.fl6_sport = inet->inet_sport;
+
++ if (!fl6.flowi6_oif)
++ fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
++
+ if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))
+ fl6.flowi6_oif = np->mcast_oif;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv6/ip6_flowlabel.c linux-libre-4.4.7-gnu/net/ipv6/ip6_flowlabel.c
+--- linux-libre-4.4-gnu/net/ipv6/ip6_flowlabel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv6/ip6_flowlabel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -540,12 +540,13 @@ int ipv6_flowlabel_opt(struct sock *sk,
+ }
+ spin_lock_bh(&ip6_sk_fl_lock);
+ for (sflp = &np->ipv6_fl_list;
+- (sfl = rcu_dereference(*sflp)) != NULL;
++ (sfl = rcu_dereference_protected(*sflp,
++ lockdep_is_held(&ip6_sk_fl_lock))) != NULL;
+ sflp = &sfl->next) {
+ if (sfl->fl->label == freq.flr_label) {
+ if (freq.flr_label == (np->flow_label&IPV6_FLOWLABEL_MASK))
+ np->flow_label &= ~IPV6_FLOWLABEL_MASK;
+- *sflp = rcu_dereference(sfl->next);
++ *sflp = sfl->next;
+ spin_unlock_bh(&ip6_sk_fl_lock);
+ fl_release(sfl->fl);
+ kfree_rcu(sfl, rcu);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv6/ip6_output.c linux-libre-4.4.7-gnu/net/ipv6/ip6_output.c
+--- linux-libre-4.4-gnu/net/ipv6/ip6_output.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv6/ip6_output.c 2016-04-12 12:09:26.000000000 -0400
+@@ -909,6 +909,7 @@ static int ip6_dst_lookup_tail(struct ne
+ struct rt6_info *rt;
+ #endif
+ int err;
++ int flags = 0;
+
+ /* The correct way to handle this would be to do
+ * ip6_route_get_saddr, and then ip6_route_output; however,
+@@ -940,10 +941,13 @@ static int ip6_dst_lookup_tail(struct ne
+ dst_release(*dst);
+ *dst = NULL;
+ }
++
++ if (fl6->flowi6_oif)
++ flags |= RT6_LOOKUP_F_IFACE;
+ }
+
+ if (!*dst)
+- *dst = ip6_route_output(net, sk, fl6);
++ *dst = ip6_route_output_flags(net, sk, fl6, flags);
+
+ err = (*dst)->error;
+ if (err)
+@@ -1353,7 +1357,7 @@ emsgsize:
+ (skb && skb_is_gso(skb))) &&
+ (sk->sk_protocol == IPPROTO_UDP) &&
+ (rt->dst.dev->features & NETIF_F_UFO) &&
+- (sk->sk_type == SOCK_DGRAM)) {
++ (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) {
+ err = ip6_ufo_append_data(sk, queue, getfrag, from, length,
+ hh_len, fragheaderlen,
+ transhdrlen, mtu, flags, fl6);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv6/route.c linux-libre-4.4.7-gnu/net/ipv6/route.c
+--- linux-libre-4.4-gnu/net/ipv6/route.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv6/route.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1174,11 +1174,10 @@ static struct rt6_info *ip6_pol_route_ou
+ return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
+ }
+
+-struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
+- struct flowi6 *fl6)
++struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
++ struct flowi6 *fl6, int flags)
+ {
+ struct dst_entry *dst;
+- int flags = 0;
+ bool any_src;
+
+ dst = l3mdev_rt6_dst_by_oif(net, fl6);
+@@ -1199,7 +1198,7 @@ struct dst_entry *ip6_route_output(struc
+
+ return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
+ }
+-EXPORT_SYMBOL(ip6_route_output);
++EXPORT_SYMBOL_GPL(ip6_route_output_flags);
+
+ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
+ {
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv6/tcp_ipv6.c linux-libre-4.4.7-gnu/net/ipv6/tcp_ipv6.c
+--- linux-libre-4.4-gnu/net/ipv6/tcp_ipv6.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv6/tcp_ipv6.c 2016-04-12 12:09:26.000000000 -0400
+@@ -328,6 +328,7 @@ static void tcp_v6_err(struct sk_buff *s
+ struct tcp_sock *tp;
+ __u32 seq, snd_una;
+ struct sock *sk;
++ bool fatal;
+ int err;
+
+ sk = __inet6_lookup_established(net, &tcp_hashinfo,
+@@ -346,8 +347,9 @@ static void tcp_v6_err(struct sk_buff *s
+ return;
+ }
+ seq = ntohl(th->seq);
++ fatal = icmpv6_err_convert(type, code, &err);
+ if (sk->sk_state == TCP_NEW_SYN_RECV)
+- return tcp_req_err(sk, seq);
++ return tcp_req_err(sk, seq, fatal);
+
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG)
+@@ -401,7 +403,6 @@ static void tcp_v6_err(struct sk_buff *s
+ goto out;
+ }
+
+- icmpv6_err_convert(type, code, &err);
+
+ /* Might be for an request_sock */
+ switch (sk->sk_state) {
+@@ -462,8 +463,10 @@ static int tcp_v6_send_synack(const stru
+ if (np->repflow && ireq->pktopts)
+ fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
+
++ rcu_read_lock();
+ err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
+ np->tclass);
++ rcu_read_unlock();
+ err = net_xmit_eval(err);
+ }
+
+@@ -1385,7 +1388,7 @@ process:
+
+ if (sk->sk_state == TCP_NEW_SYN_RECV) {
+ struct request_sock *req = inet_reqsk(sk);
+- struct sock *nsk = NULL;
++ struct sock *nsk;
+
+ sk = req->rsk_listener;
+ tcp_v6_fill_cb(skb, hdr, th);
+@@ -1393,24 +1396,24 @@ process:
+ reqsk_put(req);
+ goto discard_it;
+ }
+- if (likely(sk->sk_state == TCP_LISTEN)) {
+- nsk = tcp_check_req(sk, skb, req, false);
+- } else {
++ if (unlikely(sk->sk_state != TCP_LISTEN)) {
+ inet_csk_reqsk_queue_drop_and_put(sk, req);
+ goto lookup;
+ }
++ sock_hold(sk);
++ nsk = tcp_check_req(sk, skb, req, false);
+ if (!nsk) {
+ reqsk_put(req);
+- goto discard_it;
++ goto discard_and_relse;
+ }
+ if (nsk == sk) {
+- sock_hold(sk);
+ reqsk_put(req);
+ tcp_v6_restore_cb(skb);
+ } else if (tcp_child_process(sk, nsk, skb)) {
+ tcp_v6_send_reset(nsk, skb);
+- goto discard_it;
++ goto discard_and_relse;
+ } else {
++ sock_put(sk);
+ return 0;
+ }
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/ipv6/xfrm6_mode_tunnel.c linux-libre-4.4.7-gnu/net/ipv6/xfrm6_mode_tunnel.c
+--- linux-libre-4.4-gnu/net/ipv6/xfrm6_mode_tunnel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/ipv6/xfrm6_mode_tunnel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -23,7 +23,7 @@ static inline void ipip6_ecn_decapsulate
+ struct ipv6hdr *inner_iph = ipipv6_hdr(skb);
+
+ if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
+- IP6_ECN_set_ce(inner_iph);
++ IP6_ECN_set_ce(skb, inner_iph);
+ }
+
+ /* Add encapsulation header.
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/iucv/af_iucv.c linux-libre-4.4.7-gnu/net/iucv/af_iucv.c
+--- linux-libre-4.4-gnu/net/iucv/af_iucv.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/iucv/af_iucv.c 2016-04-12 12:09:26.000000000 -0400
+@@ -708,6 +708,9 @@ static int iucv_sock_bind(struct socket
+ if (!addr || addr->sa_family != AF_IUCV)
+ return -EINVAL;
+
++ if (addr_len < sizeof(struct sockaddr_iucv))
++ return -EINVAL;
++
+ lock_sock(sk);
+ if (sk->sk_state != IUCV_OPEN) {
+ err = -EBADFD;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/l2tp/l2tp_netlink.c linux-libre-4.4.7-gnu/net/l2tp/l2tp_netlink.c
+--- linux-libre-4.4-gnu/net/l2tp/l2tp_netlink.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/l2tp/l2tp_netlink.c 2016-04-12 12:09:26.000000000 -0400
+@@ -124,8 +124,13 @@ static int l2tp_tunnel_notify(struct gen
+ ret = l2tp_nl_tunnel_send(msg, info->snd_portid, info->snd_seq,
+ NLM_F_ACK, tunnel, cmd);
+
+- if (ret >= 0)
+- return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ if (ret >= 0) {
++ ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ /* We don't care if no one is listening */
++ if (ret == -ESRCH)
++ ret = 0;
++ return ret;
++ }
+
+ nlmsg_free(msg);
+
+@@ -147,8 +152,13 @@ static int l2tp_session_notify(struct ge
+ ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
+ NLM_F_ACK, session, cmd);
+
+- if (ret >= 0)
+- return genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ if (ret >= 0) {
++ ret = genlmsg_multicast_allns(family, msg, 0, 0, GFP_ATOMIC);
++ /* We don't care if no one is listening */
++ if (ret == -ESRCH)
++ ret = 0;
++ return ret;
++ }
+
+ nlmsg_free(msg);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/agg-rx.c linux-libre-4.4.7-gnu/net/mac80211/agg-rx.c
+--- linux-libre-4.4-gnu/net/mac80211/agg-rx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/agg-rx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -291,7 +291,7 @@ void __ieee80211_start_rx_ba_session(str
+ }
+
+ /* prepare A-MPDU MLME for Rx aggregation */
+- tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
++ tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
+ if (!tid_agg_rx)
+ goto end;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/ibss.c linux-libre-4.4.7-gnu/net/mac80211/ibss.c
+--- linux-libre-4.4-gnu/net/mac80211/ibss.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/ibss.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1732,7 +1732,6 @@ void ieee80211_ibss_notify_scan_complete
+ if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ continue;
+ sdata->u.ibss.last_scan_completed = jiffies;
+- ieee80211_queue_work(&local->hw, &sdata->work);
+ }
+ mutex_unlock(&local->iflist_mtx);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/ieee80211_i.h linux-libre-4.4.7-gnu/net/mac80211/ieee80211_i.h
+--- linux-libre-4.4-gnu/net/mac80211/ieee80211_i.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/ieee80211_i.h 2016-04-12 12:09:26.000000000 -0400
+@@ -92,7 +92,7 @@ struct ieee80211_fragment_entry {
+ u16 extra_len;
+ u16 last_frag;
+ u8 rx_queue;
+- bool ccmp; /* Whether fragments were encrypted with CCMP */
++ bool check_sequential_pn; /* needed for CCMP/GCMP */
+ u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+ };
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/mesh.c linux-libre-4.4.7-gnu/net/mac80211/mesh.c
+--- linux-libre-4.4-gnu/net/mac80211/mesh.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/mesh.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1370,17 +1370,6 @@ out:
+ sdata_unlock(sdata);
+ }
+
+-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
+-{
+- struct ieee80211_sub_if_data *sdata;
+-
+- rcu_read_lock();
+- list_for_each_entry_rcu(sdata, &local->interfaces, list)
+- if (ieee80211_vif_is_mesh(&sdata->vif) &&
+- ieee80211_sdata_running(sdata))
+- ieee80211_queue_work(&local->hw, &sdata->work);
+- rcu_read_unlock();
+-}
+
+ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
+ {
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/mesh.h linux-libre-4.4.7-gnu/net/mac80211/mesh.h
+--- linux-libre-4.4-gnu/net/mac80211/mesh.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/mesh.h 2016-04-12 12:09:26.000000000 -0400
+@@ -362,14 +362,10 @@ static inline bool mesh_path_sel_is_hwmp
+ return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP;
+ }
+
+-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
+-
+ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
+ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
+ void ieee80211s_stop(void);
+ #else
+-static inline void
+-ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
+ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
+ { return false; }
+ static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/mlme.c linux-libre-4.4.7-gnu/net/mac80211/mlme.c
+--- linux-libre-4.4-gnu/net/mac80211/mlme.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/mlme.c 2016-04-12 12:09:26.000000000 -0400
+@@ -4003,8 +4003,6 @@ static void ieee80211_restart_sta_timer(
+ if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR))
+ ieee80211_queue_work(&sdata->local->hw,
+ &sdata->u.mgd.monitor_work);
+- /* and do all the other regular work too */
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ }
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/rc80211_minstrel.c linux-libre-4.4.7-gnu/net/mac80211/rc80211_minstrel.c
+--- linux-libre-4.4-gnu/net/mac80211/rc80211_minstrel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/rc80211_minstrel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -711,7 +711,7 @@ static u32 minstrel_get_expected_through
+ * computing cur_tp
+ */
+ tmp_mrs = &mi->r[idx].stats;
+- tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma);
++ tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10;
+ tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
+
+ return tmp_cur_tp;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/rc80211_minstrel_ht.c linux-libre-4.4.7-gnu/net/mac80211/rc80211_minstrel_ht.c
+--- linux-libre-4.4-gnu/net/mac80211/rc80211_minstrel_ht.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/rc80211_minstrel_ht.c 2016-04-12 12:09:26.000000000 -0400
+@@ -691,7 +691,7 @@ minstrel_aggr_check(struct ieee80211_sta
+ if (likely(sta->ampdu_mlme.tid_tx[tid]))
+ return;
+
+- ieee80211_start_tx_ba_session(pubsta, tid, 5000);
++ ieee80211_start_tx_ba_session(pubsta, tid, 0);
+ }
+
+ static void
+@@ -871,7 +871,7 @@ minstrel_ht_set_rate(struct minstrel_pri
+ * - if station is in dynamic SMPS (and streams > 1)
+ * - for fallback rates, to increase chances of getting through
+ */
+- if (offset > 0 &&
++ if (offset > 0 ||
+ (mi->sta->smps_mode == IEEE80211_SMPS_DYNAMIC &&
+ group->streams > 1)) {
+ ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
+@@ -1334,7 +1334,8 @@ static u32 minstrel_ht_get_expected_thro
+ prob = mi->groups[i].rates[j].prob_ewma;
+
+ /* convert tp_avg from pkt per second in kbps */
+- tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * AVG_PKT_SIZE * 8 / 1024;
++ tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10;
++ tp_avg = tp_avg * AVG_PKT_SIZE * 8 / 1024;
+
+ return tp_avg;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/rx.c linux-libre-4.4.7-gnu/net/mac80211/rx.c
+--- linux-libre-4.4-gnu/net/mac80211/rx.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/rx.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1754,7 +1754,7 @@ ieee80211_reassemble_add(struct ieee8021
+ entry->seq = seq;
+ entry->rx_queue = rx_queue;
+ entry->last_frag = frag;
+- entry->ccmp = 0;
++ entry->check_sequential_pn = false;
+ entry->extra_len = 0;
+
+ return entry;
+@@ -1850,15 +1850,27 @@ ieee80211_rx_h_defragment(struct ieee802
+ rx->seqno_idx, &(rx->skb));
+ if (rx->key &&
+ (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
+- rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) &&
++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
+ ieee80211_has_protected(fc)) {
+ int queue = rx->security_idx;
+- /* Store CCMP PN so that we can verify that the next
+- * fragment has a sequential PN value. */
+- entry->ccmp = 1;
++
++ /* Store CCMP/GCMP PN so that we can verify that the
++ * next fragment has a sequential PN value.
++ */
++ entry->check_sequential_pn = true;
+ memcpy(entry->last_pn,
+ rx->key->u.ccmp.rx_pn[queue],
+ IEEE80211_CCMP_PN_LEN);
++ BUILD_BUG_ON(offsetof(struct ieee80211_key,
++ u.ccmp.rx_pn) !=
++ offsetof(struct ieee80211_key,
++ u.gcmp.rx_pn));
++ BUILD_BUG_ON(sizeof(rx->key->u.ccmp.rx_pn[queue]) !=
++ sizeof(rx->key->u.gcmp.rx_pn[queue]));
++ BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
++ IEEE80211_GCMP_PN_LEN);
+ }
+ return RX_QUEUED;
+ }
+@@ -1873,15 +1885,21 @@ ieee80211_rx_h_defragment(struct ieee802
+ return RX_DROP_MONITOR;
+ }
+
+- /* Verify that MPDUs within one MSDU have sequential PN values.
+- * (IEEE 802.11i, 8.3.3.4.5) */
+- if (entry->ccmp) {
++ /* "The receiver shall discard MSDUs and MMPDUs whose constituent
++ * MPDU PN values are not incrementing in steps of 1."
++ * see IEEE P802.11-REVmc/D5.0, 12.5.3.4.4, item d (for CCMP)
++ * and IEEE P802.11-REVmc/D5.0, 12.5.5.4.4, item d (for GCMP)
++ */
++ if (entry->check_sequential_pn) {
+ int i;
+ u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
+ int queue;
++
+ if (!rx->key ||
+ (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
+- rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256))
++ rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
++ rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
++ rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
+ return RX_DROP_UNUSABLE;
+ memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+ for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
+@@ -3367,6 +3385,7 @@ static bool ieee80211_accept_frame(struc
+ return false;
+ /* ignore action frames to TDLS-peers */
+ if (ieee80211_is_action(hdr->frame_control) &&
++ !is_broadcast_ether_addr(bssid) &&
+ !ether_addr_equal(bssid, hdr->addr1))
+ return false;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/mac80211/scan.c linux-libre-4.4.7-gnu/net/mac80211/scan.c
+--- linux-libre-4.4-gnu/net/mac80211/scan.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/mac80211/scan.c 2016-04-12 12:09:26.000000000 -0400
+@@ -314,6 +314,7 @@ static void __ieee80211_scan_completed(s
+ bool was_scanning = local->scanning;
+ struct cfg80211_scan_request *scan_req;
+ struct ieee80211_sub_if_data *scan_sdata;
++ struct ieee80211_sub_if_data *sdata;
+
+ lockdep_assert_held(&local->mtx);
+
+@@ -373,7 +374,16 @@ static void __ieee80211_scan_completed(s
+
+ ieee80211_mlme_notify_scan_completed(local);
+ ieee80211_ibss_notify_scan_completed(local);
+- ieee80211_mesh_notify_scan_completed(local);
++
++ /* Requeue all the work that might have been ignored while
++ * the scan was in progress; if there was none this will
++ * just be a no-op for the particular interface.
++ */
++ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
++ if (ieee80211_sdata_running(sdata))
++ ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ }
++
+ if (was_scanning)
+ ieee80211_start_next_roc(local);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/openvswitch/datapath.c linux-libre-4.4.7-gnu/net/openvswitch/datapath.c
+--- linux-libre-4.4-gnu/net/openvswitch/datapath.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/openvswitch/datapath.c 2016-04-12 12:09:26.000000000 -0400
+@@ -336,12 +336,10 @@ static int queue_gso_packets(struct data
+ unsigned short gso_type = skb_shinfo(skb)->gso_type;
+ struct sw_flow_key later_key;
+ struct sk_buff *segs, *nskb;
+- struct ovs_skb_cb ovs_cb;
+ int err;
+
+- ovs_cb = *OVS_CB(skb);
++ BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_SGO_CB_OFFSET);
+ segs = __skb_gso_segment(skb, NETIF_F_SG, false);
+- *OVS_CB(skb) = ovs_cb;
+ if (IS_ERR(segs))
+ return PTR_ERR(segs);
+ if (segs == NULL)
+@@ -359,7 +357,6 @@ static int queue_gso_packets(struct data
+ /* Queue all of the segments. */
+ skb = segs;
+ do {
+- *OVS_CB(skb) = ovs_cb;
+ if (gso_type & SKB_GSO_UDP && skb != segs)
+ key = &later_key;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/openvswitch/vport-vxlan.c linux-libre-4.4.7-gnu/net/openvswitch/vport-vxlan.c
+--- linux-libre-4.4-gnu/net/openvswitch/vport-vxlan.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/openvswitch/vport-vxlan.c 2016-04-12 12:09:26.000000000 -0400
+@@ -90,7 +90,7 @@ static struct vport *vxlan_tnl_create(co
+ int err;
+ struct vxlan_config conf = {
+ .no_share = true,
+- .flags = VXLAN_F_COLLECT_METADATA,
++ .flags = VXLAN_F_COLLECT_METADATA | VXLAN_F_UDP_ZERO_CSUM6_RX,
+ };
+
+ if (!options) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/phonet/af_phonet.c linux-libre-4.4.7-gnu/net/phonet/af_phonet.c
+--- linux-libre-4.4-gnu/net/phonet/af_phonet.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/phonet/af_phonet.c 2016-04-12 12:09:26.000000000 -0400
+@@ -377,6 +377,10 @@ static int phonet_rcv(struct sk_buff *sk
+ struct sockaddr_pn sa;
+ u16 len;
+
++ skb = skb_share_check(skb, GFP_ATOMIC);
++ if (!skb)
++ return NET_RX_DROP;
++
+ /* check we have at least a full Phonet header */
+ if (!pskb_pull(skb, sizeof(struct phonethdr)))
+ goto out;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/rfkill/core.c linux-libre-4.4.7-gnu/net/rfkill/core.c
+--- linux-libre-4.4-gnu/net/rfkill/core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/rfkill/core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1095,17 +1095,6 @@ static unsigned int rfkill_fop_poll(stru
+ return res;
+ }
+
+-static bool rfkill_readable(struct rfkill_data *data)
+-{
+- bool r;
+-
+- mutex_lock(&data->mtx);
+- r = !list_empty(&data->events);
+- mutex_unlock(&data->mtx);
+-
+- return r;
+-}
+-
+ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+ {
+@@ -1122,8 +1111,11 @@ static ssize_t rfkill_fop_read(struct fi
+ goto out;
+ }
+ mutex_unlock(&data->mtx);
++ /* since we re-check and it just compares pointers,
++ * using !list_empty() without locking isn't a problem
++ */
+ ret = wait_event_interruptible(data->read_wait,
+- rfkill_readable(data));
++ !list_empty(&data->events));
+ mutex_lock(&data->mtx);
+
+ if (ret)
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/sched/cls_flower.c linux-libre-4.4.7-gnu/net/sched/cls_flower.c
+--- linux-libre-4.4-gnu/net/sched/cls_flower.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/sched/cls_flower.c 2016-04-12 12:09:26.000000000 -0400
+@@ -252,23 +252,28 @@ static int fl_set_key(struct net *net, s
+ fl_set_key_val(tb, key->eth.src, TCA_FLOWER_KEY_ETH_SRC,
+ mask->eth.src, TCA_FLOWER_KEY_ETH_SRC_MASK,
+ sizeof(key->eth.src));
++
+ fl_set_key_val(tb, &key->basic.n_proto, TCA_FLOWER_KEY_ETH_TYPE,
+ &mask->basic.n_proto, TCA_FLOWER_UNSPEC,
+ sizeof(key->basic.n_proto));
++
+ if (key->basic.n_proto == htons(ETH_P_IP) ||
+ key->basic.n_proto == htons(ETH_P_IPV6)) {
+ fl_set_key_val(tb, &key->basic.ip_proto, TCA_FLOWER_KEY_IP_PROTO,
+ &mask->basic.ip_proto, TCA_FLOWER_UNSPEC,
+ sizeof(key->basic.ip_proto));
+ }
+- if (key->control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
++
++ if (tb[TCA_FLOWER_KEY_IPV4_SRC] || tb[TCA_FLOWER_KEY_IPV4_DST]) {
++ key->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
+ fl_set_key_val(tb, &key->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC,
+ &mask->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC_MASK,
+ sizeof(key->ipv4.src));
+ fl_set_key_val(tb, &key->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST,
+ &mask->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST_MASK,
+ sizeof(key->ipv4.dst));
+- } else if (key->control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
++ } else if (tb[TCA_FLOWER_KEY_IPV6_SRC] || tb[TCA_FLOWER_KEY_IPV6_DST]) {
++ key->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
+ fl_set_key_val(tb, &key->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC,
+ &mask->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC_MASK,
+ sizeof(key->ipv6.src));
+@@ -276,6 +281,7 @@ static int fl_set_key(struct net *net, s
+ &mask->ipv6.dst, TCA_FLOWER_KEY_IPV6_DST_MASK,
+ sizeof(key->ipv6.dst));
+ }
++
+ if (key->basic.ip_proto == IPPROTO_TCP) {
+ fl_set_key_val(tb, &key->tp.src, TCA_FLOWER_KEY_TCP_SRC,
+ &mask->tp.src, TCA_FLOWER_UNSPEC,
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/sched/sch_api.c linux-libre-4.4.7-gnu/net/sched/sch_api.c
+--- linux-libre-4.4-gnu/net/sched/sch_api.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/sched/sch_api.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1852,6 +1852,7 @@ reset:
+ }
+
+ tp = old_tp;
++ protocol = tc_skb_protocol(skb);
+ goto reclassify;
+ #endif
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/sctp/protocol.c linux-libre-4.4.7-gnu/net/sctp/protocol.c
+--- linux-libre-4.4-gnu/net/sctp/protocol.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/sctp/protocol.c 2016-04-12 12:09:26.000000000 -0400
+@@ -60,6 +60,8 @@
+ #include <net/inet_common.h>
+ #include <net/inet_ecn.h>
+
++#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)
++
+ /* Global data structures. */
+ struct sctp_globals sctp_globals __read_mostly;
+
+@@ -1352,6 +1354,8 @@ static __init int sctp_init(void)
+ unsigned long limit;
+ int max_share;
+ int order;
++ int num_entries;
++ int max_entry_order;
+
+ sock_skb_cb_check_size(sizeof(struct sctp_ulpevent));
+
+@@ -1404,14 +1408,24 @@ static __init int sctp_init(void)
+
+ /* Size and allocate the association hash table.
+ * The methodology is similar to that of the tcp hash tables.
++ * Though not identical. Start by getting a goal size
+ */
+ if (totalram_pages >= (128 * 1024))
+ goal = totalram_pages >> (22 - PAGE_SHIFT);
+ else
+ goal = totalram_pages >> (24 - PAGE_SHIFT);
+
+- for (order = 0; (1UL << order) < goal; order++)
+- ;
++ /* Then compute the page order for said goal */
++ order = get_order(goal);
++
++ /* Now compute the required page order for the maximum sized table we
++ * want to create
++ */
++ max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES *
++ sizeof(struct sctp_bind_hashbucket));
++
++ /* Limit the page order by that maximum hash table size */
++ order = min(order, max_entry_order);
+
+ do {
+ sctp_assoc_hashsize = (1UL << order) * PAGE_SIZE /
+@@ -1445,20 +1459,35 @@ static __init int sctp_init(void)
+ INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
+ }
+
+- /* Allocate and initialize the SCTP port hash table. */
++ /* Allocate and initialize the SCTP port hash table.
++ * Note that order is initalized to start at the max sized
++ * table we want to support. If we can't get that many pages
++ * reduce the order and try again
++ */
+ do {
+- sctp_port_hashsize = (1UL << order) * PAGE_SIZE /
+- sizeof(struct sctp_bind_hashbucket);
+- if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
+- continue;
+ sctp_port_hashtable = (struct sctp_bind_hashbucket *)
+ __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order);
+ } while (!sctp_port_hashtable && --order > 0);
++
+ if (!sctp_port_hashtable) {
+ pr_err("Failed bind hash alloc\n");
+ status = -ENOMEM;
+ goto err_bhash_alloc;
+ }
++
++ /* Now compute the number of entries that will fit in the
++ * port hash space we allocated
++ */
++ num_entries = (1UL << order) * PAGE_SIZE /
++ sizeof(struct sctp_bind_hashbucket);
++
++ /* And finish by rounding it down to the nearest power of two
++ * this wastes some memory of course, but its needed because
++ * the hash function operates based on the assumption that
++ * that the number of entries is a power of two
++ */
++ sctp_port_hashsize = rounddown_pow_of_two(num_entries);
++
+ for (i = 0; i < sctp_port_hashsize; i++) {
+ spin_lock_init(&sctp_port_hashtable[i].lock);
+ INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/sctp/socket.c linux-libre-4.4.7-gnu/net/sctp/socket.c
+--- linux-libre-4.4-gnu/net/sctp/socket.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/sctp/socket.c 2016-04-12 12:09:26.000000000 -0400
+@@ -5542,6 +5542,7 @@ static int sctp_getsockopt_hmac_ident(st
+ struct sctp_hmac_algo_param *hmacs;
+ __u16 data_len = 0;
+ u32 num_idents;
++ int i;
+
+ if (!ep->auth_enable)
+ return -EACCES;
+@@ -5559,8 +5560,12 @@ static int sctp_getsockopt_hmac_ident(st
+ return -EFAULT;
+ if (put_user(num_idents, &p->shmac_num_idents))
+ return -EFAULT;
+- if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
+- return -EFAULT;
++ for (i = 0; i < num_idents; i++) {
++ __u16 hmacid = ntohs(hmacs->hmac_ids[i]);
++
++ if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16)))
++ return -EFAULT;
++ }
+ return 0;
+ }
+
+@@ -6640,6 +6645,7 @@ static int sctp_msghdr_parse(const struc
+
+ if (cmsgs->srinfo->sinfo_flags &
+ ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
++ SCTP_SACK_IMMEDIATELY |
+ SCTP_ABORT | SCTP_EOF))
+ return -EINVAL;
+ break;
+@@ -6663,6 +6669,7 @@ static int sctp_msghdr_parse(const struc
+
+ if (cmsgs->sinfo->snd_flags &
+ ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
++ SCTP_SACK_IMMEDIATELY |
+ SCTP_ABORT | SCTP_EOF))
+ return -EINVAL;
+ break;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/sctp/sysctl.c linux-libre-4.4.7-gnu/net/sctp/sysctl.c
+--- linux-libre-4.4-gnu/net/sctp/sysctl.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/sctp/sysctl.c 2016-04-12 12:09:26.000000000 -0400
+@@ -320,7 +320,7 @@ static int proc_sctp_do_hmac_alg(struct
+ struct ctl_table tbl;
+ bool changed = false;
+ char *none = "none";
+- char tmp[8];
++ char tmp[8] = {0};
+ int ret;
+
+ memset(&tbl, 0, sizeof(struct ctl_table));
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/sunrpc/cache.c linux-libre-4.4.7-gnu/net/sunrpc/cache.c
+--- linux-libre-4.4-gnu/net/sunrpc/cache.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/sunrpc/cache.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1225,7 +1225,7 @@ int qword_get(char **bpp, char *dest, in
+ if (bp[0] == '\\' && bp[1] == 'x') {
+ /* HEX STRING */
+ bp += 2;
+- while (len < bufsize) {
++ while (len < bufsize - 1) {
+ int h, l;
+
+ h = hex_to_bin(bp[0]);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/sunrpc/xprtsock.c linux-libre-4.4.7-gnu/net/sunrpc/xprtsock.c
+--- linux-libre-4.4-gnu/net/sunrpc/xprtsock.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/sunrpc/xprtsock.c 2016-04-12 12:09:26.000000000 -0400
+@@ -398,7 +398,6 @@ static int xs_sendpages(struct socket *s
+ if (unlikely(!sock))
+ return -ENOTSOCK;
+
+- clear_bit(SOCKWQ_ASYNC_NOSPACE, &sock->flags);
+ if (base != 0) {
+ addr = NULL;
+ addrlen = 0;
+@@ -442,7 +441,6 @@ static void xs_nospace_callback(struct r
+ struct sock_xprt *transport = container_of(task->tk_rqstp->rq_xprt, struct sock_xprt, xprt);
+
+ transport->inet->sk_write_pending--;
+- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
+ }
+
+ /**
+@@ -467,20 +465,11 @@ static int xs_nospace(struct rpc_task *t
+
+ /* Don't race with disconnect */
+ if (xprt_connected(xprt)) {
+- if (test_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags)) {
+- /*
+- * Notify TCP that we're limited by the application
+- * window size
+- */
+- set_bit(SOCK_NOSPACE, &transport->sock->flags);
+- sk->sk_write_pending++;
+- /* ...and wait for more buffer space */
+- xprt_wait_for_buffer_space(task, xs_nospace_callback);
+- }
+- } else {
+- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
++ /* wait for more buffer space */
++ sk->sk_write_pending++;
++ xprt_wait_for_buffer_space(task, xs_nospace_callback);
++ } else
+ ret = -ENOTCONN;
+- }
+
+ spin_unlock_bh(&xprt->transport_lock);
+
+@@ -616,9 +605,6 @@ process_status:
+ case -EAGAIN:
+ status = xs_nospace(task);
+ break;
+- default:
+- dprintk("RPC: sendmsg returned unrecognized error %d\n",
+- -status);
+ case -ENETUNREACH:
+ case -ENOBUFS:
+ case -EPIPE:
+@@ -626,7 +612,10 @@ process_status:
+ case -EPERM:
+ /* When the server has died, an ICMP port unreachable message
+ * prompts ECONNREFUSED. */
+- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
++ break;
++ default:
++ dprintk("RPC: sendmsg returned unrecognized error %d\n",
++ -status);
+ }
+
+ return status;
+@@ -706,16 +695,16 @@ static int xs_tcp_send_request(struct rp
+ case -EAGAIN:
+ status = xs_nospace(task);
+ break;
+- default:
+- dprintk("RPC: sendmsg returned unrecognized error %d\n",
+- -status);
+ case -ECONNRESET:
+ case -ECONNREFUSED:
+ case -ENOTCONN:
+ case -EADDRINUSE:
+ case -ENOBUFS:
+ case -EPIPE:
+- clear_bit(SOCKWQ_ASYNC_NOSPACE, &transport->sock->flags);
++ break;
++ default:
++ dprintk("RPC: sendmsg returned unrecognized error %d\n",
++ -status);
+ }
+
+ return status;
+@@ -1609,19 +1598,23 @@ static void xs_tcp_state_change(struct s
+
+ static void xs_write_space(struct sock *sk)
+ {
+- struct socket *sock;
++ struct socket_wq *wq;
+ struct rpc_xprt *xprt;
+
+- if (unlikely(!(sock = sk->sk_socket)))
++ if (!sk->sk_socket)
+ return;
+- clear_bit(SOCK_NOSPACE, &sock->flags);
++ clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+
+ if (unlikely(!(xprt = xprt_from_sock(sk))))
+ return;
+- if (test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &sock->flags) == 0)
+- return;
++ rcu_read_lock();
++ wq = rcu_dereference(sk->sk_wq);
++ if (!wq || test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags) == 0)
++ goto out;
+
+ xprt_write_space(xprt);
++out:
++ rcu_read_unlock();
+ }
+
+ /**
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/switchdev/switchdev.c linux-libre-4.4.7-gnu/net/switchdev/switchdev.c
+--- linux-libre-4.4-gnu/net/switchdev/switchdev.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/switchdev/switchdev.c 2016-04-12 12:09:26.000000000 -0400
+@@ -20,6 +20,7 @@
+ #include <linux/list.h>
+ #include <linux/workqueue.h>
+ #include <linux/if_vlan.h>
++#include <linux/rtnetlink.h>
+ #include <net/ip_fib.h>
+ #include <net/switchdev.h>
+
+@@ -565,7 +566,6 @@ int switchdev_port_obj_dump(struct net_d
+ }
+ EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
+
+-static DEFINE_MUTEX(switchdev_mutex);
+ static RAW_NOTIFIER_HEAD(switchdev_notif_chain);
+
+ /**
+@@ -580,9 +580,9 @@ int register_switchdev_notifier(struct n
+ {
+ int err;
+
+- mutex_lock(&switchdev_mutex);
++ rtnl_lock();
+ err = raw_notifier_chain_register(&switchdev_notif_chain, nb);
+- mutex_unlock(&switchdev_mutex);
++ rtnl_unlock();
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(register_switchdev_notifier);
+@@ -598,9 +598,9 @@ int unregister_switchdev_notifier(struct
+ {
+ int err;
+
+- mutex_lock(&switchdev_mutex);
++ rtnl_lock();
+ err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb);
+- mutex_unlock(&switchdev_mutex);
++ rtnl_unlock();
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
+@@ -614,16 +614,17 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_n
+ * Call all network notifier blocks. This should be called by driver
+ * when it needs to propagate hardware event.
+ * Return values are same as for atomic_notifier_call_chain().
++ * rtnl_lock must be held.
+ */
+ int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
+ struct switchdev_notifier_info *info)
+ {
+ int err;
+
++ ASSERT_RTNL();
++
+ info->dev = dev;
+- mutex_lock(&switchdev_mutex);
+ err = raw_notifier_call_chain(&switchdev_notif_chain, val, info);
+- mutex_unlock(&switchdev_mutex);
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/tipc/bcast.c linux-libre-4.4.7-gnu/net/tipc/bcast.c
+--- linux-libre-4.4-gnu/net/tipc/bcast.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/tipc/bcast.c 2016-04-12 12:09:26.000000000 -0400
+@@ -399,8 +399,10 @@ int tipc_nl_add_bc_link(struct net *net,
+
+ hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
+ NLM_F_MULTI, TIPC_NL_LINK_GET);
+- if (!hdr)
++ if (!hdr) {
++ tipc_bcast_unlock(net);
+ return -EMSGSIZE;
++ }
+
+ attrs = nla_nest_start(msg->skb, TIPC_NLA_LINK);
+ if (!attrs)
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/tipc/node.c linux-libre-4.4.7-gnu/net/tipc/node.c
+--- linux-libre-4.4-gnu/net/tipc/node.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/tipc/node.c 2016-04-12 12:09:26.000000000 -0400
+@@ -168,12 +168,6 @@ struct tipc_node *tipc_node_create(struc
+ skb_queue_head_init(&n_ptr->bc_entry.inputq1);
+ __skb_queue_head_init(&n_ptr->bc_entry.arrvq);
+ skb_queue_head_init(&n_ptr->bc_entry.inputq2);
+- hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]);
+- list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
+- if (n_ptr->addr < temp_node->addr)
+- break;
+- }
+- list_add_tail_rcu(&n_ptr->list, &temp_node->list);
+ n_ptr->state = SELF_DOWN_PEER_LEAVING;
+ n_ptr->signature = INVALID_NODE_SIG;
+ n_ptr->active_links[0] = INVALID_BEARER_ID;
+@@ -193,6 +187,12 @@ struct tipc_node *tipc_node_create(struc
+ tipc_node_get(n_ptr);
+ setup_timer(&n_ptr->timer, tipc_node_timeout, (unsigned long)n_ptr);
+ n_ptr->keepalive_intv = U32_MAX;
++ hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]);
++ list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
++ if (n_ptr->addr < temp_node->addr)
++ break;
++ }
++ list_add_tail_rcu(&n_ptr->list, &temp_node->list);
+ exit:
+ spin_unlock_bh(&tn->node_list_lock);
+ return n_ptr;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/tipc/subscr.c linux-libre-4.4.7-gnu/net/tipc/subscr.c
+--- linux-libre-4.4-gnu/net/tipc/subscr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/tipc/subscr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -289,15 +289,14 @@ static void tipc_subscrb_rcv_cb(struct n
+ struct sockaddr_tipc *addr, void *usr_data,
+ void *buf, size_t len)
+ {
+- struct tipc_subscriber *subscriber = usr_data;
++ struct tipc_subscriber *subscrb = usr_data;
+ struct tipc_subscription *sub = NULL;
+ struct tipc_net *tn = net_generic(net, tipc_net_id);
+
+- tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscriber, &sub);
+- if (sub)
+- tipc_nametbl_subscribe(sub);
+- else
+- tipc_conn_terminate(tn->topsrv, subscriber->conid);
++ if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub))
++ return tipc_conn_terminate(tn->topsrv, subscrb->conid);
++
++ tipc_nametbl_subscribe(sub);
+ }
+
+ /* Handle one request to establish a new subscriber */
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/unix/af_unix.c linux-libre-4.4.7-gnu/net/unix/af_unix.c
+--- linux-libre-4.4-gnu/net/unix/af_unix.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/unix/af_unix.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1496,7 +1496,7 @@ static void unix_detach_fds(struct scm_c
+ UNIXCB(skb).fp = NULL;
+
+ for (i = scm->fp->count-1; i >= 0; i--)
+- unix_notinflight(scm->fp->fp[i]);
++ unix_notinflight(scm->fp->user, scm->fp->fp[i]);
+ }
+
+ static void unix_destruct_scm(struct sk_buff *skb)
+@@ -1513,6 +1513,21 @@ static void unix_destruct_scm(struct sk_
+ sock_wfree(skb);
+ }
+
++/*
++ * The "user->unix_inflight" variable is protected by the garbage
++ * collection lock, and we just read it locklessly here. If you go
++ * over the limit, there might be a tiny race in actually noticing
++ * it across threads. Tough.
++ */
++static inline bool too_many_unix_fds(struct task_struct *p)
++{
++ struct user_struct *user = current_user();
++
++ if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)))
++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
++ return false;
++}
++
+ #define MAX_RECURSION_LEVEL 4
+
+ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
+@@ -1521,6 +1536,9 @@ static int unix_attach_fds(struct scm_co
+ unsigned char max_level = 0;
+ int unix_sock_count = 0;
+
++ if (too_many_unix_fds(current))
++ return -ETOOMANYREFS;
++
+ for (i = scm->fp->count - 1; i >= 0; i--) {
+ struct sock *sk = unix_get_socket(scm->fp->fp[i]);
+
+@@ -1542,10 +1560,8 @@ static int unix_attach_fds(struct scm_co
+ if (!UNIXCB(skb).fp)
+ return -ENOMEM;
+
+- if (unix_sock_count) {
+- for (i = scm->fp->count - 1; i >= 0; i--)
+- unix_inflight(scm->fp->fp[i]);
+- }
++ for (i = scm->fp->count - 1; i >= 0; i--)
++ unix_inflight(scm->fp->user, scm->fp->fp[i]);
+ return max_level;
+ }
+
+@@ -1765,7 +1781,12 @@ restart_locked:
+ goto out_unlock;
+ }
+
+- if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
++ /* other == sk && unix_peer(other) != sk if
++ * - unix_peer(sk) == NULL, destination address bound to sk
++ * - unix_peer(sk) == sk by time of get but disconnected before lock
++ */
++ if (other != sk &&
++ unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
+ if (timeo) {
+ timeo = unix_wait_for_peer(other, timeo);
+
+@@ -2254,13 +2275,15 @@ static int unix_stream_read_generic(stru
+ size_t size = state->size;
+ unsigned int last_len;
+
+- err = -EINVAL;
+- if (sk->sk_state != TCP_ESTABLISHED)
++ if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
++ err = -EINVAL;
+ goto out;
++ }
+
+- err = -EOPNOTSUPP;
+- if (flags & MSG_OOB)
++ if (unlikely(flags & MSG_OOB)) {
++ err = -EOPNOTSUPP;
+ goto out;
++ }
+
+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
+ timeo = sock_rcvtimeo(sk, noblock);
+@@ -2306,9 +2329,11 @@ again:
+ goto unlock;
+
+ unix_state_unlock(sk);
+- err = -EAGAIN;
+- if (!timeo)
++ if (!timeo) {
++ err = -EAGAIN;
+ break;
++ }
++
+ mutex_unlock(&u->readlock);
+
+ timeo = unix_stream_data_wait(sk, timeo, last,
+@@ -2316,6 +2341,7 @@ again:
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
++ scm_destroy(&scm);
+ goto out;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/unix/diag.c linux-libre-4.4.7-gnu/net/unix/diag.c
+--- linux-libre-4.4-gnu/net/unix/diag.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/unix/diag.c 2016-04-12 12:09:26.000000000 -0400
+@@ -220,7 +220,7 @@ done:
+ return skb->len;
+ }
+
+-static struct sock *unix_lookup_by_ino(int ino)
++static struct sock *unix_lookup_by_ino(unsigned int ino)
+ {
+ int i;
+ struct sock *sk;
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/unix/garbage.c linux-libre-4.4.7-gnu/net/unix/garbage.c
+--- linux-libre-4.4-gnu/net/unix/garbage.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/unix/garbage.c 2016-04-12 12:09:26.000000000 -0400
+@@ -116,15 +116,15 @@ struct sock *unix_get_socket(struct file
+ * descriptor if it is for an AF_UNIX socket.
+ */
+
+-void unix_inflight(struct file *fp)
++void unix_inflight(struct user_struct *user, struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
+
++ spin_lock(&unix_gc_lock);
++
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+
+- spin_lock(&unix_gc_lock);
+-
+ if (atomic_long_inc_return(&u->inflight) == 1) {
+ BUG_ON(!list_empty(&u->link));
+ list_add_tail(&u->link, &gc_inflight_list);
+@@ -132,25 +132,28 @@ void unix_inflight(struct file *fp)
+ BUG_ON(list_empty(&u->link));
+ }
+ unix_tot_inflight++;
+- spin_unlock(&unix_gc_lock);
+ }
++ user->unix_inflight++;
++ spin_unlock(&unix_gc_lock);
+ }
+
+-void unix_notinflight(struct file *fp)
++void unix_notinflight(struct user_struct *user, struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
+
++ spin_lock(&unix_gc_lock);
++
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+
+- spin_lock(&unix_gc_lock);
+ BUG_ON(list_empty(&u->link));
+
+ if (atomic_long_dec_and_test(&u->inflight))
+ list_del_init(&u->link);
+ unix_tot_inflight--;
+- spin_unlock(&unix_gc_lock);
+ }
++ user->unix_inflight--;
++ spin_unlock(&unix_gc_lock);
+ }
+
+ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/wireless/core.c linux-libre-4.4.7-gnu/net/wireless/core.c
+--- linux-libre-4.4-gnu/net/wireless/core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/wireless/core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1147,6 +1147,8 @@ static int cfg80211_netdev_notifier_call
+ return NOTIFY_DONE;
+ }
+
++ wireless_nlevent_flush();
++
+ return NOTIFY_OK;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/wireless/wext-core.c linux-libre-4.4.7-gnu/net/wireless/wext-core.c
+--- linux-libre-4.4-gnu/net/wireless/wext-core.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/wireless/wext-core.c 2016-04-12 12:09:26.000000000 -0400
+@@ -342,6 +342,40 @@ static const int compat_event_type_size[
+
+ /* IW event code */
+
++void wireless_nlevent_flush(void)
++{
++ struct sk_buff *skb;
++ struct net *net;
++
++ ASSERT_RTNL();
++
++ for_each_net(net) {
++ while ((skb = skb_dequeue(&net->wext_nlevents)))
++ rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
++ GFP_KERNEL);
++ }
++}
++EXPORT_SYMBOL_GPL(wireless_nlevent_flush);
++
++static int wext_netdev_notifier_call(struct notifier_block *nb,
++ unsigned long state, void *ptr)
++{
++ /*
++ * When a netdev changes state in any way, flush all pending messages
++ * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
++ * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
++ * or similar - all of which could otherwise happen due to delays from
++ * schedule_work().
++ */
++ wireless_nlevent_flush();
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wext_netdev_notifier = {
++ .notifier_call = wext_netdev_notifier_call,
++};
++
+ static int __net_init wext_pernet_init(struct net *net)
+ {
+ skb_queue_head_init(&net->wext_nlevents);
+@@ -360,7 +394,12 @@ static struct pernet_operations wext_per
+
+ static int __init wireless_nlevent_init(void)
+ {
+- return register_pernet_subsys(&wext_pernet_ops);
++ int err = register_pernet_subsys(&wext_pernet_ops);
++
++ if (err)
++ return err;
++
++ return register_netdevice_notifier(&wext_netdev_notifier);
+ }
+
+ subsys_initcall(wireless_nlevent_init);
+@@ -368,17 +407,8 @@ subsys_initcall(wireless_nlevent_init);
+ /* Process events generated by the wireless layer or the driver. */
+ static void wireless_nlevent_process(struct work_struct *work)
+ {
+- struct sk_buff *skb;
+- struct net *net;
+-
+ rtnl_lock();
+-
+- for_each_net(net) {
+- while ((skb = skb_dequeue(&net->wext_nlevents)))
+- rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
+- GFP_KERNEL);
+- }
+-
++ wireless_nlevent_flush();
+ rtnl_unlock();
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/net/xfrm/xfrm_output.c linux-libre-4.4.7-gnu/net/xfrm/xfrm_output.c
+--- linux-libre-4.4-gnu/net/xfrm/xfrm_output.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/net/xfrm/xfrm_output.c 2016-04-12 12:09:26.000000000 -0400
+@@ -167,6 +167,8 @@ static int xfrm_output_gso(struct net *n
+ {
+ struct sk_buff *segs;
+
++ BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET);
++ BUILD_BUG_ON(sizeof(*IP6CB(skb)) > SKB_SGO_CB_OFFSET);
+ segs = skb_gso_segment(skb, 0);
+ kfree_skb(skb);
+ if (IS_ERR(segs))
+diff -druNp --no-dereference linux-libre-4.4-gnu/scripts/bloat-o-meter linux-libre-4.4.7-gnu/scripts/bloat-o-meter
+--- linux-libre-4.4-gnu/scripts/bloat-o-meter 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/scripts/bloat-o-meter 2016-04-12 12:09:26.000000000 -0400
+@@ -58,8 +58,8 @@ for name in common:
+ delta.sort()
+ delta.reverse()
+
+-print "add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
+- (add, remove, grow, shrink, up, -down, up-down)
+-print "%-40s %7s %7s %+7s" % ("function", "old", "new", "delta")
++print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
++ (add, remove, grow, shrink, up, -down, up-down))
++print("%-40s %7s %7s %+7s" % ("function", "old", "new", "delta"))
+ for d, n in delta:
+- if d: print "%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)
++ if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
+diff -druNp --no-dereference linux-libre-4.4-gnu/scripts/coccinelle/iterators/use_after_iter.cocci linux-libre-4.4.7-gnu/scripts/coccinelle/iterators/use_after_iter.cocci
+--- linux-libre-4.4-gnu/scripts/coccinelle/iterators/use_after_iter.cocci 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/scripts/coccinelle/iterators/use_after_iter.cocci 2016-04-12 12:09:26.000000000 -0400
+@@ -123,7 +123,7 @@ list_remove_head(x,c,...)
+ |
+ sizeof(<+...c...+>)
+ |
+-&c->member
++ &c->member
+ |
+ c = E
+ |
+diff -druNp --no-dereference linux-libre-4.4-gnu/scripts/kconfig/Makefile linux-libre-4.4.7-gnu/scripts/kconfig/Makefile
+--- linux-libre-4.4-gnu/scripts/kconfig/Makefile 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/scripts/kconfig/Makefile 2016-04-12 12:09:26.000000000 -0400
+@@ -96,13 +96,15 @@ savedefconfig: $(obj)/conf
+ defconfig: $(obj)/conf
+ ifeq ($(KBUILD_DEFCONFIG),)
+ $< $(silent) --defconfig $(Kconfig)
+-else ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),)
++else
++ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),)
+ @$(kecho) "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
+ $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
+ else
+ @$(kecho) "*** Default configuration is based on target '$(KBUILD_DEFCONFIG)'"
+ $(Q)$(MAKE) -f $(srctree)/Makefile $(KBUILD_DEFCONFIG)
+ endif
++endif
+
+ %_defconfig: $(obj)/conf
+ $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
+diff -druNp --no-dereference linux-libre-4.4-gnu/scripts/ld-version.sh linux-libre-4.4.7-gnu/scripts/ld-version.sh
+--- linux-libre-4.4-gnu/scripts/ld-version.sh 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/scripts/ld-version.sh 2016-04-12 12:09:26.000000000 -0400
+@@ -1,7 +1,7 @@
+ #!/usr/bin/awk -f
+ # extract linker version number from stdin and turn into single number
+ {
+- gsub(".*)", "");
++ gsub(".*\\)", "");
+ split($1,a, ".");
+ print a[1]*10000000 + a[2]*100000 + a[3]*10000 + a[4]*100 + a[5];
+ exit
+diff -druNp --no-dereference linux-libre-4.4-gnu/scripts/link-vmlinux.sh linux-libre-4.4.7-gnu/scripts/link-vmlinux.sh
+--- linux-libre-4.4-gnu/scripts/link-vmlinux.sh 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/scripts/link-vmlinux.sh 2016-04-12 12:09:26.000000000 -0400
+@@ -62,7 +62,7 @@ vmlinux_link()
+ -Wl,--start-group \
+ ${KBUILD_VMLINUX_MAIN} \
+ -Wl,--end-group \
+- -lutil -lrt ${1}
++ -lutil -lrt -lpthread ${1}
+ rm -f linux
+ fi
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/scripts/package/mkspec linux-libre-4.4.7-gnu/scripts/package/mkspec
+--- linux-libre-4.4-gnu/scripts/package/mkspec 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/scripts/package/mkspec 2016-04-12 12:09:26.000000000 -0400
+@@ -131,11 +131,11 @@ echo 'rm -rf $RPM_BUILD_ROOT'
+ echo ""
+ echo "%post"
+ echo "if [ -x /sbin/installkernel -a -r /boot/vmlinuz-$KERNELRELEASE -a -r /boot/System.map-$KERNELRELEASE ]; then"
+-echo "cp /boot/vmlinuz-$KERNELRELEASE /boot/vmlinuz-$KERNELRELEASE-rpm"
+-echo "cp /boot/System.map-$KERNELRELEASE /boot/System.map-$KERNELRELEASE-rpm"
++echo "cp /boot/vmlinuz-$KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm"
++echo "cp /boot/System.map-$KERNELRELEASE /boot/.System.map-$KERNELRELEASE-rpm"
+ echo "rm -f /boot/vmlinuz-$KERNELRELEASE /boot/System.map-$KERNELRELEASE"
+-echo "/sbin/installkernel $KERNELRELEASE /boot/vmlinuz-$KERNELRELEASE-rpm /boot/System.map-$KERNELRELEASE-rpm"
+-echo "rm -f /boot/vmlinuz-$KERNELRELEASE-rpm /boot/System.map-$KERNELRELEASE-rpm"
++echo "/sbin/installkernel $KERNELRELEASE /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm"
++echo "rm -f /boot/.vmlinuz-$KERNELRELEASE-rpm /boot/.System.map-$KERNELRELEASE-rpm"
+ echo "fi"
+ echo ""
+ echo "%files"
+diff -druNp --no-dereference linux-libre-4.4-gnu/scripts/recordmcount.pl linux-libre-4.4.7-gnu/scripts/recordmcount.pl
+--- linux-libre-4.4-gnu/scripts/recordmcount.pl 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/scripts/recordmcount.pl 2016-04-12 12:09:26.000000000 -0400
+@@ -263,7 +263,8 @@ if ($arch eq "x86_64") {
+
+ } elsif ($arch eq "powerpc") {
+ $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";
+- $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";
++ # See comment in the sparc64 section for why we use '\w'.
++ $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?\\w*?)>:";
+ $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";
+
+ if ($bits == 64) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/security/commoncap.c linux-libre-4.4.7-gnu/security/commoncap.c
+--- linux-libre-4.4-gnu/security/commoncap.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/security/commoncap.c 2016-04-12 12:09:26.000000000 -0400
+@@ -137,12 +137,17 @@ int cap_ptrace_access_check(struct task_
+ {
+ int ret = 0;
+ const struct cred *cred, *child_cred;
++ const kernel_cap_t *caller_caps;
+
+ rcu_read_lock();
+ cred = current_cred();
+ child_cred = __task_cred(child);
++ if (mode & PTRACE_MODE_FSCREDS)
++ caller_caps = &cred->cap_effective;
++ else
++ caller_caps = &cred->cap_permitted;
+ if (cred->user_ns == child_cred->user_ns &&
+- cap_issubset(child_cred->cap_permitted, cred->cap_permitted))
++ cap_issubset(child_cred->cap_permitted, *caller_caps))
+ goto out;
+ if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE))
+ goto out;
+diff -druNp --no-dereference linux-libre-4.4-gnu/security/integrity/evm/evm_main.c linux-libre-4.4.7-gnu/security/integrity/evm/evm_main.c
+--- linux-libre-4.4-gnu/security/integrity/evm/evm_main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/security/integrity/evm/evm_main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -23,6 +23,7 @@
+ #include <linux/integrity.h>
+ #include <linux/evm.h>
+ #include <crypto/hash.h>
++#include <crypto/algapi.h>
+ #include "evm.h"
+
+ int evm_initialized;
+@@ -148,7 +149,7 @@ static enum integrity_status evm_verify_
+ xattr_value_len, calc.digest);
+ if (rc)
+ break;
+- rc = memcmp(xattr_data->digest, calc.digest,
++ rc = crypto_memneq(xattr_data->digest, calc.digest,
+ sizeof(calc.digest));
+ if (rc)
+ rc = -EINVAL;
+diff -druNp --no-dereference linux-libre-4.4-gnu/security/keys/process_keys.c linux-libre-4.4.7-gnu/security/keys/process_keys.c
+--- linux-libre-4.4-gnu/security/keys/process_keys.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/security/keys/process_keys.c 2016-04-12 12:09:26.000000000 -0400
+@@ -794,6 +794,7 @@ long join_session_keyring(const char *na
+ ret = PTR_ERR(keyring);
+ goto error2;
+ } else if (keyring == new->session_keyring) {
++ key_put(keyring);
+ ret = 0;
+ goto error2;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/security/smack/smack_lsm.c linux-libre-4.4.7-gnu/security/smack/smack_lsm.c
+--- linux-libre-4.4-gnu/security/smack/smack_lsm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/security/smack/smack_lsm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -398,12 +398,10 @@ static int smk_copy_relabel(struct list_
+ */
+ static inline unsigned int smk_ptrace_mode(unsigned int mode)
+ {
+- switch (mode) {
+- case PTRACE_MODE_READ:
+- return MAY_READ;
+- case PTRACE_MODE_ATTACH:
++ if (mode & PTRACE_MODE_ATTACH)
+ return MAY_READWRITE;
+- }
++ if (mode & PTRACE_MODE_READ)
++ return MAY_READ;
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/security/yama/yama_lsm.c linux-libre-4.4.7-gnu/security/yama/yama_lsm.c
+--- linux-libre-4.4-gnu/security/yama/yama_lsm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/security/yama/yama_lsm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -281,7 +281,7 @@ static int yama_ptrace_access_check(stru
+ int rc = 0;
+
+ /* require ptrace target be a child of ptracer on attach */
+- if (mode == PTRACE_MODE_ATTACH) {
++ if (mode & PTRACE_MODE_ATTACH) {
+ switch (ptrace_scope) {
+ case YAMA_SCOPE_DISABLED:
+ /* No additional restrictions. */
+@@ -307,7 +307,7 @@ static int yama_ptrace_access_check(stru
+ }
+ }
+
+- if (rc) {
++ if (rc && (mode & PTRACE_MODE_NOAUDIT) == 0) {
+ printk_ratelimited(KERN_NOTICE
+ "ptrace of pid %d was attempted by: %s (pid %d)\n",
+ child->pid, current->comm, current->pid);
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/compress_offload.c linux-libre-4.4.7-gnu/sound/core/compress_offload.c
+--- linux-libre-4.4-gnu/sound/core/compress_offload.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/compress_offload.c 2016-04-12 12:09:26.000000000 -0400
+@@ -44,6 +44,13 @@
+ #include <sound/compress_offload.h>
+ #include <sound/compress_driver.h>
+
++/* struct snd_compr_codec_caps overflows the ioctl bit size for some
++ * architectures, so we need to disable the relevant ioctls.
++ */
++#if _IOC_SIZEBITS < 14
++#define COMPR_CODEC_CAPS_OVERFLOW
++#endif
++
+ /* TODO:
+ * - add substream support for multiple devices in case of
+ * SND_DYNAMIC_MINORS is not used
+@@ -438,6 +445,7 @@ out:
+ return retval;
+ }
+
++#ifndef COMPR_CODEC_CAPS_OVERFLOW
+ static int
+ snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+ {
+@@ -461,6 +469,7 @@ out:
+ kfree(caps);
+ return retval;
+ }
++#endif /* !COMPR_CODEC_CAPS_OVERFLOW */
+
+ /* revisit this with snd_pcm_preallocate_xxx */
+ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+@@ -799,9 +808,11 @@ static long snd_compr_ioctl(struct file
+ case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+ retval = snd_compr_get_caps(stream, arg);
+ break;
++#ifndef COMPR_CODEC_CAPS_OVERFLOW
+ case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+ retval = snd_compr_get_codec_caps(stream, arg);
+ break;
++#endif
+ case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+ retval = snd_compr_set_params(stream, arg);
+ break;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/control.c linux-libre-4.4.7-gnu/sound/core/control.c
+--- linux-libre-4.4-gnu/sound/core/control.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/control.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1405,6 +1405,8 @@ static int snd_ctl_tlv_ioctl(struct snd_
+ return -EFAULT;
+ if (tlv.length < sizeof(unsigned int) * 2)
+ return -EINVAL;
++ if (!tlv.numid)
++ return -EINVAL;
+ down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_numid(card, tlv.numid);
+ if (kctl == NULL) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/control_compat.c linux-libre-4.4.7-gnu/sound/core/control_compat.c
+--- linux-libre-4.4-gnu/sound/core/control_compat.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/control_compat.c 2016-04-12 12:09:26.000000000 -0400
+@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 {
+ unsigned char reserved[128];
+ };
+
++#ifdef CONFIG_X86_X32
++/* x32 has a different alignment for 64bit values from ia32 */
++struct snd_ctl_elem_value_x32 {
++ struct snd_ctl_elem_id id;
++ unsigned int indirect; /* bit-field causes misalignment */
++ union {
++ s32 integer[128];
++ unsigned char data[512];
++ s64 integer64[64];
++ } value;
++ unsigned char reserved[128];
++};
++#endif /* CONFIG_X86_X32 */
+
+ /* get the value type and count of the control */
+ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
+@@ -219,9 +232,11 @@ static int get_elem_size(int type, int c
+
+ static int copy_ctl_value_from_user(struct snd_card *card,
+ struct snd_ctl_elem_value *data,
+- struct snd_ctl_elem_value32 __user *data32,
++ void __user *userdata,
++ void __user *valuep,
+ int *typep, int *countp)
+ {
++ struct snd_ctl_elem_value32 __user *data32 = userdata;
+ int i, type, size;
+ int uninitialized_var(count);
+ unsigned int indirect;
+@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(stru
+ if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+ type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+ for (i = 0; i < count; i++) {
++ s32 __user *intp = valuep;
+ int val;
+- if (get_user(val, &data32->value.integer[i]))
++ if (get_user(val, &intp[i]))
+ return -EFAULT;
+ data->value.integer.value[i] = val;
+ }
+@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(stru
+ dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
+ return -EINVAL;
+ }
+- if (copy_from_user(data->value.bytes.data,
+- data32->value.data, size))
++ if (copy_from_user(data->value.bytes.data, valuep, size))
+ return -EFAULT;
+ }
+
+@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(stru
+ }
+
+ /* restore the value to 32bit */
+-static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
++static int copy_ctl_value_to_user(void __user *userdata,
++ void __user *valuep,
+ struct snd_ctl_elem_value *data,
+ int type, int count)
+ {
+@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct
+ if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+ type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+ for (i = 0; i < count; i++) {
++ s32 __user *intp = valuep;
+ int val;
+ val = data->value.integer.value[i];
+- if (put_user(val, &data32->value.integer[i]))
++ if (put_user(val, &intp[i]))
+ return -EFAULT;
+ }
+ } else {
+ size = get_elem_size(type, count);
+- if (copy_to_user(data32->value.data,
+- data->value.bytes.data, size))
++ if (copy_to_user(valuep, data->value.bytes.data, size))
+ return -EFAULT;
+ }
+ return 0;
+ }
+
+-static int snd_ctl_elem_read_user_compat(struct snd_card *card,
+- struct snd_ctl_elem_value32 __user *data32)
++static int ctl_elem_read_user(struct snd_card *card,
++ void __user *userdata, void __user *valuep)
+ {
+ struct snd_ctl_elem_value *data;
+ int err, type, count;
+@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat
+ if (data == NULL)
+ return -ENOMEM;
+
+- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
++ err = copy_ctl_value_from_user(card, data, userdata, valuep,
++ &type, &count);
++ if (err < 0)
+ goto error;
+
+ snd_power_lock(card);
+@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat
+ err = snd_ctl_elem_read(card, data);
+ snd_power_unlock(card);
+ if (err >= 0)
+- err = copy_ctl_value_to_user(data32, data, type, count);
++ err = copy_ctl_value_to_user(userdata, valuep, data,
++ type, count);
+ error:
+ kfree(data);
+ return err;
+ }
+
+-static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
+- struct snd_ctl_elem_value32 __user *data32)
++static int ctl_elem_write_user(struct snd_ctl_file *file,
++ void __user *userdata, void __user *valuep)
+ {
+ struct snd_ctl_elem_value *data;
+ struct snd_card *card = file->card;
+@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compa
+ if (data == NULL)
+ return -ENOMEM;
+
+- if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
++ err = copy_ctl_value_from_user(card, data, userdata, valuep,
++ &type, &count);
++ if (err < 0)
+ goto error;
+
+ snd_power_lock(card);
+@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compa
+ err = snd_ctl_elem_write(card, file, data);
+ snd_power_unlock(card);
+ if (err >= 0)
+- err = copy_ctl_value_to_user(data32, data, type, count);
++ err = copy_ctl_value_to_user(userdata, valuep, data,
++ type, count);
+ error:
+ kfree(data);
+ return err;
+ }
+
++static int snd_ctl_elem_read_user_compat(struct snd_card *card,
++ struct snd_ctl_elem_value32 __user *data32)
++{
++ return ctl_elem_read_user(card, data32, &data32->value);
++}
++
++static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
++ struct snd_ctl_elem_value32 __user *data32)
++{
++ return ctl_elem_write_user(file, data32, &data32->value);
++}
++
++#ifdef CONFIG_X86_X32
++static int snd_ctl_elem_read_user_x32(struct snd_card *card,
++ struct snd_ctl_elem_value_x32 __user *data32)
++{
++ return ctl_elem_read_user(card, data32, &data32->value);
++}
++
++static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file,
++ struct snd_ctl_elem_value_x32 __user *data32)
++{
++ return ctl_elem_write_user(file, data32, &data32->value);
++}
++#endif /* CONFIG_X86_X32 */
++
+ /* add or replace a user control */
+ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
+ struct snd_ctl_elem_info32 __user *data32,
+@@ -393,6 +441,10 @@ enum {
+ SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
+ SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32),
+ SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32),
++#ifdef CONFIG_X86_X32
++ SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32),
++ SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32),
++#endif /* CONFIG_X86_X32 */
+ };
+
+ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+@@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(
+ return snd_ctl_elem_add_compat(ctl, argp, 0);
+ case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
+ return snd_ctl_elem_add_compat(ctl, argp, 1);
++#ifdef CONFIG_X86_X32
++ case SNDRV_CTL_IOCTL_ELEM_READ_X32:
++ return snd_ctl_elem_read_user_x32(ctl->card, argp);
++ case SNDRV_CTL_IOCTL_ELEM_WRITE_X32:
++ return snd_ctl_elem_write_user_x32(ctl, argp);
++#endif /* CONFIG_X86_X32 */
+ }
+
+ down_read(&snd_ioctl_rwsem);
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/hrtimer.c linux-libre-4.4.7-gnu/sound/core/hrtimer.c
+--- linux-libre-4.4-gnu/sound/core/hrtimer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/hrtimer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -90,7 +90,7 @@ static int snd_hrtimer_start(struct snd_
+ struct snd_hrtimer *stime = t->private_data;
+
+ atomic_set(&stime->running, 0);
+- hrtimer_cancel(&stime->hrt);
++ hrtimer_try_to_cancel(&stime->hrt);
+ hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
+ HRTIMER_MODE_REL);
+ atomic_set(&stime->running, 1);
+@@ -101,6 +101,7 @@ static int snd_hrtimer_stop(struct snd_t
+ {
+ struct snd_hrtimer *stime = t->private_data;
+ atomic_set(&stime->running, 0);
++ hrtimer_try_to_cancel(&stime->hrt);
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/oss/pcm_oss.c linux-libre-4.4.7-gnu/sound/core/oss/pcm_oss.c
+--- linux-libre-4.4-gnu/sound/core/oss/pcm_oss.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/oss/pcm_oss.c 2016-04-12 12:09:26.000000000 -0400
+@@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_su
+ return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
+ }
+
+-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
++static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
++ bool trylock)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_hw_params *params, *sparams;
+@@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(str
+ struct snd_mask sformat_mask;
+ struct snd_mask mask;
+
+- if (mutex_lock_interruptible(&runtime->oss.params_lock))
++ if (trylock) {
++ if (!(mutex_trylock(&runtime->oss.params_lock)))
++ return -EAGAIN;
++ } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
+ return -EINTR;
+ sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+@@ -1092,7 +1096,7 @@ static int snd_pcm_oss_get_active_substr
+ if (asubstream == NULL)
+ asubstream = substream;
+ if (substream->runtime->oss.params) {
+- err = snd_pcm_oss_change_params(substream);
++ err = snd_pcm_oss_change_params(substream, false);
+ if (err < 0)
+ return err;
+ }
+@@ -1132,7 +1136,7 @@ static int snd_pcm_oss_make_ready(struct
+ return 0;
+ runtime = substream->runtime;
+ if (runtime->oss.params) {
+- err = snd_pcm_oss_change_params(substream);
++ err = snd_pcm_oss_change_params(substream, false);
+ if (err < 0)
+ return err;
+ }
+@@ -2163,7 +2167,7 @@ static int snd_pcm_oss_get_space(struct
+ runtime = substream->runtime;
+
+ if (runtime->oss.params &&
+- (err = snd_pcm_oss_change_params(substream)) < 0)
++ (err = snd_pcm_oss_change_params(substream, false)) < 0)
+ return err;
+
+ info.fragsize = runtime->oss.period_bytes;
+@@ -2800,7 +2804,12 @@ static int snd_pcm_oss_mmap(struct file
+ return -EIO;
+
+ if (runtime->oss.params) {
+- if ((err = snd_pcm_oss_change_params(substream)) < 0)
++ /* use mutex_trylock() for params_lock for avoiding a deadlock
++ * between mmap_sem and params_lock taken by
++ * copy_from/to_user() in snd_pcm_oss_write/read()
++ */
++ err = snd_pcm_oss_change_params(substream, true);
++ if (err < 0)
+ return err;
+ }
+ #ifdef CONFIG_SND_PCM_OSS_PLUGINS
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/pcm_compat.c linux-libre-4.4.7-gnu/sound/core/pcm_compat.c
+--- linux-libre-4.4-gnu/sound/core/pcm_compat.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/pcm_compat.c 2016-04-12 12:09:26.000000000 -0400
+@@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_co
+ return err;
+ }
+
++#ifdef CONFIG_X86_X32
++/* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */
++static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
++ struct snd_pcm_channel_info __user *src);
++#define snd_pcm_ioctl_channel_info_x32(s, p) \
++ snd_pcm_channel_info_user(s, p)
++#endif /* CONFIG_X86_X32 */
++
+ struct snd_pcm_status32 {
+ s32 state;
+ struct compat_timespec trigger_tstamp;
+@@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(st
+ return err;
+ }
+
++#ifdef CONFIG_X86_X32
++/* X32 ABI has 64bit timespec and 64bit alignment */
++struct snd_pcm_status_x32 {
++ s32 state;
++ u32 rsvd; /* alignment */
++ struct timespec trigger_tstamp;
++ struct timespec tstamp;
++ u32 appl_ptr;
++ u32 hw_ptr;
++ s32 delay;
++ u32 avail;
++ u32 avail_max;
++ u32 overrange;
++ s32 suspended_state;
++ u32 audio_tstamp_data;
++ struct timespec audio_tstamp;
++ struct timespec driver_tstamp;
++ u32 audio_tstamp_accuracy;
++ unsigned char reserved[52-2*sizeof(struct timespec)];
++} __packed;
++
++#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
++
++static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
++ struct snd_pcm_status_x32 __user *src,
++ bool ext)
++{
++ struct snd_pcm_status status;
++ int err;
++
++ memset(&status, 0, sizeof(status));
++ /*
++ * with extension, parameters are read/write,
++ * get audio_tstamp_data from user,
++ * ignore rest of status structure
++ */
++ if (ext && get_user(status.audio_tstamp_data,
++ (u32 __user *)(&src->audio_tstamp_data)))
++ return -EFAULT;
++ err = snd_pcm_status(substream, &status);
++ if (err < 0)
++ return err;
++
++ if (clear_user(src, sizeof(*src)))
++ return -EFAULT;
++ if (put_user(status.state, &src->state) ||
++ put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
++ put_timespec(&status.tstamp, &src->tstamp) ||
++ put_user(status.appl_ptr, &src->appl_ptr) ||
++ put_user(status.hw_ptr, &src->hw_ptr) ||
++ put_user(status.delay, &src->delay) ||
++ put_user(status.avail, &src->avail) ||
++ put_user(status.avail_max, &src->avail_max) ||
++ put_user(status.overrange, &src->overrange) ||
++ put_user(status.suspended_state, &src->suspended_state) ||
++ put_user(status.audio_tstamp_data, &src->audio_tstamp_data) ||
++ put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
++ put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
++ put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
++ return -EFAULT;
++
++ return err;
++}
++#endif /* CONFIG_X86_X32 */
++
+ /* both for HW_PARAMS and HW_REFINE */
+ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
+ int refine,
+@@ -255,10 +328,15 @@ static int snd_pcm_ioctl_hw_params_compa
+ if (! (runtime = substream->runtime))
+ return -ENOTTY;
+
+- /* only fifo_size is different, so just copy all */
+- data = memdup_user(data32, sizeof(*data32));
+- if (IS_ERR(data))
+- return PTR_ERR(data);
++ data = kmalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ /* only fifo_size (RO from userspace) is different, so just copy all */
++ if (copy_from_user(data, data32, sizeof(*data32))) {
++ err = -EFAULT;
++ goto error;
++ }
+
+ if (refine)
+ err = snd_pcm_hw_refine(substream, data);
+@@ -464,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat
+ return 0;
+ }
+
++#ifdef CONFIG_X86_X32
++/* X32 ABI has 64bit timespec and 64bit alignment */
++struct snd_pcm_mmap_status_x32 {
++ s32 state;
++ s32 pad1;
++ u32 hw_ptr;
++ u32 pad2; /* alignment */
++ struct timespec tstamp;
++ s32 suspended_state;
++ struct timespec audio_tstamp;
++} __packed;
++
++struct snd_pcm_mmap_control_x32 {
++ u32 appl_ptr;
++ u32 avail_min;
++};
++
++struct snd_pcm_sync_ptr_x32 {
++ u32 flags;
++ u32 rsvd; /* alignment */
++ union {
++ struct snd_pcm_mmap_status_x32 status;
++ unsigned char reserved[64];
++ } s;
++ union {
++ struct snd_pcm_mmap_control_x32 control;
++ unsigned char reserved[64];
++ } c;
++} __packed;
++
++static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
++ struct snd_pcm_sync_ptr_x32 __user *src)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ volatile struct snd_pcm_mmap_status *status;
++ volatile struct snd_pcm_mmap_control *control;
++ u32 sflags;
++ struct snd_pcm_mmap_control scontrol;
++ struct snd_pcm_mmap_status sstatus;
++ snd_pcm_uframes_t boundary;
++ int err;
++
++ if (snd_BUG_ON(!runtime))
++ return -EINVAL;
++
++ if (get_user(sflags, &src->flags) ||
++ get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
++ get_user(scontrol.avail_min, &src->c.control.avail_min))
++ return -EFAULT;
++ if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
++ err = snd_pcm_hwsync(substream);
++ if (err < 0)
++ return err;
++ }
++ status = runtime->status;
++ control = runtime->control;
++ boundary = recalculate_boundary(runtime);
++ if (!boundary)
++ boundary = 0x7fffffff;
++ snd_pcm_stream_lock_irq(substream);
++ /* FIXME: we should consider the boundary for the sync from app */
++ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
++ control->appl_ptr = scontrol.appl_ptr;
++ else
++ scontrol.appl_ptr = control->appl_ptr % boundary;
++ if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
++ control->avail_min = scontrol.avail_min;
++ else
++ scontrol.avail_min = control->avail_min;
++ sstatus.state = status->state;
++ sstatus.hw_ptr = status->hw_ptr % boundary;
++ sstatus.tstamp = status->tstamp;
++ sstatus.suspended_state = status->suspended_state;
++ sstatus.audio_tstamp = status->audio_tstamp;
++ snd_pcm_stream_unlock_irq(substream);
++ if (put_user(sstatus.state, &src->s.status.state) ||
++ put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
++ put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
++ put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
++ put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) ||
++ put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
++ put_user(scontrol.avail_min, &src->c.control.avail_min))
++ return -EFAULT;
++
++ return 0;
++}
++#endif /* CONFIG_X86_X32 */
+
+ /*
+ */
+@@ -482,7 +647,12 @@ enum {
+ SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
+ SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
+ SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
+-
++#ifdef CONFIG_X86_X32
++ SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info),
++ SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32),
++ SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32),
++ SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32),
++#endif /* CONFIG_X86_X32 */
+ };
+
+ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+@@ -554,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct
+ return snd_pcm_ioctl_rewind_compat(substream, argp);
+ case SNDRV_PCM_IOCTL_FORWARD32:
+ return snd_pcm_ioctl_forward_compat(substream, argp);
++#ifdef CONFIG_X86_X32
++ case SNDRV_PCM_IOCTL_STATUS_X32:
++ return snd_pcm_status_user_x32(substream, argp, false);
++ case SNDRV_PCM_IOCTL_STATUS_EXT_X32:
++ return snd_pcm_status_user_x32(substream, argp, true);
++ case SNDRV_PCM_IOCTL_SYNC_PTR_X32:
++ return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
++ case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32:
++ return snd_pcm_ioctl_channel_info_x32(substream, argp);
++#endif /* CONFIG_X86_X32 */
+ }
+
+ return -ENOIOCTLCMD;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/pcm_lib.c linux-libre-4.4.7-gnu/sound/core/pcm_lib.c
+--- linux-libre-4.4-gnu/sound/core/pcm_lib.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/pcm_lib.c 2016-04-12 12:09:26.000000000 -0400
+@@ -322,7 +322,7 @@ static int snd_pcm_update_hw_ptr0(struct
+ char name[16];
+ snd_pcm_debug_name(substream, name, sizeof(name));
+ pcm_err(substream->pcm,
+- "BUG: %s, pos = %ld, buffer size = %ld, period size = %ld\n",
++ "invalid position: %s, pos = %ld, buffer size = %ld, period size = %ld\n",
+ name, pos, runtime->buffer_size,
+ runtime->period_size);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/pcm_native.c linux-libre-4.4.7-gnu/sound/core/pcm_native.c
+--- linux-libre-4.4-gnu/sound/core/pcm_native.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/pcm_native.c 2016-04-12 12:09:26.000000000 -0400
+@@ -74,6 +74,18 @@ static int snd_pcm_open(struct file *fil
+ static DEFINE_RWLOCK(snd_pcm_link_rwlock);
+ static DECLARE_RWSEM(snd_pcm_link_rwsem);
+
++/* Writer in rwsem may block readers even during its waiting in queue,
++ * and this may lead to a deadlock when the code path takes read sem
++ * twice (e.g. one in snd_pcm_action_nonatomic() and another in
++ * snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to
++ * spin until it gets the lock.
++ */
++static inline void down_write_nonblock(struct rw_semaphore *lock)
++{
++ while (!down_write_trylock(lock))
++ cond_resched();
++}
++
+ /**
+ * snd_pcm_stream_lock - Lock the PCM stream
+ * @substream: PCM substream
+@@ -1813,7 +1825,7 @@ static int snd_pcm_link(struct snd_pcm_s
+ res = -ENOMEM;
+ goto _nolock;
+ }
+- down_write(&snd_pcm_link_rwsem);
++ down_write_nonblock(&snd_pcm_link_rwsem);
+ write_lock_irq(&snd_pcm_link_rwlock);
+ if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
+ substream->runtime->status->state != substream1->runtime->status->state ||
+@@ -1860,7 +1872,7 @@ static int snd_pcm_unlink(struct snd_pcm
+ struct snd_pcm_substream *s;
+ int res = 0;
+
+- down_write(&snd_pcm_link_rwsem);
++ down_write_nonblock(&snd_pcm_link_rwsem);
+ write_lock_irq(&snd_pcm_link_rwlock);
+ if (!snd_pcm_stream_linked(substream)) {
+ res = -EALREADY;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/rawmidi.c linux-libre-4.4.7-gnu/sound/core/rawmidi.c
+--- linux-libre-4.4-gnu/sound/core/rawmidi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/rawmidi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -942,31 +942,36 @@ static long snd_rawmidi_kernel_read1(str
+ unsigned long flags;
+ long result = 0, count1;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ unsigned long appl_ptr;
+
++ spin_lock_irqsave(&runtime->lock, flags);
+ while (count > 0 && runtime->avail) {
+ count1 = runtime->buffer_size - runtime->appl_ptr;
+ if (count1 > count)
+ count1 = count;
+- spin_lock_irqsave(&runtime->lock, flags);
+ if (count1 > (int)runtime->avail)
+ count1 = runtime->avail;
++
++ /* update runtime->appl_ptr before unlocking for userbuf */
++ appl_ptr = runtime->appl_ptr;
++ runtime->appl_ptr += count1;
++ runtime->appl_ptr %= runtime->buffer_size;
++ runtime->avail -= count1;
++
+ if (kernelbuf)
+- memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
++ memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
+ if (userbuf) {
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ if (copy_to_user(userbuf + result,
+- runtime->buffer + runtime->appl_ptr, count1)) {
++ runtime->buffer + appl_ptr, count1)) {
+ return result > 0 ? result : -EFAULT;
+ }
+ spin_lock_irqsave(&runtime->lock, flags);
+ }
+- runtime->appl_ptr += count1;
+- runtime->appl_ptr %= runtime->buffer_size;
+- runtime->avail -= count1;
+- spin_unlock_irqrestore(&runtime->lock, flags);
+ result += count1;
+ count -= count1;
+ }
++ spin_unlock_irqrestore(&runtime->lock, flags);
+ return result;
+ }
+
+@@ -1055,23 +1060,16 @@ int snd_rawmidi_transmit_empty(struct sn
+ EXPORT_SYMBOL(snd_rawmidi_transmit_empty);
+
+ /**
+- * snd_rawmidi_transmit_peek - copy data from the internal buffer
++ * __snd_rawmidi_transmit_peek - copy data from the internal buffer
+ * @substream: the rawmidi substream
+ * @buffer: the buffer pointer
+ * @count: data size to transfer
+ *
+- * Copies data from the internal output buffer to the given buffer.
+- *
+- * Call this in the interrupt handler when the midi output is ready,
+- * and call snd_rawmidi_transmit_ack() after the transmission is
+- * finished.
+- *
+- * Return: The size of copied data, or a negative error code on failure.
++ * This is a variant of snd_rawmidi_transmit_peek() without spinlock.
+ */
+-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count)
+ {
+- unsigned long flags;
+ int result, count1;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
+@@ -1081,7 +1079,6 @@ int snd_rawmidi_transmit_peek(struct snd
+ return -EINVAL;
+ }
+ result = 0;
+- spin_lock_irqsave(&runtime->lock, flags);
+ if (runtime->avail >= runtime->buffer_size) {
+ /* warning: lowlevel layer MUST trigger down the hardware */
+ goto __skip;
+@@ -1106,25 +1103,47 @@ int snd_rawmidi_transmit_peek(struct snd
+ }
+ }
+ __skip:
++ return result;
++}
++EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
++
++/**
++ * snd_rawmidi_transmit_peek - copy data from the internal buffer
++ * @substream: the rawmidi substream
++ * @buffer: the buffer pointer
++ * @count: data size to transfer
++ *
++ * Copies data from the internal output buffer to the given buffer.
++ *
++ * Call this in the interrupt handler when the midi output is ready,
++ * and call snd_rawmidi_transmit_ack() after the transmission is
++ * finished.
++ *
++ * Return: The size of copied data, or a negative error code on failure.
++ */
++int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++ unsigned char *buffer, int count)
++{
++ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ int result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&runtime->lock, flags);
++ result = __snd_rawmidi_transmit_peek(substream, buffer, count);
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ return result;
+ }
+ EXPORT_SYMBOL(snd_rawmidi_transmit_peek);
+
+ /**
+- * snd_rawmidi_transmit_ack - acknowledge the transmission
++ * __snd_rawmidi_transmit_ack - acknowledge the transmission
+ * @substream: the rawmidi substream
+ * @count: the transferred count
+ *
+- * Advances the hardware pointer for the internal output buffer with
+- * the given size and updates the condition.
+- * Call after the transmission is finished.
+- *
+- * Return: The advanced size if successful, or a negative error code on failure.
++ * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
+ */
+-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
++int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+ {
+- unsigned long flags;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
+ if (runtime->buffer == NULL) {
+@@ -1132,7 +1151,6 @@ int snd_rawmidi_transmit_ack(struct snd_
+ "snd_rawmidi_transmit_ack: output is not active!!!\n");
+ return -EINVAL;
+ }
+- spin_lock_irqsave(&runtime->lock, flags);
+ snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
+ runtime->hw_ptr += count;
+ runtime->hw_ptr %= runtime->buffer_size;
+@@ -1142,9 +1160,32 @@ int snd_rawmidi_transmit_ack(struct snd_
+ if (runtime->drain || snd_rawmidi_ready(substream))
+ wake_up(&runtime->sleep);
+ }
+- spin_unlock_irqrestore(&runtime->lock, flags);
+ return count;
+ }
++EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
++
++/**
++ * snd_rawmidi_transmit_ack - acknowledge the transmission
++ * @substream: the rawmidi substream
++ * @count: the transferred count
++ *
++ * Advances the hardware pointer for the internal output buffer with
++ * the given size and updates the condition.
++ * Call after the transmission is finished.
++ *
++ * Return: The advanced size if successful, or a negative error code on failure.
++ */
++int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
++{
++ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ int result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&runtime->lock, flags);
++ result = __snd_rawmidi_transmit_ack(substream, count);
++ spin_unlock_irqrestore(&runtime->lock, flags);
++ return result;
++}
+ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
+
+ /**
+@@ -1160,12 +1201,22 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
+ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count)
+ {
++ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ int result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&runtime->lock, flags);
+ if (!substream->opened)
+- return -EBADFD;
+- count = snd_rawmidi_transmit_peek(substream, buffer, count);
+- if (count < 0)
+- return count;
+- return snd_rawmidi_transmit_ack(substream, count);
++ result = -EBADFD;
++ else {
++ count = __snd_rawmidi_transmit_peek(substream, buffer, count);
++ if (count <= 0)
++ result = count;
++ else
++ result = __snd_rawmidi_transmit_ack(substream, count);
++ }
++ spin_unlock_irqrestore(&runtime->lock, flags);
++ return result;
+ }
+ EXPORT_SYMBOL(snd_rawmidi_transmit);
+
+@@ -1177,8 +1228,9 @@ static long snd_rawmidi_kernel_write1(st
+ unsigned long flags;
+ long count1, result;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ unsigned long appl_ptr;
+
+- if (snd_BUG_ON(!kernelbuf && !userbuf))
++ if (!kernelbuf && !userbuf)
+ return -EINVAL;
+ if (snd_BUG_ON(!runtime->buffer))
+ return -EINVAL;
+@@ -1197,12 +1249,19 @@ static long snd_rawmidi_kernel_write1(st
+ count1 = count;
+ if (count1 > (long)runtime->avail)
+ count1 = runtime->avail;
++
++ /* update runtime->appl_ptr before unlocking for userbuf */
++ appl_ptr = runtime->appl_ptr;
++ runtime->appl_ptr += count1;
++ runtime->appl_ptr %= runtime->buffer_size;
++ runtime->avail -= count1;
++
+ if (kernelbuf)
+- memcpy(runtime->buffer + runtime->appl_ptr,
++ memcpy(runtime->buffer + appl_ptr,
+ kernelbuf + result, count1);
+ else if (userbuf) {
+ spin_unlock_irqrestore(&runtime->lock, flags);
+- if (copy_from_user(runtime->buffer + runtime->appl_ptr,
++ if (copy_from_user(runtime->buffer + appl_ptr,
+ userbuf + result, count1)) {
+ spin_lock_irqsave(&runtime->lock, flags);
+ result = result > 0 ? result : -EFAULT;
+@@ -1210,9 +1269,6 @@ static long snd_rawmidi_kernel_write1(st
+ }
+ spin_lock_irqsave(&runtime->lock, flags);
+ }
+- runtime->appl_ptr += count1;
+- runtime->appl_ptr %= runtime->buffer_size;
+- runtime->avail -= count1;
+ result += count1;
+ count -= count1;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/rawmidi_compat.c linux-libre-4.4.7-gnu/sound/core/rawmidi_compat.c
+--- linux-libre-4.4-gnu/sound/core/rawmidi_compat.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/rawmidi_compat.c 2016-04-12 12:09:26.000000000 -0400
+@@ -94,9 +94,58 @@ static int snd_rawmidi_ioctl_status_comp
+ return 0;
+ }
+
++#ifdef CONFIG_X86_X32
++/* X32 ABI has 64bit timespec and 64bit alignment */
++struct snd_rawmidi_status_x32 {
++ s32 stream;
++ u32 rsvd; /* alignment */
++ struct timespec tstamp;
++ u32 avail;
++ u32 xruns;
++ unsigned char reserved[16];
++} __attribute__((packed));
++
++#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
++
++static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile,
++ struct snd_rawmidi_status_x32 __user *src)
++{
++ int err;
++ struct snd_rawmidi_status status;
++
++ if (rfile->output == NULL)
++ return -EINVAL;
++ if (get_user(status.stream, &src->stream))
++ return -EFAULT;
++
++ switch (status.stream) {
++ case SNDRV_RAWMIDI_STREAM_OUTPUT:
++ err = snd_rawmidi_output_status(rfile->output, &status);
++ break;
++ case SNDRV_RAWMIDI_STREAM_INPUT:
++ err = snd_rawmidi_input_status(rfile->input, &status);
++ break;
++ default:
++ return -EINVAL;
++ }
++ if (err < 0)
++ return err;
++
++ if (put_timespec(&status.tstamp, &src->tstamp) ||
++ put_user(status.avail, &src->avail) ||
++ put_user(status.xruns, &src->xruns))
++ return -EFAULT;
++
++ return 0;
++}
++#endif /* CONFIG_X86_X32 */
++
+ enum {
+ SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
+ SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
++#ifdef CONFIG_X86_X32
++ SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32),
++#endif /* CONFIG_X86_X32 */
+ };
+
+ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+@@ -115,6 +164,10 @@ static long snd_rawmidi_ioctl_compat(str
+ return snd_rawmidi_ioctl_params_compat(rfile, argp);
+ case SNDRV_RAWMIDI_IOCTL_STATUS32:
+ return snd_rawmidi_ioctl_status_compat(rfile, argp);
++#ifdef CONFIG_X86_X32
++ case SNDRV_RAWMIDI_IOCTL_STATUS_X32:
++ return snd_rawmidi_ioctl_status_x32(rfile, argp);
++#endif /* CONFIG_X86_X32 */
+ }
+ return -ENOIOCTLCMD;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss.c linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss.c
+--- linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss.c 2016-04-12 12:09:26.000000000 -0400
+@@ -148,8 +148,6 @@ odev_release(struct inode *inode, struct
+ if ((dp = file->private_data) == NULL)
+ return 0;
+
+- snd_seq_oss_drain_write(dp);
+-
+ mutex_lock(&register_mutex);
+ snd_seq_oss_release(dp);
+ mutex_unlock(&register_mutex);
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss_device.h linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss_device.h
+--- linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss_device.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss_device.h 2016-04-12 12:09:26.000000000 -0400
+@@ -127,7 +127,6 @@ int snd_seq_oss_write(struct seq_oss_dev
+ unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait);
+
+ void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
+-void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp);
+
+ /* */
+ void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss_init.c linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss_init.c
+--- linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss_init.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss_init.c 2016-04-12 12:09:26.000000000 -0400
+@@ -202,7 +202,7 @@ snd_seq_oss_open(struct file *file, int
+
+ dp->index = i;
+ if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
+- pr_err("ALSA: seq_oss: too many applications\n");
++ pr_debug("ALSA: seq_oss: too many applications\n");
+ rc = -ENOMEM;
+ goto _error;
+ }
+@@ -435,22 +435,6 @@ snd_seq_oss_release(struct seq_oss_devin
+ }
+
+
+-/*
+- * Wait until the queue is empty (if we don't have nonblock)
+- */
+-void
+-snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
+-{
+- if (! dp->timer->running)
+- return;
+- if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) &&
+- dp->writeq) {
+- while (snd_seq_oss_writeq_sync(dp->writeq))
+- ;
+- }
+-}
+-
+-
+ /*
+ * reset sequencer devices
+ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss_synth.c linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss_synth.c
+--- linux-libre-4.4-gnu/sound/core/seq/oss/seq_oss_synth.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/oss/seq_oss_synth.c 2016-04-12 12:09:26.000000000 -0400
+@@ -308,7 +308,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss
+ struct seq_oss_synth *rec;
+ struct seq_oss_synthinfo *info;
+
+- if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
++ if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
+ return;
+ for (i = 0; i < dp->max_synthdev; i++) {
+ info = &dp->synths[i];
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/seq_clientmgr.c linux-libre-4.4.7-gnu/sound/core/seq/seq_clientmgr.c
+--- linux-libre-4.4-gnu/sound/core/seq/seq_clientmgr.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/seq_clientmgr.c 2016-04-12 12:09:26.000000000 -0400
+@@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct
+ else
+ down_read(&grp->list_mutex);
+ list_for_each_entry(subs, &grp->list_head, src_list) {
++ /* both ports ready? */
++ if (atomic_read(&subs->ref_count) != 2)
++ continue;
+ event->dest = subs->info.dest;
+ if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
+ /* convert time according to flag with subscription */
+@@ -1962,7 +1965,7 @@ static int snd_seq_ioctl_remove_events(s
+ * No restrictions so for a user client we can clear
+ * the whole fifo
+ */
+- if (client->type == USER_CLIENT)
++ if (client->type == USER_CLIENT && client->data.user.fifo)
+ snd_seq_fifo_clear(client->data.user.fifo);
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/seq_compat.c linux-libre-4.4.7-gnu/sound/core/seq/seq_compat.c
+--- linux-libre-4.4-gnu/sound/core/seq/seq_compat.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/seq_compat.c 2016-04-12 12:09:26.000000000 -0400
+@@ -49,11 +49,12 @@ static int snd_seq_call_port_info_ioctl(
+ struct snd_seq_port_info *data;
+ mm_segment_t fs;
+
+- data = memdup_user(data32, sizeof(*data32));
+- if (IS_ERR(data))
+- return PTR_ERR(data);
++ data = kmalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
+
+- if (get_user(data->flags, &data32->flags) ||
++ if (copy_from_user(data, data32, sizeof(*data32)) ||
++ get_user(data->flags, &data32->flags) ||
+ get_user(data->time_queue, &data32->time_queue))
+ goto error;
+ data->kernel = NULL;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/seq_memory.c linux-libre-4.4.7-gnu/sound/core/seq/seq_memory.c
+--- linux-libre-4.4-gnu/sound/core/seq/seq_memory.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/seq_memory.c 2016-04-12 12:09:26.000000000 -0400
+@@ -383,15 +383,20 @@ int snd_seq_pool_init(struct snd_seq_poo
+
+ if (snd_BUG_ON(!pool))
+ return -EINVAL;
+- if (pool->ptr) /* should be atomic? */
+- return 0;
+
+- pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
+- if (!pool->ptr)
++ cellptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
++ if (!cellptr)
+ return -ENOMEM;
+
+ /* add new cells to the free cell list */
+ spin_lock_irqsave(&pool->lock, flags);
++ if (pool->ptr) {
++ spin_unlock_irqrestore(&pool->lock, flags);
++ vfree(cellptr);
++ return 0;
++ }
++
++ pool->ptr = cellptr;
+ pool->free = NULL;
+
+ for (cell = 0; cell < pool->size; cell++) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/seq_ports.c linux-libre-4.4.7-gnu/sound/core/seq/seq_ports.c
+--- linux-libre-4.4-gnu/sound/core/seq/seq_ports.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/seq_ports.c 2016-04-12 12:09:26.000000000 -0400
+@@ -173,10 +173,6 @@ struct snd_seq_client_port *snd_seq_crea
+ }
+
+ /* */
+-enum group_type {
+- SRC_LIST, DEST_LIST
+-};
+-
+ static int subscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+@@ -203,6 +199,20 @@ static struct snd_seq_client_port *get_c
+ return NULL;
+ }
+
++static void delete_and_unsubscribe_port(struct snd_seq_client *client,
++ struct snd_seq_client_port *port,
++ struct snd_seq_subscribers *subs,
++ bool is_src, bool ack);
++
++static inline struct snd_seq_subscribers *
++get_subscriber(struct list_head *p, bool is_src)
++{
++ if (is_src)
++ return list_entry(p, struct snd_seq_subscribers, src_list);
++ else
++ return list_entry(p, struct snd_seq_subscribers, dest_list);
++}
++
+ /*
+ * remove all subscribers on the list
+ * this is called from port_delete, for each src and dest list.
+@@ -210,7 +220,7 @@ static struct snd_seq_client_port *get_c
+ static void clear_subscriber_list(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+- int grptype)
++ int is_src)
+ {
+ struct list_head *p, *n;
+
+@@ -219,15 +229,13 @@ static void clear_subscriber_list(struct
+ struct snd_seq_client *c;
+ struct snd_seq_client_port *aport;
+
+- if (grptype == SRC_LIST) {
+- subs = list_entry(p, struct snd_seq_subscribers, src_list);
++ subs = get_subscriber(p, is_src);
++ if (is_src)
+ aport = get_client_port(&subs->info.dest, &c);
+- } else {
+- subs = list_entry(p, struct snd_seq_subscribers, dest_list);
++ else
+ aport = get_client_port(&subs->info.sender, &c);
+- }
+- list_del(p);
+- unsubscribe_port(client, port, grp, &subs->info, 0);
++ delete_and_unsubscribe_port(client, port, subs, is_src, false);
++
+ if (!aport) {
+ /* looks like the connected port is being deleted.
+ * we decrease the counter, and when both ports are deleted
+@@ -235,21 +243,14 @@ static void clear_subscriber_list(struct
+ */
+ if (atomic_dec_and_test(&subs->ref_count))
+ kfree(subs);
+- } else {
+- /* ok we got the connected port */
+- struct snd_seq_port_subs_info *agrp;
+- agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
+- down_write(&agrp->list_mutex);
+- if (grptype == SRC_LIST)
+- list_del(&subs->dest_list);
+- else
+- list_del(&subs->src_list);
+- up_write(&agrp->list_mutex);
+- unsubscribe_port(c, aport, agrp, &subs->info, 1);
+- kfree(subs);
+- snd_seq_port_unlock(aport);
+- snd_seq_client_unlock(c);
++ continue;
+ }
++
++ /* ok we got the connected port */
++ delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
++ kfree(subs);
++ snd_seq_port_unlock(aport);
++ snd_seq_client_unlock(c);
+ }
+ }
+
+@@ -262,8 +263,8 @@ static int port_delete(struct snd_seq_cl
+ snd_use_lock_sync(&port->use_lock);
+
+ /* clear subscribers info */
+- clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
+- clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
++ clear_subscriber_list(client, port, &port->c_src, true);
++ clear_subscriber_list(client, port, &port->c_dest, false);
+
+ if (port->private_free)
+ port->private_free(port->private_data);
+@@ -479,85 +480,123 @@ static int match_subs_info(struct snd_se
+ return 0;
+ }
+
+-
+-/* connect two ports */
+-int snd_seq_port_connect(struct snd_seq_client *connector,
+- struct snd_seq_client *src_client,
+- struct snd_seq_client_port *src_port,
+- struct snd_seq_client *dest_client,
+- struct snd_seq_client_port *dest_port,
+- struct snd_seq_port_subscribe *info)
++static int check_and_subscribe_port(struct snd_seq_client *client,
++ struct snd_seq_client_port *port,
++ struct snd_seq_subscribers *subs,
++ bool is_src, bool exclusive, bool ack)
+ {
+- struct snd_seq_port_subs_info *src = &src_port->c_src;
+- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+- struct snd_seq_subscribers *subs, *s;
+- int err, src_called = 0;
+- unsigned long flags;
+- int exclusive;
+-
+- subs = kzalloc(sizeof(*subs), GFP_KERNEL);
+- if (! subs)
+- return -ENOMEM;
+-
+- subs->info = *info;
+- atomic_set(&subs->ref_count, 2);
+-
+- down_write(&src->list_mutex);
+- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
++ struct snd_seq_port_subs_info *grp;
++ struct list_head *p;
++ struct snd_seq_subscribers *s;
++ int err;
+
+- exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
++ grp = is_src ? &port->c_src : &port->c_dest;
+ err = -EBUSY;
++ down_write(&grp->list_mutex);
+ if (exclusive) {
+- if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
++ if (!list_empty(&grp->list_head))
+ goto __error;
+ } else {
+- if (src->exclusive || dest->exclusive)
++ if (grp->exclusive)
+ goto __error;
+ /* check whether already exists */
+- list_for_each_entry(s, &src->list_head, src_list) {
+- if (match_subs_info(info, &s->info))
+- goto __error;
+- }
+- list_for_each_entry(s, &dest->list_head, dest_list) {
+- if (match_subs_info(info, &s->info))
++ list_for_each(p, &grp->list_head) {
++ s = get_subscriber(p, is_src);
++ if (match_subs_info(&subs->info, &s->info))
+ goto __error;
+ }
+ }
+
+- if ((err = subscribe_port(src_client, src_port, src, info,
+- connector->number != src_client->number)) < 0)
+- goto __error;
+- src_called = 1;
+-
+- if ((err = subscribe_port(dest_client, dest_port, dest, info,
+- connector->number != dest_client->number)) < 0)
++ err = subscribe_port(client, port, grp, &subs->info, ack);
++ if (err < 0) {
++ grp->exclusive = 0;
+ goto __error;
++ }
+
+ /* add to list */
+- write_lock_irqsave(&src->list_lock, flags);
+- // write_lock(&dest->list_lock); // no other lock yet
+- list_add_tail(&subs->src_list, &src->list_head);
+- list_add_tail(&subs->dest_list, &dest->list_head);
+- // write_unlock(&dest->list_lock); // no other lock yet
+- write_unlock_irqrestore(&src->list_lock, flags);
++ write_lock_irq(&grp->list_lock);
++ if (is_src)
++ list_add_tail(&subs->src_list, &grp->list_head);
++ else
++ list_add_tail(&subs->dest_list, &grp->list_head);
++ grp->exclusive = exclusive;
++ atomic_inc(&subs->ref_count);
++ write_unlock_irq(&grp->list_lock);
++ err = 0;
+
+- src->exclusive = dest->exclusive = exclusive;
++ __error:
++ up_write(&grp->list_mutex);
++ return err;
++}
++
++static void delete_and_unsubscribe_port(struct snd_seq_client *client,
++ struct snd_seq_client_port *port,
++ struct snd_seq_subscribers *subs,
++ bool is_src, bool ack)
++{
++ struct snd_seq_port_subs_info *grp;
++ struct list_head *list;
++ bool empty;
++
++ grp = is_src ? &port->c_src : &port->c_dest;
++ list = is_src ? &subs->src_list : &subs->dest_list;
++ down_write(&grp->list_mutex);
++ write_lock_irq(&grp->list_lock);
++ empty = list_empty(list);
++ if (!empty)
++ list_del_init(list);
++ grp->exclusive = 0;
++ write_unlock_irq(&grp->list_lock);
++ up_write(&grp->list_mutex);
++
++ if (!empty)
++ unsubscribe_port(client, port, grp, &subs->info, ack);
++}
++
++/* connect two ports */
++int snd_seq_port_connect(struct snd_seq_client *connector,
++ struct snd_seq_client *src_client,
++ struct snd_seq_client_port *src_port,
++ struct snd_seq_client *dest_client,
++ struct snd_seq_client_port *dest_port,
++ struct snd_seq_port_subscribe *info)
++{
++ struct snd_seq_subscribers *subs;
++ bool exclusive;
++ int err;
++
++ subs = kzalloc(sizeof(*subs), GFP_KERNEL);
++ if (!subs)
++ return -ENOMEM;
++
++ subs->info = *info;
++ atomic_set(&subs->ref_count, 0);
++ INIT_LIST_HEAD(&subs->src_list);
++ INIT_LIST_HEAD(&subs->dest_list);
++
++ exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
++
++ err = check_and_subscribe_port(src_client, src_port, subs, true,
++ exclusive,
++ connector->number != src_client->number);
++ if (err < 0)
++ goto error;
++ err = check_and_subscribe_port(dest_client, dest_port, subs, false,
++ exclusive,
++ connector->number != dest_client->number);
++ if (err < 0)
++ goto error_dest;
+
+- up_write(&dest->list_mutex);
+- up_write(&src->list_mutex);
+ return 0;
+
+- __error:
+- if (src_called)
+- unsubscribe_port(src_client, src_port, src, info,
+- connector->number != src_client->number);
++ error_dest:
++ delete_and_unsubscribe_port(src_client, src_port, subs, true,
++ connector->number != src_client->number);
++ error:
+ kfree(subs);
+- up_write(&dest->list_mutex);
+- up_write(&src->list_mutex);
+ return err;
+ }
+
+-
+ /* remove the connection */
+ int snd_seq_port_disconnect(struct snd_seq_client *connector,
+ struct snd_seq_client *src_client,
+@@ -567,37 +606,28 @@ int snd_seq_port_disconnect(struct snd_s
+ struct snd_seq_port_subscribe *info)
+ {
+ struct snd_seq_port_subs_info *src = &src_port->c_src;
+- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+ struct snd_seq_subscribers *subs;
+ int err = -ENOENT;
+- unsigned long flags;
+
+ down_write(&src->list_mutex);
+- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
+-
+ /* look for the connection */
+ list_for_each_entry(subs, &src->list_head, src_list) {
+ if (match_subs_info(info, &subs->info)) {
+- write_lock_irqsave(&src->list_lock, flags);
+- // write_lock(&dest->list_lock); // no lock yet
+- list_del(&subs->src_list);
+- list_del(&subs->dest_list);
+- // write_unlock(&dest->list_lock);
+- write_unlock_irqrestore(&src->list_lock, flags);
+- src->exclusive = dest->exclusive = 0;
+- unsubscribe_port(src_client, src_port, src, info,
+- connector->number != src_client->number);
+- unsubscribe_port(dest_client, dest_port, dest, info,
+- connector->number != dest_client->number);
+- kfree(subs);
++ atomic_dec(&subs->ref_count); /* mark as not ready */
+ err = 0;
+ break;
+ }
+ }
+-
+- up_write(&dest->list_mutex);
+ up_write(&src->list_mutex);
+- return err;
++ if (err < 0)
++ return err;
++
++ delete_and_unsubscribe_port(src_client, src_port, subs, true,
++ connector->number != src_client->number);
++ delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
++ connector->number != dest_client->number);
++ kfree(subs);
++ return 0;
+ }
+
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/seq_queue.c linux-libre-4.4.7-gnu/sound/core/seq/seq_queue.c
+--- linux-libre-4.4-gnu/sound/core/seq/seq_queue.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/seq_queue.c 2016-04-12 12:09:26.000000000 -0400
+@@ -142,8 +142,10 @@ static struct snd_seq_queue *queue_new(i
+ static void queue_delete(struct snd_seq_queue *q)
+ {
+ /* stop and release the timer */
++ mutex_lock(&q->timer_mutex);
+ snd_seq_timer_stop(q->timer);
+ snd_seq_timer_close(q);
++ mutex_unlock(&q->timer_mutex);
+ /* wait until access free */
+ snd_use_lock_sync(&q->use_lock);
+ /* release resources... */
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/seq_timer.c linux-libre-4.4.7-gnu/sound/core/seq/seq_timer.c
+--- linux-libre-4.4-gnu/sound/core/seq/seq_timer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/seq_timer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -90,6 +90,9 @@ void snd_seq_timer_delete(struct snd_seq
+
+ void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&tmr->lock, flags);
+ /* setup defaults */
+ tmr->ppq = 96; /* 96 PPQ */
+ tmr->tempo = 500000; /* 120 BPM */
+@@ -105,21 +108,25 @@ void snd_seq_timer_defaults(struct snd_s
+ tmr->preferred_resolution = seq_default_timer_resolution;
+
+ tmr->skew = tmr->skew_base = SKEW_BASE;
++ spin_unlock_irqrestore(&tmr->lock, flags);
+ }
+
+-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
++static void seq_timer_reset(struct snd_seq_timer *tmr)
+ {
+- unsigned long flags;
+-
+- spin_lock_irqsave(&tmr->lock, flags);
+-
+ /* reset time & songposition */
+ tmr->cur_time.tv_sec = 0;
+ tmr->cur_time.tv_nsec = 0;
+
+ tmr->tick.cur_tick = 0;
+ tmr->tick.fraction = 0;
++}
+
++void snd_seq_timer_reset(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&tmr->lock, flags);
++ seq_timer_reset(tmr);
+ spin_unlock_irqrestore(&tmr->lock, flags);
+ }
+
+@@ -138,8 +145,11 @@ static void snd_seq_timer_interrupt(stru
+ tmr = q->timer;
+ if (tmr == NULL)
+ return;
+- if (!tmr->running)
++ spin_lock_irqsave(&tmr->lock, flags);
++ if (!tmr->running) {
++ spin_unlock_irqrestore(&tmr->lock, flags);
+ return;
++ }
+
+ resolution *= ticks;
+ if (tmr->skew != tmr->skew_base) {
+@@ -148,8 +158,6 @@ static void snd_seq_timer_interrupt(stru
+ (((resolution & 0xffff) * tmr->skew) >> 16);
+ }
+
+- spin_lock_irqsave(&tmr->lock, flags);
+-
+ /* update timer */
+ snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
+
+@@ -296,26 +304,30 @@ int snd_seq_timer_open(struct snd_seq_qu
+ t->callback = snd_seq_timer_interrupt;
+ t->callback_data = q;
+ t->flags |= SNDRV_TIMER_IFLG_AUTO;
++ spin_lock_irq(&tmr->lock);
+ tmr->timeri = t;
++ spin_unlock_irq(&tmr->lock);
+ return 0;
+ }
+
+ int snd_seq_timer_close(struct snd_seq_queue *q)
+ {
+ struct snd_seq_timer *tmr;
++ struct snd_timer_instance *t;
+
+ tmr = q->timer;
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
+- if (tmr->timeri) {
+- snd_timer_stop(tmr->timeri);
+- snd_timer_close(tmr->timeri);
+- tmr->timeri = NULL;
+- }
++ spin_lock_irq(&tmr->lock);
++ t = tmr->timeri;
++ tmr->timeri = NULL;
++ spin_unlock_irq(&tmr->lock);
++ if (t)
++ snd_timer_close(t);
+ return 0;
+ }
+
+-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
++static int seq_timer_stop(struct snd_seq_timer *tmr)
+ {
+ if (! tmr->timeri)
+ return -EINVAL;
+@@ -326,6 +338,17 @@ int snd_seq_timer_stop(struct snd_seq_ti
+ return 0;
+ }
+
++int snd_seq_timer_stop(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&tmr->lock, flags);
++ err = seq_timer_stop(tmr);
++ spin_unlock_irqrestore(&tmr->lock, flags);
++ return err;
++}
++
+ static int initialize_timer(struct snd_seq_timer *tmr)
+ {
+ struct snd_timer *t;
+@@ -358,13 +381,13 @@ static int initialize_timer(struct snd_s
+ return 0;
+ }
+
+-int snd_seq_timer_start(struct snd_seq_timer * tmr)
++static int seq_timer_start(struct snd_seq_timer *tmr)
+ {
+ if (! tmr->timeri)
+ return -EINVAL;
+ if (tmr->running)
+- snd_seq_timer_stop(tmr);
+- snd_seq_timer_reset(tmr);
++ seq_timer_stop(tmr);
++ seq_timer_reset(tmr);
+ if (initialize_timer(tmr) < 0)
+ return -EINVAL;
+ snd_timer_start(tmr->timeri, tmr->ticks);
+@@ -373,14 +396,25 @@ int snd_seq_timer_start(struct snd_seq_t
+ return 0;
+ }
+
+-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
++int snd_seq_timer_start(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&tmr->lock, flags);
++ err = seq_timer_start(tmr);
++ spin_unlock_irqrestore(&tmr->lock, flags);
++ return err;
++}
++
++static int seq_timer_continue(struct snd_seq_timer *tmr)
+ {
+ if (! tmr->timeri)
+ return -EINVAL;
+ if (tmr->running)
+ return -EBUSY;
+ if (! tmr->initialized) {
+- snd_seq_timer_reset(tmr);
++ seq_timer_reset(tmr);
+ if (initialize_timer(tmr) < 0)
+ return -EINVAL;
+ }
+@@ -390,11 +424,24 @@ int snd_seq_timer_continue(struct snd_se
+ return 0;
+ }
+
++int snd_seq_timer_continue(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&tmr->lock, flags);
++ err = seq_timer_continue(tmr);
++ spin_unlock_irqrestore(&tmr->lock, flags);
++ return err;
++}
++
+ /* return current 'real' time. use timeofday() to get better granularity. */
+ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
+ {
+ snd_seq_real_time_t cur_time;
++ unsigned long flags;
+
++ spin_lock_irqsave(&tmr->lock, flags);
+ cur_time = tmr->cur_time;
+ if (tmr->running) {
+ struct timeval tm;
+@@ -410,7 +457,7 @@ snd_seq_real_time_t snd_seq_timer_get_cu
+ }
+ snd_seq_sanity_real_time(&cur_time);
+ }
+-
++ spin_unlock_irqrestore(&tmr->lock, flags);
+ return cur_time;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/seq/seq_virmidi.c linux-libre-4.4.7-gnu/sound/core/seq/seq_virmidi.c
+--- linux-libre-4.4-gnu/sound/core/seq/seq_virmidi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/seq/seq_virmidi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -155,21 +155,26 @@ static void snd_virmidi_output_trigger(s
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
+ int count, res;
+ unsigned char buf[32], *pbuf;
++ unsigned long flags;
+
+ if (up) {
+ vmidi->trigger = 1;
+ if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
+ !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
+- snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail);
+- return; /* ignored */
++ while (snd_rawmidi_transmit(substream, buf,
++ sizeof(buf)) > 0) {
++ /* ignored */
++ }
++ return;
+ }
+ if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+ return;
+ vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+ }
++ spin_lock_irqsave(&substream->runtime->lock, flags);
+ while (1) {
+- count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
++ count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
+ if (count <= 0)
+ break;
+ pbuf = buf;
+@@ -179,16 +184,18 @@ static void snd_virmidi_output_trigger(s
+ snd_midi_event_reset_encode(vmidi->parser);
+ continue;
+ }
+- snd_rawmidi_transmit_ack(substream, res);
++ __snd_rawmidi_transmit_ack(substream, res);
+ pbuf += res;
+ count -= res;
+ if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+- return;
++ goto out;
+ vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+ }
+ }
+ }
++ out:
++ spin_unlock_irqrestore(&substream->runtime->lock, flags);
+ } else {
+ vmidi->trigger = 0;
+ }
+@@ -254,9 +261,13 @@ static int snd_virmidi_output_open(struc
+ */
+ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
+ {
++ struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
+- snd_midi_event_free(vmidi->parser);
++
++ write_lock_irq(&rdev->filelist_lock);
+ list_del(&vmidi->list);
++ write_unlock_irq(&rdev->filelist_lock);
++ snd_midi_event_free(vmidi->parser);
+ substream->runtime->private_data = NULL;
+ kfree(vmidi);
+ return 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/timer.c linux-libre-4.4.7-gnu/sound/core/timer.c
+--- linux-libre-4.4-gnu/sound/core/timer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/timer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -65,6 +65,7 @@ struct snd_timer_user {
+ int qtail;
+ int qused;
+ int queue_size;
++ bool disconnected;
+ struct snd_timer_read *queue;
+ struct snd_timer_tread *tqueue;
+ spinlock_t qlock;
+@@ -73,7 +74,7 @@ struct snd_timer_user {
+ struct timespec tstamp; /* trigger tstamp */
+ wait_queue_head_t qchange_sleep;
+ struct fasync_struct *fasync;
+- struct mutex tread_sem;
++ struct mutex ioctl_lock;
+ };
+
+ /* list of timers */
+@@ -215,11 +216,13 @@ static void snd_timer_check_master(struc
+ slave->slave_id == master->slave_id) {
+ list_move_tail(&slave->open_list, &master->slave_list_head);
+ spin_lock_irq(&slave_active_lock);
++ spin_lock(&master->timer->lock);
+ slave->master = master;
+ slave->timer = master->timer;
+ if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
+ list_add_tail(&slave->active_list,
+ &master->slave_active_head);
++ spin_unlock(&master->timer->lock);
+ spin_unlock_irq(&slave_active_lock);
+ }
+ }
+@@ -288,6 +291,9 @@ int snd_timer_open(struct snd_timer_inst
+ mutex_unlock(&register_mutex);
+ return -ENOMEM;
+ }
++ /* take a card refcount for safe disconnection */
++ if (timer->card)
++ get_device(&timer->card->card_dev);
+ timeri->slave_class = tid->dev_sclass;
+ timeri->slave_id = slave_id;
+ if (list_empty(&timer->open_list_head) && timer->hw.open)
+@@ -299,8 +305,7 @@ int snd_timer_open(struct snd_timer_inst
+ return 0;
+ }
+
+-static int _snd_timer_stop(struct snd_timer_instance *timeri,
+- int keep_flag, int event);
++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event);
+
+ /*
+ * close a timer instance
+@@ -342,19 +347,25 @@ int snd_timer_close(struct snd_timer_ins
+ spin_unlock_irq(&timer->lock);
+ mutex_lock(&register_mutex);
+ list_del(&timeri->open_list);
+- if (timer && list_empty(&timer->open_list_head) &&
++ if (list_empty(&timer->open_list_head) &&
+ timer->hw.close)
+ timer->hw.close(timer);
+ /* remove slave links */
++ spin_lock_irq(&slave_active_lock);
++ spin_lock(&timer->lock);
+ list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
+ open_list) {
+- spin_lock_irq(&slave_active_lock);
+- _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
+ list_move_tail(&slave->open_list, &snd_timer_slave_list);
+ slave->master = NULL;
+ slave->timer = NULL;
+- spin_unlock_irq(&slave_active_lock);
++ list_del_init(&slave->ack_list);
++ list_del_init(&slave->active_list);
+ }
++ spin_unlock(&timer->lock);
++ spin_unlock_irq(&slave_active_lock);
++ /* release a card refcount for safe disconnection */
++ if (timer->card)
++ put_device(&timer->card->card_dev);
+ mutex_unlock(&register_mutex);
+ }
+ out:
+@@ -411,7 +422,7 @@ static void snd_timer_notify1(struct snd
+ spin_lock_irqsave(&timer->lock, flags);
+ list_for_each_entry(ts, &ti->slave_active_head, active_list)
+ if (ts->ccallback)
+- ts->ccallback(ti, event + 100, &tstamp, resolution);
++ ts->ccallback(ts, event + 100, &tstamp, resolution);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ }
+
+@@ -440,10 +451,17 @@ static int snd_timer_start_slave(struct
+ unsigned long flags;
+
+ spin_lock_irqsave(&slave_active_lock, flags);
++ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
++ spin_unlock_irqrestore(&slave_active_lock, flags);
++ return -EBUSY;
++ }
+ timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
+- if (timeri->master)
++ if (timeri->master && timeri->timer) {
++ spin_lock(&timeri->timer->lock);
+ list_add_tail(&timeri->active_list,
+ &timeri->master->slave_active_head);
++ spin_unlock(&timeri->timer->lock);
++ }
+ spin_unlock_irqrestore(&slave_active_lock, flags);
+ return 1; /* delayed start */
+ }
+@@ -461,23 +479,32 @@ int snd_timer_start(struct snd_timer_ins
+ return -EINVAL;
+ if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
+ result = snd_timer_start_slave(timeri);
+- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
++ if (result >= 0)
++ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+ return result;
+ }
+ timer = timeri->timer;
+ if (timer == NULL)
+ return -EINVAL;
++ if (timer->card && timer->card->shutdown)
++ return -ENODEV;
+ spin_lock_irqsave(&timer->lock, flags);
++ if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
++ SNDRV_TIMER_IFLG_START)) {
++ result = -EBUSY;
++ goto unlock;
++ }
+ timeri->ticks = timeri->cticks = ticks;
+ timeri->pticks = 0;
+ result = snd_timer_start1(timer, timeri, ticks);
++ unlock:
+ spin_unlock_irqrestore(&timer->lock, flags);
+- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
++ if (result >= 0)
++ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+ return result;
+ }
+
+-static int _snd_timer_stop(struct snd_timer_instance * timeri,
+- int keep_flag, int event)
++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
+ {
+ struct snd_timer *timer;
+ unsigned long flags;
+@@ -486,19 +513,36 @@ static int _snd_timer_stop(struct snd_ti
+ return -ENXIO;
+
+ if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
+- if (!keep_flag) {
+- spin_lock_irqsave(&slave_active_lock, flags);
+- timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
++ spin_lock_irqsave(&slave_active_lock, flags);
++ if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
+ spin_unlock_irqrestore(&slave_active_lock, flags);
++ return -EBUSY;
+ }
++ if (timeri->timer)
++ spin_lock(&timeri->timer->lock);
++ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
++ list_del_init(&timeri->ack_list);
++ list_del_init(&timeri->active_list);
++ if (timeri->timer)
++ spin_unlock(&timeri->timer->lock);
++ spin_unlock_irqrestore(&slave_active_lock, flags);
+ goto __end;
+ }
+ timer = timeri->timer;
+ if (!timer)
+ return -EINVAL;
+ spin_lock_irqsave(&timer->lock, flags);
++ if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
++ SNDRV_TIMER_IFLG_START))) {
++ spin_unlock_irqrestore(&timer->lock, flags);
++ return -EBUSY;
++ }
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
++ if (timer->card && timer->card->shutdown) {
++ spin_unlock_irqrestore(&timer->lock, flags);
++ return 0;
++ }
+ if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
+ !(--timer->running)) {
+ timer->hw.stop(timer);
+@@ -511,9 +555,7 @@ static int _snd_timer_stop(struct snd_ti
+ }
+ }
+ }
+- if (!keep_flag)
+- timeri->flags &=
+- ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
++ timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ __end:
+ if (event != SNDRV_TIMER_EVENT_RESOLUTION)
+@@ -532,7 +574,7 @@ int snd_timer_stop(struct snd_timer_inst
+ unsigned long flags;
+ int err;
+
+- err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
++ err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP);
+ if (err < 0)
+ return err;
+ timer = timeri->timer;
+@@ -561,11 +603,18 @@ int snd_timer_continue(struct snd_timer_
+ timer = timeri->timer;
+ if (! timer)
+ return -EINVAL;
++ if (timer->card && timer->card->shutdown)
++ return -ENODEV;
+ spin_lock_irqsave(&timer->lock, flags);
++ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
++ result = -EBUSY;
++ goto unlock;
++ }
+ if (!timeri->cticks)
+ timeri->cticks = 1;
+ timeri->pticks = 0;
+ result = snd_timer_start1(timer, timeri, timer->sticks);
++ unlock:
+ spin_unlock_irqrestore(&timer->lock, flags);
+ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
+ return result;
+@@ -576,7 +625,7 @@ int snd_timer_continue(struct snd_timer_
+ */
+ int snd_timer_pause(struct snd_timer_instance * timeri)
+ {
+- return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
++ return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE);
+ }
+
+ /*
+@@ -624,6 +673,9 @@ static void snd_timer_tasklet(unsigned l
+ unsigned long resolution, ticks;
+ unsigned long flags;
+
++ if (timer->card && timer->card->shutdown)
++ return;
++
+ spin_lock_irqsave(&timer->lock, flags);
+ /* now process all callbacks */
+ while (!list_empty(&timer->sack_list_head)) {
+@@ -664,6 +716,9 @@ void snd_timer_interrupt(struct snd_time
+ if (timer == NULL)
+ return;
+
++ if (timer->card && timer->card->shutdown)
++ return;
++
+ spin_lock_irqsave(&timer->lock, flags);
+
+ /* remember the current resolution */
+@@ -693,8 +748,8 @@ void snd_timer_interrupt(struct snd_time
+ ti->cticks = ti->ticks;
+ } else {
+ ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+- if (--timer->running)
+- list_del(&ti->active_list);
++ --timer->running;
++ list_del_init(&ti->active_list);
+ }
+ if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
+ (ti->flags & SNDRV_TIMER_IFLG_FAST))
+@@ -874,11 +929,28 @@ static int snd_timer_dev_register(struct
+ return 0;
+ }
+
++/* just for reference in snd_timer_dev_disconnect() below */
++static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
++ int event, struct timespec *tstamp,
++ unsigned long resolution);
++
+ static int snd_timer_dev_disconnect(struct snd_device *device)
+ {
+ struct snd_timer *timer = device->device_data;
++ struct snd_timer_instance *ti;
++
+ mutex_lock(&register_mutex);
+ list_del_init(&timer->device_list);
++ /* wake up pending sleepers */
++ list_for_each_entry(ti, &timer->open_list_head, open_list) {
++ /* FIXME: better to have a ti.disconnect() op */
++ if (ti->ccallback == snd_timer_user_ccallback) {
++ struct snd_timer_user *tu = ti->callback_data;
++
++ tu->disconnected = true;
++ wake_up(&tu->qchange_sleep);
++ }
++ }
+ mutex_unlock(&register_mutex);
+ return 0;
+ }
+@@ -889,6 +961,8 @@ void snd_timer_notify(struct snd_timer *
+ unsigned long resolution = 0;
+ struct snd_timer_instance *ti, *ts;
+
++ if (timer->card && timer->card->shutdown)
++ return;
+ if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
+ return;
+ if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_MSTART ||
+@@ -1047,6 +1121,8 @@ static void snd_timer_proc_read(struct s
+
+ mutex_lock(&register_mutex);
+ list_for_each_entry(timer, &snd_timer_list, device_list) {
++ if (timer->card && timer->card->shutdown)
++ continue;
+ switch (timer->tmr_class) {
+ case SNDRV_TIMER_CLASS_GLOBAL:
+ snd_iprintf(buffer, "G%i: ", timer->tmr_device);
+@@ -1253,7 +1329,7 @@ static int snd_timer_user_open(struct in
+ return -ENOMEM;
+ spin_lock_init(&tu->qlock);
+ init_waitqueue_head(&tu->qchange_sleep);
+- mutex_init(&tu->tread_sem);
++ mutex_init(&tu->ioctl_lock);
+ tu->ticks = 1;
+ tu->queue_size = 128;
+ tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
+@@ -1273,8 +1349,10 @@ static int snd_timer_user_release(struct
+ if (file->private_data) {
+ tu = file->private_data;
+ file->private_data = NULL;
++ mutex_lock(&tu->ioctl_lock);
+ if (tu->timeri)
+ snd_timer_close(tu->timeri);
++ mutex_unlock(&tu->ioctl_lock);
+ kfree(tu->queue);
+ kfree(tu->tqueue);
+ kfree(tu);
+@@ -1512,7 +1590,6 @@ static int snd_timer_user_tselect(struct
+ int err = 0;
+
+ tu = file->private_data;
+- mutex_lock(&tu->tread_sem);
+ if (tu->timeri) {
+ snd_timer_close(tu->timeri);
+ tu->timeri = NULL;
+@@ -1556,7 +1633,6 @@ static int snd_timer_user_tselect(struct
+ }
+
+ __err:
+- mutex_unlock(&tu->tread_sem);
+ return err;
+ }
+
+@@ -1769,7 +1845,7 @@ enum {
+ SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
+ };
+
+-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
++static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+ {
+ struct snd_timer_user *tu;
+@@ -1786,17 +1862,11 @@ static long snd_timer_user_ioctl(struct
+ {
+ int xarg;
+
+- mutex_lock(&tu->tread_sem);
+- if (tu->timeri) { /* too late */
+- mutex_unlock(&tu->tread_sem);
++ if (tu->timeri) /* too late */
+ return -EBUSY;
+- }
+- if (get_user(xarg, p)) {
+- mutex_unlock(&tu->tread_sem);
++ if (get_user(xarg, p))
+ return -EFAULT;
+- }
+ tu->tread = xarg ? 1 : 0;
+- mutex_unlock(&tu->tread_sem);
+ return 0;
+ }
+ case SNDRV_TIMER_IOCTL_GINFO:
+@@ -1829,6 +1899,18 @@ static long snd_timer_user_ioctl(struct
+ return -ENOTTY;
+ }
+
++static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct snd_timer_user *tu = file->private_data;
++ long ret;
++
++ mutex_lock(&tu->ioctl_lock);
++ ret = __snd_timer_user_ioctl(file, cmd, arg);
++ mutex_unlock(&tu->ioctl_lock);
++ return ret;
++}
++
+ static int snd_timer_user_fasync(int fd, struct file * file, int on)
+ {
+ struct snd_timer_user *tu;
+@@ -1842,6 +1924,7 @@ static ssize_t snd_timer_user_read(struc
+ {
+ struct snd_timer_user *tu;
+ long result = 0, unit;
++ int qhead;
+ int err = 0;
+
+ tu = file->private_data;
+@@ -1853,7 +1936,7 @@ static ssize_t snd_timer_user_read(struc
+
+ if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
+ err = -EAGAIN;
+- break;
++ goto _error;
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -1866,40 +1949,39 @@ static ssize_t snd_timer_user_read(struc
+
+ remove_wait_queue(&tu->qchange_sleep, &wait);
+
++ if (tu->disconnected) {
++ err = -ENODEV;
++ goto _error;
++ }
+ if (signal_pending(current)) {
+ err = -ERESTARTSYS;
+- break;
++ goto _error;
+ }
+ }
+
++ qhead = tu->qhead++;
++ tu->qhead %= tu->queue_size;
+ spin_unlock_irq(&tu->qlock);
+- if (err < 0)
+- goto _error;
+
+ if (tu->tread) {
+- if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
+- sizeof(struct snd_timer_tread))) {
++ if (copy_to_user(buffer, &tu->tqueue[qhead],
++ sizeof(struct snd_timer_tread)))
+ err = -EFAULT;
+- goto _error;
+- }
+ } else {
+- if (copy_to_user(buffer, &tu->queue[tu->qhead++],
+- sizeof(struct snd_timer_read))) {
++ if (copy_to_user(buffer, &tu->queue[qhead],
++ sizeof(struct snd_timer_read)))
+ err = -EFAULT;
+- goto _error;
+- }
+ }
+
+- tu->qhead %= tu->queue_size;
+-
+- result += unit;
+- buffer += unit;
+-
+ spin_lock_irq(&tu->qlock);
+ tu->qused--;
++ if (err < 0)
++ goto _error;
++ result += unit;
++ buffer += unit;
+ }
+- spin_unlock_irq(&tu->qlock);
+ _error:
++ spin_unlock_irq(&tu->qlock);
+ return result > 0 ? result : err;
+ }
+
+@@ -1915,6 +1997,8 @@ static unsigned int snd_timer_user_poll(
+ mask = 0;
+ if (tu->qused)
+ mask |= POLLIN | POLLRDNORM;
++ if (tu->disconnected)
++ mask |= POLLERR;
+
+ return mask;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/core/timer_compat.c linux-libre-4.4.7-gnu/sound/core/timer_compat.c
+--- linux-libre-4.4-gnu/sound/core/timer_compat.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/core/timer_compat.c 2016-04-12 12:09:26.000000000 -0400
+@@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(
+ struct snd_timer_status32 __user *_status)
+ {
+ struct snd_timer_user *tu;
+- struct snd_timer_status status;
++ struct snd_timer_status32 status;
+
+ tu = file->private_data;
+ if (snd_BUG_ON(!tu->timeri))
+ return -ENXIO;
+ memset(&status, 0, sizeof(status));
+- status.tstamp = tu->tstamp;
++ status.tstamp.tv_sec = tu->tstamp.tv_sec;
++ status.tstamp.tv_nsec = tu->tstamp.tv_nsec;
+ status.resolution = snd_timer_resolution(tu->timeri);
+ status.lost = tu->timeri->lost;
+ status.overrun = tu->overrun;
+@@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(
+ return 0;
+ }
+
++#ifdef CONFIG_X86_X32
++/* X32 ABI has the same struct as x86-64 */
++#define snd_timer_user_status_x32(file, s) \
++ snd_timer_user_status(file, s)
++#endif /* CONFIG_X86_X32 */
++
+ /*
+ */
+
+ enum {
+ SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
+ SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
++#ifdef CONFIG_X86_X32
++ SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status),
++#endif /* CONFIG_X86_X32 */
+ };
+
+ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+@@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(
+ return snd_timer_user_info_compat(file, argp);
+ case SNDRV_TIMER_IOCTL_STATUS32:
+ return snd_timer_user_status_compat(file, argp);
++#ifdef CONFIG_X86_X32
++ case SNDRV_TIMER_IOCTL_STATUS_X32:
++ return snd_timer_user_status_x32(file, argp);
++#endif /* CONFIG_X86_X32 */
+ }
+ return -ENOIOCTLCMD;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/drivers/dummy.c linux-libre-4.4.7-gnu/sound/drivers/dummy.c
+--- linux-libre-4.4-gnu/sound/drivers/dummy.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/drivers/dummy.c 2016-04-12 12:09:26.000000000 -0400
+@@ -109,6 +109,9 @@ struct dummy_timer_ops {
+ snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
+ };
+
++#define get_dummy_ops(substream) \
++ (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
++
+ struct dummy_model {
+ const char *name;
+ int (*playback_constraints)(struct snd_pcm_runtime *runtime);
+@@ -137,7 +140,6 @@ struct snd_dummy {
+ int iobox;
+ struct snd_kcontrol *cd_volume_ctl;
+ struct snd_kcontrol *cd_switch_ctl;
+- const struct dummy_timer_ops *timer_ops;
+ };
+
+ /*
+@@ -231,6 +233,8 @@ static struct dummy_model *dummy_models[
+ */
+
+ struct dummy_systimer_pcm {
++ /* ops must be the first item */
++ const struct dummy_timer_ops *timer_ops;
+ spinlock_t lock;
+ struct timer_list timer;
+ unsigned long base_time;
+@@ -366,6 +370,8 @@ static struct dummy_timer_ops dummy_syst
+ */
+
+ struct dummy_hrtimer_pcm {
++ /* ops must be the first item */
++ const struct dummy_timer_ops *timer_ops;
+ ktime_t base_time;
+ ktime_t period_time;
+ atomic_t running;
+@@ -492,31 +498,25 @@ static struct dummy_timer_ops dummy_hrti
+
+ static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+- return dummy->timer_ops->start(substream);
++ return get_dummy_ops(substream)->start(substream);
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+- return dummy->timer_ops->stop(substream);
++ return get_dummy_ops(substream)->stop(substream);
+ }
+ return -EINVAL;
+ }
+
+ static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+- return dummy->timer_ops->prepare(substream);
++ return get_dummy_ops(substream)->prepare(substream);
+ }
+
+ static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+- return dummy->timer_ops->pointer(substream);
++ return get_dummy_ops(substream)->pointer(substream);
+ }
+
+ static struct snd_pcm_hardware dummy_pcm_hardware = {
+@@ -562,17 +562,19 @@ static int dummy_pcm_open(struct snd_pcm
+ struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+ struct dummy_model *model = dummy->model;
+ struct snd_pcm_runtime *runtime = substream->runtime;
++ const struct dummy_timer_ops *ops;
+ int err;
+
+- dummy->timer_ops = &dummy_systimer_ops;
++ ops = &dummy_systimer_ops;
+ #ifdef CONFIG_HIGH_RES_TIMERS
+ if (hrtimer)
+- dummy->timer_ops = &dummy_hrtimer_ops;
++ ops = &dummy_hrtimer_ops;
+ #endif
+
+- err = dummy->timer_ops->create(substream);
++ err = ops->create(substream);
+ if (err < 0)
+ return err;
++ get_dummy_ops(substream) = ops;
+
+ runtime->hw = dummy->pcm_hw;
+ if (substream->pcm->device & 1) {
+@@ -594,7 +596,7 @@ static int dummy_pcm_open(struct snd_pcm
+ err = model->capture_constraints(substream->runtime);
+ }
+ if (err < 0) {
+- dummy->timer_ops->free(substream);
++ get_dummy_ops(substream)->free(substream);
+ return err;
+ }
+ return 0;
+@@ -602,8 +604,7 @@ static int dummy_pcm_open(struct snd_pcm
+
+ static int dummy_pcm_close(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+- dummy->timer_ops->free(substream);
++ get_dummy_ops(substream)->free(substream);
+ return 0;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/firewire/bebob/bebob_stream.c linux-libre-4.4.7-gnu/sound/firewire/bebob/bebob_stream.c
+--- linux-libre-4.4-gnu/sound/firewire/bebob/bebob_stream.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/firewire/bebob/bebob_stream.c 2016-04-12 12:09:26.000000000 -0400
+@@ -47,14 +47,16 @@ static const unsigned int bridgeco_freq_
+ [6] = 0x07,
+ };
+
+-static unsigned int
+-get_formation_index(unsigned int rate)
++static int
++get_formation_index(unsigned int rate, unsigned int *index)
+ {
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) {
+- if (snd_bebob_rate_table[i] == rate)
+- return i;
++ if (snd_bebob_rate_table[i] == rate) {
++ *index = i;
++ return 0;
++ }
+ }
+ return -EINVAL;
+ }
+@@ -425,7 +427,9 @@ make_both_connections(struct snd_bebob *
+ goto end;
+
+ /* confirm params for both streams */
+- index = get_formation_index(rate);
++ err = get_formation_index(rate, &index);
++ if (err < 0)
++ goto end;
+ pcm_channels = bebob->tx_stream_formations[index].pcm;
+ midi_channels = bebob->tx_stream_formations[index].midi;
+ err = amdtp_am824_set_parameters(&bebob->tx_stream, rate,
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/isa/Kconfig linux-libre-4.4.7-gnu/sound/isa/Kconfig
+--- linux-libre-4.4-gnu/sound/isa/Kconfig 2016-01-10 21:18:01.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/isa/Kconfig 2016-04-12 21:33:40.000000000 -0400
+@@ -3,6 +3,7 @@
+ config SND_WSS_LIB
+ tristate
+ select SND_PCM
++ select SND_TIMER
+
+ config SND_SB_COMMON
+ tristate
+@@ -42,6 +43,7 @@ config SND_AD1816A
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_PCM
++ select SND_TIMER
+ help
+ Say Y here to include support for Analog Devices SoundPort
+ AD1816A or compatible sound chips.
+@@ -209,6 +211,7 @@ config SND_GUSCLASSIC
+ tristate "Gravis UltraSound Classic"
+ select SND_RAWMIDI
+ select SND_PCM
++ select SND_TIMER
+ help
+ Say Y here to include support for Gravis UltraSound Classic
+ soundcards.
+@@ -221,6 +224,7 @@ config SND_GUSEXTREME
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_PCM
++ select SND_TIMER
+ help
+ Say Y here to include support for Gravis UltraSound Extreme
+ soundcards.
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/hda_bind.c linux-libre-4.4.7-gnu/sound/pci/hda/hda_bind.c
+--- linux-libre-4.4-gnu/sound/pci/hda/hda_bind.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/hda_bind.c 2016-04-12 12:09:26.000000000 -0400
+@@ -174,14 +174,40 @@ static inline bool codec_probed(struct h
+ return device_attach(hda_codec_dev(codec)) > 0 && codec->preset;
+ }
+
+-/* try to auto-load and bind the codec module */
+-static void codec_bind_module(struct hda_codec *codec)
++/* try to auto-load codec module */
++static void request_codec_module(struct hda_codec *codec)
+ {
+ #ifdef MODULE
+ char modalias[32];
++ const char *mod = NULL;
+
+- snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias));
+- request_module(modalias);
++ switch (codec->probe_id) {
++ case HDA_CODEC_ID_GENERIC_HDMI:
++#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
++ mod = "snd-hda-codec-hdmi";
++#endif
++ break;
++ case HDA_CODEC_ID_GENERIC:
++#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
++ mod = "snd-hda-codec-generic";
++#endif
++ break;
++ default:
++ snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias));
++ mod = modalias;
++ break;
++ }
++
++ if (mod)
++ request_module(mod);
++#endif /* MODULE */
++}
++
++/* try to auto-load and bind the codec module */
++static void codec_bind_module(struct hda_codec *codec)
++{
++#ifdef MODULE
++ request_codec_module(codec);
+ if (codec_probed(codec))
+ return;
+ #endif
+@@ -218,17 +244,13 @@ static int codec_bind_generic(struct hda
+
+ if (is_likely_hdmi_codec(codec)) {
+ codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI;
+-#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
+- request_module("snd-hda-codec-hdmi");
+-#endif
++ request_codec_module(codec);
+ if (codec_probed(codec))
+ return 0;
+ }
+
+ codec->probe_id = HDA_CODEC_ID_GENERIC;
+-#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
+- request_module("snd-hda-codec-generic");
+-#endif
++ request_codec_module(codec);
+ if (codec_probed(codec))
+ return 0;
+ return -ENODEV;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/hda_generic.c linux-libre-4.4.7-gnu/sound/pci/hda/hda_generic.c
+--- linux-libre-4.4-gnu/sound/pci/hda/hda_generic.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/hda_generic.c 2016-04-12 12:09:26.000000000 -0400
+@@ -771,9 +771,6 @@ static void activate_amp(struct hda_code
+ unsigned int caps;
+ unsigned int mask, val;
+
+- if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
+- return;
+-
+ caps = query_amp_caps(codec, nid, dir);
+ val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
+ mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
+@@ -784,12 +781,22 @@ static void activate_amp(struct hda_code
+ update_amp(codec, nid, dir, idx, mask, val);
+ }
+
++static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
++ int dir, int idx, int idx_to_check,
++ bool enable)
++{
++ /* check whether the given amp is still used by others */
++ if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
++ return;
++ activate_amp(codec, nid, dir, idx, idx_to_check, enable);
++}
++
+ static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
+ int i, bool enable)
+ {
+ hda_nid_t nid = path->path[i];
+ init_amp(codec, nid, HDA_OUTPUT, 0);
+- activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
++ check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
+ }
+
+ static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
+@@ -817,9 +824,16 @@ static void activate_amp_in(struct hda_c
+ * when aa-mixer is available, we need to enable the path as well
+ */
+ for (n = 0; n < nums; n++) {
+- if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
+- continue;
+- activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
++ if (n != idx) {
++ if (conn[n] != spec->mixer_merge_nid)
++ continue;
++ /* when aamix is disabled, force to off */
++ if (!add_aamix) {
++ activate_amp(codec, nid, HDA_INPUT, n, n, false);
++ continue;
++ }
++ }
++ check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
+ }
+ }
+
+@@ -1580,6 +1594,12 @@ static bool map_singles(struct hda_codec
+ return found;
+ }
+
++static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
++{
++ return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
++ spec->aamix_out_paths[2];
++}
++
+ /* create a new path including aamix if available, and return its index */
+ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
+ {
+@@ -2422,25 +2442,51 @@ static void update_aamix_paths(struct hd
+ }
+ }
+
++/* re-initialize the output paths; only called from loopback_mixing_put() */
++static void update_output_paths(struct hda_codec *codec, int num_outs,
++ const int *paths)
++{
++ struct hda_gen_spec *spec = codec->spec;
++ struct nid_path *path;
++ int i;
++
++ for (i = 0; i < num_outs; i++) {
++ path = snd_hda_get_path_from_idx(codec, paths[i]);
++ if (path)
++ snd_hda_activate_path(codec, path, path->active,
++ spec->aamix_mode);
++ }
++}
++
+ static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_gen_spec *spec = codec->spec;
++ const struct auto_pin_cfg *cfg = &spec->autocfg;
+ unsigned int val = ucontrol->value.enumerated.item[0];
+
+ if (val == spec->aamix_mode)
+ return 0;
+ spec->aamix_mode = val;
+- update_aamix_paths(codec, val, spec->out_paths[0],
+- spec->aamix_out_paths[0],
+- spec->autocfg.line_out_type);
+- update_aamix_paths(codec, val, spec->hp_paths[0],
+- spec->aamix_out_paths[1],
+- AUTO_PIN_HP_OUT);
+- update_aamix_paths(codec, val, spec->speaker_paths[0],
+- spec->aamix_out_paths[2],
+- AUTO_PIN_SPEAKER_OUT);
++ if (has_aamix_out_paths(spec)) {
++ update_aamix_paths(codec, val, spec->out_paths[0],
++ spec->aamix_out_paths[0],
++ cfg->line_out_type);
++ update_aamix_paths(codec, val, spec->hp_paths[0],
++ spec->aamix_out_paths[1],
++ AUTO_PIN_HP_OUT);
++ update_aamix_paths(codec, val, spec->speaker_paths[0],
++ spec->aamix_out_paths[2],
++ AUTO_PIN_SPEAKER_OUT);
++ } else {
++ update_output_paths(codec, cfg->line_outs, spec->out_paths);
++ if (cfg->line_out_type != AUTO_PIN_HP_OUT)
++ update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
++ if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
++ update_output_paths(codec, cfg->speaker_outs,
++ spec->speaker_paths);
++ }
+ return 1;
+ }
+
+@@ -2458,12 +2504,13 @@ static int create_loopback_mixing_ctl(st
+
+ if (!spec->mixer_nid)
+ return 0;
+- if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
+- spec->aamix_out_paths[2]))
+- return 0;
+ if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
+ return -ENOMEM;
+ spec->have_aamix_ctl = 1;
++ /* if no explicit aamix path is present (e.g. for Realtek codecs),
++ * enable aamix as default -- just for compatibility
++ */
++ spec->aamix_mode = !has_aamix_out_paths(spec);
+ return 0;
+ }
+
+@@ -3998,9 +4045,9 @@ static void pin_power_callback(struct hd
+ struct hda_jack_callback *jack,
+ bool on)
+ {
+- if (jack && jack->tbl->nid)
++ if (jack && jack->nid)
+ sync_power_state_change(codec,
+- set_pin_power_jack(codec, jack->tbl->nid, on));
++ set_pin_power_jack(codec, jack->nid, on));
+ }
+
+ /* callback only doing power up -- called at first */
+@@ -5664,6 +5711,8 @@ static void init_aamix_paths(struct hda_
+
+ if (!spec->have_aamix_ctl)
+ return;
++ if (!has_aamix_out_paths(spec))
++ return;
+ update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
+ spec->aamix_out_paths[0],
+ spec->autocfg.line_out_type);
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/hda_intel.c linux-libre-4.4.7-gnu/sound/pci/hda/hda_intel.c
+--- linux-libre-4.4-gnu/sound/pci/hda/hda_intel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/hda_intel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -90,6 +90,8 @@ enum {
+ #define NVIDIA_HDA_ENABLE_COHBIT 0x01
+
+ /* Defines for Intel SCH HDA snoop control */
++#define INTEL_HDA_CGCTL 0x48
++#define INTEL_HDA_CGCTL_MISCBDCGE (0x1 << 6)
+ #define INTEL_SCH_HDA_DEVC 0x78
+ #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
+
+@@ -355,7 +357,10 @@ enum {
+ ((pci)->device == 0x0d0c) || \
+ ((pci)->device == 0x160c))
+
+-#define IS_BROXTON(pci) ((pci)->device == 0x5a98)
++#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
++#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
++#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
++#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
+
+ static char *driver_short_names[] = {
+ [AZX_DRIVER_ICH] = "HDA Intel",
+@@ -528,15 +533,26 @@ static void hda_intel_init_chip(struct a
+ {
+ struct hdac_bus *bus = azx_bus(chip);
+ struct pci_dev *pci = chip->pci;
++ u32 val;
+
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
+ snd_hdac_set_codec_wakeup(bus, true);
++ if (IS_SKL_PLUS(pci)) {
++ pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
++ val = val & ~INTEL_HDA_CGCTL_MISCBDCGE;
++ pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
++ }
+ azx_init_chip(chip, full_reset);
++ if (IS_SKL_PLUS(pci)) {
++ pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
++ val = val | INTEL_HDA_CGCTL_MISCBDCGE;
++ pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
++ }
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
+ snd_hdac_set_codec_wakeup(bus, false);
+
+ /* reduce dma latency to avoid noise */
+- if (IS_BROXTON(pci))
++ if (IS_BXT(pci))
+ bxt_reduce_dma_latency(chip);
+ }
+
+@@ -958,11 +974,6 @@ static int azx_resume(struct device *dev
+ /* put codec down to D3 at hibernation for Intel SKL+;
+ * otherwise BIOS may still access the codec and screw up the driver
+ */
+-#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
+-#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+-#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
+-
+ static int azx_freeze_noirq(struct device *dev)
+ {
+ struct pci_dev *pci = to_pci_dev(dev);
+@@ -2126,9 +2137,17 @@ i915_power_fail:
+ static void azx_remove(struct pci_dev *pci)
+ {
+ struct snd_card *card = pci_get_drvdata(pci);
++ struct azx *chip;
++ struct hda_intel *hda;
++
++ if (card) {
++ /* cancel the pending probing work */
++ chip = card->private_data;
++ hda = container_of(chip, struct hda_intel, chip);
++ cancel_work_sync(&hda->probe_work);
+
+- if (card)
+ snd_card_free(card);
++ }
+ }
+
+ static void azx_shutdown(struct pci_dev *pci)
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/hda_jack.c linux-libre-4.4.7-gnu/sound/pci/hda/hda_jack.c
+--- linux-libre-4.4-gnu/sound/pci/hda/hda_jack.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/hda_jack.c 2016-04-12 12:09:26.000000000 -0400
+@@ -259,7 +259,7 @@ snd_hda_jack_detect_enable_callback(stru
+ if (!callback)
+ return ERR_PTR(-ENOMEM);
+ callback->func = func;
+- callback->tbl = jack;
++ callback->nid = jack->nid;
+ callback->next = jack->callback;
+ jack->callback = callback;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/hda_jack.h linux-libre-4.4.7-gnu/sound/pci/hda/hda_jack.h
+--- linux-libre-4.4-gnu/sound/pci/hda/hda_jack.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/hda_jack.h 2016-04-12 12:09:26.000000000 -0400
+@@ -21,7 +21,7 @@ struct hda_jack_callback;
+ typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
+
+ struct hda_jack_callback {
+- struct hda_jack_tbl *tbl;
++ hda_nid_t nid;
+ hda_jack_callback_fn func;
+ unsigned int private_data; /* arbitrary data */
+ struct hda_jack_callback *next;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/patch_ca0132.c linux-libre-4.4.7-gnu/sound/pci/hda/patch_ca0132.c
+--- linux-libre-4.4-gnu/sound/pci/hda/patch_ca0132.c 2016-01-10 21:17:37.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/patch_ca0132.c 2016-04-12 21:33:17.000000000 -0400
+@@ -4427,13 +4427,16 @@ static void ca0132_process_dsp_response(
+ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
+ {
+ struct ca0132_spec *spec = codec->spec;
++ struct hda_jack_tbl *tbl;
+
+ /* Delay enabling the HP amp, to let the mic-detection
+ * state machine run.
+ */
+ cancel_delayed_work_sync(&spec->unsol_hp_work);
+ schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
+- cb->tbl->block_report = 1;
++ tbl = snd_hda_jack_tbl_get(codec, cb->nid);
++ if (tbl)
++ tbl->block_report = 1;
+ }
+
+ static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/patch_cirrus.c linux-libre-4.4.7-gnu/sound/pci/hda/patch_cirrus.c
+--- linux-libre-4.4-gnu/sound/pci/hda/patch_cirrus.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/patch_cirrus.c 2016-04-12 12:09:26.000000000 -0400
+@@ -174,8 +174,12 @@ static void cs_automute(struct hda_codec
+ snd_hda_gen_update_outputs(codec);
+
+ if (spec->gpio_eapd_hp || spec->gpio_eapd_speaker) {
+- spec->gpio_data = spec->gen.hp_jack_present ?
+- spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
++ if (spec->gen.automute_speaker)
++ spec->gpio_data = spec->gen.hp_jack_present ?
++ spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
++ else
++ spec->gpio_data =
++ spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
+ snd_hda_codec_write(codec, 0x01, 0,
+ AC_VERB_SET_GPIO_DATA, spec->gpio_data);
+ }
+@@ -614,6 +618,7 @@ enum {
+ CS4208_MAC_AUTO,
+ CS4208_MBA6,
+ CS4208_MBP11,
++ CS4208_MACMINI,
+ CS4208_GPIO0,
+ };
+
+@@ -621,6 +626,7 @@ static const struct hda_model_fixup cs42
+ { .id = CS4208_GPIO0, .name = "gpio0" },
+ { .id = CS4208_MBA6, .name = "mba6" },
+ { .id = CS4208_MBP11, .name = "mbp11" },
++ { .id = CS4208_MACMINI, .name = "macmini" },
+ {}
+ };
+
+@@ -632,6 +638,7 @@ static const struct snd_pci_quirk cs4208
+ /* codec SSID matching */
+ static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
++ SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI),
+ SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
+ SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
+ SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
+@@ -666,6 +673,24 @@ static void cs4208_fixup_mac(struct hda_
+ snd_hda_apply_fixup(codec, action);
+ }
+
++/* MacMini 7,1 has the inverted jack detection */
++static void cs4208_fixup_macmini(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ static const struct hda_pintbl pincfgs[] = {
++ { 0x18, 0x00ab9150 }, /* mic (audio-in) jack: disable detect */
++ { 0x21, 0x004be140 }, /* SPDIF: disable detect */
++ { }
++ };
++
++ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
++ /* HP pin (0x10) has an inverted detection */
++ codec->inv_jack_detect = 1;
++ /* disable the bogus Mic and SPDIF jack detections */
++ snd_hda_apply_pincfgs(codec, pincfgs);
++ }
++}
++
+ static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+ {
+@@ -709,6 +734,12 @@ static const struct hda_fixup cs4208_fix
+ .chained = true,
+ .chain_id = CS4208_GPIO0,
+ },
++ [CS4208_MACMINI] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = cs4208_fixup_macmini,
++ .chained = true,
++ .chain_id = CS4208_GPIO0,
++ },
+ [CS4208_GPIO0] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cs4208_fixup_gpio0,
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/patch_conexant.c linux-libre-4.4.7-gnu/sound/pci/hda/patch_conexant.c
+--- linux-libre-4.4-gnu/sound/pci/hda/patch_conexant.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/patch_conexant.c 2016-04-12 12:09:26.000000000 -0400
+@@ -204,8 +204,13 @@ static void cx_auto_reboot_notify(struct
+ {
+ struct conexant_spec *spec = codec->spec;
+
+- if (codec->core.vendor_id != 0x14f150f2)
++ switch (codec->core.vendor_id) {
++ case 0x14f150f2: /* CX20722 */
++ case 0x14f150f4: /* CX20724 */
++ break;
++ default:
+ return;
++ }
+
+ /* Turn the CX20722 codec into D3 to avoid spurious noises
+ from the internal speaker during (and after) reboot */
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/patch_hdmi.c linux-libre-4.4.7-gnu/sound/pci/hda/patch_hdmi.c
+--- linux-libre-4.4-gnu/sound/pci/hda/patch_hdmi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/patch_hdmi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -438,7 +438,8 @@ static int hdmi_eld_ctl_get(struct snd_k
+ eld = &per_pin->sink_eld;
+
+ mutex_lock(&per_pin->lock);
+- if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
++ if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
++ eld->eld_size > ELD_MAX_SIZE) {
+ mutex_unlock(&per_pin->lock);
+ snd_BUG();
+ return -EINVAL;
+@@ -1183,7 +1184,7 @@ static void check_presence_and_report(st
+ static void jack_callback(struct hda_codec *codec,
+ struct hda_jack_callback *jack)
+ {
+- check_presence_and_report(codec, jack->tbl->nid);
++ check_presence_and_report(codec, jack->nid);
+ }
+
+ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+@@ -2352,6 +2353,10 @@ static void intel_pin_eld_notify(void *a
+ struct hda_codec *codec = audio_ptr;
+ int pin_nid = port + 0x04;
+
++ /* we assume only from port-B to port-D */
++ if (port < 1 || port > 3)
++ return;
++
+ /* skip notification during system suspend (but not in runtime PM);
+ * the state will be updated at resume
+ */
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/patch_realtek.c linux-libre-4.4.7-gnu/sound/pci/hda/patch_realtek.c
+--- linux-libre-4.4-gnu/sound/pci/hda/patch_realtek.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/patch_realtek.c 2016-04-12 12:09:26.000000000 -0400
+@@ -282,7 +282,7 @@ static void alc_update_knob_master(struc
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (!uctl)
+ return;
+- val = snd_hda_codec_read(codec, jack->tbl->nid, 0,
++ val = snd_hda_codec_read(codec, jack->nid, 0,
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+ val &= HDA_AMP_VOLMASK;
+ uctl->value.integer.value[0] = val;
+@@ -327,6 +327,7 @@ static void alc_fill_eapd_coef(struct hd
+ case 0x10ec0292:
+ alc_update_coef_idx(codec, 0x4, 1<<15, 0);
+ break;
++ case 0x10ec0225:
+ case 0x10ec0233:
+ case 0x10ec0255:
+ case 0x10ec0256:
+@@ -900,6 +901,7 @@ static struct alc_codec_rename_pci_table
+ { 0x10ec0899, 0x1028, 0, "ALC3861" },
+ { 0x10ec0298, 0x1028, 0, "ALC3266" },
+ { 0x10ec0256, 0x1028, 0, "ALC3246" },
++ { 0x10ec0225, 0x1028, 0, "ALC3253" },
+ { 0x10ec0670, 0x1025, 0, "ALC669X" },
+ { 0x10ec0676, 0x1025, 0, "ALC679X" },
+ { 0x10ec0282, 0x1043, 0, "ALC3229" },
+@@ -1785,7 +1787,6 @@ enum {
+ ALC882_FIXUP_NO_PRIMARY_HP,
+ ALC887_FIXUP_ASUS_BASS,
+ ALC887_FIXUP_BASS_CHMAP,
+- ALC882_FIXUP_DISABLE_AAMIX,
+ };
+
+ static void alc889_fixup_coef(struct hda_codec *codec,
+@@ -1947,8 +1948,6 @@ static void alc882_fixup_no_primary_hp(s
+
+ static void alc_fixup_bass_chmap(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action);
+-static void alc_fixup_disable_aamix(struct hda_codec *codec,
+- const struct hda_fixup *fix, int action);
+
+ static const struct hda_fixup alc882_fixups[] = {
+ [ALC882_FIXUP_ABIT_AW9D_MAX] = {
+@@ -2186,10 +2185,6 @@ static const struct hda_fixup alc882_fix
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc_fixup_bass_chmap,
+ },
+- [ALC882_FIXUP_DISABLE_AAMIX] = {
+- .type = HDA_FIXUP_FUNC,
+- .v.func = alc_fixup_disable_aamix,
+- },
+ };
+
+ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+@@ -2228,6 +2223,7 @@ static const struct snd_pci_quirk alc882
+ SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
+ SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
+ SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
++ SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
+
+ /* All Apple entries are in codec SSIDs */
+ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
+@@ -2257,7 +2253,6 @@ static const struct snd_pci_quirk alc882
+ SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
+ SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
+- SND_PCI_QUIRK(0x1458, 0xa182, "Gigabyte Z170X-UD3", ALC882_FIXUP_DISABLE_AAMIX),
+ SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+ SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
+@@ -2651,6 +2646,7 @@ enum {
+ ALC269_TYPE_ALC298,
+ ALC269_TYPE_ALC255,
+ ALC269_TYPE_ALC256,
++ ALC269_TYPE_ALC225,
+ };
+
+ /*
+@@ -2680,6 +2676,7 @@ static int alc269_parse_auto_config(stru
+ case ALC269_TYPE_ALC298:
+ case ALC269_TYPE_ALC255:
+ case ALC269_TYPE_ALC256:
++ case ALC269_TYPE_ALC225:
+ ssids = alc269_ssids;
+ break;
+ default:
+@@ -3658,6 +3655,16 @@ static void alc_headset_mode_unplugged(s
+ WRITE_COEF(0xb7, 0x802b),
+ {}
+ };
++ static struct coef_fw coef0225[] = {
++ UPDATE_COEF(0x4a, 1<<8, 0),
++ UPDATE_COEFEX(0x57, 0x05, 1<<14, 0),
++ UPDATE_COEF(0x63, 3<<14, 3<<14),
++ UPDATE_COEF(0x4a, 3<<4, 2<<4),
++ UPDATE_COEF(0x4a, 3<<10, 3<<10),
++ UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
++ UPDATE_COEF(0x4a, 3<<10, 0),
++ {}
++ };
+
+ switch (codec->core.vendor_id) {
+ case 0x10ec0255:
+@@ -3682,6 +3689,9 @@ static void alc_headset_mode_unplugged(s
+ case 0x10ec0668:
+ alc_process_coef_fw(codec, coef0668);
+ break;
++ case 0x10ec0225:
++ alc_process_coef_fw(codec, coef0225);
++ break;
+ }
+ codec_dbg(codec, "Headset jack set to unplugged mode.\n");
+ }
+@@ -3727,6 +3737,13 @@ static void alc_headset_mode_mic_in(stru
+ UPDATE_COEF(0xc3, 0, 1<<12),
+ {}
+ };
++ static struct coef_fw coef0225[] = {
++ UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14),
++ UPDATE_COEF(0x4a, 3<<4, 2<<4),
++ UPDATE_COEF(0x63, 3<<14, 0),
++ {}
++ };
++
+
+ switch (codec->core.vendor_id) {
+ case 0x10ec0255:
+@@ -3772,6 +3789,12 @@ static void alc_headset_mode_mic_in(stru
+ alc_process_coef_fw(codec, coef0688);
+ snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
+ break;
++ case 0x10ec0225:
++ alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
++ snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
++ alc_process_coef_fw(codec, coef0225);
++ snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
++ break;
+ }
+ codec_dbg(codec, "Headset jack set to mic-in mode.\n");
+ }
+@@ -3884,6 +3907,13 @@ static void alc_headset_mode_ctia(struct
+ WRITE_COEF(0xc3, 0x0000),
+ {}
+ };
++ static struct coef_fw coef0225[] = {
++ UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
++ UPDATE_COEF(0x49, 1<<8, 1<<8),
++ UPDATE_COEF(0x4a, 7<<6, 7<<6),
++ UPDATE_COEF(0x4a, 3<<4, 3<<4),
++ {}
++ };
+
+ switch (codec->core.vendor_id) {
+ case 0x10ec0255:
+@@ -3912,6 +3942,9 @@ static void alc_headset_mode_ctia(struct
+ case 0x10ec0668:
+ alc_process_coef_fw(codec, coef0688);
+ break;
++ case 0x10ec0225:
++ alc_process_coef_fw(codec, coef0225);
++ break;
+ }
+ codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
+ }
+@@ -3955,6 +3988,13 @@ static void alc_headset_mode_omtp(struct
+ WRITE_COEF(0xc3, 0x0000),
+ {}
+ };
++ static struct coef_fw coef0225[] = {
++ UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10),
++ UPDATE_COEF(0x49, 1<<8, 1<<8),
++ UPDATE_COEF(0x4a, 7<<6, 7<<6),
++ UPDATE_COEF(0x4a, 3<<4, 3<<4),
++ {}
++ };
+
+ switch (codec->core.vendor_id) {
+ case 0x10ec0255:
+@@ -3983,6 +4023,9 @@ static void alc_headset_mode_omtp(struct
+ case 0x10ec0668:
+ alc_process_coef_fw(codec, coef0688);
+ break;
++ case 0x10ec0225:
++ alc_process_coef_fw(codec, coef0225);
++ break;
+ }
+ codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
+ }
+@@ -4014,6 +4057,11 @@ static void alc_determine_headset_type(s
+ WRITE_COEF(0xc3, 0x0c00),
+ {}
+ };
++ static struct coef_fw coef0225[] = {
++ UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
++ UPDATE_COEF(0x49, 1<<8, 1<<8),
++ {}
++ };
+
+ switch (codec->core.vendor_id) {
+ case 0x10ec0255:
+@@ -4058,6 +4106,12 @@ static void alc_determine_headset_type(s
+ val = alc_read_coef_idx(codec, 0xbe);
+ is_ctia = (val & 0x1c02) == 0x1c02;
+ break;
++ case 0x10ec0225:
++ alc_process_coef_fw(codec, coef0225);
++ msleep(800);
++ val = alc_read_coef_idx(codec, 0x46);
++ is_ctia = (val & 0x00f0) == 0x00f0;
++ break;
+ }
+
+ codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
+@@ -4666,6 +4720,7 @@ enum {
+ ALC290_FIXUP_SUBWOOFER,
+ ALC290_FIXUP_SUBWOOFER_HSJACK,
+ ALC269_FIXUP_THINKPAD_ACPI,
++ ALC269_FIXUP_DMIC_THINKPAD_ACPI,
+ ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
+ ALC255_FIXUP_HEADSET_MODE,
+@@ -4694,6 +4749,7 @@ enum {
+ ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
+ ALC293_FIXUP_LENOVO_SPK_NOISE,
+ ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
++ ALC255_FIXUP_DELL_SPK_NOISE,
+ };
+
+ static const struct hda_fixup alc269_fixups[] = {
+@@ -5103,6 +5159,12 @@ static const struct hda_fixup alc269_fix
+ .type = HDA_FIXUP_FUNC,
+ .v.func = hda_fixup_thinkpad_acpi,
+ },
++ [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc_fixup_inv_dmic,
++ .chained = true,
++ .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
++ },
+ [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+@@ -5307,6 +5369,12 @@ static const struct hda_fixup alc269_fix
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc233_fixup_lenovo_line2_mic_hotkey,
+ },
++ [ALC255_FIXUP_DELL_SPK_NOISE] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc_fixup_disable_aamix,
++ .chained = true,
++ .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -5318,12 +5386,14 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
+ SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
++ SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
+ SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
+ SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
+ SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+ SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
+ SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
++ SND_PCI_QUIRK(0x1028, 0x05be, "Dell Latitude E6540", ALC292_FIXUP_DELL_E7X),
+ SND_PCI_QUIRK(0x1028, 0x05ca, "Dell Latitude E7240", ALC292_FIXUP_DELL_E7X),
+ SND_PCI_QUIRK(0x1028, 0x05cb, "Dell Latitude E7440", ALC292_FIXUP_DELL_E7X),
+ SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
+@@ -5332,6 +5402,7 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
+ SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
++ SND_PCI_QUIRK(0x1028, 0x062c, "Dell Latitude E5550", ALC292_FIXUP_DELL_E7X),
+ SND_PCI_QUIRK(0x1028, 0x062e, "Dell Latitude E7450", ALC292_FIXUP_DELL_E7X),
+ SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
+ SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+@@ -5347,6 +5418,7 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+ SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+ SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
++ SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
+ SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
+@@ -5457,6 +5529,8 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
+ SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
++ SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
++ SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+ SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+@@ -5550,6 +5624,9 @@ static const struct hda_model_fixup alc2
+ {.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
+ {}
+ };
++#define ALC225_STANDARD_PINS \
++ {0x12, 0xb7a60130}, \
++ {0x21, 0x04211020}
+
+ #define ALC256_STANDARD_PINS \
+ {0x12, 0x90a60140}, \
+@@ -5571,6 +5648,12 @@ static const struct hda_model_fixup alc2
+ {0x21, 0x03211020}
+
+ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
++ SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
++ ALC225_STANDARD_PINS,
++ {0x14, 0x901701a0}),
++ SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
++ ALC225_STANDARD_PINS,
++ {0x14, 0x901701b0}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
+ {0x14, 0x90170110},
+ {0x21, 0x02211020}),
+@@ -5617,6 +5700,10 @@ static const struct snd_hda_pin_quirk al
+ {0x21, 0x02211040}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x12, 0x90a60170},
++ {0x14, 0x90171130},
++ {0x21, 0x02211040}),
++ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
++ {0x12, 0x90a60170},
+ {0x14, 0x90170140},
+ {0x21, 0x02211050}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5548", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+@@ -5892,6 +5979,9 @@ static int patch_alc269(struct hda_codec
+ spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
+ alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
+ break;
++ case 0x10ec0225:
++ spec->codec_variant = ALC269_TYPE_ALC225;
++ break;
+ }
+
+ if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
+@@ -6552,6 +6642,7 @@ static const struct snd_pci_quirk alc662
+ SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+ SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
++ SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
+ SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
+ SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
+ SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
+@@ -6781,6 +6872,7 @@ static int patch_alc680(struct hda_codec
+ */
+ static const struct hda_device_id snd_hda_id_realtek[] = {
+ HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
++ HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/hda/patch_sigmatel.c linux-libre-4.4.7-gnu/sound/pci/hda/patch_sigmatel.c
+--- linux-libre-4.4-gnu/sound/pci/hda/patch_sigmatel.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/hda/patch_sigmatel.c 2016-04-12 12:09:26.000000000 -0400
+@@ -493,9 +493,9 @@ static void jack_update_power(struct hda
+ if (!spec->num_pwrs)
+ return;
+
+- if (jack && jack->tbl->nid) {
+- stac_toggle_power_map(codec, jack->tbl->nid,
+- snd_hda_jack_detect(codec, jack->tbl->nid),
++ if (jack && jack->nid) {
++ stac_toggle_power_map(codec, jack->nid,
++ snd_hda_jack_detect(codec, jack->nid),
+ true);
+ return;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/intel8x0.c linux-libre-4.4.7-gnu/sound/pci/intel8x0.c
+--- linux-libre-4.4-gnu/sound/pci/intel8x0.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/intel8x0.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2879,6 +2879,7 @@ static void intel8x0_measure_ac97_clock(
+
+ static struct snd_pci_quirk intel8x0_clock_list[] = {
+ SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000),
++ SND_PCI_QUIRK(0x1014, 0x0581, "AD1981B", 48000),
+ SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100),
+ SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000),
+ SND_PCI_QUIRK(0x1028, 0x01ad, "AD1981B", 48000),
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/Kconfig linux-libre-4.4.7-gnu/sound/pci/Kconfig
+--- linux-libre-4.4-gnu/sound/pci/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -155,6 +155,7 @@ config SND_AZT3328
+ select SND_PCM
+ select SND_RAWMIDI
+ select SND_AC97_CODEC
++ select SND_TIMER
+ depends on ZONE_DMA
+ help
+ Say Y here to include support for Aztech AZF3328 (PCI168)
+@@ -463,6 +464,7 @@ config SND_EMU10K1
+ select SND_HWDEP
+ select SND_RAWMIDI
+ select SND_AC97_CODEC
++ select SND_TIMER
+ depends on ZONE_DMA
+ help
+ Say Y to include support for Sound Blaster PCI 512, Live!,
+@@ -889,6 +891,7 @@ config SND_YMFPCI
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
++ select SND_TIMER
+ help
+ Say Y here to include support for Yamaha PCI audio chips -
+ YMF724, YMF724F, YMF740, YMF740C, YMF744, YMF754.
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/rme9652/hdsp.c linux-libre-4.4.7-gnu/sound/pci/rme9652/hdsp.c
+--- linux-libre-4.4-gnu/sound/pci/rme9652/hdsp.c 2016-01-10 21:17:44.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/rme9652/hdsp.c 2016-04-12 21:33:22.000000000 -0400
+@@ -2875,7 +2875,7 @@ static int snd_hdsp_get_dds_offset(struc
+ {
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
+
+- ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
++ ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp);
+ return 0;
+ }
+
+@@ -2887,7 +2887,7 @@ static int snd_hdsp_put_dds_offset(struc
+
+ if (!snd_hdsp_use_is_exclusive(hdsp))
+ return -EBUSY;
+- val = ucontrol->value.enumerated.item[0];
++ val = ucontrol->value.integer.value[0];
+ spin_lock_irq(&hdsp->lock);
+ if (val != hdsp_dds_offset(hdsp))
+ change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/pci/rme9652/hdspm.c linux-libre-4.4.7-gnu/sound/pci/rme9652/hdspm.c
+--- linux-libre-4.4-gnu/sound/pci/rme9652/hdspm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/pci/rme9652/hdspm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1601,6 +1601,9 @@ static void hdspm_set_dds_value(struct h
+ {
+ u64 n;
+
++ if (snd_BUG_ON(rate <= 0))
++ return;
++
+ if (rate >= 112000)
+ rate /= 4;
+ else if (rate >= 56000)
+@@ -2215,6 +2218,8 @@ static int hdspm_get_system_sample_rate(
+ } else {
+ /* slave mode, return external sample rate */
+ rate = hdspm_external_sample_rate(hdspm);
++ if (!rate)
++ rate = hdspm->system_sample_rate;
+ }
+ }
+
+@@ -2260,8 +2265,11 @@ static int snd_hdspm_put_system_sample_r
+ ucontrol)
+ {
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
++ int rate = ucontrol->value.integer.value[0];
+
+- hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
++ if (rate < 27000 || rate > 207000)
++ return -EINVAL;
++ hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
+ return 0;
+ }
+
+@@ -4449,7 +4457,7 @@ static int snd_hdspm_get_tco_word_term(s
+ {
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+- ucontrol->value.enumerated.item[0] = hdspm->tco->term;
++ ucontrol->value.integer.value[0] = hdspm->tco->term;
+
+ return 0;
+ }
+@@ -4460,8 +4468,8 @@ static int snd_hdspm_put_tco_word_term(s
+ {
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+- if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
+- hdspm->tco->term = ucontrol->value.enumerated.item[0];
++ if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
++ hdspm->tco->term = ucontrol->value.integer.value[0];
+
+ hdspm_tco_write(hdspm);
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/codecs/rt5645.c linux-libre-4.4.7-gnu/sound/soc/codecs/rt5645.c
+--- linux-libre-4.4-gnu/sound/soc/codecs/rt5645.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/codecs/rt5645.c 2016-04-12 12:09:26.000000000 -0400
+@@ -621,7 +621,7 @@ static const struct snd_kcontrol_new rt5
+
+ /* IN1/IN2 Control */
+ SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1,
+- RT5645_BST_SFT1, 8, 0, bst_tlv),
++ RT5645_BST_SFT1, 12, 0, bst_tlv),
+ SOC_SINGLE_TLV("IN2 Boost", RT5645_IN2_CTRL,
+ RT5645_BST_SFT2, 8, 0, bst_tlv),
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/codecs/wm5110.c linux-libre-4.4.7-gnu/sound/soc/codecs/wm5110.c
+--- linux-libre-4.4-gnu/sound/soc/codecs/wm5110.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/codecs/wm5110.c 2016-04-12 12:09:26.000000000 -0400
+@@ -360,15 +360,13 @@ static int wm5110_hp_ev(struct snd_soc_d
+
+ static int wm5110_clear_pga_volume(struct arizona *arizona, int output)
+ {
+- struct reg_sequence clear_pga = {
+- ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4, 0x80
+- };
++ unsigned int reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + output * 4;
+ int ret;
+
+- ret = regmap_multi_reg_write_bypassed(arizona->regmap, &clear_pga, 1);
++ ret = regmap_write(arizona->regmap, reg, 0x80);
+ if (ret)
+ dev_err(arizona->dev, "Failed to clear PGA (0x%x): %d\n",
+- clear_pga.reg, ret);
++ reg, ret);
+
+ return ret;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/codecs/wm8958-dsp2.c linux-libre-4.4.7-gnu/sound/soc/codecs/wm8958-dsp2.c
+--- linux-libre-4.4-gnu/sound/soc/codecs/wm8958-dsp2.c 2016-01-10 21:18:35.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/codecs/wm8958-dsp2.c 2016-04-12 21:34:14.000000000 -0400
+@@ -459,7 +459,7 @@ static int wm8958_put_mbc_enum(struct sn
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
+- int value = ucontrol->value.integer.value[0];
++ int value = ucontrol->value.enumerated.item[0];
+ int reg;
+
+ /* Don't allow on the fly reconfiguration */
+@@ -549,7 +549,7 @@ static int wm8958_put_vss_enum(struct sn
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
+- int value = ucontrol->value.integer.value[0];
++ int value = ucontrol->value.enumerated.item[0];
+ int reg;
+
+ /* Don't allow on the fly reconfiguration */
+@@ -582,7 +582,7 @@ static int wm8958_put_vss_hpf_enum(struc
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
+- int value = ucontrol->value.integer.value[0];
++ int value = ucontrol->value.enumerated.item[0];
+ int reg;
+
+ /* Don't allow on the fly reconfiguration */
+@@ -749,7 +749,7 @@ static int wm8958_put_enh_eq_enum(struct
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
+- int value = ucontrol->value.integer.value[0];
++ int value = ucontrol->value.enumerated.item[0];
+ int reg;
+
+ /* Don't allow on the fly reconfiguration */
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/codecs/wm8994.c linux-libre-4.4.7-gnu/sound/soc/codecs/wm8994.c
+--- linux-libre-4.4-gnu/sound/soc/codecs/wm8994.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/codecs/wm8994.c 2016-04-12 12:09:26.000000000 -0400
+@@ -362,7 +362,7 @@ static int wm8994_put_drc_enum(struct sn
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
+ int drc = wm8994_get_drc(kcontrol->id.name);
+- int value = ucontrol->value.integer.value[0];
++ int value = ucontrol->value.enumerated.item[0];
+
+ if (drc < 0)
+ return drc;
+@@ -469,7 +469,7 @@ static int wm8994_put_retune_mobile_enum
+ struct wm8994 *control = wm8994->wm8994;
+ struct wm8994_pdata *pdata = &control->pdata;
+ int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
+- int value = ucontrol->value.integer.value[0];
++ int value = ucontrol->value.enumerated.item[0];
+
+ if (block < 0)
+ return block;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/ac97.c linux-libre-4.4.7-gnu/sound/soc/samsung/ac97.c
+--- linux-libre-4.4-gnu/sound/soc/samsung/ac97.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/ac97.c 2016-04-12 12:09:26.000000000 -0400
+@@ -324,7 +324,7 @@ static const struct snd_soc_component_dr
+
+ static int s3c_ac97_probe(struct platform_device *pdev)
+ {
+- struct resource *mem_res, *dmatx_res, *dmarx_res, *dmamic_res, *irq_res;
++ struct resource *mem_res, *irq_res;
+ struct s3c_audio_pdata *ac97_pdata;
+ int ret;
+
+@@ -335,24 +335,6 @@ static int s3c_ac97_probe(struct platfor
+ }
+
+ /* Check for availability of necessary resource */
+- dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+- if (!dmatx_res) {
+- dev_err(&pdev->dev, "Unable to get AC97-TX dma resource\n");
+- return -ENXIO;
+- }
+-
+- dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+- if (!dmarx_res) {
+- dev_err(&pdev->dev, "Unable to get AC97-RX dma resource\n");
+- return -ENXIO;
+- }
+-
+- dmamic_res = platform_get_resource(pdev, IORESOURCE_DMA, 2);
+- if (!dmamic_res) {
+- dev_err(&pdev->dev, "Unable to get AC97-MIC dma resource\n");
+- return -ENXIO;
+- }
+-
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq_res) {
+ dev_err(&pdev->dev, "AC97 IRQ not provided!\n");
+@@ -364,11 +346,11 @@ static int s3c_ac97_probe(struct platfor
+ if (IS_ERR(s3c_ac97.regs))
+ return PTR_ERR(s3c_ac97.regs);
+
+- s3c_ac97_pcm_out.channel = dmatx_res->start;
++ s3c_ac97_pcm_out.slave = ac97_pdata->dma_playback;
+ s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
+- s3c_ac97_pcm_in.channel = dmarx_res->start;
++ s3c_ac97_pcm_in.slave = ac97_pdata->dma_capture;
+ s3c_ac97_pcm_in.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
+- s3c_ac97_mic_in.channel = dmamic_res->start;
++ s3c_ac97_mic_in.slave = ac97_pdata->dma_capture_mic;
+ s3c_ac97_mic_in.dma_addr = mem_res->start + S3C_AC97_MIC_DATA;
+
+ init_completion(&s3c_ac97.done);
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/dmaengine.c linux-libre-4.4.7-gnu/sound/soc/samsung/dmaengine.c
+--- linux-libre-4.4-gnu/sound/soc/samsung/dmaengine.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/dmaengine.c 2016-04-12 12:09:26.000000000 -0400
+@@ -50,14 +50,14 @@ void samsung_asoc_init_dma_data(struct s
+
+ if (playback) {
+ playback_data = &playback->dma_data;
+- playback_data->filter_data = (void *)playback->channel;
++ playback_data->filter_data = playback->slave;
+ playback_data->chan_name = playback->ch_name;
+ playback_data->addr = playback->dma_addr;
+ playback_data->addr_width = playback->dma_size;
+ }
+ if (capture) {
+ capture_data = &capture->dma_data;
+- capture_data->filter_data = (void *)capture->channel;
++ capture_data->filter_data = capture->slave;
+ capture_data->chan_name = capture->ch_name;
+ capture_data->addr = capture->dma_addr;
+ capture_data->addr_width = capture->dma_size;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/dma.h linux-libre-4.4.7-gnu/sound/soc/samsung/dma.h
+--- linux-libre-4.4-gnu/sound/soc/samsung/dma.h 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/dma.h 2016-04-12 12:09:26.000000000 -0400
+@@ -15,7 +15,7 @@
+ #include <sound/dmaengine_pcm.h>
+
+ struct s3c_dma_params {
+- int channel; /* Channel ID */
++ void *slave; /* Channel ID */
+ dma_addr_t dma_addr;
+ int dma_size; /* Size of the DMA transfer */
+ char *ch_name;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/i2s.c linux-libre-4.4.7-gnu/sound/soc/samsung/i2s.c
+--- linux-libre-4.4-gnu/sound/soc/samsung/i2s.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/i2s.c 2016-04-12 12:09:26.000000000 -0400
+@@ -480,10 +480,11 @@ static int i2s_set_sysclk(struct snd_soc
+ unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;
+ unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
+ u32 mod, mask, val = 0;
++ unsigned long flags;
+
+- spin_lock(i2s->lock);
++ spin_lock_irqsave(i2s->lock, flags);
+ mod = readl(i2s->addr + I2SMOD);
+- spin_unlock(i2s->lock);
++ spin_unlock_irqrestore(i2s->lock, flags);
+
+ switch (clk_id) {
+ case SAMSUNG_I2S_OPCLK:
+@@ -574,11 +575,11 @@ static int i2s_set_sysclk(struct snd_soc
+ return -EINVAL;
+ }
+
+- spin_lock(i2s->lock);
++ spin_lock_irqsave(i2s->lock, flags);
+ mod = readl(i2s->addr + I2SMOD);
+ mod = (mod & ~mask) | val;
+ writel(mod, i2s->addr + I2SMOD);
+- spin_unlock(i2s->lock);
++ spin_unlock_irqrestore(i2s->lock, flags);
+
+ return 0;
+ }
+@@ -589,6 +590,7 @@ static int i2s_set_fmt(struct snd_soc_da
+ struct i2s_dai *i2s = to_info(dai);
+ int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;
+ u32 mod, tmp = 0;
++ unsigned long flags;
+
+ lrp_shift = i2s->variant_regs->lrp_off;
+ sdf_shift = i2s->variant_regs->sdf_off;
+@@ -648,7 +650,7 @@ static int i2s_set_fmt(struct snd_soc_da
+ return -EINVAL;
+ }
+
+- spin_lock(i2s->lock);
++ spin_lock_irqsave(i2s->lock, flags);
+ mod = readl(i2s->addr + I2SMOD);
+ /*
+ * Don't change the I2S mode if any controller is active on this
+@@ -656,7 +658,7 @@ static int i2s_set_fmt(struct snd_soc_da
+ */
+ if (any_active(i2s) &&
+ ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {
+- spin_unlock(i2s->lock);
++ spin_unlock_irqrestore(i2s->lock, flags);
+ dev_err(&i2s->pdev->dev,
+ "%s:%d Other DAI busy\n", __func__, __LINE__);
+ return -EAGAIN;
+@@ -665,7 +667,7 @@ static int i2s_set_fmt(struct snd_soc_da
+ mod &= ~(sdf_mask | lrp_rlow | mod_slave);
+ mod |= tmp;
+ writel(mod, i2s->addr + I2SMOD);
+- spin_unlock(i2s->lock);
++ spin_unlock_irqrestore(i2s->lock, flags);
+
+ return 0;
+ }
+@@ -675,6 +677,7 @@ static int i2s_hw_params(struct snd_pcm_
+ {
+ struct i2s_dai *i2s = to_info(dai);
+ u32 mod, mask = 0, val = 0;
++ unsigned long flags;
+
+ if (!is_secondary(i2s))
+ mask |= (MOD_DC2_EN | MOD_DC1_EN);
+@@ -743,11 +746,11 @@ static int i2s_hw_params(struct snd_pcm_
+ return -EINVAL;
+ }
+
+- spin_lock(i2s->lock);
++ spin_lock_irqsave(i2s->lock, flags);
+ mod = readl(i2s->addr + I2SMOD);
+ mod = (mod & ~mask) | val;
+ writel(mod, i2s->addr + I2SMOD);
+- spin_unlock(i2s->lock);
++ spin_unlock_irqrestore(i2s->lock, flags);
+
+ samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
+
+@@ -1257,27 +1260,14 @@ static int samsung_i2s_probe(struct plat
+ pri_dai->lock = &pri_dai->spinlock;
+
+ if (!np) {
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+- if (!res) {
+- dev_err(&pdev->dev,
+- "Unable to get I2S-TX dma resource\n");
+- return -ENXIO;
+- }
+- pri_dai->dma_playback.channel = res->start;
+-
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+- if (!res) {
+- dev_err(&pdev->dev,
+- "Unable to get I2S-RX dma resource\n");
+- return -ENXIO;
+- }
+- pri_dai->dma_capture.channel = res->start;
+-
+ if (i2s_pdata == NULL) {
+ dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n");
+ return -EINVAL;
+ }
+
++ pri_dai->dma_playback.slave = i2s_pdata->dma_playback;
++ pri_dai->dma_capture.slave = i2s_pdata->dma_capture;
++
+ if (&i2s_pdata->type)
+ i2s_cfg = &i2s_pdata->type.i2s;
+
+@@ -1338,11 +1328,8 @@ static int samsung_i2s_probe(struct plat
+ sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
+ sec_dai->dma_playback.ch_name = "tx-sec";
+
+- if (!np) {
+- res = platform_get_resource(pdev, IORESOURCE_DMA, 2);
+- if (res)
+- sec_dai->dma_playback.channel = res->start;
+- }
++ if (!np)
++ sec_dai->dma_playback.slave = i2s_pdata->dma_play_sec;
+
+ sec_dai->dma_playback.dma_size = 4;
+ sec_dai->addr = pri_dai->addr;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/pcm.c linux-libre-4.4.7-gnu/sound/soc/samsung/pcm.c
+--- linux-libre-4.4-gnu/sound/soc/samsung/pcm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/pcm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -486,7 +486,7 @@ static const struct snd_soc_component_dr
+ static int s3c_pcm_dev_probe(struct platform_device *pdev)
+ {
+ struct s3c_pcm_info *pcm;
+- struct resource *mem_res, *dmatx_res, *dmarx_res;
++ struct resource *mem_res;
+ struct s3c_audio_pdata *pcm_pdata;
+ int ret;
+
+@@ -499,18 +499,6 @@ static int s3c_pcm_dev_probe(struct plat
+ pcm_pdata = pdev->dev.platform_data;
+
+ /* Check for availability of necessary resource */
+- dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+- if (!dmatx_res) {
+- dev_err(&pdev->dev, "Unable to get PCM-TX dma resource\n");
+- return -ENXIO;
+- }
+-
+- dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+- if (!dmarx_res) {
+- dev_err(&pdev->dev, "Unable to get PCM-RX dma resource\n");
+- return -ENXIO;
+- }
+-
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ dev_err(&pdev->dev, "Unable to get register resource\n");
+@@ -568,8 +556,10 @@ static int s3c_pcm_dev_probe(struct plat
+ s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start
+ + S3C_PCM_TXFIFO;
+
+- s3c_pcm_stereo_in[pdev->id].channel = dmarx_res->start;
+- s3c_pcm_stereo_out[pdev->id].channel = dmatx_res->start;
++ if (pcm_pdata) {
++ s3c_pcm_stereo_in[pdev->id].slave = pcm_pdata->dma_capture;
++ s3c_pcm_stereo_out[pdev->id].slave = pcm_pdata->dma_playback;
++ }
+
+ pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id];
+ pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id];
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/s3c2412-i2s.c linux-libre-4.4.7-gnu/sound/soc/samsung/s3c2412-i2s.c
+--- linux-libre-4.4-gnu/sound/soc/samsung/s3c2412-i2s.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/s3c2412-i2s.c 2016-04-12 12:09:26.000000000 -0400
+@@ -34,13 +34,13 @@
+ #include "s3c2412-i2s.h"
+
+ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
+- .channel = DMACH_I2S_OUT,
++ .slave = (void *)(uintptr_t)DMACH_I2S_OUT,
+ .ch_name = "tx",
+ .dma_size = 4,
+ };
+
+ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
+- .channel = DMACH_I2S_IN,
++ .slave = (void *)(uintptr_t)DMACH_I2S_IN,
+ .ch_name = "rx",
+ .dma_size = 4,
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/s3c24xx-i2s.c linux-libre-4.4.7-gnu/sound/soc/samsung/s3c24xx-i2s.c
+--- linux-libre-4.4-gnu/sound/soc/samsung/s3c24xx-i2s.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/s3c24xx-i2s.c 2016-04-12 12:09:26.000000000 -0400
+@@ -32,13 +32,13 @@
+ #include "s3c24xx-i2s.h"
+
+ static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
+- .channel = DMACH_I2S_OUT,
++ .slave = (void *)(uintptr_t)DMACH_I2S_OUT,
+ .ch_name = "tx",
+ .dma_size = 2,
+ };
+
+ static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
+- .channel = DMACH_I2S_IN,
++ .slave = (void *)(uintptr_t)DMACH_I2S_IN,
+ .ch_name = "rx",
+ .dma_size = 2,
+ };
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/samsung/spdif.c linux-libre-4.4.7-gnu/sound/soc/samsung/spdif.c
+--- linux-libre-4.4-gnu/sound/soc/samsung/spdif.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/samsung/spdif.c 2016-04-12 12:09:26.000000000 -0400
+@@ -359,7 +359,7 @@ static const struct snd_soc_component_dr
+ static int spdif_probe(struct platform_device *pdev)
+ {
+ struct s3c_audio_pdata *spdif_pdata;
+- struct resource *mem_res, *dma_res;
++ struct resource *mem_res;
+ struct samsung_spdif_info *spdif;
+ int ret;
+
+@@ -367,12 +367,6 @@ static int spdif_probe(struct platform_d
+
+ dev_dbg(&pdev->dev, "Entered %s\n", __func__);
+
+- dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+- if (!dma_res) {
+- dev_err(&pdev->dev, "Unable to get dma resource.\n");
+- return -ENXIO;
+- }
+-
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ dev_err(&pdev->dev, "Unable to get register resource.\n");
+@@ -432,7 +426,7 @@ static int spdif_probe(struct platform_d
+
+ spdif_stereo_out.dma_size = 2;
+ spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
+- spdif_stereo_out.channel = dma_res->start;
++ spdif_stereo_out.slave = spdif_pdata ? spdif_pdata->dma_playback : NULL;
+
+ spdif->dma_playback = &spdif_stereo_out;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/soc-compress.c linux-libre-4.4.7-gnu/sound/soc/soc-compress.c
+--- linux-libre-4.4-gnu/sound/soc/soc-compress.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/soc-compress.c 2016-04-12 12:09:26.000000000 -0400
+@@ -630,6 +630,7 @@ int snd_soc_new_compress(struct snd_soc_
+ struct snd_pcm *be_pcm;
+ char new_name[64];
+ int ret = 0, direction = 0;
++ int playback = 0, capture = 0;
+
+ if (rtd->num_codecs > 1) {
+ dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
+@@ -641,11 +642,27 @@ int snd_soc_new_compress(struct snd_soc_
+ rtd->dai_link->stream_name, codec_dai->name, num);
+
+ if (codec_dai->driver->playback.channels_min)
++ playback = 1;
++ if (codec_dai->driver->capture.channels_min)
++ capture = 1;
++
++ capture = capture && cpu_dai->driver->capture.channels_min;
++ playback = playback && cpu_dai->driver->playback.channels_min;
++
++ /*
++ * Compress devices are unidirectional so only one of the directions
++ * should be set, check for that (xor)
++ */
++ if (playback + capture != 1) {
++ dev_err(rtd->card->dev, "Invalid direction for compress P %d, C %d\n",
++ playback, capture);
++ return -EINVAL;
++ }
++
++ if(playback)
+ direction = SND_COMPRESS_PLAYBACK;
+- else if (codec_dai->driver->capture.channels_min)
+- direction = SND_COMPRESS_CAPTURE;
+ else
+- return -EINVAL;
++ direction = SND_COMPRESS_CAPTURE;
+
+ compr = kzalloc(sizeof(*compr), GFP_KERNEL);
+ if (compr == NULL) {
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/soc-dapm.c linux-libre-4.4.7-gnu/sound/soc/soc-dapm.c
+--- linux-libre-4.4-gnu/sound/soc/soc-dapm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/soc-dapm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -3568,7 +3568,7 @@ static int snd_soc_dapm_dai_link_get(str
+ {
+ struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
+
+- ucontrol->value.integer.value[0] = w->params_select;
++ ucontrol->value.enumerated.item[0] = w->params_select;
+
+ return 0;
+ }
+@@ -3582,13 +3582,13 @@ static int snd_soc_dapm_dai_link_put(str
+ if (w->power)
+ return -EBUSY;
+
+- if (ucontrol->value.integer.value[0] == w->params_select)
++ if (ucontrol->value.enumerated.item[0] == w->params_select)
+ return 0;
+
+- if (ucontrol->value.integer.value[0] >= w->num_params)
++ if (ucontrol->value.enumerated.item[0] >= w->num_params)
+ return -EINVAL;
+
+- w->params_select = ucontrol->value.integer.value[0];
++ w->params_select = ucontrol->value.enumerated.item[0];
+
+ return 0;
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/soc/soc-pcm.c linux-libre-4.4.7-gnu/sound/soc/soc-pcm.c
+--- linux-libre-4.4-gnu/sound/soc/soc-pcm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/soc/soc-pcm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1743,7 +1743,8 @@ int dpcm_be_dai_hw_free(struct snd_soc_p
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
+- (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
+ continue;
+
+ dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/sparc/Kconfig linux-libre-4.4.7-gnu/sound/sparc/Kconfig
+--- linux-libre-4.4-gnu/sound/sparc/Kconfig 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/sparc/Kconfig 2016-04-12 12:09:26.000000000 -0400
+@@ -22,6 +22,7 @@ config SND_SUN_AMD7930
+ config SND_SUN_CS4231
+ tristate "Sun CS4231"
+ select SND_PCM
++ select SND_TIMER
+ help
+ Say Y here to include support for CS4231 sound device on Sun.
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/card.c linux-libre-4.4.7-gnu/sound/usb/card.c
+--- linux-libre-4.4-gnu/sound/usb/card.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/card.c 2016-04-12 12:09:26.000000000 -0400
+@@ -675,6 +675,8 @@ int snd_usb_autoresume(struct snd_usb_au
+
+ void snd_usb_autosuspend(struct snd_usb_audio *chip)
+ {
++ if (atomic_read(&chip->shutdown))
++ return;
+ if (atomic_dec_and_test(&chip->active))
+ usb_autopm_put_interface(chip->pm_intf);
+ }
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/clock.c linux-libre-4.4.7-gnu/sound/usb/clock.c
+--- linux-libre-4.4-gnu/sound/usb/clock.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/clock.c 2016-04-12 12:09:26.000000000 -0400
+@@ -285,6 +285,8 @@ static int set_sample_rate_v1(struct snd
+ unsigned char data[3];
+ int err, crate;
+
++ if (get_iface_desc(alts)->bNumEndpoints < 1)
++ return -EINVAL;
+ ep = get_endpoint(alts, 0)->bEndpointAddress;
+
+ /* if endpoint doesn't have sampling rate control, bail out */
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/endpoint.c linux-libre-4.4.7-gnu/sound/usb/endpoint.c
+--- linux-libre-4.4-gnu/sound/usb/endpoint.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/endpoint.c 2016-04-12 12:09:26.000000000 -0400
+@@ -438,6 +438,9 @@ exit_clear:
+ *
+ * New endpoints will be added to chip->ep_list and must be freed by
+ * calling snd_usb_endpoint_free().
++ *
++ * For SND_USB_ENDPOINT_TYPE_SYNC, the caller needs to guarantee that
++ * bNumEndpoints > 1 beforehand.
+ */
+ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
+ struct usb_host_interface *alts,
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/midi.c linux-libre-4.4.7-gnu/sound/usb/midi.c
+--- linux-libre-4.4-gnu/sound/usb/midi.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/midi.c 2016-04-12 12:09:26.000000000 -0400
+@@ -2454,7 +2454,6 @@ int snd_usbmidi_create(struct snd_card *
+ else
+ err = snd_usbmidi_create_endpoints(umidi, endpoints);
+ if (err < 0) {
+- snd_usbmidi_free(umidi);
+ return err;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/mixer_quirks.c linux-libre-4.4.7-gnu/sound/usb/mixer_quirks.c
+--- linux-libre-4.4-gnu/sound/usb/mixer_quirks.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/mixer_quirks.c 2016-04-12 12:09:26.000000000 -0400
+@@ -793,7 +793,7 @@ static int snd_nativeinstruments_control
+ return 0;
+
+ kcontrol->private_value &= ~(0xff << 24);
+- kcontrol->private_value |= newval;
++ kcontrol->private_value |= (unsigned int)newval << 24;
+ err = snd_ni_update_cur_val(list);
+ return err < 0 ? err : 1;
+ }
+@@ -1519,7 +1519,11 @@ static int snd_microii_spdif_default_get
+
+ /* use known values for that card: interface#1 altsetting#1 */
+ iface = usb_ifnum_to_if(chip->dev, 1);
++ if (!iface || iface->num_altsetting < 2)
++ return -EINVAL;
+ alts = &iface->altsetting[1];
++ if (get_iface_desc(alts)->bNumEndpoints < 1)
++ return -EINVAL;
+ ep = get_endpoint(alts, 0)->bEndpointAddress;
+
+ err = snd_usb_ctl_msg(chip->dev,
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/pcm.c linux-libre-4.4.7-gnu/sound/usb/pcm.c
+--- linux-libre-4.4-gnu/sound/usb/pcm.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/pcm.c 2016-04-12 12:09:26.000000000 -0400
+@@ -159,6 +159,8 @@ static int init_pitch_v1(struct snd_usb_
+ unsigned char data[1];
+ int err;
+
++ if (get_iface_desc(alts)->bNumEndpoints < 1)
++ return -EINVAL;
+ ep = get_endpoint(alts, 0)->bEndpointAddress;
+
+ data[0] = 1;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/quirks.c linux-libre-4.4.7-gnu/sound/usb/quirks.c
+--- linux-libre-4.4-gnu/sound/usb/quirks.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/quirks.c 2016-04-12 12:09:26.000000000 -0400
+@@ -150,6 +150,7 @@ static int create_fixed_stream_quirk(str
+ usb_audio_err(chip, "cannot memdup\n");
+ return -ENOMEM;
+ }
++ INIT_LIST_HEAD(&fp->list);
+ if (fp->nr_rates > MAX_NR_RATES) {
+ kfree(fp);
+ return -EINVAL;
+@@ -167,19 +168,20 @@ static int create_fixed_stream_quirk(str
+ stream = (fp->endpoint & USB_DIR_IN)
+ ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+ err = snd_usb_add_audio_stream(chip, stream, fp);
+- if (err < 0) {
+- kfree(fp);
+- kfree(rate_table);
+- return err;
+- }
++ if (err < 0)
++ goto error;
+ if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber ||
+ fp->altset_idx >= iface->num_altsetting) {
+- kfree(fp);
+- kfree(rate_table);
+- return -EINVAL;
++ err = -EINVAL;
++ goto error;
+ }
+ alts = &iface->altsetting[fp->altset_idx];
+ altsd = get_iface_desc(alts);
++ if (altsd->bNumEndpoints < 1) {
++ err = -EINVAL;
++ goto error;
++ }
++
+ fp->protocol = altsd->bInterfaceProtocol;
+
+ if (fp->datainterval == 0)
+@@ -190,6 +192,12 @@ static int create_fixed_stream_quirk(str
+ snd_usb_init_pitch(chip, fp->iface, alts, fp);
+ snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max);
+ return 0;
++
++ error:
++ list_del(&fp->list); /* unlink for avoiding double-free */
++ kfree(fp);
++ kfree(rate_table);
++ return err;
+ }
+
+ static int create_auto_pcm_quirk(struct snd_usb_audio *chip,
+@@ -462,6 +470,7 @@ static int create_uaxx_quirk(struct snd_
+ fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+ fp->datainterval = 0;
+ fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
++ INIT_LIST_HEAD(&fp->list);
+
+ switch (fp->maxpacksize) {
+ case 0x120:
+@@ -485,6 +494,7 @@ static int create_uaxx_quirk(struct snd_
+ ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+ err = snd_usb_add_audio_stream(chip, stream, fp);
+ if (err < 0) {
++ list_del(&fp->list); /* unlink for avoiding double-free */
+ kfree(fp);
+ return err;
+ }
+@@ -1121,8 +1131,11 @@ bool snd_usb_get_sample_rate_quirk(struc
+ switch (chip->usb_id) {
+ case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema */
+ case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
++ case USB_ID(0x045E, 0x076E): /* MS Lifecam HD-5001 */
++ case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
+ case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
+ case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
++ case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
+ case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
+ case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
+ case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
+@@ -1205,8 +1218,12 @@ void snd_usb_set_interface_quirk(struct
+ * "Playback Design" products need a 50ms delay after setting the
+ * USB interface.
+ */
+- if (le16_to_cpu(dev->descriptor.idVendor) == 0x23ba)
++ switch (le16_to_cpu(dev->descriptor.idVendor)) {
++ case 0x23ba: /* Playback Design */
++ case 0x0644: /* TEAC Corp. */
+ mdelay(50);
++ break;
++ }
+ }
+
+ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
+@@ -1221,6 +1238,14 @@ void snd_usb_ctl_msg_quirk(struct usb_de
+ (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+ mdelay(20);
+
++ /*
++ * "TEAC Corp." products need a 20ms delay after each
++ * class compliant request
++ */
++ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0644) &&
++ (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
++ mdelay(20);
++
+ /* Marantz/Denon devices with USB DAC functionality need a delay
+ * after each class compliant request
+ */
+@@ -1269,6 +1294,7 @@ u64 snd_usb_interface_dsd_format_quirks(
+ case USB_ID(0x20b1, 0x3008): /* iFi Audio micro/nano iDSD */
+ case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
+ case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
++ case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */
+ if (fp->altsetting == 2)
+ return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+ break;
+@@ -1277,6 +1303,7 @@ u64 snd_usb_interface_dsd_format_quirks(
+ case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
+ case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
+ case USB_ID(0x20b1, 0x3023): /* Aune X1S 32BIT/384 DSD DAC */
++ case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */
+ if (fp->altsetting == 3)
+ return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+ break;
+diff -druNp --no-dereference linux-libre-4.4-gnu/sound/usb/stream.c linux-libre-4.4.7-gnu/sound/usb/stream.c
+--- linux-libre-4.4-gnu/sound/usb/stream.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/sound/usb/stream.c 2016-04-12 12:09:26.000000000 -0400
+@@ -316,7 +316,9 @@ static struct snd_pcm_chmap_elem *conver
+ /*
+ * add this endpoint to the chip instance.
+ * if a stream with the same endpoint already exists, append to it.
+- * if not, create a new pcm stream.
++ * if not, create a new pcm stream. note, fp is added to the substream
++ * fmt_list and will be freed on the chip instance release. do not free
++ * fp or do remove it from the substream fmt_list to avoid double-free.
+ */
+ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+ int stream,
+@@ -677,6 +679,7 @@ int snd_usb_parse_audio_interface(struct
+ * (fp->maxpacksize & 0x7ff);
+ fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
+ fp->clock = clock;
++ INIT_LIST_HEAD(&fp->list);
+
+ /* some quirks for attributes here */
+
+@@ -725,6 +728,7 @@ int snd_usb_parse_audio_interface(struct
+ dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
+ err = snd_usb_add_audio_stream(chip, stream, fp);
+ if (err < 0) {
++ list_del(&fp->list); /* unlink for avoiding double-free */
+ kfree(fp->rate_table);
+ kfree(fp->chmap);
+ kfree(fp);
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/hv/hv_vss_daemon.c linux-libre-4.4.7-gnu/tools/hv/hv_vss_daemon.c
+--- linux-libre-4.4-gnu/tools/hv/hv_vss_daemon.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/hv/hv_vss_daemon.c 2016-04-12 12:09:26.000000000 -0400
+@@ -254,7 +254,7 @@ int main(int argc, char *argv[])
+ syslog(LOG_ERR, "Illegal op:%d\n", op);
+ }
+ vss_msg->error = error;
+- len = write(vss_fd, &error, sizeof(struct hv_vss_msg));
++ len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
+ if (len != sizeof(struct hv_vss_msg)) {
+ syslog(LOG_ERR, "write failed; error: %d %s", errno,
+ strerror(errno));
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/hv/Makefile linux-libre-4.4.7-gnu/tools/hv/Makefile
+--- linux-libre-4.4-gnu/tools/hv/Makefile 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/hv/Makefile 2016-04-12 12:09:26.000000000 -0400
+@@ -5,6 +5,8 @@ PTHREAD_LIBS = -lpthread
+ WARNINGS = -Wall -Wextra
+ CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) $(shell getconf LFS_CFLAGS)
+
++CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
++
+ all: hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
+ %: %.c
+ $(CC) $(CFLAGS) -o $@ $^
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/lib/traceevent/event-parse.c linux-libre-4.4.7-gnu/tools/lib/traceevent/event-parse.c
+--- linux-libre-4.4-gnu/tools/lib/traceevent/event-parse.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/lib/traceevent/event-parse.c 2016-04-12 12:09:26.000000000 -0400
+@@ -4968,13 +4968,12 @@ static void pretty_print(struct trace_se
+ sizeof(long) != 8) {
+ char *p;
+
+- ls = 2;
+ /* make %l into %ll */
+- p = strchr(format, 'l');
+- if (p)
++ if (ls == 1 && (p = strchr(format, 'l')))
+ memmove(p+1, p, strlen(p)+1);
+ else if (strcmp(format, "%p") == 0)
+ strcpy(format, "0x%llx");
++ ls = 2;
+ }
+ switch (ls) {
+ case -2:
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/perf/util/parse-events.c linux-libre-4.4.7-gnu/tools/perf/util/parse-events.c
+--- linux-libre-4.4-gnu/tools/perf/util/parse-events.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/perf/util/parse-events.c 2016-04-12 12:09:26.000000000 -0400
+@@ -399,6 +399,9 @@ static void tracepoint_error(struct pars
+ {
+ char help[BUFSIZ];
+
++ if (!e)
++ return;
++
+ /*
+ * We get error directly from syscall errno ( > 0),
+ * or from encoded pointer's error ( < 0).
+@@ -2098,11 +2101,11 @@ char *parse_events_formats_error_string(
+
+ /* valid terms */
+ if (additional_terms) {
+- if (!asprintf(&str, "valid terms: %s,%s",
+- additional_terms, static_terms))
++ if (asprintf(&str, "valid terms: %s,%s",
++ additional_terms, static_terms) < 0)
+ goto fail;
+ } else {
+- if (!asprintf(&str, "valid terms: %s", static_terms))
++ if (asprintf(&str, "valid terms: %s", static_terms) < 0)
+ goto fail;
+ }
+ return str;
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/perf/util/pmu.c linux-libre-4.4.7-gnu/tools/perf/util/pmu.c
+--- linux-libre-4.4-gnu/tools/perf/util/pmu.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/perf/util/pmu.c 2016-04-12 12:09:26.000000000 -0400
+@@ -283,13 +283,12 @@ static int pmu_aliases_parse(char *dir,
+ {
+ struct dirent *evt_ent;
+ DIR *event_dir;
+- int ret = 0;
+
+ event_dir = opendir(dir);
+ if (!event_dir)
+ return -EINVAL;
+
+- while (!ret && (evt_ent = readdir(event_dir))) {
++ while ((evt_ent = readdir(event_dir))) {
+ char path[PATH_MAX];
+ char *name = evt_ent->d_name;
+ FILE *file;
+@@ -305,17 +304,19 @@ static int pmu_aliases_parse(char *dir,
+
+ snprintf(path, PATH_MAX, "%s/%s", dir, name);
+
+- ret = -EINVAL;
+ file = fopen(path, "r");
+- if (!file)
+- break;
++ if (!file) {
++ pr_debug("Cannot open %s\n", path);
++ continue;
++ }
+
+- ret = perf_pmu__new_alias(head, dir, name, file);
++ if (perf_pmu__new_alias(head, dir, name, file) < 0)
++ pr_debug("Cannot set up %s\n", name);
+ fclose(file);
+ }
+
+ closedir(event_dir);
+- return ret;
++ return 0;
+ }
+
+ /*
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/perf/util/session.c linux-libre-4.4.7-gnu/tools/perf/util/session.c
+--- linux-libre-4.4-gnu/tools/perf/util/session.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/perf/util/session.c 2016-04-12 12:09:26.000000000 -0400
+@@ -972,7 +972,7 @@ static struct machine *machines__find_fo
+
+ machine = machines__find(machines, pid);
+ if (!machine)
+- machine = machines__find(machines, DEFAULT_GUEST_KERNEL_ID);
++ machine = machines__findnew(machines, DEFAULT_GUEST_KERNEL_ID);
+ return machine;
+ }
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/perf/util/setup.py linux-libre-4.4.7-gnu/tools/perf/util/setup.py
+--- linux-libre-4.4-gnu/tools/perf/util/setup.py 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/perf/util/setup.py 2016-04-12 12:09:26.000000000 -0400
+@@ -22,6 +22,7 @@ cflags = getenv('CFLAGS', '').split()
+ # switch off several checks (need to be at the end of cflags list)
+ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ]
+
++src_perf = getenv('srctree') + '/tools/perf'
+ build_lib = getenv('PYTHON_EXTBUILD_LIB')
+ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
+ libtraceevent = getenv('LIBTRACEEVENT')
+@@ -30,6 +31,9 @@ libapikfs = getenv('LIBAPI')
+ ext_sources = [f.strip() for f in file('util/python-ext-sources')
+ if len(f.strip()) > 0 and f[0] != '#']
+
++# use full paths with source files
++ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources)
++
+ perf = Extension('perf',
+ sources = ext_sources,
+ include_dirs = ['util/include'],
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/perf/util/stat.c linux-libre-4.4.7-gnu/tools/perf/util/stat.c
+--- linux-libre-4.4-gnu/tools/perf/util/stat.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/perf/util/stat.c 2016-04-12 12:09:26.000000000 -0400
+@@ -310,7 +310,6 @@ int perf_stat_process_counter(struct per
+ int i, ret;
+
+ aggr->val = aggr->ena = aggr->run = 0;
+- init_stats(ps->res_stats);
+
+ if (counter->per_pkg)
+ zero_per_pkg(counter);
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/testing/selftests/efivarfs/efivarfs.sh linux-libre-4.4.7-gnu/tools/testing/selftests/efivarfs/efivarfs.sh
+--- linux-libre-4.4-gnu/tools/testing/selftests/efivarfs/efivarfs.sh 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/testing/selftests/efivarfs/efivarfs.sh 2016-04-12 12:09:26.000000000 -0400
+@@ -88,7 +88,11 @@ test_delete()
+ exit 1
+ fi
+
+- rm $file
++ rm $file 2>/dev/null
++ if [ $? -ne 0 ]; then
++ chattr -i $file
++ rm $file
++ fi
+
+ if [ -e $file ]; then
+ echo "$file couldn't be deleted" >&2
+@@ -111,6 +115,7 @@ test_zero_size_delete()
+ exit 1
+ fi
+
++ chattr -i $file
+ printf "$attrs" > $file
+
+ if [ -e $file ]; then
+@@ -141,7 +146,11 @@ test_valid_filenames()
+ echo "$file could not be created" >&2
+ ret=1
+ else
+- rm $file
++ rm $file 2>/dev/null
++ if [ $? -ne 0 ]; then
++ chattr -i $file
++ rm $file
++ fi
+ fi
+ done
+
+@@ -174,7 +183,11 @@ test_invalid_filenames()
+
+ if [ -e $file ]; then
+ echo "Creating $file should have failed" >&2
+- rm $file
++ rm $file 2>/dev/null
++ if [ $? -ne 0 ]; then
++ chattr -i $file
++ rm $file
++ fi
+ ret=1
+ fi
+ done
+diff -druNp --no-dereference linux-libre-4.4-gnu/tools/testing/selftests/efivarfs/open-unlink.c linux-libre-4.4.7-gnu/tools/testing/selftests/efivarfs/open-unlink.c
+--- linux-libre-4.4-gnu/tools/testing/selftests/efivarfs/open-unlink.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/tools/testing/selftests/efivarfs/open-unlink.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1,10 +1,68 @@
++#include <errno.h>
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <sys/ioctl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
++#include <linux/fs.h>
++
++static int set_immutable(const char *path, int immutable)
++{
++ unsigned int flags;
++ int fd;
++ int rc;
++ int error;
++
++ fd = open(path, O_RDONLY);
++ if (fd < 0)
++ return fd;
++
++ rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
++ if (rc < 0) {
++ error = errno;
++ close(fd);
++ errno = error;
++ return rc;
++ }
++
++ if (immutable)
++ flags |= FS_IMMUTABLE_FL;
++ else
++ flags &= ~FS_IMMUTABLE_FL;
++
++ rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
++ error = errno;
++ close(fd);
++ errno = error;
++ return rc;
++}
++
++static int get_immutable(const char *path)
++{
++ unsigned int flags;
++ int fd;
++ int rc;
++ int error;
++
++ fd = open(path, O_RDONLY);
++ if (fd < 0)
++ return fd;
++
++ rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
++ if (rc < 0) {
++ error = errno;
++ close(fd);
++ errno = error;
++ return rc;
++ }
++ close(fd);
++ if (flags & FS_IMMUTABLE_FL)
++ return 1;
++ return 0;
++}
+
+ int main(int argc, char **argv)
+ {
+@@ -27,7 +85,7 @@ int main(int argc, char **argv)
+ buf[4] = 0;
+
+ /* create a test variable */
+- fd = open(path, O_WRONLY | O_CREAT);
++ fd = open(path, O_WRONLY | O_CREAT, 0600);
+ if (fd < 0) {
+ perror("open(O_WRONLY)");
+ return EXIT_FAILURE;
+@@ -41,6 +99,18 @@ int main(int argc, char **argv)
+
+ close(fd);
+
++ rc = get_immutable(path);
++ if (rc < 0) {
++ perror("ioctl(FS_IOC_GETFLAGS)");
++ return EXIT_FAILURE;
++ } else if (rc) {
++ rc = set_immutable(path, 0);
++ if (rc < 0) {
++ perror("ioctl(FS_IOC_SETFLAGS)");
++ return EXIT_FAILURE;
++ }
++ }
++
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+diff -druNp --no-dereference linux-libre-4.4-gnu/virt/kvm/arm/arch_timer.c linux-libre-4.4.7-gnu/virt/kvm/arm/arch_timer.c
+--- linux-libre-4.4-gnu/virt/kvm/arm/arch_timer.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/virt/kvm/arm/arch_timer.c 2016-04-12 12:09:26.000000000 -0400
+@@ -143,7 +143,7 @@ static void kvm_timer_update_irq(struct
+ * Check if there was a change in the timer state (should we raise or lower
+ * the line level to the GIC).
+ */
+-static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
++static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
+ {
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+@@ -154,10 +154,12 @@ static void kvm_timer_update_state(struc
+ * until we call this function from kvm_timer_flush_hwstate.
+ */
+ if (!vgic_initialized(vcpu->kvm))
+- return;
++ return -ENODEV;
+
+ if (kvm_timer_should_fire(vcpu) != timer->irq.level)
+ kvm_timer_update_irq(vcpu, !timer->irq.level);
++
++ return 0;
+ }
+
+ /*
+@@ -218,7 +220,8 @@ void kvm_timer_flush_hwstate(struct kvm_
+ bool phys_active;
+ int ret;
+
+- kvm_timer_update_state(vcpu);
++ if (kvm_timer_update_state(vcpu))
++ return;
+
+ /*
+ * If we enter the guest with the virtual input level to the VGIC
+diff -druNp --no-dereference linux-libre-4.4-gnu/virt/kvm/arm/vgic.c linux-libre-4.4.7-gnu/virt/kvm/arm/vgic.c
+--- linux-libre-4.4-gnu/virt/kvm/arm/vgic.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/virt/kvm/arm/vgic.c 2016-04-12 12:09:26.000000000 -0400
+@@ -1875,8 +1875,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vc
+ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
+ {
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+-
+- int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8;
++ int nr_longs = BITS_TO_LONGS(nr_irqs - VGIC_NR_PRIVATE_IRQS);
++ int sz = nr_longs * sizeof(unsigned long);
+ vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL);
+ vgic_cpu->active_shared = kzalloc(sz, GFP_KERNEL);
+ vgic_cpu->pend_act_shared = kzalloc(sz, GFP_KERNEL);
+diff -druNp --no-dereference linux-libre-4.4-gnu/virt/kvm/async_pf.c linux-libre-4.4.7-gnu/virt/kvm/async_pf.c
+--- linux-libre-4.4-gnu/virt/kvm/async_pf.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/virt/kvm/async_pf.c 2016-04-12 12:09:26.000000000 -0400
+@@ -173,7 +173,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *
+ * do alloc nowait since if we are going to sleep anyway we
+ * may as well sleep faulting in page
+ */
+- work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT);
++ work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT | __GFP_NOWARN);
+ if (!work)
+ return 0;
+
+diff -druNp --no-dereference linux-libre-4.4-gnu/virt/kvm/kvm_main.c linux-libre-4.4.7-gnu/virt/kvm/kvm_main.c
+--- linux-libre-4.4-gnu/virt/kvm/kvm_main.c 2016-01-10 18:01:32.000000000 -0500
++++ linux-libre-4.4.7-gnu/virt/kvm/kvm_main.c 2016-04-12 12:09:26.000000000 -0400
+@@ -547,6 +547,16 @@ static struct kvm *kvm_create_vm(unsigne
+ if (!kvm)
+ return ERR_PTR(-ENOMEM);
+
++ spin_lock_init(&kvm->mmu_lock);
++ atomic_inc(&current->mm->mm_count);
++ kvm->mm = current->mm;
++ kvm_eventfd_init(kvm);
++ mutex_init(&kvm->lock);
++ mutex_init(&kvm->irq_lock);
++ mutex_init(&kvm->slots_lock);
++ atomic_set(&kvm->users_count, 1);
++ INIT_LIST_HEAD(&kvm->devices);
++
+ r = kvm_arch_init_vm(kvm, type);
+ if (r)
+ goto out_err_no_disable;
+@@ -579,16 +589,6 @@ static struct kvm *kvm_create_vm(unsigne
+ goto out_err;
+ }
+
+- spin_lock_init(&kvm->mmu_lock);
+- kvm->mm = current->mm;
+- atomic_inc(&kvm->mm->mm_count);
+- kvm_eventfd_init(kvm);
+- mutex_init(&kvm->lock);
+- mutex_init(&kvm->irq_lock);
+- mutex_init(&kvm->slots_lock);
+- atomic_set(&kvm->users_count, 1);
+- INIT_LIST_HEAD(&kvm->devices);
+-
+ r = kvm_init_mmu_notifier(kvm);
+ if (r)
+ goto out_err;
+@@ -613,6 +613,7 @@ out_err_no_disable:
+ for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
+ kvm_free_memslots(kvm, kvm->memslots[i]);
+ kvm_arch_free_vm(kvm);
++ mmdrop(current->mm);
+ return ERR_PTR(r);
+ }
+
+@@ -1961,6 +1962,9 @@ static void grow_halt_poll_ns(struct kvm
+ else
+ val *= halt_poll_ns_grow;
+
++ if (val > halt_poll_ns)
++ val = halt_poll_ns;
++
+ vcpu->halt_poll_ns = val;
+ trace_kvm_halt_poll_ns_grow(vcpu->vcpu_id, val, old);
+ }