summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libre/linux-libre-lts/patch-4.4-gnu-4.4.7-gnu.patch37457
1 files changed, 0 insertions, 37457 deletions
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
deleted file mode 100644
index 014dfa298..000000000
--- a/libre/linux-libre-lts/patch-4.4-gnu-4.4.7-gnu.patch
+++ /dev/null
@@ -1,37457 +0,0 @@
-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);
- }