diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2020-01-07 20:21:42 +0000 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2020-01-07 20:21:42 +0000 |
commit | 529fc8e93bfd0b4939cf59bd532dab51dd632987 (patch) | |
tree | 91b88b2b22d738eabfd7567d1c5b2828dbb8b856 | |
parent | 1a570d9cee6c53aef600bc0c7a5e204d92d0e82f (diff) | |
download | linux-stable-queue-529fc8e93bfd0b4939cf59bd532dab51dd632987.tar.gz |
Add various patches requested for stable
11 files changed, 826 insertions, 0 deletions
diff --git a/queue-3.16/arm64-debug-don-t-propagate-unknown-far-into-si_code-for-debug.patch b/queue-3.16/arm64-debug-don-t-propagate-unknown-far-into-si_code-for-debug.patch new file mode 100644 index 00000000..1cd4233b --- /dev/null +++ b/queue-3.16/arm64-debug-don-t-propagate-unknown-far-into-si_code-for-debug.patch @@ -0,0 +1,59 @@ +From: Will Deacon <will.deacon@arm.com> +Date: Fri, 1 Mar 2019 13:28:00 +0000 +Subject: arm64: debug: Don't propagate UNKNOWN FAR into si_code for debug + signals + +commit b9a4b9d084d978f80eb9210727c81804588b42ff upstream. + +FAR_EL1 is UNKNOWN for all debug exceptions other than those caused by +taking a hardware watchpoint. Unfortunately, if a debug handler returns +a non-zero value, then we will propagate the UNKNOWN FAR value to +userspace via the si_addr field of the SIGTRAP siginfo_t. + +Instead, let's set si_addr to take on the PC of the faulting instruction, +which we have available in the current pt_regs. + +Reviewed-by: Mark Rutland <mark.rutland@arm.com> +Signed-off-by: Will Deacon <will.deacon@arm.com> +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm64/mm/fault.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -512,11 +512,12 @@ void __init hook_debug_fault_code(int nr + debug_fault_info[nr].name = name; + } + +-asmlinkage int __exception do_debug_exception(unsigned long addr, ++asmlinkage int __exception do_debug_exception(unsigned long addr_if_watchpoint, + unsigned int esr, + struct pt_regs *regs) + { + const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr); ++ unsigned long pc = instruction_pointer(regs); + struct siginfo info; + int rv; + +@@ -527,16 +528,16 @@ asmlinkage int __exception do_debug_exce + if (interrupts_enabled(regs)) + trace_hardirqs_off(); + +- if (!inf->fn(addr, esr, regs)) { ++ if (!inf->fn(addr_if_watchpoint, esr, regs)) { + rv = 1; + } else { + pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n", +- inf->name, esr, addr); ++ inf->name, esr, pc); + + info.si_signo = inf->sig; + info.si_errno = 0; + info.si_code = inf->code; +- info.si_addr = (void __user *)addr; ++ info.si_addr = (void __user *)pc; + arm64_notify_die("", regs, &info, 0); + rv = 0; + } diff --git a/queue-3.16/arm64-debug-ensure-debug-handlers-check-triggering-exception-level.patch b/queue-3.16/arm64-debug-ensure-debug-handlers-check-triggering-exception-level.patch new file mode 100644 index 00000000..8e7e4728 --- /dev/null +++ b/queue-3.16/arm64-debug-ensure-debug-handlers-check-triggering-exception-level.patch @@ -0,0 +1,64 @@ +From: Will Deacon <will.deacon@arm.com> +Date: Fri, 1 Mar 2019 13:28:01 +0000 +Subject: arm64: debug: Ensure debug handlers check triggering exception level + +commit 6bd288569b50bc89fa5513031086746968f585cb upstream. + +Debug exception handlers may be called for exceptions generated both by +user and kernel code. In many cases, this is checked explicitly, but +in other cases things either happen to work by happy accident or they +go slightly wrong. For example, executing 'brk #4' from userspace will +enter the kprobes code and be ignored, but the instruction will be +retried forever in userspace instead of delivering a SIGTRAP. + +Fix this issue in the most stable-friendly fashion by simply adding +explicit checks of the triggering exception level to all of our debug +exception handlers. + +Reviewed-by: Mark Rutland <mark.rutland@arm.com> +Signed-off-by: Will Deacon <will.deacon@arm.com> +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm64/kernel/kgdb.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c +index bcac81e600b9..f72743dc070d 100644 +--- a/arch/arm64/kernel/kgdb.c ++++ b/arch/arm64/kernel/kgdb.c +@@ -215,22 +215,31 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, + + static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr) + { ++ if (user_mode(regs)) ++ return DBG_HOOK_ERROR; ++ + kgdb_handle_exception(1, SIGTRAP, 0, regs); +- return 0; ++ return DBG_HOOK_HANDLED; + } + + static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) + { ++ if (user_mode(regs)) ++ return DBG_HOOK_ERROR; ++ + compiled_break = 1; + kgdb_handle_exception(1, SIGTRAP, 0, regs); + +- return 0; ++ return DBG_HOOK_HANDLED; + } + + static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) + { ++ if (user_mode(regs)) ++ return DBG_HOOK_ERROR; ++ + kgdb_handle_exception(1, SIGTRAP, 0, regs); +- return 0; ++ return DBG_HOOK_HANDLED; + } + + static struct break_hook kgdb_brkpt_hook = { diff --git a/queue-3.16/dmaengine-qcom-bam_dma-fix-resource-leak.patch b/queue-3.16/dmaengine-qcom-bam_dma-fix-resource-leak.patch new file mode 100644 index 00000000..5c235d1c --- /dev/null +++ b/queue-3.16/dmaengine-qcom-bam_dma-fix-resource-leak.patch @@ -0,0 +1,50 @@ +From: Jeffrey Hugo <jeffrey.l.hugo@gmail.com> +Date: Thu, 17 Oct 2019 08:26:06 -0700 +Subject: dmaengine: qcom: bam_dma: Fix resource leak + +commit 7667819385457b4aeb5fac94f67f52ab52cc10d5 upstream. + +bam_dma_terminate_all() will leak resources if any of the transactions are +committed to the hardware (present in the desc fifo), and not complete. +Since bam_dma_terminate_all() does not cause the hardware to be updated, +the hardware will still operate on any previously committed transactions. +This can cause memory corruption if the memory for the transaction has been +reassigned, and will cause a sync issue between the BAM and its client(s). + +Fix this by properly updating the hardware in bam_dma_terminate_all(). + +Fixes: e7c0fe2a5c84 ("dmaengine: add Qualcomm BAM dma driver") +Signed-off-by: Jeffrey Hugo <jeffrey.l.hugo@gmail.com> +Link: https://lore.kernel.org/r/20191017152606.34120-1-jeffrey.l.hugo@gmail.com +Signed-off-by: Vinod Koul <vkoul@kernel.org> +[Jeffrey Hugo: Backported to 4.4 which is lacking 6b4faeac05bc + ("dmaengine: qcom-bam: Process multiple pending descriptors")] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/dma/qcom_bam_dma.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/dma/qcom_bam_dma.c ++++ b/drivers/dma/qcom_bam_dma.c +@@ -539,7 +539,21 @@ static void bam_dma_terminate_all(struct + + /* remove all transactions, including active transaction */ + spin_lock_irqsave(&bchan->vc.lock, flag); ++ /* ++ * If we have transactions queued, then some might be committed to the ++ * hardware in the desc fifo. The only way to reset the desc fifo is ++ * to do a hardware reset (either by pipe or the entire block). ++ * bam_chan_init_hw() will trigger a pipe reset, and also reinit the ++ * pipe. If the pipe is left disabled (default state after pipe reset) ++ * and is accessed by a connected hardware engine, a fatal error in ++ * the BAM will occur. There is a small window where this could happen ++ * with bam_chan_init_hw(), but it is assumed that the caller has ++ * stopped activity on any attached hardware engine. Make sure to do ++ * this first so that the BAM hardware doesn't cause memory corruption ++ * by accessing freed resources. ++ */ + if (bchan->curr_txd) { ++ bam_chan_init_hw(bchan, bchan->curr_txd->dir); + list_add(&bchan->curr_txd->vd.node, &bchan->vc.desc_issued); + bchan->curr_txd = NULL; + } diff --git a/queue-3.16/filldir-remove-warn_on_once-for-bad-directory-entries.patch b/queue-3.16/filldir-remove-warn_on_once-for-bad-directory-entries.patch new file mode 100644 index 00000000..577fa88b --- /dev/null +++ b/queue-3.16/filldir-remove-warn_on_once-for-bad-directory-entries.patch @@ -0,0 +1,37 @@ +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Fri, 18 Oct 2019 18:41:16 -0400 +Subject: filldir[64]: remove WARN_ON_ONCE() for bad directory entries + +commit b9959c7a347d6adbb558fba7e36e9fef3cba3b07 upstream. + +This was always meant to be a temporary thing, just for testing and to +see if it actually ever triggered. + +The only thing that reported it was syzbot doing disk image fuzzing, and +then that warning is expected. So let's just remove it before -rc4, +because the extra sanity testing should probably go to -stable, but we +don't want the warning to do so. + +Reported-by: syzbot+3031f712c7ad5dd4d926@syzkaller.appspotmail.com +Fixes: 8a23eb804ca4 ("Make filldir[64]() verify the directory entry filename is valid") +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Siddharth Chandrasekaran <csiddharth@vmware.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/readdir.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -77,9 +77,9 @@ EXPORT_SYMBOL(iterate_dir); + */ + static int verify_dirent_name(const char *name, int len) + { +- if (WARN_ON_ONCE(!len)) ++ if (!len) + return -EIO; +- if (WARN_ON_ONCE(memchr(name, '/', len))) ++ if (memchr(name, '/', len)) + return -EIO; + return 0; + } diff --git a/queue-3.16/locking-x86-kill-atomic_or_long.patch b/queue-3.16/locking-x86-kill-atomic_or_long.patch new file mode 100644 index 00000000..7fc8ab8e --- /dev/null +++ b/queue-3.16/locking-x86-kill-atomic_or_long.patch @@ -0,0 +1,45 @@ +From: Peter Zijlstra <peterz@infradead.org> +Date: Wed, 23 Apr 2014 17:02:18 +0200 +Subject: locking,x86: Kill atomic_or_long() + +commit f6b4ecee0eb7bfa66ae8d5652105ed4da53209a3 upstream. + +There are no users, kill it. + +Signed-off-by: Peter Zijlstra <peterz@infradead.org> +Cc: Jesse Brandeburg <jesse.brandeburg@intel.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> +Link: http://lkml.kernel.org/r/20140508135851.768177189@infradead.org +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16 because this function is broken after + "x86/atomic: Fix smp_mb__{before,after}_atomic()"] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/include/asm/atomic.h | 15 --------------- + 1 file changed, 15 deletions(-) + +--- a/arch/x86/include/asm/atomic.h ++++ b/arch/x86/include/asm/atomic.h +@@ -218,21 +218,6 @@ static inline short int atomic_inc_short + return *v; + } + +-#ifdef CONFIG_X86_64 +-/** +- * atomic_or_long - OR of two long integers +- * @v1: pointer to type unsigned long +- * @v2: pointer to type unsigned long +- * +- * Atomically ORs @v1 and @v2 +- * Returns the result of the OR +- */ +-static inline void atomic_or_long(unsigned long *v1, unsigned long v2) +-{ +- asm(LOCK_PREFIX "orq %1, %0" : "+m" (*v1) : "r" (v2)); +-} +-#endif +- + /* These are x86-specific, used by some header files */ + #define atomic_clear_mask(mask, addr) \ + asm volatile(LOCK_PREFIX "andl %0,%1" \ diff --git a/queue-3.16/locking-x86-remove-the-unused-atomic_inc_short-methd.patch b/queue-3.16/locking-x86-remove-the-unused-atomic_inc_short-methd.patch new file mode 100644 index 00000000..d0015e85 --- /dev/null +++ b/queue-3.16/locking-x86-remove-the-unused-atomic_inc_short-methd.patch @@ -0,0 +1,63 @@ +From: Dmitry Vyukov <dvyukov@google.com> +Date: Fri, 26 May 2017 19:29:00 +0200 +Subject: locking/x86: Remove the unused atomic_inc_short() methd + +commit 31b35f6b4d5285a311e10753f4eb17304326b211 upstream. + +It is completely unused and implemented only on x86. +Remove it. + +Suggested-by: Mark Rutland <mark.rutland@arm.com> +Signed-off-by: Dmitry Vyukov <dvyukov@google.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: Andrew Morton <akpm@linux-foundation.org> +Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> +Cc: H. Peter Anvin <hpa@zytor.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Link: http://lkml.kernel.org/r/20170526172900.91058-1-dvyukov@google.com +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16 because this function is broken after + "x86/atomic: Fix smp_mb__{before,after}_atomic()": + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/tile/lib/atomic_asm_32.S | 3 +-- + arch/x86/include/asm/atomic.h | 13 ------------- + 2 files changed, 1 insertion(+), 15 deletions(-) + +--- a/arch/tile/lib/atomic_asm_32.S ++++ b/arch/tile/lib/atomic_asm_32.S +@@ -24,8 +24,7 @@ + * has an opportunity to return -EFAULT to the user if needed. + * The 64-bit routines just return a "long long" with the value, + * since they are only used from kernel space and don't expect to fault. +- * Support for 16-bit ops is included in the framework but we don't provide +- * any (x86_64 has an atomic_inc_short(), so we might want to some day). ++ * Support for 16-bit ops is included in the framework but we don't provide any. + * + * Note that the caller is advised to issue a suitable L1 or L2 + * prefetch on the address being manipulated to avoid extra stalls. +--- a/arch/x86/include/asm/atomic.h ++++ b/arch/x86/include/asm/atomic.h +@@ -205,19 +205,6 @@ static inline int __atomic_add_unless(at + return c; + } + +-/** +- * atomic_inc_short - increment of a short integer +- * @v: pointer to type int +- * +- * Atomically adds 1 to @v +- * Returns the new value of @u +- */ +-static inline short int atomic_inc_short(short int *v) +-{ +- asm(LOCK_PREFIX "addw $1, %0" : "+m" (*v)); +- return *v; +-} +- + /* These are x86-specific, used by some header files */ + #define atomic_clear_mask(mask, addr) \ + asm volatile(LOCK_PREFIX "andl %0,%1" \ diff --git a/queue-3.16/make-filldir-verify-the-directory-entry-filename-is-valid.patch b/queue-3.16/make-filldir-verify-the-directory-entry-filename-is-valid.patch new file mode 100644 index 00000000..c1d569e4 --- /dev/null +++ b/queue-3.16/make-filldir-verify-the-directory-entry-filename-is-valid.patch @@ -0,0 +1,138 @@ +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Sat, 5 Oct 2019 11:32:52 -0700 +Subject: Make filldir[64]() verify the directory entry filename is valid + +commit 8a23eb804ca4f2be909e372cf5a9e7b30ae476cd upstream. + +This has been discussed several times, and now filesystem people are +talking about doing it individually at the filesystem layer, so head +that off at the pass and just do it in getdents{64}(). + +This is partially based on a patch by Jann Horn, but checks for NUL +bytes as well, and somewhat simplified. + +There's also commentary about how it might be better if invalid names +due to filesystem corruption don't cause an immediate failure, but only +an error at the end of the readdir(), so that people can still see the +filenames that are ok. + +There's also been discussion about just how much POSIX strictly speaking +requires this since it's about filesystem corruption. It's really more +"protect user space from bad behavior" as pointed out by Jann. But +since Eric Biederman looked up the POSIX wording, here it is for context: + + "From readdir: + + The readdir() function shall return a pointer to a structure + representing the directory entry at the current position in the + directory stream specified by the argument dirp, and position the + directory stream at the next entry. It shall return a null pointer + upon reaching the end of the directory stream. The structure dirent + defined in the <dirent.h> header describes a directory entry. + + From definitions: + + 3.129 Directory Entry (or Link) + + An object that associates a filename with a file. Several directory + entries can associate names with the same file. + + ... + + 3.169 Filename + + A name consisting of 1 to {NAME_MAX} bytes used to name a file. The + characters composing the name may be selected from the set of all + character values excluding the slash character and the null byte. The + filenames dot and dot-dot have special meaning. A filename is + sometimes referred to as a 'pathname component'." + +Note that I didn't bother adding the checks to any legacy interfaces +that nobody uses. + +Also note that if this ends up being noticeable as a performance +regression, we can fix that to do a much more optimized model that +checks for both NUL and '/' at the same time one word at a time. + +We haven't really tended to optimize 'memchr()', and it only checks for +one pattern at a time anyway, and we really _should_ check for NUL too +(but see the comment about "soft errors" in the code about why it +currently only checks for '/') + +See the CONFIG_DCACHE_WORD_ACCESS case of hash_name() for how the name +lookup code looks for pathname terminating characters in parallel. + +Link: https://lore.kernel.org/lkml/20190118161440.220134-2-jannh@google.com/ +Cc: Alexander Viro <viro@zeniv.linux.org.uk> +Cc: Jann Horn <jannh@google.com> +Cc: Eric W. Biederman <ebiederm@xmission.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Siddharth Chandrasekaran <csiddharth@vmware.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/readdir.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -51,6 +51,40 @@ out: + EXPORT_SYMBOL(iterate_dir); + + /* ++ * POSIX says that a dirent name cannot contain NULL or a '/'. ++ * ++ * It's not 100% clear what we should really do in this case. ++ * The filesystem is clearly corrupted, but returning a hard ++ * error means that you now don't see any of the other names ++ * either, so that isn't a perfect alternative. ++ * ++ * And if you return an error, what error do you use? Several ++ * filesystems seem to have decided on EUCLEAN being the error ++ * code for EFSCORRUPTED, and that may be the error to use. Or ++ * just EIO, which is perhaps more obvious to users. ++ * ++ * In order to see the other file names in the directory, the ++ * caller might want to make this a "soft" error: skip the ++ * entry, and return the error at the end instead. ++ * ++ * Note that this should likely do a "memchr(name, 0, len)" ++ * check too, since that would be filesystem corruption as ++ * well. However, that case can't actually confuse user space, ++ * which has to do a strlen() on the name anyway to find the ++ * filename length, and the above "soft error" worry means ++ * that it's probably better left alone until we have that ++ * issue clarified. ++ */ ++static int verify_dirent_name(const char *name, int len) ++{ ++ if (WARN_ON_ONCE(!len)) ++ return -EIO; ++ if (WARN_ON_ONCE(memchr(name, '/', len))) ++ return -EIO; ++ return 0; ++} ++ ++/* + * Traditional linux readdir() handling.. + * + * "count=1" is a special case, meaning that the buffer is one +@@ -157,6 +191,9 @@ static int filldir(void * __buf, const c + int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2, + sizeof(long)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; +@@ -240,6 +277,9 @@ static int filldir64(void * __buf, const + int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, + sizeof(u64)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; diff --git a/queue-3.16/mwifiex-fix-nl80211_tx_power_limited.patch b/queue-3.16/mwifiex-fix-nl80211_tx_power_limited.patch new file mode 100644 index 00000000..d530360d --- /dev/null +++ b/queue-3.16/mwifiex-fix-nl80211_tx_power_limited.patch @@ -0,0 +1,106 @@ +From: Adrian Bunk <bunk@kernel.org> +Date: Wed, 13 Feb 2019 15:59:38 +0200 +Subject: mwifiex: Fix NL80211_TX_POWER_LIMITED + +commit 65a576e27309120e0621f54d5c81eb9128bd56be upstream. + +NL80211_TX_POWER_LIMITED was treated as NL80211_TX_POWER_AUTOMATIC, +which is the opposite of what should happen and can cause nasty +regulatory problems. + +if/else converted to a switch without default to make gcc warn +on unhandled enum values. + +Signed-off-by: Adrian Bunk <bunk@kernel.org> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +[bwh: Backported to 3.16: adjust filenames] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/wireless/mwifiex/cfg80211.c | 13 +++++++++++-- + drivers/net/wireless/mwifiex/ioctl.h | 1 + + drivers/net/wireless/mwifiex/sta_ioctl.c | 11 +++++++---- + 3 files changed, 19 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/mwifiex/cfg80211.c ++++ b/drivers/net/wireless/mwifiex/cfg80211.c +@@ -343,11 +343,20 @@ mwifiex_cfg80211_set_tx_power(struct wip + struct mwifiex_power_cfg power_cfg; + int dbm = MBM_TO_DBM(mbm); + +- if (type == NL80211_TX_POWER_FIXED) { ++ switch (type) { ++ case NL80211_TX_POWER_FIXED: + power_cfg.is_power_auto = 0; ++ power_cfg.is_power_fixed = 1; + power_cfg.power_level = dbm; +- } else { ++ break; ++ case NL80211_TX_POWER_LIMITED: ++ power_cfg.is_power_auto = 0; ++ power_cfg.is_power_fixed = 0; ++ power_cfg.power_level = dbm; ++ break; ++ case NL80211_TX_POWER_AUTOMATIC: + power_cfg.is_power_auto = 1; ++ break; + } + + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); +--- a/drivers/net/wireless/mwifiex/ioctl.h ++++ b/drivers/net/wireless/mwifiex/ioctl.h +@@ -245,6 +245,7 @@ struct mwifiex_ds_encrypt_key { + + struct mwifiex_power_cfg { + u32 is_power_auto; ++ u32 is_power_fixed; + u32 power_level; + }; + +--- a/drivers/net/wireless/mwifiex/sta_ioctl.c ++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c +@@ -659,6 +659,9 @@ int mwifiex_set_tx_power(struct mwifiex_ + txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; + txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET); + if (!power_cfg->is_power_auto) { ++ u16 dbm_min = power_cfg->is_power_fixed ? ++ dbm : priv->min_tx_power_level; ++ + txp_cfg->mode = cpu_to_le32(1); + pg_tlv = (struct mwifiex_types_power_group *) + (buf + sizeof(struct host_cmd_ds_txpwr_cfg)); +@@ -673,7 +676,7 @@ int mwifiex_set_tx_power(struct mwifiex_ + pg->last_rate_code = 0x03; + pg->modulation_class = MOD_CLASS_HR_DSSS; + pg->power_step = 0; +- pg->power_min = (s8) dbm; ++ pg->power_min = (s8) dbm_min; + pg->power_max = (s8) dbm; + pg++; + /* Power group for modulation class OFDM */ +@@ -681,7 +684,7 @@ int mwifiex_set_tx_power(struct mwifiex_ + pg->last_rate_code = 0x07; + pg->modulation_class = MOD_CLASS_OFDM; + pg->power_step = 0; +- pg->power_min = (s8) dbm; ++ pg->power_min = (s8) dbm_min; + pg->power_max = (s8) dbm; + pg++; + /* Power group for modulation class HTBW20 */ +@@ -689,7 +692,7 @@ int mwifiex_set_tx_power(struct mwifiex_ + pg->last_rate_code = 0x20; + pg->modulation_class = MOD_CLASS_HT; + pg->power_step = 0; +- pg->power_min = (s8) dbm; ++ pg->power_min = (s8) dbm_min; + pg->power_max = (s8) dbm; + pg->ht_bandwidth = HT_BW_20; + pg++; +@@ -698,7 +701,7 @@ int mwifiex_set_tx_power(struct mwifiex_ + pg->last_rate_code = 0x20; + pg->modulation_class = MOD_CLASS_HT; + pg->power_step = 0; +- pg->power_min = (s8) dbm; ++ pg->power_min = (s8) dbm_min; + pg->power_max = (s8) dbm; + pg->ht_bandwidth = HT_BW_40; + } diff --git a/queue-3.16/series b/queue-3.16/series index 91ec0f81..a5dfa860 100644 --- a/queue-3.16/series +++ b/queue-3.16/series @@ -43,3 +43,13 @@ mmc-mmc-fix-switch-timeout-issue-caused-by-jiffies-precision.patch cfg80211-size-various-nl80211-messages-correctly.patch arm64-support-keyctl-system-call-in-32-bit-mode.patch stmmac-copy-unicast-mac-address-to-mac-registers.patch +arm64-debug-don-t-propagate-unknown-far-into-si_code-for-debug.patch +arm64-debug-ensure-debug-handlers-check-triggering-exception-level.patch +x86-atomic-fix-smp_mb__-before-after-_atomic.patch +locking-x86-kill-atomic_or_long.patch +locking-x86-remove-the-unused-atomic_inc_short-methd.patch +dmaengine-qcom-bam_dma-fix-resource-leak.patch +mwifiex-fix-nl80211_tx_power_limited.patch +xhci-fix-usb3-device-initiated-resume-race-with-roothub-autosuspend.patch +make-filldir-verify-the-directory-entry-filename-is-valid.patch +filldir-remove-warn_on_once-for-bad-directory-entries.patch diff --git a/queue-3.16/x86-atomic-fix-smp_mb__-before-after-_atomic.patch b/queue-3.16/x86-atomic-fix-smp_mb__-before-after-_atomic.patch new file mode 100644 index 00000000..1f899a11 --- /dev/null +++ b/queue-3.16/x86-atomic-fix-smp_mb__-before-after-_atomic.patch @@ -0,0 +1,141 @@ +From: Peter Zijlstra <peterz@infradead.org> +Date: Wed, 24 Apr 2019 13:38:23 +0200 +Subject: x86/atomic: Fix smp_mb__{before,after}_atomic() + +commit 69d927bba39517d0980462efc051875b7f4db185 upstream. + +Recent probing at the Linux Kernel Memory Model uncovered a +'surprise'. Strongly ordered architectures where the atomic RmW +primitive implies full memory ordering and +smp_mb__{before,after}_atomic() are a simple barrier() (such as x86) +fail for: + + *x = 1; + atomic_inc(u); + smp_mb__after_atomic(); + r0 = *y; + +Because, while the atomic_inc() implies memory order, it +(surprisingly) does not provide a compiler barrier. This then allows +the compiler to re-order like so: + + atomic_inc(u); + *x = 1; + smp_mb__after_atomic(); + r0 = *y; + +Which the CPU is then allowed to re-order (under TSO rules) like: + + atomic_inc(u); + r0 = *y; + *x = 1; + +And this very much was not intended. Therefore strengthen the atomic +RmW ops to include a compiler barrier. + +NOTE: atomic_{or,and,xor} and the bitops already had the compiler +barrier. + +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Ingo Molnar <mingo@kernel.org> +Signed-off-by: Jari Ruusu <jari.ruusu@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/include/asm/atomic.h | 8 ++++---- + arch/x86/include/asm/atomic64_64.h | 8 ++++---- + arch/x86/include/asm/barrier.h | 4 ++-- + 3 files changed, 10 insertions(+), 10 deletions(-) + +--- a/arch/x86/include/asm/atomic.h ++++ b/arch/x86/include/asm/atomic.h +@@ -49,7 +49,7 @@ static inline void atomic_add(int i, ato + { + asm volatile(LOCK_PREFIX "addl %1,%0" + : "+m" (v->counter) +- : "ir" (i)); ++ : "ir" (i) : "memory"); + } + + /** +@@ -63,7 +63,7 @@ static inline void atomic_sub(int i, ato + { + asm volatile(LOCK_PREFIX "subl %1,%0" + : "+m" (v->counter) +- : "ir" (i)); ++ : "ir" (i) : "memory"); + } + + /** +@@ -89,7 +89,7 @@ static inline int atomic_sub_and_test(in + static inline void atomic_inc(atomic_t *v) + { + asm volatile(LOCK_PREFIX "incl %0" +- : "+m" (v->counter)); ++ : "+m" (v->counter) :: "memory"); + } + + /** +@@ -101,7 +101,7 @@ static inline void atomic_inc(atomic_t * + static inline void atomic_dec(atomic_t *v) + { + asm volatile(LOCK_PREFIX "decl %0" +- : "+m" (v->counter)); ++ : "+m" (v->counter) :: "memory"); + } + + /** +--- a/arch/x86/include/asm/atomic64_64.h ++++ b/arch/x86/include/asm/atomic64_64.h +@@ -44,7 +44,7 @@ static inline void atomic64_add(long i, + { + asm volatile(LOCK_PREFIX "addq %1,%0" + : "=m" (v->counter) +- : "er" (i), "m" (v->counter)); ++ : "er" (i), "m" (v->counter) : "memory"); + } + + /** +@@ -58,7 +58,7 @@ static inline void atomic64_sub(long i, + { + asm volatile(LOCK_PREFIX "subq %1,%0" + : "=m" (v->counter) +- : "er" (i), "m" (v->counter)); ++ : "er" (i), "m" (v->counter) : "memory"); + } + + /** +@@ -85,7 +85,7 @@ static inline void atomic64_inc(atomic64 + { + asm volatile(LOCK_PREFIX "incq %0" + : "=m" (v->counter) +- : "m" (v->counter)); ++ : "m" (v->counter) : "memory"); + } + + /** +@@ -98,7 +98,7 @@ static inline void atomic64_dec(atomic64 + { + asm volatile(LOCK_PREFIX "decq %0" + : "=m" (v->counter) +- : "m" (v->counter)); ++ : "m" (v->counter) : "memory"); + } + + /** +--- a/arch/x86/include/asm/barrier.h ++++ b/arch/x86/include/asm/barrier.h +@@ -167,8 +167,8 @@ do { \ + #endif + + /* Atomic operations are already serializing on x86 */ +-#define smp_mb__before_atomic() barrier() +-#define smp_mb__after_atomic() barrier() ++#define smp_mb__before_atomic() do { } while (0) ++#define smp_mb__after_atomic() do { } while (0) + + /* + * Stop RDTSC speculation. This is needed when you need to use RDTSC diff --git a/queue-3.16/xhci-fix-usb3-device-initiated-resume-race-with-roothub-autosuspend.patch b/queue-3.16/xhci-fix-usb3-device-initiated-resume-race-with-roothub-autosuspend.patch new file mode 100644 index 00000000..f4f6b70b --- /dev/null +++ b/queue-3.16/xhci-fix-usb3-device-initiated-resume-race-with-roothub-autosuspend.patch @@ -0,0 +1,113 @@ +From: Mathias Nyman <mathias.nyman@linux.intel.com> +Date: Wed, 11 Dec 2019 16:20:03 +0200 +Subject: xhci: fix USB3 device initiated resume race with roothub autosuspend + +commit 057d476fff778f1d3b9f861fdb5437ea1a3cfc99 upstream. + +A race in xhci USB3 remote wake handling may force device back to suspend +after it initiated resume siganaling, causing a missed resume event or warm +reset of device. + +When a USB3 link completes resume signaling and goes to enabled (UO) +state a interrupt is issued and the interrupt handler will clear the +bus_state->port_remote_wakeup resume flag, allowing bus suspend. + +If the USB3 roothub thread just finished reading port status before +the interrupt, finding ports still in suspended (U3) state, but hasn't +yet started suspending the hub, then the xhci interrupt handler will clear +the flag that prevented roothub suspend and allow bus to suspend, forcing +all port links back to suspended (U3) state. + +Example case: +usb_runtime_suspend() # because all ports still show suspended U3 + usb_suspend_both() + hub_suspend(); # successful as hub->wakeup_bits not set yet +==> INTERRUPT +xhci_irq() + handle_port_status() + clear bus_state->port_remote_wakeup + usb_wakeup_notification() + sets hub->wakeup_bits; + kick_hub_wq() +<== END INTERRUPT + hcd_bus_suspend() + xhci_bus_suspend() # success as port_remote_wakeup bits cleared + +Fix this by increasing roothub usage count during port resume to prevent +roothub autosuspend, and by making sure bus_state->port_remote_wakeup +flag is only cleared after resume completion is visible, i.e. +after xhci roothub returned U0 or other non-U3 link state link on a +get port status request. + +Issue rootcaused by Chiasheng Lee + +Cc: Lee, Hou-hsun <hou-hsun.lee@intel.com> +Reported-by: Lee, Chiasheng <chiasheng.lee@intel.com> +Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Link: https://lore.kernel.org/r/20191211142007.8847-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[Mathias Nyman: Backport for 4.9 and 4.4 stable kernels] +[bwh: Backported to 3.16: USB 3.0 SS is the highest speed we handle] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/host/xhci-hub.c | 8 ++++++++ + drivers/usb/host/xhci-ring.c | 6 +----- + drivers/usb/host/xhci.h | 1 + + 3 files changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -612,6 +612,14 @@ static u32 xhci_get_port_status(struct u + status |= USB_PORT_STAT_C_BH_RESET << 16; + if ((raw_port_status & PORT_CEC)) + status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; ++ ++ /* USB3 remote wake resume signaling completed */ ++ if (bus_state->port_remote_wakeup & (1 << wIndex) && ++ (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME && ++ (raw_port_status & PORT_PLS_MASK) != XDEV_RECOVERY) { ++ bus_state->port_remote_wakeup &= ~(1 << wIndex); ++ usb_hcd_end_port_resume(&hcd->self, wIndex); ++ } + } + + if (hcd->speed != HCD_USB3) { +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1605,9 +1605,6 @@ static void handle_port_status(struct xh + usb_hcd_resume_root_hub(hcd); + } + +- if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE) +- bus_state->port_remote_wakeup &= ~(1 << faked_port_index); +- + if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) { + xhci_dbg(xhci, "port resume event for port %d\n", port_id); + +@@ -1626,6 +1623,7 @@ static void handle_port_status(struct xh + bus_state->port_remote_wakeup |= 1 << faked_port_index; + xhci_test_and_clear_bit(xhci, port_array, + faked_port_index, PORT_PLC); ++ usb_hcd_start_port_resume(&hcd->self, faked_port_index); + xhci_set_link_state(xhci, port_array, faked_port_index, + XDEV_U0); + /* Need to wait until the next link state change +@@ -1663,8 +1661,6 @@ static void handle_port_status(struct xh + if (slot_id && xhci->devs[slot_id]) + xhci_ring_device(xhci, slot_id); + if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { +- bus_state->port_remote_wakeup &= +- ~(1 << faked_port_index); + xhci_test_and_clear_bit(xhci, port_array, + faked_port_index, PORT_PLC); + usb_wakeup_notification(hcd->self.root_hub, +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -288,6 +288,7 @@ struct xhci_op_regs { + #define XDEV_U3 (0x3 << 5) + #define XDEV_INACTIVE (0x6 << 5) + #define XDEV_POLLING (0x7 << 5) ++#define XDEV_RECOVERY (0x8 << 5) + #define XDEV_COMP_MODE (0xa << 5) + #define XDEV_RESUME (0xf << 5) + /* true: port has power (see HCC_PPC) */ |