From d6be0cdd95936af15f9c546364b687d3561f34cf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 May 2018 11:39:09 +0200 Subject: [PATCH] 4.9-stable patches added patches: futex-remove-duplicated-code-and-fix-undefined-behaviour.patch mm-vmstat-print-non-populated-zones-in-zoneinfo.patch serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch --- ...ted-code-and-fix-undefined-behaviour.patch | 1090 +++++++++++++++++ ...rint-non-populated-zones-in-zoneinfo.patch | 143 +++ ...p-fix-error-handling-in-sccnxp_probe.patch | 52 + queue-4.9/series | 3 + 4 files changed, 1288 insertions(+) create mode 100644 queue-4.9/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch create mode 100644 queue-4.9/mm-vmstat-print-non-populated-zones-in-zoneinfo.patch create mode 100644 queue-4.9/serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch diff --git a/queue-4.9/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch b/queue-4.9/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch new file mode 100644 index 00000000000..0ecb8a0b86c --- /dev/null +++ b/queue-4.9/futex-remove-duplicated-code-and-fix-undefined-behaviour.patch @@ -0,0 +1,1090 @@ +From 30d6e0a4190d37740e9447e4e4815f06992dd8c3 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Thu, 24 Aug 2017 09:31:05 +0200 +Subject: futex: Remove duplicated code and fix undefined behaviour + +From: Jiri Slaby + +commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream. + +There is code duplicated over all architecture's headers for +futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr, +and comparison of the result. + +Remove this duplication and leave up to the arches only the needed +assembly which is now in arch_futex_atomic_op_inuser. + +This effectively distributes the Will Deacon's arm64 fix for undefined +behaviour reported by UBSAN to all architectures. The fix was done in +commit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with +FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump. + +And as suggested by Thomas, check for negative oparg too, because it was +also reported to cause undefined behaviour report. + +Note that s390 removed access_ok check in d12a29703 ("s390/uaccess: +remove pointless access_ok() checks") as access_ok there returns true. +We introduce it back to the helper for the sake of simplicity (it gets +optimized away anyway). + +Signed-off-by: Jiri Slaby +Signed-off-by: Thomas Gleixner +Acked-by: Russell King +Acked-by: Michael Ellerman (powerpc) +Acked-by: Heiko Carstens [s390] +Acked-by: Chris Metcalf [for tile] +Reviewed-by: Darren Hart (VMware) +Reviewed-by: Will Deacon [core/arm64] +Cc: linux-mips@linux-mips.org +Cc: Rich Felker +Cc: linux-ia64@vger.kernel.org +Cc: linux-sh@vger.kernel.org +Cc: peterz@infradead.org +Cc: Benjamin Herrenschmidt +Cc: Max Filippov +Cc: Paul Mackerras +Cc: sparclinux@vger.kernel.org +Cc: Jonas Bonn +Cc: linux-s390@vger.kernel.org +Cc: linux-arch@vger.kernel.org +Cc: Yoshinori Sato +Cc: linux-hexagon@vger.kernel.org +Cc: Helge Deller +Cc: "James E.J. Bottomley" +Cc: Catalin Marinas +Cc: Matt Turner +Cc: linux-snps-arc@lists.infradead.org +Cc: Fenghua Yu +Cc: Arnd Bergmann +Cc: linux-xtensa@linux-xtensa.org +Cc: Stefan Kristiansson +Cc: openrisc@lists.librecores.org +Cc: Ivan Kokshaysky +Cc: Stafford Horne +Cc: linux-arm-kernel@lists.infradead.org +Cc: Richard Henderson +Cc: Chris Zankel +Cc: Michal Simek +Cc: Tony Luck +Cc: linux-parisc@vger.kernel.org +Cc: Vineet Gupta +Cc: Ralf Baechle +Cc: Richard Kuo +Cc: linux-alpha@vger.kernel.org +Cc: Martin Schwidefsky +Cc: linuxppc-dev@lists.ozlabs.org +Cc: "David S. Miller" +Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby@suse.cz +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + arch/alpha/include/asm/futex.h | 26 +++--------------- + arch/arc/include/asm/futex.h | 40 +++------------------------- + arch/arm/include/asm/futex.h | 26 ++---------------- + arch/arm64/include/asm/futex.h | 27 ++----------------- + arch/frv/include/asm/futex.h | 3 +- + arch/frv/kernel/futex.c | 27 ++----------------- + arch/hexagon/include/asm/futex.h | 38 ++------------------------- + arch/ia64/include/asm/futex.h | 25 ++---------------- + arch/microblaze/include/asm/futex.h | 38 ++------------------------- + arch/mips/include/asm/futex.h | 25 ++---------------- + arch/parisc/include/asm/futex.h | 26 ++---------------- + arch/powerpc/include/asm/futex.h | 26 +++--------------- + arch/s390/include/asm/futex.h | 23 +++------------- + arch/sh/include/asm/futex.h | 26 ++---------------- + arch/sparc/include/asm/futex_64.h | 26 +++--------------- + arch/tile/include/asm/futex.h | 40 +++------------------------- + arch/x86/include/asm/futex.h | 40 +++------------------------- + arch/xtensa/include/asm/futex.h | 27 +++---------------- + include/asm-generic/futex.h | 50 ++++++------------------------------ + kernel/futex.c | 39 ++++++++++++++++++++++++++++ + 20 files changed, 126 insertions(+), 472 deletions(-) + +--- a/arch/alpha/include/asm/futex.h ++++ b/arch/alpha/include/asm/futex.h +@@ -29,18 +29,10 @@ + : "r" (uaddr), "r"(oparg) \ + : "memory") + +-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arc/include/asm/futex.h ++++ b/arch/arc/include/asm/futex.h +@@ -73,20 +73,11 @@ + + #endif + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; +- + #ifndef CONFIG_ARC_HAS_LLSC + preempt_disable(); /* to guarantee atomic r-m-w of futex op */ + #endif +@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm/include/asm/futex.h ++++ b/arch/arm/include/asm/futex.h +@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + #endif /* !SMP */ + + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret, tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + #ifndef CONFIG_SMP + preempt_disable(); + #endif +@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op, + preempt_enable(); + #endif + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/arm64/include/asm/futex.h ++++ b/arch/arm64/include/asm/futex.h +@@ -51,20 +51,9 @@ + : "memory") + + static inline int +-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *_uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (int)(encoded_op << 8) >> 20; +- int cmparg = (int)(encoded_op << 20) >> 20; + int oldval = 0, ret, tmp; +- u32 __user *uaddr = __uaccess_mask_ptr(_uaddr); +- +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1U << (oparg & 0x1f); +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -95,17 +84,9 @@ futex_atomic_op_inuser(unsigned int enco + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/frv/include/asm/futex.h ++++ b/arch/frv/include/asm/futex.h +@@ -7,7 +7,8 @@ + #include + #include + +-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr); ++extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr); + + static inline int + futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +--- a/arch/frv/kernel/futex.c ++++ b/arch/frv/kernel/futex.c +@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x + /* + * do the futex operations + */ +-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; break; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + +-} /* end futex_atomic_op_inuser() */ ++} /* end arch_futex_atomic_op_inuser() */ +--- a/arch/hexagon/include/asm/futex.h ++++ b/arch/hexagon/include/asm/futex.h +@@ -31,18 +31,9 @@ + + + static inline int +-futex_atomic_op_inuser(int encoded_op, int __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) +- return -EFAULT; + + pagefault_disable(); + +@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/ia64/include/asm/futex.h ++++ b/arch/ia64/include/asm/futex.h +@@ -45,18 +45,9 @@ do { \ + } while (0) + + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/microblaze/include/asm/futex.h ++++ b/arch/microblaze/include/asm/futex.h +@@ -29,18 +29,9 @@ + }) + + static inline int +-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/mips/include/asm/futex.h ++++ b/arch/mips/include/asm/futex.h +@@ -83,18 +83,9 @@ + } + + static inline int +-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/parisc/include/asm/futex.h ++++ b/arch/parisc/include/asm/futex.h +@@ -32,22 +32,12 @@ _futex_spin_unlock_irqrestore(u32 __user + } + + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) + { + unsigned long int flags; +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval, ret; + u32 tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr))) +- return -EFAULT; +- + _futex_spin_lock_irqsave(uaddr, &flags); + pagefault_disable(); + +@@ -85,17 +75,9 @@ out_pagefault_enable: + pagefault_enable(); + _futex_spin_unlock_irqrestore(uaddr, &flags); + +- if (ret == 0) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/powerpc/include/asm/futex.h ++++ b/arch/powerpc/include/asm/futex.h +@@ -31,18 +31,10 @@ + : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ + : "cr0", "memory") + +-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/s390/include/asm/futex.h ++++ b/arch/s390/include/asm/futex.h +@@ -21,17 +21,12 @@ + : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ + "m" (*uaddr) : "cc"); + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, newval, ret; + + load_kernel_asce(); +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; + + pagefault_disable(); + switch (op) { +@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/sh/include/asm/futex.h ++++ b/arch/sh/include/asm/futex.h +@@ -27,21 +27,12 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval); + } + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- u32 oparg = (encoded_op << 8) >> 20; +- u32 cmparg = (encoded_op << 20) >> 20; + u32 oldval, newval, prev; + int ret; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + do { +@@ -80,17 +71,8 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = ((int)oldval < (int)cmparg); break; +- case FUTEX_OP_CMP_GE: ret = ((int)oldval >= (int)cmparg); break; +- case FUTEX_OP_CMP_LE: ret = ((int)oldval <= (int)cmparg); break; +- case FUTEX_OP_CMP_GT: ret = ((int)oldval > (int)cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; + + return ret; + } +--- a/arch/sparc/include/asm/futex_64.h ++++ b/arch/sparc/include/asm/futex_64.h +@@ -29,22 +29,14 @@ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "memory") + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret, tem; + +- if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))) +- return -EFAULT; + if (unlikely((((unsigned long) uaddr) & 0x3UL))) + return -EINVAL; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + pagefault_disable(); + + switch (op) { +@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/tile/include/asm/futex.h ++++ b/arch/tile/include/asm/futex.h +@@ -106,12 +106,9 @@ + lock = __atomic_hashed_lock((int __force *)uaddr) + #endif + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int uninitialized_var(val), ret; + + __futex_prolog(); +@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser + /* The 32-bit futex code makes this assumption, so validate it here. */ + BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int)); + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + switch (op) { + case FUTEX_OP_SET: +@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser + } + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (val == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (val != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (val < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (val >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (val <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (val > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = val; ++ + return ret; + } + +--- a/arch/x86/include/asm/futex.h ++++ b/arch/x86/include/asm/futex.h +@@ -41,20 +41,11 @@ + "+m" (*uaddr), "=&r" (tem) \ + : "r" (oparg), "i" (-EFAULT), "1" (0)) + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret, tem; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; +- + pagefault_disable(); + + switch (op) { +@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: +- ret = (oldval == cmparg); +- break; +- case FUTEX_OP_CMP_NE: +- ret = (oldval != cmparg); +- break; +- case FUTEX_OP_CMP_LT: +- ret = (oldval < cmparg); +- break; +- case FUTEX_OP_CMP_GE: +- ret = (oldval >= cmparg); +- break; +- case FUTEX_OP_CMP_LE: +- ret = (oldval <= cmparg); +- break; +- case FUTEX_OP_CMP_GT: +- ret = (oldval > cmparg); +- break; +- default: +- ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/arch/xtensa/include/asm/futex.h ++++ b/arch/xtensa/include/asm/futex.h +@@ -44,18 +44,10 @@ + : "r" (uaddr), "I" (-EFAULT), "r" (oparg) \ + : "memory") + +-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, ++ u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + #if !XCHAL_HAVE_S32C1I + return -ENOSYS; +@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser + + pagefault_enable(); + +- if (ret) +- return ret; +- +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: return (oldval == cmparg); +- case FUTEX_OP_CMP_NE: return (oldval != cmparg); +- case FUTEX_OP_CMP_LT: return (oldval < cmparg); +- case FUTEX_OP_CMP_GE: return (oldval >= cmparg); +- case FUTEX_OP_CMP_LE: return (oldval <= cmparg); +- case FUTEX_OP_CMP_GT: return (oldval > cmparg); +- } ++ if (!ret) ++ *oval = oldval; + +- return -ENOSYS; ++ return ret; + } + + static inline int +--- a/include/asm-generic/futex.h ++++ b/include/asm-generic/futex.h +@@ -13,7 +13,7 @@ + */ + + /** +- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant ++ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant + * argument and comparison of the previous + * futex value with another constant. + * +@@ -25,18 +25,11 @@ + * <0 - On error + */ + static inline int +-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval, ret; + u32 tmp; + +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- + preempt_disable(); + pagefault_disable(); + +@@ -74,17 +67,9 @@ out_pagefault_enable: + pagefault_enable(); + preempt_enable(); + +- if (ret == 0) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (ret == 0) ++ *oval = oldval; ++ + return ret; + } + +@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, + + #else + static inline int +-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) ++arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr) + { +- int op = (encoded_op >> 28) & 7; +- int cmp = (encoded_op >> 24) & 15; +- int oparg = (encoded_op << 8) >> 20; +- int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; +- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) +- oparg = 1 << oparg; +- +- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32))) +- return -EFAULT; + + pagefault_disable(); + +@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op, + + pagefault_enable(); + +- if (!ret) { +- switch (cmp) { +- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; +- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; +- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; +- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; +- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; +- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; +- default: ret = -ENOSYS; +- } +- } ++ if (!ret) ++ *oval = oldval; ++ + return ret; + } + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1458,6 +1458,45 @@ out: + return ret; + } + ++static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr) ++{ ++ unsigned int op = (encoded_op & 0x70000000) >> 28; ++ unsigned int cmp = (encoded_op & 0x0f000000) >> 24; ++ int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12); ++ int cmparg = sign_extend32(encoded_op & 0x00000fff, 12); ++ int oldval, ret; ++ ++ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) { ++ if (oparg < 0 || oparg > 31) ++ return -EINVAL; ++ oparg = 1 << oparg; ++ } ++ ++ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) ++ return -EFAULT; ++ ++ ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr); ++ if (ret) ++ return ret; ++ ++ switch (cmp) { ++ case FUTEX_OP_CMP_EQ: ++ return oldval == cmparg; ++ case FUTEX_OP_CMP_NE: ++ return oldval != cmparg; ++ case FUTEX_OP_CMP_LT: ++ return oldval < cmparg; ++ case FUTEX_OP_CMP_GE: ++ return oldval >= cmparg; ++ case FUTEX_OP_CMP_LE: ++ return oldval <= cmparg; ++ case FUTEX_OP_CMP_GT: ++ return oldval > cmparg; ++ default: ++ return -ENOSYS; ++ } ++} ++ + /* + * Wake up all waiters hashed on the physical page that is mapped + * to this virtual address: diff --git a/queue-4.9/mm-vmstat-print-non-populated-zones-in-zoneinfo.patch b/queue-4.9/mm-vmstat-print-non-populated-zones-in-zoneinfo.patch new file mode 100644 index 00000000000..9b1effc20d2 --- /dev/null +++ b/queue-4.9/mm-vmstat-print-non-populated-zones-in-zoneinfo.patch @@ -0,0 +1,143 @@ +From b2bd8598195f1b2a72130592125ac6b4218988a2 Mon Sep 17 00:00:00 2001 +From: David Rientjes +Date: Wed, 3 May 2017 14:52:59 -0700 +Subject: mm, vmstat: print non-populated zones in zoneinfo + +From: David Rientjes + +commit b2bd8598195f1b2a72130592125ac6b4218988a2 upstream. + +Initscripts can use the information (protection levels) from +/proc/zoneinfo to configure vm.lowmem_reserve_ratio at boot. + +vm.lowmem_reserve_ratio is an array of ratios for each configured zone +on the system. If a zone is not populated on an arch, /proc/zoneinfo +suppresses its output. + +This results in there not being a 1:1 mapping between the set of zones +emitted by /proc/zoneinfo and the zones configured by +vm.lowmem_reserve_ratio. + +This patch shows statistics for non-populated zones in /proc/zoneinfo. +The zones exist and hold a spot in the vm.lowmem_reserve_ratio array. +Without this patch, it is not possible to determine which index in the +array controls which zone if one or more zones on the system are not +populated. + +Remaining users of walk_zones_in_node() are unchanged. Files such as +/proc/pagetypeinfo require certain zone data to be initialized properly +for display, which is not done for unpopulated zones. + +Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1703031451310.98023@chino.kir.corp.google.com +Signed-off-by: David Rientjes +Reviewed-by: Anshuman Khandual +Cc: Vlastimil Babka +Cc: Mel Gorman +Cc: Johannes Weiner +Cc: Michal Hocko +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Jisheng Zhang +Signed-off-by: Greg Kroah-Hartman + +--- + mm/vmstat.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -1120,8 +1120,12 @@ static void frag_stop(struct seq_file *m + { + } + +-/* Walk all the zones in a node and print using a callback */ ++/* ++ * Walk zones in a node and print using a callback. ++ * If @assert_populated is true, only use callback for zones that are populated. ++ */ + static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat, ++ bool assert_populated, + void (*print)(struct seq_file *m, pg_data_t *, struct zone *)) + { + struct zone *zone; +@@ -1129,7 +1133,7 @@ static void walk_zones_in_node(struct se + unsigned long flags; + + for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { +- if (!populated_zone(zone)) ++ if (assert_populated && !populated_zone(zone)) + continue; + + spin_lock_irqsave(&zone->lock, flags); +@@ -1157,7 +1161,7 @@ static void frag_show_print(struct seq_f + static int frag_show(struct seq_file *m, void *arg) + { + pg_data_t *pgdat = (pg_data_t *)arg; +- walk_zones_in_node(m, pgdat, frag_show_print); ++ walk_zones_in_node(m, pgdat, true, frag_show_print); + return 0; + } + +@@ -1198,7 +1202,7 @@ static int pagetypeinfo_showfree(struct + seq_printf(m, "%6d ", order); + seq_putc(m, '\n'); + +- walk_zones_in_node(m, pgdat, pagetypeinfo_showfree_print); ++ walk_zones_in_node(m, pgdat, true, pagetypeinfo_showfree_print); + + return 0; + } +@@ -1250,7 +1254,7 @@ static int pagetypeinfo_showblockcount(s + for (mtype = 0; mtype < MIGRATE_TYPES; mtype++) + seq_printf(m, "%12s ", migratetype_names[mtype]); + seq_putc(m, '\n'); +- walk_zones_in_node(m, pgdat, pagetypeinfo_showblockcount_print); ++ walk_zones_in_node(m, pgdat, true, pagetypeinfo_showblockcount_print); + + return 0; + } +@@ -1276,7 +1280,7 @@ static void pagetypeinfo_showmixedcount( + seq_printf(m, "%12s ", migratetype_names[mtype]); + seq_putc(m, '\n'); + +- walk_zones_in_node(m, pgdat, pagetypeinfo_showmixedcount_print); ++ walk_zones_in_node(m, pgdat, true, pagetypeinfo_showmixedcount_print); + #endif /* CONFIG_PAGE_OWNER */ + } + +@@ -1432,12 +1436,15 @@ static void zoneinfo_show_print(struct s + } + + /* +- * Output information about zones in @pgdat. ++ * Output information about zones in @pgdat. All zones are printed regardless ++ * of whether they are populated or not: lowmem_reserve_ratio operates on the ++ * set of all zones and userspace would not be aware of such zones if they are ++ * suppressed here (zoneinfo displays the effect of lowmem_reserve_ratio). + */ + static int zoneinfo_show(struct seq_file *m, void *arg) + { + pg_data_t *pgdat = (pg_data_t *)arg; +- walk_zones_in_node(m, pgdat, zoneinfo_show_print); ++ walk_zones_in_node(m, pgdat, false, zoneinfo_show_print); + return 0; + } + +@@ -1865,7 +1872,7 @@ static int unusable_show(struct seq_file + if (!node_state(pgdat->node_id, N_MEMORY)) + return 0; + +- walk_zones_in_node(m, pgdat, unusable_show_print); ++ walk_zones_in_node(m, pgdat, true, unusable_show_print); + + return 0; + } +@@ -1917,7 +1924,7 @@ static int extfrag_show(struct seq_file + { + pg_data_t *pgdat = (pg_data_t *)arg; + +- walk_zones_in_node(m, pgdat, extfrag_show_print); ++ walk_zones_in_node(m, pgdat, true, extfrag_show_print); + + return 0; + } diff --git a/queue-4.9/serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch b/queue-4.9/serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch new file mode 100644 index 00000000000..08aad9e8906 --- /dev/null +++ b/queue-4.9/serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch @@ -0,0 +1,52 @@ +From c91261437985d481c472639d4397931d77f5d4e9 Mon Sep 17 00:00:00 2001 +From: Alexey Khoroshilov +Date: Sat, 2 Sep 2017 23:13:55 +0300 +Subject: serial: sccnxp: Fix error handling in sccnxp_probe() + +From: Alexey Khoroshilov + +commit c91261437985d481c472639d4397931d77f5d4e9 upstream. + +sccnxp_probe() returns result of regulator_disable() that may lead +to returning zero, while device is not properly initialized. +Also the driver enables clocks, but it does not disable it. + +Found by Linux Driver Verification project (linuxtesting.org). + +Signed-off-by: Alexey Khoroshilov +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/sccnxp.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/tty/serial/sccnxp.c ++++ b/drivers/tty/serial/sccnxp.c +@@ -889,7 +889,16 @@ static int sccnxp_probe(struct platform_ + goto err_out; + uartclk = 0; + } else { +- clk_prepare_enable(clk); ++ ret = clk_prepare_enable(clk); ++ if (ret) ++ goto err_out; ++ ++ ret = devm_add_action_or_reset(&pdev->dev, ++ (void(*)(void *))clk_disable_unprepare, ++ clk); ++ if (ret) ++ goto err_out; ++ + uartclk = clk_get_rate(clk); + } + +@@ -988,7 +997,7 @@ static int sccnxp_probe(struct platform_ + uart_unregister_driver(&s->uart); + err_out: + if (!IS_ERR(s->regulator)) +- return regulator_disable(s->regulator); ++ regulator_disable(s->regulator); + + return ret; + } diff --git a/queue-4.9/series b/queue-4.9/series index cc8e702163b..24c3a93232b 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -23,3 +23,6 @@ bonding-send-learning-packets-for-vlans-on-slave.patch tcp-ignore-fast-open-on-repair-mode.patch sctp-fix-the-issue-that-the-cookie-ack-with-auth-can-t-get-processed.patch sctp-delay-the-authentication-for-the-duplicated-cookie-echo-chunk.patch +mm-vmstat-print-non-populated-zones-in-zoneinfo.patch +serial-sccnxp-fix-error-handling-in-sccnxp_probe.patch +futex-remove-duplicated-code-and-fix-undefined-behaviour.patch -- 2.47.3