commit: 7d9a8056d89cb172bf638ec581f7429d45e52efe Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Wed Dec 22 14:09:28 2021 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Wed Dec 22 14:09:28 2021 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=7d9a8056
Linux patch 4.4.296 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> 0000_README | 14 +- 1295_linux-4.4.296.patch | 1358 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1367 insertions(+), 5 deletions(-) diff --git a/0000_README b/0000_README index e68fc753..2168e76a 100644 --- a/0000_README +++ b/0000_README @@ -1203,23 +1203,27 @@ Patch: 1289_linux-4.4.290.patch From: http://www.kernel.org Desc: Linux 4.4.290 -Patch: 1290_linux-4.4.291.patc +Patch: 1290_linux-4.4.291.patch From: http://www.kernel.org Desc: Linux 4.4.291 -Patch: 1291_linux-4.4.292.patc +Patch: 1291_linux-4.4.292.patch From: http://www.kernel.org Desc: Linux 4.4.292 -Patch: 1292_linux-4.4.293.patc +Patch: 1292_linux-4.4.293.patch From: http://www.kernel.org Desc: Linux 4.4.293 -Patch: 1293_linux-4.4.294.patc +Patch: 1293_linux-4.4.294.patch From: http://www.kernel.org Desc: Linux 4.4.294 -Patch: 1294_linux-4.4.295.patc +Patch: 1294_linux-4.4.295.patch +From: http://www.kernel.org +Desc: Linux 4.4.295 + +Patch: 1295_linux-4.4.296.patch From: http://www.kernel.org Desc: Linux 4.4.295 diff --git a/1295_linux-4.4.296.patch b/1295_linux-4.4.296.patch new file mode 100644 index 00000000..dea5ca91 --- /dev/null +++ b/1295_linux-4.4.296.patch @@ -0,0 +1,1358 @@ +diff --git a/Makefile b/Makefile +index b2a9f72ab8000..37c12303478e3 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 4 +-SUBLEVEL = 295 ++SUBLEVEL = 296 + EXTRAVERSION = + NAME = Blurry Fish Butt + +diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c +index d130a5ece5d55..bf24690ec83af 100644 +--- a/arch/arm/mm/copypage-fa.c ++++ b/arch/arm/mm/copypage-fa.c +@@ -17,26 +17,25 @@ + /* + * Faraday optimised copy_user_page + */ +-static void __naked +-fa_copy_user_page(void *kto, const void *kfrom) ++static void fa_copy_user_page(void *kto, const void *kfrom) + { +- asm("\ +- stmfd sp!, {r4, lr} @ 2\n\ +- mov r2, %0 @ 1\n\ +-1: ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +- stmia r0, {r3, r4, ip, lr} @ 4\n\ +- mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ +- add r0, r0, #16 @ 1\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +- stmia r0, {r3, r4, ip, lr} @ 4\n\ +- mcr p15, 0, r0, c7, c14, 1 @ 1 clean and invalidate D line\n\ +- add r0, r0, #16 @ 1\n\ +- subs r2, r2, #1 @ 1\n\ ++ int tmp; ++ ++ asm volatile ("\ ++1: ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++ stmia %0, {r3, r4, ip, lr} @ 4\n\ ++ mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ ++ add %0, %0, #16 @ 1\n\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++ stmia %0, {r3, r4, ip, lr} @ 4\n\ ++ mcr p15, 0, %0, c7, c14, 1 @ 1 clean and invalidate D line\n\ ++ add %0, %0, #16 @ 1\n\ ++ subs %2, %2, #1 @ 1\n\ + bne 1b @ 1\n\ +- mcr p15, 0, r2, c7, c10, 4 @ 1 drain WB\n\ +- ldmfd sp!, {r4, pc} @ 3" +- : +- : "I" (PAGE_SIZE / 32)); ++ mcr p15, 0, %2, c7, c10, 4 @ 1 drain WB" ++ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) ++ : "2" (PAGE_SIZE / 32) ++ : "r3", "r4", "ip", "lr"); + } + + void fa_copy_user_highpage(struct page *to, struct page *from, +diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c +index 49ee0c1a72097..cc819732d9b82 100644 +--- a/arch/arm/mm/copypage-feroceon.c ++++ b/arch/arm/mm/copypage-feroceon.c +@@ -13,58 +13,56 @@ + #include <linux/init.h> + #include <linux/highmem.h> + +-static void __naked +-feroceon_copy_user_page(void *kto, const void *kfrom) ++static void feroceon_copy_user_page(void *kto, const void *kfrom) + { +- asm("\ +- stmfd sp!, {r4-r9, lr} \n\ +- mov ip, %2 \n\ +-1: mov lr, r1 \n\ +- ldmia r1!, {r2 - r9} \n\ +- pld [lr, #32] \n\ +- pld [lr, #64] \n\ +- pld [lr, #96] \n\ +- pld [lr, #128] \n\ +- pld [lr, #160] \n\ +- pld [lr, #192] \n\ +- pld [lr, #224] \n\ +- stmia r0, {r2 - r9} \n\ +- ldmia r1!, {r2 - r9} \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ +- stmia r0, {r2 - r9} \n\ +- ldmia r1!, {r2 - r9} \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ +- stmia r0, {r2 - r9} \n\ +- ldmia r1!, {r2 - r9} \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ +- stmia r0, {r2 - r9} \n\ +- ldmia r1!, {r2 - r9} \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ +- stmia r0, {r2 - r9} \n\ +- ldmia r1!, {r2 - r9} \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ +- stmia r0, {r2 - r9} \n\ +- ldmia r1!, {r2 - r9} \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ +- stmia r0, {r2 - r9} \n\ +- ldmia r1!, {r2 - r9} \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ +- stmia r0, {r2 - r9} \n\ +- subs ip, ip, #(32 * 8) \n\ +- mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ +- add r0, r0, #32 \n\ ++ int tmp; ++ ++ asm volatile ("\ ++1: ldmia %1!, {r2 - r7, ip, lr} \n\ ++ pld [%1, #0] \n\ ++ pld [%1, #32] \n\ ++ pld [%1, #64] \n\ ++ pld [%1, #96] \n\ ++ pld [%1, #128] \n\ ++ pld [%1, #160] \n\ ++ pld [%1, #192] \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ ldmia %1!, {r2 - r7, ip, lr} \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ ldmia %1!, {r2 - r7, ip, lr} \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ ldmia %1!, {r2 - r7, ip, lr} \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ ldmia %1!, {r2 - r7, ip, lr} \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ ldmia %1!, {r2 - r7, ip, lr} \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ ldmia %1!, {r2 - r7, ip, lr} \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ ldmia %1!, {r2 - r7, ip, lr} \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ ++ stmia %0, {r2 - r7, ip, lr} \n\ ++ subs %2, %2, #(32 * 8) \n\ ++ mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ ++ add %0, %0, #32 \n\ + bne 1b \n\ +- mcr p15, 0, ip, c7, c10, 4 @ drain WB\n\ +- ldmfd sp!, {r4-r9, pc}" +- : +- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE)); ++ mcr p15, 0, %2, c7, c10, 4 @ drain WB" ++ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) ++ : "2" (PAGE_SIZE) ++ : "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr"); + } + + void feroceon_copy_user_highpage(struct page *to, struct page *from, +diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c +index 1267e64133b92..db624170854a0 100644 +--- a/arch/arm/mm/copypage-v4mc.c ++++ b/arch/arm/mm/copypage-v4mc.c +@@ -40,12 +40,11 @@ static DEFINE_RAW_SPINLOCK(minicache_lock); + * instruction. If your processor does not supply this, you have to write your + * own copy_user_highpage that does the right thing. + */ +-static void __naked +-mc_copy_user_page(void *from, void *to) ++static void mc_copy_user_page(void *from, void *to) + { +- asm volatile( +- "stmfd sp!, {r4, lr} @ 2\n\ +- mov r4, %2 @ 1\n\ ++ int tmp; ++ ++ asm volatile ("\ + ldmia %0!, {r2, r3, ip, lr} @ 4\n\ + 1: mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %1!, {r2, r3, ip, lr} @ 4\n\ +@@ -55,13 +54,13 @@ mc_copy_user_page(void *from, void *to) + mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %1!, {r2, r3, ip, lr} @ 4\n\ + ldmia %0!, {r2, r3, ip, lr} @ 4\n\ +- subs r4, r4, #1 @ 1\n\ ++ subs %2, %2, #1 @ 1\n\ + stmia %1!, {r2, r3, ip, lr} @ 4\n\ + ldmneia %0!, {r2, r3, ip, lr} @ 4\n\ +- bne 1b @ 1\n\ +- ldmfd sp!, {r4, pc} @ 3" +- : +- : "r" (from), "r" (to), "I" (PAGE_SIZE / 64)); ++ bne 1b @ " ++ : "+&r" (from), "+&r" (to), "=&r" (tmp) ++ : "2" (PAGE_SIZE / 64) ++ : "r2", "r3", "ip", "lr"); + } + + void v4_mc_copy_user_highpage(struct page *to, struct page *from, +diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c +index 067d0fdd630c1..cd3e165afeede 100644 +--- a/arch/arm/mm/copypage-v4wb.c ++++ b/arch/arm/mm/copypage-v4wb.c +@@ -22,29 +22,28 @@ + * instruction. If your processor does not supply this, you have to write your + * own copy_user_highpage that does the right thing. + */ +-static void __naked +-v4wb_copy_user_page(void *kto, const void *kfrom) ++static void v4wb_copy_user_page(void *kto, const void *kfrom) + { +- asm("\ +- stmfd sp!, {r4, lr} @ 2\n\ +- mov r2, %2 @ 1\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +-1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ +- stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\ +- stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +- mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ +- stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +- subs r2, r2, #1 @ 1\n\ +- stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmneia r1!, {r3, r4, ip, lr} @ 4\n\ ++ int tmp; ++ ++ asm volatile ("\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++1: mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ ++ stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4+1\n\ ++ stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++ mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ ++ stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++ subs %2, %2, #1 @ 1\n\ ++ stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmneia %1!, {r3, r4, ip, lr} @ 4\n\ + bne 1b @ 1\n\ +- mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB\n\ +- ldmfd sp!, {r4, pc} @ 3" +- : +- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64)); ++ mcr p15, 0, %1, c7, c10, 4 @ 1 drain WB" ++ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) ++ : "2" (PAGE_SIZE / 64) ++ : "r3", "r4", "ip", "lr"); + } + + void v4wb_copy_user_highpage(struct page *to, struct page *from, +diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c +index b85c5da2e510e..8614572e1296b 100644 +--- a/arch/arm/mm/copypage-v4wt.c ++++ b/arch/arm/mm/copypage-v4wt.c +@@ -20,27 +20,26 @@ + * dirty data in the cache. However, we do have to ensure that + * subsequent reads are up to date. + */ +-static void __naked +-v4wt_copy_user_page(void *kto, const void *kfrom) ++static void v4wt_copy_user_page(void *kto, const void *kfrom) + { +- asm("\ +- stmfd sp!, {r4, lr} @ 2\n\ +- mov r2, %2 @ 1\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +-1: stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4+1\n\ +- stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +- stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmia r1!, {r3, r4, ip, lr} @ 4\n\ +- subs r2, r2, #1 @ 1\n\ +- stmia r0!, {r3, r4, ip, lr} @ 4\n\ +- ldmneia r1!, {r3, r4, ip, lr} @ 4\n\ ++ int tmp; ++ ++ asm volatile ("\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++1: stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4+1\n\ ++ stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++ stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmia %1!, {r3, r4, ip, lr} @ 4\n\ ++ subs %2, %2, #1 @ 1\n\ ++ stmia %0!, {r3, r4, ip, lr} @ 4\n\ ++ ldmneia %1!, {r3, r4, ip, lr} @ 4\n\ + bne 1b @ 1\n\ +- mcr p15, 0, r2, c7, c7, 0 @ flush ID cache\n\ +- ldmfd sp!, {r4, pc} @ 3" +- : +- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64)); ++ mcr p15, 0, %2, c7, c7, 0 @ flush ID cache" ++ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) ++ : "2" (PAGE_SIZE / 64) ++ : "r3", "r4", "ip", "lr"); + } + + void v4wt_copy_user_highpage(struct page *to, struct page *from, +diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c +index 03a2042aced5f..55cbc3a89d858 100644 +--- a/arch/arm/mm/copypage-xsc3.c ++++ b/arch/arm/mm/copypage-xsc3.c +@@ -21,53 +21,46 @@ + + /* + * XSC3 optimised copy_user_highpage +- * r0 = destination +- * r1 = source + * + * The source page may have some clean entries in the cache already, but we + * can safely ignore them - break_cow() will flush them out of the cache + * if we eventually end up using our copied page. + * + */ +-static void __naked +-xsc3_mc_copy_user_page(void *kto, const void *kfrom) ++static void xsc3_mc_copy_user_page(void *kto, const void *kfrom) + { +- asm("\ +- stmfd sp!, {r4, r5, lr} \n\ +- mov lr, %2 \n\ +- \n\ +- pld [r1, #0] \n\ +- pld [r1, #32] \n\ +-1: pld [r1, #64] \n\ +- pld [r1, #96] \n\ ++ int tmp; ++ ++ asm volatile ("\ ++ pld [%1, #0] \n\ ++ pld [%1, #32] \n\ ++1: pld [%1, #64] \n\ ++ pld [%1, #96] \n\ + \n\ +-2: ldrd r2, [r1], #8 \n\ +- mov ip, r0 \n\ +- ldrd r4, [r1], #8 \n\ +- mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\ +- strd r2, [r0], #8 \n\ +- ldrd r2, [r1], #8 \n\ +- strd r4, [r0], #8 \n\ +- ldrd r4, [r1], #8 \n\ +- strd r2, [r0], #8 \n\ +- strd r4, [r0], #8 \n\ +- ldrd r2, [r1], #8 \n\ +- mov ip, r0 \n\ +- ldrd r4, [r1], #8 \n\ +- mcr p15, 0, ip, c7, c6, 1 @ invalidate\n\ +- strd r2, [r0], #8 \n\ +- ldrd r2, [r1], #8 \n\ +- subs lr, lr, #1 \n\ +- strd r4, [r0], #8 \n\ +- ldrd r4, [r1], #8 \n\ +- strd r2, [r0], #8 \n\ +- strd r4, [r0], #8 \n\ ++2: ldrd r2, [%1], #8 \n\ ++ ldrd r4, [%1], #8 \n\ ++ mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\ ++ strd r2, [%0], #8 \n\ ++ ldrd r2, [%1], #8 \n\ ++ strd r4, [%0], #8 \n\ ++ ldrd r4, [%1], #8 \n\ ++ strd r2, [%0], #8 \n\ ++ strd r4, [%0], #8 \n\ ++ ldrd r2, [%1], #8 \n\ ++ ldrd r4, [%1], #8 \n\ ++ mcr p15, 0, %0, c7, c6, 1 @ invalidate\n\ ++ strd r2, [%0], #8 \n\ ++ ldrd r2, [%1], #8 \n\ ++ subs %2, %2, #1 \n\ ++ strd r4, [%0], #8 \n\ ++ ldrd r4, [%1], #8 \n\ ++ strd r2, [%0], #8 \n\ ++ strd r4, [%0], #8 \n\ + bgt 1b \n\ +- beq 2b \n\ +- \n\ +- ldmfd sp!, {r4, r5, pc}" +- : +- : "r" (kto), "r" (kfrom), "I" (PAGE_SIZE / 64 - 1)); ++ beq 2b " ++ : "+&r" (kto), "+&r" (kfrom), "=&r" (tmp) ++ : "2" (PAGE_SIZE / 64 - 1) ++ : "r2", "r3", "r4", "r5"); + } + + void xsc3_mc_copy_user_highpage(struct page *to, struct page *from, +@@ -85,8 +78,6 @@ void xsc3_mc_copy_user_highpage(struct page *to, struct page *from, + + /* + * XScale optimised clear_user_page +- * r0 = destination +- * r1 = virtual user address of ultimate destination page + */ + void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr) + { +diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c +index 0fb85025344d9..c775d4b7adb08 100644 +--- a/arch/arm/mm/copypage-xscale.c ++++ b/arch/arm/mm/copypage-xscale.c +@@ -36,52 +36,51 @@ static DEFINE_RAW_SPINLOCK(minicache_lock); + * Dcache aliasing issue. The writes will be forwarded to the write buffer, + * and merged as appropriate. + */ +-static void __naked +-mc_copy_user_page(void *from, void *to) ++static void mc_copy_user_page(void *from, void *to) + { ++ int tmp; ++ + /* + * Strangely enough, best performance is achieved + * when prefetching destination as well. (NP) + */ +- asm volatile( +- "stmfd sp!, {r4, r5, lr} \n\ +- mov lr, %2 \n\ +- pld [r0, #0] \n\ +- pld [r0, #32] \n\ +- pld [r1, #0] \n\ +- pld [r1, #32] \n\ +-1: pld [r0, #64] \n\ +- pld [r0, #96] \n\ +- pld [r1, #64] \n\ +- pld [r1, #96] \n\ +-2: ldrd r2, [r0], #8 \n\ +- ldrd r4, [r0], #8 \n\ +- mov ip, r1 \n\ +- strd r2, [r1], #8 \n\ +- ldrd r2, [r0], #8 \n\ +- strd r4, [r1], #8 \n\ +- ldrd r4, [r0], #8 \n\ +- strd r2, [r1], #8 \n\ +- strd r4, [r1], #8 \n\ ++ asm volatile ("\ ++ pld [%0, #0] \n\ ++ pld [%0, #32] \n\ ++ pld [%1, #0] \n\ ++ pld [%1, #32] \n\ ++1: pld [%0, #64] \n\ ++ pld [%0, #96] \n\ ++ pld [%1, #64] \n\ ++ pld [%1, #96] \n\ ++2: ldrd r2, [%0], #8 \n\ ++ ldrd r4, [%0], #8 \n\ ++ mov ip, %1 \n\ ++ strd r2, [%1], #8 \n\ ++ ldrd r2, [%0], #8 \n\ ++ strd r4, [%1], #8 \n\ ++ ldrd r4, [%0], #8 \n\ ++ strd r2, [%1], #8 \n\ ++ strd r4, [%1], #8 \n\ + mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\ +- ldrd r2, [r0], #8 \n\ ++ ldrd r2, [%0], #8 \n\ + mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\ +- ldrd r4, [r0], #8 \n\ +- mov ip, r1 \n\ +- strd r2, [r1], #8 \n\ +- ldrd r2, [r0], #8 \n\ +- strd r4, [r1], #8 \n\ +- ldrd r4, [r0], #8 \n\ +- strd r2, [r1], #8 \n\ +- strd r4, [r1], #8 \n\ ++ ldrd r4, [%0], #8 \n\ ++ mov ip, %1 \n\ ++ strd r2, [%1], #8 \n\ ++ ldrd r2, [%0], #8 \n\ ++ strd r4, [%1], #8 \n\ ++ ldrd r4, [%0], #8 \n\ ++ strd r2, [%1], #8 \n\ ++ strd r4, [%1], #8 \n\ + mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\ +- subs lr, lr, #1 \n\ ++ subs %2, %2, #1 \n\ + mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\ + bgt 1b \n\ +- beq 2b \n\ +- ldmfd sp!, {r4, r5, pc} " +- : +- : "r" (from), "r" (to), "I" (PAGE_SIZE / 64 - 1)); ++ beq 2b " ++ : "+&r" (from), "+&r" (to), "=&r" (tmp) ++ : "2" (PAGE_SIZE / 64 - 1) ++ : "r2", "r3", "r4", "r5", "ip"); + } + + void xscale_mc_copy_user_highpage(struct page *to, struct page *from, +diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c +index b27917dfdcc05..1e44b7880200d 100644 +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1319,11 +1319,13 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + unsigned long flags; + struct blkfront_info *info = (struct blkfront_info *)dev_id; + int error; ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; + + spin_lock_irqsave(&info->io_lock, flags); + + if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) { + spin_unlock_irqrestore(&info->io_lock, flags); ++ xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS); + return IRQ_HANDLED; + } + +@@ -1340,6 +1342,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + unsigned long id; + unsigned int op; + ++ eoiflag = 0; ++ + RING_COPY_RESPONSE(&info->ring, i, &bret); + id = bret.id; + +@@ -1444,6 +1448,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + + spin_unlock_irqrestore(&info->io_lock, flags); + ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + + err: +@@ -1451,6 +1457,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) + + spin_unlock_irqrestore(&info->io_lock, flags); + ++ /* No EOI in order to avoid further interrupts. */ ++ + pr_alert("%s disabled for further use\n", info->gd->disk_name); + return IRQ_HANDLED; + } +@@ -1489,8 +1497,8 @@ static int setup_blkring(struct xenbus_device *dev, + if (err) + goto fail; + +- err = bind_evtchn_to_irqhandler(info->evtchn, blkif_interrupt, 0, +- "blkif", info); ++ err = bind_evtchn_to_irqhandler_lateeoi(info->evtchn, blkif_interrupt, ++ 0, "blkif", info); + if (err <= 0) { + xenbus_dev_fatal(dev, err, + "bind_evtchn_to_irqhandler failed"); +diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c +index 15f2e7025b78e..1d5510cb6db4e 100644 +--- a/drivers/char/agp/parisc-agp.c ++++ b/drivers/char/agp/parisc-agp.c +@@ -285,7 +285,7 @@ agp_ioc_init(void __iomem *ioc_regs) + return 0; + } + +-static int ++static int __init + lba_find_capability(int cap) + { + struct _parisc_agp_info *info = &parisc_agp_info; +@@ -370,7 +370,7 @@ fail: + return error; + } + +-static int ++static int __init + find_quicksilver(struct device *dev, void *data) + { + struct parisc_device **lba = data; +@@ -382,7 +382,7 @@ find_quicksilver(struct device *dev, void *data) + return 0; + } + +-static int ++static int __init + parisc_agp_init(void) + { + extern struct sba_device *sba_list; +diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c +index a9356a3dea926..da8465cf26cb8 100644 +--- a/drivers/hwmon/dell-smm-hwmon.c ++++ b/drivers/hwmon/dell-smm-hwmon.c +@@ -551,15 +551,18 @@ static const struct file_operations i8k_fops = { + .unlocked_ioctl = i8k_ioctl, + }; + ++static struct proc_dir_entry *entry; ++ + static void __init i8k_init_procfs(void) + { + /* Register the proc entry */ +- proc_create("i8k", 0, NULL, &i8k_fops); ++ entry = proc_create("i8k", 0, NULL, &i8k_fops); + } + + static void __exit i8k_exit_procfs(void) + { +- remove_proc_entry("i8k", NULL); ++ if (entry) ++ remove_proc_entry("i8k", NULL); + } + + #else +diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c +index 9096d17beb5bb..587f1a5a10243 100644 +--- a/drivers/i2c/busses/i2c-rk3x.c ++++ b/drivers/i2c/busses/i2c-rk3x.c +@@ -325,8 +325,8 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) + if (!(ipd & REG_INT_MBRF)) + return; + +- /* ack interrupt */ +- i2c_writel(i2c, REG_INT_MBRF, REG_IPD); ++ /* ack interrupt (read also produces a spurious START flag, clear it too) */ ++ i2c_writel(i2c, REG_INT_MBRF | REG_INT_START, REG_IPD); + + /* Can only handle a maximum of 32 bytes at a time */ + if (len > 32) +diff --git a/drivers/input/touchscreen/of_touchscreen.c b/drivers/input/touchscreen/of_touchscreen.c +index bb6f2fe146672..490f3055aec39 100644 +--- a/drivers/input/touchscreen/of_touchscreen.c ++++ b/drivers/input/touchscreen/of_touchscreen.c +@@ -75,8 +75,8 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch) + data_present = touchscreen_get_prop_u32(dev, "touchscreen-size-x", + input_abs_get_max(input, + axis) + 1, +- &maximum) | +- touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x", ++ &maximum); ++ data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x", + input_abs_get_fuzz(input, axis), + &fuzz); + if (data_present) +@@ -86,8 +86,8 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch) + data_present = touchscreen_get_prop_u32(dev, "touchscreen-size-y", + input_abs_get_max(input, + axis) + 1, +- &maximum) | +- touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y", ++ &maximum); ++ data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y", + input_abs_get_fuzz(input, axis), + &fuzz); + if (data_present) +@@ -97,11 +97,11 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch) + data_present = touchscreen_get_prop_u32(dev, + "touchscreen-max-pressure", + input_abs_get_max(input, axis), +- &maximum) | +- touchscreen_get_prop_u32(dev, +- "touchscreen-fuzz-pressure", +- input_abs_get_fuzz(input, axis), +- &fuzz); ++ &maximum); ++ data_present |= touchscreen_get_prop_u32(dev, ++ "touchscreen-fuzz-pressure", ++ input_abs_get_fuzz(input, axis), ++ &fuzz); + if (data_present) + touchscreen_set_params(input, axis, maximum, fuzz); + } +diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c +index 9e4d1212f4c16..63f2baed3c8a6 100644 +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -423,9 +423,9 @@ static int rebalance_children(struct shadow_spine *s, + + memcpy(n, dm_block_data(child), + dm_bm_block_size(dm_tm_get_bm(info->tm))); +- dm_tm_unlock(info->tm, child); + + dm_tm_dec(info->tm, dm_block_location(child)); ++ dm_tm_unlock(info->tm, child); + return 0; + } + +diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c +index 94f06c35ad9c3..c76102754c226 100644 +--- a/drivers/net/ethernet/broadcom/bcmsysport.c ++++ b/drivers/net/ethernet/broadcom/bcmsysport.c +@@ -90,9 +90,13 @@ static inline void tdma_port_write_desc_addr(struct bcm_sysport_priv *priv, + struct dma_desc *desc, + unsigned int port) + { ++ unsigned long desc_flags; ++ + /* Ports are latched, so write upper address first */ ++ spin_lock_irqsave(&priv->desc_lock, desc_flags); + tdma_writel(priv, desc->addr_status_len, TDMA_WRITE_PORT_HI(port)); + tdma_writel(priv, desc->addr_lo, TDMA_WRITE_PORT_LO(port)); ++ spin_unlock_irqrestore(&priv->desc_lock, desc_flags); + } + + /* Ethtool operations */ +@@ -1608,6 +1612,7 @@ static int bcm_sysport_open(struct net_device *dev) + } + + /* Initialize both hardware and software ring */ ++ spin_lock_init(&priv->desc_lock); + for (i = 0; i < dev->num_tx_queues; i++) { + ret = bcm_sysport_init_tx_ring(priv, i); + if (ret) { +diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h +index e668b1ce58280..bb484c7faf679 100644 +--- a/drivers/net/ethernet/broadcom/bcmsysport.h ++++ b/drivers/net/ethernet/broadcom/bcmsysport.h +@@ -660,6 +660,7 @@ struct bcm_sysport_priv { + int wol_irq; + + /* Transmit rings */ ++ spinlock_t desc_lock; + struct bcm_sysport_tx_ring tx_rings[TDMA_NUM_RINGS]; + + /* Receive queue */ +diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c +index 519b72c418884..ab080118201df 100644 +--- a/drivers/net/ethernet/intel/igbvf/netdev.c ++++ b/drivers/net/ethernet/intel/igbvf/netdev.c +@@ -2793,6 +2793,7 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + return 0; + + err_hw_init: ++ netif_napi_del(&adapter->rx_ring->napi); + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + err_sw_init: +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 324e2e15092f3..ca3c7a4402a1b 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -609,11 +609,9 @@ static int lan78xx_read_otp(struct lan78xx_net *dev, u32 offset, + ret = lan78xx_read_raw_otp(dev, 0, 1, &sig); + + if (ret == 0) { +- if (sig == OTP_INDICATOR_1) +- offset = offset; +- else if (sig == OTP_INDICATOR_2) ++ if (sig == OTP_INDICATOR_2) + offset += 0x100; +- else ++ else if (sig != OTP_INDICATOR_1) + ret = -EINVAL; + if (!ret) + ret = lan78xx_read_raw_otp(dev, offset, length, data); +diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c +index 15c73ebe5efca..044478c9adad6 100644 +--- a/drivers/net/xen-netback/netback.c ++++ b/drivers/net/xen-netback/netback.c +@@ -189,11 +189,15 @@ void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb) + + spin_lock_irqsave(&queue->rx_queue.lock, flags); + +- __skb_queue_tail(&queue->rx_queue, skb); +- +- queue->rx_queue_len += skb->len; +- if (queue->rx_queue_len > queue->rx_queue_max) ++ if (queue->rx_queue_len >= queue->rx_queue_max) { + netif_tx_stop_queue(netdev_get_tx_queue(queue->vif->dev, queue->id)); ++ kfree_skb(skb); ++ queue->vif->dev->stats.rx_dropped++; ++ } else { ++ __skb_queue_tail(&queue->rx_queue, skb); ++ ++ queue->rx_queue_len += skb->len; ++ } + + spin_unlock_irqrestore(&queue->rx_queue.lock, flags); + } +@@ -243,6 +247,7 @@ static void xenvif_rx_queue_drop_expired(struct xenvif_queue *queue) + break; + xenvif_rx_dequeue(queue); + kfree_skb(skb); ++ queue->vif->dev->stats.rx_dropped++; + } + } + +diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c +index 46b9f379035f5..637d5e894012c 100644 +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -141,6 +141,9 @@ struct netfront_queue { + struct sk_buff *rx_skbs[NET_RX_RING_SIZE]; + grant_ref_t gref_rx_head; + grant_ref_t grant_rx_ref[NET_RX_RING_SIZE]; ++ ++ unsigned int rx_rsp_unconsumed; ++ spinlock_t rx_cons_lock; + }; + + struct netfront_info { +@@ -365,11 +368,12 @@ static int xennet_open(struct net_device *dev) + return 0; + } + +-static void xennet_tx_buf_gc(struct netfront_queue *queue) ++static bool xennet_tx_buf_gc(struct netfront_queue *queue) + { + RING_IDX cons, prod; + unsigned short id; + struct sk_buff *skb; ++ bool work_done = false; + const struct device *dev = &queue->info->netdev->dev; + + BUG_ON(!netif_carrier_ok(queue->info->netdev)); +@@ -386,6 +390,8 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) + for (cons = queue->tx.rsp_cons; cons != prod; cons++) { + struct xen_netif_tx_response txrsp; + ++ work_done = true; ++ + RING_COPY_RESPONSE(&queue->tx, cons, &txrsp); + if (txrsp.status == XEN_NETIF_RSP_NULL) + continue; +@@ -439,11 +445,13 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) + + xennet_maybe_wake_tx(queue); + +- return; ++ return work_done; + + err: + queue->info->broken = true; + dev_alert(dev, "Disabled for further use\n"); ++ ++ return work_done; + } + + struct xennet_gnttab_make_txreq { +@@ -748,6 +756,16 @@ static int xennet_close(struct net_device *dev) + return 0; + } + ++static void xennet_set_rx_rsp_cons(struct netfront_queue *queue, RING_IDX val) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&queue->rx_cons_lock, flags); ++ queue->rx.rsp_cons = val; ++ queue->rx_rsp_unconsumed = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx); ++ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); ++} ++ + static void xennet_move_rx_slot(struct netfront_queue *queue, struct sk_buff *skb, + grant_ref_t ref) + { +@@ -799,7 +817,7 @@ static int xennet_get_extras(struct netfront_queue *queue, + xennet_move_rx_slot(queue, skb, ref); + } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); + +- queue->rx.rsp_cons = cons; ++ xennet_set_rx_rsp_cons(queue, cons); + return err; + } + +@@ -879,7 +897,7 @@ next: + } + + if (unlikely(err)) +- queue->rx.rsp_cons = cons + slots; ++ xennet_set_rx_rsp_cons(queue, cons + slots); + + return err; + } +@@ -933,7 +951,8 @@ static int xennet_fill_frags(struct netfront_queue *queue, + __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); + } + if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) { +- queue->rx.rsp_cons = ++cons + skb_queue_len(list); ++ xennet_set_rx_rsp_cons(queue, ++ ++cons + skb_queue_len(list)); + kfree_skb(nskb); + return -ENOENT; + } +@@ -946,7 +965,7 @@ static int xennet_fill_frags(struct netfront_queue *queue, + kfree_skb(nskb); + } + +- queue->rx.rsp_cons = cons; ++ xennet_set_rx_rsp_cons(queue, cons); + + return 0; + } +@@ -1067,7 +1086,9 @@ err: + + if (unlikely(xennet_set_skb_gso(skb, gso))) { + __skb_queue_head(&tmpq, skb); +- queue->rx.rsp_cons += skb_queue_len(&tmpq); ++ xennet_set_rx_rsp_cons(queue, ++ queue->rx.rsp_cons + ++ skb_queue_len(&tmpq)); + goto err; + } + } +@@ -1091,7 +1112,8 @@ err: + + __skb_queue_tail(&rxq, skb); + +- i = ++queue->rx.rsp_cons; ++ i = queue->rx.rsp_cons + 1; ++ xennet_set_rx_rsp_cons(queue, i); + work_done++; + } + +@@ -1275,40 +1297,79 @@ static int xennet_set_features(struct net_device *dev, + return 0; + } + +-static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id) ++static bool xennet_handle_tx(struct netfront_queue *queue, unsigned int *eoi) + { +- struct netfront_queue *queue = dev_id; + unsigned long flags; + +- if (queue->info->broken) +- return IRQ_HANDLED; ++ if (unlikely(queue->info->broken)) ++ return false; + + spin_lock_irqsave(&queue->tx_lock, flags); +- xennet_tx_buf_gc(queue); ++ if (xennet_tx_buf_gc(queue)) ++ *eoi = 0; + spin_unlock_irqrestore(&queue->tx_lock, flags); + ++ return true; ++} ++ ++static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id) ++{ ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ ++ if (likely(xennet_handle_tx(dev_id, &eoiflag))) ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + } + +-static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id) ++static bool xennet_handle_rx(struct netfront_queue *queue, unsigned int *eoi) + { +- struct netfront_queue *queue = dev_id; +- struct net_device *dev = queue->info->netdev; ++ unsigned int work_queued; ++ unsigned long flags; + +- if (queue->info->broken) +- return IRQ_HANDLED; ++ if (unlikely(queue->info->broken)) ++ return false; ++ ++ spin_lock_irqsave(&queue->rx_cons_lock, flags); ++ work_queued = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx); ++ if (work_queued > queue->rx_rsp_unconsumed) { ++ queue->rx_rsp_unconsumed = work_queued; ++ *eoi = 0; ++ } else if (unlikely(work_queued < queue->rx_rsp_unconsumed)) { ++ const struct device *dev = &queue->info->netdev->dev; ++ ++ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); ++ dev_alert(dev, "RX producer index going backwards\n"); ++ dev_alert(dev, "Disabled for further use\n"); ++ queue->info->broken = true; ++ return false; ++ } ++ spin_unlock_irqrestore(&queue->rx_cons_lock, flags); + +- if (likely(netif_carrier_ok(dev) && +- RING_HAS_UNCONSUMED_RESPONSES(&queue->rx))) ++ if (likely(netif_carrier_ok(queue->info->netdev) && work_queued)) + napi_schedule(&queue->napi); + ++ return true; ++} ++ ++static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id) ++{ ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ ++ if (likely(xennet_handle_rx(dev_id, &eoiflag))) ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + } + + static irqreturn_t xennet_interrupt(int irq, void *dev_id) + { +- xennet_tx_interrupt(irq, dev_id); +- xennet_rx_interrupt(irq, dev_id); ++ unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ ++ if (xennet_handle_tx(dev_id, &eoiflag) && ++ xennet_handle_rx(dev_id, &eoiflag)) ++ xen_irq_lateeoi(irq, eoiflag); ++ + return IRQ_HANDLED; + } + +@@ -1540,9 +1601,10 @@ static int setup_netfront_single(struct netfront_queue *queue) + if (err < 0) + goto fail; + +- err = bind_evtchn_to_irqhandler(queue->tx_evtchn, +- xennet_interrupt, +- 0, queue->info->netdev->name, queue); ++ err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn, ++ xennet_interrupt, 0, ++ queue->info->netdev->name, ++ queue); + if (err < 0) + goto bind_fail; + queue->rx_evtchn = queue->tx_evtchn; +@@ -1570,18 +1632,18 @@ static int setup_netfront_split(struct netfront_queue *queue) + + snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name), + "%s-tx", queue->name); +- err = bind_evtchn_to_irqhandler(queue->tx_evtchn, +- xennet_tx_interrupt, +- 0, queue->tx_irq_name, queue); ++ err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn, ++ xennet_tx_interrupt, 0, ++ queue->tx_irq_name, queue); + if (err < 0) + goto bind_tx_fail; + queue->tx_irq = err; + + snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name), + "%s-rx", queue->name); +- err = bind_evtchn_to_irqhandler(queue->rx_evtchn, +- xennet_rx_interrupt, +- 0, queue->rx_irq_name, queue); ++ err = bind_evtchn_to_irqhandler_lateeoi(queue->rx_evtchn, ++ xennet_rx_interrupt, 0, ++ queue->rx_irq_name, queue); + if (err < 0) + goto bind_rx_fail; + queue->rx_irq = err; +@@ -1683,6 +1745,7 @@ static int xennet_init_queue(struct netfront_queue *queue) + + spin_lock_init(&queue->tx_lock); + spin_lock_init(&queue->rx_lock); ++ spin_lock_init(&queue->rx_cons_lock); + + setup_timer(&queue->rx_refill_timer, rx_refill_timeout, + (unsigned long)queue); +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 534aa676bf551..92e78547b00a5 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -840,7 +840,7 @@ out_free: + free_msi_irqs(dev); + + out_disable: +- pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0); ++ pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0); + + return ret; + } +diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c +index c4f5e5bbb8dce..9397e8ba26469 100644 +--- a/drivers/soc/tegra/fuse/fuse-tegra.c ++++ b/drivers/soc/tegra/fuse/fuse-tegra.c +@@ -176,7 +176,7 @@ static struct platform_driver tegra_fuse_driver = { + }; + module_platform_driver(tegra_fuse_driver); + +-bool __init tegra_fuse_read_spare(unsigned int spare) ++u32 __init tegra_fuse_read_spare(unsigned int spare) + { + unsigned int offset = fuse->soc->info->spare + spare * 4; + +diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h +index 10c2076d5089a..f368bd5373088 100644 +--- a/drivers/soc/tegra/fuse/fuse.h ++++ b/drivers/soc/tegra/fuse/fuse.h +@@ -62,7 +62,7 @@ struct tegra_fuse { + void tegra_init_revision(void); + void tegra_init_apbmisc(void); + +-bool __init tegra_fuse_read_spare(unsigned int spare); ++u32 __init tegra_fuse_read_spare(unsigned int spare); + u32 __init tegra_fuse_read_early(unsigned int offset); + + #ifdef CONFIG_ARCH_TEGRA_2x_SOC +diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c +index e503ad91a25a5..4826a6db87b17 100644 +--- a/drivers/tty/hvc/hvc_xen.c ++++ b/drivers/tty/hvc/hvc_xen.c +@@ -49,6 +49,8 @@ struct xencons_info { + struct xenbus_device *xbdev; + struct xencons_interface *intf; + unsigned int evtchn; ++ XENCONS_RING_IDX out_cons; ++ unsigned int out_cons_same; + struct hvc_struct *hvc; + int irq; + int vtermno; +@@ -150,6 +152,8 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) + XENCONS_RING_IDX cons, prod; + int recv = 0; + struct xencons_info *xencons = vtermno_to_xencons(vtermno); ++ unsigned int eoiflag = 0; ++ + if (xencons == NULL) + return -EINVAL; + intf = xencons->intf; +@@ -169,7 +173,27 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len) + mb(); /* read ring before consuming */ + intf->in_cons = cons; + +- notify_daemon(xencons); ++ /* ++ * When to mark interrupt having been spurious: ++ * - there was no new data to be read, and ++ * - the backend did not consume some output bytes, and ++ * - the previous round with no read data didn't see consumed bytes ++ * (we might have a race with an interrupt being in flight while ++ * updating xencons->out_cons, so account for that by allowing one ++ * round without any visible reason) ++ */ ++ if (intf->out_cons != xencons->out_cons) { ++ xencons->out_cons = intf->out_cons; ++ xencons->out_cons_same = 0; ++ } ++ if (recv) { ++ notify_daemon(xencons); ++ } else if (xencons->out_cons_same++ > 1) { ++ eoiflag = XEN_EOI_FLAG_SPURIOUS; ++ } ++ ++ xen_irq_lateeoi(xencons->irq, eoiflag); ++ + return recv; + } + +@@ -391,7 +415,7 @@ static int xencons_connect_backend(struct xenbus_device *dev, + if (ret) + return ret; + info->evtchn = evtchn; +- irq = bind_evtchn_to_irq(evtchn); ++ irq = bind_interdomain_evtchn_to_irq_lateeoi(dev->otherend_id, evtchn); + if (irq < 0) + return irq; + info->irq = irq; +@@ -555,7 +579,7 @@ static int __init xen_hvc_init(void) + return r; + + info = vtermno_to_xencons(HVC_COOKIE); +- info->irq = bind_evtchn_to_irq(info->evtchn); ++ info->irq = bind_evtchn_to_irq_lateeoi(info->evtchn); + } + if (info->irq < 0) + info->irq = 0; /* NO_IRQ */ +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +index 1f584d15a3ca4..580ba69f1e4a4 100644 +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -1485,14 +1485,14 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) + u8 endp; + + if (w_length > USB_COMP_EP0_BUFSIZ) { +- if (ctrl->bRequestType == USB_DIR_OUT) { +- goto done; +- } else { ++ if (ctrl->bRequestType & USB_DIR_IN) { + /* Cast away the const, we are going to overwrite on purpose. */ + __le16 *temp = (__le16 *)&ctrl->wLength; + + *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); + w_length = USB_COMP_EP0_BUFSIZ; ++ } else { ++ goto done; + } + } + +diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c +index f1c5a22704b28..e8818ad973e4b 100644 +--- a/drivers/usb/gadget/legacy/dbgp.c ++++ b/drivers/usb/gadget/legacy/dbgp.c +@@ -345,14 +345,14 @@ static int dbgp_setup(struct usb_gadget *gadget, + u16 len = 0; + + if (length > DBGP_REQ_LEN) { +- if (ctrl->bRequestType == USB_DIR_OUT) { +- return err; +- } else { ++ if (ctrl->bRequestType & USB_DIR_IN) { + /* Cast away the const, we are going to overwrite on purpose. */ + __le16 *temp = (__le16 *)&ctrl->wLength; + + *temp = cpu_to_le16(DBGP_REQ_LEN); + length = DBGP_REQ_LEN; ++ } else { ++ return err; + } + } + +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index af0b34763326d..f2b4fdd1f49d5 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -1335,14 +1335,14 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) + u16 w_length = le16_to_cpu(ctrl->wLength); + + if (w_length > RBUF_SIZE) { +- if (ctrl->bRequestType == USB_DIR_OUT) { +- return value; +- } else { ++ if (ctrl->bRequestType & USB_DIR_IN) { + /* Cast away the const, we are going to overwrite on purpose. */ + __le16 *temp = (__le16 *)&ctrl->wLength; + + *temp = cpu_to_le16(RBUF_SIZE); + w_length = RBUF_SIZE; ++ } else { ++ return value; + } + } + +diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c +index 502931f658a8e..9479abb9eaaaf 100644 +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -1195,6 +1195,14 @@ static const struct usb_device_id option_ids[] = { + .driver_info = NCTRL(2) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ + .driver_info = NCTRL(0) | RSVD(1) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */ ++ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */ ++ .driver_info = NCTRL(0) | RSVD(1) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */ ++ .driver_info = NCTRL(2) | RSVD(3) }, ++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ ++ .driver_info = NCTRL(0) | RSVD(1) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), + .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index ea5cb1ba282fd..5ee62045150c0 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -844,6 +844,11 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) + return 0; + } + ++static bool delegation_hashed(struct nfs4_delegation *dp) ++{ ++ return !(list_empty(&dp->dl_perfile)); ++} ++ + static bool + unhash_delegation_locked(struct nfs4_delegation *dp) + { +@@ -851,7 +856,7 @@ unhash_delegation_locked(struct nfs4_delegation *dp) + + lockdep_assert_held(&state_lock); + +- if (list_empty(&dp->dl_perfile)) ++ if (!delegation_hashed(dp)) + return false; + + dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID; +@@ -3656,7 +3661,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb) + * queued for a lease break. Don't queue it again. + */ + spin_lock(&state_lock); +- if (dp->dl_time == 0) { ++ if (delegation_hashed(dp) && dp->dl_time == 0) { + dp->dl_time = get_seconds(); + list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru); + } +diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c +index d9837d25dfe06..19fbd6c6283ba 100644 +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -966,8 +966,7 @@ int do_settimeofday64(const struct timespec64 *ts) + timekeeping_forward_now(tk); + + xt = tk_xtime(tk); +- ts_delta.tv_sec = ts->tv_sec - xt.tv_sec; +- ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec; ++ ts_delta = timespec64_sub(*ts, xt); + + if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { + ret = -EINVAL; +diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c +index 4932e9f243a2c..3d49ffe8a34d5 100644 +--- a/net/mac80211/agg-tx.c ++++ b/net/mac80211/agg-tx.c +@@ -109,7 +109,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, + mgmt->u.action.u.addba_req.start_seq_num = + cpu_to_le16(start_seq_num << 4); + +- ieee80211_tx_skb(sdata, skb); ++ ieee80211_tx_skb_tid(sdata, skb, tid); + } + + void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 65cf129eaad33..2f23b7fef8ef7 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1804,6 +1804,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + if (msg->msg_flags&MSG_OOB) + return -EOPNOTSUPP; + ++ if (len == 0) { ++ pr_warn_once("Zero length message leads to an empty skb\n"); ++ return -ENODATA; ++ } ++ + err = scm_send(sock, msg, &scm, true); + if (err < 0) + return err; +diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c +index 00a0f0476a543..4286b900a3066 100644 +--- a/net/nfc/netlink.c ++++ b/net/nfc/netlink.c +@@ -632,8 +632,10 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) + { + struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; + +- nfc_device_iter_exit(iter); +- kfree(iter); ++ if (iter) { ++ nfc_device_iter_exit(iter); ++ kfree(iter); ++ } + + return 0; + } +diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl +index 5ca4ec2970197..b690b294fc36b 100755 +--- a/scripts/recordmcount.pl ++++ b/scripts/recordmcount.pl +@@ -248,7 +248,7 @@ if ($arch eq "x86_64") { + + } elsif ($arch eq "s390" && $bits == 64) { + if ($cc =~ /-DCC_USING_HOTPATCH/) { +- $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$"; ++ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*(bcrl\\s*0,|jgnop\\s*)[0-9a-f]+ <([^\+]*)>\$"; + $mcount_adjust = 0; + } else { + $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
