[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <2026011947-everglade-defensive-bddf@gregkh>
Date: Mon, 19 Jan 2026 13:19:47 +0100
From: Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To: linux-kernel@...r.kernel.org,
akpm@...ux-foundation.org,
torvalds@...ux-foundation.org,
stable@...r.kernel.org
Cc: lwn@....net,
jslaby@...e.cz,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Subject: Re: Linux 5.10.248
diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst
index 8fb03f57546d..a38cc2be8d99 100644
--- a/Documentation/filesystems/mount_api.rst
+++ b/Documentation/filesystems/mount_api.rst
@@ -79,7 +79,6 @@ context. This is represented by the fs_context structure::
unsigned int sb_flags;
unsigned int sb_flags_mask;
unsigned int s_iflags;
- unsigned int lsm_flags;
enum fs_context_purpose purpose:8;
...
};
diff --git a/Documentation/process/2.Process.rst b/Documentation/process/2.Process.rst
index e05fb1b8f8b6..112a8a70b5ee 100644
--- a/Documentation/process/2.Process.rst
+++ b/Documentation/process/2.Process.rst
@@ -104,8 +104,10 @@ kernels go out with a handful of known regressions though, hopefully, none
of them are serious.
Once a stable release is made, its ongoing maintenance is passed off to the
-"stable team," currently Greg Kroah-Hartman. The stable team will release
-occasional updates to the stable release using the 5.x.y numbering scheme.
+"stable team," currently consists of Greg Kroah-Hartman and Sasha Levin. The
+stable team will release occasional updates to the stable release using the
+5.x.y numbering scheme.
+
To be considered for an update release, a patch must (1) fix a significant
bug, and (2) already be merged into the mainline for the next development
kernel. Kernels will typically receive stable updates for a little more
diff --git a/Makefile b/Makefile
index 6739b0e65702..451389daf57b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 10
-SUBLEVEL = 247
+SUBLEVEL = 248
EXTRAVERSION =
NAME = Dare mighty things
diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h
index 971311605288..a09d04b49cc6 100644
--- a/arch/alpha/include/uapi/asm/ioctls.h
+++ b/arch/alpha/include/uapi/asm/ioctls.h
@@ -23,10 +23,10 @@
#define TCSETSW _IOW('t', 21, struct termios)
#define TCSETSF _IOW('t', 22, struct termios)
-#define TCGETA _IOR('t', 23, struct termio)
-#define TCSETA _IOW('t', 24, struct termio)
-#define TCSETAW _IOW('t', 25, struct termio)
-#define TCSETAF _IOW('t', 28, struct termio)
+#define TCGETA 0x40127417
+#define TCSETA 0x80127418
+#define TCSETAW 0x80127419
+#define TCSETAF 0x8012741c
#define TCSBRK _IO('t', 29)
#define TCXONC _IO('t', 30)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 335308aff6ce..05fc9c6ee8c5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1513,7 +1513,7 @@ config HIGHMEM
config HIGHPTE
bool "Allocate 2nd-level pagetables from highmem" if EXPERT
- depends on HIGHMEM
+ depends on HIGHMEM && !PREEMPT_RT
default y
help
The VM uses one page of physical memory for each page table.
diff --git a/arch/arm/boot/dts/imx6q-ba16.dtsi b/arch/arm/boot/dts/imx6q-ba16.dtsi
index 133991ca8c63..6147d1ff4515 100644
--- a/arch/arm/boot/dts/imx6q-ba16.dtsi
+++ b/arch/arm/boot/dts/imx6q-ba16.dtsi
@@ -320,7 +320,7 @@ rtc@32 {
pinctrl-0 = <&pinctrl_rtc>;
reg = <0x32>;
interrupt-parent = <&gpio4>;
- interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
};
};
diff --git a/arch/arm/include/asm/word-at-a-time.h b/arch/arm/include/asm/word-at-a-time.h
index 352ab213520d..2e6d0b4349f4 100644
--- a/arch/arm/include/asm/word-at-a-time.h
+++ b/arch/arm/include/asm/word-at-a-time.h
@@ -66,7 +66,7 @@ static inline unsigned long find_zero(unsigned long mask)
*/
static inline unsigned long load_unaligned_zeropad(const void *addr)
{
- unsigned long ret, offset;
+ unsigned long ret, tmp;
/* Load word from unaligned pointer addr */
asm(
@@ -74,9 +74,9 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
"2:\n"
" .pushsection .text.fixup,\"ax\"\n"
" .align 2\n"
- "3: and %1, %2, #0x3\n"
- " bic %2, %2, #0x3\n"
- " ldr %0, [%2]\n"
+ "3: bic %1, %2, #0x3\n"
+ " ldr %0, [%1]\n"
+ " and %1, %2, #0x3\n"
" lsl %1, %1, #0x3\n"
#ifndef __ARMEB__
" lsr %0, %0, %1\n"
@@ -89,7 +89,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
" .align 3\n"
" .long 1b, 3b\n"
" .popsection"
- : "=&r" (ret), "=&r" (offset)
+ : "=&r" (ret), "=&r" (tmp)
: "r" (addr), "Qo" (*(unsigned long *)addr));
return ret;
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 970d8f318177..e98fe8c006cc 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -342,7 +342,7 @@ static void __maybe_unused build_bhb_mitigation(struct jit_ctx *ctx)
arm64_get_spectre_v2_state() == SPECTRE_VULNERABLE)
return;
- if (capable(CAP_SYS_ADMIN))
+ if (ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN))
return;
if (supports_clearbhb(SCOPE_SYSTEM)) {
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
index de0768a49ee8..ef671680740e 100644
--- a/arch/mips/sgi-ip22/ip22-gio.c
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -372,7 +372,8 @@ static void ip22_check_gio(int slotno, unsigned long addr, int irq)
gio_dev->resource.flags = IORESOURCE_MEM;
gio_dev->irq = irq;
dev_set_name(&gio_dev->dev, "%d", slotno);
- gio_device_register(gio_dev);
+ if (gio_device_register(gio_dev))
+ gio_dev_put(gio_dev);
} else
printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
}
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index cd2cc1b1648c..39fac62a8b12 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -262,6 +262,8 @@ int main(void)
BLANK();
DEFINE(TIF_BLOCKSTEP_PA_BIT, 31-TIF_BLOCKSTEP);
DEFINE(TIF_SINGLESTEP_PA_BIT, 31-TIF_SINGLESTEP);
+ DEFINE(TIF_32BIT_PA_BIT, 31-TIF_32BIT);
+
BLANK();
DEFINE(ASM_PMD_SHIFT, PMD_SHIFT);
DEFINE(ASM_PGDIR_SHIFT, PGDIR_SHIFT);
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index b86ba022136e..d9dc751b91be 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1072,8 +1072,6 @@ ENTRY_CFI(intr_save) /* for os_hpmc */
STREG %r17, PT_IOR(%r29)
#if defined(CONFIG_64BIT)
- b,n intr_save2
-
skip_save_ior:
/* We have a itlb miss, and when executing code above 4 Gb on ILP64, we
* need to adjust iasq/iaoq here in the same way we adjusted isr/ior
@@ -1082,10 +1080,17 @@ skip_save_ior:
bb,COND(>=),n %r8,PSW_W_BIT,intr_save2
LDREG PT_IASQ0(%r29), %r16
LDREG PT_IAOQ0(%r29), %r17
- /* adjust iasq/iaoq */
+ /* adjust iasq0/iaoq0 */
space_adjust %r16,%r17,%r1
STREG %r16, PT_IASQ0(%r29)
STREG %r17, PT_IAOQ0(%r29)
+
+ LDREG PT_IASQ1(%r29), %r16
+ LDREG PT_IAOQ1(%r29), %r17
+ /* adjust iasq1/iaoq1 */
+ space_adjust %r16,%r17,%r1
+ STREG %r16, PT_IASQ1(%r29)
+ STREG %r17, PT_IAOQ1(%r29)
#else
skip_save_ior:
#endif
@@ -1908,6 +1913,10 @@ syscall_restore_rfi:
extru,= %r19,TIF_BLOCKSTEP_PA_BIT,1,%r0
depi -1,7,1,%r20 /* T bit */
+#ifdef CONFIG_64BIT
+ extru,<> %r19,TIF_32BIT_PA_BIT,1,%r0
+ depi -1,4,1,%r20 /* W bit */
+#endif
STREG %r20,TASK_PT_PSW(%r1)
/* Always store space registers, since sr3 can be changed (e.g. fork) */
@@ -1921,7 +1930,6 @@ syscall_restore_rfi:
STREG %r25,TASK_PT_IASQ0(%r1)
STREG %r25,TASK_PT_IASQ1(%r1)
- /* XXX W bit??? */
/* Now if old D bit is clear, it means we didn't save all registers
* on syscall entry, so do that now. This only happens on TRACEME
* calls, or if someone attached to us while we were on a syscall.
diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c
index 53b3b2621457..78704927453a 100644
--- a/arch/powerpc/boot/addnote.c
+++ b/arch/powerpc/boot/addnote.c
@@ -68,8 +68,8 @@ static int e_class = ELFCLASS32;
#define PUT_16BE(off, v)(buf[off] = ((v) >> 8) & 0xff, \
buf[(off) + 1] = (v) & 0xff)
#define PUT_32BE(off, v)(PUT_16BE((off), (v) >> 16L), PUT_16BE((off) + 2, (v)))
-#define PUT_64BE(off, v)((PUT_32BE((off), (v) >> 32L), \
- PUT_32BE((off) + 4, (v))))
+#define PUT_64BE(off, v)((PUT_32BE((off), (unsigned long long)(v) >> 32L), \
+ PUT_32BE((off) + 4, (unsigned long long)(v))))
#define GET_16LE(off) ((buf[off]) + (buf[(off)+1] << 8))
#define GET_32LE(off) (GET_16LE(off) + (GET_16LE((off)+2U) << 16U))
@@ -78,7 +78,8 @@ static int e_class = ELFCLASS32;
#define PUT_16LE(off, v) (buf[off] = (v) & 0xff, \
buf[(off) + 1] = ((v) >> 8) & 0xff)
#define PUT_32LE(off, v) (PUT_16LE((off), (v)), PUT_16LE((off) + 2, (v) >> 16L))
-#define PUT_64LE(off, v) (PUT_32LE((off), (v)), PUT_32LE((off) + 4, (v) >> 32L))
+#define PUT_64LE(off, v) (PUT_32LE((off), (unsigned long long)(v)), \
+ PUT_32LE((off) + 4, (unsigned long long)(v) >> 32L))
#define GET_16(off) (e_data == ELFDATA2MSB ? GET_16BE(off) : GET_16LE(off))
#define GET_32(off) (e_data == ELFDATA2MSB ? GET_32BE(off) : GET_32LE(off))
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index cf375d67eacb..e4c25944d22a 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1767,8 +1767,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
return 0;
}
-void preload_new_slb_context(unsigned long start, unsigned long sp);
-
/*
* Set up a thread for executing a new program
*/
@@ -1776,9 +1774,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
{
#ifdef CONFIG_PPC64
unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */
-
- if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !radix_enabled())
- preload_new_slb_context(start, sp);
#endif
/*
diff --git a/arch/powerpc/mm/book3s64/internal.h b/arch/powerpc/mm/book3s64/internal.h
index c12d78ee42f5..b3f64e149ece 100644
--- a/arch/powerpc/mm/book3s64/internal.h
+++ b/arch/powerpc/mm/book3s64/internal.h
@@ -13,6 +13,5 @@ static inline bool stress_slb(void)
return static_branch_unlikely(&stress_slb_key);
}
-void slb_setup_new_exec(void);
#endif /* ARCH_POWERPC_MM_BOOK3S64_INTERNAL_H */
diff --git a/arch/powerpc/mm/book3s64/mmu_context.c b/arch/powerpc/mm/book3s64/mmu_context.c
index 0c8557220ae2..86ad6f8b2be2 100644
--- a/arch/powerpc/mm/book3s64/mmu_context.c
+++ b/arch/powerpc/mm/book3s64/mmu_context.c
@@ -147,8 +147,6 @@ static int hash__init_new_context(struct mm_struct *mm)
void hash__setup_new_exec(void)
{
slice_setup_new_exec();
-
- slb_setup_new_exec();
}
static int radix__init_new_context(struct mm_struct *mm)
diff --git a/arch/powerpc/mm/book3s64/slb.c b/arch/powerpc/mm/book3s64/slb.c
index ccf0a876a7bd..72f3461ff7ee 100644
--- a/arch/powerpc/mm/book3s64/slb.c
+++ b/arch/powerpc/mm/book3s64/slb.c
@@ -352,94 +352,6 @@ static void preload_age(struct thread_info *ti)
ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR;
}
-void slb_setup_new_exec(void)
-{
- struct thread_info *ti = current_thread_info();
- struct mm_struct *mm = current->mm;
- unsigned long exec = 0x10000000;
-
- WARN_ON(irqs_disabled());
-
- /*
- * preload cache can only be used to determine whether a SLB
- * entry exists if it does not start to overflow.
- */
- if (ti->slb_preload_nr + 2 > SLB_PRELOAD_NR)
- return;
-
- hard_irq_disable();
-
- /*
- * We have no good place to clear the slb preload cache on exec,
- * flush_thread is about the earliest arch hook but that happens
- * after we switch to the mm and have aleady preloaded the SLBEs.
- *
- * For the most part that's probably okay to use entries from the
- * previous exec, they will age out if unused. It may turn out to
- * be an advantage to clear the cache before switching to it,
- * however.
- */
-
- /*
- * preload some userspace segments into the SLB.
- * Almost all 32 and 64bit PowerPC executables are linked at
- * 0x10000000 so it makes sense to preload this segment.
- */
- if (!is_kernel_addr(exec)) {
- if (preload_add(ti, exec))
- slb_allocate_user(mm, exec);
- }
-
- /* Libraries and mmaps. */
- if (!is_kernel_addr(mm->mmap_base)) {
- if (preload_add(ti, mm->mmap_base))
- slb_allocate_user(mm, mm->mmap_base);
- }
-
- /* see switch_slb */
- asm volatile("isync" : : : "memory");
-
- local_irq_enable();
-}
-
-void preload_new_slb_context(unsigned long start, unsigned long sp)
-{
- struct thread_info *ti = current_thread_info();
- struct mm_struct *mm = current->mm;
- unsigned long heap = mm->start_brk;
-
- WARN_ON(irqs_disabled());
-
- /* see above */
- if (ti->slb_preload_nr + 3 > SLB_PRELOAD_NR)
- return;
-
- hard_irq_disable();
-
- /* Userspace entry address. */
- if (!is_kernel_addr(start)) {
- if (preload_add(ti, start))
- slb_allocate_user(mm, start);
- }
-
- /* Top of stack, grows down. */
- if (!is_kernel_addr(sp)) {
- if (preload_add(ti, sp))
- slb_allocate_user(mm, sp);
- }
-
- /* Bottom of heap, grows up. */
- if (heap && !is_kernel_addr(heap)) {
- if (preload_add(ti, heap))
- slb_allocate_user(mm, heap);
- }
-
- /* see switch_slb */
- asm volatile("isync" : : : "memory");
-
- local_irq_enable();
-}
-
static void slb_cache_slbie_kernel(unsigned int index)
{
unsigned long slbie_data = get_paca()->slb_cache[index];
diff --git a/arch/powerpc/mm/ptdump/hashpagetable.c b/arch/powerpc/mm/ptdump/hashpagetable.c
index ad6df9a2e7c8..6fed0fc236ff 100644
--- a/arch/powerpc/mm/ptdump/hashpagetable.c
+++ b/arch/powerpc/mm/ptdump/hashpagetable.c
@@ -216,6 +216,8 @@ static int native_find(unsigned long ea, int psize, bool primary, u64 *v, u64
vpn = hpt_vpn(ea, vsid, ssize);
hash = hpt_hash(vpn, shift, ssize);
want_v = hpte_encode_avpn(vpn, psize, ssize);
+ if (cpu_has_feature(CPU_FTR_ARCH_300))
+ want_v = hpte_old_to_new_v(want_v);
/* to check in the secondary hash table, we invert the hash */
if (!primary)
@@ -229,6 +231,10 @@ static int native_find(unsigned long ea, int psize, bool primary, u64 *v, u64
/* HPTE matches */
*v = be64_to_cpu(hptep->v);
*r = be64_to_cpu(hptep->r);
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ *v = hpte_new_to_old_v(*v, *r);
+ *r = hpte_new_to_old_r(*r);
+ }
return 0;
}
++hpte_group;
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c
index 45a3a3022a85..e0886ea54646 100644
--- a/arch/powerpc/platforms/pseries/cmm.c
+++ b/arch/powerpc/platforms/pseries/cmm.c
@@ -550,7 +550,7 @@ static int cmm_migratepage(struct balloon_dev_info *b_dev_info,
spin_lock_irqsave(&b_dev_info->pages_lock, flags);
balloon_page_insert(b_dev_info, newpage);
- balloon_page_delete(page);
+ __count_vm_event(BALLOON_MIGRATE);
b_dev_info->isolated_pages--;
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
@@ -560,6 +560,7 @@ static int cmm_migratepage(struct balloon_dev_info *b_dev_info,
*/
plpar_page_set_active(page);
+ balloon_page_finalize(page);
/* balloon page list reference */
put_page(page);
@@ -570,7 +571,6 @@ static int cmm_balloon_compaction_init(void)
{
int rc;
- balloon_devinfo_init(&b_dev_info);
b_dev_info.migratepage = cmm_migratepage;
balloon_mnt = kern_mount(&balloon_fs);
@@ -624,6 +624,7 @@ static int cmm_init(void)
if (!firmware_has_feature(FW_FEATURE_CMO) && !simulate)
return -EOPNOTSUPP;
+ balloon_devinfo_init(&b_dev_info);
rc = cmm_balloon_compaction_init();
if (rc)
return rc;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 2e0c3b0a5a58..253774d155a1 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -732,6 +732,7 @@ static void __ref smp_get_core_info(struct sclp_core_info *info, int early)
continue;
info->core[info->configured].core_id =
address >> smp_cpu_mt_shift;
+ info->core[info->configured].type = boot_core_type;
info->configured++;
}
info->combined = info->configured;
diff --git a/arch/x86/crypto/blake2s-core.S b/arch/x86/crypto/blake2s-core.S
index b50b35ff1fdb..ca2644820dfc 100644
--- a/arch/x86/crypto/blake2s-core.S
+++ b/arch/x86/crypto/blake2s-core.S
@@ -54,7 +54,7 @@ SYM_FUNC_START(blake2s_compress_ssse3)
movdqa ROT16(%rip),%xmm12
movdqa ROR328(%rip),%xmm13
movdqu 0x20(%rdi),%xmm14
- movq %rcx,%xmm15
+ movd %ecx,%xmm15
leaq SIGMA+0xa0(%rip),%r8
jmp .Lbeginofloop
.align 32
@@ -179,7 +179,7 @@ SYM_FUNC_START(blake2s_compress_avx512)
vmovdqu (%rdi),%xmm0
vmovdqu 0x10(%rdi),%xmm1
vmovdqu 0x20(%rdi),%xmm4
- vmovq %rcx,%xmm5
+ vmovd %ecx,%xmm5
vmovdqa IV(%rip),%xmm14
vmovdqa IV+16(%rip),%xmm15
jmp .Lblake2s_compress_avx512_mainloop
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index fb2e81fa62c4..73d1cebddee7 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3515,7 +3515,9 @@ static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event)
if (!event->attr.exclude_kernel)
flags &= ~PERF_SAMPLE_REGS_USER;
if (event->attr.sample_regs_user & ~PEBS_GP_REGS)
- flags &= ~(PERF_SAMPLE_REGS_USER | PERF_SAMPLE_REGS_INTR);
+ flags &= ~PERF_SAMPLE_REGS_USER;
+ if (event->attr.sample_regs_intr & ~PEBS_GP_REGS)
+ flags &= ~PERF_SAMPLE_REGS_INTR;
return flags;
}
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index b94f615600d5..d5186653311d 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -109,12 +109,12 @@ convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs);
extern void send_sigtrap(struct pt_regs *regs, int error_code, int si_code);
-static inline unsigned long regs_return_value(struct pt_regs *regs)
+static __always_inline unsigned long regs_return_value(struct pt_regs *regs)
{
return regs->ax;
}
-static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
+static __always_inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
{
regs->ax = rc;
}
@@ -195,34 +195,34 @@ static inline bool ip_within_syscall_gap(struct pt_regs *regs)
}
#endif
-static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+static __always_inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
{
return regs->sp;
}
-static inline unsigned long instruction_pointer(struct pt_regs *regs)
+static __always_inline unsigned long instruction_pointer(struct pt_regs *regs)
{
return regs->ip;
}
-static inline void instruction_pointer_set(struct pt_regs *regs,
- unsigned long val)
+static __always_inline
+void instruction_pointer_set(struct pt_regs *regs, unsigned long val)
{
regs->ip = val;
}
-static inline unsigned long frame_pointer(struct pt_regs *regs)
+static __always_inline unsigned long frame_pointer(struct pt_regs *regs)
{
return regs->bp;
}
-static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+static __always_inline unsigned long user_stack_pointer(struct pt_regs *regs)
{
return regs->sp;
}
-static inline void user_stack_pointer_set(struct pt_regs *regs,
- unsigned long val)
+static __always_inline
+void user_stack_pointer_set(struct pt_regs *regs, unsigned long val)
{
regs->sp = val;
}
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index 49600643faba..f248eb2ac2d4 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -88,9 +88,6 @@ get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
return (unsigned long *)task->thread.sp;
}
-void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
- unsigned long *stack, const char *log_lvl);
-
/* The form of the top of the frame on the stack */
struct stack_frame {
struct stack_frame *next_frame;
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index cf92191de2b2..dc0cd8c1ac13 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -183,8 +183,14 @@ static void show_regs_if_on_stack(struct stack_info *info, struct pt_regs *regs,
}
}
-void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
- unsigned long *stack, const char *log_lvl)
+/*
+ * This function reads pointers from the stack and dereferences them. The
+ * pointers may not have their KMSAN shadow set up properly, which may result
+ * in false positive reports. Disable instrumentation to avoid those.
+ */
+__no_kmsan_checks
+static void __show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack, const char *log_lvl)
{
struct unwind_state state;
struct stack_info stack_info = {0};
@@ -305,6 +311,25 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
}
}
+static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+ unsigned long *stack, const char *log_lvl)
+{
+ /*
+ * Disable KASAN to avoid false positives during walking another
+ * task's stacks, as values on these stacks may change concurrently
+ * with task execution.
+ */
+ bool disable_kasan = task && task != current;
+
+ if (disable_kasan)
+ kasan_disable_current();
+
+ __show_trace_log_lvl(task, regs, stack, log_lvl);
+
+ if (disable_kasan)
+ kasan_enable_current();
+}
+
void show_stack(struct task_struct *task, unsigned long *sp,
const char *loglvl)
{
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index d7c44b257f7f..8943114f9ebe 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -183,6 +183,16 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp)
}
#endif
+/*
+ * While walking the stack, KMSAN may stomp on stale locals from other
+ * functions that were marked as uninitialized upon function exit, and
+ * now hold the call frame information for the current function (e.g. the frame
+ * pointer). Because KMSAN does not specifically mark call frames as
+ * initialized, false positive reports are possible. To prevent such reports,
+ * we mark the functions scanning the stack (here and below) with
+ * __no_kmsan_checks.
+ */
+__no_kmsan_checks
static bool update_stack_state(struct unwind_state *state,
unsigned long *next_bp)
{
@@ -251,6 +261,7 @@ static bool update_stack_state(struct unwind_state *state,
return true;
}
+__no_kmsan_checks
bool unwind_next_frame(struct unwind_state *state)
{
struct pt_regs *regs;
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index fdbca15ecb44..79679dd7ec86 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1790,15 +1790,33 @@ static void advance_periodic_target_expiration(struct kvm_lapic *apic)
ktime_t delta;
/*
- * Synchronize both deadlines to the same time source or
- * differences in the periods (caused by differences in the
- * underlying clocks or numerical approximation errors) will
- * cause the two to drift apart over time as the errors
- * accumulate.
+ * Use kernel time as the time source for both the hrtimer deadline and
+ * TSC-based deadline so that they stay synchronized. Computing each
+ * deadline independently will cause the two deadlines to drift apart
+ * over time as differences in the periods accumulate, e.g. due to
+ * differences in the underlying clocks or numerical approximation errors.
*/
apic->lapic_timer.target_expiration =
ktime_add_ns(apic->lapic_timer.target_expiration,
apic->lapic_timer.period);
+
+ /*
+ * If the new expiration is in the past, e.g. because userspace stopped
+ * running the VM for an extended duration, then force the expiration
+ * to "now" and don't try to play catch-up with the missed events. KVM
+ * will only deliver a single interrupt regardless of how many events
+ * are pending, i.e. restarting the timer with an expiration in the
+ * past will do nothing more than waste host cycles, and can even lead
+ * to a hard lockup in extreme cases.
+ */
+ if (ktime_before(apic->lapic_timer.target_expiration, now))
+ apic->lapic_timer.target_expiration = now;
+
+ /*
+ * Note, ensuring the expiration isn't in the past also prevents delta
+ * from going negative, which could cause the TSC deadline to become
+ * excessively large due to it an unsigned value.
+ */
delta = ktime_sub(apic->lapic_timer.target_expiration, now);
apic->lapic_timer.tscdeadline = kvm_read_l1_tsc(apic->vcpu, tscl) +
nsec_to_cycles(apic->vcpu, delta);
@@ -2434,9 +2452,9 @@ static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
apic_timer_expired(apic, true);
- if (lapic_is_periodic(apic)) {
+ if (lapic_is_periodic(apic) && !WARN_ON_ONCE(!apic->lapic_timer.period)) {
advance_periodic_target_expiration(apic);
- hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
+ hrtimer_set_expires(&ktimer->timer, ktimer->target_expiration);
return HRTIMER_RESTART;
} else
return HRTIMER_NORESTART;
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index 3e59df2ebc97..bc523302970e 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -528,7 +528,7 @@ int nested_svm_vmrun(struct vcpu_svm *svm)
if (!nested_vmcb_check_save(svm, vmcb12) ||
!nested_vmcb_check_controls(&svm->nested.ctl)) {
vmcb12->control.exit_code = SVM_EXIT_ERR;
- vmcb12->control.exit_code_hi = 0;
+ vmcb12->control.exit_code_hi = -1u;
vmcb12->control.exit_info_1 = 0;
vmcb12->control.exit_info_2 = 0;
goto out;
@@ -587,7 +587,7 @@ int nested_svm_vmrun(struct vcpu_svm *svm)
svm->nested.nested_run_pending = 0;
svm->vmcb->control.exit_code = SVM_EXIT_ERR;
- svm->vmcb->control.exit_code_hi = 0;
+ svm->vmcb->control.exit_code_hi = -1u;
svm->vmcb->control.exit_info_1 = 0;
svm->vmcb->control.exit_info_2 = 0;
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 8caf3c7a0601..0ca511389227 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3900,20 +3900,20 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,
INTERCEPT_SELECTIVE_CR0)))
break;
- cr0 = vcpu->arch.cr0 & ~SVM_CR0_SELECTIVE_MASK;
- val = info->src_val & ~SVM_CR0_SELECTIVE_MASK;
-
+ /* LMSW always triggers INTERCEPT_SELECTIVE_CR0 */
if (info->intercept == x86_intercept_lmsw) {
- cr0 &= 0xfUL;
- val &= 0xfUL;
- /* lmsw can't clear PE - catch this here */
- if (cr0 & X86_CR0_PE)
- val |= X86_CR0_PE;
+ icpt_info.exit_code = SVM_EXIT_CR0_SEL_WRITE;
+ break;
}
+ /*
+ * MOV-to-CR0 only triggers INTERCEPT_SELECTIVE_CR0 if any bit
+ * other than SVM_CR0_SELECTIVE_MASK is changed.
+ */
+ cr0 = vcpu->arch.cr0 & ~SVM_CR0_SELECTIVE_MASK;
+ val = info->src_val & ~SVM_CR0_SELECTIVE_MASK;
if (cr0 ^ val)
icpt_info.exit_code = SVM_EXIT_CR0_SEL_WRITE;
-
break;
}
case SVM_EXIT_READ_DR0:
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 21531aa163cb..a72009746067 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -23,6 +23,7 @@
#include <linux/sched/sysctl.h>
#include <linux/sched/topology.h>
#include <linux/sched/signal.h>
+#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/crash_dump.h>
#include <linux/prefetch.h>
@@ -2548,6 +2549,7 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node)
{
struct blk_mq_hw_ctx *hctx = hlist_entry_safe(node,
struct blk_mq_hw_ctx, cpuhp_online);
+ int ret = 0;
if (!cpumask_test_cpu(cpu, hctx->cpumask) ||
!blk_mq_last_cpu_in_hctx(cpu, hctx))
@@ -2569,12 +2571,24 @@ static int blk_mq_hctx_notify_offline(unsigned int cpu, struct hlist_node *node)
* frozen and there are no requests.
*/
if (percpu_ref_tryget(&hctx->queue->q_usage_counter)) {
- while (blk_mq_hctx_has_requests(hctx))
+ while (blk_mq_hctx_has_requests(hctx)) {
+ /*
+ * The wakeup capable IRQ handler of block device is
+ * not called during suspend. Skip the loop by checking
+ * pm_wakeup_pending to prevent the deadlock and improve
+ * suspend latency.
+ */
+ if (pm_wakeup_pending()) {
+ clear_bit(BLK_MQ_S_INACTIVE, &hctx->state);
+ ret = -EBUSY;
+ break;
+ }
msleep(5);
+ }
percpu_ref_put(&hctx->queue->q_usage_counter);
}
- return 0;
+ return ret;
}
static int blk_mq_hctx_notify_online(unsigned int cpu, struct hlist_node *node)
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 4bf514a7bd82..4d3436cd677d 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -2216,8 +2216,10 @@ bool blk_throtl_bio(struct bio *bio)
rcu_read_lock();
/* see throtl_charge_bio() */
- if (bio_flagged(bio, BIO_THROTTLED))
- goto out;
+ if (bio_flagged(bio, BIO_THROTTLED)) {
+ rcu_read_unlock();
+ return false;
+ }
if (!cgroup_subsys_on_dfl(io_cgrp_subsys)) {
blkg_rwstat_add(&tg->stat_bytes, bio->bi_opf,
@@ -2225,8 +2227,10 @@ bool blk_throtl_bio(struct bio *bio)
blkg_rwstat_add(&tg->stat_ios, bio->bi_opf, 1);
}
- if (!tg->has_rules[rw])
- goto out;
+ if (!tg->has_rules[rw]) {
+ rcu_read_unlock();
+ return false;
+ }
spin_lock_irq(&q->queue_lock);
@@ -2310,14 +2314,14 @@ bool blk_throtl_bio(struct bio *bio)
}
out_unlock:
- spin_unlock_irq(&q->queue_lock);
-out:
bio_set_flag(bio, BIO_THROTTLED);
#ifdef CONFIG_BLK_DEV_THROTTLING_LOW
if (throttled || !td->track_bio_latency)
bio->bi_issue.value |= BIO_ISSUE_THROTL_SKIP_LATENCY;
#endif
+ spin_unlock_irq(&q->queue_lock);
+
rcu_read_unlock();
return throttled;
}
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 25cf2fa3dde7..3d622904f4c3 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -1127,14 +1127,13 @@ struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
if (unlikely(!areq))
return ERR_PTR(-ENOMEM);
+ memset(areq, 0, areqlen);
+
ctx->inflight = true;
areq->areqlen = areqlen;
areq->sk = sk;
- areq->last_rsgl = NULL;
INIT_LIST_HEAD(&areq->rsgl_list);
- areq->tsgl = NULL;
- areq->tsgl_entries = 0;
return areq;
}
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index be21cfdc6dbc..a48fc7c24341 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -423,9 +423,8 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk)
if (!ctx)
return -ENOMEM;
- ctx->result = NULL;
+ memset(ctx, 0, len);
ctx->len = len;
- ctx->more = false;
crypto_init_wait(&ctx->wait);
ask->private = ctx;
diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
index 407408c43730..38a8f20a02e2 100644
--- a/crypto/algif_rng.c
+++ b/crypto/algif_rng.c
@@ -250,9 +250,8 @@ static int rng_accept_parent(void *private, struct sock *sk)
if (!ctx)
return -ENOMEM;
+ memset(ctx, 0, len);
ctx->len = len;
- ctx->addtl = NULL;
- ctx->addtl_len = 0;
/*
* No seeding done at that point -- if multiple accepts are
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 33e77d846caa..ef0e56642a07 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -11,6 +11,7 @@
#include <crypto/public_key.h>
#include <linux/seq_file.h>
#include <linux/module.h>
+#include <linux/overflow.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <keys/system_keyring.h>
@@ -138,12 +139,17 @@ struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
size_t len_2)
{
struct asymmetric_key_id *kid;
-
- kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2,
- GFP_KERNEL);
+ size_t kid_sz;
+ size_t len;
+
+ if (check_add_overflow(len_1, len_2, &len))
+ return ERR_PTR(-EOVERFLOW);
+ if (check_add_overflow(sizeof(struct asymmetric_key_id), len, &kid_sz))
+ return ERR_PTR(-EOVERFLOW);
+ kid = kmalloc(kid_sz, GFP_KERNEL);
if (!kid)
return ERR_PTR(-ENOMEM);
- kid->len = len_1 + len_2;
+ kid->len = len;
memcpy(kid->data, val_1, len_1);
memcpy(kid->data + len_1, val_2, len_2);
return kid;
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
index b1bcfe537daf..562ab102226a 100644
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -51,6 +51,7 @@ static int seqiv_aead_encrypt(struct aead_request *req)
struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
struct aead_request *subreq = aead_request_ctx(req);
crypto_completion_t compl;
+ bool unaligned_info;
void *data;
u8 *info;
unsigned int ivsize = 8;
@@ -80,8 +81,9 @@ static int seqiv_aead_encrypt(struct aead_request *req)
return err;
}
- if (unlikely(!IS_ALIGNED((unsigned long)info,
- crypto_aead_alignmask(geniv) + 1))) {
+ unaligned_info = !IS_ALIGNED((unsigned long)info,
+ crypto_aead_alignmask(geniv) + 1);
+ if (unlikely(unaligned_info)) {
info = kmemdup(req->iv, ivsize, req->base.flags &
CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
GFP_ATOMIC);
@@ -101,7 +103,7 @@ static int seqiv_aead_encrypt(struct aead_request *req)
scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
err = crypto_aead_encrypt(subreq);
- if (unlikely(info != req->iv))
+ if (unlikely(unaligned_info))
seqiv_aead_encrypt_complete2(req, err);
return err;
}
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
index 901fa5ca284d..91c4dc9026bf 100644
--- a/drivers/acpi/acpica/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -169,9 +169,12 @@ acpi_ns_walk_namespace(acpi_object_type type,
if (start_node == ACPI_ROOT_OBJECT) {
start_node = acpi_gbl_root_node;
- if (!start_node) {
- return_ACPI_STATUS(AE_NO_NAMESPACE);
- }
+ }
+
+ /* Avoid walking the namespace if the StartNode is NULL */
+
+ if (!start_node) {
+ return_ACPI_STATUS(AE_NO_NAMESPACE);
}
/* Null child means "get first node" */
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 250ea9ec5f0c..bdb23ca251e2 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -22,6 +22,7 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/bitfield.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
@@ -500,6 +501,7 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
{
struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
int flags = sync ? MF_ACTION_REQUIRED : 0;
+ char error_type[120];
bool queued = false;
int sec_sev, i;
char *p;
@@ -513,9 +515,8 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
p = (char *)(err + 1);
for (i = 0; i < err->err_info_num; i++) {
struct cper_arm_err_info *err_info = (struct cper_arm_err_info *)p;
- bool is_cache = (err_info->type == CPER_ARM_CACHE_ERROR);
+ bool is_cache = err_info->type & CPER_ARM_CACHE_ERROR;
bool has_pa = (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR);
- const char *error_type = "unknown error";
/*
* The field (err_info->error_info & BIT(26)) is fixed to set to
@@ -529,12 +530,15 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
continue;
}
- if (err_info->type < ARRAY_SIZE(cper_proc_error_type_strs))
- error_type = cper_proc_error_type_strs[err_info->type];
+ cper_bits_to_str(error_type, sizeof(error_type),
+ FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type),
+ cper_proc_error_type_strs,
+ ARRAY_SIZE(cper_proc_error_type_strs));
pr_warn_ratelimited(FW_WARN GHES_PFX
- "Unhandled processor error type: %s\n",
- error_type);
+ "Unhandled processor error type 0x%02x: %s%s\n",
+ err_info->type, error_type,
+ (err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : "");
p += err_info->length;
}
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index b62348a7e4d9..b4cc61cd5d32 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -1097,7 +1097,8 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
/* Are any of the regs PCC ?*/
if (CPC_IN_PCC(highest_reg) || CPC_IN_PCC(lowest_reg) ||
CPC_IN_PCC(lowest_non_linear_reg) || CPC_IN_PCC(nominal_reg) ||
- CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg)) {
+ CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg) ||
+ CPC_IN_PCC(guaranteed_reg)) {
if (pcc_ss_id < 0) {
pr_debug("Invalid pcc_ss_id\n");
return -ENODEV;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 2ac48cda5b20..eae7efae3b5c 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -54,7 +54,7 @@ static int map_x2apic_id(struct acpi_subtable_header *entry,
if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
return -ENODEV;
- if (device_declaration && (apic->uid == acpi_id)) {
+ if (apic->uid == acpi_id && (device_declaration || acpi_id < 255)) {
*apic_id = apic->local_apic_id;
return 0;
}
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 821150dcb976..3a3efd15b849 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1188,7 +1188,7 @@ static struct fwnode_handle *acpi_graph_get_next_endpoint(
if (!prev) {
do {
- port = fwnode_get_next_child_node(fwnode, port);
+ port = acpi_get_next_subnode(fwnode, port);
/*
* The names of the port nodes begin with "port@"
* followed by the number of the port node and they also
@@ -1206,13 +1206,13 @@ static struct fwnode_handle *acpi_graph_get_next_endpoint(
if (!port)
return NULL;
- endpoint = fwnode_get_next_child_node(port, prev);
+ endpoint = acpi_get_next_subnode(port, prev);
while (!endpoint) {
- port = fwnode_get_next_child_node(fwnode, port);
+ port = acpi_get_next_subnode(fwnode, port);
if (!port)
break;
if (is_acpi_graph_node(port, "port"))
- endpoint = fwnode_get_next_child_node(port, NULL);
+ endpoint = acpi_get_next_subnode(port, NULL);
}
/*
@@ -1423,6 +1423,7 @@ static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
+ fwnode_handle_put(port_fwnode);
return 0;
}
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
index 0b2c20fddb7c..39eb1f41b92b 100644
--- a/drivers/amba/tegra-ahb.c
+++ b/drivers/amba/tegra-ahb.c
@@ -144,6 +144,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn)
if (!dev)
return -EPROBE_DEFER;
ahb = dev_get_drvdata(dev);
+ put_device(dev);
val = gizmo_readl(ahb, AHB_ARBITRATION_XBAR_CTRL);
val |= AHB_ARBITRATION_XBAR_CTRL_SMMU_INIT_DONE;
gizmo_writel(ahb, val, AHB_ARBITRATION_XBAR_CTRL);
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 17f44abc9418..ee0c379415b4 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -1590,7 +1590,8 @@ he_stop(struct he_dev *he_dev)
he_dev->tbrq_base, he_dev->tbrq_phys);
if (he_dev->tpdrq_base)
- dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+ dma_free_coherent(&he_dev->pci_dev->dev,
+ CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
he_dev->tpdrq_base, he_dev->tpdrq_phys);
dma_pool_destroy(he_dev->tpd_pool);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 31b77cf9cc8e..d15d033be2c9 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1749,16 +1749,18 @@ void pm_runtime_init(struct device *dev)
*/
void pm_runtime_reinit(struct device *dev)
{
- if (!pm_runtime_enabled(dev)) {
- if (dev->power.runtime_status == RPM_ACTIVE)
- pm_runtime_set_suspended(dev);
- if (dev->power.irq_safe) {
- spin_lock_irq(&dev->power.lock);
- dev->power.irq_safe = 0;
- spin_unlock_irq(&dev->power.lock);
- if (dev->parent)
- pm_runtime_put(dev->parent);
- }
+ if (pm_runtime_enabled(dev))
+ return;
+
+ if (dev->power.runtime_status == RPM_ACTIVE)
+ pm_runtime_set_suspended(dev);
+
+ if (dev->power.irq_safe) {
+ spin_lock_irq(&dev->power.lock);
+ dev->power.irq_safe = 0;
+ spin_unlock_irq(&dev->power.lock);
+ if (dev->parent)
+ pm_runtime_put(dev->parent);
}
/*
* Clear power.needs_force_resume in case it has been set by
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 4ef407a33996..6b78dbe45ef9 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -332,7 +332,7 @@ static bool initialized;
* This default is used whenever the current disk size is unknown.
* [Now it is rather a minimum]
*/
-#define MAX_DISK_SIZE 4 /* 3984 */
+#define MAX_DISK_SIZE (PAGE_SIZE / 1024)
/*
* globals used by 'result()'
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 477600958719..649a1e881265 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -468,7 +468,8 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
}
/*
- * Send or receive packet.
+ * Send or receive packet. Return a positive value on success and
+ * negtive value on failue, and never return 0.
*/
static int sock_xmit(struct nbd_device *nbd, int index, int send,
struct iov_iter *iter, int msg_flags, int *sent)
@@ -594,7 +595,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
result = sock_xmit(nbd, index, 1, &from,
(type == NBD_CMD_WRITE) ? MSG_MORE : 0, &sent);
trace_nbd_header_sent(req, handle);
- if (result <= 0) {
+ if (result < 0) {
if (was_interrupted(result)) {
/* If we havne't sent anything we can just return BUSY,
* however if we have sent something we need to make
@@ -638,7 +639,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
skip = 0;
}
result = sock_xmit(nbd, index, 1, &from, flags, &sent);
- if (result <= 0) {
+ if (result < 0) {
if (was_interrupted(result)) {
/* We've already sent the header, we
* have no choice but to set pending and
@@ -672,38 +673,45 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
return 0;
}
-/* NULL returned = something went wrong, inform userspace */
-static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
+static int nbd_read_reply(struct nbd_device *nbd, int index,
+ struct nbd_reply *reply)
{
- struct nbd_config *config = nbd->config;
- int result;
- struct nbd_reply reply;
- struct nbd_cmd *cmd;
- struct request *req = NULL;
- u64 handle;
- u16 hwq;
- u32 tag;
- struct kvec iov = {.iov_base = &reply, .iov_len = sizeof(reply)};
+ struct kvec iov = {.iov_base = reply, .iov_len = sizeof(*reply)};
struct iov_iter to;
- int ret = 0;
+ int result;
- reply.magic = 0;
- iov_iter_kvec(&to, READ, &iov, 1, sizeof(reply));
+ reply->magic = 0;
+ iov_iter_kvec(&to, READ, &iov, 1, sizeof(*reply));
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
- if (result <= 0) {
- if (!nbd_disconnected(config))
+ if (result < 0) {
+ if (!nbd_disconnected(nbd->config))
dev_err(disk_to_dev(nbd->disk),
"Receive control failed (result %d)\n", result);
- return ERR_PTR(result);
+ return result;
}
- if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
+ if (ntohl(reply->magic) != NBD_REPLY_MAGIC) {
dev_err(disk_to_dev(nbd->disk), "Wrong magic (0x%lx)\n",
- (unsigned long)ntohl(reply.magic));
- return ERR_PTR(-EPROTO);
+ (unsigned long)ntohl(reply->magic));
+ return -EPROTO;
}
- memcpy(&handle, reply.handle, sizeof(handle));
+ return 0;
+}
+
+/* NULL returned = something went wrong, inform userspace */
+static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index,
+ struct nbd_reply *reply)
+{
+ int result;
+ struct nbd_cmd *cmd;
+ struct request *req = NULL;
+ u64 handle;
+ u16 hwq;
+ u32 tag;
+ int ret = 0;
+
+ memcpy(&handle, reply->handle, sizeof(handle));
tag = nbd_handle_to_tag(handle);
hwq = blk_mq_unique_tag_to_hwq(tag);
if (hwq < nbd->tag_set.nr_hw_queues)
@@ -736,9 +744,9 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
ret = -ENOENT;
goto out;
}
- if (ntohl(reply.error)) {
+ if (ntohl(reply->error)) {
dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
- ntohl(reply.error));
+ ntohl(reply->error));
cmd->status = BLK_STS_IOERR;
goto out;
}
@@ -747,11 +755,12 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
if (rq_data_dir(req) != WRITE) {
struct req_iterator iter;
struct bio_vec bvec;
+ struct iov_iter to;
rq_for_each_segment(bvec, req, iter) {
iov_iter_bvec(&to, READ, &bvec, 1, bvec.bv_len);
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
- if (result <= 0) {
+ if (result < 0) {
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
result);
/*
@@ -760,7 +769,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
* and let the timeout stuff handle resubmitting
* this request onto another connection.
*/
- if (nbd_disconnected(config)) {
+ if (nbd_disconnected(nbd->config)) {
cmd->status = BLK_STS_IOERR;
goto out;
}
@@ -784,27 +793,33 @@ static void recv_work(struct work_struct *work)
work);
struct nbd_device *nbd = args->nbd;
struct nbd_config *config = nbd->config;
+ struct nbd_sock *nsock;
struct nbd_cmd *cmd;
struct request *rq;
while (1) {
- cmd = nbd_read_stat(nbd, args->index);
- if (IS_ERR(cmd)) {
- struct nbd_sock *nsock = config->socks[args->index];
+ struct nbd_reply reply;
- mutex_lock(&nsock->tx_lock);
- nbd_mark_nsock_dead(nbd, nsock, 1);
- mutex_unlock(&nsock->tx_lock);
+ if (nbd_read_reply(nbd, args->index, &reply))
+ break;
+
+ cmd = nbd_handle_reply(nbd, args->index, &reply);
+ if (IS_ERR(cmd))
break;
- }
rq = blk_mq_rq_from_pdu(cmd);
if (likely(!blk_should_fake_timeout(rq->q)))
blk_mq_complete_request(rq);
}
- nbd_config_put(nbd);
+
+ nsock = config->socks[args->index];
+ mutex_lock(&nsock->tx_lock);
+ nbd_mark_nsock_dead(nbd, nsock, 1);
+ mutex_unlock(&nsock->tx_lock);
+
atomic_dec(&config->recv_threads);
wake_up(&config->recv_wq);
+ nbd_config_put(nbd);
kfree(args);
}
@@ -1194,7 +1209,7 @@ static void send_disconnects(struct nbd_device *nbd)
iov_iter_kvec(&from, WRITE, &iov, 1, sizeof(request));
mutex_lock(&nsock->tx_lock);
ret = sock_xmit(nbd, i, 1, &from, 0, NULL);
- if (ret <= 0)
+ if (ret < 0)
dev_err(disk_to_dev(nbd->disk),
"Send disconnect failed %d\n", ret);
mutex_unlock(&nsock->tx_lock);
@@ -2037,12 +2052,13 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
}
ret = nbd_start_device(nbd);
out:
- mutex_unlock(&nbd->config_lock);
if (!ret) {
set_bit(NBD_RT_HAS_CONFIG_REF, &config->runtime_flags);
refcount_inc(&nbd->config_refs);
nbd_connect_reply(info, nbd->index);
}
+ mutex_unlock(&nbd->config_lock);
+
nbd_config_put(nbd);
if (put_dev)
nbd_put(nbd);
diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
index 71b86fee81c2..2aebb07eff92 100644
--- a/drivers/block/rnbd/rnbd-clt.c
+++ b/drivers/block/rnbd/rnbd-clt.c
@@ -23,7 +23,6 @@ MODULE_LICENSE("GPL");
static int rnbd_client_major;
static DEFINE_IDA(index_ida);
-static DEFINE_MUTEX(ida_lock);
static DEFINE_MUTEX(sess_lock);
static LIST_HEAD(sess_list);
@@ -55,9 +54,7 @@ static void rnbd_clt_put_dev(struct rnbd_clt_dev *dev)
if (!refcount_dec_and_test(&dev->refcount))
return;
- mutex_lock(&ida_lock);
- ida_simple_remove(&index_ida, dev->clt_device_id);
- mutex_unlock(&ida_lock);
+ ida_free(&index_ida, dev->clt_device_id);
kfree(dev->hw_queues);
kfree(dev->pathname);
rnbd_clt_put_sess(dev->sess);
@@ -1381,11 +1378,11 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
goto out_alloc;
}
- mutex_lock(&ida_lock);
- ret = ida_simple_get(&index_ida, 0, 1 << (MINORBITS - RNBD_PART_BITS),
- GFP_KERNEL);
- mutex_unlock(&ida_lock);
- if (ret < 0) {
+ dev->clt_device_id = ida_alloc_max(&index_ida,
+ (1 << (MINORBITS - RNBD_PART_BITS)) - 1,
+ GFP_KERNEL);
+ if (dev->clt_device_id < 0) {
+ ret = dev->clt_device_id;
pr_err("Failed to initialize device '%s' from session %s, allocating idr failed, err: %d\n",
pathname, sess->sessname, ret);
goto out_queues;
@@ -1394,10 +1391,9 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
dev->pathname = kstrdup(pathname, GFP_KERNEL);
if (!dev->pathname) {
ret = -ENOMEM;
- goto out_queues;
+ goto out_ida;
}
- dev->clt_device_id = ret;
dev->sess = sess;
dev->access_mode = access_mode;
mutex_init(&dev->lock);
@@ -1412,6 +1408,8 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
return dev;
+out_ida:
+ ida_free(&index_ida, dev->clt_device_id);
out_queues:
kfree(dev->hw_queues);
out_alloc:
diff --git a/drivers/block/rnbd/rnbd-clt.h b/drivers/block/rnbd/rnbd-clt.h
index 2941e3862b9c..beda2d6ce910 100644
--- a/drivers/block/rnbd/rnbd-clt.h
+++ b/drivers/block/rnbd/rnbd-clt.h
@@ -105,7 +105,7 @@ struct rnbd_clt_dev {
struct rnbd_queue *hw_queues;
u32 device_id;
/* local Idr index - used to track minor number allocations. */
- u32 clt_device_id;
+ int clt_device_id;
struct mutex lock;
enum rnbd_clt_dev_state dev_state;
char *pathname;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 155eaaf0485a..c5e4f675270c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -396,6 +396,8 @@ static const struct usb_device_id blacklist_table[] = {
/* Realtek 8821CE Bluetooth devices */
{ USB_DEVICE(0x13d3, 0x3529), .driver_info = BTUSB_REALTEK |
BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x13d3, 0x3533), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
/* Realtek 8822CE Bluetooth devices */
{ USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK |
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index dd7791f48537..4f13e7d8101b 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -1085,14 +1085,14 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
static int fsl_mc_bus_remove(struct platform_device *pdev)
{
struct fsl_mc *mc = platform_get_drvdata(pdev);
+ struct fsl_mc_io *mc_io;
if (!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev))
return -EINVAL;
+ mc_io = mc->root_mc_bus_dev->mc_io;
fsl_mc_device_remove(mc->root_mc_bus_dev);
-
- fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);
- mc->root_mc_bus_dev->mc_io = NULL;
+ fsl_destroy_mc_io(mc_io);
return 0;
}
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index ed38c25fb0c5..fe5b0997aee6 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -37,6 +37,7 @@ enum sysc_soc {
SOC_UNKNOWN,
SOC_2420,
SOC_2430,
+ SOC_AM33,
SOC_3430,
SOC_AM35,
SOC_3630,
@@ -2933,6 +2934,7 @@ static void ti_sysc_idle(struct work_struct *work)
static const struct soc_device_attribute sysc_soc_match[] = {
SOC_FLAG("OMAP242*", SOC_2420),
SOC_FLAG("OMAP243*", SOC_2430),
+ SOC_FLAG("AM33*", SOC_AM33),
SOC_FLAG("AM35*", SOC_AM35),
SOC_FLAG("OMAP3[45]*", SOC_3430),
SOC_FLAG("OMAP3[67]*", SOC_3630),
@@ -3121,10 +3123,15 @@ static int sysc_check_active_timer(struct sysc *ddata)
* can be dropped if we stop supporting old beagleboard revisions
* A to B4 at some point.
*/
- if (sysc_soc->soc == SOC_3430 || sysc_soc->soc == SOC_AM35)
+ switch (sysc_soc->soc) {
+ case SOC_AM33:
+ case SOC_3430:
+ case SOC_AM35:
error = -ENXIO;
- else
+ break;
+ default:
error = -EBUSY;
+ }
if ((ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) &&
(ddata->cfg.quirks & SYSC_QUIRK_NO_IDLE))
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 14b2d8034c51..a45bce78f341 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -836,7 +836,10 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ret = -ENOTTY;
break;
}
- Dummy = readb(apbs[IndexCard].RamIO + VERS);
+
+ if (cmd != 6)
+ Dummy = readb(apbs[IndexCard].RamIO + VERS);
+
kfree(adgl);
mutex_unlock(&ac_mutex);
return 0;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 5b01985aed22..a72cd57dd8a5 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -605,7 +605,8 @@ static void __ipmi_bmc_unregister(struct ipmi_smi *intf);
static int __ipmi_bmc_register(struct ipmi_smi *intf,
struct ipmi_device_id *id,
bool guid_set, guid_t *guid, int intf_num);
-static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id);
+static int __scan_channels(struct ipmi_smi *intf,
+ struct ipmi_device_id *id, bool rescan);
/**
@@ -2556,7 +2557,7 @@ static int __bmc_get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc,
if (__ipmi_bmc_register(intf, &id, guid_set, &guid, intf_num))
need_waiter(intf); /* Retry later on an error. */
else
- __scan_channels(intf, &id);
+ __scan_channels(intf, &id, false);
if (!intf_set) {
@@ -2576,7 +2577,7 @@ static int __bmc_get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc,
goto out_noprocessing;
} else if (memcmp(&bmc->fetch_id, &bmc->id, sizeof(bmc->id)))
/* Version info changes, scan the channels again. */
- __scan_channels(intf, &bmc->fetch_id);
+ __scan_channels(intf, &bmc->fetch_id, true);
bmc->dyn_id_expiry = jiffies + IPMI_DYN_DEV_ID_EXPIRY;
@@ -3305,8 +3306,6 @@ channel_handler(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
intf->channels_ready = true;
wake_up(&intf->waitq);
} else {
- intf->channel_list = intf->wchannels + set;
- intf->channels_ready = true;
rv = send_channel_info_cmd(intf, intf->curr_channel);
}
@@ -3328,10 +3327,17 @@ channel_handler(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
/*
* Must be holding intf->bmc_reg_mutex to call this.
*/
-static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id)
+static int __scan_channels(struct ipmi_smi *intf,
+ struct ipmi_device_id *id,
+ bool rescan)
{
int rv;
+ if (rescan) {
+ /* Clear channels_ready to force channels rescan. */
+ intf->channels_ready = false;
+ }
+
if (ipmi_version_major(id) > 1
|| (ipmi_version_major(id) == 1
&& ipmi_version_minor(id) >= 5)) {
@@ -3503,7 +3509,7 @@ int ipmi_add_smi(struct module *owner,
}
mutex_lock(&intf->bmc_reg_mutex);
- rv = __scan_channels(intf, &id);
+ rv = __scan_channels(intf, &id, false);
mutex_unlock(&intf->bmc_reg_mutex);
if (rv)
goto out_err_bmc_reg;
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 1e4f1a5049a5..528ed316150e 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -269,7 +269,6 @@ static void tpm_dev_release(struct device *dev)
kfree(chip->work_space.context_buf);
kfree(chip->work_space.session_buf);
- kfree(chip->allocated_banks);
kfree(chip);
}
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index ca7158fa6e6c..28e562843fa5 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -794,11 +794,6 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
*/
int tpm1_get_pcr_allocation(struct tpm_chip *chip)
{
- chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
- GFP_KERNEL);
- if (!chip->allocated_banks)
- return -ENOMEM;
-
chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index d0e11d7a3c08..0b683d991bed 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -574,11 +574,9 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
nr_possible_banks = be32_to_cpup(
(__be32 *)&buf.data[TPM_HEADER_SIZE + 5]);
-
- chip->allocated_banks = kcalloc(nr_possible_banks,
- sizeof(*chip->allocated_banks),
- GFP_KERNEL);
- if (!chip->allocated_banks) {
+ if (nr_possible_banks > TPM2_MAX_PCR_BANKS) {
+ pr_err("tpm: out of bank capacity: %u > %u\n",
+ nr_possible_banks, TPM2_MAX_PCR_BANKS);
rc = -ENOMEM;
goto out;
}
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 5c8f009bb6f7..712db89020f3 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1617,8 +1617,8 @@ static void handle_control_message(struct virtio_device *vdev,
break;
case VIRTIO_CONSOLE_RESIZE: {
struct {
- __virtio16 rows;
__virtio16 cols;
+ __virtio16 rows;
} size;
if (!is_console_port(port))
diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c
index 84c8900542e4..b477396917ad 100644
--- a/drivers/clk/mvebu/cp110-system-controller.c
+++ b/drivers/clk/mvebu/cp110-system-controller.c
@@ -110,6 +110,25 @@ static const char * const gate_base_names[] = {
[CP110_GATE_EIP197] = "eip197"
};
+static unsigned long gate_flags(const u8 bit_idx)
+{
+ switch (bit_idx) {
+ case CP110_GATE_PCIE_X1_0:
+ case CP110_GATE_PCIE_X1_1:
+ case CP110_GATE_PCIE_X4:
+ /*
+ * If a port had an active link at boot time, stopping
+ * the clock creates a failed state from which controller
+ * driver can not recover.
+ * Prevent stopping this clock till after a driver has taken
+ * ownership.
+ */
+ return CLK_IGNORE_UNUSED;
+ default:
+ return 0;
+ }
+};
+
struct cp110_gate_clk {
struct clk_hw hw;
struct regmap *regmap;
@@ -171,6 +190,7 @@ static struct clk_hw *cp110_register_gate(const char *name,
init.ops = &cp110_gate_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
+ init.flags = gate_flags(bit_idx);
gate->regmap = regmap;
gate->bit_idx = bit_idx;
diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
index 285f6ac25372..22212a157acf 100644
--- a/drivers/clk/renesas/r9a06g032-clocks.c
+++ b/drivers/clk/renesas/r9a06g032-clocks.c
@@ -917,9 +917,10 @@ static int __init r9a06g032_clocks_probe(struct platform_device *pdev)
if (IS_ERR(mclk))
return PTR_ERR(mclk);
- clocks->reg = of_iomap(np, 0);
- if (WARN_ON(!clocks->reg))
- return -ENOMEM;
+ clocks->reg = devm_of_iomap(dev, np, 0, NULL);
+ if (IS_ERR(clocks->reg))
+ return PTR_ERR(clocks->reg);
+
for (i = 0; i < ARRAY_SIZE(r9a06g032_clocks); ++i) {
const struct r9a06g032_clkdesc *d = &r9a06g032_clocks[i];
const char *parent_name = d->source ?
diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c
index f7a7bcf6f52e..c58fb697fbba 100644
--- a/drivers/cpufreq/cpufreq-nforce2.c
+++ b/drivers/cpufreq/cpufreq-nforce2.c
@@ -145,6 +145,8 @@ static unsigned int nforce2_fsb_read(int bootfsb)
pci_read_config_dword(nforce2_sub5, NFORCE2_BOOTFSB, &fsb);
fsb /= 1000000;
+ pci_dev_put(nforce2_sub5);
+
/* Check if PLL register is already set */
pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
@@ -432,6 +434,7 @@ static int __init nforce2_init(void)
static void __exit nforce2_exit(void)
{
cpufreq_unregister_driver(&nforce2_driver);
+ pci_dev_put(nforce2_dev);
}
module_init(nforce2_init);
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index bed496cf8d24..f95b4658097a 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -518,7 +518,7 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy)
if (policy->cpu != 0) {
ret = -EINVAL;
- goto out_dmc1;
+ goto out;
}
/*
@@ -530,7 +530,7 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy)
if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
pr_err("CPUFreq doesn't support this memory type\n");
ret = -EINVAL;
- goto out_dmc1;
+ goto out;
}
/* Find current refresh counter and frequency each DMC */
@@ -544,6 +544,8 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy)
cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
return 0;
+out:
+ clk_put(dmc1_clk);
out_dmc1:
clk_put(dmc0_clk);
out_dmc0:
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index bb1389f276d7..6b65d537c95c 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -29,12 +29,18 @@ static const struct scmi_handle *handle;
static unsigned int scmi_cpufreq_get_rate(unsigned int cpu)
{
- struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
+ struct cpufreq_policy *policy;
+ struct scmi_data *priv;
const struct scmi_perf_ops *perf_ops = handle->perf_ops;
- struct scmi_data *priv = policy->driver_data;
unsigned long rate;
int ret;
+ policy = cpufreq_cpu_get_raw(cpu);
+ if (unlikely(!policy))
+ return 0;
+
+ priv = policy->driver_data;
+
ret = perf_ops->freq_get(handle, priv->domain_id, &rate, false);
if (ret)
return 0;
diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c
index 6140e4927322..5754dc88c684 100644
--- a/drivers/crypto/ccree/cc_buffer_mgr.c
+++ b/drivers/crypto/ccree/cc_buffer_mgr.c
@@ -1235,6 +1235,7 @@ int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
int rc = 0;
u32 dummy = 0;
u32 mapped_nents = 0;
+ int sg_nents;
dev_dbg(dev, " update params : curr_buff=%pK curr_buff_cnt=0x%X nbytes=0x%X src=%pK curr_index=%u\n",
curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index);
@@ -1248,7 +1249,10 @@ int cc_map_hash_request_update(struct cc_drvdata *drvdata, void *ctx,
if (total_in_len < block_size) {
dev_dbg(dev, " less than one block: curr_buff=%pK *curr_buff_cnt=0x%X copy_to=%pK\n",
curr_buff, *curr_buff_cnt, &curr_buff[*curr_buff_cnt]);
- areq_ctx->in_nents = sg_nents_for_len(src, nbytes);
+ sg_nents = sg_nents_for_len(src, nbytes);
+ if (sg_nents < 0)
+ return sg_nents;
+ areq_ctx->in_nents = sg_nents;
sg_copy_to_buffer(src, areq_ctx->in_nents,
&curr_buff[*curr_buff_cnt], nbytes);
*curr_buff_cnt += nbytes;
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 42d9f25efc5c..e59053738a43 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -36,6 +36,8 @@
static char driver_name[] = KBUILD_MODNAME;
+#define RCV_BUFFER_SIZE (16 * 1024)
+
/* this is the physical layout of a PCL, its size is 128 bytes */
struct pcl {
__le32 next;
@@ -513,20 +515,18 @@ remove_card(struct pci_dev *dev)
wake_up_interruptible(&client->buffer.wait);
spin_unlock_irq(&lynx->client_list_lock);
- pci_free_consistent(lynx->pci_device, sizeof(struct pcl),
- lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
- pci_free_consistent(lynx->pci_device, sizeof(struct pcl),
- lynx->rcv_pcl, lynx->rcv_pcl_bus);
- pci_free_consistent(lynx->pci_device, PAGE_SIZE,
- lynx->rcv_buffer, lynx->rcv_buffer_bus);
+ dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
+ lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
+ dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
+ lynx->rcv_pcl, lynx->rcv_pcl_bus);
+ dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
+ lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);
pci_disable_device(dev);
lynx_put(lynx);
}
-#define RCV_BUFFER_SIZE (16 * 1024)
-
static int
add_card(struct pci_dev *dev, const struct pci_device_id *unused)
{
@@ -534,7 +534,7 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
u32 p, end;
int ret, i;
- if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
+ if (dma_set_mask(&dev->dev, DMA_BIT_MASK(32))) {
dev_err(&dev->dev,
"DMA address limits not supported for PCILynx hardware\n");
return -ENXIO;
@@ -566,12 +566,16 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
goto fail_deallocate_lynx;
}
- lynx->rcv_start_pcl = pci_alloc_consistent(lynx->pci_device,
- sizeof(struct pcl), &lynx->rcv_start_pcl_bus);
- lynx->rcv_pcl = pci_alloc_consistent(lynx->pci_device,
- sizeof(struct pcl), &lynx->rcv_pcl_bus);
- lynx->rcv_buffer = pci_alloc_consistent(lynx->pci_device,
- RCV_BUFFER_SIZE, &lynx->rcv_buffer_bus);
+ lynx->rcv_start_pcl = dma_alloc_coherent(&lynx->pci_device->dev,
+ sizeof(struct pcl),
+ &lynx->rcv_start_pcl_bus,
+ GFP_KERNEL);
+ lynx->rcv_pcl = dma_alloc_coherent(&lynx->pci_device->dev,
+ sizeof(struct pcl),
+ &lynx->rcv_pcl_bus, GFP_KERNEL);
+ lynx->rcv_buffer = dma_alloc_coherent(&lynx->pci_device->dev,
+ RCV_BUFFER_SIZE,
+ &lynx->rcv_buffer_bus, GFP_KERNEL);
if (lynx->rcv_start_pcl == NULL ||
lynx->rcv_pcl == NULL ||
lynx->rcv_buffer == NULL) {
@@ -669,14 +673,15 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
fail_deallocate_buffers:
if (lynx->rcv_start_pcl)
- pci_free_consistent(lynx->pci_device, sizeof(struct pcl),
- lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
+ dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
+ lynx->rcv_start_pcl,
+ lynx->rcv_start_pcl_bus);
if (lynx->rcv_pcl)
- pci_free_consistent(lynx->pci_device, sizeof(struct pcl),
- lynx->rcv_pcl, lynx->rcv_pcl_bus);
+ dma_free_coherent(&lynx->pci_device->dev, sizeof(struct pcl),
+ lynx->rcv_pcl, lynx->rcv_pcl_bus);
if (lynx->rcv_buffer)
- pci_free_consistent(lynx->pci_device, PAGE_SIZE,
- lynx->rcv_buffer, lynx->rcv_buffer_bus);
+ dma_free_coherent(&lynx->pci_device->dev, RCV_BUFFER_SIZE,
+ lynx->rcv_buffer, lynx->rcv_buffer_bus);
iounmap(lynx->registers);
fail_deallocate_lynx:
diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-arm.c
index 36d3b8b9da47..ea43589944ba 100644
--- a/drivers/firmware/efi/cper-arm.c
+++ b/drivers/firmware/efi/cper-arm.c
@@ -94,15 +94,11 @@ static void cper_print_arm_err_info(const char *pfx, u32 type,
bool proc_context_corrupt, corrected, precise_pc, restartable_pc;
bool time_out, access_mode;
- /* If the type is unknown, bail. */
- if (type > CPER_ARM_MAX_TYPE)
- return;
-
/*
* Vendor type errors have error information values that are vendor
* specific.
*/
- if (type == CPER_ARM_VENDOR_ERROR)
+ if (type & CPER_ARM_VENDOR_ERROR)
return;
if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) {
@@ -117,43 +113,38 @@ static void cper_print_arm_err_info(const char *pfx, u32 type,
if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
& CPER_ARM_ERR_OPERATION_MASK);
- switch (type) {
- case CPER_ARM_CACHE_ERROR:
+ if (type & CPER_ARM_CACHE_ERROR) {
if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
- printk("%soperation type: %s\n", pfx,
+ printk("%scache error, operation type: %s\n", pfx,
arm_cache_err_op_strs[op_type]);
}
- break;
- case CPER_ARM_TLB_ERROR:
+ }
+ if (type & CPER_ARM_TLB_ERROR) {
if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
- printk("%soperation type: %s\n", pfx,
+ printk("%sTLB error, operation type: %s\n", pfx,
arm_tlb_err_op_strs[op_type]);
}
- break;
- case CPER_ARM_BUS_ERROR:
+ }
+ if (type & CPER_ARM_BUS_ERROR) {
if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
- printk("%soperation type: %s\n", pfx,
+ printk("%sbus error, operation type: %s\n", pfx,
arm_bus_err_op_strs[op_type]);
}
- break;
}
}
if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
& CPER_ARM_ERR_LEVEL_MASK);
- switch (type) {
- case CPER_ARM_CACHE_ERROR:
+ if (type & CPER_ARM_CACHE_ERROR)
printk("%scache level: %d\n", pfx, level);
- break;
- case CPER_ARM_TLB_ERROR:
+
+ if (type & CPER_ARM_TLB_ERROR)
printk("%sTLB level: %d\n", pfx, level);
- break;
- case CPER_ARM_BUS_ERROR:
+
+ if (type & CPER_ARM_BUS_ERROR)
printk("%saffinity level at which the bus error occurred: %d\n",
pfx, level);
- break;
- }
}
if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
@@ -241,7 +232,8 @@ void cper_print_proc_arm(const char *pfx,
int i, len, max_ctx_type;
struct cper_arm_err_info *err_info;
struct cper_arm_ctx_info *ctx_info;
- char newpfx[64], infopfx[64];
+ char newpfx[64], infopfx[ARRAY_SIZE(newpfx) + 1];
+ char error_type[120];
printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
@@ -290,9 +282,15 @@ void cper_print_proc_arm(const char *pfx,
newpfx);
}
- printk("%serror_type: %d, %s\n", newpfx, err_info->type,
- err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
- cper_proc_error_type_strs[err_info->type] : "unknown");
+ cper_bits_to_str(error_type, sizeof(error_type),
+ FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type),
+ cper_proc_error_type_strs,
+ ARRAY_SIZE(cper_proc_error_type_strs));
+
+ printk("%serror_type: 0x%02x: %s%s\n", newpfx, err_info->type,
+ error_type,
+ (err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : "");
+
if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
printk("%serror_info: 0x%016llx\n", newpfx,
err_info->error_info);
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 232c092c4c97..8e24c36d7b63 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -12,6 +12,7 @@
* Specification version 2.4.
*/
+#include <linux/bitmap.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/time.h>
@@ -105,6 +106,65 @@ void cper_print_bits(const char *pfx, unsigned int bits,
printk("%s\n", buf);
}
+/**
+ * cper_bits_to_str - return a string for set bits
+ * @buf: buffer to store the output string
+ * @buf_size: size of the output string buffer
+ * @bits: bit mask
+ * @strs: string array, indexed by bit position
+ * @strs_size: size of the string array: @strs
+ *
+ * Add to @buf the bitmask in hexadecimal. Then, for each set bit in @bits,
+ * add the corresponding string describing the bit in @strs to @buf.
+ *
+ * A typical example is::
+ *
+ * const char * const bits[] = {
+ * "bit 3 name",
+ * "bit 4 name",
+ * "bit 5 name",
+ * };
+ * char str[120];
+ * unsigned int bitmask = BIT(3) | BIT(5);
+ * #define MASK GENMASK(5,3)
+ *
+ * cper_bits_to_str(str, sizeof(str), FIELD_GET(MASK, bitmask),
+ * bits, ARRAY_SIZE(bits));
+ *
+ * The above code fills the string ``str`` with ``bit 3 name|bit 5 name``.
+ *
+ * Return: number of bytes stored or an error code if lower than zero.
+ */
+int cper_bits_to_str(char *buf, int buf_size, unsigned long bits,
+ const char * const strs[], unsigned int strs_size)
+{
+ int len = buf_size;
+ char *str = buf;
+ int i, size;
+
+ *buf = '\0';
+
+ for_each_set_bit(i, &bits, strs_size) {
+ if (!(bits & BIT_ULL(i)))
+ continue;
+
+ if (*buf && len > 0) {
+ *str = '|';
+ len--;
+ str++;
+ }
+
+ size = strscpy(str, strs[i], len);
+ if (size < 0)
+ return size;
+
+ len -= size;
+ str += size;
+ }
+ return buf_size - len;
+}
+EXPORT_SYMBOL_GPL(cper_bits_to_str);
+
static const char * const proc_type_strs[] = {
"IA32/X64",
"IA64",
diff --git a/drivers/firmware/imx/imx-scu-irq.c b/drivers/firmware/imx/imx-scu-irq.c
index d9dcc20945c6..1f08b708e83d 100644
--- a/drivers/firmware/imx/imx-scu-irq.c
+++ b/drivers/firmware/imx/imx-scu-irq.c
@@ -137,6 +137,18 @@ int imx_scu_enable_general_irq_channel(struct device *dev)
struct mbox_chan *ch;
int ret = 0, i = 0;
+ if (!of_parse_phandle_with_args(dev->of_node, "mboxes",
+ "#mbox-cells", 0, &spec)) {
+ i = of_alias_get_id(spec.np, "mu");
+ of_node_put(spec.np);
+ }
+
+ /* use mu1 as general mu irq channel if failed */
+ if (i < 0)
+ i = 1;
+
+ mu_resource_id = IMX_SC_R_MU_0A + i;
+
ret = imx_scu_get_handle(&imx_sc_irq_ipc_handle);
if (ret)
return ret;
@@ -148,6 +160,8 @@ int imx_scu_enable_general_irq_channel(struct device *dev)
cl->dev = dev;
cl->rx_callback = imx_scu_irq_callback;
+ INIT_WORK(&imx_sc_irq_work, imx_scu_irq_work_handler);
+
/* SCU general IRQ uses general interrupt channel 3 */
ch = mbox_request_channel_byname(cl, "gip3");
if (IS_ERR(ch)) {
@@ -157,18 +171,6 @@ int imx_scu_enable_general_irq_channel(struct device *dev)
return ret;
}
- INIT_WORK(&imx_sc_irq_work, imx_scu_irq_work_handler);
-
- if (!of_parse_phandle_with_args(dev->of_node, "mboxes",
- "#mbox-cells", 0, &spec))
- i = of_alias_get_id(spec.np, "mu");
-
- /* use mu1 as general mu irq channel if failed */
- if (i < 0)
- i = 1;
-
- mu_resource_id = IMX_SC_R_MU_0A + i;
-
return ret;
}
EXPORT_SYMBOL(imx_scu_enable_general_irq_channel);
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index 9dd41eaf32cb..3cc61bb6f896 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -961,10 +961,10 @@ static enum bp_result get_embedded_panel_info_v2_1(
/* not provided by VBIOS */
info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
- info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
- & ATOM_HSYNC_POLARITY);
- info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
- & ATOM_VSYNC_POLARITY);
+ info->lcd_timing.misc_info.H_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo &
+ ATOM_HSYNC_POLARITY);
+ info->lcd_timing.misc_info.V_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo &
+ ATOM_VSYNC_POLARITY);
/* not provided by VBIOS */
info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
index 98391ba103d6..1262b72d532b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
@@ -104,7 +104,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state,
struct dc_plane_state *dc_create_plane_state(struct dc *dc)
{
struct dc_plane_state *plane_state = kvzalloc(sizeof(*plane_state),
- GFP_KERNEL);
+ GFP_ATOMIC);
if (NULL == plane_state)
return NULL;
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 6ef4ea07d1bb..c8db96b41dfa 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -34,47 +34,6 @@ static const struct drm_framebuffer_funcs psb_fb_funcs = {
.create_handle = drm_gem_fb_create_handle,
};
-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
-
-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_framebuffer *fb = fb_helper->fb;
- uint32_t v;
-
- if (!fb)
- return -ENOMEM;
-
- if (regno > 255)
- return 1;
-
- red = CMAP_TOHW(red, info->var.red.length);
- blue = CMAP_TOHW(blue, info->var.blue.length);
- green = CMAP_TOHW(green, info->var.green.length);
- transp = CMAP_TOHW(transp, info->var.transp.length);
-
- v = (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset) |
- (transp << info->var.transp.offset);
-
- if (regno < 16) {
- switch (fb->format->cpp[0] * 8) {
- case 16:
- ((uint32_t *) info->pseudo_palette)[regno] = v;
- break;
- case 24:
- case 32:
- ((uint32_t *) info->pseudo_palette)[regno] = v;
- break;
- }
- }
-
- return 0;
-}
-
static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
@@ -167,7 +126,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
static const struct fb_ops psbfb_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_setcolreg = psbfb_setcolreg,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = psbfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
@@ -178,7 +136,6 @@ static const struct fb_ops psbfb_ops = {
static const struct fb_ops psbfb_roll_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_setcolreg = psbfb_setcolreg,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
@@ -189,7 +146,6 @@ static const struct fb_ops psbfb_roll_ops = {
static const struct fb_ops psbfb_unaccel_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
- .fb_setcolreg = psbfb_setcolreg,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index 87d845d6d3bc..0db27699025a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -794,7 +794,7 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu,
return;
/* Set the fence to ALLOW mode so we can access the registers */
- gpu_write(gpu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
+ gmu_write(&a6xx_gpu->gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
_a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[2],
&a6xx_state->gmu_registers[2], false);
diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h
index 93f8f4f64578..b43c4f9bbcdf 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/atom.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h
@@ -152,8 +152,21 @@ static inline struct nv50_head_atom *
nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc);
+
if (IS_ERR(statec))
return (void *)statec;
+
+ return nv50_head_atom(statec);
+}
+
+static inline struct nv50_head_atom *
+nv50_head_atom_get_new(struct drm_atomic_state *state, struct drm_crtc *crtc)
+{
+ struct drm_crtc_state *statec = drm_atomic_get_new_crtc_state(state, crtc);
+
+ if (!statec)
+ return NULL;
+
return nv50_head_atom(statec);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index 4ae04a728bd0..4a7fc3921601 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -561,7 +561,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
asyw->image.offset[0] = nvbo->offset;
if (wndw->func->prepare) {
- asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
+ asyh = nv50_head_atom_get_new(asyw->state.state, asyw->state.crtc);
if (IS_ERR(asyh))
return PTR_ERR(asyh);
diff --git a/drivers/gpu/drm/panel/panel-visionox-rm69299.c b/drivers/gpu/drm/panel/panel-visionox-rm69299.c
index 6134432e4918..2260d5abf1ae 100644
--- a/drivers/gpu/drm/panel/panel-visionox-rm69299.c
+++ b/drivers/gpu/drm/panel/panel-visionox-rm69299.c
@@ -64,7 +64,7 @@ static int visionox_rm69299_unprepare(struct drm_panel *panel)
struct visionox_rm69299 *ctx = panel_to_ctx(panel);
int ret;
- ctx->dsi->mode_flags = 0;
+ ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
if (ret < 0)
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index d5e8e3a8bff3..0100d6f091b5 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -302,7 +302,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
variant->name, priv);
if (ret != 0) {
dev_err(dev, "%s failed irq %d\n", __func__, ret);
- return ret;
+ goto dev_put;
}
ret = pl111_modeset_init(drm);
diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c
index 575bc331716e..f860ff1db648 100644
--- a/drivers/gpu/drm/vgem/vgem_fence.c
+++ b/drivers/gpu/drm/vgem/vgem_fence.c
@@ -94,7 +94,7 @@ static struct dma_fence *vgem_fence_create(struct vgem_file *vfile,
dma_fence_init(&fence->base, &vgem_fence_ops, &fence->lock,
dma_fence_context_alloc(1), 1);
- timer_setup(&fence->timer, vgem_fence_timeout, 0);
+ timer_setup(&fence->timer, vgem_fence_timeout, TIMER_IRQSAFE);
/* We force the fence to expire within 10s to prevent driver hangs */
mod_timer(&fence->timer, jiffies + VGEM_FENCE_TIMEOUT);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 17d7f172a9e0..361f96d09374 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1520,6 +1520,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
SVGA3dCmdHeader *header)
{
struct vmw_buffer_object *vmw_bo = NULL;
+ struct vmw_resource *res;
struct vmw_surface *srf = NULL;
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSurfaceDMA);
int ret;
@@ -1555,18 +1556,24 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
dirty = (cmd->body.transfer == SVGA3D_WRITE_HOST_VRAM) ?
VMW_RES_DIRTY_SET : 0;
- ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
- dirty, user_surface_converter,
- &cmd->body.host.sid, NULL);
+ ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, dirty,
+ user_surface_converter, &cmd->body.host.sid,
+ NULL);
if (unlikely(ret != 0)) {
if (unlikely(ret != -ERESTARTSYS))
VMW_DEBUG_USER("could not find surface for DMA.\n");
return ret;
}
- srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);
+ res = sw_context->res_cache[vmw_res_surface].res;
+ if (!res) {
+ VMW_DEBUG_USER("Invalid DMA surface.\n");
+ return -EINVAL;
+ }
- vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base, header);
+ srf = vmw_res_to_srf(res);
+ vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base,
+ header);
return 0;
}
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 89aa7a0e51de..e789452181fe 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1349,7 +1349,12 @@ EXPORT_SYMBOL_GPL(hid_snto32);
static u32 s32ton(__s32 value, unsigned n)
{
- s32 a = value >> (n - 1);
+ s32 a;
+
+ if (!value || !n)
+ return 0;
+
+ a = value >> (n - 1);
if (a && a != -1)
return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
return value & ((1 << n) - 1);
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 3399953256d8..1c41a6297d3b 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -718,7 +718,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
switch (usage->hid) {
/* These usage IDs map directly to the usage codes. */
- case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
+ case HID_GD_X: case HID_GD_Y:
case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
if (field->flags & HID_MAIN_ITEM_RELATIVE)
map_rel(usage->hid & 0xf);
@@ -726,6 +726,22 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
map_abs_clear(usage->hid & 0xf);
break;
+ case HID_GD_Z:
+ /* HID_GD_Z is mapped to ABS_DISTANCE for stylus/pen */
+ if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+ map_rel(usage->hid & 0xf);
+ } else {
+ if (field->application == HID_DG_PEN ||
+ field->physical == HID_DG_PEN ||
+ field->logical == HID_DG_STYLUS ||
+ field->physical == HID_DG_STYLUS ||
+ field->application == HID_DG_DIGITIZER)
+ map_abs_clear(ABS_DISTANCE);
+ else
+ map_abs_clear(usage->hid & 0xf);
+ }
+ break;
+
case HID_GD_WHEEL:
if (field->flags & HID_MAIN_ITEM_RELATIVE) {
set_bit(REL_WHEEL, input->relbit);
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index bda9150aa372..bd31315fdaf5 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -755,7 +755,6 @@ static void delayedwork_callback(struct work_struct *work)
struct dj_workitem workitem;
unsigned long flags;
int count;
- int retval;
dbg_hid("%s\n", __func__);
@@ -792,11 +791,7 @@ static void delayedwork_callback(struct work_struct *work)
logi_dj_recv_destroy_djhid_device(djrcv_dev, &workitem);
break;
case WORKITEM_TYPE_UNKNOWN:
- retval = logi_dj_recv_query_paired_devices(djrcv_dev);
- if (retval) {
- hid_err(djrcv_dev->hidpp, "%s: logi_dj_recv_query_paired_devices error: %d\n",
- __func__, retval);
- }
+ logi_dj_recv_query_paired_devices(djrcv_dev);
break;
case WORKITEM_TYPE_EMPTY:
dbg_hid("%s: device list is empty\n", __func__);
@@ -1173,8 +1168,10 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
djrcv_dev->last_query = jiffies;
- if (djrcv_dev->type != recvr_type_dj)
- return logi_dj_recv_query_hidpp_devices(djrcv_dev);
+ if (djrcv_dev->type != recvr_type_dj) {
+ retval = logi_dj_recv_query_hidpp_devices(djrcv_dev);
+ goto out;
+ }
dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
if (!dj_report)
@@ -1184,6 +1181,10 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
kfree(dj_report);
+out:
+ if (retval < 0)
+ hid_err(djrcv_dev->hidpp, "%s error:%d\n", __func__, retval);
+
return retval;
}
@@ -1209,6 +1210,8 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
(u8)timeout;
retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
+ if (retval)
+ goto out;
/*
* Ugly sleep to work around a USB 3.0 bug when the receiver is
@@ -1217,11 +1220,6 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
* 50 msec should gives enough time to the receiver to be ready.
*/
msleep(50);
-
- if (retval) {
- kfree(dj_report);
- return retval;
- }
}
/*
@@ -1247,7 +1245,12 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,
HID_REQ_SET_REPORT);
+out:
kfree(dj_report);
+
+ if (retval < 0)
+ hid_err(hdev, "%s error:%d\n", __func__, retval);
+
return retval;
}
@@ -1753,11 +1756,8 @@ static int logi_dj_probe(struct hid_device *hdev,
if (has_hidpp) {
retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
- if (retval < 0) {
- hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
- __func__, retval);
+ if (retval < 0)
goto switch_to_dj_mode_fail;
- }
}
/* This is enabling the polling urb on the IN endpoint */
@@ -1775,15 +1775,11 @@ static int logi_dj_probe(struct hid_device *hdev,
spin_lock_irqsave(&djrcv_dev->lock, flags);
djrcv_dev->ready = true;
spin_unlock_irqrestore(&djrcv_dev->lock, flags);
- retval = logi_dj_recv_query_paired_devices(djrcv_dev);
- if (retval < 0) {
- hid_err(hdev, "%s: logi_dj_recv_query_paired_devices error:%d\n",
- __func__, retval);
- /*
- * This can happen with a KVM, let the probe succeed,
- * logi_dj_recv_queue_unknown_work will retry later.
- */
- }
+ /*
+ * This can fail with a KVM. Ignore errors to let the probe
+ * succeed, logi_dj_recv_queue_unknown_work will retry later.
+ */
+ logi_dj_recv_query_paired_devices(djrcv_dev);
}
return 0;
@@ -1800,18 +1796,12 @@ static int logi_dj_probe(struct hid_device *hdev,
#ifdef CONFIG_PM
static int logi_dj_reset_resume(struct hid_device *hdev)
{
- int retval;
struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
if (!djrcv_dev || djrcv_dev->hidpp != hdev)
return 0;
- retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
- if (retval < 0) {
- hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
- __func__, retval);
- }
-
+ logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
return 0;
}
#endif
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index ee99f5b3342d..0d15148d5253 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -220,6 +220,15 @@ static const struct hid_device_id hid_quirks[] = {
* used as a driver. See hid_scan_report().
*/
static const struct hid_device_id hid_have_special_driver[] = {
+#if IS_ENABLED(CONFIG_APPLEDISPLAY)
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x9218) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x9219) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x921c) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x921d) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x9222) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x9226) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, 0x9236) },
+#endif
#if IS_ENABLED(CONFIG_HID_A4TECH)
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 79b498f816fe..ceeb3f891608 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -741,7 +741,7 @@ static void applesmc_idev_poll(struct input_dev *idev)
static ssize_t applesmc_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "applesmc\n");
+ return sysfs_emit(buf, "applesmc\n");
}
static ssize_t applesmc_position_show(struct device *dev,
@@ -763,8 +763,8 @@ static ssize_t applesmc_position_show(struct device *dev,
out:
if (ret)
return ret;
- else
- return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z);
+
+ return sysfs_emit(buf, "(%d,%d,%d)\n", x, y, z);
}
static ssize_t applesmc_light_show(struct device *dev,
@@ -804,8 +804,8 @@ static ssize_t applesmc_light_show(struct device *dev,
out:
if (ret)
return ret;
- else
- return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right);
+
+ return sysfs_emit(sysfsbuf, "(%d,%d)\n", left, right);
}
/* Displays sensor key as label */
@@ -814,7 +814,7 @@ static ssize_t applesmc_show_sensor_label(struct device *dev,
{
const char *key = smcreg.index[to_index(devattr)];
- return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key);
+ return sysfs_emit(sysfsbuf, "%s\n", key);
}
/* Displays degree Celsius * 1000 */
@@ -832,7 +832,7 @@ static ssize_t applesmc_show_temperature(struct device *dev,
temp = 250 * (value >> 6);
- return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", temp);
+ return sysfs_emit(sysfsbuf, "%d\n", temp);
}
static ssize_t applesmc_show_fan_speed(struct device *dev,
@@ -851,7 +851,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
return ret;
speed = ((buffer[0] << 8 | buffer[1]) >> 2);
- return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
+ return sysfs_emit(sysfsbuf, "%u\n", speed);
}
static ssize_t applesmc_store_fan_speed(struct device *dev,
@@ -891,7 +891,7 @@ static ssize_t applesmc_show_fan_manual(struct device *dev,
return ret;
manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
- return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
+ return sysfs_emit(sysfsbuf, "%d\n", manual);
}
static ssize_t applesmc_store_fan_manual(struct device *dev,
@@ -943,14 +943,14 @@ static ssize_t applesmc_show_fan_position(struct device *dev,
if (ret)
return ret;
- else
- return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4);
+
+ return sysfs_emit(sysfsbuf, "%s\n", buffer + 4);
}
static ssize_t applesmc_calibrate_show(struct device *dev,
struct device_attribute *attr, char *sysfsbuf)
{
- return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y);
+ return sysfs_emit(sysfsbuf, "(%d,%d)\n", rest_x, rest_y);
}
static ssize_t applesmc_calibrate_store(struct device *dev,
@@ -992,7 +992,7 @@ static ssize_t applesmc_key_count_show(struct device *dev,
count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
((u32)buffer[2]<<8) + buffer[3];
- return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
+ return sysfs_emit(sysfsbuf, "%d\n", count);
}
static ssize_t applesmc_key_at_index_read_show(struct device *dev,
@@ -1020,7 +1020,7 @@ static ssize_t applesmc_key_at_index_data_length_show(struct device *dev,
if (IS_ERR(entry))
return PTR_ERR(entry);
- return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len);
+ return sysfs_emit(sysfsbuf, "%d\n", entry->len);
}
static ssize_t applesmc_key_at_index_type_show(struct device *dev,
@@ -1032,7 +1032,7 @@ static ssize_t applesmc_key_at_index_type_show(struct device *dev,
if (IS_ERR(entry))
return PTR_ERR(entry);
- return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type);
+ return sysfs_emit(sysfsbuf, "%s\n", entry->type);
}
static ssize_t applesmc_key_at_index_name_show(struct device *dev,
@@ -1044,13 +1044,13 @@ static ssize_t applesmc_key_at_index_name_show(struct device *dev,
if (IS_ERR(entry))
return PTR_ERR(entry);
- return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key);
+ return sysfs_emit(sysfsbuf, "%s\n", entry->key);
}
static ssize_t applesmc_key_at_index_show(struct device *dev,
struct device_attribute *attr, char *sysfsbuf)
{
- return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index);
+ return sysfs_emit(sysfsbuf, "%d\n", key_at_index);
}
static ssize_t applesmc_key_at_index_store(struct device *dev,
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index fe90f0536d76..235d56e96879 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -282,6 +282,9 @@ static ssize_t ibmpex_high_low_store(struct device *dev,
{
struct ibmpex_bmc_data *data = dev_get_drvdata(dev);
+ if (!data)
+ return -ENODEV;
+
ibmpex_reset_high_low_data(data);
return count;
@@ -514,6 +517,9 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data)
{
int i, j;
+ hwmon_device_unregister(data->hwmon_dev);
+ dev_set_drvdata(data->bmc_device, NULL);
+
device_remove_file(data->bmc_device,
&sensor_dev_attr_reset_high_low.dev_attr);
device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr);
@@ -527,8 +533,7 @@ static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data)
}
list_del(&data->list);
- dev_set_drvdata(data->bmc_device, NULL);
- hwmon_device_unregister(data->hwmon_dev);
+
ipmi_destroy_user(data->user);
kfree(data->sensors);
kfree(data);
diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c
index f4c7b5f76359..fc3007c3e85c 100644
--- a/drivers/hwmon/ina209.c
+++ b/drivers/hwmon/ina209.c
@@ -259,7 +259,7 @@ static ssize_t ina209_interval_show(struct device *dev,
{
struct ina209_data *data = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", data->update_interval);
+ return sysfs_emit(buf, "%d\n", data->update_interval);
}
/*
@@ -343,7 +343,7 @@ static ssize_t ina209_value_show(struct device *dev,
return PTR_ERR(data);
val = ina209_from_reg(attr->index, data->regs[attr->index]);
- return snprintf(buf, PAGE_SIZE, "%ld\n", val);
+ return sysfs_emit(buf, "%ld\n", val);
}
static ssize_t ina209_alarm_show(struct device *dev,
@@ -363,7 +363,7 @@ static ssize_t ina209_alarm_show(struct device *dev,
* All alarms are in the INA209_STATUS register. To avoid a long
* switch statement, the mask is passed in attr->index
*/
- return snprintf(buf, PAGE_SIZE, "%u\n", !!(status & mask));
+ return sysfs_emit(buf, "%u\n", !!(status & mask));
}
/* Shunt voltage, history, limits, alarms */
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index ca97f9e931bc..84a03cfe1fed 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -386,7 +386,7 @@ static ssize_t ina226_alert_show(struct device *dev,
val = ina226_reg_to_alert(data, attr->index, regval);
}
- ret = snprintf(buf, PAGE_SIZE, "%d\n", val);
+ ret = sysfs_emit(buf, "%d\n", val);
abort:
mutex_unlock(&data->config_lock);
return ret;
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c
index 836e7579e166..7e6720b0157f 100644
--- a/drivers/hwmon/ina3221.c
+++ b/drivers/hwmon/ina3221.c
@@ -698,7 +698,7 @@ static ssize_t ina3221_shunt_show(struct device *dev,
unsigned int channel = sd_attr->index;
struct ina3221_input *input = &ina->inputs[channel];
- return snprintf(buf, PAGE_SIZE, "%d\n", input->shunt_resistor);
+ return sysfs_emit(buf, "%d\n", input->shunt_resistor);
}
static ssize_t ina3221_shunt_store(struct device *dev,
diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c
index c83eb2fd80eb..1109fffa76fb 100644
--- a/drivers/hwmon/lineage-pem.c
+++ b/drivers/hwmon/lineage-pem.c
@@ -280,7 +280,7 @@ static ssize_t pem_bool_show(struct device *dev, struct device_attribute *da,
return PTR_ERR(data);
status = data->data_string[attr->nr] & attr->index;
- return snprintf(buf, PAGE_SIZE, "%d\n", !!status);
+ return sysfs_emit(buf, "%d\n", !!status);
}
static ssize_t pem_data_show(struct device *dev, struct device_attribute *da,
@@ -296,7 +296,7 @@ static ssize_t pem_data_show(struct device *dev, struct device_attribute *da,
value = pem_get_data(data->data_string, sizeof(data->data_string),
attr->index);
- return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+ return sysfs_emit(buf, "%ld\n", value);
}
static ssize_t pem_input_show(struct device *dev, struct device_attribute *da,
@@ -312,7 +312,7 @@ static ssize_t pem_input_show(struct device *dev, struct device_attribute *da,
value = pem_get_input(data->input_string, sizeof(data->input_string),
attr->index);
- return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+ return sysfs_emit(buf, "%ld\n", value);
}
static ssize_t pem_fan_show(struct device *dev, struct device_attribute *da,
@@ -328,7 +328,7 @@ static ssize_t pem_fan_show(struct device *dev, struct device_attribute *da,
value = pem_get_fan(data->fan_speed, sizeof(data->fan_speed),
attr->index);
- return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+ return sysfs_emit(buf, "%ld\n", value);
}
/* Voltages */
diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
index 65d792f18425..c06ab7317431 100644
--- a/drivers/hwmon/ltc2945.c
+++ b/drivers/hwmon/ltc2945.c
@@ -226,7 +226,7 @@ static ssize_t ltc2945_value_show(struct device *dev,
value = ltc2945_reg_to_val(dev, attr->index);
if (value < 0)
return value;
- return snprintf(buf, PAGE_SIZE, "%lld\n", value);
+ return sysfs_emit(buf, "%lld\n", value);
}
static ssize_t ltc2945_value_store(struct device *dev,
@@ -335,7 +335,7 @@ static ssize_t ltc2945_bool_show(struct device *dev,
if (fault) /* Clear reported faults in chip register */
regmap_update_bits(regmap, LTC2945_FAULT, attr->index, 0);
- return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
+ return sysfs_emit(buf, "%d\n", !!fault);
}
/* Input voltages */
diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c
index 78b191b26bb2..c126fc3e3449 100644
--- a/drivers/hwmon/ltc2990.c
+++ b/drivers/hwmon/ltc2990.c
@@ -147,7 +147,7 @@ static ssize_t ltc2990_value_show(struct device *dev,
if (unlikely(ret < 0))
return ret;
- return snprintf(buf, PAGE_SIZE, "%d\n", value);
+ return sysfs_emit(buf, "%d\n", value);
}
static umode_t ltc2990_attrs_visible(struct kobject *kobj,
diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c
index 321f54e237bd..13b85367a21f 100644
--- a/drivers/hwmon/ltc4151.c
+++ b/drivers/hwmon/ltc4151.c
@@ -128,7 +128,7 @@ static ssize_t ltc4151_value_show(struct device *dev,
return PTR_ERR(data);
value = ltc4151_get_value(data, attr->index);
- return snprintf(buf, PAGE_SIZE, "%d\n", value);
+ return sysfs_emit(buf, "%d\n", value);
}
/*
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
index 7cef3cb2962b..1d18c212054f 100644
--- a/drivers/hwmon/ltc4215.c
+++ b/drivers/hwmon/ltc4215.c
@@ -139,7 +139,7 @@ static ssize_t ltc4215_voltage_show(struct device *dev,
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
const int voltage = ltc4215_get_voltage(dev, attr->index);
- return snprintf(buf, PAGE_SIZE, "%d\n", voltage);
+ return sysfs_emit(buf, "%d\n", voltage);
}
static ssize_t ltc4215_current_show(struct device *dev,
@@ -147,7 +147,7 @@ static ssize_t ltc4215_current_show(struct device *dev,
{
const unsigned int curr = ltc4215_get_current(dev);
- return snprintf(buf, PAGE_SIZE, "%u\n", curr);
+ return sysfs_emit(buf, "%u\n", curr);
}
static ssize_t ltc4215_power_show(struct device *dev,
@@ -159,7 +159,7 @@ static ssize_t ltc4215_power_show(struct device *dev,
/* current in mA * voltage in mV == power in uW */
const unsigned int power = abs(output_voltage * curr);
- return snprintf(buf, PAGE_SIZE, "%u\n", power);
+ return sysfs_emit(buf, "%u\n", power);
}
static ssize_t ltc4215_alarm_show(struct device *dev,
@@ -170,7 +170,7 @@ static ssize_t ltc4215_alarm_show(struct device *dev,
const u8 reg = data->regs[LTC4215_STATUS];
const u32 mask = attr->index;
- return snprintf(buf, PAGE_SIZE, "%u\n", !!(reg & mask));
+ return sysfs_emit(buf, "%u\n", !!(reg & mask));
}
/*
diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c
index 3efce6d1cb88..d2027ca5c925 100644
--- a/drivers/hwmon/ltc4222.c
+++ b/drivers/hwmon/ltc4222.c
@@ -94,7 +94,7 @@ static ssize_t ltc4222_value_show(struct device *dev,
value = ltc4222_get_value(dev, attr->index);
if (value < 0)
return value;
- return snprintf(buf, PAGE_SIZE, "%d\n", value);
+ return sysfs_emit(buf, "%d\n", value);
}
static ssize_t ltc4222_bool_show(struct device *dev,
@@ -112,7 +112,7 @@ static ssize_t ltc4222_bool_show(struct device *dev,
if (fault) /* Clear reported faults in chip register */
regmap_update_bits(regmap, attr->nr, attr->index, 0);
- return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
+ return sysfs_emit(buf, "%d\n", !!fault);
}
/* Voltages */
diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c
index d0beb43abf3f..75e89cec381e 100644
--- a/drivers/hwmon/ltc4260.c
+++ b/drivers/hwmon/ltc4260.c
@@ -79,7 +79,7 @@ static ssize_t ltc4260_value_show(struct device *dev,
value = ltc4260_get_value(dev, attr->index);
if (value < 0)
return value;
- return snprintf(buf, PAGE_SIZE, "%d\n", value);
+ return sysfs_emit(buf, "%d\n", value);
}
static ssize_t ltc4260_bool_show(struct device *dev,
@@ -98,7 +98,7 @@ static ssize_t ltc4260_bool_show(struct device *dev,
if (fault) /* Clear reported faults in chip register */
regmap_update_bits(regmap, LTC4260_FAULT, attr->index, 0);
- return snprintf(buf, PAGE_SIZE, "%d\n", !!fault);
+ return sysfs_emit(buf, "%d\n", !!fault);
}
/* Voltages */
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
index 1dab84b52df5..b81e9c3d297b 100644
--- a/drivers/hwmon/ltc4261.c
+++ b/drivers/hwmon/ltc4261.c
@@ -130,7 +130,7 @@ static ssize_t ltc4261_value_show(struct device *dev,
return PTR_ERR(data);
value = ltc4261_get_value(data, attr->index);
- return snprintf(buf, PAGE_SIZE, "%d\n", value);
+ return sysfs_emit(buf, "%d\n", value);
}
static ssize_t ltc4261_bool_show(struct device *dev,
@@ -147,7 +147,7 @@ static ssize_t ltc4261_bool_show(struct device *dev,
if (fault) /* Clear reported faults in chip register */
i2c_smbus_write_byte_data(data->client, LTC4261_FAULT, ~fault);
- return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
+ return sysfs_emit(buf, "%d\n", fault ? 1 : 0);
}
/*
diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c
index b4c519e52fff..5787db933fad 100644
--- a/drivers/hwmon/max16065.c
+++ b/drivers/hwmon/max16065.c
@@ -195,7 +195,7 @@ static ssize_t max16065_alarm_show(struct device *dev,
i2c_smbus_write_byte_data(data->client,
MAX16065_FAULT(attr2->nr), val);
- return snprintf(buf, PAGE_SIZE, "%d\n", !!val);
+ return sysfs_emit(buf, "%d\n", !!val);
}
static ssize_t max16065_input_show(struct device *dev,
@@ -208,20 +208,21 @@ static ssize_t max16065_input_show(struct device *dev,
if (unlikely(adc < 0))
return adc;
- return snprintf(buf, PAGE_SIZE, "%d\n",
- ADC_TO_MV(adc, data->range[attr->index]));
+ return sysfs_emit(buf, "%d\n",
+ ADC_TO_MV(adc, data->range[attr->index]));
}
static ssize_t max16065_current_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct max16065_data *data = max16065_update_device(dev);
+ int curr_sense = data->curr_sense;
- if (unlikely(data->curr_sense < 0))
- return data->curr_sense;
+ if (unlikely(curr_sense < 0))
+ return curr_sense;
- return snprintf(buf, PAGE_SIZE, "%d\n",
- ADC_TO_CURR(data->curr_sense, data->curr_gain));
+ return sysfs_emit(buf, "%d\n",
+ ADC_TO_CURR(curr_sense, data->curr_gain));
}
static ssize_t max16065_limit_store(struct device *dev,
@@ -257,8 +258,8 @@ static ssize_t max16065_limit_show(struct device *dev,
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
struct max16065_data *data = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n",
- data->limit[attr2->nr][attr2->index]);
+ return sysfs_emit(buf, "%d\n",
+ data->limit[attr2->nr][attr2->index]);
}
/* Construct a sensor_device_attribute structure for each register */
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index 18f1b57431ff..479ea4ce451a 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -261,7 +261,7 @@ static ssize_t occ_show_temp_1(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t occ_show_temp_2(struct device *dev,
@@ -312,7 +312,7 @@ static ssize_t occ_show_temp_2(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t occ_show_temp_10(struct device *dev,
@@ -359,7 +359,7 @@ static ssize_t occ_show_temp_10(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t occ_show_freq_1(struct device *dev,
@@ -389,7 +389,7 @@ static ssize_t occ_show_freq_1(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t occ_show_freq_2(struct device *dev,
@@ -419,7 +419,7 @@ static ssize_t occ_show_freq_2(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+ return sysfs_emit(buf, "%u\n", val);
}
static ssize_t occ_show_power_1(struct device *dev,
@@ -458,7 +458,7 @@ static ssize_t occ_show_power_1(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
+ return sysfs_emit(buf, "%llu\n", val);
}
static u64 occ_get_powr_avg(u64 accum, u32 samples)
@@ -485,9 +485,9 @@ static ssize_t occ_show_power_2(struct device *dev,
switch (sattr->nr) {
case 0:
- return snprintf(buf, PAGE_SIZE - 1, "%u_%u_%u\n",
- get_unaligned_be32(&power->sensor_id),
- power->function_id, power->apss_channel);
+ return sysfs_emit(buf, "%u_%u_%u\n",
+ get_unaligned_be32(&power->sensor_id),
+ power->function_id, power->apss_channel);
case 1:
val = occ_get_powr_avg(get_unaligned_be64(&power->accumulator),
get_unaligned_be32(&power->update_tag));
@@ -503,7 +503,7 @@ static ssize_t occ_show_power_2(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
+ return sysfs_emit(buf, "%llu\n", val);
}
static ssize_t occ_show_power_a0(struct device *dev,
@@ -524,8 +524,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
switch (sattr->nr) {
case 0:
- return snprintf(buf, PAGE_SIZE - 1, "%u_system\n",
- get_unaligned_be32(&power->sensor_id));
+ return sysfs_emit(buf, "%u_system\n",
+ get_unaligned_be32(&power->sensor_id));
case 1:
val = occ_get_powr_avg(get_unaligned_be64(&power->system.accumulator),
get_unaligned_be32(&power->system.update_tag));
@@ -538,8 +538,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
val = get_unaligned_be16(&power->system.value) * 1000000ULL;
break;
case 4:
- return snprintf(buf, PAGE_SIZE - 1, "%u_proc\n",
- get_unaligned_be32(&power->sensor_id));
+ return sysfs_emit(buf, "%u_proc\n",
+ get_unaligned_be32(&power->sensor_id));
case 5:
val = occ_get_powr_avg(get_unaligned_be64(&power->proc.accumulator),
get_unaligned_be32(&power->proc.update_tag));
@@ -552,8 +552,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
val = get_unaligned_be16(&power->proc.value) * 1000000ULL;
break;
case 8:
- return snprintf(buf, PAGE_SIZE - 1, "%u_vdd\n",
- get_unaligned_be32(&power->sensor_id));
+ return sysfs_emit(buf, "%u_vdd\n",
+ get_unaligned_be32(&power->sensor_id));
case 9:
val = occ_get_powr_avg(get_unaligned_be64(&power->vdd.accumulator),
get_unaligned_be32(&power->vdd.update_tag));
@@ -566,8 +566,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
val = get_unaligned_be16(&power->vdd.value) * 1000000ULL;
break;
case 12:
- return snprintf(buf, PAGE_SIZE - 1, "%u_vdn\n",
- get_unaligned_be32(&power->sensor_id));
+ return sysfs_emit(buf, "%u_vdn\n",
+ get_unaligned_be32(&power->sensor_id));
case 13:
val = occ_get_powr_avg(get_unaligned_be64(&power->vdn.accumulator),
get_unaligned_be32(&power->vdn.update_tag));
@@ -583,7 +583,7 @@ static ssize_t occ_show_power_a0(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
+ return sysfs_emit(buf, "%llu\n", val);
}
static ssize_t occ_show_caps_1_2(struct device *dev,
@@ -604,7 +604,7 @@ static ssize_t occ_show_caps_1_2(struct device *dev,
switch (sattr->nr) {
case 0:
- return snprintf(buf, PAGE_SIZE - 1, "system\n");
+ return sysfs_emit(buf, "system\n");
case 1:
val = get_unaligned_be16(&caps->cap) * 1000000ULL;
break;
@@ -633,7 +633,7 @@ static ssize_t occ_show_caps_1_2(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
+ return sysfs_emit(buf, "%llu\n", val);
}
static ssize_t occ_show_caps_3(struct device *dev,
@@ -654,7 +654,7 @@ static ssize_t occ_show_caps_3(struct device *dev,
switch (sattr->nr) {
case 0:
- return snprintf(buf, PAGE_SIZE - 1, "system\n");
+ return sysfs_emit(buf, "system\n");
case 1:
val = get_unaligned_be16(&caps->cap) * 1000000ULL;
break;
@@ -683,7 +683,7 @@ static ssize_t occ_show_caps_3(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
+ return sysfs_emit(buf, "%llu\n", val);
}
static ssize_t occ_store_caps_user(struct device *dev,
@@ -726,21 +726,22 @@ static ssize_t occ_show_extended(struct device *dev,
switch (sattr->nr) {
case 0:
- if (extn->flags & EXTN_FLAG_SENSOR_ID)
- rc = snprintf(buf, PAGE_SIZE - 1, "%u",
- get_unaligned_be32(&extn->sensor_id));
- else
- rc = snprintf(buf, PAGE_SIZE - 1, "%02x%02x%02x%02x\n",
- extn->name[0], extn->name[1],
- extn->name[2], extn->name[3]);
+ if (extn->flags & EXTN_FLAG_SENSOR_ID) {
+ rc = sysfs_emit(buf, "%u",
+ get_unaligned_be32(&extn->sensor_id));
+ } else {
+ rc = sysfs_emit(buf, "%02x%02x%02x%02x\n",
+ extn->name[0], extn->name[1],
+ extn->name[2], extn->name[3]);
+ }
break;
case 1:
- rc = snprintf(buf, PAGE_SIZE - 1, "%02x\n", extn->flags);
+ rc = sysfs_emit(buf, "%02x\n", extn->flags);
break;
case 2:
- rc = snprintf(buf, PAGE_SIZE - 1, "%02x%02x%02x%02x%02x%02x\n",
- extn->data[0], extn->data[1], extn->data[2],
- extn->data[3], extn->data[4], extn->data[5]);
+ rc = sysfs_emit(buf, "%02x%02x%02x%02x%02x%02x\n",
+ extn->data[0], extn->data[1], extn->data[2],
+ extn->data[3], extn->data[4], extn->data[5]);
break;
default:
return -EINVAL;
diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c
index c73be0747e66..03b16abef67f 100644
--- a/drivers/hwmon/occ/sysfs.c
+++ b/drivers/hwmon/occ/sysfs.c
@@ -67,7 +67,7 @@ static ssize_t occ_sysfs_show(struct device *dev,
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t occ_error_show(struct device *dev,
@@ -77,7 +77,7 @@ static ssize_t occ_error_show(struct device *dev,
occ_update_response(occ);
- return snprintf(buf, PAGE_SIZE - 1, "%d\n", occ->error);
+ return sysfs_emit(buf, "%d\n", occ->error);
}
static SENSOR_DEVICE_ATTR(occ_master, 0444, occ_sysfs_show, NULL, 0);
diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c
index be493182174d..b166d9c1b47e 100644
--- a/drivers/hwmon/pmbus/inspur-ipsps.c
+++ b/drivers/hwmon/pmbus/inspur-ipsps.c
@@ -70,7 +70,7 @@ static ssize_t ipsps_string_show(struct device *dev,
p = memscan(data, '#', rc);
*p = '\0';
- return snprintf(buf, PAGE_SIZE, "%s\n", data);
+ return sysfs_emit(buf, "%s\n", data);
}
static ssize_t ipsps_fw_version_show(struct device *dev,
@@ -91,9 +91,9 @@ static ssize_t ipsps_fw_version_show(struct device *dev,
if (rc != 6)
return -EPROTO;
- return snprintf(buf, PAGE_SIZE, "%u.%02u%u-%u.%02u\n",
- data[1], data[2]/* < 100 */, data[3]/*< 10*/,
- data[4], data[5]/* < 100 */);
+ return sysfs_emit(buf, "%u.%02u%u-%u.%02u\n",
+ data[1], data[2]/* < 100 */, data[3]/*< 10*/,
+ data[4], data[5]/* < 100 */);
}
static ssize_t ipsps_mode_show(struct device *dev,
@@ -111,19 +111,19 @@ static ssize_t ipsps_mode_show(struct device *dev,
switch (rc) {
case MODE_ACTIVE:
- return snprintf(buf, PAGE_SIZE, "[%s] %s %s\n",
- MODE_ACTIVE_STRING,
- MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
+ return sysfs_emit(buf, "[%s] %s %s\n",
+ MODE_ACTIVE_STRING,
+ MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
case MODE_STANDBY:
- return snprintf(buf, PAGE_SIZE, "%s [%s] %s\n",
- MODE_ACTIVE_STRING,
- MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
+ return sysfs_emit(buf, "%s [%s] %s\n",
+ MODE_ACTIVE_STRING,
+ MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
case MODE_REDUNDANCY:
- return snprintf(buf, PAGE_SIZE, "%s %s [%s]\n",
- MODE_ACTIVE_STRING,
- MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
+ return sysfs_emit(buf, "%s %s [%s]\n",
+ MODE_ACTIVE_STRING,
+ MODE_STANDBY_STRING, MODE_REDUNDANCY_STRING);
default:
- return snprintf(buf, PAGE_SIZE, "unspecified\n");
+ return sysfs_emit(buf, "unspecified\n");
}
}
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index b795c90a46d9..e90ab980b836 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -962,7 +962,7 @@ static ssize_t pmbus_show_boolean(struct device *dev,
val = pmbus_get_boolean(client, boolean, attr->index);
if (val < 0)
return val;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t pmbus_show_sensor(struct device *dev,
@@ -978,7 +978,7 @@ static ssize_t pmbus_show_sensor(struct device *dev,
if (sensor->data < 0)
ret = sensor->data;
else
- ret = snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
+ ret = sysfs_emit(buf, "%lld\n", pmbus_reg2data(data, sensor));
mutex_unlock(&data->update_lock);
return ret;
}
@@ -1014,7 +1014,7 @@ static ssize_t pmbus_show_label(struct device *dev,
{
struct pmbus_label *label = to_pmbus_label(da);
- return snprintf(buf, PAGE_SIZE, "%s\n", label->label);
+ return sysfs_emit(buf, "%s\n", label->label);
}
static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr)
@@ -2054,7 +2054,7 @@ static ssize_t pmbus_show_samples(struct device *dev,
if (val < 0)
return val;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t pmbus_set_samples(struct device *dev,
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index f2703c5460d0..70ae665db477 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -166,7 +166,7 @@ static ssize_t s3c_hwmon_ch_show(struct device *dev,
ret *= cfg->mult;
ret = DIV_ROUND_CLOSEST(ret, cfg->div);
- return snprintf(buf, PAGE_SIZE, "%d\n", ret);
+ return sysfs_emit(buf, "%d\n", ret);
}
/**
@@ -187,7 +187,7 @@ static ssize_t s3c_hwmon_label_show(struct device *dev,
cfg = pdata->in[sen_attr->index];
- return snprintf(buf, PAGE_SIZE, "%s\n", cfg->name);
+ return sysfs_emit(buf, "%s\n", cfg->name);
}
/**
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 039644263101..a7e0d7bcf923 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -195,7 +195,7 @@ static int reg_to_rpm(u16 reg)
static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
+ return sysfs_emit(buf, "%s\n", DEVNAME);
}
static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
@@ -209,7 +209,7 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
return PTR_ERR(data);
val = reg_to_temp(data->temp[attr->index]);
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t temp_fault_show(struct device *dev,
@@ -221,7 +221,7 @@ static ssize_t temp_fault_show(struct device *dev,
if (IS_ERR(data))
return PTR_ERR(data);
- return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0);
+ return sysfs_emit(buf, "%d\n", data->temp[attr->index] == 0);
}
static ssize_t temp_max_show(struct device *dev,
@@ -232,7 +232,7 @@ static ssize_t temp_max_show(struct device *dev,
int val;
val = reg_to_temp_limit(data->temp_max[attr->index]);
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t temp_crit_show(struct device *dev,
@@ -243,7 +243,7 @@ static ssize_t temp_crit_show(struct device *dev,
int val;
val = reg_to_temp_limit(data->temp_crit[attr->index]);
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
@@ -260,7 +260,7 @@ static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
if (val < 0)
return val;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t fan_fault_show(struct device *dev,
@@ -272,8 +272,8 @@ static ssize_t fan_fault_show(struct device *dev,
if (IS_ERR(data))
return PTR_ERR(data);
- return snprintf(buf, PAGE_SIZE, "%d\n",
- data->fan[attr->index] == 0xffff);
+ return sysfs_emit(buf, "%d\n",
+ data->fan[attr->index] == 0xffff);
}
static ssize_t fan_min_show(struct device *dev,
@@ -285,7 +285,7 @@ static ssize_t fan_min_show(struct device *dev,
if (val < 0)
return val;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t in_show(struct device *dev, struct device_attribute *devattr,
@@ -301,7 +301,7 @@ static ssize_t in_show(struct device *dev, struct device_attribute *devattr,
val = DIV_ROUND_CLOSEST(
data->in[attr->index] * SCH5627_REG_IN_FACTOR[attr->index],
10000);
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t in_label_show(struct device *dev,
@@ -309,8 +309,8 @@ static ssize_t in_label_show(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- return snprintf(buf, PAGE_SIZE, "%s\n",
- SCH5627_IN_LABELS[attr->index]);
+ return sysfs_emit(buf, "%s\n",
+ SCH5627_IN_LABELS[attr->index]);
}
static DEVICE_ATTR_RO(name);
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
index 200bb2bfc986..5683a38740f6 100644
--- a/drivers/hwmon/sch5636.c
+++ b/drivers/hwmon/sch5636.c
@@ -160,7 +160,7 @@ static int reg_to_rpm(u16 reg)
static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
+ return sysfs_emit(buf, "%s\n", DEVNAME);
}
static ssize_t in_value_show(struct device *dev,
@@ -176,7 +176,7 @@ static ssize_t in_value_show(struct device *dev,
val = DIV_ROUND_CLOSEST(
data->in[attr->index] * SCH5636_REG_IN_FACTORS[attr->index],
255);
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t in_label_show(struct device *dev,
@@ -184,8 +184,8 @@ static ssize_t in_label_show(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- return snprintf(buf, PAGE_SIZE, "%s\n",
- SCH5636_IN_LABELS[attr->index]);
+ return sysfs_emit(buf, "%s\n",
+ SCH5636_IN_LABELS[attr->index]);
}
static ssize_t temp_value_show(struct device *dev,
@@ -199,7 +199,7 @@ static ssize_t temp_value_show(struct device *dev,
return PTR_ERR(data);
val = (data->temp_val[attr->index] - 64) * 1000;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t temp_fault_show(struct device *dev,
@@ -213,7 +213,7 @@ static ssize_t temp_fault_show(struct device *dev,
return PTR_ERR(data);
val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_WORKING) ? 0 : 1;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t temp_alarm_show(struct device *dev,
@@ -227,7 +227,7 @@ static ssize_t temp_alarm_show(struct device *dev,
return PTR_ERR(data);
val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_ALARM) ? 1 : 0;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t fan_value_show(struct device *dev,
@@ -244,7 +244,7 @@ static ssize_t fan_value_show(struct device *dev,
if (val < 0)
return val;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t fan_fault_show(struct device *dev,
@@ -258,7 +258,7 @@ static ssize_t fan_fault_show(struct device *dev,
return PTR_ERR(data);
val = (data->fan_ctrl[attr->index] & SCH5636_FAN_NOT_PRESENT) ? 1 : 0;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t fan_alarm_show(struct device *dev,
@@ -272,7 +272,7 @@ static ssize_t fan_alarm_show(struct device *dev,
return PTR_ERR(data);
val = (data->fan_ctrl[attr->index] & SCH5636_FAN_ALARM) ? 1 : 0;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static struct sensor_device_attribute sch5636_attr[] = {
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
index b6cbe9810a1b..62906d9c4b86 100644
--- a/drivers/hwmon/smm665.c
+++ b/drivers/hwmon/smm665.c
@@ -351,7 +351,7 @@ static ssize_t smm665_show_crit_alarm(struct device *dev,
if (data->faults & (1 << attr->index))
val = 1;
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
static ssize_t smm665_show_input(struct device *dev,
@@ -366,7 +366,7 @@ static ssize_t smm665_show_input(struct device *dev,
return PTR_ERR(data);
val = smm665_convert(data->adc[adc], adc);
- return snprintf(buf, PAGE_SIZE, "%d\n", val);
+ return sysfs_emit(buf, "%d\n", val);
}
#define SMM665_SHOW(what) \
diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c
index 6928be6dbe4e..0ed28408aa07 100644
--- a/drivers/hwmon/stts751.c
+++ b/drivers/hwmon/stts751.c
@@ -387,7 +387,7 @@ static ssize_t max_alarm_show(struct device *dev,
if (ret < 0)
return ret;
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->max_alert);
+ return sysfs_emit(buf, "%d\n", priv->max_alert);
}
static ssize_t min_alarm_show(struct device *dev,
@@ -404,7 +404,7 @@ static ssize_t min_alarm_show(struct device *dev,
if (ret < 0)
return ret;
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->min_alert);
+ return sysfs_emit(buf, "%d\n", priv->min_alert);
}
static ssize_t input_show(struct device *dev, struct device_attribute *attr,
@@ -419,7 +419,7 @@ static ssize_t input_show(struct device *dev, struct device_attribute *attr,
if (ret < 0)
return ret;
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->temp);
+ return sysfs_emit(buf, "%d\n", priv->temp);
}
static ssize_t therm_show(struct device *dev, struct device_attribute *attr,
@@ -427,7 +427,7 @@ static ssize_t therm_show(struct device *dev, struct device_attribute *attr,
{
struct stts751_priv *priv = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->therm);
+ return sysfs_emit(buf, "%d\n", priv->therm);
}
static ssize_t therm_store(struct device *dev, struct device_attribute *attr,
@@ -469,7 +469,7 @@ static ssize_t hyst_show(struct device *dev, struct device_attribute *attr,
{
struct stts751_priv *priv = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->hyst);
+ return sysfs_emit(buf, "%d\n", priv->hyst);
}
static ssize_t hyst_store(struct device *dev, struct device_attribute *attr,
@@ -509,7 +509,7 @@ static ssize_t therm_trip_show(struct device *dev,
if (ret < 0)
return ret;
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->therm_trip);
+ return sysfs_emit(buf, "%d\n", priv->therm_trip);
}
static ssize_t max_show(struct device *dev, struct device_attribute *attr,
@@ -517,7 +517,7 @@ static ssize_t max_show(struct device *dev, struct device_attribute *attr,
{
struct stts751_priv *priv = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->event_max);
+ return sysfs_emit(buf, "%d\n", priv->event_max);
}
static ssize_t max_store(struct device *dev, struct device_attribute *attr,
@@ -551,7 +551,7 @@ static ssize_t min_show(struct device *dev, struct device_attribute *attr,
{
struct stts751_priv *priv = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", priv->event_min);
+ return sysfs_emit(buf, "%d\n", priv->event_min);
}
static ssize_t min_store(struct device *dev, struct device_attribute *attr,
@@ -585,8 +585,8 @@ static ssize_t interval_show(struct device *dev,
{
struct stts751_priv *priv = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n",
- stts751_intervals[priv->interval]);
+ return sysfs_emit(buf, "%d\n",
+ stts751_intervals[priv->interval]);
}
static ssize_t interval_store(struct device *dev,
diff --git a/drivers/hwmon/vexpress-hwmon.c b/drivers/hwmon/vexpress-hwmon.c
index e7109657129a..44d798be3d59 100644
--- a/drivers/hwmon/vexpress-hwmon.c
+++ b/drivers/hwmon/vexpress-hwmon.c
@@ -27,7 +27,7 @@ static ssize_t vexpress_hwmon_label_show(struct device *dev,
{
const char *label = of_get_property(dev->of_node, "label", NULL);
- return snprintf(buffer, PAGE_SIZE, "%s\n", label);
+ return sysfs_emit(buffer, "%s\n", label);
}
static ssize_t vexpress_hwmon_u32_show(struct device *dev,
@@ -41,8 +41,8 @@ static ssize_t vexpress_hwmon_u32_show(struct device *dev,
if (err)
return err;
- return snprintf(buffer, PAGE_SIZE, "%u\n", value /
- to_sensor_dev_attr(dev_attr)->index);
+ return sysfs_emit(buffer, "%u\n", value /
+ to_sensor_dev_attr(dev_attr)->index);
}
static ssize_t vexpress_hwmon_u64_show(struct device *dev,
@@ -60,9 +60,9 @@ static ssize_t vexpress_hwmon_u64_show(struct device *dev,
if (err)
return err;
- return snprintf(buffer, PAGE_SIZE, "%llu\n",
- div_u64(((u64)value_hi << 32) | value_lo,
- to_sensor_dev_attr(dev_attr)->index));
+ return sysfs_emit(buffer, "%llu\n",
+ div_u64(((u64)value_hi << 32) | value_lo,
+ to_sensor_dev_attr(dev_attr)->index));
}
static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj,
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 3c1be2c11fdf..e51635590498 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -218,9 +218,14 @@ static u8 fan_to_reg(long rpm, int div)
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
}
-#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
- ((val) == 255 ? 0 : \
- 1350000 / ((val) * (div))))
+static int fan_from_reg(int val, int div)
+{
+ if (val == 0)
+ return -1;
+ if (val == 255)
+ return 0;
+ return 1350000 / (val * div);
+}
/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */
#define TEMP1_FROM_REG(val) ((val) * 1000)
@@ -521,7 +526,7 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
struct w83791d_data *data = w83791d_update_device(dev); \
int nr = sensor_attr->index; \
return sprintf(buf, "%d\n", \
- FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+ fan_from_reg(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
}
show_fan_reg(fan);
@@ -585,10 +590,10 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
if (err)
return err;
+ mutex_lock(&data->update_lock);
/* Save fan_min */
- min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
+ min = fan_from_reg(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
- mutex_lock(&data->update_lock);
data->fan_div[nr] = div_to_reg(nr, val);
switch (nr) {
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 542afff1423b..796ab47d3cb7 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -77,15 +77,25 @@ FAN_TO_REG(long rpm, int div)
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
}
-#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
- ((val) == 255 ? 0 : \
- 1350000 / ((val) * (div))))
+static int fan_from_reg(int val, int div)
+{
+ if (val == 0)
+ return -1;
+ if (val == 255)
+ return 0;
+ return 1350000 / (val * div);
+}
/* for temp */
#define TEMP_TO_REG(val) (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 \
: (val)) / 1000, 0, 0xff))
-#define TEMP_FROM_REG(val) (((val) & 0x80 ? \
- (val) - 0x100 : (val)) * 1000)
+
+static int temp_from_reg(int val)
+{
+ if (val & 0x80)
+ return (val - 0x100) * 1000;
+ return val * 1000;
+}
/*
* The analog voltage inputs have 8mV LSB. Since the sysfs output is
@@ -281,7 +291,7 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
int nr = to_sensor_dev_attr(attr)->index; \
struct w83l786ng_data *data = w83l786ng_update_device(dev); \
return sprintf(buf, "%d\n", \
- FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+ fan_from_reg(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
}
show_fan_reg(fan);
@@ -348,7 +358,7 @@ store_fan_div(struct device *dev, struct device_attribute *attr,
/* Save fan_min */
mutex_lock(&data->update_lock);
- min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
+ min = fan_from_reg(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
data->fan_div[nr] = DIV_TO_REG(val);
@@ -410,7 +420,7 @@ show_temp(struct device *dev, struct device_attribute *attr, char *buf)
int nr = sensor_attr->nr;
int index = sensor_attr->index;
struct w83l786ng_data *data = w83l786ng_update_device(dev);
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index]));
+ return sprintf(buf, "%d\n", temp_from_reg(data->temp[nr][index]));
}
static ssize_t
diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
index 15889bcc8587..29457877dd46 100644
--- a/drivers/hwmon/xgene-hwmon.c
+++ b/drivers/hwmon/xgene-hwmon.c
@@ -329,14 +329,14 @@ static ssize_t temp1_input_show(struct device *dev,
temp = sign_extend32(val, TEMP_NEGATIVE_BIT);
- return snprintf(buf, PAGE_SIZE, "%d\n", CELSIUS_TO_mCELSIUS(temp));
+ return sysfs_emit(buf, "%d\n", CELSIUS_TO_mCELSIUS(temp));
}
static ssize_t temp1_label_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "SoC Temperature\n");
+ return sysfs_emit(buf, "SoC Temperature\n");
}
static ssize_t temp1_critical_alarm_show(struct device *dev,
@@ -345,21 +345,21 @@ static ssize_t temp1_critical_alarm_show(struct device *dev,
{
struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n", ctx->temp_critical_alarm);
+ return sysfs_emit(buf, "%d\n", ctx->temp_critical_alarm);
}
static ssize_t power1_label_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "CPU power\n");
+ return sysfs_emit(buf, "CPU power\n");
}
static ssize_t power2_label_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return snprintf(buf, PAGE_SIZE, "IO power\n");
+ return sysfs_emit(buf, "IO power\n");
}
static ssize_t power1_input_show(struct device *dev,
@@ -374,7 +374,7 @@ static ssize_t power1_input_show(struct device *dev,
if (rc < 0)
return rc;
- return snprintf(buf, PAGE_SIZE, "%u\n", mWATT_TO_uWATT(val));
+ return sysfs_emit(buf, "%u\n", mWATT_TO_uWATT(val));
}
static ssize_t power2_input_show(struct device *dev,
@@ -389,7 +389,7 @@ static ssize_t power2_input_show(struct device *dev,
if (rc < 0)
return rc;
- return snprintf(buf, PAGE_SIZE, "%u\n", mWATT_TO_uWATT(val));
+ return sysfs_emit(buf, "%u\n", mWATT_TO_uWATT(val));
}
static DEVICE_ATTR_RO(temp1_label);
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 9cb8c7d13d46..68af130712bc 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -810,13 +810,17 @@ static int intel_th_output_open(struct inode *inode, struct file *file)
int err;
dev = bus_find_device_by_devt(&intel_th_bus, inode->i_rdev);
- if (!dev || !dev->driver)
- return -ENODEV;
+ if (!dev || !dev->driver) {
+ err = -ENODEV;
+ goto out_no_device;
+ }
thdrv = to_intel_th_driver(dev->driver);
fops = fops_get(thdrv->fops);
- if (!fops)
- return -ENODEV;
+ if (!fops) {
+ err = -ENODEV;
+ goto out_put_device;
+ }
replace_fops(file, fops);
@@ -824,10 +828,16 @@ static int intel_th_output_open(struct inode *inode, struct file *file)
if (file->f_op->open) {
err = file->f_op->open(inode, file);
- return err;
+ if (err)
+ goto out_put_device;
}
return 0;
+
+out_put_device:
+ put_device(dev);
+out_no_device:
+ return err;
}
static const struct file_operations intel_th_output_fops = {
diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c
index cd3fd5ee5f65..a52333d5ee0b 100644
--- a/drivers/i2c/busses/i2c-amd-mp2-pci.c
+++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c
@@ -461,13 +461,16 @@ struct amd_mp2_dev *amd_mp2_find_device(void)
{
struct device *dev;
struct pci_dev *pci_dev;
+ struct amd_mp2_dev *mp2_dev;
dev = driver_find_next_device(&amd_mp2_pci_driver.driver, NULL);
if (!dev)
return NULL;
pci_dev = to_pci_dev(dev);
- return (struct amd_mp2_dev *)pci_get_drvdata(pci_dev);
+ mp2_dev = (struct amd_mp2_dev *)pci_get_drvdata(pci_dev);
+ put_device(dev);
+ return mp2_dev;
}
EXPORT_SYMBOL_GPL(amd_mp2_find_device);
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 203b7497b52d..aff869854ef0 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2536,13 +2536,13 @@ int i3c_master_register(struct i3c_master_controller *master,
INIT_LIST_HEAD(&master->boardinfo.i2c);
INIT_LIST_HEAD(&master->boardinfo.i3c);
- ret = i3c_bus_init(i3cbus);
- if (ret)
- return ret;
-
device_initialize(&master->dev);
dev_set_name(&master->dev, "i3c-%d", i3cbus->id);
+ ret = i3c_bus_init(i3cbus);
+ if (ret)
+ goto err_put_dev;
+
ret = of_populate_i3c_bus(master);
if (ret)
goto err_put_dev;
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index 6cf8c3321d6a..f6df7ed86b4b 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -119,6 +119,13 @@ struct st_lsm6dsx_odr_table_entry {
int odr_len;
};
+struct st_lsm6dsx_samples_to_discard {
+ struct {
+ u32 milli_hz;
+ u16 samples;
+ } val[ST_LSM6DSX_ODR_LIST_SIZE];
+};
+
struct st_lsm6dsx_fs {
u32 gain;
u8 val;
@@ -282,6 +289,7 @@ struct st_lsm6dsx_ext_dev_settings {
* @irq_config: interrupts related registers.
* @drdy_mask: register info for data-ready mask (addr + mask).
* @odr_table: Hw sensors odr table (Hz + val).
+ * @samples_to_discard: Number of samples to discard for filters settling time.
* @fs_table: Hw sensors gain table (gain + val).
* @decimator: List of decimator register info (addr + mask).
* @batch: List of FIFO batching register info (addr + mask).
@@ -315,6 +323,7 @@ struct st_lsm6dsx_settings {
} irq_config;
struct st_lsm6dsx_reg drdy_mask;
struct st_lsm6dsx_odr_table_entry odr_table[2];
+ struct st_lsm6dsx_samples_to_discard samples_to_discard[2];
struct st_lsm6dsx_fs_table_entry fs_table[2];
struct st_lsm6dsx_reg decimator[ST_LSM6DSX_ID_MAX];
struct st_lsm6dsx_reg batch[2];
@@ -335,7 +344,8 @@ enum st_lsm6dsx_fifo_mode {
* @id: Sensor identifier.
* @hw: Pointer to instance of struct st_lsm6dsx_hw.
* @gain: Configured sensor sensitivity.
- * @odr: Output data rate of the sensor [Hz].
+ * @odr: Output data rate of the sensor [mHz].
+ * @samples_to_discard: Number of samples to discard for filters settling time.
* @watermark: Sensor watermark level.
* @decimator: Sensor decimation factor.
* @sip: Number of samples in a given pattern.
@@ -350,6 +360,7 @@ struct st_lsm6dsx_sensor {
u32 gain;
u32 odr;
+ u16 samples_to_discard;
u16 watermark;
u8 decimator;
u8 sip;
@@ -499,6 +510,17 @@ st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev,
return &hw->orientation;
}
+static inline int
+st_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable)
+{
+ if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
+ sensor->id == ST_LSM6DSX_ID_EXT1 ||
+ sensor->id == ST_LSM6DSX_ID_EXT2)
+ return st_lsm6dsx_shub_set_enable(sensor, enable);
+
+ return st_lsm6dsx_sensor_set_enable(sensor, enable);
+}
+
static const
struct iio_chan_spec_ext_info __maybe_unused st_lsm6dsx_accel_ext_info[] = {
IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix),
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index 2e6c634c56c7..29ee52c3036b 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -459,17 +459,31 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
}
if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) {
- iio_push_to_buffers_with_timestamp(
- hw->iio_devs[ST_LSM6DSX_ID_GYRO],
- &hw->scan[ST_LSM6DSX_ID_GYRO],
- gyro_sensor->ts_ref + ts);
+ /*
+ * We need to discards gyro samples during
+ * filters settling time
+ */
+ if (gyro_sensor->samples_to_discard > 0)
+ gyro_sensor->samples_to_discard--;
+ else
+ iio_push_to_buffers_with_timestamp(
+ hw->iio_devs[ST_LSM6DSX_ID_GYRO],
+ &hw->scan[ST_LSM6DSX_ID_GYRO],
+ gyro_sensor->ts_ref + ts);
gyro_sip--;
}
if (acc_sip > 0 && !(sip % acc_sensor->decimator)) {
- iio_push_to_buffers_with_timestamp(
- hw->iio_devs[ST_LSM6DSX_ID_ACC],
- &hw->scan[ST_LSM6DSX_ID_ACC],
- acc_sensor->ts_ref + ts);
+ /*
+ * We need to discards accel samples during
+ * filters settling time
+ */
+ if (acc_sensor->samples_to_discard > 0)
+ acc_sensor->samples_to_discard--;
+ else
+ iio_push_to_buffers_with_timestamp(
+ hw->iio_devs[ST_LSM6DSX_ID_ACC],
+ &hw->scan[ST_LSM6DSX_ID_ACC],
+ acc_sensor->ts_ref + ts);
acc_sip--;
}
if (ext_sip > 0 && !(sip % ext_sensor->decimator)) {
@@ -659,6 +673,30 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
return err;
}
+static void
+st_lsm6dsx_update_samples_to_discard(struct st_lsm6dsx_sensor *sensor)
+{
+ const struct st_lsm6dsx_samples_to_discard *data;
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ int i;
+
+ if (sensor->id != ST_LSM6DSX_ID_GYRO &&
+ sensor->id != ST_LSM6DSX_ID_ACC)
+ return;
+
+ /* check if drdy mask is supported in hw */
+ if (hw->settings->drdy_mask.addr)
+ return;
+
+ data = &hw->settings->samples_to_discard[sensor->id];
+ for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) {
+ if (data->val[i].milli_hz == sensor->odr) {
+ sensor->samples_to_discard = data->val[i].samples;
+ return;
+ }
+ }
+}
+
int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
{
struct st_lsm6dsx_hw *hw = sensor->hw;
@@ -678,17 +716,12 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
goto out;
}
- if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
- sensor->id == ST_LSM6DSX_ID_EXT1 ||
- sensor->id == ST_LSM6DSX_ID_EXT2) {
- err = st_lsm6dsx_shub_set_enable(sensor, enable);
- if (err < 0)
- goto out;
- } else {
- err = st_lsm6dsx_sensor_set_enable(sensor, enable);
- if (err < 0)
- goto out;
- }
+ if (enable)
+ st_lsm6dsx_update_samples_to_discard(sensor);
+
+ err = st_lsm6dsx_device_set_enable(sensor, enable);
+ if (err < 0)
+ goto out;
err = st_lsm6dsx_set_fifo_odr(sensor, enable);
if (err < 0)
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 2c528425b03b..9ee1b29cfc27 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -618,6 +618,24 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
.fs_len = 4,
},
},
+ .samples_to_discard = {
+ [ST_LSM6DSX_ID_ACC] = {
+ .val[0] = { 12500, 1 },
+ .val[1] = { 26000, 1 },
+ .val[2] = { 52000, 1 },
+ .val[3] = { 104000, 2 },
+ .val[4] = { 208000, 2 },
+ .val[5] = { 416000, 2 },
+ },
+ [ST_LSM6DSX_ID_GYRO] = {
+ .val[0] = { 12500, 2 },
+ .val[1] = { 26000, 5 },
+ .val[2] = { 52000, 7 },
+ .val[3] = { 104000, 12 },
+ .val[4] = { 208000, 20 },
+ .val[5] = { 416000, 36 },
+ },
+ },
.irq_config = {
.irq1 = {
.addr = 0x0d,
@@ -2450,12 +2468,7 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
continue;
}
- if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
- sensor->id == ST_LSM6DSX_ID_EXT1 ||
- sensor->id == ST_LSM6DSX_ID_EXT2)
- err = st_lsm6dsx_shub_set_enable(sensor, false);
- else
- err = st_lsm6dsx_sensor_set_enable(sensor, false);
+ err = st_lsm6dsx_device_set_enable(sensor, false);
if (err < 0)
return err;
@@ -2486,12 +2499,7 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev)
if (!(hw->suspend_mask & BIT(sensor->id)))
continue;
- if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
- sensor->id == ST_LSM6DSX_ID_EXT1 ||
- sensor->id == ST_LSM6DSX_ID_EXT2)
- err = st_lsm6dsx_shub_set_enable(sensor, true);
- else
- err = st_lsm6dsx_sensor_set_enable(sensor, true);
+ err = st_lsm6dsx_device_set_enable(sensor, true);
if (err < 0)
return err;
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 779e9af479fd..6e02b8d1abb0 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -81,37 +81,25 @@ static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = {
.min = sizeof(struct rdma_nla_ls_gid)},
};
-static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
+static void ib_nl_process_ip_rsep(const struct nlmsghdr *nlh)
{
struct nlattr *tb[LS_NLA_TYPE_MAX] = {};
+ union ib_gid gid;
+ struct addr_req *req;
+ int found = 0;
int ret;
if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR)
- return false;
+ return;
ret = nla_parse_deprecated(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
nlmsg_len(nlh), ib_nl_addr_policy, NULL);
if (ret)
- return false;
-
- return true;
-}
-
-static void ib_nl_process_good_ip_rsep(const struct nlmsghdr *nlh)
-{
- const struct nlattr *head, *curr;
- union ib_gid gid;
- struct addr_req *req;
- int len, rem;
- int found = 0;
-
- head = (const struct nlattr *)nlmsg_data(nlh);
- len = nlmsg_len(nlh);
+ return;
- nla_for_each_attr(curr, head, len, rem) {
- if (curr->nla_type == LS_NLA_TYPE_DGID)
- memcpy(&gid, nla_data(curr), nla_len(curr));
- }
+ if (!tb[LS_NLA_TYPE_DGID])
+ return;
+ memcpy(&gid, nla_data(tb[LS_NLA_TYPE_DGID]), sizeof(gid));
spin_lock_bh(&lock);
list_for_each_entry(req, &req_list, list) {
@@ -138,8 +126,7 @@ int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
!(NETLINK_CB(skb).sk))
return -EPERM;
- if (ib_nl_is_good_ip_resp(nlh))
- ib_nl_process_good_ip_rsep(nlh);
+ ib_nl_process_ip_rsep(nlh);
return 0;
}
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 0603d069de92..61edd923114e 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1840,6 +1840,7 @@ static void destroy_mc(struct rdma_id_private *id_priv,
ib_sa_free_multicast(mc->sa_mc);
if (rdma_protocol_roce(id_priv->id.device, id_priv->id.port_num)) {
+ struct rdma_cm_event *event = &mc->iboe_join.event;
struct rdma_dev_addr *dev_addr =
&id_priv->id.route.addr.dev_addr;
struct net_device *ndev = NULL;
@@ -1862,6 +1863,8 @@ static void destroy_mc(struct rdma_id_private *id_priv,
dev_put(ndev);
cancel_work_sync(&mc->iboe_join.work);
+ if (event->event == RDMA_CM_EVENT_MULTICAST_JOIN)
+ rdma_destroy_ah_attr(&event->param.ud.ah_attr);
}
kfree(mc);
}
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 3848fe0449a4..82c059cad1c8 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1396,8 +1396,13 @@ int ib_register_device(struct ib_device *device, const char *name,
return ret;
}
dev_set_uevent_suppress(&device->dev, false);
+
+ down_read(&devices_rwsem);
+
/* Mark for userspace that device is ready */
kobject_uevent(&device->dev.kobj, KOBJ_ADD);
+
+ up_read(&devices_rwsem);
ib_device_put(device);
return 0;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 4fcabe5a84be..4a28f30c39f1 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -735,7 +735,7 @@ int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
(struct in6_addr *)dgid);
return 0;
} else if (net_type == RDMA_NETWORK_IPV6 ||
- net_type == RDMA_NETWORK_IB || RDMA_NETWORK_ROCE_V1) {
+ net_type == RDMA_NETWORK_IB || net_type == RDMA_NETWORK_ROCE_V1) {
*dgid = hdr->ibgrh.dgid;
*sgid = hdr->ibgrh.sgid;
return 0;
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 089d7de829a0..5d0c1241b948 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -2647,14 +2647,9 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_ROCE_CRC;
}
- switch (wr->send_flags) {
- case IB_SEND_IP_CSUM:
+ if (wr->send_flags & IB_SEND_IP_CSUM)
wqe.rawqp1.lflags |=
SQ_SEND_RAWETH_QP1_LFLAGS_IP_CHKSUM;
- break;
- default:
- break;
- }
fallthrough;
case IB_WR_SEND_WITH_INV:
rc = bnxt_re_build_send_wqe(qp, wr, &wqe);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index 0d61a1563f48..f9b56744d674 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -775,7 +775,7 @@ static int bnxt_qplib_map_creq_db(struct bnxt_qplib_rcfw *rcfw, u32 reg_offt)
creq_db->reg.bar_id = RCFW_COMM_CONS_PCI_BAR_REGION;
creq_db->reg.bar_base = pci_resource_start(pdev, creq_db->reg.bar_id);
- if (!creq_db->reg.bar_id)
+ if (!creq_db->reg.bar_base)
dev_err(&pdev->dev,
"QPLIB: CREQ BAR region %d resc start is 0!",
creq_db->reg.bar_id);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index be98b23488b4..8547a8512541 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -70,9 +70,7 @@ static void __free_pbl(struct bnxt_qplib_res *res, struct bnxt_qplib_pbl *pbl,
for (i = 0; i < pbl->pg_count; i++) {
if (pbl->pg_arr[i])
dma_free_coherent(&pdev->dev, pbl->pg_size,
- (void *)((unsigned long)
- pbl->pg_arr[i] &
- PAGE_MASK),
+ pbl->pg_arr[i],
pbl->pg_map_arr[i]);
else
dev_warn(&pdev->dev,
@@ -242,7 +240,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
if (npbl % BIT(MAX_PDL_LVL_SHIFT))
npde++;
/* Alloc PDE pages */
- sginfo.pgsize = npde * pg_size;
+ sginfo.pgsize = npde * ROCE_PG_SIZE_4K;
sginfo.npages = 1;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_0], &sginfo);
if (rc)
@@ -250,7 +248,7 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq,
/* Alloc PBL pages */
sginfo.npages = npbl;
- sginfo.pgsize = PAGE_SIZE;
+ sginfo.pgsize = ROCE_PG_SIZE_4K;
rc = __alloc_pbl(res, &hwq->pbl[PBL_LVL_1], &sginfo);
if (rc)
goto fail;
diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index 9cf051818725..d7fccffeeb58 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -1145,13 +1145,9 @@ static int umem_to_page_list(struct efa_dev *dev,
u32 hp_cnt,
u8 hp_shift)
{
- u32 pages_in_hp = BIT(hp_shift - PAGE_SHIFT);
struct ib_block_iter biter;
unsigned int hp_idx = 0;
- ibdev_dbg(&dev->ibdev, "hp_cnt[%u], pages_in_hp[%u]\n",
- hp_cnt, pages_in_hp);
-
rdma_umem_for_each_dma_block(umem, &biter, BIT(hp_shift))
page_list[hp_idx++] = rdma_block_iter_dma_address(&biter);
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index 2b315974f478..3e6f12f98a89 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -1405,7 +1405,7 @@ static struct rtrs_srv *get_or_create_srv(struct rtrs_srv_ctx *ctx,
kfree(srv->chunks);
err_free_srv:
- kfree(srv);
+ put_device(&srv->dev);
return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index 194d899f3ef8..a2a5c3f5c42e 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -1169,6 +1169,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
/*
* A lot of modern Clevo barebones have touchpad and/or keyboard issues
* after suspend fixable with nomux + reset + noloop + nopnp. Luckily,
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 83e685557a19..98e6bfb07717 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -86,7 +86,7 @@ static int titsc_config_wires(struct titsc *ts_dev)
wire_order[i] = ts_dev->config_inp[i] & 0x0F;
if (WARN_ON(analog_line[i] > 7))
return -EINVAL;
- if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
+ if (WARN_ON(wire_order[i] >= ARRAY_SIZE(config_pins)))
return -EINVAL;
}
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 8ac0ac915efd..1ba6adb5b912 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -697,16 +697,11 @@ static void iommu_enable_command_buffer(struct amd_iommu *iommu)
BUG_ON(iommu->cmd_buf == NULL);
- if (!is_kdump_kernel()) {
- /*
- * Command buffer is re-used for kdump kernel and setting
- * of MMIO register is not required.
- */
- entry = iommu_virt_to_phys(iommu->cmd_buf);
- entry |= MMIO_CMD_SIZE_512;
- memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,
- &entry, sizeof(entry));
- }
+ entry = iommu_virt_to_phys(iommu->cmd_buf);
+ entry |= MMIO_CMD_SIZE_512;
+
+ memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,
+ &entry, sizeof(entry));
amd_iommu_reset_cmd_buffer(iommu);
}
@@ -755,15 +750,10 @@ static void iommu_enable_event_buffer(struct amd_iommu *iommu)
BUG_ON(iommu->evt_buf == NULL);
- if (!is_kdump_kernel()) {
- /*
- * Event buffer is re-used for kdump kernel and setting
- * of MMIO register is not required.
- */
- entry = iommu_virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK;
- memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET,
- &entry, sizeof(entry));
- }
+ entry = iommu_virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK;
+
+ memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET,
+ &entry, sizeof(entry));
/* set head and tail to zero manually */
writel(0x00, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index 91d9c4d98f39..af1191a81e29 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -48,17 +48,19 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
/*
* Some platforms support more than the Arm SMMU architected maximum of
- * 128 stream matching groups. For unknown reasons, the additional
- * groups don't exhibit the same behavior as the architected registers,
- * so limit the groups to 128 until the behavior is fixed for the other
- * groups.
+ * 128 stream matching groups. The additional registers appear to have
+ * the same behavior as the architected registers in the hardware.
+ * However, on some firmware versions, the hypervisor does not
+ * correctly trap and emulate accesses to the additional registers,
+ * resulting in unexpected behavior.
+ *
+ * If there are more than 128 groups, use the last reliable group to
+ * detect if we need to apply the bypass quirk.
*/
- if (smmu->num_mapping_groups > 128) {
- dev_notice(smmu->dev, "\tLimiting the stream matching groups to 128\n");
- smmu->num_mapping_groups = 128;
- }
-
- last_s2cr = ARM_SMMU_GR0_S2CR(smmu->num_mapping_groups - 1);
+ if (smmu->num_mapping_groups > 128)
+ last_s2cr = ARM_SMMU_GR0_S2CR(127);
+ else
+ last_s2cr = ARM_SMMU_GR0_S2CR(smmu->num_mapping_groups - 1);
/*
* With some firmware versions writes to S2CR of type FAULT are
@@ -81,6 +83,11 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
reg = FIELD_PREP(ARM_SMMU_CBAR_TYPE, CBAR_TYPE_S1_TRANS_S2_BYPASS);
arm_smmu_gr1_write(smmu, ARM_SMMU_GR1_CBAR(qsmmu->bypass_cbndx), reg);
+
+ if (smmu->num_mapping_groups > 128) {
+ dev_notice(smmu->dev, "\tLimiting the stream matching groups to 128\n");
+ smmu->num_mapping_groups = 128;
+ }
}
for (i = 0; i < smmu->num_mapping_groups; i++) {
diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index 37c8f75a3580..369a34cb75b5 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -586,15 +586,15 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
qcom_iommu = platform_get_drvdata(iommu_pdev);
+ put_device(&iommu_pdev->dev);
+
/* make sure the asid specified in dt is valid, so we don't have
* to sanity check this elsewhere, since 'asid - 1' is used to
* index into qcom_iommu->ctxs:
*/
if (WARN_ON(asid < 1) ||
- WARN_ON(asid > qcom_iommu->num_ctxs)) {
- put_device(&iommu_pdev->dev);
+ WARN_ON(asid > qcom_iommu->num_ctxs))
return -EINVAL;
- }
if (!dev_iommu_priv_get(dev)) {
dev_iommu_priv_set(dev, qcom_iommu);
@@ -603,10 +603,8 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
* multiple different iommu devices. Multiple context
* banks are ok, but multiple devices are not:
*/
- if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev))) {
- put_device(&iommu_pdev->dev);
+ if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev)))
return -EINVAL;
- }
}
return iommu_fwspec_add_ids(dev, &asid, 1);
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 0cdb5493a464..b4c68bb9f515 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1299,17 +1299,14 @@ static int exynos_iommu_of_xlate(struct device *dev,
return -ENODEV;
data = platform_get_drvdata(sysmmu);
- if (!data) {
- put_device(&sysmmu->dev);
+ put_device(&sysmmu->dev);
+ if (!data)
return -ENODEV;
- }
if (!owner) {
owner = kzalloc(sizeof(*owner), GFP_KERNEL);
- if (!owner) {
- put_device(&sysmmu->dev);
+ if (!owner)
return -ENOMEM;
- }
INIT_LIST_HEAD(&owner->controllers);
mutex_init(&owner->rpm_lock);
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index bae6c7078ec9..c64467635a62 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -732,6 +732,8 @@ static int ipmmu_init_platform_device(struct device *dev,
dev_iommu_priv_set(dev, platform_get_drvdata(ipmmu_pdev));
+ put_device(&ipmmu_pdev->dev);
+
return 0;
}
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 051815c9d2bb..d798e9e1105a 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -526,6 +526,8 @@ static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
return -EINVAL;
dev_iommu_priv_set(dev, platform_get_drvdata(m4updev));
+
+ put_device(&m4updev->dev);
}
return iommu_fwspec_add_ids(dev, args->args, 1);
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 2abbdd71d8d9..acb984c4044d 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -393,6 +393,8 @@ static int mtk_iommu_create_mapping(struct device *dev,
return -EINVAL;
dev_iommu_priv_set(dev, platform_get_drvdata(m4updev));
+
+ put_device(&m4updev->dev);
}
ret = iommu_fwspec_add_ids(dev, args->args, 1);
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index ff2c692c0db4..5b08bbf09b65 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1686,6 +1686,7 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev)
}
oiommu = platform_get_drvdata(pdev);
+ put_device(&pdev->dev);
if (!oiommu) {
of_node_put(np);
kfree(arch_data);
@@ -1693,7 +1694,6 @@ static struct iommu_device *omap_iommu_probe_device(struct device *dev)
}
tmp->iommu_dev = oiommu;
- tmp->dev = &pdev->dev;
of_node_put(np);
}
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 18ee713ede78..0411db302e79 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -88,7 +88,6 @@ struct omap_iommu {
/**
* struct omap_iommu_arch_data - omap iommu private data
* @iommu_dev: handle of the OMAP iommu device
- * @dev: handle of the iommu device
*
* This is an omap iommu private data object, which binds an iommu user
* to its iommu device. This object should be placed at the iommu user's
@@ -97,7 +96,6 @@ struct omap_iommu {
*/
struct omap_iommu_arch_data {
struct omap_iommu *iommu_dev;
- struct device *dev;
};
struct cr_regs {
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index f31f66b12366..1a77bd46b458 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -767,6 +767,8 @@ static int sun50i_iommu_of_xlate(struct device *dev,
dev_iommu_priv_set(dev, platform_get_drvdata(iommu_pdev));
+ put_device(&iommu_pdev->dev);
+
return iommu_fwspec_add_ids(dev, &id, 1);
}
diff --git a/drivers/irqchip/qcom-irq-combiner.c b/drivers/irqchip/qcom-irq-combiner.c
index aa54bfcb0433..7783cbdb8dc0 100644
--- a/drivers/irqchip/qcom-irq-combiner.c
+++ b/drivers/irqchip/qcom-irq-combiner.c
@@ -226,7 +226,7 @@ static int get_registers(struct platform_device *pdev, struct combiner *comb)
return 0;
}
-static int __init combiner_probe(struct platform_device *pdev)
+static int combiner_probe(struct platform_device *pdev)
{
struct combiner *combiner;
int nregs;
diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
index 279f3958e0ab..db154a03c675 100644
--- a/drivers/leds/leds-lp50xx.c
+++ b/drivers/leds/leds-lp50xx.c
@@ -53,11 +53,17 @@
#define LP50XX_SW_RESET 0xff
#define LP50XX_CHIP_EN BIT(6)
+#define LP50XX_CHIP_DISABLE 0x00
+#define LP50XX_START_TIME_US 500
+#define LP50XX_RESET_TIME_US 3
+
+#define LP50XX_EN_GPIO_LOW 0
+#define LP50XX_EN_GPIO_HIGH 1
/* There are 3 LED outputs per bank */
#define LP50XX_LEDS_PER_MODULE 3
-#define LP5009_MAX_LED_MODULES 2
+#define LP5009_MAX_LED_MODULES 3
#define LP5012_MAX_LED_MODULES 4
#define LP5018_MAX_LED_MODULES 6
#define LP5024_MAX_LED_MODULES 8
@@ -322,7 +328,7 @@ static int lp50xx_brightness_set(struct led_classdev *cdev,
ret = regmap_write(led->priv->regmap, reg_val, brightness);
if (ret) {
- dev_err(&led->priv->client->dev,
+ dev_err(led->priv->dev,
"Cannot write brightness value %d\n", ret);
goto out;
}
@@ -338,7 +344,7 @@ static int lp50xx_brightness_set(struct led_classdev *cdev,
ret = regmap_write(led->priv->regmap, reg_val,
mc_dev->subled_info[i].intensity);
if (ret) {
- dev_err(&led->priv->client->dev,
+ dev_err(led->priv->dev,
"Cannot write intensity value %d\n", ret);
goto out;
}
@@ -348,17 +354,15 @@ static int lp50xx_brightness_set(struct led_classdev *cdev,
return ret;
}
-static int lp50xx_set_banks(struct lp50xx *priv, u32 led_banks[])
+static int lp50xx_set_banks(struct lp50xx *priv, u32 led_banks[], int num_leds)
{
u8 led_config_lo, led_config_hi;
u32 bank_enable_mask = 0;
int ret;
int i;
- for (i = 0; i < priv->chip_info->max_modules; i++) {
- if (led_banks[i])
- bank_enable_mask |= (1 << led_banks[i]);
- }
+ for (i = 0; i < num_leds; i++)
+ bank_enable_mask |= (1 << led_banks[i]);
led_config_lo = (u8)(bank_enable_mask & 0xff);
led_config_hi = (u8)(bank_enable_mask >> 8) & 0xff;
@@ -378,21 +382,42 @@ static int lp50xx_reset(struct lp50xx *priv)
return regmap_write(priv->regmap, priv->chip_info->reset_reg, LP50XX_SW_RESET);
}
-static int lp50xx_enable_disable(struct lp50xx *priv, int enable_disable)
+static int lp50xx_enable(struct lp50xx *priv)
{
int ret;
if (priv->enable_gpio) {
- ret = gpiod_direction_output(priv->enable_gpio, enable_disable);
+ ret = gpiod_direction_output(priv->enable_gpio, LP50XX_EN_GPIO_HIGH);
if (ret)
return ret;
+
+ udelay(LP50XX_START_TIME_US);
}
- if (enable_disable)
- return regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
- else
- return regmap_write(priv->regmap, LP50XX_DEV_CFG0, 0);
+ ret = lp50xx_reset(priv);
+ if (ret)
+ return ret;
+
+ return regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
+}
+
+static int lp50xx_disable(struct lp50xx *priv)
+{
+ int ret;
+
+ ret = regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_DISABLE);
+ if (ret)
+ return ret;
+
+ if (priv->enable_gpio) {
+ ret = gpiod_direction_output(priv->enable_gpio, LP50XX_EN_GPIO_LOW);
+ if (ret)
+ return ret;
+
+ udelay(LP50XX_RESET_TIME_US);
+ }
+ return 0;
}
static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
@@ -404,7 +429,7 @@ static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
if (num_leds > 1) {
if (num_leds > priv->chip_info->max_modules) {
- dev_err(&priv->client->dev, "reg property is invalid\n");
+ dev_err(priv->dev, "reg property is invalid\n");
return -EINVAL;
}
@@ -412,13 +437,13 @@ static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
ret = fwnode_property_read_u32_array(child, "reg", led_banks, num_leds);
if (ret) {
- dev_err(&priv->client->dev, "reg property is missing\n");
+ dev_err(priv->dev, "reg property is missing\n");
return ret;
}
- ret = lp50xx_set_banks(priv, led_banks);
+ ret = lp50xx_set_banks(priv, led_banks, num_leds);
if (ret) {
- dev_err(&priv->client->dev, "Cannot setup banked LEDs\n");
+ dev_err(priv->dev, "Cannot setup banked LEDs\n");
return ret;
}
@@ -426,12 +451,12 @@ static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
} else {
ret = fwnode_property_read_u32(child, "reg", &led_number);
if (ret) {
- dev_err(&priv->client->dev, "led reg property missing\n");
+ dev_err(priv->dev, "led reg property missing\n");
return ret;
}
if (led_number > priv->chip_info->num_leds) {
- dev_err(&priv->client->dev, "led-sources property is invalid\n");
+ dev_err(priv->dev, "led-sources property is invalid\n");
return -EINVAL;
}
@@ -462,6 +487,10 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
return ret;
}
+ ret = lp50xx_enable(priv);
+ if (ret)
+ return ret;
+
priv->regulator = devm_regulator_get(priv->dev, "vled");
if (IS_ERR(priv->regulator))
priv->regulator = NULL;
@@ -470,7 +499,7 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
led = &priv->leds[i];
ret = fwnode_property_count_u32(child, "reg");
if (ret < 0) {
- dev_err(&priv->client->dev, "reg property is invalid\n");
+ dev_err(priv->dev, "reg property is invalid\n");
goto child_out;
}
@@ -520,12 +549,11 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
led_cdev = &led->mc_cdev.led_cdev;
led_cdev->brightness_set_blocking = lp50xx_brightness_set;
- ret = devm_led_classdev_multicolor_register_ext(&priv->client->dev,
+ ret = devm_led_classdev_multicolor_register_ext(priv->dev,
&led->mc_cdev,
&init_data);
if (ret) {
- dev_err(&priv->client->dev, "led register err: %d\n",
- ret);
+ dev_err(priv->dev, "led register err: %d\n", ret);
goto child_out;
}
i++;
@@ -570,14 +598,6 @@ static int lp50xx_probe(struct i2c_client *client,
return ret;
}
- ret = lp50xx_reset(led);
- if (ret)
- return ret;
-
- ret = lp50xx_enable_disable(led, 1);
- if (ret)
- return ret;
-
return lp50xx_probe_dt(led);
}
@@ -586,17 +606,14 @@ static int lp50xx_remove(struct i2c_client *client)
struct lp50xx *led = i2c_get_clientdata(client);
int ret;
- ret = lp50xx_enable_disable(led, 0);
- if (ret) {
- dev_err(&led->client->dev, "Failed to disable chip\n");
- return ret;
- }
+ ret = lp50xx_disable(led);
+ if (ret)
+ dev_err(led->dev, "Failed to disable chip\n");
if (led->regulator) {
ret = regulator_disable(led->regulator);
if (ret)
- dev_err(&led->client->dev,
- "Failed to disable regulator\n");
+ dev_err(led->dev, "Failed to disable regulator\n");
}
mutex_destroy(&led->lock);
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index c2cc45e19c4b..1083c71fe3bb 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -364,6 +364,9 @@ static int netxbig_gpio_ext_get(struct device *dev,
if (!addr)
return -ENOMEM;
+ gpio_ext->addr = addr;
+ gpio_ext->num_addr = 0;
+
/*
* We cannot use devm_ managed resources with these GPIO descriptors
* since they are associated with the "GPIO extension device" which
@@ -375,45 +378,58 @@ static int netxbig_gpio_ext_get(struct device *dev,
gpiod = gpiod_get_index(gpio_ext_dev, "addr", i,
GPIOD_OUT_LOW);
if (IS_ERR(gpiod))
- return PTR_ERR(gpiod);
+ goto err_set_code;
gpiod_set_consumer_name(gpiod, "GPIO extension addr");
addr[i] = gpiod;
+ gpio_ext->num_addr++;
}
- gpio_ext->addr = addr;
- gpio_ext->num_addr = num_addr;
ret = gpiod_count(gpio_ext_dev, "data");
if (ret < 0) {
dev_err(dev,
"Failed to count GPIOs in DT property data-gpios\n");
- return ret;
+ goto err_free_addr;
}
num_data = ret;
data = devm_kcalloc(dev, num_data, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
+ if (!data) {
+ ret = -ENOMEM;
+ goto err_free_addr;
+ }
+
+ gpio_ext->data = data;
+ gpio_ext->num_data = 0;
for (i = 0; i < num_data; i++) {
gpiod = gpiod_get_index(gpio_ext_dev, "data", i,
GPIOD_OUT_LOW);
if (IS_ERR(gpiod))
- return PTR_ERR(gpiod);
+ goto err_free_data;
gpiod_set_consumer_name(gpiod, "GPIO extension data");
data[i] = gpiod;
+ gpio_ext->num_data++;
}
- gpio_ext->data = data;
- gpio_ext->num_data = num_data;
gpiod = gpiod_get(gpio_ext_dev, "enable", GPIOD_OUT_LOW);
if (IS_ERR(gpiod)) {
dev_err(dev,
"Failed to get GPIO from DT property enable-gpio\n");
- return PTR_ERR(gpiod);
+ goto err_free_data;
}
gpiod_set_consumer_name(gpiod, "GPIO extension enable");
gpio_ext->enable = gpiod;
return devm_add_action_or_reset(dev, netxbig_gpio_ext_remove, gpio_ext);
+
+err_free_data:
+ for (i = 0; i < gpio_ext->num_data; i++)
+ gpiod_put(gpio_ext->data[i]);
+err_set_code:
+ ret = PTR_ERR(gpiod);
+err_free_addr:
+ for (i = 0; i < gpio_ext->num_addr; i++)
+ gpiod_put(gpio_ext->addr[i]);
+ return ret;
}
static int netxbig_leds_get_of_pdata(struct device *dev,
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 28b8581b44dd..b622df9f4b23 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -186,13 +186,14 @@ static int mac_hid_toggle_emumouse(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int *valp = table->data;
- int old_val = *valp;
+ int old_val;
int rc;
rc = mutex_lock_killable(&mac_hid_emumouse_mutex);
if (rc)
return rc;
+ old_val = *valp;
rc = proc_dointvec(table, write, buffer, lenp, ppos);
if (rc == 0 && write && *valp != old_val) {
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c
index f6e142934b77..ecd8782d8158 100644
--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -101,7 +101,7 @@ static int __ebs_rw_bvec(struct ebs_c *ec, int rw, struct bio_vec *bv, struct bv
} else {
flush_dcache_page(bv->bv_page);
memcpy(ba, pa, cur_len);
- dm_bufio_mark_partial_buffer_dirty(b, buf_off, buf_off + cur_len);
+ dm_bufio_mark_buffer_dirty(b);
}
dm_bufio_release(b);
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index e3d35c6c9f71..ec194ed87d62 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -454,6 +454,7 @@ static int log_writes_kthread(void *arg)
struct log_writes_c *lc = (struct log_writes_c *)arg;
sector_t sector = 0;
+ set_freezable();
while (!kthread_should_stop()) {
bool super = false;
bool logging_enabled;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 3c0960f294fb..aa70f668b5cc 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -2259,6 +2259,8 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev)
mddev->reshape_position = le64_to_cpu(sb->reshape_position);
rs->raid_type = get_raid_type_by_ll(mddev->level, mddev->layout);
+ if (!rs->raid_type)
+ return -EINVAL;
}
} else {
diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
index 0a3345e1a0f3..2c58faba5f7b 100644
--- a/drivers/media/cec/core/cec-core.c
+++ b/drivers/media/cec/core/cec-core.c
@@ -433,6 +433,7 @@ static int __init cec_devnode_init(void)
ret = bus_register(&cec_bus_type);
if (ret < 0) {
+ debugfs_remove_recursive(top_cec_dir);
unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES);
pr_warn("cec: bus_register failed\n");
return -EIO;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 202215a69526..9eeb7a4d1f80 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -3561,7 +3561,7 @@ static int adv76xx_probe(struct i2c_client *client,
err = media_entity_pads_init(&sd->entity, state->source_pad + 1,
state->pads);
if (err)
- goto err_work_queues;
+ goto err_i2c;
/* Configure regmaps */
err = configure_regmaps(state);
@@ -3602,8 +3602,6 @@ static int adv76xx_probe(struct i2c_client *client,
err_entity:
media_entity_cleanup(&sd->entity);
-err_work_queues:
- cancel_delayed_work(&state->delayed_work_enable_hotplug);
err_i2c:
adv76xx_unregister_clients(state);
err_hdl:
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 6bd5ffa09bfc..d81ce7a0c8fd 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -2671,6 +2671,7 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
/* CP block */
struct adv7842_state *state = to_state(sd);
struct v4l2_dv_timings timings;
+ int temp;
u8 reg_io_0x02 = io_read(sd, 0x02);
u8 reg_io_0x21 = io_read(sd, 0x21);
u8 reg_rep_0x77 = rep_read(sd, 0x77);
@@ -2793,8 +2794,9 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
(((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
"(16-235)" : "(0-255)",
(reg_io_0x02 & 0x08) ? "enabled" : "disabled");
+ temp = cp_read(sd, 0xf4) >> 4;
v4l2_info(sd, "Color space conversion: %s\n",
- csc_coeff_sel_rb[cp_read(sd, 0xf4) >> 4]);
+ temp < 0 ? "" : csc_coeff_sel_rb[temp]);
if (!is_digital_input(sd))
return 0;
@@ -2824,8 +2826,9 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
hdmi_read(sd, 0x5f));
v4l2_info(sd, "AV Mute: %s\n",
(hdmi_read(sd, 0x04) & 0x40) ? "on" : "off");
+ temp = hdmi_read(sd, 0x0b) >> 6;
v4l2_info(sd, "Deep color mode: %s\n",
- deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]);
+ temp < 0 ? "" : deep_color_mode_txt[temp]);
adv7842_log_infoframes(sd);
@@ -3549,7 +3552,7 @@ static int adv7842_probe(struct i2c_client *client,
state->pad.flags = MEDIA_PAD_FL_SOURCE;
err = media_entity_pads_init(&sd->entity, 1, &state->pad);
if (err)
- goto err_work_queues;
+ goto err_i2c;
err = adv7842_core_init(sd);
if (err)
@@ -3570,8 +3573,6 @@ static int adv7842_probe(struct i2c_client *client,
err_entity:
media_entity_cleanup(&sd->entity);
-err_work_queues:
- cancel_delayed_work(&state->delayed_work_enable_hotplug);
err_i2c:
adv7842_unregister_clients(sd);
err_hdl:
diff --git a/drivers/media/i2c/msp3400-kthreads.c b/drivers/media/i2c/msp3400-kthreads.c
index 52e506f86de5..fd9733458908 100644
--- a/drivers/media/i2c/msp3400-kthreads.c
+++ b/drivers/media/i2c/msp3400-kthreads.c
@@ -592,6 +592,8 @@ int msp3400c_thread(void *data)
"carrier2 val: %5d / %s\n", val, cd[i].name);
}
+ if (max1 < 0 || max1 > 3)
+ goto restart;
/* program the msp3400 according to the results */
state->main = msp3400c_carrier_detect_main[max1].cdo;
switch (max1) {
diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c
index 8476330964fc..d79221e31841 100644
--- a/drivers/media/i2c/tda1997x.c
+++ b/drivers/media/i2c/tda1997x.c
@@ -2779,7 +2779,6 @@ static int tda1997x_probe(struct i2c_client *client,
err_free_handler:
v4l2_ctrl_handler_free(&state->hdl);
err_free_mutex:
- cancel_delayed_work(&state->delayed_work_enable_hpd);
mutex_destroy(&state->page_lock);
mutex_destroy(&state->lock);
err_free_state:
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 72a0e94e2e21..f90de09c1485 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -1614,7 +1614,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
* This creates device entries by register itself to the V4L2 driver and
* initializes fields of each channel objects
*/
-static __init int vpif_probe(struct platform_device *pdev)
+static int vpif_probe(struct platform_device *pdev)
{
struct vpif_subdev_info *subdevdata;
struct i2c_adapter *i2c_adap;
@@ -1817,7 +1817,7 @@ static int vpif_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume);
-static __refdata struct platform_driver vpif_driver = {
+static struct platform_driver vpif_driver = {
.driver = {
.name = VPIF_DRIVER_NAME,
.pm = &vpif_pm_ops,
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index bd37011fb671..2ae2a0aada0d 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -1409,12 +1409,14 @@ static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
mutex_lock(&fmd->media_dev.graph_mutex);
ret = fimc_md_create_links(fmd);
- if (ret < 0)
- goto unlock;
+ if (ret < 0) {
+ mutex_unlock(&fmd->media_dev.graph_mutex);
+ return ret;
+ }
- ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
-unlock:
mutex_unlock(&fmd->media_dev.graph_mutex);
+
+ ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
if (ret < 0)
return ret;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
index 1ec29f1b163a..84efc824d267 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
@@ -94,8 +94,10 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id);
fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
- if (!fw)
+ if (!fw) {
+ put_device(&fw_pdev->dev);
return ERR_PTR(-ENOMEM);
+ }
fw->type = VPU;
fw->ops = &mtk_vcodec_vpu_msg;
fw->pdev = fw_pdev;
diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c
index 083dba95beaa..c5161c39c045 100644
--- a/drivers/media/platform/rcar_drif.c
+++ b/drivers/media/platform/rcar_drif.c
@@ -1253,6 +1253,7 @@ static struct device_node *rcar_drif_bond_enabled(struct platform_device *p)
if (np && of_device_is_available(np))
return np;
+ of_node_put(np);
return NULL;
}
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
index 3237fef5d502..f5182ffd9bcb 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -279,7 +279,7 @@ static int st_rc_probe(struct platform_device *pdev)
else
rc_dev->rx_base = rc_dev->base;
- rc_dev->rstc = reset_control_get_optional_exclusive(dev, NULL);
+ rc_dev->rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(rc_dev->rstc)) {
ret = PTR_ERR(rc_dev->rstc);
goto err;
diff --git a/drivers/media/test-drivers/vidtv/vidtv_channel.c b/drivers/media/test-drivers/vidtv/vidtv_channel.c
index f3023e91b3eb..3541155c6fc6 100644
--- a/drivers/media/test-drivers/vidtv/vidtv_channel.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_channel.c
@@ -461,12 +461,15 @@ int vidtv_channel_si_init(struct vidtv_mux *m)
/* assemble all programs and assign to PAT */
vidtv_psi_pat_program_assign(m->si.pat, programs);
+ programs = NULL;
/* assemble all services and assign to SDT */
vidtv_psi_sdt_service_assign(m->si.sdt, services);
+ services = NULL;
/* assemble all events and assign to EIT */
vidtv_psi_eit_event_assign(m->si.eit, events);
+ events = NULL;
m->si.pmt_secs = vidtv_psi_pmt_create_sec_for_each_pat_entry(m->si.pat,
m->pcr_pid);
diff --git a/drivers/media/usb/dvb-usb/dtv5100.c b/drivers/media/usb/dvb-usb/dtv5100.c
index 1c13e493322c..89b3a5a790d8 100644
--- a/drivers/media/usb/dvb-usb/dtv5100.c
+++ b/drivers/media/usb/dvb-usb/dtv5100.c
@@ -55,6 +55,11 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
}
index = (addr << 8) + wbuf[0];
+ if (rlen > sizeof(st->data)) {
+ warn("rlen = %x is too big!\n", rlen);
+ return -EINVAL;
+ }
+
memcpy(st->data, rbuf, rlen);
msleep(1); /* avoid I2C errors */
return usb_control_msg(d->udev, pipe, request,
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index d22ce328a279..10c21580a827 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -3617,7 +3617,7 @@ static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
pvr2_trace(
PVR2_TRACE_ERROR_LEGS,
"Attempted to execute %d byte control-read transfer (limit=%d)",
- write_len,PVR2_CTL_BUFFSIZE);
+ read_len, PVR2_CTL_BUFFSIZE);
return -EINVAL;
}
if ((!write_len) && (!read_len)) {
diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c
index 59efe7d5dcaa..5fe7473f0474 100644
--- a/drivers/mfd/altera-sysmgr.c
+++ b/drivers/mfd/altera-sysmgr.c
@@ -118,6 +118,8 @@ struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
sysmgr = dev_get_drvdata(dev);
+ put_device(dev);
+
return sysmgr->regmap;
}
EXPORT_SYMBOL_GPL(altr_sysmgr_regmap_lookup_by_phandle);
diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
index 6d0af8486269..4f57766b4249 100644
--- a/drivers/mfd/da9055-core.c
+++ b/drivers/mfd/da9055-core.c
@@ -410,6 +410,7 @@ int da9055_device_init(struct da9055 *da9055)
err:
mfd_remove_devices(da9055->dev);
+ regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
return ret;
}
diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c
index a6661e07035b..e3a1afa19389 100644
--- a/drivers/mfd/max77620.c
+++ b/drivers/mfd/max77620.c
@@ -254,7 +254,7 @@ static int max77620_irq_global_unmask(void *irq_drv_data)
return ret;
}
-static struct regmap_irq_chip max77620_top_irq_chip = {
+static const struct regmap_irq_chip max77620_top_irq_chip = {
.name = "max77620-top",
.irqs = max77620_top_irqs,
.num_irqs = ARRAY_SIZE(max77620_top_irqs),
@@ -499,6 +499,7 @@ static int max77620_probe(struct i2c_client *client,
{
const struct regmap_config *rmap_config;
struct max77620_chip *chip;
+ struct regmap_irq_chip *chip_desc;
const struct mfd_cell *mfd_cells;
int n_mfd_cells;
bool pm_off;
@@ -509,6 +510,14 @@ static int max77620_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, chip);
+
+ chip_desc = devm_kmemdup(&client->dev, &max77620_top_irq_chip,
+ sizeof(max77620_top_irq_chip),
+ GFP_KERNEL);
+ if (!chip_desc)
+ return -ENOMEM;
+ chip_desc->irq_drv_data = chip;
+
chip->dev = &client->dev;
chip->chip_irq = client->irq;
chip->chip_id = (enum max77620_chip_id)id->driver_data;
@@ -545,11 +554,9 @@ static int max77620_probe(struct i2c_client *client,
if (ret < 0)
return ret;
- max77620_top_irq_chip.irq_drv_data = chip;
ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
IRQF_ONESHOT | IRQF_SHARED, 0,
- &max77620_top_irq_chip,
- &chip->top_irq_data);
+ chip_desc, &chip->top_irq_data);
if (ret < 0) {
dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret);
return ret;
diff --git a/drivers/mfd/mt6358-irq.c b/drivers/mfd/mt6358-irq.c
index db734f2831ff..db89da7b98f1 100644
--- a/drivers/mfd/mt6358-irq.c
+++ b/drivers/mfd/mt6358-irq.c
@@ -227,6 +227,7 @@ int mt6358_irq_init(struct mt6397_chip *chip)
if (ret) {
dev_err(chip->dev, "Failed to register IRQ=%d, ret=%d\n",
chip->irq, ret);
+ irq_domain_remove(chip->irq_domain);
return ret;
}
diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c
index 2924919da991..e1daed7edc84 100644
--- a/drivers/mfd/mt6397-irq.c
+++ b/drivers/mfd/mt6397-irq.c
@@ -206,6 +206,7 @@ int mt6397_irq_init(struct mt6397_chip *chip)
if (ret) {
dev_err(chip->dev, "failed to register irq=%d; err: %d\n",
chip->irq, ret);
+ irq_domain_remove(chip->irq_domain);
return ret;
}
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index b31b6dc9c38a..159a68db61e4 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -122,6 +122,8 @@
#define MEI_DEV_ID_WCL_P 0x4D70 /* Wildcat Lake P */
+#define MEI_DEV_ID_NVL_S 0x6E68 /* Nova Lake Point S */
+
/*
* MEI HW Section
*/
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index a9bc13570bae..c03ca7c466ee 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -128,6 +128,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_WCL_P, MEI_ME_PCH15_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_NVL_S, MEI_ME_PCH15_CFG)},
+
/* required last entry */
{0, }
};
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index b837e7eba5f7..be1004a31664 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -1810,8 +1810,7 @@ static int vmballoon_migratepage(struct balloon_dev_info *b_dev_info,
* @pages_lock . We keep holding @comm_lock since we will need it in a
* second.
*/
- balloon_page_delete(page);
-
+ balloon_page_finalize(page);
put_page(page);
/* Inflate */
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index ee063baed136..5c39c9c65323 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -79,7 +79,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
mutex_init(&shared[i].lock);
for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
*chip = lpddr->chips[i];
- chip->start += j << lpddr->chipshift;
+ chip->start += (unsigned long)j << lpddr->chipshift;
chip->oldstate = chip->state = FL_READY;
chip->priv = &shared[i];
/* those should be reset too since
@@ -562,7 +562,7 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
break;
if ((len + ofs - 1) >> lpddr->chipshift)
- thislen = (1<<lpddr->chipshift) - ofs;
+ thislen = (1UL << lpddr->chipshift) - ofs;
else
thislen = len;
/* get the chip */
@@ -578,7 +578,7 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
len -= thislen;
ofs = 0;
- last_end += 1 << lpddr->chipshift;
+ last_end += 1UL << lpddr->chipshift;
chipnum++;
chip = &lpddr->chips[chipnum];
}
@@ -604,7 +604,7 @@ static int lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
break;
if ((len + ofs - 1) >> lpddr->chipshift)
- thislen = (1<<lpddr->chipshift) - ofs;
+ thislen = (1UL << lpddr->chipshift) - ofs;
else
thislen = len;
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 416ed1ca1d52..b80e4216f98c 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1761,6 +1761,9 @@ static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
if (!ent->is_valid)
return 0;
+ if (is_multicast_ether_addr(ent->mac))
+ return 0;
+
if (port != ent->port)
return 0;
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 741c67e546d4..822208dac22c 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1471,7 +1471,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
return 0;
free_ring:
- dma_free_coherent(&pdev->dev,
+ dma_free_coherent(gendev,
sizeof(struct boom_rx_desc) * RX_RING_SIZE +
sizeof(struct boom_tx_desc) * TX_RING_SIZE,
vp->rx_ring, vp->rx_ring_dma);
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 7ad9a4715691..f29a38675afb 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -1809,6 +1809,9 @@ static int b44_nway_reset(struct net_device *dev)
u32 bmcr;
int r;
+ if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+ return phy_ethtool_nway_reset(dev);
+
spin_lock_irq(&bp->lock);
b44_readphy(bp, MII_BMCR, &bmcr);
b44_readphy(bp, MII_BMCR, &bmcr);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 40c53404bccb..fd54a194a5e5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -330,6 +330,38 @@ static void bnxt_db_cq(struct bnxt *bp, struct bnxt_db_info *db, u32 idx)
BNXT_DB_CQ(db, idx);
}
+static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay)
+{
+ if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)))
+ return;
+
+ if (BNXT_PF(bp))
+ queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay);
+ else
+ schedule_delayed_work(&bp->fw_reset_task, delay);
+}
+
+static void bnxt_queue_sp_work(struct bnxt *bp)
+{
+ if (BNXT_PF(bp))
+ queue_work(bnxt_pf_wq, &bp->sp_task);
+ else
+ schedule_work(&bp->sp_task);
+}
+
+static void bnxt_sched_reset_rxr(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
+{
+ if (!rxr->bnapi->in_reset) {
+ rxr->bnapi->in_reset = true;
+ if (bp->flags & BNXT_FLAG_CHIP_P5)
+ set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
+ else
+ set_bit(BNXT_RST_RING_SP_EVENT, &bp->sp_event);
+ bnxt_queue_sp_work(bp);
+ }
+ rxr->rx_next_cons = 0xffff;
+}
+
const u16 bnxt_lhint_arr[] = {
TX_BD_FLAGS_LHINT_512_AND_SMALLER,
TX_BD_FLAGS_LHINT_512_TO_1023,
@@ -1181,46 +1213,16 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
return 0;
}
-static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay)
-{
- if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)))
- return;
-
- if (BNXT_PF(bp))
- queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay);
- else
- schedule_delayed_work(&bp->fw_reset_task, delay);
-}
-
-static void bnxt_queue_sp_work(struct bnxt *bp)
-{
- if (BNXT_PF(bp))
- queue_work(bnxt_pf_wq, &bp->sp_task);
- else
- schedule_work(&bp->sp_task);
-}
-
-static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
-{
- if (!rxr->bnapi->in_reset) {
- rxr->bnapi->in_reset = true;
- if (bp->flags & BNXT_FLAG_CHIP_P5)
- set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event);
- else
- set_bit(BNXT_RST_RING_SP_EVENT, &bp->sp_event);
- bnxt_queue_sp_work(bp);
- }
- rxr->rx_next_cons = 0xffff;
-}
-
static u16 bnxt_alloc_agg_idx(struct bnxt_rx_ring_info *rxr, u16 agg_id)
{
struct bnxt_tpa_idx_map *map = rxr->rx_tpa_idx_map;
u16 idx = agg_id & MAX_TPA_P5_MASK;
- if (test_bit(idx, map->agg_idx_bmap))
- idx = find_first_zero_bit(map->agg_idx_bmap,
- BNXT_AGG_IDX_BMAP_SIZE);
+ if (test_bit(idx, map->agg_idx_bmap)) {
+ idx = find_first_zero_bit(map->agg_idx_bmap, MAX_TPA_P5);
+ if (idx >= MAX_TPA_P5)
+ return INVALID_HW_RING_ID;
+ }
__set_bit(idx, map->agg_idx_bmap);
map->agg_id_tbl[agg_id] = idx;
return idx;
@@ -1253,6 +1255,13 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
if (bp->flags & BNXT_FLAG_CHIP_P5) {
agg_id = TPA_START_AGG_ID_P5(tpa_start);
agg_id = bnxt_alloc_agg_idx(rxr, agg_id);
+ if (unlikely(agg_id == INVALID_HW_RING_ID)) {
+ netdev_warn(bp->dev, "Unable to allocate agg ID for ring %d, agg 0x%x\n",
+ rxr->bnapi->index,
+ TPA_START_AGG_ID_P5(tpa_start));
+ bnxt_sched_reset_rxr(bp, rxr);
+ return;
+ }
} else {
agg_id = TPA_START_AGG_ID(tpa_start);
}
@@ -1267,7 +1276,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
netdev_warn(bp->dev, "TPA cons %x, expected cons %x, error code %x\n",
cons, rxr->rx_next_cons,
TPA_START_ERROR_CODE(tpa_start1));
- bnxt_sched_reset(bp, rxr);
+ bnxt_sched_reset_rxr(bp, rxr);
return;
}
/* Store cfa_code in tpa_info to use in tpa_end
@@ -1785,7 +1794,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
if (rxr->rx_next_cons != 0xffff)
netdev_warn(bp->dev, "RX cons %x != expected cons %x\n",
cons, rxr->rx_next_cons);
- bnxt_sched_reset(bp, rxr);
+ bnxt_sched_reset_rxr(bp, rxr);
if (rc1)
return rc1;
goto next_rx_no_prod_no_len;
@@ -1823,7 +1832,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
!(bp->fw_cap & BNXT_FW_CAP_RING_MONITOR)) {
netdev_warn_once(bp->dev, "RX buffer error %x\n",
rx_err);
- bnxt_sched_reset(bp, rxr);
+ bnxt_sched_reset_rxr(bp, rxr);
}
}
goto next_rx_no_len;
@@ -2165,7 +2174,7 @@ static int bnxt_async_event_process(struct bnxt *bp,
goto async_event_process_exit;
}
rxr = bp->bnapi[grp_idx]->rx_ring;
- bnxt_sched_reset(bp, rxr);
+ bnxt_sched_reset_rxr(bp, rxr);
goto async_event_process_exit;
}
default:
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index b7b07beb17ff..c2122d5cda62 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -870,11 +870,9 @@ struct bnxt_tpa_info {
struct rx_agg_cmp *agg_arr;
};
-#define BNXT_AGG_IDX_BMAP_SIZE (MAX_TPA_P5 / BITS_PER_LONG)
-
struct bnxt_tpa_idx_map {
u16 agg_id_tbl[1024];
- unsigned long agg_idx_bmap[BNXT_AGG_IDX_BMAP_SIZE];
+ DECLARE_BITMAP(agg_idx_bmap, MAX_TPA_P5);
};
struct bnxt_rx_ring_info {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index aa987cad7cad..99b5b956ed8f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -9196,6 +9196,9 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
bool writen_to_tbl = false;
int ret = 0;
+ if (vlan_id >= VLAN_N_VID)
+ return -EINVAL;
+
/* When device is resetting or reset failed, firmware is unable to
* handle mailbox. Just record the vlan id, and remove it after
* reset finished.
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index 15dca78fd736..98abb47014b7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -434,12 +434,12 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
new_tqps = kinfo->rss_size * num_tc;
kinfo->num_tqps = min(new_tqps, hdev->num_tqps);
- kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps,
+ kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps,
sizeof(struct hnae3_queue *), GFP_KERNEL);
if (!kinfo->tqp)
return -ENOMEM;
- for (i = 0; i < kinfo->num_tqps; i++) {
+ for (i = 0; i < hdev->num_tqps; i++) {
hdev->htqp[i].q.handle = &hdev->nic;
hdev->htqp[i].q.tqp_index = i;
kinfo->tqp[i] = &hdev->htqp[i].q;
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 5e28cf4fa2cd..0b7502902913 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -4090,7 +4090,15 @@ static bool e1000_tbi_should_accept(struct e1000_adapter *adapter,
u32 length, const u8 *data)
{
struct e1000_hw *hw = &adapter->hw;
- u8 last_byte = *(data + length - 1);
+ u8 last_byte;
+
+ /* Guard against OOB on data[length - 1] */
+ if (unlikely(!length))
+ return false;
+ /* Upper bound: length must not exceed rx_buffer_len */
+ if (unlikely(length > adapter->rx_buffer_len))
+ return false;
+ last_byte = *(data + length - 1);
if (TBI_ACCEPT(hw, status, errors, length, last_byte)) {
unsigned long irq_flags;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index f11cb3176cab..f11d6166186f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -2101,6 +2101,7 @@ static void i40e_set_rx_mode(struct net_device *netdev)
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->back->state);
}
+ i40e_service_event_schedule(vsi->back);
}
/**
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 65259722a572..4ed93c7f81d2 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -1262,11 +1262,11 @@ static int iavf_config_rss_reg(struct iavf_adapter *adapter)
u16 i;
dw = (u32 *)adapter->rss_key;
- for (i = 0; i <= adapter->rss_key_size / 4; i++)
+ for (i = 0; i < adapter->rss_key_size / 4; i++)
wr32(hw, IAVF_VFQF_HKEY(i), dw[i]);
dw = (u32 *)adapter->rss_lut;
- for (i = 0; i <= adapter->rss_lut_size / 4; i++)
+ for (i = 0; i < adapter->rss_lut_size / 4; i++)
wr32(hw, IAVF_VFQF_HLUT(i), dw[i]);
iavf_flush(hw);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
index 9b6938dde267..6e547e177511 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
@@ -382,6 +382,14 @@ static int otx2_set_ringparam(struct net_device *netdev,
*/
if (rx_count < pfvf->hw.rq_skid)
rx_count = pfvf->hw.rq_skid;
+
+ if (ring->rx_pending < 16) {
+ netdev_err(netdev,
+ "rx ring size %u invalid, min is 16\n",
+ ring->rx_pending);
+ return -EINVAL;
+ }
+
rx_count = Q_COUNT(Q_SIZE(rx_count, 3));
/* Due pipelining impact minimum 2000 unused SQ CQE's
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
index d49fd21f4963..f3985421e739 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
@@ -33,6 +33,7 @@
#include "lib/eq.h"
#include "fw_tracer.h"
#include "fw_tracer_tracepoint.h"
+#include <linux/ctype.h>
static int mlx5_query_mtrc_caps(struct mlx5_fw_tracer *tracer)
{
@@ -354,6 +355,47 @@ static const char *VAL_PARM = "%llx";
static const char *REPLACE_64_VAL_PARM = "%x%x";
static const char *PARAM_CHAR = "%";
+static bool mlx5_is_valid_spec(const char *str)
+{
+ /* Parse format specifiers to find the actual type.
+ * Structure: %[flags][width][.precision][length]type
+ * Skip flags, width, precision & length.
+ */
+ while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l')
+ str++;
+
+ /* Check if it's a valid integer/hex specifier or %%:
+ * Valid formats: %x, %d, %i, %u, etc.
+ */
+ if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' &&
+ *str != 'u' && *str != 'c' && *str != '%')
+ return false;
+
+ return true;
+}
+
+static bool mlx5_tracer_validate_params(const char *str)
+{
+ const char *substr = str;
+
+ if (!str)
+ return false;
+
+ substr = strstr(substr, PARAM_CHAR);
+ while (substr) {
+ if (!mlx5_is_valid_spec(substr + 1))
+ return false;
+
+ if (*(substr + 1) == '%')
+ substr = strstr(substr + 2, PARAM_CHAR);
+ else
+ substr = strstr(substr + 1, PARAM_CHAR);
+
+ }
+
+ return true;
+}
+
static int mlx5_tracer_message_hash(u32 message_id)
{
return jhash_1word(message_id, 0) & (MESSAGE_HASH_SIZE - 1);
@@ -413,6 +455,10 @@ static int mlx5_tracer_get_num_of_params(char *str)
char *substr, *pstr = str;
int num_of_params = 0;
+ /* Validate that all parameters are valid before processing */
+ if (!mlx5_tracer_validate_params(str))
+ return -EINVAL;
+
/* replace %llx with %x%x */
substr = strstr(pstr, VAL_PARM);
while (substr) {
@@ -421,11 +467,15 @@ static int mlx5_tracer_get_num_of_params(char *str)
substr = strstr(pstr, VAL_PARM);
}
- /* count all the % characters */
+ /* count all the % characters, but skip %% (escaped percent) */
substr = strstr(str, PARAM_CHAR);
while (substr) {
- num_of_params += 1;
- str = substr + 1;
+ if (*(substr + 1) != '%') {
+ num_of_params += 1;
+ str = substr + 1;
+ } else {
+ str = substr + 2;
+ }
substr = strstr(str, PARAM_CHAR);
}
@@ -460,6 +510,7 @@ static void poll_trace(struct mlx5_fw_tracer *tracer,
tracer_event->event_id = MLX5_GET(tracer_event, trace, event_id);
tracer_event->lost_event = MLX5_GET(tracer_event, trace, lost);
+ tracer_event->out = trace;
switch (tracer_event->event_id) {
case TRACER_EVENT_TYPE_TIMESTAMP:
@@ -563,14 +614,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt,
{
char tmp[512];
- snprintf(tmp, sizeof(tmp), str_frmt->string,
- str_frmt->params[0],
- str_frmt->params[1],
- str_frmt->params[2],
- str_frmt->params[3],
- str_frmt->params[4],
- str_frmt->params[5],
- str_frmt->params[6]);
+ if (str_frmt->invalid_string)
+ snprintf(tmp, sizeof(tmp), "BAD_FORMAT: %s", str_frmt->string);
+ else
+ snprintf(tmp, sizeof(tmp), str_frmt->string,
+ str_frmt->params[0],
+ str_frmt->params[1],
+ str_frmt->params[2],
+ str_frmt->params[3],
+ str_frmt->params[4],
+ str_frmt->params[5],
+ str_frmt->params[6]);
trace_mlx5_fw(dev->tracer, trace_timestamp, str_frmt->lost,
str_frmt->event_id, tmp);
@@ -582,6 +636,33 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt,
mlx5_tracer_clean_message(str_frmt);
}
+static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer,
+ struct tracer_event *tracer_event)
+{
+ struct tracer_string_format *cur_string;
+
+ cur_string = mlx5_tracer_message_insert(tracer, tracer_event);
+ if (!cur_string)
+ return -1;
+
+ cur_string->event_id = tracer_event->event_id;
+ cur_string->timestamp = tracer_event->string_event.timestamp;
+ cur_string->lost = tracer_event->lost_event;
+ cur_string->string = "0x%08x%08x";
+ cur_string->num_of_params = 2;
+ cur_string->params[0] = upper_32_bits(*tracer_event->out);
+ cur_string->params[1] = lower_32_bits(*tracer_event->out);
+ list_add_tail(&cur_string->list, &tracer->ready_strings_list);
+ return 0;
+}
+
+static void mlx5_tracer_handle_bad_format_string(struct mlx5_fw_tracer *tracer,
+ struct tracer_string_format *cur_string)
+{
+ cur_string->invalid_string = true;
+ list_add_tail(&cur_string->list, &tracer->ready_strings_list);
+}
+
static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
struct tracer_event *tracer_event)
{
@@ -590,14 +671,20 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
if (tracer_event->string_event.tdsn == 0) {
cur_string = mlx5_tracer_get_string(tracer, tracer_event);
if (!cur_string)
- return -1;
+ return mlx5_tracer_handle_raw_string(tracer, tracer_event);
- cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string);
- cur_string->last_param_num = 0;
cur_string->event_id = tracer_event->event_id;
cur_string->tmsn = tracer_event->string_event.tmsn;
cur_string->timestamp = tracer_event->string_event.timestamp;
cur_string->lost = tracer_event->lost_event;
+ cur_string->last_param_num = 0;
+ cur_string->num_of_params = mlx5_tracer_get_num_of_params(cur_string->string);
+ if (cur_string->num_of_params < 0) {
+ pr_debug("%s Invalid format string parameters\n",
+ __func__);
+ mlx5_tracer_handle_bad_format_string(tracer, cur_string);
+ return 0;
+ }
if (cur_string->num_of_params == 0) /* trace with no params */
list_add_tail(&cur_string->list, &tracer->ready_strings_list);
} else {
@@ -605,7 +692,12 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
if (!cur_string) {
pr_debug("%s Got string event for unknown string tmsn: %d\n",
__func__, tracer_event->string_event.tmsn);
- return -1;
+ return mlx5_tracer_handle_raw_string(tracer, tracer_event);
+ }
+ if (cur_string->num_of_params < 0) {
+ pr_debug("%s string parameter of invalid string, dumping\n",
+ __func__);
+ return 0;
}
cur_string->last_param_num += 1;
if (cur_string->last_param_num > TRACER_MAX_PARAMS) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h
index 97252a85d65e..603ef441f1b2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h
@@ -117,6 +117,7 @@ struct tracer_string_format {
struct list_head list;
u32 timestamp;
bool lost;
+ bool invalid_string;
};
enum mlx5_fw_tracer_ownership_state {
@@ -158,6 +159,7 @@ struct tracer_event {
struct tracer_string_event string_event;
struct tracer_timestamp_event timestamp_event;
};
+ u64 *out;
};
struct mlx5_ifc_tracer_event_bits {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index b0229ceae234..f41dc9bb3660 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -199,7 +199,7 @@ static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
struct mlx5e_tx_wqe {
struct mlx5_wqe_ctrl_seg ctrl;
struct mlx5_wqe_eth_seg eth;
- struct mlx5_wqe_data_seg data[0];
+ struct mlx5_wqe_data_seg data[];
};
struct mlx5e_rx_wqe_ll {
@@ -215,7 +215,7 @@ struct mlx5e_umr_wqe {
struct mlx5_wqe_ctrl_seg ctrl;
struct mlx5_wqe_umr_ctrl_seg uctrl;
struct mlx5_mkey_seg mkc;
- struct mlx5_mtt inline_mtts[0];
+ struct mlx5_mtt inline_mtts[];
};
extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
index ae90d533a350..923e10d06f3d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
@@ -341,8 +341,10 @@ mlx5e_xmit_xdp_frame(struct mlx5e_xdpsq *sq, struct mlx5e_xmit_data *xdptxd,
/* copy the inline part if required */
if (sq->min_inline_mode != MLX5_INLINE_MODE_NONE) {
- memcpy(eseg->inline_hdr.start, xdptxd->data, MLX5E_XDP_MIN_INLINE);
+ memcpy(eseg->inline_hdr.start, xdptxd->data, sizeof(eseg->inline_hdr.start));
eseg->inline_hdr.sz = cpu_to_be16(MLX5E_XDP_MIN_INLINE);
+ memcpy(dseg, xdptxd->data + sizeof(eseg->inline_hdr.start),
+ MLX5E_XDP_MIN_INLINE - sizeof(eseg->inline_hdr.start));
dma_len -= MLX5E_XDP_MIN_INLINE;
dma_addr += MLX5E_XDP_MIN_INLINE;
dseg++;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index 4bb219565c58..b62c3514ddf1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -381,7 +381,8 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
mlx5_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
break;
default:
- mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
+ mlx5_core_dbg(dev, "Module ID not recognized: 0x%x\n",
+ module_id);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
index ee308d9aedcd..d8a4bbb8e899 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
@@ -440,7 +440,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table,
rhashtable_remove_fast(&mr_table->route_ht,
&mr_orig_route->ht_node,
mlxsw_sp_mr_route_ht_params);
+ mutex_lock(&mr_table->route_list_lock);
list_del(&mr_orig_route->node);
+ mutex_unlock(&mr_table->route_list_lock);
mlxsw_sp_mr_route_destroy(mr_table, mr_orig_route);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index d2887ae508bb..e22ee1336d74 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -2032,6 +2032,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
if (!neigh_entry)
return NULL;
+ neigh_hold(n);
neigh_entry->key.n = n;
neigh_entry->rif = rif;
INIT_LIST_HEAD(&neigh_entry->nexthop_list);
@@ -2041,6 +2042,7 @@ mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
{
+ neigh_release(neigh_entry->key.n);
kfree(neigh_entry);
}
@@ -3607,6 +3609,8 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
if (err)
goto err_neigh_entry_insert;
+ neigh_release(old_n);
+
read_lock_bh(&n->lock);
nud_state = n->nud_state;
dead = n->dead;
@@ -3615,14 +3619,10 @@ mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
list_for_each_entry(nh, &neigh_entry->nexthop_list,
neigh_list_node) {
- neigh_release(old_n);
- neigh_clone(n);
__mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
}
- neigh_release(n);
-
return 0;
err_neigh_entry_insert:
@@ -3711,6 +3711,11 @@ static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
}
}
+ /* Release the reference taken by neigh_lookup() / neigh_create() since
+ * neigh_entry already holds one.
+ */
+ neigh_release(n);
+
/* If that is the first nexthop connected to that neigh, add to
* nexthop_neighs_list
*/
@@ -3737,11 +3742,9 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_nexthop *nh)
{
struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
- struct neighbour *n;
if (!neigh_entry)
return;
- n = neigh_entry->key.n;
__mlxsw_sp_nexthop_neigh_update(nh, true);
list_del(&nh->neigh_list_node);
@@ -3755,8 +3758,6 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
-
- neigh_release(n);
}
static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index a1405a3e294c..0409866bc025 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -333,7 +333,7 @@ int fjes_hw_init(struct fjes_hw *hw)
ret = fjes_hw_reset(hw);
if (ret)
- return ret;
+ goto err_iounmap;
fjes_hw_set_irqmask(hw, REG_ICTL_MASK_ALL, true);
@@ -346,8 +346,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->max_epid = fjes_hw_get_max_epid(hw);
hw->my_epid = fjes_hw_get_my_epid(hw);
- if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid))
- return -ENXIO;
+ if ((hw->max_epid == 0) || (hw->my_epid >= hw->max_epid)) {
+ ret = -ENXIO;
+ goto err_iounmap;
+ }
ret = fjes_hw_setup(hw);
@@ -355,6 +357,10 @@ int fjes_hw_init(struct fjes_hw *hw)
hw->hw_info.trace_size = FJES_DEBUG_BUFFER_SIZE;
return ret;
+
+err_iounmap:
+ fjes_hw_iounmap(hw);
+ return ret;
}
void fjes_hw_exit(struct fjes_hw *hw)
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index d04b1450875b..a113a06c98a5 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -726,6 +726,9 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
struct ethhdr *eth = eth_hdr(skb);
rx_handler_result_t ret = RX_HANDLER_PASS;
+ if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+ return RX_HANDLER_PASS;
+
if (is_multicast_ether_addr(eth->h_dest)) {
if (ipvlan_external_frame(skb, port)) {
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c
index e2273588c75b..a929399a10d1 100644
--- a/drivers/net/mdio/mdio-aspeed.c
+++ b/drivers/net/mdio/mdio-aspeed.c
@@ -39,34 +39,42 @@ struct aspeed_mdio {
void __iomem *base;
};
-static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum)
+static int aspeed_mdio_op(struct mii_bus *bus, u8 st, u8 op, u8 phyad, u8 regad,
+ u16 data)
{
struct aspeed_mdio *ctx = bus->priv;
u32 ctrl;
- u32 data;
- int rc;
- dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d\n", __func__, addr,
- regnum);
-
- /* Just clause 22 for the moment */
- if (regnum & MII_ADDR_C45)
- return -EOPNOTSUPP;
+ dev_dbg(&bus->dev, "%s: st: %u op: %u, phyad: %u, regad: %u, data: %u\n",
+ __func__, st, op, phyad, regad, data);
ctrl = ASPEED_MDIO_CTRL_FIRE
- | FIELD_PREP(ASPEED_MDIO_CTRL_ST, ASPEED_MDIO_CTRL_ST_C22)
- | FIELD_PREP(ASPEED_MDIO_CTRL_OP, MDIO_C22_OP_READ)
- | FIELD_PREP(ASPEED_MDIO_CTRL_PHYAD, addr)
- | FIELD_PREP(ASPEED_MDIO_CTRL_REGAD, regnum);
+ | FIELD_PREP(ASPEED_MDIO_CTRL_ST, st)
+ | FIELD_PREP(ASPEED_MDIO_CTRL_OP, op)
+ | FIELD_PREP(ASPEED_MDIO_CTRL_PHYAD, phyad)
+ | FIELD_PREP(ASPEED_MDIO_CTRL_REGAD, regad)
+ | FIELD_PREP(ASPEED_MDIO_DATA_MIIRDATA, data);
iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL);
- rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
+ /* Workaround for read-after-write issue.
+ * The controller may return stale data if a read follows immediately
+ * after a write. A dummy read forces the hardware to update its
+ * internal state, ensuring that the next real read returns correct data.
+ */
+ ioread32(ctx->base + ASPEED_MDIO_CTRL);
+
+ return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
!(ctrl & ASPEED_MDIO_CTRL_FIRE),
ASPEED_MDIO_INTERVAL_US,
ASPEED_MDIO_TIMEOUT_US);
- if (rc < 0)
- return rc;
+}
+
+static int aspeed_mdio_get_data(struct mii_bus *bus)
+{
+ struct aspeed_mdio *ctx = bus->priv;
+ int rc;
+ u32 data;
rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_DATA, data,
data & ASPEED_MDIO_DATA_IDLE,
@@ -78,31 +86,36 @@ static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum)
return FIELD_GET(ASPEED_MDIO_DATA_MIIRDATA, data);
}
-static int aspeed_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
+static int aspeed_mdio_read(struct mii_bus *bus, int addr, int regnum)
{
- struct aspeed_mdio *ctx = bus->priv;
- u32 ctrl;
+ int rc;
- dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d, val: 0x%x\n",
- __func__, addr, regnum, val);
+ dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d\n", __func__, addr,
+ regnum);
/* Just clause 22 for the moment */
if (regnum & MII_ADDR_C45)
return -EOPNOTSUPP;
- ctrl = ASPEED_MDIO_CTRL_FIRE
- | FIELD_PREP(ASPEED_MDIO_CTRL_ST, ASPEED_MDIO_CTRL_ST_C22)
- | FIELD_PREP(ASPEED_MDIO_CTRL_OP, MDIO_C22_OP_WRITE)
- | FIELD_PREP(ASPEED_MDIO_CTRL_PHYAD, addr)
- | FIELD_PREP(ASPEED_MDIO_CTRL_REGAD, regnum)
- | FIELD_PREP(ASPEED_MDIO_CTRL_MIIWDATA, val);
+ rc = aspeed_mdio_op(bus, ASPEED_MDIO_CTRL_ST_C22, MDIO_C22_OP_READ,
+ addr, regnum, 0);
+ if (rc < 0)
+ return rc;
- iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL);
+ return aspeed_mdio_get_data(bus);
+}
- return readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
- !(ctrl & ASPEED_MDIO_CTRL_FIRE),
- ASPEED_MDIO_INTERVAL_US,
- ASPEED_MDIO_TIMEOUT_US);
+static int aspeed_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
+{
+ dev_dbg(&bus->dev, "%s: addr: %d, regnum: %d, val: 0x%x\n",
+ __func__, addr, regnum, val);
+
+ /* Just clause 22 for the moment */
+ if (regnum & MII_ADDR_C45)
+ return -EOPNOTSUPP;
+
+ return aspeed_mdio_op(bus, ASPEED_MDIO_CTRL_ST_C22, MDIO_C22_OP_WRITE,
+ addr, regnum, val);
}
static int aspeed_mdio_probe(struct platform_device *pdev)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index c05a60f23677..03cc3da8c3c1 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -872,7 +872,7 @@ static void __team_queue_override_enabled_check(struct team *team)
static void team_queue_override_port_prio_changed(struct team *team,
struct team_port *port)
{
- if (!port->queue_id || team_port_enabled(port))
+ if (!port->queue_id || !team_port_enabled(port))
return;
__team_queue_override_port_del(team, port);
__team_queue_override_port_add(team, port);
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 138279bbb544..e3ddb990dc54 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -193,6 +193,8 @@ static int update_eth_regs_async(pegasus_t *pegasus)
netif_device_detach(pegasus->net);
netif_err(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
+ usb_free_urb(async_urb);
+ kfree(req);
}
return ret;
}
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index eb4f3f8a1906..185b8c8b19ba 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -211,6 +211,8 @@ static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg)
if (res == -ENODEV)
netif_device_detach(dev->netdev);
dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res);
+ kfree(req);
+ usb_free_urb(async_urb);
}
return res;
}
diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
index 1ec11a08820d..d4f0dfe1175a 100644
--- a/drivers/net/usb/sr9700.c
+++ b/drivers/net/usb/sr9700.c
@@ -52,7 +52,7 @@ static int sr_read_reg(struct usbnet *dev, u8 reg, u8 *value)
static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value)
{
- return usbnet_write_cmd(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ return usbnet_write_cmd(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0);
}
@@ -64,7 +64,7 @@ static void sr_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
static void sr_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
{
- usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG,
+ usbnet_write_cmd_async(dev, SR_WR_REG, SR_REQ_WR_REG,
value, reg, NULL, 0);
}
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
index 025619cd14e8..acd6743f3827 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
@@ -1023,9 +1023,6 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
dma_addr_t *mapping;
entry = priv->rx_ring + priv->rx_ring_sz*i;
if (!skb) {
- dma_free_coherent(&priv->pdev->dev,
- priv->rx_ring_sz * 32,
- priv->rx_ring, priv->rx_ring_dma);
wiphy_err(dev->wiphy, "Cannot allocate RX skb\n");
return -ENOMEM;
}
@@ -1037,9 +1034,7 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
if (dma_mapping_error(&priv->pdev->dev, *mapping)) {
kfree_skb(skb);
- dma_free_coherent(&priv->pdev->dev,
- priv->rx_ring_sz * 32,
- priv->rx_ring, priv->rx_ring_dma);
+ priv->rx_buf[i] = NULL;
wiphy_err(dev->wiphy, "Cannot map DMA for RX skb\n");
return -ENOMEM;
}
@@ -1130,7 +1125,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
ret = rtl8180_init_rx_ring(dev);
if (ret)
- return ret;
+ goto err_free_rings;
for (i = 0; i < (dev->queues + 1); i++)
if ((ret = rtl8180_init_tx_ring(dev, i, 16)))
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
index c9df185dc3f4..00493a239117 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
@@ -338,14 +338,16 @@ static void rtl8187_rx_cb(struct urb *urb)
spin_unlock_irqrestore(&priv->rx_queue.lock, f);
skb_put(skb, urb->actual_length);
- if (unlikely(urb->status)) {
- dev_kfree_skb_irq(skb);
- return;
- }
+ if (unlikely(urb->status))
+ goto free_skb;
if (!priv->is_rtl8187b) {
- struct rtl8187_rx_hdr *hdr =
- (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
+ struct rtl8187_rx_hdr *hdr;
+
+ if (skb->len < sizeof(struct rtl8187_rx_hdr))
+ goto free_skb;
+
+ hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
flags = le32_to_cpu(hdr->flags);
/* As with the RTL8187B below, the AGC is used to calculate
* signal strength. In this case, the scaling
@@ -355,8 +357,12 @@ static void rtl8187_rx_cb(struct urb *urb)
rx_status.antenna = (hdr->signal >> 7) & 1;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
} else {
- struct rtl8187b_rx_hdr *hdr =
- (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
+ struct rtl8187b_rx_hdr *hdr;
+
+ if (skb->len < sizeof(struct rtl8187b_rx_hdr))
+ goto free_skb;
+
+ hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
/* The Realtek datasheet for the RTL8187B shows that the RX
* header contains the following quantities: signal quality,
* RSSI, AGC, the received power in dB, and the measured SNR.
@@ -409,6 +415,11 @@ static void rtl8187_rx_cb(struct urb *urb)
skb_unlink(skb, &priv->rx_queue);
dev_kfree_skb_irq(skb);
}
+ return;
+
+free_skb:
+ dev_kfree_skb_irq(skb);
+ return;
}
static int rtl8187_init_urbs(struct ieee80211_hw *dev)
diff --git a/drivers/net/wireless/st/cw1200/bh.c b/drivers/net/wireless/st/cw1200/bh.c
index 361fef6e1eea..61916e202f20 100644
--- a/drivers/net/wireless/st/cw1200/bh.c
+++ b/drivers/net/wireless/st/cw1200/bh.c
@@ -320,10 +320,12 @@ static int cw1200_bh_rx_helper(struct cw1200_common *priv,
if (wsm_id & 0x0400) {
int rc = wsm_release_tx_buffer(priv, 1);
- if (WARN_ON(rc < 0))
+ if (WARN_ON(rc < 0)) {
+ dev_kfree_skb(skb_rx);
return rc;
- else if (rc > 0)
+ } else if (rc > 0) {
*tx = 1;
+ }
}
/* cw1200_wsm_rx takes care on SKB livetime */
diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
index 68eb1253f888..77ada0a5c739 100644
--- a/drivers/nfc/pn533/usb.c
+++ b/drivers/nfc/pn533/usb.c
@@ -411,7 +411,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
if (rc || (transferred != sizeof(cmd))) {
nfc_err(&phy->udev->dev,
"Reader power on cmd error %d\n", rc);
- return rc;
+ return rc ?: -EINVAL;
}
rc = usb_submit_urb(phy->in_urb, GFP_KERNEL);
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index e37e7207c60c..dbc9173ec0f8 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -1500,14 +1500,14 @@ nvme_fc_match_disconn_ls(struct nvme_fc_rport *rport,
{
struct fcnvme_ls_disconnect_assoc_rqst *rqst =
&lsop->rqstbuf->rq_dis_assoc;
- struct nvme_fc_ctrl *ctrl, *ret = NULL;
+ struct nvme_fc_ctrl *ctrl, *tmp, *ret = NULL;
struct nvmefc_ls_rcv_op *oldls = NULL;
u64 association_id = be64_to_cpu(rqst->associd.association_id);
unsigned long flags;
spin_lock_irqsave(&rport->lock, flags);
- list_for_each_entry(ctrl, &rport->ctrl_list, ctrl_list) {
+ list_for_each_entry_safe(ctrl, tmp, &rport->ctrl_list, ctrl_list) {
if (!nvme_fc_ctrl_get(ctrl))
continue;
spin_lock(&ctrl->lock);
@@ -1520,7 +1520,9 @@ nvme_fc_match_disconn_ls(struct nvme_fc_rport *rport,
if (ret)
/* leave the ctrl get reference */
break;
+ spin_unlock_irqrestore(&rport->lock, flags);
nvme_fc_ctrl_put(ctrl);
+ spin_lock_irqsave(&rport->lock, flags);
}
spin_unlock_irqrestore(&rport->lock, flags);
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index ec175ae99873..11b750f12ee9 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -154,7 +154,9 @@ static int gsc_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
gsc_dev->eim = ((u32) gsc_dev->gsc_irq.txn_addr) | gsc_dev->gsc_irq.txn_data;
/* switch IRQ's for devices below LASI/WAX to other CPU */
- gsc_writel(gsc_dev->eim, gsc_dev->hpa + OFFSET_IAR);
+ /* ASP chip (svers 0x70) does not support reprogramming */
+ if (gsc_dev->gsc->id.sversion != 0x70)
+ gsc_writel(gsc_dev->eim, gsc_dev->hpa + OFFSET_IAR);
irq_data_update_effective_affinity(d, &tmask);
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 6245c179ce49..6844c4652e70 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -1382,6 +1382,8 @@ static int ks_pcie_probe(struct platform_device *pdev)
break;
default:
dev_err(dev, "INVALID device type %d\n", mode);
+ ret = -EINVAL;
+ goto err_get_sync;
}
ks_pcie_enable_error_irq(ks_pcie);
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 9d2f511f13fa..2dfeec79c671 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -52,7 +52,7 @@
#define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf)
#define PCIE_PORT_DEBUG0 0x728
-#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f
+#define PORT_LOGIC_LTSSM_STATE_MASK 0x3f
#define PORT_LOGIC_LTSSM_STATE_L0 0x11
#define PCIE_PORT_DEBUG1 0x72C
#define PCIE_PORT_DEBUG1_LINK_UP BIT(4)
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index 85be07e8b418..a5454b39672f 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -43,7 +43,6 @@
#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc
-#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00
#define PCIE_RC_DL_MDIO_ADDR 0x1100
#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
@@ -865,7 +864,7 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
int num_out_wins = 0;
u16 nlw, cls, lnksta;
int i, ret, memc;
- u32 tmp, burst, aspm_support;
+ u32 tmp, burst;
/* Reset the bridge */
pcie->bridge_sw_init_set(pcie, 1);
@@ -987,12 +986,9 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
}
/* Don't advertise L0s capability if 'aspm-no-l0s' */
- aspm_support = PCIE_LINK_STATE_L1;
- if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
- aspm_support |= PCIE_LINK_STATE_L0S;
tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
- u32p_replace_bits(&tmp, aspm_support,
- PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
+ if (of_property_read_bool(pcie->np, "aspm-no-l0s"))
+ tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S;
writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
/*
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index a16a03b8f66f..fe15e59e7c56 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -584,6 +584,8 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *drv = pci_dev->driver;
+ pci_dev->state_saved = false;
+
if (drv && drv->suspend) {
pci_power_t prev = pci_dev->current_state;
int error;
@@ -985,6 +987,8 @@ static int pci_pm_freeze(struct device *dev)
if (!pm) {
pci_pm_default_suspend(pci_dev);
+ if (!pm_runtime_suspended(dev))
+ pci_dev->state_saved = false;
return 0;
}
diff --git a/drivers/phy/broadcom/phy-bcm63xx-usbh.c b/drivers/phy/broadcom/phy-bcm63xx-usbh.c
index 6c05ba8b08be..296ca55d8dfa 100644
--- a/drivers/phy/broadcom/phy-bcm63xx-usbh.c
+++ b/drivers/phy/broadcom/phy-bcm63xx-usbh.c
@@ -374,7 +374,7 @@ static struct phy *bcm63xx_usbh_phy_xlate(struct device *dev,
return of_phy_simple_xlate(dev, args);
}
-static int __init bcm63xx_usbh_phy_probe(struct platform_device *pdev)
+static int bcm63xx_usbh_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct bcm63xx_usbh_phy *usbh;
@@ -431,7 +431,7 @@ static int __init bcm63xx_usbh_phy_probe(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id bcm63xx_usbh_phy_ids[] __initconst = {
+static const struct of_device_id bcm63xx_usbh_phy_ids[] = {
{ .compatible = "brcm,bcm6318-usbh-phy", .data = &usbh_bcm6318 },
{ .compatible = "brcm,bcm6328-usbh-phy", .data = &usbh_bcm6328 },
{ .compatible = "brcm,bcm6358-usbh-phy", .data = &usbh_bcm6358 },
@@ -442,7 +442,7 @@ static const struct of_device_id bcm63xx_usbh_phy_ids[] __initconst = {
};
MODULE_DEVICE_TABLE(of, bcm63xx_usbh_phy_ids);
-static struct platform_driver bcm63xx_usbh_phy_driver __refdata = {
+static struct platform_driver bcm63xx_usbh_phy_driver = {
.driver = {
.name = "bcm63xx-usbh-phy",
.of_match_table = bcm63xx_usbh_phy_ids,
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 9485737638b3..07bf09042045 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -490,7 +490,8 @@ static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_function *func;
enum pin_config_param param;
- unsigned offset = 0, data = 0, i, j, ret;
+ unsigned offset = 0, data = 0, i, j;
+ int ret;
ret = pcs_get_function(pctldev, pin, &func);
if (ret)
@@ -553,24 +554,33 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
{
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_function *func;
- unsigned offset = 0, shift = 0, i, data, ret;
+ unsigned offset = 0, shift = 0, i, data;
u32 arg;
- int j;
+ int j, ret;
+ enum pin_config_param param;
ret = pcs_get_function(pctldev, pin, &func);
if (ret)
return ret;
for (j = 0; j < num_configs; j++) {
+ param = pinconf_to_config_param(configs[j]);
+
+ /* BIAS_DISABLE has no entry in the func->conf table */
+ if (param == PIN_CONFIG_BIAS_DISABLE) {
+ /* This just disables all bias entries */
+ pcs_pinconf_clear_bias(pctldev, pin);
+ continue;
+ }
+
for (i = 0; i < func->nconfs; i++) {
- if (pinconf_to_config_param(configs[j])
- != func->conf[i].param)
+ if (param != func->conf[i].param)
continue;
offset = pin * (pcs->width / BITS_PER_BYTE);
data = pcs->read(pcs->base + offset);
arg = pinconf_to_config_argument(configs[j]);
- switch (func->conf[i].param) {
+ switch (param) {
/* 2 parameters */
case PIN_CONFIG_INPUT_SCHMITT:
case PIN_CONFIG_DRIVE_STRENGTH:
@@ -581,9 +591,6 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
data |= (arg << shift) & func->conf[i].mask;
break;
/* 4 parameters */
- case PIN_CONFIG_BIAS_DISABLE:
- pcs_pinconf_clear_bias(pctldev, pin);
- break;
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_UP:
if (arg) {
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 049a34f0e13f..f72a1598de28 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -213,7 +213,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
*/
if (d && i != gpio_func &&
!test_and_set_bit(d->hwirq, pctrl->disabled_for_mux))
- disable_irq(irq);
+ disable_irq_nosync(irq);
raw_spin_lock_irqsave(&pctrl->lock, flags);
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 6b6fdb711659..0094ccb4c63c 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -1494,7 +1494,7 @@ int stm32_pctl_probe(struct platform_device *pdev)
if (hwlock_id == -EPROBE_DEFER)
return hwlock_id;
} else {
- pctl->hwlock = hwspin_lock_request_specific(hwlock_id);
+ pctl->hwlock = devm_hwspin_lock_request_specific(dev, hwlock_id);
}
spin_lock_init(&pctl->irqmux_lock);
diff --git a/drivers/platform/chrome/cros_ec_ishtp.c b/drivers/platform/chrome/cros_ec_ishtp.c
index 81364029af36..2774fbe1bbad 100644
--- a/drivers/platform/chrome/cros_ec_ishtp.c
+++ b/drivers/platform/chrome/cros_ec_ishtp.c
@@ -714,6 +714,7 @@ static int cros_ec_ishtp_remove(struct ishtp_cl_device *cl_device)
cancel_work_sync(&client_data->work_ishtp_reset);
cancel_work_sync(&client_data->work_ec_evt);
+ cros_ec_unregister(client_data->ec_dev);
cros_ish_deinit(cros_ish_cl);
ishtp_put_device(cl_device);
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index ebec49957ed0..b35a0539a99c 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -81,6 +81,7 @@ MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
enum acer_wmi_event_ids {
WMID_HOTKEY_EVENT = 0x1,
+ WMID_BACKLIGHT_EVENT = 0x4,
WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5,
};
@@ -1890,6 +1891,9 @@ static void acer_wmi_notify(u32 value, void *context)
sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true);
}
break;
+ case WMID_BACKLIGHT_EVENT:
+ /* Already handled by acpi-video */
+ break;
case WMID_ACCEL_OR_KBD_DOCK_EVENT:
acer_gsensor_event();
acer_kbd_dock_event(&return_value);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 265232d1b9a8..4f56f853b756 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -721,14 +721,14 @@ static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
kbd_led_update(asus);
}
-static void kbd_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
+static int kbd_led_set(struct led_classdev *led_cdev, enum led_brightness value)
{
/* Prevent disabling keyboard backlight on module unregister */
if (led_cdev->flags & LED_UNREGISTERING)
- return;
+ return 0;
do_kbd_led_set(led_cdev, value);
+ return 0;
}
static void kbd_led_set_by_kbd(struct asus_wmi *asus, enum led_brightness value)
@@ -865,7 +865,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
asus->kbd_led_wk = led_val;
asus->kbd_led.name = "asus::kbd_backlight";
asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
- asus->kbd_led.brightness_set = kbd_led_set;
+ asus->kbd_led.brightness_set_blocking = kbd_led_set;
asus->kbd_led.brightness_get = kbd_led_get;
asus->kbd_led.max_brightness = 3;
diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c
index 23ebd0c046e1..da9f80bde794 100644
--- a/drivers/platform/x86/huawei-wmi.c
+++ b/drivers/platform/x86/huawei-wmi.c
@@ -82,6 +82,10 @@ static const struct key_entry huawei_wmi_keymap[] = {
{ KE_KEY, 0x289, { KEY_WLAN } },
// Huawei |M| key
{ KE_KEY, 0x28a, { KEY_CONFIG } },
+ // HONOR YOYO key
+ { KE_KEY, 0x28b, { KEY_NOTIFICATION_CENTER } },
+ // HONOR print screen
+ { KE_KEY, 0x28e, { KEY_PRINT } },
// Keyboard backlit
{ KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } },
{ KE_IGNORE, 0x294, { KEY_KBDILLUMUP } },
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
index 5fc665f7d9b3..10cab7bdfe15 100644
--- a/drivers/platform/x86/ibm_rtl.c
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -262,7 +262,7 @@ static int __init ibm_rtl_init(void) {
/* search for the _RTL_ signature at the start of the table */
for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
struct ibm_rtl_table __iomem * tmp;
- tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
+ tmp = (struct ibm_rtl_table __iomem *) (ebda_map + i*sizeof(unsigned int));
if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
phys_addr_t addr;
unsigned int plen;
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index dfb4af759aa7..fd6b3383ac4f 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -1146,6 +1146,9 @@ static void __exit msi_cleanup(void)
sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
if (!quirks->old_ec_model && threeg_exists)
device_remove_file(&msipf_device->dev, &dev_attr_threeg);
+ if (quirks->old_ec_model)
+ sysfs_remove_group(&msipf_device->dev.kobj,
+ &msipf_old_attribute_group);
platform_device_unregister(msipf_device);
platform_driver_unregister(&msipf_driver);
backlight_device_unregister(msibl_device);
diff --git a/drivers/power/supply/apm_power.c b/drivers/power/supply/apm_power.c
index 9d1a7fbcaed4..50b963694559 100644
--- a/drivers/power/supply/apm_power.c
+++ b/drivers/power/supply/apm_power.c
@@ -365,7 +365,8 @@ static int __init apm_battery_init(void)
static void __exit apm_battery_exit(void)
{
- apm_get_power_status = NULL;
+ if (apm_get_power_status == apm_battery_apm_get_power_status)
+ apm_get_power_status = NULL;
}
module_init(apm_battery_init);
diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c
index 18b33f14dfee..aae655109862 100644
--- a/drivers/power/supply/wm831x_power.c
+++ b/drivers/power/supply/wm831x_power.c
@@ -144,6 +144,7 @@ static int wm831x_usb_limit_change(struct notifier_block *nb,
struct wm831x_power,
usb_notify);
unsigned int i, best;
+ int ret;
/* Find the highest supported limit */
best = 0;
@@ -156,8 +157,13 @@ static int wm831x_usb_limit_change(struct notifier_block *nb,
dev_dbg(wm831x_power->wm831x->dev,
"Limiting USB current to %umA", wm831x_usb_limits[best]);
- wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
- WM831X_USB_ILIM_MASK, best);
+ ret = wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
+ WM831X_USB_ILIM_MASK, best);
+ if (ret < 0) {
+ dev_err(wm831x_power->wm831x->dev,
+ "Failed to set USB current limit: %d\n", ret);
+ return ret;
+ }
return 0;
}
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
index fe5d05da7ce7..40cf6e337bde 100644
--- a/drivers/powercap/powercap_sys.c
+++ b/drivers/powercap/powercap_sys.c
@@ -67,7 +67,7 @@ static ssize_t show_constraint_##_attr(struct device *dev, \
int id; \
struct powercap_zone_constraint *pconst;\
\
- if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+ if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \
return -EINVAL; \
if (id >= power_zone->const_id_cnt) \
return -EINVAL; \
@@ -92,7 +92,7 @@ static ssize_t store_constraint_##_attr(struct device *dev,\
int id; \
struct powercap_zone_constraint *pconst;\
\
- if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+ if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1) \
return -EINVAL; \
if (id >= power_zone->const_id_cnt) \
return -EINVAL; \
@@ -161,7 +161,7 @@ static ssize_t show_constraint_name(struct device *dev,
ssize_t len = -ENODATA;
struct powercap_zone_constraint *pconst;
- if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id))
+ if (sscanf(dev_attr->attr.name, "constraint_%d_", &id) != 1)
return -EINVAL;
if (id >= power_zone->const_id_cnt)
return -EINVAL;
@@ -625,17 +625,23 @@ struct powercap_control_type *powercap_register_control_type(
INIT_LIST_HEAD(&control_type->node);
control_type->dev.class = &powercap_class;
dev_set_name(&control_type->dev, "%s", name);
- result = device_register(&control_type->dev);
- if (result) {
- put_device(&control_type->dev);
- return ERR_PTR(result);
- }
idr_init(&control_type->idr);
mutex_lock(&powercap_cntrl_list_lock);
list_add_tail(&control_type->node, &powercap_cntrl_list);
mutex_unlock(&powercap_cntrl_list_lock);
+ result = device_register(&control_type->dev);
+ if (result) {
+ mutex_lock(&powercap_cntrl_list_lock);
+ list_del(&control_type->node);
+ mutex_unlock(&powercap_cntrl_list_lock);
+
+ idr_destroy(&control_type->idr);
+ put_device(&control_type->dev);
+ return ERR_PTR(result);
+ }
+
return control_type;
}
EXPORT_SYMBOL_GPL(powercap_register_control_type);
diff --git a/drivers/pwm/pwm-bcm2835.c b/drivers/pwm/pwm-bcm2835.c
index 6841dcfe27fc..0a7819f2200a 100644
--- a/drivers/pwm/pwm-bcm2835.c
+++ b/drivers/pwm/pwm-bcm2835.c
@@ -35,36 +35,15 @@ static inline struct bcm2835_pwm *to_bcm2835_pwm(struct pwm_chip *chip)
return container_of(chip, struct bcm2835_pwm, chip);
}
-static int bcm2835_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+static int bcm2835_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
{
- struct bcm2835_pwm *pc = to_bcm2835_pwm(chip);
- u32 value;
-
- value = readl(pc->base + PWM_CONTROL);
- value &= ~(PWM_CONTROL_MASK << PWM_CONTROL_SHIFT(pwm->hwpwm));
- value |= (PWM_MODE << PWM_CONTROL_SHIFT(pwm->hwpwm));
- writel(value, pc->base + PWM_CONTROL);
-
- return 0;
-}
-
-static void bcm2835_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct bcm2835_pwm *pc = to_bcm2835_pwm(chip);
- u32 value;
-
- value = readl(pc->base + PWM_CONTROL);
- value &= ~(PWM_CONTROL_MASK << PWM_CONTROL_SHIFT(pwm->hwpwm));
- writel(value, pc->base + PWM_CONTROL);
-}
-static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
- int duty_ns, int period_ns)
-{
struct bcm2835_pwm *pc = to_bcm2835_pwm(chip);
unsigned long rate = clk_get_rate(pc->clk);
+ unsigned long long period;
unsigned long scaler;
- u32 period;
+ u32 val;
if (!rate) {
dev_err(pc->dev, "failed to get clock rate\n");
@@ -72,65 +51,43 @@ static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
}
scaler = DIV_ROUND_CLOSEST(NSEC_PER_SEC, rate);
- period = DIV_ROUND_CLOSEST(period_ns, scaler);
+ /* set period */
+ period = DIV_ROUND_CLOSEST_ULL(state->period, scaler);
- if (period < PERIOD_MIN)
+ /* dont accept a period that is too small or has been truncated */
+ if ((period < PERIOD_MIN) || (period > U32_MAX))
return -EINVAL;
- writel(DIV_ROUND_CLOSEST(duty_ns, scaler),
- pc->base + DUTY(pwm->hwpwm));
writel(period, pc->base + PERIOD(pwm->hwpwm));
- return 0;
-}
+ /* set duty cycle */
+ val = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, scaler);
+ writel(val, pc->base + DUTY(pwm->hwpwm));
-static int bcm2835_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct bcm2835_pwm *pc = to_bcm2835_pwm(chip);
- u32 value;
-
- value = readl(pc->base + PWM_CONTROL);
- value |= PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm);
- writel(value, pc->base + PWM_CONTROL);
+ /* set polarity */
+ val = readl(pc->base + PWM_CONTROL);
- return 0;
-}
-
-static void bcm2835_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct bcm2835_pwm *pc = to_bcm2835_pwm(chip);
- u32 value;
+ val &= ~(PWM_CONTROL_MASK << PWM_CONTROL_SHIFT(pwm->hwpwm));
+ val |= PWM_MODE << PWM_CONTROL_SHIFT(pwm->hwpwm);
- value = readl(pc->base + PWM_CONTROL);
- value &= ~(PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm));
- writel(value, pc->base + PWM_CONTROL);
-}
-
-static int bcm2835_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
- enum pwm_polarity polarity)
-{
- struct bcm2835_pwm *pc = to_bcm2835_pwm(chip);
- u32 value;
-
- value = readl(pc->base + PWM_CONTROL);
+ if (state->polarity == PWM_POLARITY_NORMAL)
+ val &= ~(PWM_POLARITY << PWM_CONTROL_SHIFT(pwm->hwpwm));
+ else
+ val |= PWM_POLARITY << PWM_CONTROL_SHIFT(pwm->hwpwm);
- if (polarity == PWM_POLARITY_NORMAL)
- value &= ~(PWM_POLARITY << PWM_CONTROL_SHIFT(pwm->hwpwm));
+ /* enable/disable */
+ if (state->enabled)
+ val |= PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm);
else
- value |= PWM_POLARITY << PWM_CONTROL_SHIFT(pwm->hwpwm);
+ val &= ~(PWM_ENABLE << PWM_CONTROL_SHIFT(pwm->hwpwm));
- writel(value, pc->base + PWM_CONTROL);
+ writel(val, pc->base + PWM_CONTROL);
return 0;
}
static const struct pwm_ops bcm2835_pwm_ops = {
- .request = bcm2835_pwm_request,
- .free = bcm2835_pwm_free,
- .config = bcm2835_pwm_config,
- .enable = bcm2835_pwm_enable,
- .disable = bcm2835_pwm_disable,
- .set_polarity = bcm2835_set_polarity,
+ .apply = bcm2835_pwm_apply,
.owner = THIS_MODULE,
};
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 2ca2855255be..b8734757d884 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -458,8 +458,7 @@ static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}
- if (state->polarity != pwm->state.polarity)
- stm32_pwm_set_polarity(priv, pwm->hwpwm, state->polarity);
+ stm32_pwm_set_polarity(priv, pwm->hwpwm, state->polarity);
ret = stm32_pwm_config(priv, pwm->hwpwm,
state->duty_cycle, state->period);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index b2d866d60651..0e2129be0226 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1495,6 +1495,8 @@ static int set_machine_constraints(struct regulator_dev *rdev)
* and we have control then make sure it is enabled.
*/
if (rdev->constraints->always_on || rdev->constraints->boot_on) {
+ bool supply_enabled = false;
+
/* If we want to enable this regulator, make sure that we know
* the supplying regulator.
*/
@@ -1514,11 +1516,14 @@ static int set_machine_constraints(struct regulator_dev *rdev)
rdev->supply = NULL;
return ret;
}
+ supply_enabled = true;
}
ret = _regulator_do_enable(rdev);
if (ret < 0 && ret != -EINVAL) {
rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret));
+ if (supply_enabled)
+ regulator_disable(rdev->supply);
return ret;
}
@@ -1805,6 +1810,7 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
{
struct regulator_supply_alias *map;
+ mutex_lock(®ulator_list_mutex);
map = regulator_find_supply_alias(*dev, *supply);
if (map) {
dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
@@ -1813,6 +1819,7 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
*dev = map->alias_dev;
*supply = map->alias_supply;
}
+ mutex_unlock(®ulator_list_mutex);
}
static int regulator_match(struct device *dev, const void *data)
@@ -2291,22 +2298,26 @@ int regulator_register_supply_alias(struct device *dev, const char *id,
const char *alias_id)
{
struct regulator_supply_alias *map;
+ struct regulator_supply_alias *new_map;
- map = regulator_find_supply_alias(dev, id);
- if (map)
- return -EEXIST;
-
- map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
- if (!map)
+ new_map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
+ if (!new_map)
return -ENOMEM;
- map->src_dev = dev;
- map->src_supply = id;
- map->alias_dev = alias_dev;
- map->alias_supply = alias_id;
-
- list_add(&map->list, ®ulator_supply_alias_list);
+ mutex_lock(®ulator_list_mutex);
+ map = regulator_find_supply_alias(dev, id);
+ if (map) {
+ mutex_unlock(®ulator_list_mutex);
+ kfree(new_map);
+ return -EEXIST;
+ }
+ new_map->src_dev = dev;
+ new_map->src_supply = id;
+ new_map->alias_dev = alias_dev;
+ new_map->alias_supply = alias_id;
+ list_add(&new_map->list, ®ulator_supply_alias_list);
+ mutex_unlock(®ulator_list_mutex);
pr_info("Adding alias for supply %s,%s -> %s,%s\n",
id, dev_name(dev), alias_id, dev_name(alias_dev));
@@ -2326,11 +2337,13 @@ void regulator_unregister_supply_alias(struct device *dev, const char *id)
{
struct regulator_supply_alias *map;
+ mutex_lock(®ulator_list_mutex);
map = regulator_find_supply_alias(dev, id);
if (map) {
list_del(&map->list);
kfree(map);
}
+ mutex_unlock(®ulator_list_mutex);
}
EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
index fec59c6b6fdb..e5e0924935b9 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1244,6 +1244,7 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept)
{
struct glink_channel *channel = to_glink_channel(ept);
struct qcom_glink *glink = channel->glink;
+ struct rpmsg_channel_info chinfo;
unsigned long flags;
spin_lock_irqsave(&channel->recv_lock, flags);
@@ -1251,6 +1252,13 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept)
spin_unlock_irqrestore(&channel->recv_lock, flags);
/* Decouple the potential rpdev from the channel */
+ if (channel->rpdev) {
+ strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name));
+ chinfo.src = RPMSG_ADDR_ANY;
+ chinfo.dst = RPMSG_ADDR_ANY;
+
+ rpmsg_unregister_device(glink->dev, &chinfo);
+ }
channel->rpdev = NULL;
qcom_glink_send_close_req(glink, channel);
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 13e56a23e41e..a1903b4a7f00 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -1648,15 +1648,15 @@ static int __init ap_module_init(void)
{
int rc, i;
- rc = ap_debug_init();
- if (rc)
- return rc;
-
if (!ap_instructions_available()) {
pr_warn("The hardware system does not support AP instructions\n");
return -ENODEV;
}
+ rc = ap_debug_init();
+ if (rc)
+ return rc;
+
/* init ap_queue hashtable */
hash_init(ap_queues);
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 7a78606598c4..356bd3363ae3 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -897,6 +897,9 @@ static void asd_pci_remove(struct pci_dev *dev)
asd_disable_ints(asd_ha);
+ /* Ensure all scheduled tasklets complete before freeing resources */
+ tasklet_kill(&asd_ha->seq.dl_tasklet);
+
asd_remove_dev_attrs(asd_ha);
/* XXX more here as needed */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 8c376736a8f5..4ae6b76c2c5e 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -62,8 +62,8 @@
#include <linux/hdreg.h>
#include <linux/reboot.h>
#include <linux/stringify.h>
+#include <linux/irq.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/processor.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
@@ -8665,6 +8665,30 @@ static int ipr_dump_mailbox_wait(struct ipr_cmnd *ipr_cmd)
return IPR_RC_JOB_RETURN;
}
+/**
+ * ipr_set_affinity_nobalance
+ * @ioa_cfg: ipr_ioa_cfg struct for an ipr device
+ * @flag: bool
+ * true: ensable "IRQ_NO_BALANCING" bit for msix interrupt
+ * false: disable "IRQ_NO_BALANCING" bit for msix interrupt
+ * Description: This function will be called to disable/enable
+ * "IRQ_NO_BALANCING" to avoid irqbalance daemon
+ * kicking in during adapter reset.
+ **/
+static void ipr_set_affinity_nobalance(struct ipr_ioa_cfg *ioa_cfg, bool flag)
+{
+ int irq, i;
+
+ for (i = 0; i < ioa_cfg->nvectors; i++) {
+ irq = pci_irq_vector(ioa_cfg->pdev, i);
+
+ if (flag)
+ irq_set_status_flags(irq, IRQ_NO_BALANCING);
+ else
+ irq_clear_status_flags(irq, IRQ_NO_BALANCING);
+ }
+}
+
/**
* ipr_reset_restore_cfg_space - Restore PCI config space.
* @ipr_cmd: ipr command struct
@@ -8689,6 +8713,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
return IPR_RC_JOB_CONTINUE;
}
+ ipr_set_affinity_nobalance(ioa_cfg, false);
ipr_fail_all_ops(ioa_cfg);
if (ioa_cfg->sis64) {
@@ -8768,6 +8793,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
rc = pci_write_config_byte(ioa_cfg->pdev, PCI_BIST, PCI_BIST_START);
if (rc == PCIBIOS_SUCCESSFUL) {
+ ipr_set_affinity_nobalance(ioa_cfg, true);
ipr_cmd->job_step = ipr_reset_bist_done;
ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
rc = IPR_RC_JOB_RETURN;
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index def9fac7aa4f..2a83bd5d834d 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -933,10 +933,17 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
if (WARN_ON_ONCE(session->leadconn))
return;
+ iscsi_session_remove(cls_session);
+ /*
+ * Our get_host_param needs to access the session, so remove the
+ * host from sysfs before freeing the session to make sure userspace
+ * is no longer accessing the callout.
+ */
+ iscsi_host_remove(shost);
+
iscsi_tcp_r2tpool_free(cls_session->dd_data);
- iscsi_session_teardown(cls_session);
- iscsi_host_remove(shost);
+ iscsi_session_free(cls_session);
iscsi_host_free(shost);
}
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index bad5730bf7ab..7e82ddce5031 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -2892,20 +2892,34 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
}
EXPORT_SYMBOL_GPL(iscsi_session_setup);
+/*
+ * issi_session_remove - Remove session from iSCSI class.
+ */
+void iscsi_session_remove(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *session = cls_session->dd_data;
+ struct Scsi_Host *shost = session->host;
+
+ iscsi_remove_session(cls_session);
+ /*
+ * host removal only has to wait for its children to be removed from
+ * sysfs, and iscsi_tcp needs to do iscsi_host_remove before freeing
+ * the session, so drop the session count here.
+ */
+ iscsi_host_dec_session_cnt(shost);
+}
+EXPORT_SYMBOL_GPL(iscsi_session_remove);
+
/**
- * iscsi_session_teardown - destroy session, host, and cls_session
+ * iscsi_session_free - Free iscsi session and it's resources
* @cls_session: iscsi session
*/
-void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+void iscsi_session_free(struct iscsi_cls_session *cls_session)
{
struct iscsi_session *session = cls_session->dd_data;
struct module *owner = cls_session->transport->owner;
- struct Scsi_Host *shost = session->host;
iscsi_pool_free(&session->cmdpool);
-
- iscsi_remove_session(cls_session);
-
kfree(session->password);
kfree(session->password_in);
kfree(session->username);
@@ -2921,10 +2935,19 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
kfree(session->discovery_parent_type);
iscsi_free_session(cls_session);
-
- iscsi_host_dec_session_cnt(shost);
module_put(owner);
}
+EXPORT_SYMBOL_GPL(iscsi_session_free);
+
+/**
+ * iscsi_session_teardown - destroy session and cls_session
+ * @cls_session: iscsi session
+ */
+void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+{
+ iscsi_session_remove(cls_session);
+ iscsi_session_free(cls_session);
+}
EXPORT_SYMBOL_GPL(iscsi_session_teardown);
/**
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 3ef2fde28b8e..52e09c3e2b50 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -114,20 +114,6 @@ static inline void sas_fail_probe(struct domain_device *dev, const char *func, i
func, dev->parent ? "exp-attached" :
"direct-attached",
SAS_ADDR(dev->sas_addr), err);
-
- /*
- * If the device probe failed, the expander phy attached address
- * needs to be reset so that the phy will not be treated as flutter
- * in the next revalidation
- */
- if (dev->parent && !dev_is_expander(dev->dev_type)) {
- struct sas_phy *phy = dev->phy;
- struct domain_device *parent = dev->parent;
- struct ex_phy *ex_phy = &parent->ex_dev.ex_phy[phy->number];
-
- memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
- }
-
sas_unregister_dev(dev->port, dev);
}
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 8b7c71e779a7..aa6a68e235c9 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -249,6 +249,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
/* Issue set host interrupt command to send cmd out. */
ha->flags.mbox_int = 0;
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+ reinit_completion(&ha->mbx_intr_comp);
/* Unlock mbx registers and wait for interrupt */
ql_dbg(ql_dbg_mbx, vha, 0x100f,
@@ -275,6 +276,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
"cmd=%x Timeout.\n", command);
spin_lock_irqsave(&ha->hardware_lock, flags);
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+ reinit_completion(&ha->mbx_intr_comp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (chip_reset != ha->chip_reset) {
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a6ecb4bb7456..63c3610db82f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1752,12 +1752,6 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
- if (qla2x00_chip_is_down(vha)) {
- req->outstanding_cmds[cnt] = NULL;
- sp->done(sp, res);
- continue;
- }
-
switch (sp->cmd_type) {
case TYPE_SRB:
qla2x00_abort_srb(qp, sp, res, &flags);
@@ -3288,13 +3282,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
base_vha->mgmt_svr_loop_id, host->sg_tablesize);
if (ha->mqenable) {
- bool startit = false;
-
- if (QLA_TGT_MODE_ENABLED())
- startit = false;
-
- if (ql2x_ini_mode == QLA2XXX_INI_MODE_ENABLED)
- startit = true;
+ bool startit = !!(host->active_mode & MODE_INITIATOR);
/* Create start of day qpairs for Block MQ */
for (i = 0; i < ha->max_qpairs; i++)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 646bf8e998a0..b24e80a9c8ca 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -732,6 +732,8 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
sg_remove_request(sfp, srp);
return -EFAULT;
}
+ hp->duration = jiffies_to_msecs(jiffies);
+
if (hp->interface_id != 'S') {
sg_remove_request(sfp, srp);
return -ENOSYS;
@@ -817,7 +819,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return -ENODEV;
}
- hp->duration = jiffies_to_msecs(jiffies);
if (hp->interface_id != '\0' && /* v3 (or later) interface */
(SG_FLAG_Q_AT_TAIL & hp->flags))
at_head = 0;
@@ -1361,9 +1362,6 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
"sg_cmd_done: pack_id=%d, res=0x%x\n",
srp->header.pack_id, result));
srp->header.resid = resid;
- ms = jiffies_to_msecs(jiffies);
- srp->header.duration = (ms > srp->header.duration) ?
- (ms - srp->header.duration) : 0;
if (0 != result) {
struct scsi_sense_hdr sshdr;
@@ -1413,6 +1411,9 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
done = 0;
}
srp->done = done;
+ ms = jiffies_to_msecs(jiffies);
+ srp->header.duration = (ms > srp->header.duration) ?
+ (ms - srp->header.duration) : 0;
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
if (likely(done)) {
@@ -2560,6 +2561,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
const sg_io_hdr_t *hp;
const char * cp;
unsigned int ms;
+ unsigned int duration;
k = 0;
list_for_each_entry(fp, &sdp->sfds, sfd_siblings) {
@@ -2598,13 +2600,17 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
seq_printf(s, " id=%d blen=%d",
srp->header.pack_id, blen);
if (srp->done)
- seq_printf(s, " dur=%d", hp->duration);
+ seq_printf(s, " dur=%u", hp->duration);
else {
ms = jiffies_to_msecs(jiffies);
- seq_printf(s, " t_o/elap=%d/%d",
+ duration = READ_ONCE(hp->duration);
+ if (duration)
+ duration = (ms > duration ?
+ ms - duration : 0);
+ seq_printf(s, " t_o/elap=%u/%u",
(new_interface ? hp->timeout :
jiffies_to_msecs(fp->timeout)),
- (ms > hp->duration ? ms - hp->duration : 0));
+ duration);
}
seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
(int) srp->data.cmd_opcode);
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index 22302612e032..3c2a07bf9209 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -133,6 +133,7 @@ static int sim710_probe_common(struct device *dev, unsigned long base_addr,
out_put_host:
scsi_host_put(host);
out_release:
+ ioport_unmap(hostdata->base);
release_region(base_addr, 64);
out_free:
kfree(hostdata);
@@ -148,6 +149,7 @@ static int sim710_device_remove(struct device *dev)
scsi_remove_host(host);
NCR_700_release(host);
+ ioport_unmap(hostdata->base);
kfree(hostdata);
free_irq(host->irq, host);
release_region(host->base, 64);
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index fa607f218250..2b074b26db72 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -1849,6 +1849,7 @@ static int stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_scsi_host_put:
scsi_host_put(host);
out_disable:
+ unregister_reboot_notifier(&stex_notifier);
pci_disable_device(pdev);
return err;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a212e6ad11d5..c5f41023c71b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5766,10 +5766,12 @@ static void ufshcd_err_handler(struct work_struct *work)
spin_unlock_irqrestore(hba->host->host_lock, flags);
return;
}
- ufshcd_set_eh_in_progress(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
+
ufshcd_err_handling_prepare(hba);
+
spin_lock_irqsave(hba->host->host_lock, flags);
+ ufshcd_set_eh_in_progress(hba);
ufshcd_scsi_block_requests(hba);
/*
* A full reset and restore might have happened after preparation
diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c
index d0329ad170d1..677a4ce1c8cb 100644
--- a/drivers/soc/amlogic/meson-canvas.c
+++ b/drivers/soc/amlogic/meson-canvas.c
@@ -72,10 +72,9 @@ struct meson_canvas *meson_canvas_get(struct device *dev)
* current state, this driver probe cannot return -EPROBE_DEFER
*/
canvas = dev_get_drvdata(&canvas_pdev->dev);
- if (!canvas) {
- put_device(&canvas_pdev->dev);
+ put_device(&canvas_pdev->dev);
+ if (!canvas)
return ERR_PTR(-EINVAL);
- }
return canvas;
}
diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c
index 8b80c8e94c77..bfebdcaf8814 100644
--- a/drivers/soc/qcom/ocmem.c
+++ b/drivers/soc/qcom/ocmem.c
@@ -211,9 +211,9 @@ struct ocmem *of_get_ocmem(struct device *dev)
of_node_put(devnode);
ocmem = platform_get_drvdata(pdev);
+ put_device(&pdev->dev);
if (!ocmem) {
dev_err(dev, "Cannot get ocmem\n");
- put_device(&pdev->dev);
return ERR_PTR(-ENODEV);
}
return ocmem;
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 63302e21e574..8c679402093b 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -369,7 +369,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
if (t->bits_per_word == 16 || t->bits_per_word == 32)
t->bits_per_word = 8; /* pretend its 8 bits */
if (t->bits_per_word == 8 && t->len >= 256 &&
- (mpc8xxx_spi->flags & SPI_CPM1))
+ !(t->len & 1) && (mpc8xxx_spi->flags & SPI_CPM1))
t->bits_per_word = 16;
}
}
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f1a0073a8700..a4e35c2f7d6e 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -493,9 +493,15 @@ static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
{
u32 reg;
- reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
- reg |= MX51_ECSPI_CTRL_XCH;
- writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
+ if (spi_imx->usedma) {
+ reg = readl(spi_imx->base + MX51_ECSPI_DMA);
+ reg |= MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN;
+ writel(reg, spi_imx->base + MX51_ECSPI_DMA);
+ } else {
+ reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
+ reg |= MX51_ECSPI_CTRL_XCH;
+ writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
+ }
}
static void mx51_disable_dma(struct spi_imx_data *spi_imx)
@@ -650,7 +656,6 @@ static void mx51_setup_wml(struct spi_imx_data *spi_imx)
writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) |
MX51_ECSPI_DMA_TX_WML(spi_imx->wml) |
MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
- MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN |
MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA);
}
@@ -1424,6 +1429,8 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
reinit_completion(&spi_imx->dma_tx_completion);
dma_async_issue_pending(master->dma_tx);
+ spi_imx->devtype_data->trigger(spi_imx);
+
transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
/* Wait SDMA to finish the data transfer.*/
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 523edfdf5dcd..d497fc4bc19e 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -298,7 +298,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
/* Read out all the data from the Rx FIFO */
rx_words = n_words;
- stalled = 10;
+ stalled = 32;
while (rx_words) {
if (rx_words == n_words && !(stalled--) &&
!(sr & XSPI_SR_TX_EMPTY_MASK) &&
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 854b8bdc57a1..de89922e7397 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2961,7 +2961,12 @@ static int compat_chaninfo(struct file *file, unsigned long arg)
chaninfo.rangelist = compat_ptr(chaninfo32.rangelist);
mutex_lock(&dev->mutex);
- err = do_chaninfo_ioctl(dev, &chaninfo);
+ if (!dev->attached) {
+ dev_dbg(dev->class_dev, "no driver attached\n");
+ err = -ENODEV;
+ } else {
+ err = do_chaninfo_ioctl(dev, &chaninfo);
+ }
mutex_unlock(&dev->mutex);
return err;
}
@@ -2982,7 +2987,12 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
rangeinfo.range_ptr = compat_ptr(rangeinfo32.range_ptr);
mutex_lock(&dev->mutex);
- err = do_rangeinfo_ioctl(dev, &rangeinfo);
+ if (!dev->attached) {
+ dev_dbg(dev->class_dev, "no driver attached\n");
+ err = -ENODEV;
+ } else {
+ err = do_rangeinfo_ioctl(dev, &rangeinfo);
+ }
mutex_unlock(&dev->mutex);
return err;
}
@@ -3058,7 +3068,12 @@ static int compat_cmd(struct file *file, unsigned long arg)
return rc;
mutex_lock(&dev->mutex);
- rc = do_cmd_ioctl(dev, &cmd, ©, file);
+ if (!dev->attached) {
+ dev_dbg(dev->class_dev, "no driver attached\n");
+ rc = -ENODEV;
+ } else {
+ rc = do_cmd_ioctl(dev, &cmd, ©, file);
+ }
mutex_unlock(&dev->mutex);
if (copy) {
/* Special case: copy cmd back to user. */
@@ -3083,7 +3098,12 @@ static int compat_cmdtest(struct file *file, unsigned long arg)
return rc;
mutex_lock(&dev->mutex);
- rc = do_cmdtest_ioctl(dev, &cmd, ©, file);
+ if (!dev->attached) {
+ dev_dbg(dev->class_dev, "no driver attached\n");
+ rc = -ENODEV;
+ } else {
+ rc = do_cmdtest_ioctl(dev, &cmd, ©, file);
+ }
mutex_unlock(&dev->mutex);
if (copy) {
err = put_compat_cmd(compat_ptr(arg), &cmd);
@@ -3143,7 +3163,12 @@ static int compat_insnlist(struct file *file, unsigned long arg)
}
mutex_lock(&dev->mutex);
- rc = do_insnlist_ioctl(dev, insns, insnlist32.n_insns, file);
+ if (!dev->attached) {
+ dev_dbg(dev->class_dev, "no driver attached\n");
+ rc = -ENODEV;
+ } else {
+ rc = do_insnlist_ioctl(dev, insns, insnlist32.n_insns, file);
+ }
mutex_unlock(&dev->mutex);
kfree(insns);
return rc;
@@ -3162,7 +3187,12 @@ static int compat_insn(struct file *file, unsigned long arg)
return rc;
mutex_lock(&dev->mutex);
- rc = do_insn_ioctl(dev, &insn, file);
+ if (!dev->attached) {
+ dev_dbg(dev->class_dev, "no driver attached\n");
+ rc = -ENODEV;
+ } else {
+ rc = do_insn_ioctl(dev, &insn, file);
+ }
mutex_unlock(&dev->mutex);
return rc;
}
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index 786fd15698df..a72ec43df1df 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -250,9 +250,6 @@ static int c6xdigio_attach(struct comedi_device *dev,
if (ret)
return ret;
- /* Make sure that PnP ports get activated */
- pnp_register_driver(&c6xdigio_pnp_driver);
-
s = &dev->subdevices[0];
/* pwm output subdevice */
s->type = COMEDI_SUBD_PWM;
@@ -279,19 +276,46 @@ static int c6xdigio_attach(struct comedi_device *dev,
return 0;
}
-static void c6xdigio_detach(struct comedi_device *dev)
-{
- comedi_legacy_detach(dev);
- pnp_unregister_driver(&c6xdigio_pnp_driver);
-}
-
static struct comedi_driver c6xdigio_driver = {
.driver_name = "c6xdigio",
.module = THIS_MODULE,
.attach = c6xdigio_attach,
- .detach = c6xdigio_detach,
+ .detach = comedi_legacy_detach,
};
-module_comedi_driver(c6xdigio_driver);
+
+static bool c6xdigio_pnp_registered = false;
+
+static int __init c6xdigio_module_init(void)
+{
+ int ret;
+
+ ret = comedi_driver_register(&c6xdigio_driver);
+ if (ret)
+ return ret;
+
+ if (IS_ENABLED(CONFIG_PNP)) {
+ /* Try to activate the PnP ports */
+ ret = pnp_register_driver(&c6xdigio_pnp_driver);
+ if (ret) {
+ pr_warn("failed to register pnp driver - err %d\n",
+ ret);
+ ret = 0; /* ignore the error. */
+ } else {
+ c6xdigio_pnp_registered = true;
+ }
+ }
+
+ return 0;
+}
+module_init(c6xdigio_module_init);
+
+static void __exit c6xdigio_module_exit(void)
+{
+ if (c6xdigio_pnp_registered)
+ pnp_unregister_driver(&c6xdigio_pnp_driver);
+ comedi_driver_unregister(&c6xdigio_driver);
+}
+module_exit(c6xdigio_module_exit);
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi driver for the C6x_DIGIO DSP daughter card");
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index c1897aee9a9a..6292842505f5 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -68,6 +68,11 @@
#define MULTIQ3_TRSFRCNTR_OL 0x10 /* xfer CNTR to OL (x and y) */
#define MULTIQ3_EFLAG_RESET 0x06 /* reset E bit of flag reg */
+/*
+ * Limit on the number of optional encoder channels
+ */
+#define MULTIQ3_MAX_ENC_CHANS 8
+
static void multiq3_set_ctrl(struct comedi_device *dev, unsigned int bits)
{
/*
@@ -313,6 +318,10 @@ static int multiq3_attach(struct comedi_device *dev,
s->insn_read = multiq3_encoder_insn_read;
s->insn_config = multiq3_encoder_insn_config;
+ /* sanity check for number of encoder channels */
+ if (s->n_chan > MULTIQ3_MAX_ENC_CHANS)
+ s->n_chan = MULTIQ3_MAX_ENC_CHANS;
+
for (i = 0; i < s->n_chan; i++)
multiq3_encoder_reset(dev, i);
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 2c04fcff0e1c..723ca72d1bd3 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -1229,8 +1229,8 @@ int fbtft_probe_common(struct fbtft_display *display,
par->pdev = pdev;
if (display->buswidth == 0) {
- dev_err(dev, "buswidth is not set\n");
- return -EINVAL;
+ ret = dev_err_probe(dev, -EINVAL, "buswidth is not set\n");
+ goto out_release;
}
/* write register functions */
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
index b912ad2f4b72..1144749b4f58 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -1281,6 +1281,9 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
status = _STATS_FAILURE_;
goto OnAssocReqFail;
} else {
+ if (ie_len > sizeof(supportRate))
+ ie_len = sizeof(supportRate);
+
memcpy(supportRate, p+2, ie_len);
supportRateNum = ie_len;
@@ -1288,7 +1291,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
pkt_len - WLAN_HDR_A3_LEN - ie_offset);
if (p != NULL) {
- if (supportRateNum <= sizeof(supportRate)) {
+ if (supportRateNum + ie_len <= sizeof(supportRate)) {
memcpy(supportRate+supportRateNum, p+2, ie_len);
supportRateNum += ie_len;
}
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index e6996428c07d..182a89ecc542 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -2635,7 +2635,6 @@ static ssize_t target_lu_gp_members_show(struct config_item *item, char *page)
cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&dev->dev_group.cg_item));
- cur_len++; /* Extra byte for NULL terminator */
if ((cur_len + len) > PAGE_SIZE || cur_len > LU_GROUP_NAME_BUF) {
pr_warn("Ran out of lu_gp_show_attr"
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 8d294b658592..ddcfd5c17d96 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1449,6 +1449,7 @@ target_cmd_init_cdb(struct se_cmd *cmd, unsigned char *cdb)
cmd->t_task_cdb = kzalloc(scsi_command_size(cdb),
GFP_KERNEL);
if (!cmd->t_task_cdb) {
+ cmd->t_task_cdb = &cmd->__t_task_cdb[0];
pr_err("Unable to allocate cmd->t_task_cdb"
" %u > sizeof(cmd->__t_task_cdb): %lu ops\n",
scsi_command_size(cdb),
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index ea32b5c03e70..fd34fbc9cdee 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1926,6 +1926,11 @@ pci_moxa_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_MOXA_CP138E_A 0x1381
#define PCI_DEVICE_ID_MOXA_CP168EL_A 0x1683
+#define PCI_DEVICE_ID_ADDIDATA_CPCI7500 0x7003
+#define PCI_DEVICE_ID_ADDIDATA_CPCI7500_NG 0x7024
+#define PCI_DEVICE_ID_ADDIDATA_CPCI7420_NG 0x7025
+#define PCI_DEVICE_ID_ADDIDATA_CPCI7300_NG 0x7026
+
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
@@ -5753,6 +5758,38 @@ static const struct pci_device_id serial_pci_tbl[] = {
0,
pbn_ADDIDATA_PCIe_8_3906250 },
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_CPCI7500,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_4_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_CPCI7500_NG,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_4_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_CPCI7420_NG,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_2_115200 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_CPCI7300_NG,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_b0_1_115200 },
+
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
PCI_VENDOR_ID_IBM, 0x0299,
0, 0, pbn_b0_bt_2_115200 },
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index a1952e4f1fcb..e850959ecf55 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -1137,6 +1137,9 @@ static int sprd_clk_init(struct uart_port *uport)
clk_uart = devm_clk_get(uport->dev, "uart");
if (IS_ERR(clk_uart)) {
+ if (PTR_ERR(clk_uart) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
dev_warn(uport->dev, "uart%d can't get uart clock\n",
uport->line);
clk_uart = NULL;
@@ -1144,6 +1147,9 @@ static int sprd_clk_init(struct uart_port *uport)
clk_parent = devm_clk_get(uport->dev, "source");
if (IS_ERR(clk_parent)) {
+ if (PTR_ERR(clk_parent) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
dev_warn(uport->dev, "uart%d can't get source clock\n",
uport->line);
clk_parent = NULL;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index d64aaff223e7..059ea576c6c1 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -2381,7 +2381,7 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
break;
case USB_CDC_MBIM_EXTENDED_TYPE:
if (elength < sizeof(struct usb_cdc_mbim_extended_desc))
- break;
+ goto next_desc;
hdr->usb_cdc_mbim_extended_desc =
(struct usb_cdc_mbim_extended_desc *)buffer;
break;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index f421650cfa03..db667038c8eb 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -341,8 +341,11 @@ static void dwc2_driver_shutdown(struct platform_device *dev)
{
struct dwc2_hsotg *hsotg = platform_get_drvdata(dev);
- dwc2_disable_global_interrupts(hsotg);
- synchronize_irq(hsotg->irq);
+ if (hsotg->ll_hw_enabled) {
+ dwc2_disable_global_interrupts(hsotg);
+ synchronize_irq(hsotg->irq);
+ dwc2_lowlevel_hw_disable(hsotg);
+ }
}
/**
@@ -623,9 +626,13 @@ static int dwc2_driver_probe(struct platform_device *dev)
static int __maybe_unused dwc2_suspend(struct device *dev)
{
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
- bool is_device_mode = dwc2_is_device_mode(dwc2);
+ bool is_device_mode;
int ret = 0;
+ if (!dwc2->ll_hw_enabled)
+ return 0;
+
+ is_device_mode = dwc2_is_device_mode(dwc2);
if (is_device_mode)
dwc2_hsotg_suspend(dwc2);
@@ -676,6 +683,9 @@ static int __maybe_unused dwc2_resume(struct device *dev)
struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
int ret = 0;
+ if (!dwc2->ll_hw_enabled)
+ return 0;
+
if (dwc2->phy_off_for_suspend && dwc2->ll_hw_enabled) {
ret = __dwc2_lowlevel_hw_enable(dwc2);
if (ret)
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index e62ecd22b3ed..32f4df566ce8 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -71,11 +71,11 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
simple->num_clocks = ret;
ret = clk_bulk_prepare_enable(simple->num_clocks, simple->clks);
if (ret)
- goto err_resetc_assert;
+ goto err_clk_put_all;
ret = of_platform_populate(np, NULL, NULL, dev);
if (ret)
- goto err_clk_put;
+ goto err_clk_disable;
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -83,8 +83,9 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
return 0;
-err_clk_put:
+err_clk_disable:
clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
+err_clk_put_all:
clk_bulk_put_all(simple->num_clocks, simple->clks);
err_resetc_assert:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7aa4a7a46233..5ea6d0c929db 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -4109,7 +4109,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
if (!dwc->gadget)
return;
- dwc3_enable_susphy(dwc, false);
+ dwc3_enable_susphy(dwc, true);
usb_del_gadget(dwc->gadget);
dwc3_gadget_free_endpoints(dwc);
usb_put_gadget(dwc->gadget);
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 05718f6fa60d..9fa76abdaadc 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -155,7 +155,7 @@ int dwc3_host_init(struct dwc3 *dwc)
void dwc3_host_exit(struct dwc3 *dwc)
{
- dwc3_enable_susphy(dwc, false);
+ dwc3_enable_susphy(dwc, true);
platform_device_unregister(dwc->xhci);
dwc->xhci = NULL;
}
diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index d9cbbde8ff59..a82c6e19572b 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -38,6 +38,7 @@ MODULE_LICENSE("GPL");
static DEFINE_IDA(driver_id_numbers);
#define DRIVER_DRIVER_NAME_LENGTH_MAX 32
+#define USB_RAW_IO_LENGTH_MAX KMALLOC_MAX_SIZE
#define RAW_EVENT_QUEUE_SIZE 16
@@ -619,6 +620,8 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr,
return ERR_PTR(-EINVAL);
if (!usb_raw_io_flags_valid(io->flags))
return ERR_PTR(-EINVAL);
+ if (io->length > USB_RAW_IO_LENGTH_MAX)
+ return ERR_PTR(-EINVAL);
if (get_from_user)
data = memdup_user(ptr + sizeof(*io), io->length);
else {
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index dd2fafc5b0c3..598053bf985d 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -1037,8 +1037,13 @@ static void usb_gadget_state_work(struct work_struct *work)
void usb_gadget_set_state(struct usb_gadget *gadget,
enum usb_device_state state)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&gadget->state_lock, flags);
gadget->state = state;
- schedule_work(&gadget->work);
+ if (!gadget->teardown)
+ schedule_work(&gadget->work);
+ spin_unlock_irqrestore(&gadget->state_lock, flags);
}
EXPORT_SYMBOL_GPL(usb_gadget_set_state);
@@ -1199,6 +1204,8 @@ void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget,
void (*release)(struct device *dev))
{
dev_set_name(&gadget->dev, "gadget");
+ spin_lock_init(&gadget->state_lock);
+ gadget->teardown = false;
INIT_WORK(&gadget->work, usb_gadget_state_work);
gadget->dev.parent = parent;
@@ -1376,6 +1383,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
void usb_del_gadget(struct usb_gadget *gadget)
{
struct usb_udc *udc = gadget->udc;
+ unsigned long flags;
if (!udc)
return;
@@ -1394,6 +1402,13 @@ void usb_del_gadget(struct usb_gadget *gadget)
mutex_unlock(&udc_lock);
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
+ /*
+ * Set the teardown flag before flushing the work to prevent new work
+ * from being scheduled while we are cleaning up.
+ */
+ spin_lock_irqsave(&gadget->state_lock, flags);
+ gadget->teardown = true;
+ spin_unlock_irqrestore(&gadget->state_lock, flags);
flush_work(&gadget->work);
device_unregister(&udc->dev);
device_del(&gadget->dev);
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 314cb5ea061a..172017998e15 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3026,7 +3026,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
if (retval)
- return retval;
+ goto err_put_client;
udc->board = &lpc32xx_usbddata;
@@ -3044,28 +3044,32 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
/* Get IRQs */
for (i = 0; i < 4; i++) {
udc->udp_irq[i] = platform_get_irq(pdev, i);
- if (udc->udp_irq[i] < 0)
- return udc->udp_irq[i];
+ if (udc->udp_irq[i] < 0) {
+ retval = udc->udp_irq[i];
+ goto err_put_client;
+ }
}
udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(udc->udp_baseaddr)) {
dev_err(udc->dev, "IO map failure\n");
- return PTR_ERR(udc->udp_baseaddr);
+ retval = PTR_ERR(udc->udp_baseaddr);
+ goto err_put_client;
}
/* Get USB device clock */
udc->usb_slv_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(udc->usb_slv_clk)) {
dev_err(udc->dev, "failed to acquire USB device clock\n");
- return PTR_ERR(udc->usb_slv_clk);
+ retval = PTR_ERR(udc->usb_slv_clk);
+ goto err_put_client;
}
/* Enable USB device clock */
retval = clk_prepare_enable(udc->usb_slv_clk);
if (retval < 0) {
dev_err(udc->dev, "failed to start USB device clock\n");
- return retval;
+ goto err_put_client;
}
/* Setup deferred workqueue data */
@@ -3168,6 +3172,9 @@ static int lpc32xx_udc_probe(struct platform_device *pdev)
udc->udca_v_base, udc->udca_p_base);
i2c_fail:
clk_disable_unprepare(udc->usb_slv_clk);
+err_put_client:
+ put_device(&udc->isp1301_i2c_client->dev);
+
dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
return retval;
@@ -3194,6 +3201,7 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
clk_disable_unprepare(udc->usb_slv_clk);
+ put_device(&udc->isp1301_i2c_client->dev);
return 0;
}
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 7f159ed1fa41..ca472fde0d64 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -1542,12 +1542,6 @@ static int __tegra_xudc_ep_set_halt(struct tegra_xudc_ep *ep, bool halt)
return -ENOTSUPP;
}
- if (!!(xudc_readl(xudc, EP_HALT) & BIT(ep->index)) == halt) {
- dev_dbg(xudc->dev, "EP %u already %s\n", ep->index,
- halt ? "halted" : "not halted");
- return 0;
- }
-
if (halt) {
ep_halt(xudc, ep->index);
} else {
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 106a6bcefb08..a1555bce22d0 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -51,8 +51,6 @@ static struct hc_driver __read_mostly ohci_nxp_hc_driver;
static struct i2c_client *isp1301_i2c_client;
-static struct clk *usb_host_clk;
-
static void isp1301_configure_lpc32xx(void)
{
/* LPC32XX only supports DAT_SE0 USB mode */
@@ -155,6 +153,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
struct resource *res;
int ret = 0, irq;
struct device_node *isp1301_node;
+ struct clk *usb_host_clk;
if (pdev->dev.of_node) {
isp1301_node = of_parse_phandle(pdev->dev.of_node,
@@ -180,26 +179,20 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
}
/* Enable USB host clock */
- usb_host_clk = devm_clk_get(&pdev->dev, NULL);
+ usb_host_clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(usb_host_clk)) {
- dev_err(&pdev->dev, "failed to acquire USB OHCI clock\n");
+ dev_err(&pdev->dev, "failed to acquire and start USB OHCI clock\n");
ret = PTR_ERR(usb_host_clk);
goto fail_disable;
}
- ret = clk_prepare_enable(usb_host_clk);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to start USB OHCI clock\n");
- goto fail_disable;
- }
-
isp1301_configure();
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
if (!hcd) {
dev_err(&pdev->dev, "Failed to allocate HC buffer\n");
ret = -ENOMEM;
- goto fail_hcd;
+ goto fail_disable;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -230,9 +223,8 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
ohci_nxp_stop_hc();
fail_resource:
usb_put_hcd(hcd);
-fail_hcd:
- clk_disable_unprepare(usb_host_clk);
fail_disable:
+ put_device(&isp1301_i2c_client->dev);
isp1301_i2c_client = NULL;
return ret;
}
@@ -244,7 +236,7 @@ static int ohci_hcd_nxp_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
ohci_nxp_stop_hc();
usb_put_hcd(hcd);
- clk_disable_unprepare(usb_host_clk);
+ put_device(&isp1301_i2c_client->dev);
isp1301_i2c_client = NULL;
return 0;
diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c
index 980235169d81..d03eea7beeca 100644
--- a/drivers/usb/host/xhci-dbgtty.c
+++ b/drivers/usb/host/xhci-dbgtty.c
@@ -468,6 +468,12 @@ static void xhci_dbc_tty_unregister_device(struct xhci_dbc *dbc)
if (!port->registered)
return;
+ /*
+ * Hang up the TTY. This wakes up any blocked
+ * writers and causes subsequent writes to fail.
+ */
+ tty_vhangup(port->port.tty);
+
tty_unregister_device(dbc_tty_driver, 0);
xhci_dbc_tty_exit_port(port);
port->registered = false;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 05f119e7178c..a7a7f0a8488a 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1564,7 +1564,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
* SS devices are only visible to roothub after link training completes.
* Keep polling roothubs for a grace period after xHC start
*/
- if (xhci->run_graceperiod) {
+ if (hcd->speed >= HCD_USB3 && xhci->run_graceperiod) {
if (time_before(jiffies, xhci->run_graceperiod))
status = 1;
else
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index e681c0dd9fbf..7220c3a55dde 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -133,10 +133,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
if (!ring || !first || !last)
return;
- /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
- chain_links = !!(xhci_link_trb_quirk(xhci) ||
- (ring->type == TYPE_ISOC &&
- (xhci->quirks & XHCI_AMD_0x96_HOST)));
+ chain_links = xhci_link_chain_quirk(xhci, ring->type);
next = ring->enq_seg->next;
xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
@@ -326,10 +323,7 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
struct xhci_segment *prev;
bool chain_links;
- /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
- chain_links = !!(xhci_link_trb_quirk(xhci) ||
- (type == TYPE_ISOC &&
- (xhci->quirks & XHCI_AMD_0x96_HOST)));
+ chain_links = xhci_link_chain_quirk(xhci, type);
prev = xhci_segment_alloc(xhci, cycle_state, max_packet, flags);
if (!prev)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bf2787bb04ea..a337e1fda33d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -230,9 +230,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
* AMD 0.96 host, carry over the chain bit of the previous TRB
* (which may mean the chain bit is cleared).
*/
- if (!(ring->type == TYPE_ISOC &&
- (xhci->quirks & XHCI_AMD_0x96_HOST)) &&
- !xhci_link_trb_quirk(xhci)) {
+ if (!xhci_link_chain_quirk(xhci, ring->type)) {
next->link.control &= cpu_to_le32(~TRB_CHAIN);
next->link.control |= cpu_to_le32(chain);
}
@@ -3138,9 +3136,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
/* If we're not dealing with 0.95 hardware or isoc rings
* on AMD 0.96 host, clear the chain bit.
*/
- if (!xhci_link_trb_quirk(xhci) &&
- !(ep_ring->type == TYPE_ISOC &&
- (xhci->quirks & XHCI_AMD_0x96_HOST)))
+ if (!xhci_link_chain_quirk(xhci, ep_ring->type))
ep_ring->enqueue->link.control &=
cpu_to_le32(~TRB_CHAIN);
else
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6bb1ddc3918c..4d4ac8ec614b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1998,9 +1998,21 @@ static inline void xhci_write_64(struct xhci_hcd *xhci,
lo_hi_writeq(val, regs);
}
-static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
+
+/*
+ * Reportedly, some chapters of v0.95 spec said that Link TRB always has its chain bit set.
+ * Other chapters and later specs say that it should only be set if the link is inside a TD
+ * which continues from the end of one segment to the next segment.
+ *
+ * Some 0.95 hardware was found to misbehave if any link TRB doesn't have the chain bit set.
+ *
+ * 0.96 hardware from AMD and NEC was found to ignore unchained isochronous link TRBs when
+ * "resynchronizing the pipe" after a Missed Service Error.
+ */
+static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type)
{
- return xhci->quirks & XHCI_LINK_TRB_QUIRK;
+ return (xhci->quirks & XHCI_LINK_TRB_QUIRK) ||
+ (type == TYPE_ISOC && (xhci->quirks & (XHCI_AMD_0x96_HOST | XHCI_NEC_HOST)));
}
/* xHCI debugging */
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
index d99d424c05a7..50909cc9a0bb 100644
--- a/drivers/usb/misc/chaoskey.c
+++ b/drivers/usb/misc/chaoskey.c
@@ -445,9 +445,19 @@ static ssize_t chaoskey_read(struct file *file,
goto bail;
mutex_unlock(&dev->rng_lock);
- result = mutex_lock_interruptible(&dev->lock);
- if (result)
- goto bail;
+ if (file->f_flags & O_NONBLOCK) {
+ result = mutex_trylock(&dev->lock);
+ if (result == 0) {
+ result = -EAGAIN;
+ goto bail;
+ } else {
+ result = 0;
+ }
+ } else {
+ result = mutex_lock_interruptible(&dev->lock);
+ if (result)
+ goto bail;
+ }
if (dev->valid == dev->used) {
result = _chaoskey_fill(dev);
if (result < 0) {
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index c63e545fb105..dfa0d5ce6012 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -1345,24 +1345,6 @@ static int sisusbdummycon_blank(struct vc_data *vc, int blank, int mode_switch)
return 0;
}
-static int sisusbdummycon_font_set(struct vc_data *vc,
- struct console_font *font,
- unsigned int flags)
-{
- return 0;
-}
-
-static int sisusbdummycon_font_default(struct vc_data *vc,
- struct console_font *font, char *name)
-{
- return 0;
-}
-
-static int sisusbdummycon_font_copy(struct vc_data *vc, int con)
-{
- return 0;
-}
-
static const struct consw sisusb_dummy_con = {
.owner = THIS_MODULE,
.con_startup = sisusbdummycon_startup,
@@ -1375,9 +1357,6 @@ static const struct consw sisusb_dummy_con = {
.con_scroll = sisusbdummycon_scroll,
.con_switch = sisusbdummycon_switch,
.con_blank = sisusbdummycon_blank,
- .con_font_set = sisusbdummycon_font_set,
- .con_font_default = sisusbdummycon_font_default,
- .con_font_copy = sisusbdummycon_font_copy,
};
int
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 5adbf7fd24fd..3ed8d67e887f 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -634,6 +634,8 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
return -EINVAL;
}
+ INIT_LIST_HEAD(&x->head);
+
usb_charger_init(x);
ret = usb_add_extcon(x);
if (ret)
@@ -679,6 +681,8 @@ int usb_add_phy_dev(struct usb_phy *x)
return -EINVAL;
}
+ INIT_LIST_HEAD(&x->head);
+
usb_charger_init(x);
ret = usb_add_extcon(x);
if (ret)
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 75fff2e4cbc6..56fc3ff5016f 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -713,11 +713,13 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv,
/* make sure pipe is not busy */
ret = usbhsp_pipe_barrier(pipe);
if (ret < 0) {
+ usbhsp_put_pipe(pipe);
dev_err(dev, "pipe setup failed %d\n", usbhs_pipe_number(pipe));
return NULL;
}
if (usbhsp_setup_pipecfg(pipe, is_host, dir_in, &pipecfg)) {
+ usbhsp_put_pipe(pipe);
dev_err(dev, "can't setup pipe\n");
return NULL;
}
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 9bb123ab9bc9..5a6ba8bc7d9e 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -448,7 +448,7 @@ static int belkin_sa_tiocmset(struct tty_struct *tty,
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned long control_state;
unsigned long flags;
- int retval;
+ int retval = 0;
int rts = 0;
int dtr = 0;
@@ -465,26 +465,32 @@ static int belkin_sa_tiocmset(struct tty_struct *tty,
}
if (clear & TIOCM_RTS) {
control_state &= ~TIOCM_RTS;
- rts = 0;
+ rts = 1;
}
if (clear & TIOCM_DTR) {
control_state &= ~TIOCM_DTR;
- dtr = 0;
+ dtr = 1;
}
priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags);
- retval = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, rts);
- if (retval < 0) {
- dev_err(&port->dev, "Set RTS error %d\n", retval);
- goto exit;
+ if (rts) {
+ retval = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST,
+ !!(control_state & TIOCM_RTS));
+ if (retval < 0) {
+ dev_err(&port->dev, "Set RTS error %d\n", retval);
+ goto exit;
+ }
}
- retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, dtr);
- if (retval < 0) {
- dev_err(&port->dev, "Set DTR error %d\n", retval);
- goto exit;
+ if (dtr) {
+ retval = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST,
+ !!(control_state & TIOCM_DTR));
+ if (retval < 0) {
+ dev_err(&port->dev, "Set DTR error %d\n", retval);
+ goto exit;
+ }
}
exit:
return retval;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 4e0b82459199..17e03baf09a2 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -606,10 +606,8 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
- { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_TIAO_UMPA_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_NT_ORIONLXM_PID, 1) },
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLX_PLUS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORION_IO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONMX_PID) },
@@ -820,24 +818,17 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
- { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, CYBER_CORTEX_AV_PID, 1) },
{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) },
{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) },
{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) },
{ USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) },
- { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(FIC_VID, FIC_NEO1973_DEBUG_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_OOCDLINK_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, LMI_LM3S_DEVEL_BOARD_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_TURTELIZER_PID, 1) },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
@@ -879,17 +870,14 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(ATMEL_VID, STK541_PID) },
{ USB_DEVICE(DE_VID, STB_PID) },
{ USB_DEVICE(DE_VID, WHT_PID) },
- { USB_DEVICE(ADI_VID, ADI_GNICE_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(ADI_VID, ADI_GNICE_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(ADI_VID, ADI_GNICEPLUS_PID, 1) },
{ USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
USB_CLASS_VENDOR_SPEC,
USB_SUBCLASS_VENDOR_SPEC, 0x00) },
{ USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
- { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(MARVELL_VID, MARVELL_SHEEVAPLUG_PID, 1) },
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
{ USB_DEVICE(FTDI_VID, PI_C865_PID) },
@@ -912,10 +900,8 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(PI_VID, PI_1016_PID) },
{ USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
- { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, MARVELL_OPENRD_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, TI_XDS100V2_PID, 1) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
@@ -924,18 +910,14 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
{ USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) },
{ USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) },
- { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_ST_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, XVERVE_SIGNALYZER_ST_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, XVERVE_SIGNALYZER_SLITE_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, XVERVE_SIGNALYZER_SH2_PID, 1) },
{ USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) },
{ USB_DEVICE(FTDI_VID, ACCESIO_COM4SM_PID) },
- { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(IONICS_VID, IONICS_PLUGCOMPUTER_PID, 1) },
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) },
@@ -950,15 +932,12 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_FHE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
- { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(ST_VID, ST_STMCLT_2232_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(ST_VID, ST_STMCLT_2232_PID, 1) },
{ USB_DEVICE(ST_VID, ST_STMCLT_4232_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
- { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID, 1) },
{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
/* Crucible Devices */
{ USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
@@ -1033,8 +1012,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(ICPDAS_VID, ICPDAS_I7561U_PID) },
{ USB_DEVICE(ICPDAS_VID, ICPDAS_I7563U_PID) },
{ USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) },
- { USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(TI_VID, TI_CC3200_LAUNCHPAD_PID, 1) },
{ USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) },
{ USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) },
{ USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) },
@@ -1054,10 +1032,8 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) },
{ USB_DEVICE_INTERFACE_NUMBER(UBLOX_VID, UBLOX_EVK_M101_PID, 2) },
/* FreeCalypso USB adapters */
- { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID),
- .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID, 1) },
+ { USB_DEVICE_INTERFACE_NUMBER(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID, 1) },
/* GMC devices */
{ USB_DEVICE(GMC_VID, GMC_Z216C_PID) },
/* Altera USB Blaster 3 */
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 49aacb0a327c..a1c3387b6a28 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -421,7 +421,7 @@ static int kobil_tiocmset(struct tty_struct *tty,
struct usb_serial_port *port = tty->driver_data;
struct device *dev = &port->dev;
struct kobil_private *priv;
- int result;
+ int result = 0;
int dtr = 0;
int rts = 0;
@@ -438,12 +438,12 @@ static int kobil_tiocmset(struct tty_struct *tty,
if (set & TIOCM_DTR)
dtr = 1;
if (clear & TIOCM_RTS)
- rts = 0;
+ rts = 1;
if (clear & TIOCM_DTR)
- dtr = 0;
+ dtr = 1;
- if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
- if (dtr != 0)
+ if (dtr && priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
+ if (set & TIOCM_DTR)
dev_dbg(dev, "%s - Setting DTR\n", __func__);
else
dev_dbg(dev, "%s - Clearing DTR\n", __func__);
@@ -451,13 +451,13 @@ static int kobil_tiocmset(struct tty_struct *tty,
usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
+ ((set & TIOCM_DTR) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
0,
NULL,
0,
KOBIL_TIMEOUT);
- } else {
- if (rts != 0)
+ } else if (rts) {
+ if (set & TIOCM_RTS)
dev_dbg(dev, "%s - Setting RTS\n", __func__);
else
dev_dbg(dev, "%s - Clearing RTS\n", __func__);
@@ -465,7 +465,7 @@ static int kobil_tiocmset(struct tty_struct *tty,
usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_SetStatusLinesOrQueues,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
- ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
+ ((set & TIOCM_RTS) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
0,
NULL,
0,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 117feb89f678..aa43c22dfce6 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1433,17 +1433,31 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x60) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c0, 0xff), /* Telit FE910C04 (rmnet) */
.driver_info = RSVD(0) | NCTRL(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c1, 0xff), /* Telit FE910C04 (RNDIS) */
+ .driver_info = NCTRL(4) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c2, 0xff), /* Telit FE910C04 (MBIM) */
+ .driver_info = NCTRL(4) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c3, 0xff), /* Telit FE910C04 (ECM) */
+ .driver_info = NCTRL(4) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c4, 0xff), /* Telit FE910C04 (rmnet) */
.driver_info = RSVD(0) | NCTRL(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c5, 0xff), /* Telit FE910C04 (RNDIS) */
+ .driver_info = NCTRL(4) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c6, 0xff), /* Telit FE910C04 (MBIM) */
+ .driver_info = NCTRL(4) },
+ { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x30), /* Telit FE910C04 (ECM) */
+ .driver_info = NCTRL(4) },
+ { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x40) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c9, 0xff), /* Telit FE910C04 (MBIM) */
+ .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10cb, 0xff), /* Telit FE910C04 (RNDIS) */
+ .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x30), /* Telit FN990B (rmnet) */
.driver_info = NCTRL(5) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x60) },
- { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x30), /* Telit FE910C04 (ECM) */
- .driver_info = NCTRL(4) },
- { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x30), /* Telit FN990B (MBIM) */
.driver_info = NCTRL(6) },
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x40) },
@@ -2376,6 +2390,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0f0, 0xff), /* Foxconn T99W373 MBIM */
.driver_info = RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe123, 0xff), /* Foxconn T99W760 MBIM */
+ .driver_info = RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe145, 0xff), /* Foxconn T99W651 RNDIS */
.driver_info = RSVD(5) | RSVD(6) },
{ USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe15f, 0xff), /* Foxconn T99W709 */
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h
index 1477e31d7763..939a98c2d3f7 100644
--- a/drivers/usb/storage/unusual_uas.h
+++ b/drivers/usb/storage/unusual_uas.h
@@ -98,7 +98,7 @@ UNUSUAL_DEV(0x125f, 0xa94a, 0x0160, 0x0160,
US_FL_NO_ATA_1X),
/* Reported-by: Benjamin Tissoires <benjamin.tissoires@...hat.com> */
-UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999,
+UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x0309,
"Initio Corporation",
"INIC-3069",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 0851d93d5909..60339c746694 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1220,6 +1220,12 @@ static int ucsi_init(struct ucsi *ucsi)
ret = -ENODEV;
goto err_reset;
}
+ /* Check if reserved bit set. This is out of spec but happens in buggy FW */
+ if (ucsi->cap.num_connectors & 0x80) {
+ dev_warn(ucsi->dev, "UCSI: Invalid num_connectors %d. Likely buggy FW\n",
+ ucsi->cap.num_connectors);
+ ucsi->cap.num_connectors &= 0x7f; // clear bit and carry on
+ }
/* Allocate the connectors. Released in ucsi_unregister_ppm() */
ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1,
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 2d2506c59881..e5660f0e97e8 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -830,15 +830,15 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
no_need_xmit:
usb_hcd_unlink_urb_from_ep(hcd, urb);
no_need_unlink:
- spin_unlock_irqrestore(&vhci->lock, flags);
if (!ret) {
/* usb_hcd_giveback_urb() should be called with
* irqs disabled
*/
- local_irq_disable();
+ spin_unlock(&vhci->lock);
usb_hcd_giveback_urb(hcd, urb, urb->status);
- local_irq_enable();
+ spin_lock(&vhci->lock);
}
+ spin_unlock_irqrestore(&vhci->lock, flags);
return ret;
}
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 7bce5f982e58..4b678dbaa93a 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -58,14 +58,15 @@ static u32 vhost_transport_get_local_cid(void)
return VHOST_VSOCK_DEFAULT_HOST_CID;
}
-/* Callers that dereference the return value must hold vhost_vsock_mutex or the
- * RCU read lock.
+/* Callers must be in an RCU read section or hold the vhost_vsock_mutex.
+ * The return value can only be dereferenced while within the section.
*/
static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
{
struct vhost_vsock *vsock;
- hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid) {
+ hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid,
+ lockdep_is_held(&vhost_vsock_mutex)) {
u32 other_cid = vsock->guest_cid;
/* Skip instances that have no CID yet */
@@ -666,9 +667,15 @@ static void vhost_vsock_reset_orphans(struct sock *sk)
* executing.
*/
+ rcu_read_lock();
+
/* If the peer is still valid, no need to reset connection */
- if (vhost_vsock_get(vsk->remote_addr.svm_cid))
+ if (vhost_vsock_get(vsk->remote_addr.svm_cid)) {
+ rcu_read_unlock();
return;
+ }
+
+ rcu_read_unlock();
/* If the close timeout is pending, let it expire. This avoids races
* with the timeout callback.
diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
index 1020e4405a4d..83e8d89cc485 100644
--- a/drivers/video/backlight/led_bl.c
+++ b/drivers/video/backlight/led_bl.c
@@ -209,8 +209,24 @@ static int led_bl_probe(struct platform_device *pdev)
return PTR_ERR(priv->bl_dev);
}
- for (i = 0; i < priv->nb_leds; i++)
+ for (i = 0; i < priv->nb_leds; i++) {
+ struct device_link *link;
+
+ link = device_link_add(&pdev->dev, priv->leds[i]->dev->parent,
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!link) {
+ dev_err(&pdev->dev, "Failed to add devlink (consumer %s, supplier %s)\n",
+ dev_name(&pdev->dev), dev_name(priv->leds[i]->dev->parent));
+ backlight_device_unregister(priv->bl_dev);
+ return -EINVAL;
+ }
+ }
+
+ for (i = 0; i < priv->nb_leds; i++) {
+ mutex_lock(&priv->leds[i]->led_access);
led_sysfs_disable(priv->leds[i]);
+ mutex_unlock(&priv->leds[i]->led_access);
+ }
backlight_update_status(priv->bl_dev);
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index 2a0d0bda7faa..f1711b2f9ff0 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -124,23 +124,6 @@ static int dummycon_switch(struct vc_data *vc)
return 0;
}
-static int dummycon_font_set(struct vc_data *vc, struct console_font *font,
- unsigned int flags)
-{
- return 0;
-}
-
-static int dummycon_font_default(struct vc_data *vc,
- struct console_font *font, char *name)
-{
- return 0;
-}
-
-static int dummycon_font_copy(struct vc_data *vc, int con)
-{
- return 0;
-}
-
/*
* The console `switch' structure for the dummy console
*
@@ -159,8 +142,5 @@ const struct consw dummy_con = {
.con_scroll = dummycon_scroll,
.con_switch = dummycon_switch,
.con_blank = dummycon_blank,
- .con_font_set = dummycon_font_set,
- .con_font_default = dummycon_font_default,
- .con_font_copy = dummycon_font_copy,
};
EXPORT_SYMBOL_GPL(dummy_con);
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 68fb531f245a..19fd3389946d 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -507,7 +507,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
fbfont->width, fbfont->height, fbfont->name);
bpc = ((fbfont->width+7)/8) * fbfont->height;
- size = bpc * 256;
+ size = bpc * fbfont->charcount;
size += sizeof(struct sti_rom_font);
nf = kzalloc(size, STI_LOWMEM);
@@ -515,7 +515,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
return NULL;
nf->first_char = 0;
- nf->last_char = 255;
+ nf->last_char = fbfont->charcount - 1;
nf->width = fbfont->width;
nf->height = fbfont->height;
nf->font_type = STI_FONT_HPROMAN8;
@@ -526,7 +526,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
dest = nf;
dest += sizeof(struct sti_rom_font);
- memcpy(dest, fbfont->data, bpc*256);
+ memcpy(dest, fbfont->data, bpc * fbfont->charcount);
cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
if (!cooked_font) {
@@ -661,7 +661,7 @@ static int sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f)
{
unsigned char *n, *p, *q;
- int size = f->raw->bytes_per_char * 256 + sizeof(struct sti_rom_font);
+ int size = f->raw->bytes_per_char * (f->raw->last_char + 1) + sizeof(struct sti_rom_font);
struct sti_rom_font *old_font;
if (sti->wordmode)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 3dd03e02bf97..478f6628c3a9 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -1006,7 +1006,7 @@ static const char *fbcon_startup(void)
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
vc->vc_font.data = (void *)(p->fontdata = font->data);
- vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
+ vc->vc_font.charcount = font->charcount;
} else {
p->fontdata = vc->vc_font.data;
}
@@ -1034,7 +1034,7 @@ static void fbcon_init(struct vc_data *vc, int init)
struct vc_data **default_mode = vc->vc_display_fg;
struct vc_data *svc = *default_mode;
struct fbcon_display *t, *p = &fb_display[vc->vc_num];
- int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
+ int logo = 1, new_rows, new_cols, rows, cols;
int cap, ret;
if (WARN_ON(info_idx == -1))
@@ -1070,6 +1070,7 @@ static void fbcon_init(struct vc_data *vc, int init)
fvc->vc_font.data);
vc->vc_font.width = fvc->vc_font.width;
vc->vc_font.height = fvc->vc_font.height;
+ vc->vc_font.charcount = fvc->vc_font.charcount;
p->userfont = t->userfont;
if (p->userfont)
@@ -1085,17 +1086,13 @@ static void fbcon_init(struct vc_data *vc, int init)
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
vc->vc_font.data = (void *)(p->fontdata = font->data);
- vc->vc_font.charcount = 256; /* FIXME Need to
- support more fonts */
+ vc->vc_font.charcount = font->charcount;
}
}
- if (p->userfont)
- charcnt = FNTCHARCNT(p->fontdata);
-
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
- if (charcnt == 256) {
+ if (vc->vc_font.charcount == 256) {
vc->vc_hi_font_mask = 0;
} else {
vc->vc_hi_font_mask = 0x100;
@@ -1367,7 +1364,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
struct vc_data **default_mode, *vc;
struct vc_data *svc;
struct fbcon_ops *ops = info->fbcon_par;
- int rows, cols, charcnt = 256;
+ int rows, cols;
p = &fb_display[unit];
@@ -1387,12 +1384,11 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
+ vc->vc_font.charcount = (*default_mode)->vc_font.charcount;
p->userfont = t->userfont;
if (p->userfont)
REFCOUNT(p->fontdata)++;
}
- if (p->userfont)
- charcnt = FNTCHARCNT(p->fontdata);
var->activate = FB_ACTIVATE_NOW;
info->var.activate = var->activate;
@@ -1402,7 +1398,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
ops->var = info->var;
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
- if (charcnt == 256) {
+ if (vc->vc_font.charcount == 256) {
vc->vc_hi_font_mask = 0;
} else {
vc->vc_hi_font_mask = 0x100;
@@ -2047,7 +2043,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
*/
if (pitch <= 0)
return -EINVAL;
- size = CALC_FONTSZ(vc->vc_font.height, pitch, FNTCHARCNT(vc->vc_font.data));
+ size = CALC_FONTSZ(vc->vc_font.height, pitch, vc->vc_font.charcount);
if (size > FNTSIZE(vc->vc_font.data))
return -EINVAL;
}
@@ -2095,7 +2091,7 @@ static int fbcon_switch(struct vc_data *vc)
struct fbcon_ops *ops;
struct fbcon_display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var;
- int i, ret, prev_console, charcnt = 256;
+ int i, ret, prev_console;
info = registered_fb[con2fb_map[vc->vc_num]];
ops = info->fbcon_par;
@@ -2172,10 +2168,7 @@ static int fbcon_switch(struct vc_data *vc)
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
- if (p->userfont)
- charcnt = FNTCHARCNT(vc->vc_font.data);
-
- if (charcnt > 256)
+ if (vc->vc_font.charcount > 256)
vc->vc_complement_mask <<= 1;
updatescrollmode(p, info, vc);
@@ -2425,31 +2418,27 @@ static void set_vc_hi_font(struct vc_data *vc, bool set)
}
}
-static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
+static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
const u8 * data, int userfont)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
int resize;
- int cnt;
char *old_data = NULL;
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
if (p->userfont)
old_data = vc->vc_font.data;
- if (userfont)
- cnt = FNTCHARCNT(data);
- else
- cnt = 256;
vc->vc_font.data = (void *)(p->fontdata = data);
if ((p->userfont = userfont))
REFCOUNT(data)++;
vc->vc_font.width = w;
vc->vc_font.height = h;
- if (vc->vc_hi_font_mask && cnt == 256)
+ vc->vc_font.charcount = charcount;
+ if (vc->vc_hi_font_mask && charcount == 256)
set_vc_hi_font(vc, false);
- else if (!vc->vc_hi_font_mask && cnt == 512)
+ else if (!vc->vc_hi_font_mask && charcount == 512)
set_vc_hi_font(vc, true);
if (resize) {
@@ -2471,16 +2460,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
return 0;
}
-static int fbcon_copy_font(struct vc_data *vc, int con)
-{
- struct fbcon_display *od = &fb_display[con];
- struct console_font *f = &vc->vc_font;
-
- if (od->fontdata == f->data)
- return 0; /* already the same font... */
- return fbcon_do_set_font(vc, f->width, f->height, od->fontdata, od->userfont);
-}
-
/*
* User asked to set font; we are guaranteed that
* a) width and height are in range 1..32
@@ -2541,9 +2520,10 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
if (!new_data)
return -ENOMEM;
+ memset(new_data, 0, FONT_EXTRA_WORDS * sizeof(int));
+
new_data += FONT_EXTRA_WORDS * sizeof(int);
FNTSIZE(new_data) = size;
- FNTCHARCNT(new_data) = charcount;
REFCOUNT(new_data) = 0; /* usage counter */
for (i=0; i< charcount; i++) {
memcpy(new_data + i*h*pitch, data + i*32*pitch, h*pitch);
@@ -2569,7 +2549,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
break;
}
}
- return fbcon_do_set_font(vc, font->width, font->height, new_data, 1);
+ return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1);
}
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
@@ -2585,7 +2565,7 @@ static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, cha
font->width = f->width;
font->height = f->height;
- return fbcon_do_set_font(vc, f->width, f->height, f->data, 0);
+ return fbcon_do_set_font(vc, f->width, f->height, f->charcount, f->data, 0);
}
static u16 palette_red[16];
@@ -3082,7 +3062,6 @@ void fbcon_get_requirement(struct fb_info *info,
struct fb_blit_caps *caps)
{
struct vc_data *vc;
- struct fbcon_display *p;
if (caps->flags) {
int i, charcnt;
@@ -3091,11 +3070,9 @@ void fbcon_get_requirement(struct fb_info *info,
vc = vc_cons[i].d;
if (vc && vc->vc_mode == KD_TEXT &&
info->node == con2fb_map[i]) {
- p = &fb_display[i];
caps->x |= 1 << (vc->vc_font.width - 1);
caps->y |= 1 << (vc->vc_font.height - 1);
- charcnt = (p->userfont) ?
- FNTCHARCNT(p->fontdata) : 256;
+ charcnt = vc->vc_font.charcount;
if (caps->len < charcnt)
caps->len = charcnt;
}
@@ -3105,11 +3082,9 @@ void fbcon_get_requirement(struct fb_info *info,
if (vc && vc->vc_mode == KD_TEXT &&
info->node == con2fb_map[fg_console]) {
- p = &fb_display[fg_console];
caps->x = 1 << (vc->vc_font.width - 1);
caps->y = 1 << (vc->vc_font.height - 1);
- caps->len = (p->userfont) ?
- FNTCHARCNT(p->fontdata) : 256;
+ caps->len = vc->vc_font.charcount;
}
}
}
@@ -3174,7 +3149,6 @@ static const struct consw fb_con = {
.con_font_set = fbcon_set_font,
.con_font_get = fbcon_get_font,
.con_font_default = fbcon_set_def_font,
- .con_font_copy = fbcon_copy_font,
.con_set_palette = fbcon_set_palette,
.con_invert_region = fbcon_invert_region,
.con_screen_pos = fbcon_screen_pos,
diff --git a/drivers/video/fbdev/core/fbcon_rotate.c b/drivers/video/fbdev/core/fbcon_rotate.c
index ac72d4f85f7d..ef1d421c261a 100644
--- a/drivers/video/fbdev/core/fbcon_rotate.c
+++ b/drivers/video/fbdev/core/fbcon_rotate.c
@@ -14,7 +14,6 @@
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
-#include <linux/font.h>
#include <asm/types.h>
#include "fbcon.h"
#include "fbcon_rotate.h"
@@ -33,7 +32,7 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
src = ops->fontdata = vc->vc_font.data;
ops->cur_rotate = ops->p->con_rotate;
- len = (!ops->p->userfont) ? 256 : FNTCHARCNT(src);
+ len = vc->vc_font.charcount;
s_cellsize = ((vc->vc_font.width + 7)/8) *
vc->vc_font.height;
d_cellsize = s_cellsize;
diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
index ef20824e9c7b..5b53fdda8b35 100644
--- a/drivers/video/fbdev/core/tileblit.c
+++ b/drivers/video/fbdev/core/tileblit.c
@@ -13,7 +13,6 @@
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
-#include <linux/font.h>
#include <asm/types.h>
#include "fbcon.h"
@@ -178,8 +177,7 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
map.width = vc->vc_font.width;
map.height = vc->vc_font.height;
map.depth = 1;
- map.length = (ops->p->userfont) ?
- FNTCHARCNT(ops->p->fontdata) : 256;
+ map.length = vc->vc_font.charcount;
map.data = ops->p->fontdata;
info->tileops->fb_settile(info, &map);
}
diff --git a/drivers/video/fbdev/gbefb.c b/drivers/video/fbdev/gbefb.c
index 8f8ca1f88fe2..dd64eebcfc30 100644
--- a/drivers/video/fbdev/gbefb.c
+++ b/drivers/video/fbdev/gbefb.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/fb.h>
@@ -65,7 +66,7 @@ struct gbefb_par {
static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
static void *gbe_mem;
static dma_addr_t gbe_dma_addr;
-static unsigned long gbe_mem_phys;
+static phys_addr_t gbe_mem_phys;
static struct {
uint16_t *cpu;
@@ -1189,7 +1190,7 @@ static int gbefb_probe(struct platform_device *p_dev)
goto out_release_mem_region;
}
- gbe_mem_phys = (unsigned long) gbe_dma_addr;
+ gbe_mem_phys = dma_to_phys(&p_dev->dev, gbe_dma_addr);
}
par = info->par;
diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
index a0db2b3d0736..be4102957c3f 100644
--- a/drivers/video/fbdev/pxafb.c
+++ b/drivers/video/fbdev/pxafb.c
@@ -418,12 +418,12 @@ static int pxafb_adjust_timing(struct pxafb_info *fbi,
var->yres = max_t(int, var->yres, MIN_YRES);
if (!(fbi->lccr0 & LCCR0_LCDT)) {
- clamp_val(var->hsync_len, 1, 64);
- clamp_val(var->vsync_len, 1, 64);
- clamp_val(var->left_margin, 1, 255);
- clamp_val(var->right_margin, 1, 255);
- clamp_val(var->upper_margin, 1, 255);
- clamp_val(var->lower_margin, 1, 255);
+ var->hsync_len = clamp(var->hsync_len, 1, 64);
+ var->vsync_len = clamp(var->vsync_len, 1, 64);
+ var->left_margin = clamp(var->left_margin, 1, 255);
+ var->right_margin = clamp(var->right_margin, 1, 255);
+ var->upper_margin = clamp(var->upper_margin, 1, 255);
+ var->lower_margin = clamp(var->lower_margin, 1, 255);
}
/* make sure each line is aligned on word boundary */
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index eda448b7a0c9..fd26d368fdf5 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -676,7 +676,7 @@ static int ssd1307fb_probe(struct i2c_client *client)
if (!ssd1307fb_defio) {
dev_err(dev, "Couldn't allocate deferred io.\n");
ret = -ENOMEM;
- goto fb_alloc_error;
+ goto fb_defio_error;
}
ssd1307fb_defio->delay = HZ / refreshrate;
@@ -756,6 +756,8 @@ static int ssd1307fb_probe(struct i2c_client *client)
regulator_disable(par->vbat_reg);
reset_oled_error:
fb_deferred_io_cleanup(info);
+fb_defio_error:
+ __free_pages(vmem, get_order(vmem_size));
fb_alloc_error:
framebuffer_release(info);
return ret;
diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c
index 34b2e5b6e84a..befbea63e587 100644
--- a/drivers/video/fbdev/tcx.c
+++ b/drivers/video/fbdev/tcx.c
@@ -436,7 +436,7 @@ static int tcx_probe(struct platform_device *op)
j = i;
break;
}
- par->mmap_map[i].poff = op->resource[j].start;
+ par->mmap_map[i].poff = op->resource[j].start - info->fix.smem_start;
}
info->flags = FBINFO_DEFAULT;
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 935ea2f3dac7..98e9d77911bc 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -796,15 +796,13 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
tell_host(vb, vb->inflate_vq);
/* balloon's page migration 2nd step -- deflate "page" */
- spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
- balloon_page_delete(page);
- spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
set_page_pfns(vb, vb->pfns, page);
tell_host(vb, vb->deflate_vq);
mutex_unlock(&vb->balloon_lock);
+ balloon_page_finalize(page);
put_page(page); /* balloon reference */
return MIGRATEPAGE_SUCCESS;
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
index eeb39f96e72e..c1ed3ce153cf 100644
--- a/drivers/watchdog/via_wdt.c
+++ b/drivers/watchdog/via_wdt.c
@@ -165,6 +165,7 @@ static int wdt_probe(struct pci_dev *pdev,
dev_err(&pdev->dev, "cannot enable PCI device\n");
return -ENODEV;
}
+ wdt_res.name = "via_wdt";
/*
* Allocate a MMIO region which contains watchdog control register
diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c
index c60723f5ed99..cabeec210f16 100644
--- a/drivers/watchdog/wdat_wdt.c
+++ b/drivers/watchdog/wdat_wdt.c
@@ -327,19 +327,27 @@ static int wdat_wdt_probe(struct platform_device *pdev)
return -ENODEV;
wdat = devm_kzalloc(dev, sizeof(*wdat), GFP_KERNEL);
- if (!wdat)
- return -ENOMEM;
+ if (!wdat) {
+ ret = -ENOMEM;
+ goto out_put_table;
+ }
regs = devm_kcalloc(dev, pdev->num_resources, sizeof(*regs),
GFP_KERNEL);
- if (!regs)
- return -ENOMEM;
+ if (!regs) {
+ ret = -ENOMEM;
+ goto out_put_table;
+ }
/* WDAT specification wants to have >= 1ms period */
- if (tbl->timer_period < 1)
- return -EINVAL;
- if (tbl->min_count > tbl->max_count)
- return -EINVAL;
+ if (tbl->timer_period < 1) {
+ ret = -EINVAL;
+ goto out_put_table;
+ }
+ if (tbl->min_count > tbl->max_count) {
+ ret = -EINVAL;
+ goto out_put_table;
+ }
wdat->period = tbl->timer_period;
wdat->wdd.min_hw_heartbeat_ms = wdat->period * tbl->min_count;
@@ -356,15 +364,20 @@ static int wdat_wdt_probe(struct platform_device *pdev)
res = &pdev->resource[i];
if (resource_type(res) == IORESOURCE_MEM) {
reg = devm_ioremap_resource(dev, res);
- if (IS_ERR(reg))
- return PTR_ERR(reg);
+ if (IS_ERR(reg)) {
+ ret = PTR_ERR(reg);
+ goto out_put_table;
+ }
} else if (resource_type(res) == IORESOURCE_IO) {
reg = devm_ioport_map(dev, res->start, 1);
- if (!reg)
- return -ENOMEM;
+ if (!reg) {
+ ret = -ENOMEM;
+ goto out_put_table;
+ }
} else {
dev_err(dev, "Unsupported resource\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_put_table;
}
regs[i] = reg;
@@ -386,8 +399,10 @@ static int wdat_wdt_probe(struct platform_device *pdev)
}
instr = devm_kzalloc(dev, sizeof(*instr), GFP_KERNEL);
- if (!instr)
- return -ENOMEM;
+ if (!instr) {
+ ret = -ENOMEM;
+ goto out_put_table;
+ }
INIT_LIST_HEAD(&instr->node);
instr->entry = entries[i];
@@ -418,7 +433,8 @@ static int wdat_wdt_probe(struct platform_device *pdev)
if (!instr->reg) {
dev_err(dev, "I/O resource not found\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_put_table;
}
instructions = wdat->instructions[action];
@@ -426,8 +442,10 @@ static int wdat_wdt_probe(struct platform_device *pdev)
instructions = devm_kzalloc(dev,
sizeof(*instructions),
GFP_KERNEL);
- if (!instructions)
- return -ENOMEM;
+ if (!instructions) {
+ ret = -ENOMEM;
+ goto out_put_table;
+ }
INIT_LIST_HEAD(instructions);
wdat->instructions[action] = instructions;
@@ -441,7 +459,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
ret = wdat_wdt_enable_reboot(wdat);
if (ret)
- return ret;
+ goto out_put_table;
platform_set_drvdata(pdev, wdat);
@@ -459,11 +477,16 @@ static int wdat_wdt_probe(struct platform_device *pdev)
ret = wdat_wdt_set_timeout(&wdat->wdd, timeout);
if (ret)
- return ret;
+ goto out_put_table;
watchdog_set_nowayout(&wdat->wdd, nowayout);
watchdog_stop_on_reboot(&wdat->wdd);
- return devm_watchdog_register_device(dev, &wdat->wdd);
+ watchdog_stop_on_unregister(&wdat->wdd);
+ ret = devm_watchdog_register_device(dev, &wdat->wdd);
+
+out_put_table:
+ acpi_put_table((struct acpi_table_header *)tbl);
+ return ret;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index fd691e4815c5..fa4e00292585 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -60,7 +60,19 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
di = (struct bfs_inode *)bh->b_data + off;
- inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
+ /*
+ * https://martin.hinner.info/fs/bfs/bfs-structure.html explains that
+ * BFS in SCO UnixWare environment used only lower 9 bits of di->i_mode
+ * value. This means that, although bfs_write_inode() saves whole
+ * inode->i_mode bits (which include S_IFMT bits and S_IS{UID,GID,VTX}
+ * bits), middle 7 bits of di->i_mode value can be garbage when these
+ * bits were not saved by bfs_write_inode().
+ * Since we can't tell whether middle 7 bits are garbage, use only
+ * lower 12 bits (i.e. tolerate S_IS{UID,GID,VTX} bits possibly being
+ * garbage) and reconstruct S_IFMT bits for Linux environment from
+ * di->i_vtype value.
+ */
+ inode->i_mode = 0x00000FFF & le32_to_cpu(di->i_mode);
if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
inode->i_mode |= S_IFDIR;
inode->i_op = &bfs_dir_inops;
@@ -70,6 +82,11 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &bfs_file_inops;
inode->i_fop = &bfs_file_operations;
inode->i_mapping->a_ops = &bfs_aops;
+ } else {
+ brelse(bh);
+ printf("Unknown vtype=%u %s:%08lx\n",
+ le32_to_cpu(di->i_vtype), inode->i_sb->s_id, ino);
+ goto error;
}
BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 489d370ddd60..3d0b854e0c19 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2655,7 +2655,6 @@ blk_status_t btrfs_submit_read_repair(struct inode *inode,
bool need_validation;
struct bio *repair_bio;
struct btrfs_io_bio *repair_io_bio;
- blk_status_t status;
btrfs_debug(fs_info,
"repair read error: read error at %llu", start);
@@ -2699,13 +2698,13 @@ blk_status_t btrfs_submit_read_repair(struct inode *inode,
"repair read error: submitting new read to mirror %d, in_validation=%d",
failrec->this_mirror, failrec->in_validation);
- status = submit_bio_hook(inode, repair_bio, failrec->this_mirror,
- failrec->bio_flags);
- if (status) {
- free_io_failure(failure_tree, tree, failrec);
- bio_put(repair_bio);
- }
- return status;
+ /*
+ * At this point we have a bio, so any errors from submit_bio_hook()
+ * will be handled by the endio on the repair_bio, so we can't return an
+ * error here.
+ */
+ submit_bio_hook(inode, repair_bio, failrec->this_mirror, failrec->bio_flags);
+ return BLK_STS_OK;
}
/* lots and lots of room for performance fixes in the end_bio funcs */
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 9d5dfcec22de..4a35d51dfef8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2573,10 +2573,8 @@ static int btrfs_search_path_in_tree_user(struct inode *inode,
}
ret = inode_permission(temp_inode, MAY_READ | MAY_EXEC);
iput(temp_inode);
- if (ret) {
- ret = -EACCES;
+ if (ret)
goto out_put;
- }
if (key.offset == upper_limit.objectid)
break;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 715a0329ba27..c8d033deb8ab 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -3820,6 +3820,10 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
unsigned int nofs_flag;
bool need_commit = false;
+ /* Set the basic fallback @last_physical before we got a sctx. */
+ if (progress)
+ progress->last_physical = start;
+
if (btrfs_fs_closing(fs_info))
return -EAGAIN;
@@ -3864,6 +3868,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
sctx = scrub_setup_ctx(fs_info, is_dev_replace);
if (IS_ERR(sctx))
return PTR_ERR(sctx);
+ sctx->stat.last_physical = start;
ret = scrub_workers_get(fs_info, is_dev_replace);
if (ret)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 9c1a7b3b84e4..2bba6e8d4374 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6899,6 +6899,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
fs_devices->seeding = true;
fs_devices->opened = 1;
+ list_add(&fs_devices->seed_list, &fs_info->fs_devices->seed_list);
return fs_devices;
}
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
index dfe298bc3782..b8ddb6fb50e9 100644
--- a/fs/exfat/super.c
+++ b/fs/exfat/super.c
@@ -757,10 +757,21 @@ static int exfat_init_fs_context(struct fs_context *fc)
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
- sbi->options.fs_uid = current_uid();
- sbi->options.fs_gid = current_gid();
- sbi->options.fs_fmask = current->fs->umask;
- sbi->options.fs_dmask = current->fs->umask;
+ if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE && fc->root) {
+ struct super_block *sb = fc->root->d_sb;
+ struct exfat_mount_options *cur_opts = &EXFAT_SB(sb)->options;
+
+ sbi->options.fs_uid = cur_opts->fs_uid;
+ sbi->options.fs_gid = cur_opts->fs_gid;
+ sbi->options.fs_fmask = cur_opts->fs_fmask;
+ sbi->options.fs_dmask = cur_opts->fs_dmask;
+ } else {
+ sbi->options.fs_uid = current_uid();
+ sbi->options.fs_gid = current_gid();
+ sbi->options.fs_fmask = current->fs->umask;
+ sbi->options.fs_dmask = current->fs->umask;
+ }
+
sbi->options.allow_utime = -1;
sbi->options.iocharset = exfat_default_iocharset;
sbi->options.errors = EXFAT_ERRORS_RO;
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index f02fcaa62804..129f7ff56b43 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -410,7 +410,12 @@ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
return -ENOSPC;
ext4_write_lock_xattr(inode, &no_expand);
-
+ /*
+ * ei->i_inline_size may have changed since the initial check
+ * if other xattrs were added. Recalculate to ensure
+ * ext4_update_inline_data() validates against current capacity.
+ */
+ (void) ext4_find_inline_data_nolock(inode);
if (ei->i_inline_off)
ret = ext4_update_inline_data(handle, inode, len);
else
@@ -438,9 +443,13 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
if (!ei->i_inline_off)
return 0;
+ down_write(&ei->i_data_sem);
+
error = ext4_get_inode_loc(inode, &is.iloc);
- if (error)
+ if (error) {
+ up_write(&ei->i_data_sem);
return error;
+ }
error = ext4_xattr_ibody_find(inode, &i, &is);
if (error)
@@ -478,6 +487,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
brelse(is.iloc.bh);
if (error == -ENODATA)
error = 0;
+ up_write(&ei->i_data_sem);
return error;
}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 97f7cac0d349..719d9a2bc5a7 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4650,6 +4650,11 @@ static inline int ext4_iget_extra_inode(struct inode *inode,
*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
int err;
+ err = xattr_check_inode(inode, IHDR(inode, raw_inode),
+ ITAIL(inode, raw_inode));
+ if (err)
+ return err;
+
ext4_set_inode_state(inode, EXT4_STATE_XATTR);
err = ext4_find_inline_data_nolock(inode);
if (!err && ext4_has_inline_data(inode))
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 60c56a39798c..d1a616bbb5bd 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -602,7 +602,25 @@ do { \
} \
} while (0)
-static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
+/*
+ * Perform buddy integrity check with the following steps:
+ *
+ * 1. Top-down validation (from highest order down to order 1, excluding order-0 bitmap):
+ * For each pair of adjacent orders, if a higher-order bit is set (indicating a free block),
+ * at most one of the two corresponding lower-order bits may be clear (free).
+ *
+ * 2. Order-0 (bitmap) validation, performed on bit pairs:
+ * - If either bit in a pair is set (1, allocated), then all corresponding higher-order bits
+ * must not be free (0).
+ * - If both bits in a pair are clear (0, free), then exactly one of the corresponding
+ * higher-order bits must be free (0).
+ *
+ * 3. Preallocation (pa) list validation:
+ * For each preallocated block (pa) in the group:
+ * - Verify that pa_pstart falls within the bounds of this block group.
+ * - Ensure the corresponding bit(s) in the order-0 bitmap are marked as allocated (1).
+ */
+static void __mb_check_buddy(struct ext4_buddy *e4b, char *file,
const char *function, int line)
{
struct super_block *sb = e4b->bd_sb;
@@ -621,7 +639,7 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
void *buddy2;
if (e4b->bd_info->bb_check_counter++ % 10)
- return 0;
+ return;
while (order > 1) {
buddy = mb_find_buddy(e4b, order, &max);
@@ -646,15 +664,6 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
continue;
}
- /* both bits in buddy2 must be 1 */
- MB_CHECK_ASSERT(mb_test_bit(i << 1, buddy2));
- MB_CHECK_ASSERT(mb_test_bit((i << 1) + 1, buddy2));
-
- for (j = 0; j < (1 << order); j++) {
- k = (i * (1 << order)) + j;
- MB_CHECK_ASSERT(
- !mb_test_bit(k, e4b->bd_bitmap));
- }
count++;
}
MB_CHECK_ASSERT(e4b->bd_info->bb_counters[order] == count);
@@ -670,15 +679,21 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
fragments++;
fstart = i;
}
- continue;
+ } else {
+ fstart = -1;
}
- fstart = -1;
- /* check used bits only */
- for (j = 0; j < e4b->bd_blkbits + 1; j++) {
- buddy2 = mb_find_buddy(e4b, j, &max2);
- k = i >> j;
- MB_CHECK_ASSERT(k < max2);
- MB_CHECK_ASSERT(mb_test_bit(k, buddy2));
+ if (!(i & 1)) {
+ int in_use, zero_bit_count = 0;
+
+ in_use = mb_test_bit(i, buddy) || mb_test_bit(i + 1, buddy);
+ for (j = 1; j < e4b->bd_blkbits + 2; j++) {
+ buddy2 = mb_find_buddy(e4b, j, &max2);
+ k = i >> j;
+ MB_CHECK_ASSERT(k < max2);
+ if (!mb_test_bit(k, buddy2))
+ zero_bit_count++;
+ }
+ MB_CHECK_ASSERT(zero_bit_count == !in_use);
}
}
MB_CHECK_ASSERT(!EXT4_MB_GRP_NEED_INIT(e4b->bd_info));
@@ -686,17 +701,18 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
grp = ext4_get_group_info(sb, e4b->bd_group);
if (!grp)
- return NULL;
+ return;
list_for_each(cur, &grp->bb_prealloc_list) {
ext4_group_t groupnr;
struct ext4_prealloc_space *pa;
pa = list_entry(cur, struct ext4_prealloc_space, pa_group_list);
+ if (!pa->pa_len)
+ continue;
ext4_get_group_no_and_offset(sb, pa->pa_pstart, &groupnr, &k);
MB_CHECK_ASSERT(groupnr == e4b->bd_group);
for (i = 0; i < pa->pa_len; i++)
MB_CHECK_ASSERT(mb_test_bit(k + i, buddy));
}
- return 0;
}
#undef MB_CHECK_ASSERT
#define mb_check_buddy(e4b) __mb_check_buddy(e4b, \
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 661a8544d781..b1ad339165e4 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -466,19 +466,17 @@ mext_check_arguments(struct inode *orig_inode,
if (IS_IMMUTABLE(donor_inode) || IS_APPEND(donor_inode))
return -EPERM;
- /* Ext4 move extent does not support swapfile */
+ /* Ext4 move extent does not support swap files */
if (IS_SWAPFILE(orig_inode) || IS_SWAPFILE(donor_inode)) {
- ext4_debug("ext4 move extent: The argument files should "
- "not be swapfile [ino:orig %lu, donor %lu]\n",
+ ext4_debug("ext4 move extent: The argument files should not be swap files [ino:orig %lu, donor %lu]\n",
orig_inode->i_ino, donor_inode->i_ino);
- return -EBUSY;
+ return -ETXTBSY;
}
- if (ext4_is_quota_file(orig_inode) && ext4_is_quota_file(donor_inode)) {
- ext4_debug("ext4 move extent: The argument files should "
- "not be quota files [ino:orig %lu, donor %lu]\n",
+ if (ext4_is_quota_file(orig_inode) || ext4_is_quota_file(donor_inode)) {
+ ext4_debug("ext4 move extent: The argument files should not be quota files [ino:orig %lu, donor %lu]\n",
orig_inode->i_ino, donor_inode->i_ino);
- return -EBUSY;
+ return -EOPNOTSUPP;
}
/* Ext4 move extent supports only extent based file */
@@ -626,11 +624,11 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
if (ret)
goto out;
ex = path[path->p_depth].p_ext;
- next_blk = ext4_ext_next_allocated_block(path);
cur_blk = le32_to_cpu(ex->ee_block);
cur_len = ext4_ext_get_actual_len(ex);
/* Check hole before the start pos */
if (cur_blk + cur_len - 1 < o_start) {
+ next_blk = ext4_ext_next_allocated_block(path);
if (next_blk == EXT_MAX_BLOCKS) {
o_start = o_end;
ret = -ENODATA;
@@ -659,7 +657,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
donor_page_index = d_start >> (PAGE_SHIFT -
donor_inode->i_blkbits);
offset_in_page = o_start % blocks_per_page;
- if (cur_len > blocks_per_page- offset_in_page)
+ if (cur_len > blocks_per_page - offset_in_page)
cur_len = blocks_per_page - offset_in_page;
/*
* Up semaphore to avoid following problems:
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 453e746ba361..41e49fee35e5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4282,10 +4282,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
}
if (sbi->s_es->s_mount_opts[0]) {
- char s_mount_opts[65];
+ char s_mount_opts[64];
- strscpy_pad(s_mount_opts, sbi->s_es->s_mount_opts,
- sizeof(s_mount_opts));
+ if (strscpy_pad(s_mount_opts, sbi->s_es->s_mount_opts,
+ sizeof(s_mount_opts)) < 0)
+ goto failed_mount;
if (!parse_options(s_mount_opts, sb, &journal_devnum,
&journal_ioprio, 0)) {
ext4_msg(sb, KERN_WARNING,
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index fa8ce1c66d12..1e0344e24266 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -263,7 +263,7 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
__ext4_xattr_check_block((inode), (bh), __func__, __LINE__)
-static int
+int
__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
void *end, const char *function, unsigned int line)
{
@@ -280,9 +280,6 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
return error;
}
-#define xattr_check_inode(inode, header, end) \
- __xattr_check_inode((inode), (header), (end), __func__, __LINE__)
-
static int
xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
void *end, int name_index, const char *name, int sorted)
@@ -599,10 +596,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
return error;
raw_inode = ext4_raw_inode(&iloc);
header = IHDR(inode, raw_inode);
- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
- error = xattr_check_inode(inode, header, end);
- if (error)
- goto cleanup;
+ end = ITAIL(inode, raw_inode);
entry = IFIRST(header);
error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
if (error)
@@ -734,7 +728,6 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
struct ext4_xattr_ibody_header *header;
struct ext4_inode *raw_inode;
struct ext4_iloc iloc;
- void *end;
int error;
if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
@@ -744,14 +737,9 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
return error;
raw_inode = ext4_raw_inode(&iloc);
header = IHDR(inode, raw_inode);
- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
- error = xattr_check_inode(inode, header, end);
- if (error)
- goto cleanup;
error = ext4_xattr_list_entries(dentry, IFIRST(header),
buffer, buffer_size);
-cleanup:
brelse(iloc.bh);
return error;
}
@@ -815,7 +803,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
struct ext4_xattr_ibody_header *header;
struct ext4_xattr_entry *entry;
qsize_t ea_inode_refs = 0;
- void *end;
int ret;
lockdep_assert_held_read(&EXT4_I(inode)->xattr_sem);
@@ -826,10 +813,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
goto out;
raw_inode = ext4_raw_inode(&iloc);
header = IHDR(inode, raw_inode);
- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
- ret = xattr_check_inode(inode, header, end);
- if (ret)
- goto out;
for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
entry = EXT4_XATTR_NEXT(entry))
@@ -1134,7 +1117,11 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent,
if (block_csum)
end = (void *)bh->b_data + bh->b_size;
else {
- ext4_get_inode_loc(parent, &iloc);
+ err = ext4_get_inode_loc(parent, &iloc);
+ if (err) {
+ EXT4_ERROR_INODE(parent, "parent inode loc (error %d)", err);
+ return;
+ }
end = (void *)ext4_raw_inode(&iloc) + EXT4_SB(parent->i_sb)->s_inode_size;
}
@@ -2215,11 +2202,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
header = IHDR(inode, raw_inode);
is->s.base = is->s.first = IFIRST(header);
is->s.here = is->s.first;
- is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+ is->s.end = ITAIL(inode, raw_inode);
if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
- error = xattr_check_inode(inode, header, is->s.end);
- if (error)
- return error;
/* Find the named attribute. */
error = xattr_find_entry(inode, &is->s.here, is->s.end,
i->name_index, i->name, 0);
@@ -2739,14 +2723,10 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
*/
base = IFIRST(header);
- end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
+ end = ITAIL(inode, raw_inode);
min_offs = end - base;
total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32);
- error = xattr_check_inode(inode, header, end);
- if (error)
- goto cleanup;
-
ifree = ext4_xattr_free_space(base, &min_offs, base, &total_ino);
if (ifree >= isize_diff)
goto shift;
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index e5e36bd11f05..cbf235422aec 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -68,6 +68,9 @@ struct ext4_xattr_entry {
((void *)raw_inode + \
EXT4_GOOD_OLD_INODE_SIZE + \
EXT4_I(inode)->i_extra_isize))
+#define ITAIL(inode, raw_inode) \
+ ((void *)(raw_inode) + \
+ EXT4_SB((inode)->i_sb)->s_inode_size)
#define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
/*
@@ -207,6 +210,13 @@ extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
extern struct mb_cache *ext4_xattr_create_cache(void);
extern void ext4_xattr_destroy_cache(struct mb_cache *);
+extern int
+__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+ void *end, const char *function, unsigned int line);
+
+#define xattr_check_inode(inode, header, end) \
+ __xattr_check_inode((inode), (header), (end), __func__, __LINE__)
+
#ifdef CONFIG_EXT4_FS_SECURITY
extern int ext4_init_security(handle_t *handle, struct inode *inode,
struct inode *dir, const struct qstr *qstr);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 622e8a816f7e..043c8ec84941 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1573,9 +1573,6 @@ struct f2fs_sb_info {
struct workqueue_struct *post_read_wq; /* post read workqueue */
- struct kmem_cache *inline_xattr_slab; /* inline xattr entry */
- unsigned int inline_xattr_slab_size; /* default inline xattr slab size */
-
#ifdef CONFIG_F2FS_FS_COMPRESSION
struct kmem_cache *page_array_slab; /* page array entry */
unsigned int page_array_slab_size; /* default page array slab size */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 81ebbc1d37a6..624368e3f89e 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1458,7 +1458,8 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
f2fs_set_data_blkaddr(dn);
}
- f2fs_update_extent_cache_range(dn, start, 0, index - start);
+ if (index > start)
+ f2fs_update_extent_cache_range(dn, start, 0, index - start);
return ret;
}
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 7be488ecb210..3f716028ca74 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -1064,9 +1064,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (whiteout) {
set_inode_flag(whiteout, FI_INC_LINK);
err = f2fs_add_link(old_dentry, whiteout);
- if (err)
+ if (err) {
+ d_invalidate(old_dentry);
+ d_invalidate(new_dentry);
goto put_out_dir;
-
+ }
spin_lock(&whiteout->i_lock);
whiteout->i_state &= ~I_LINKABLE;
spin_unlock(&whiteout->i_lock);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index cd56af93df42..320553b45ee9 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -328,7 +328,7 @@ static int recover_inode(struct inode *inode, struct page *page)
}
static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
- bool check_only)
+ bool check_only, bool *new_inode)
{
struct curseg_info *curseg;
struct page *page = NULL;
@@ -385,6 +385,8 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
if (IS_ERR(entry)) {
err = PTR_ERR(entry);
if (err == -ENOENT) {
+ if (check_only)
+ *new_inode = true;
err = 0;
goto next;
}
@@ -789,6 +791,7 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
unsigned long s_flags = sbi->sb->s_flags;
bool need_writecp = false;
bool fix_curseg_write_pointer = false;
+ bool new_inode = false;
#ifdef CONFIG_QUOTA
int quota_enabled;
#endif
@@ -813,8 +816,8 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
mutex_lock(&sbi->cp_mutex);
/* step #1: find fsynced inode numbers */
- err = find_fsync_dnodes(sbi, &inode_list, check_only);
- if (err || list_empty(&inode_list))
+ err = find_fsync_dnodes(sbi, &inode_list, check_only, &new_inode);
+ if (err < 0 || (list_empty(&inode_list) && (!check_only || !new_inode)))
goto skip;
if (check_only) {
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index d7fd28a47701..8ab7d3f9a764 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1351,7 +1351,6 @@ static void f2fs_put_super(struct super_block *sb)
destroy_device_list(sbi);
f2fs_destroy_page_array_cache(sbi);
- f2fs_destroy_xattr_caches(sbi);
mempool_destroy(sbi->write_io_dummy);
#ifdef CONFIG_QUOTA
for (i = 0; i < MAXQUOTAS; i++)
@@ -1837,9 +1836,10 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
return err;
}
-static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
+static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
{
int retry = DEFAULT_RETRY_IO_COUNT;
+ int ret;
/* we should flush all the data to keep data consistency */
do {
@@ -1858,7 +1858,11 @@ static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
set_sbi_flag(sbi, SBI_IS_DIRTY);
up_write(&sbi->gc_lock);
- f2fs_sync_fs(sbi->sb, 1);
+ ret = f2fs_sync_fs(sbi->sb, 1);
+ if (ret)
+ f2fs_err(sbi, "%s sync_fs failed, ret: %d", __func__, ret);
+
+ return ret;
}
static int f2fs_remount(struct super_block *sb, int *flags, char *data)
@@ -2006,7 +2010,9 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
if (err)
goto restore_gc;
} else {
- f2fs_enable_checkpoint(sbi);
+ err = f2fs_enable_checkpoint(sbi);
+ if (err)
+ goto restore_gc;
}
}
@@ -3722,13 +3728,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
}
}
- /* init per sbi slab cache */
- err = f2fs_init_xattr_caches(sbi);
- if (err)
- goto free_io_dummy;
err = f2fs_init_page_array_cache(sbi);
if (err)
- goto free_xattr_cache;
+ goto free_io_dummy;
/* get an inode for meta space */
sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
@@ -3910,11 +3912,15 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
}
} else {
err = f2fs_recover_fsync_data(sbi, true);
-
- if (!f2fs_readonly(sb) && err > 0) {
- err = -EINVAL;
- f2fs_err(sbi, "Need to recover fsync data");
- goto free_meta;
+ if (err > 0) {
+ if (!f2fs_readonly(sb)) {
+ f2fs_err(sbi, "Need to recover fsync data");
+ err = -EINVAL;
+ goto free_meta;
+ } else {
+ f2fs_info(sbi, "drop all fsynced data");
+ err = 0;
+ }
}
}
@@ -3934,13 +3940,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
/* f2fs_recover_fsync_data() cleared this already */
clear_sbi_flag(sbi, SBI_POR_DOING);
- if (test_opt(sbi, DISABLE_CHECKPOINT)) {
+ if (test_opt(sbi, DISABLE_CHECKPOINT))
err = f2fs_disable_checkpoint(sbi);
- if (err)
- goto sync_free_meta;
- } else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) {
- f2fs_enable_checkpoint(sbi);
- }
+ else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG))
+ err = f2fs_enable_checkpoint(sbi);
+ if (err)
+ goto sync_free_meta;
/*
* If filesystem is not mounted as read-only then
@@ -4017,8 +4022,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
sbi->meta_inode = NULL;
free_page_array_cache:
f2fs_destroy_page_array_cache(sbi);
-free_xattr_cache:
- f2fs_destroy_xattr_caches(sbi);
free_io_dummy:
mempool_destroy(sbi->write_io_dummy);
free_percpu:
@@ -4170,7 +4173,12 @@ static int __init init_f2fs_fs(void)
err = f2fs_init_compress_cache();
if (err)
goto free_compress_mempool;
+ err = f2fs_init_xattr_cache();
+ if (err)
+ goto free_compress_cache;
return 0;
+free_compress_cache:
+ f2fs_destroy_compress_cache();
free_compress_mempool:
f2fs_destroy_compress_mempool();
free_bioset:
@@ -4206,6 +4214,7 @@ static int __init init_f2fs_fs(void)
static void __exit exit_f2fs_fs(void)
{
+ f2fs_destroy_xattr_cache();
f2fs_destroy_compress_cache();
f2fs_destroy_compress_mempool();
f2fs_destroy_bioset();
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index bd7099457018..ed475fd172af 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -23,11 +23,12 @@
#include "xattr.h"
#include "segment.h"
+static struct kmem_cache *inline_xattr_slab;
static void *xattr_alloc(struct f2fs_sb_info *sbi, int size, bool *is_inline)
{
- if (likely(size == sbi->inline_xattr_slab_size)) {
+ if (likely(size == DEFAULT_XATTR_SLAB_SIZE)) {
*is_inline = true;
- return kmem_cache_zalloc(sbi->inline_xattr_slab, GFP_NOFS);
+ return kmem_cache_zalloc(inline_xattr_slab, GFP_NOFS);
}
*is_inline = false;
return f2fs_kzalloc(sbi, size, GFP_NOFS);
@@ -37,7 +38,7 @@ static void xattr_free(struct f2fs_sb_info *sbi, void *xattr_addr,
bool is_inline)
{
if (is_inline)
- kmem_cache_free(sbi->inline_xattr_slab, xattr_addr);
+ kmem_cache_free(inline_xattr_slab, xattr_addr);
else
kfree(xattr_addr);
}
@@ -814,25 +815,14 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name,
return err;
}
-int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi)
+int __init f2fs_init_xattr_cache(void)
{
- dev_t dev = sbi->sb->s_bdev->bd_dev;
- char slab_name[32];
-
- sprintf(slab_name, "f2fs_xattr_entry-%u:%u", MAJOR(dev), MINOR(dev));
-
- sbi->inline_xattr_slab_size = F2FS_OPTION(sbi).inline_xattr_size *
- sizeof(__le32) + XATTR_PADDING_SIZE;
-
- sbi->inline_xattr_slab = f2fs_kmem_cache_create(slab_name,
- sbi->inline_xattr_slab_size);
- if (!sbi->inline_xattr_slab)
- return -ENOMEM;
-
- return 0;
+ inline_xattr_slab = f2fs_kmem_cache_create("f2fs_xattr_entry",
+ DEFAULT_XATTR_SLAB_SIZE);
+ return inline_xattr_slab ? 0 : -ENOMEM;
}
-void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi)
+void f2fs_destroy_xattr_cache(void)
{
- kmem_cache_destroy(sbi->inline_xattr_slab);
-}
+ kmem_cache_destroy(inline_xattr_slab);
+}
\ No newline at end of file
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
index 416d652774a3..cb8666be9b99 100644
--- a/fs/f2fs/xattr.h
+++ b/fs/f2fs/xattr.h
@@ -88,6 +88,8 @@ struct f2fs_xattr_entry {
F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) - \
DEF_INLINE_RESERVED_SIZE - \
MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
+#define DEFAULT_XATTR_SLAB_SIZE (DEFAULT_INLINE_XATTR_ADDRS * \
+ sizeof(__le32) + XATTR_PADDING_SIZE)
/*
* On-disk structure of f2fs_xattr
@@ -131,8 +133,8 @@ extern int f2fs_setxattr(struct inode *, int, const char *,
extern int f2fs_getxattr(struct inode *, int, const char *, void *,
size_t, struct page *);
extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t);
-extern int f2fs_init_xattr_caches(struct f2fs_sb_info *);
-extern void f2fs_destroy_xattr_caches(struct f2fs_sb_info *);
+extern int __init f2fs_init_xattr_cache(void);
+extern void f2fs_destroy_xattr_cache(void);
#else
#define f2fs_xattr_handlers NULL
@@ -149,8 +151,8 @@ static inline int f2fs_getxattr(struct inode *inode, int index,
{
return -EOPNOTSUPP;
}
-static inline int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi) { return 0; }
-static inline void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) { }
+static inline int __init f2fs_init_xattr_cache(void) { return 0; }
+static inline void f2fs_destroy_xattr_cache(void) { }
#endif
#ifdef CONFIG_F2FS_FS_SECURITY
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index e566cea23827..7c127922ac0c 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -488,6 +488,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
tree->node_hash[hash] = node;
tree->node_hash_cnt++;
} else {
+ hfs_bnode_get(node2);
spin_unlock(&tree->hash_lock);
kfree(node);
wait_event(node2->lock_wq,
@@ -717,6 +718,5 @@ bool hfs_bnode_need_zeroout(struct hfs_btree *tree)
struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
const u32 volume_attr = be32_to_cpu(sbi->s_vhdr->attributes);
- return tree->cnid == HFSPLUS_CAT_CNID &&
- volume_attr & HFSPLUS_VOL_UNUSED_NODE_FIX;
+ return volume_attr & HFSPLUS_VOL_UNUSED_NODE_FIX;
}
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 29a9dcfbe81f..292cc06206a1 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -550,8 +550,13 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
res = hfsplus_rename_cat((u32)(unsigned long)old_dentry->d_fsdata,
old_dir, &old_dentry->d_name,
new_dir, &new_dentry->d_name);
- if (!res)
+ if (!res) {
new_dentry->d_fsdata = old_dentry->d_fsdata;
+
+ res = hfsplus_cat_write_inode(old_dir);
+ if (!res)
+ res = hfsplus_cat_write_inode(new_dir);
+ }
return res;
}
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 7e1d889dcc07..0ba324ee7dff 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -178,13 +178,29 @@ const struct dentry_operations hfsplus_dentry_operations = {
.d_compare = hfsplus_compare_dentry,
};
-static void hfsplus_get_perms(struct inode *inode,
- struct hfsplus_perm *perms, int dir)
+static int hfsplus_get_perms(struct inode *inode,
+ struct hfsplus_perm *perms, int dir)
{
struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
u16 mode;
mode = be16_to_cpu(perms->mode);
+ if (dir) {
+ if (mode && !S_ISDIR(mode))
+ goto bad_type;
+ } else if (mode) {
+ switch (mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFLNK:
+ case S_IFCHR:
+ case S_IFBLK:
+ case S_IFIFO:
+ case S_IFSOCK:
+ break;
+ default:
+ goto bad_type;
+ }
+ }
i_uid_write(inode, be32_to_cpu(perms->owner));
if ((test_bit(HFSPLUS_SB_UID, &sbi->flags)) || (!i_uid_read(inode) && !mode))
@@ -210,6 +226,10 @@ static void hfsplus_get_perms(struct inode *inode,
inode->i_flags |= S_APPEND;
else
inode->i_flags &= ~S_APPEND;
+ return 0;
+bad_type:
+ pr_err("invalid file type 0%04o for inode %lu\n", mode, inode->i_ino);
+ return -EIO;
}
static int hfsplus_file_open(struct inode *inode, struct file *file)
@@ -504,7 +524,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
}
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
sizeof(struct hfsplus_cat_folder));
- hfsplus_get_perms(inode, &folder->permissions, 1);
+ res = hfsplus_get_perms(inode, &folder->permissions, 1);
+ if (res)
+ goto out;
set_nlink(inode, 1);
inode->i_size = 2 + be32_to_cpu(folder->valence);
inode->i_atime = hfsp_mt2ut(folder->access_date);
@@ -531,7 +553,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
&file->rsrc_fork : &file->data_fork);
- hfsplus_get_perms(inode, &file->permissions, 0);
+ res = hfsplus_get_perms(inode, &file->permissions, 0);
+ if (res)
+ goto out;
set_nlink(inode, 1);
if (S_ISREG(inode->i_mode)) {
if (file->permissions.dev)
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 23314218fb0d..14b176d63482 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -2224,6 +2224,12 @@ int jbd2_journal_set_features(journal_t *journal, unsigned long compat,
sb->s_feature_compat |= cpu_to_be32(compat);
sb->s_feature_ro_compat |= cpu_to_be32(ro);
sb->s_feature_incompat |= cpu_to_be32(incompat);
+ /*
+ * Update the checksum now so that it is valid even for read-only
+ * filesystems where jbd2_write_superblock() doesn't get called.
+ */
+ if (jbd2_journal_has_csum_v2or3(journal))
+ sb->s_checksum = jbd2_superblock_csum(journal, sb);
unlock_buffer(journal->j_sb_buffer);
journal->j_revoke_records_per_block =
journal_revoke_records_per_block(journal);
@@ -2254,9 +2260,17 @@ void jbd2_journal_clear_features(journal_t *journal, unsigned long compat,
sb = journal->j_superblock;
+ lock_buffer(journal->j_sb_buffer);
sb->s_feature_compat &= ~cpu_to_be32(compat);
sb->s_feature_ro_compat &= ~cpu_to_be32(ro);
sb->s_feature_incompat &= ~cpu_to_be32(incompat);
+ /*
+ * Update the checksum now so that it is valid even for read-only
+ * filesystems where jbd2_write_superblock() doesn't get called.
+ */
+ if (jbd2_journal_has_csum_v2or3(journal))
+ sb->s_checksum = jbd2_superblock_csum(journal, sb);
+ unlock_buffer(journal->j_sb_buffer);
journal->j_revoke_records_per_block =
journal_revoke_records_per_block(journal);
}
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index bb20d4493ded..12f936effe6d 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -448,7 +448,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
read_unlock(&journal->j_state_lock);
current->journal_info = handle;
- rwsem_acquire_read(&journal->j_trans_commit_map, 0, 0, _THIS_IP_);
+ rwsem_acquire_read(&journal->j_trans_commit_map, 0, 1, _THIS_IP_);
jbd2_journal_free_transaction(new_transaction);
/*
* Ensure that no allocations done while the transaction is open are
@@ -1267,14 +1267,23 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
* committing transaction's lists, but it HAS to be in Forget state in
* that case: the transaction must have deleted the buffer for it to be
* reused here.
+ * In the case of file system data inconsistency, for example, if the
+ * block bitmap of a referenced block is not set, it can lead to the
+ * situation where a block being committed is allocated and used again.
+ * As a result, the following condition will not be satisfied, so here
+ * we directly trigger a JBD abort instead of immediately invoking
+ * bugon.
*/
spin_lock(&jh->b_state_lock);
- J_ASSERT_JH(jh, (jh->b_transaction == transaction ||
- jh->b_transaction == NULL ||
- (jh->b_transaction == journal->j_committing_transaction &&
- jh->b_jlist == BJ_Forget)));
+ if (!(jh->b_transaction == transaction || jh->b_transaction == NULL ||
+ (jh->b_transaction == journal->j_committing_transaction &&
+ jh->b_jlist == BJ_Forget)) || jh->b_next_transaction != NULL) {
+ err = -EROFS;
+ spin_unlock(&jh->b_state_lock);
+ jbd2_journal_abort(journal, err);
+ goto out;
+ }
- J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
if (jh->b_transaction == NULL) {
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index b72023a6b4c1..28ba7b1460aa 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -96,7 +96,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_host *host;
struct nlm_file *file;
- struct nlm_lockowner *test_owner;
__be32 rc = rpc_success;
dprintk("lockd: TEST4 called\n");
@@ -106,7 +105,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
- test_owner = argp->lock.fl.fl_owner;
/* Now check for conflicting locks */
resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
if (resp->status == nlm_drop_reply)
@@ -114,7 +112,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
else
dprintk("lockd: TEST4 status %d\n", ntohl(resp->status));
- nlmsvc_put_lockowner(test_owner);
+ nlmsvc_release_lockowner(&argp->lock);
nlmsvc_release_host(host);
nlm_release_file(file);
return rc;
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 4e30f3c50970..035f885809dd 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -604,7 +604,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
}
mode = lock_to_openmode(&lock->fl);
- error = vfs_test_lock(file->f_file[mode], &lock->fl);
+ locks_init_lock(&conflock->fl);
+ /* vfs_test_lock only uses start, end, and owner, but tests fl_file */
+ conflock->fl.fl_file = lock->fl.fl_file;
+ conflock->fl.fl_start = lock->fl.fl_start;
+ conflock->fl.fl_end = lock->fl.fl_end;
+ conflock->fl.fl_owner = lock->fl.fl_owner;
+ error = vfs_test_lock(file->f_file[mode], &conflock->fl);
if (error) {
/* We can't currently deal with deferred test requests */
if (error == FILE_LOCK_DEFERRED)
@@ -614,22 +620,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
goto out;
}
- if (lock->fl.fl_type == F_UNLCK) {
+ if (conflock->fl.fl_type == F_UNLCK) {
ret = nlm_granted;
goto out;
}
dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
- lock->fl.fl_type, (long long)lock->fl.fl_start,
- (long long)lock->fl.fl_end);
+ conflock->fl.fl_type, (long long)conflock->fl.fl_start,
+ (long long)conflock->fl.fl_end);
conflock->caller = "somehost"; /* FIXME */
conflock->len = strlen(conflock->caller);
conflock->oh.len = 0; /* don't return OH info */
- conflock->svid = lock->fl.fl_pid;
- conflock->fl.fl_type = lock->fl.fl_type;
- conflock->fl.fl_start = lock->fl.fl_start;
- conflock->fl.fl_end = lock->fl.fl_end;
- locks_release_private(&lock->fl);
+ conflock->svid = conflock->fl.fl_pid;
+ locks_release_private(&conflock->fl);
ret = nlm_lck_denied;
out:
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 32784f508c81..1a4459763644 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
struct nlm_args *argp = rqstp->rq_argp;
struct nlm_host *host;
struct nlm_file *file;
- struct nlm_lockowner *test_owner;
__be32 rc = rpc_success;
dprintk("lockd: TEST called\n");
@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
- test_owner = argp->lock.fl.fl_owner;
-
/* Now check for conflicting locks */
resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
if (resp->status == nlm_drop_reply)
@@ -137,7 +134,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
dprintk("lockd: TEST status %d vers %d\n",
ntohl(resp->status), rqstp->rq_vers);
- nlmsvc_put_lockowner(test_owner);
+ nlmsvc_release_lockowner(&argp->lock);
nlmsvc_release_host(host);
nlm_release_file(file);
return rc;
diff --git a/fs/locks.c b/fs/locks.c
index ed8b3e318f97..24a82b793c66 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2325,13 +2325,22 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
/**
* vfs_test_lock - test file byte range lock
* @filp: The file to test lock for
- * @fl: The lock to test; also used to hold result
+ * @fl: The byte-range in the file to test; also used to hold result
*
+ * On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end)
+ * in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks
+ * should be ignored. c.flc_type and c.flc_flags are ignored.
+ * Both fl_lmops and fl_ops in @fl must be NULL.
* Returns -ERRNO on failure. Indicates presence of conflicting lock by
- * setting conf->fl_type to something other than F_UNLCK.
+ * setting fl->fl_type to something other than F_UNLCK.
+ *
+ * If vfs_test_lock() does find a lock and return it, the caller must
+ * use locks_free_lock() or locks_release_private() on the returned lock.
*/
int vfs_test_lock(struct file *filp, struct file_lock *fl)
{
+ WARN_ON_ONCE(fl->fl_ops || fl->fl_lmops);
+ WARN_ON_ONCE(filp != fl->fl_file);
if (filp->f_op->lock)
return filp->f_op->lock(filp, F_GETLK, fl);
posix_test_lock(filp, fl);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 935029632d5f..75af965740a4 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -82,8 +82,9 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir
spin_lock(&dir->i_lock);
if (list_empty(&nfsi->open_files) &&
(nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
- nfsi->cache_validity |= NFS_INO_INVALID_DATA |
- NFS_INO_REVAL_FORCED;
+ nfs_set_cache_invalid(dir,
+ NFS_INO_INVALID_DATA |
+ NFS_INO_REVAL_FORCED);
list_add(&ctx->list, &nfsi->open_files);
spin_unlock(&dir->i_lock);
return ctx;
@@ -1203,10 +1204,8 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
static void nfs_mark_dir_for_revalidate(struct inode *inode)
{
- struct nfs_inode *nfsi = NFS_I(inode);
-
spin_lock(&inode->i_lock);
- nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
+ nfs_set_cache_invalid(inode, NFS_INO_REVAL_PAGECACHE);
spin_unlock(&inode->i_lock);
}
@@ -1412,6 +1411,8 @@ __nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags,
int ret;
if (flags & LOOKUP_RCU) {
+ if (dentry->d_fsdata == NFS_FSDATA_BLOCKED)
+ return -ECHILD;
parent = READ_ONCE(dentry->d_parent);
dir = d_inode_rcu(parent);
if (!dir)
@@ -1420,6 +1421,10 @@ __nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags,
if (parent != READ_ONCE(dentry->d_parent))
return -ECHILD;
} else {
+ /* Wait for unlink to complete - see unblock_revalidate() */
+ wait_var_event(&dentry->d_fsdata,
+ smp_load_acquire(&dentry->d_fsdata)
+ != NFS_FSDATA_BLOCKED);
parent = dget_parent(dentry);
ret = reval(d_inode(parent), dentry, flags);
dput(parent);
@@ -1432,6 +1437,29 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
return __nfs_lookup_revalidate(dentry, flags, nfs_do_lookup_revalidate);
}
+static void block_revalidate(struct dentry *dentry)
+{
+ /* old devname - just in case */
+ kfree(dentry->d_fsdata);
+
+ /* Any new reference that could lead to an open
+ * will take ->d_lock in lookup_open() -> d_lookup().
+ * Holding this lock ensures we cannot race with
+ * __nfs_lookup_revalidate() and removes and need
+ * for further barriers.
+ */
+ lockdep_assert_held(&dentry->d_lock);
+
+ dentry->d_fsdata = NFS_FSDATA_BLOCKED;
+}
+
+static void unblock_revalidate(struct dentry *dentry)
+{
+ /* store_release ensures wait_var_event() sees the update */
+ smp_store_release(&dentry->d_fsdata, NULL);
+ wake_up_var(&dentry->d_fsdata);
+}
+
/*
* A weaker form of d_revalidate for revalidating just the d_inode(dentry)
* when we don't really care about the dentry name. This is called when a
@@ -1495,17 +1523,18 @@ static int nfs_dentry_delete(const struct dentry *dentry)
}
/* Ensure that we revalidate inode->i_nlink */
-static void nfs_drop_nlink(struct inode *inode)
+static void nfs_drop_nlink(struct inode *inode, unsigned long gencount)
{
+ struct nfs_inode *nfsi = NFS_I(inode);
+
spin_lock(&inode->i_lock);
/* drop the inode if we're reasonably sure this is the last link */
- if (inode->i_nlink > 0)
+ if (inode->i_nlink > 0 && gencount == nfsi->attr_gencount)
drop_nlink(inode);
- NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME
- | NFS_INO_INVALID_OTHER
- | NFS_INO_REVAL_FORCED;
+ nfsi->attr_gencount = nfs_inc_attr_generation_counter();
+ nfs_set_cache_invalid(
+ inode, NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_CTIME |
+ NFS_INO_INVALID_OTHER | NFS_INO_REVAL_FORCED);
spin_unlock(&inode->i_lock);
}
@@ -1517,11 +1546,12 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
{
if (S_ISDIR(inode->i_mode))
/* drop any readdir cache as it could easily be old */
- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
+ unsigned long gencount = READ_ONCE(NFS_I(inode)->attr_gencount);
nfs_complete_unlink(dentry, inode);
- nfs_drop_nlink(inode);
+ nfs_drop_nlink(inode, gencount);
}
iput(inode);
}
@@ -1997,6 +2027,19 @@ static void nfs_dentry_handle_enoent(struct dentry *dentry)
d_delete(dentry);
}
+static void nfs_dentry_remove_handle_error(struct inode *dir,
+ struct dentry *dentry, int error)
+{
+ switch (error) {
+ case -ENOENT:
+ if (d_really_is_positive(dentry))
+ d_delete(dentry);
+ fallthrough;
+ case 0:
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ }
+}
+
int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
@@ -2019,6 +2062,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
up_write(&NFS_I(d_inode(dentry))->rmdir_sem);
} else
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
+ nfs_dentry_remove_handle_error(dir, dentry, error);
trace_nfs_rmdir_exit(dir, dentry, error);
return error;
@@ -2048,9 +2092,11 @@ static int nfs_safe_remove(struct dentry *dentry)
trace_nfs_remove_enter(dir, dentry);
if (inode != NULL) {
+ unsigned long gencount = READ_ONCE(NFS_I(inode)->attr_gencount);
+
error = NFS_PROTO(dir)->remove(dir, dentry);
if (error == 0)
- nfs_drop_nlink(inode);
+ nfs_drop_nlink(inode, gencount);
} else
error = NFS_PROTO(dir)->remove(dir, dentry);
if (error == -ENOENT)
@@ -2068,7 +2114,6 @@ static int nfs_safe_remove(struct dentry *dentry)
int nfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error;
- int need_rehash = 0;
dfprintk(VFS, "NFS: unlink(%s/%lu, %pd)\n", dir->i_sb->s_id,
dir->i_ino, dentry);
@@ -2082,16 +2127,23 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
error = nfs_sillyrename(dir, dentry);
goto out;
}
- if (!d_unhashed(dentry)) {
- __d_drop(dentry);
- need_rehash = 1;
+ /* We must prevent any concurrent open until the unlink
+ * completes. ->d_revalidate will wait for ->d_fsdata
+ * to clear. We set it here to ensure no lookup succeeds until
+ * the unlink is complete on the server.
+ */
+ error = -ETXTBSY;
+ if (WARN_ON(dentry->d_flags & DCACHE_NFSFS_RENAMED) ||
+ WARN_ON(dentry->d_fsdata == NFS_FSDATA_BLOCKED)) {
+ spin_unlock(&dentry->d_lock);
+ goto out;
}
+ block_revalidate(dentry);
+
spin_unlock(&dentry->d_lock);
error = nfs_safe_remove(dentry);
- if (!error || error == -ENOENT) {
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
- } else if (need_rehash)
- d_rehash(dentry);
+ nfs_dentry_remove_handle_error(dir, dentry, error);
+ unblock_revalidate(dentry);
out:
trace_nfs_unlink_exit(dir, dentry, error);
return error;
@@ -2194,6 +2246,14 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
}
EXPORT_SYMBOL_GPL(nfs_link);
+static void
+nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data)
+{
+ struct dentry *new_dentry = data->new_dentry;
+
+ unblock_revalidate(new_dentry);
+}
+
/*
* RENAME
* FIXME: Some nfsds, like the Linux user space nfsd, may generate a
@@ -2224,8 +2284,10 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
{
struct inode *old_inode = d_inode(old_dentry);
struct inode *new_inode = d_inode(new_dentry);
- struct dentry *dentry = NULL, *rehash = NULL;
+ unsigned long new_gencount = 0;
+ struct dentry *dentry = NULL;
struct rpc_task *task;
+ bool must_unblock = false;
int error = -EBUSY;
if (flags)
@@ -2243,18 +2305,22 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
* the new target.
*/
if (new_inode && !S_ISDIR(new_inode->i_mode)) {
- /*
- * To prevent any new references to the target during the
- * rename, we unhash the dentry in advance.
+ /* We must prevent any concurrent open until the unlink
+ * completes. ->d_revalidate will wait for ->d_fsdata
+ * to clear. We set it here to ensure no lookup succeeds until
+ * the unlink is complete on the server.
*/
- if (!d_unhashed(new_dentry)) {
- d_drop(new_dentry);
- rehash = new_dentry;
- }
+ error = -ETXTBSY;
+ if (WARN_ON(new_dentry->d_flags & DCACHE_NFSFS_RENAMED) ||
+ WARN_ON(new_dentry->d_fsdata == NFS_FSDATA_BLOCKED))
+ goto out;
+ spin_lock(&new_dentry->d_lock);
if (d_count(new_dentry) > 2) {
int err;
+ spin_unlock(&new_dentry->d_lock);
+
/* copy the target dentry's name */
dentry = d_alloc(new_dentry->d_parent,
&new_dentry->d_name);
@@ -2267,15 +2333,23 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto out;
new_dentry = dentry;
- rehash = NULL;
new_inode = NULL;
+ } else {
+ block_revalidate(new_dentry);
+ must_unblock = true;
+ new_gencount = NFS_I(new_inode)->attr_gencount;
+ spin_unlock(&new_dentry->d_lock);
}
+
}
if (S_ISREG(old_inode->i_mode))
nfs_sync_inode(old_inode);
- task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
+ task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry,
+ must_unblock ? nfs_unblock_rename : NULL);
if (IS_ERR(task)) {
+ if (must_unblock)
+ unblock_revalidate(new_dentry);
error = PTR_ERR(task);
goto out;
}
@@ -2292,19 +2366,17 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (error == 0) {
spin_lock(&old_inode->i_lock);
NFS_I(old_inode)->attr_gencount = nfs_inc_attr_generation_counter();
- NFS_I(old_inode)->cache_validity |= NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME
- | NFS_INO_REVAL_FORCED;
+ nfs_set_cache_invalid(old_inode, NFS_INO_INVALID_CHANGE |
+ NFS_INO_INVALID_CTIME |
+ NFS_INO_REVAL_FORCED);
spin_unlock(&old_inode->i_lock);
}
out:
- if (rehash)
- d_rehash(rehash);
trace_nfs_rename_exit(old_dir, old_dentry,
new_dir, new_dentry, error);
if (!error) {
if (new_inode != NULL)
- nfs_drop_nlink(new_inode);
+ nfs_drop_nlink(new_inode, new_gencount);
/*
* The d_move() should be here instead of in an async RPC completion
* handler because we need the proper locks to move the dentry. If
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 3e3114a9d193..6b800df1df29 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -207,7 +207,7 @@ static bool nfs_has_xattr_cache(const struct nfs_inode *nfsi)
}
#endif
-static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
+void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
{
struct nfs_inode *nfsi = NFS_I(inode);
bool have_delegation = NFS_PROTO(inode)->have_delegation(inode, FMODE_READ);
@@ -1065,8 +1065,8 @@ void nfs_inode_attach_open_context(struct nfs_open_context *ctx)
spin_lock(&inode->i_lock);
if (list_empty(&nfsi->open_files) &&
(nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER))
- nfsi->cache_validity |= NFS_INO_INVALID_DATA |
- NFS_INO_REVAL_FORCED;
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA |
+ NFS_INO_REVAL_FORCED);
list_add_tail_rcu(&ctx->list, &nfsi->open_files);
spin_unlock(&inode->i_lock);
}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 838f3a374485..fd15280e827a 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -11,7 +11,7 @@
#include <linux/nfs_page.h>
#include <linux/wait_bit.h>
-#define NFS_SB_MASK (SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
+#define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
extern const struct export_operations nfs_export_ops;
@@ -424,7 +424,8 @@ extern int nfs_write_inode(struct inode *, struct writeback_control *);
extern int nfs_drop_inode(struct inode *);
extern void nfs_clear_inode(struct inode *);
extern void nfs_evict_inode(struct inode *);
-void nfs_zap_acl_cache(struct inode *inode);
+extern void nfs_zap_acl_cache(struct inode *inode);
+extern void nfs_set_cache_invalid(struct inode *inode, unsigned long flags);
extern bool nfs_check_cache_invalid(struct inode *, unsigned long);
extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
extern int nfs_wait_atomic_killable(atomic_t *p, unsigned int mode);
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 1f03445b5cb4..fc9f7b9cbf53 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -149,6 +149,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
struct vfsmount *mnt = ERR_PTR(-ENOMEM);
struct nfs_server *server = NFS_SB(path->dentry->d_sb);
struct nfs_client *client = server->nfs_client;
+ unsigned long s_flags = path->dentry->d_sb->s_flags;
int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout);
int ret;
@@ -169,11 +170,21 @@ struct vfsmount *nfs_d_automount(struct path *path)
if (!ctx->clone_data.fattr)
goto out_fc;
+ if (fc->cred != server->cred) {
+ put_cred(fc->cred);
+ fc->cred = get_cred(server->cred);
+ }
+
if (fc->net_ns != client->cl_net) {
put_net(fc->net_ns);
fc->net_ns = get_net(client->cl_net);
}
+ /* Inherit the flags covered by NFS_SB_MASK */
+ fc->sb_flags_mask |= NFS_SB_MASK;
+ fc->sb_flags &= ~NFS_SB_MASK;
+ fc->sb_flags |= s_flags & NFS_SB_MASK;
+
/* for submounts we want the same server; referrals will reassign */
memcpy(&ctx->nfs_server.address, &client->cl_addr, client->cl_addrlen);
ctx->nfs_server.addrlen = client->cl_addrlen;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e3070982a909..170e9eaf536a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1688,8 +1688,17 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state,
if (nfs_stateid_is_sequential(state, stateid))
break;
- if (status)
- break;
+ if (status) {
+ if (nfs4_stateid_match_other(stateid, &state->open_stateid) &&
+ !nfs4_stateid_is_newer(stateid, &state->open_stateid)) {
+ trace_nfs4_open_stateid_update_skip(state->inode,
+ stateid, status);
+ return;
+ } else {
+ break;
+ }
+ }
+
/* Rely on seqids for serialisation with NFSv4.0 */
if (!nfs4_has_session(NFS_SERVER(state->inode)->nfs_client))
break;
diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h
index d862df9761e7..3d538cb60593 100644
--- a/fs/nfs/nfs4trace.h
+++ b/fs/nfs/nfs4trace.h
@@ -1513,6 +1513,7 @@ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_setattr);
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_delegreturn);
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update);
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_wait);
+DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_skip);
DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_close_stateid_update_wait);
DECLARE_EVENT_CLASS(nfs4_getattr_event,
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index e14cf7140bab..c5dd301c43d7 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -465,6 +465,7 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
struct pnfs_layout_segment *lseg, *next;
set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
+ clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(lo->plh_inode)->flags);
list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
pnfs_clear_lseg_state(lseg, lseg_list);
pnfs_clear_layoutreturn_info(lo);
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 7c58a1688f7f..b99f40e6b951 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1000,16 +1000,6 @@ int nfs_reconfigure(struct fs_context *fc)
sync_filesystem(sb);
- /*
- * The SB_RDONLY flag has been removed from the superblock during
- * mounts to prevent interference between different filesystems.
- * Similarly, it is also necessary to ignore the SB_RDONLY flag
- * during reconfiguration; otherwise, it may also result in the
- * creation of redundant superblocks when mounting a directory with
- * different rw and ro flags multiple times.
- */
- fc->sb_flags_mask &= ~SB_RDONLY;
-
/*
* Userspace mount programs that send binary options generally send
* them populated with default values. We have no way to know which
@@ -1258,29 +1248,13 @@ int nfs_get_tree_common(struct fs_context *fc)
if (IS_ERR(server))
return PTR_ERR(server);
- /*
- * When NFS_MOUNT_UNSHARED is not set, NFS forces the sharing of a
- * superblock among each filesystem that mounts sub-directories
- * belonging to a single exported root path.
- * To prevent interference between different filesystems, the
- * SB_RDONLY flag should be removed from the superblock.
- */
if (server->flags & NFS_MOUNT_UNSHARED)
compare_super = NULL;
- else
- fc->sb_flags &= ~SB_RDONLY;
/* -o noac implies -o sync */
if (server->flags & NFS_MOUNT_NOAC)
fc->sb_flags |= SB_SYNCHRONOUS;
- if (ctx->clone_data.sb)
- if (ctx->clone_data.sb->s_flags & SB_SYNCHRONOUS)
- fc->sb_flags |= SB_SYNCHRONOUS;
-
- if (server->caps & NFS_CAP_SECURITY_LABEL)
- fc->lsm_flags |= SECURITY_LSM_NATIVE_LABELS;
-
/* Get a superblock - note that we may end up sharing one that already exists */
fc->s_fs_info = server;
s = sget_fc(fc, compare_super, nfs_set_super);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index b27ebdccef70..5fa11e1aca4c 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -500,9 +500,9 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
spin_lock(&inode->i_lock);
NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME
- | NFS_INO_REVAL_FORCED;
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE |
+ NFS_INO_INVALID_CTIME |
+ NFS_INO_REVAL_FORCED);
spin_unlock(&inode->i_lock);
d_move(dentry, sdentry);
break;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0b05a40a21f3..a95a747fbc8d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -260,9 +260,9 @@ static void nfs_set_pageerror(struct address_space *mapping)
nfs_zap_mapping(mapping->host, mapping);
/* Force file size revalidation */
spin_lock(&inode->i_lock);
- NFS_I(inode)->cache_validity |= NFS_INO_REVAL_FORCED |
- NFS_INO_REVAL_PAGECACHE |
- NFS_INO_INVALID_SIZE;
+ nfs_set_cache_invalid(inode, NFS_INO_REVAL_FORCED |
+ NFS_INO_REVAL_PAGECACHE |
+ NFS_INO_INVALID_SIZE);
spin_unlock(&inode->i_lock);
}
@@ -1614,7 +1614,7 @@ static int nfs_writeback_done(struct rpc_task *task,
/* Deal with the suid/sgid bit corner case */
if (nfs_should_remove_suid(inode)) {
spin_lock(&inode->i_lock);
- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_OTHER;
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
spin_unlock(&inode->i_lock);
}
return 0;
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index aa9b7ae59a07..5c8f20a326d2 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -27,6 +27,7 @@ nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
{
struct nfsd4_layout_seg *seg = &args->lg_seg;
struct super_block *sb = inode->i_sb;
+ u64 length;
u32 block_size = i_blocksize(inode);
struct pnfs_block_extent *bex;
struct iomap iomap;
@@ -57,7 +58,8 @@ nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
goto out_error;
}
- if (iomap.length < args->lg_minlength) {
+ length = iomap.offset + iomap.length - seg->offset;
+ if (length < args->lg_minlength) {
dprintk("pnfsd: extent smaller than minlength\n");
goto out_layoutunavailable;
}
@@ -408,7 +410,8 @@ nfsd4_scsi_fence_client(struct nfs4_layout_stateid *ls)
struct block_device *bdev = ls->ls_file->nf_file->f_path.mnt->mnt_sb->s_bdev;
bdev->bd_disk->fops->pr_ops->pr_preempt(bdev, NFSD_MDS_PR_KEY,
- nfsd4_scsi_pr_key(clp), 0, true);
+ nfsd4_scsi_pr_key(clp),
+ PR_EXCLUSIVE_ACCESS_REG_ONLY, true);
}
const struct nfsd4_layout_ops scsi_layout_ops = {
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 37299f90b049..6d47408dd28a 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -984,7 +984,7 @@ exp_rootfh(struct net *net, struct auth_domain *clp, char *name,
{
struct svc_export *exp;
struct path path;
- struct inode *inode;
+ struct inode *inode __maybe_unused;
struct svc_fh fh;
int err;
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 41c750f34473..be0c8f1ce4e3 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -64,6 +64,8 @@ struct nfsd_net {
struct lock_manager nfsd4_manager;
bool grace_ended;
+ bool grace_end_forced;
+ bool client_tracking_active;
time64_t boot_time;
struct dentry *nfsd_client_dir;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1ac405bb5de2..6b34bfac6194 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -84,7 +84,7 @@ static u64 current_sessionid = 1;
/* forward declarations */
static bool check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner);
static void nfs4_free_ol_stateid(struct nfs4_stid *stid);
-void nfsd4_end_grace(struct nfsd_net *nn);
+static void nfsd4_end_grace(struct nfsd_net *nn);
static void _free_cpntf_state_locked(struct nfsd_net *nn, struct nfs4_cpntf_state *cps);
static void nfsd4_file_hash_remove(struct nfs4_file *fi);
@@ -2802,8 +2802,10 @@ static int client_states_open(struct inode *inode, struct file *file)
return -ENXIO;
ret = seq_open(file, &states_seq_ops);
- if (ret)
+ if (ret) {
+ drop_client(clp);
return ret;
+ }
s = file->private_data;
s->private = clp;
return 0;
@@ -5877,7 +5879,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return nfs_ok;
}
-void
+static void
nfsd4_end_grace(struct nfsd_net *nn)
{
/* do nothing if grace period already ended */
@@ -5910,6 +5912,33 @@ nfsd4_end_grace(struct nfsd_net *nn)
*/
}
+/**
+ * nfsd4_force_end_grace - forcibly end the NFSv4 grace period
+ * @nn: network namespace for the server instance to be updated
+ *
+ * Forces bypass of normal grace period completion, then schedules
+ * the laundromat to end the grace period immediately. Does not wait
+ * for the grace period to fully terminate before returning.
+ *
+ * Return values:
+ * %true: Grace termination schedule
+ * %false: No action was taken
+ */
+bool nfsd4_force_end_grace(struct nfsd_net *nn)
+{
+ if (!nn->client_tracking_ops)
+ return false;
+ spin_lock(&nn->client_lock);
+ if (nn->grace_ended || !nn->client_tracking_active) {
+ spin_unlock(&nn->client_lock);
+ return false;
+ }
+ WRITE_ONCE(nn->grace_end_forced, true);
+ mod_delayed_work(laundry_wq, &nn->laundromat_work, 0);
+ spin_unlock(&nn->client_lock);
+ return true;
+}
+
/*
* If we've waited a lease period but there are still clients trying to
* reclaim, wait a little longer to give them a chance to finish.
@@ -5919,6 +5948,8 @@ static bool clients_still_reclaiming(struct nfsd_net *nn)
time64_t double_grace_period_end = nn->boot_time +
2 * nn->nfsd4_lease;
+ if (READ_ONCE(nn->grace_end_forced))
+ return false;
if (nn->track_reclaim_completes &&
atomic_read(&nn->nr_reclaim_complete) ==
nn->reclaim_str_hashtbl_size)
@@ -8139,6 +8170,8 @@ static int nfs4_state_create_net(struct net *net)
nn->unconf_name_tree = RB_ROOT;
nn->boot_time = ktime_get_real_seconds();
nn->grace_ended = false;
+ nn->grace_end_forced = false;
+ nn->client_tracking_active = false;
nn->nfsd4_manager.block_opens = true;
INIT_LIST_HEAD(&nn->nfsd4_manager.list);
INIT_LIST_HEAD(&nn->client_lru);
@@ -8215,6 +8248,10 @@ nfs4_state_start_net(struct net *net)
return ret;
locks_start_grace(net, &nn->nfsd4_manager);
nfsd4_client_tracking_init(net);
+ /* safe for laundromat to run now */
+ spin_lock(&nn->client_lock);
+ nn->client_tracking_active = true;
+ spin_unlock(&nn->client_lock);
if (nn->track_reclaim_completes && nn->reclaim_str_hashtbl_size == 0)
goto skip_grace;
printk(KERN_INFO "NFSD: starting %lld-second grace period (net %x)\n",
@@ -8261,6 +8298,9 @@ nfs4_state_shutdown_net(struct net *net)
unregister_shrinker(&nn->nfsd_client_shrinker);
cancel_work_sync(&nn->nfsd_shrinker_work);
+ spin_lock(&nn->client_lock);
+ nn->client_tracking_active = false;
+ spin_unlock(&nn->client_lock);
cancel_delayed_work_sync(&nn->laundromat_work);
locks_end_grace(&nn->nfsd4_manager);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 57dc5493c860..4253778a9747 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3408,6 +3408,11 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
u32 supp[3];
memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
+ if (!IS_POSIXACL(d_inode(dentry)))
+ supp[0] &= ~FATTR4_WORD0_ACL;
+ if (!contextsupport)
+ supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
+
supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2feaa49fb9fe..07e5b1b23c91 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1117,9 +1117,8 @@ static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
case 'Y':
case 'y':
case '1':
- if (!nn->nfsd_serv)
+ if (!nfsd4_force_end_grace(nn))
return -EBUSY;
- nfsd4_end_grace(nn);
break;
default:
return -EINVAL;
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index e94634d30591..477828dbfc66 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -719,7 +719,7 @@ static inline void get_nfs4_file(struct nfs4_file *fi)
struct nfsd_file *find_any_file(struct nfs4_file *f);
/* grace period management */
-void nfsd4_end_grace(struct nfsd_net *nn);
+bool nfsd4_force_end_grace(struct nfsd_net *nn);
/* nfs4recover operations */
extern int nfsd4_client_tracking_init(struct net *net);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 54be4cd9794a..7739a47356e7 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1335,7 +1335,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
* Callers expect new file metadata to be committed even
* if the attributes have not changed.
*/
- if (iap->ia_valid)
+ if (iap->ia_valid || attrs->na_pacl || attrs->na_dpacl)
status = nfsd_setattr(rqstp, resfhp, attrs, 0, (time64_t)0);
else
status = nfserrno(commit_metadata(resfhp));
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index a026dbd3593f..f072eb6b563f 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -67,19 +67,22 @@ int utf8_to_utf32(const u8 *s, int inlen, unicode_t *pu)
l &= t->lmask;
if (l < t->lval || l > UNICODE_MAX ||
(l & SURROGATE_MASK) == SURROGATE_PAIR)
- return -1;
+ return -EILSEQ;
+
*pu = (unicode_t) l;
return nc;
}
if (inlen <= nc)
- return -1;
+ return -EOVERFLOW;
+
s++;
c = (*s ^ 0x80) & 0xFF;
if (c & 0xC0)
- return -1;
+ return -EILSEQ;
+
l = (l << 6) | c;
}
- return -1;
+ return -EILSEQ;
}
EXPORT_SYMBOL(utf8_to_utf32);
@@ -94,7 +97,7 @@ int utf32_to_utf8(unicode_t u, u8 *s, int maxout)
l = u;
if (l > UNICODE_MAX || (l & SURROGATE_MASK) == SURROGATE_PAIR)
- return -1;
+ return -EILSEQ;
nc = 0;
for (t = utf8_table; t->cmask && maxout; t++, maxout--) {
@@ -110,7 +113,7 @@ int utf32_to_utf8(unicode_t u, u8 *s, int maxout)
return nc;
}
}
- return -1;
+ return -EOVERFLOW;
}
EXPORT_SYMBOL(utf32_to_utf8);
@@ -217,8 +220,16 @@ int utf16s_to_utf8s(const wchar_t *pwcs, int inlen, enum utf16_endian endian,
inlen--;
}
size = utf32_to_utf8(u, op, maxout);
- if (size == -1) {
- /* Ignore character and move on */
+ if (size < 0) {
+ if (size == -EILSEQ) {
+ /* Ignore character and move on */
+ continue;
+ }
+ /*
+ * Stop filling the buffer with data once a character
+ * does not fit anymore.
+ */
+ break;
} else {
op += size;
maxout -= size;
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 9cc4ebb53504..82602157bcc0 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -224,8 +224,15 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
/*
* Include parent/name in notification either if some notification
* groups require parent info or the parent is interested in this event.
+ * The parent interest in ACCESS/MODIFY events does not apply to special
+ * files, where read/write are not on the filesystem of the parent and
+ * events can provide an undesirable side-channel for information
+ * exfiltration.
*/
- parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS;
+ parent_interested = mask & p_mask & ALL_FSNOTIFY_EVENTS &&
+ !(data_type == FSNOTIFY_EVENT_PATH &&
+ d_is_special(dentry) &&
+ (mask & (FS_ACCESS | FS_MODIFY)));
if (parent_needed || parent_interested) {
/* When notifying parent, child should be passed as data */
WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type));
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 94c7acfebe18..9f61a6d64cbc 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -3649,7 +3649,6 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path,
* So we use the new rightmost path.
*/
ocfs2_mv_path(right_path, left_path);
- left_path = NULL;
} else
ocfs2_complete_edge_insert(handle, left_path,
right_path, subtree_index);
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
index 3cc28afe9815..6df8b5513bab 100644
--- a/fs/ocfs2/move_extents.c
+++ b/fs/ocfs2/move_extents.c
@@ -100,7 +100,13 @@ static int __ocfs2_move_extent(handle_t *handle,
rec = &el->l_recs[index];
- BUG_ON(ext_flags != rec->e_flags);
+ if (ext_flags != rec->e_flags) {
+ ret = ocfs2_error(inode->i_sb,
+ "Inode %llu has corrupted extent %d with flags 0x%x at cpos %u\n",
+ (unsigned long long)ino, index, rec->e_flags, cpos);
+ goto out;
+ }
+
/*
* after moving/defraging to new location, the extent is not going
* to be refcounted anymore.
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 4f48003e4327..984bf3d24c23 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -1925,6 +1925,16 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
}
cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
+ if (!le16_to_cpu(cl->cl_next_free_rec) ||
+ le16_to_cpu(cl->cl_next_free_rec) > le16_to_cpu(cl->cl_count)) {
+ status = ocfs2_error(ac->ac_inode->i_sb,
+ "Chain allocator dinode %llu has invalid next "
+ "free chain record %u, but only %u total\n",
+ (unsigned long long)le64_to_cpu(fe->i_blkno),
+ le16_to_cpu(cl->cl_next_free_rec),
+ le16_to_cpu(cl->cl_count));
+ goto bail;
+ }
victim = ocfs2_find_victim_chain(cl);
ac->ac_chain = victim;
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
index f981283177ec..dd3e1969e6c8 100644
--- a/fs/overlayfs/export.c
+++ b/fs/overlayfs/export.c
@@ -788,7 +788,7 @@ static struct ovl_fh *ovl_fid_to_fh(struct fid *fid, int buflen, int fh_type)
return ERR_PTR(-ENOMEM);
/* Copy unaligned inner fh into aligned buffer */
- memcpy(&fh->fb, fid, buflen - OVL_FH_WIRE_OFFSET);
+ memcpy(fh->buf, fid, buflen - OVL_FH_WIRE_OFFSET);
return fh;
}
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 87b7a4a74f4e..5ac968f709a4 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -104,7 +104,7 @@ struct ovl_fh {
u8 padding[3]; /* make sure fb.fid is 32bit aligned */
union {
struct ovl_fb fb;
- u8 buf[0];
+ DECLARE_FLEX_ARRAY(u8, buf);
};
} __packed;
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index a3d5ecccfc2c..deb69740d492 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -744,6 +744,7 @@ xfs_buf_item_init(
map_size = DIV_ROUND_UP(chunks, NBWORD);
if (map_size > XFS_BLF_DATAMAP_SIZE) {
+ xfs_buf_item_free_format(bip);
kmem_cache_free(xfs_buf_item_zone, bip);
xfs_err(mp,
"buffer item dirty bitmap (%u uints) too small to reflect %u bytes!",
diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
index 338aa27e4773..ee30fb134478 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -80,12 +80,6 @@ static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
#ifdef CONFIG_BALLOON_COMPACTION
extern const struct address_space_operations balloon_aops;
-extern bool balloon_page_isolate(struct page *page,
- isolate_mode_t mode);
-extern void balloon_page_putback(struct page *page);
-extern int balloon_page_migrate(struct address_space *mapping,
- struct page *newpage,
- struct page *page, enum migrate_mode mode);
/*
* balloon_page_insert - insert a page into the balloon's page list and make
@@ -105,27 +99,6 @@ static inline void balloon_page_insert(struct balloon_dev_info *balloon,
list_add(&page->lru, &balloon->pages);
}
-/*
- * balloon_page_delete - delete a page from balloon's page list and clear
- * the page->private assignement accordingly.
- * @page : page to be released from balloon's page list
- *
- * Caller must ensure the page is locked and the spin_lock protecting balloon
- * pages list is held before deleting a page from the balloon device.
- */
-static inline void balloon_page_delete(struct page *page)
-{
- __ClearPageOffline(page);
- __ClearPageMovable(page);
- set_page_private(page, 0);
- /*
- * No touch page.lru field once @page has been isolated
- * because VM is using the field.
- */
- if (!PageIsolated(page))
- list_del(&page->lru);
-}
-
/*
* balloon_page_device - get the b_dev_info descriptor for the balloon device
* that enqueues the given page.
@@ -149,28 +122,6 @@ static inline void balloon_page_insert(struct balloon_dev_info *balloon,
list_add(&page->lru, &balloon->pages);
}
-static inline void balloon_page_delete(struct page *page)
-{
- __ClearPageOffline(page);
- list_del(&page->lru);
-}
-
-static inline bool balloon_page_isolate(struct page *page)
-{
- return false;
-}
-
-static inline void balloon_page_putback(struct page *page)
-{
- return;
-}
-
-static inline int balloon_page_migrate(struct page *newpage,
- struct page *page, enum migrate_mode mode)
-{
- return 0;
-}
-
static inline gfp_t balloon_mapping_gfp_mask(void)
{
return GFP_HIGHUSER;
@@ -178,6 +129,22 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
#endif /* CONFIG_BALLOON_COMPACTION */
+/*
+ * balloon_page_finalize - prepare a balloon page that was removed from the
+ * balloon list for release to the page allocator
+ * @page: page to be released to the page allocator
+ *
+ * Caller must ensure that the page is locked.
+ */
+static inline void balloon_page_finalize(struct page *page)
+{
+ if (IS_ENABLED(CONFIG_BALLOON_COMPACTION)) {
+ __ClearPageMovable(page);
+ set_page_private(page, 0);
+ }
+ __ClearPageOffline(page);
+}
+
/*
* balloon_page_push - insert a page into a page list.
* @head : pointer to list
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 40839ae52f61..11c03df4709f 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -487,10 +487,7 @@ static inline bool op_is_discard(unsigned int op)
}
/*
- * Check if a bio or request operation is a zone management operation, with
- * the exception of REQ_OP_ZONE_RESET_ALL which is treated as a special case
- * due to its different handling in the block layer and device response in
- * case of command failure.
+ * Check if a bio or request operation is a zone management operation.
*/
static inline bool op_is_zone_mgmt(enum req_opf op)
{
diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
index 383295e21e52..d9376e327d66 100644
--- a/include/linux/compiler-clang.h
+++ b/include/linux/compiler-clang.h
@@ -89,6 +89,29 @@
#define __no_sanitize_undefined
#endif
+#if __has_feature(memory_sanitizer)
+#define __SANITIZE_MEMORY__
+/*
+ * Unlike other sanitizers, KMSAN still inserts code into functions marked with
+ * no_sanitize("kernel-memory"). Using disable_sanitizer_instrumentation
+ * provides the behavior consistent with other __no_sanitize_ attributes,
+ * guaranteeing that __no_sanitize_memory functions remain uninstrumented.
+ */
+#define __no_sanitize_memory __disable_sanitizer_instrumentation
+
+/*
+ * The __no_kmsan_checks attribute ensures that a function does not produce
+ * false positive reports by:
+ * - initializing all local variables and memory stores in this function;
+ * - skipping all shadow checks;
+ * - passing initialized arguments to this function's callees.
+ */
+#define __no_kmsan_checks __attribute__((no_sanitize("kernel-memory")))
+#else
+#define __no_sanitize_memory
+#define __no_kmsan_checks
+#endif
+
/*
* Support for __has_feature(coverage_sanitizer) was added in Clang 13 together
* with no_sanitize("coverage"). Prior versions of Clang support coverage
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index ae9a8e17287c..a16d182a3e95 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -140,6 +140,20 @@
#define __no_sanitize_coverage
#endif
+/*
+ * Treat __SANITIZE_HWADDRESS__ the same as __SANITIZE_ADDRESS__ in the kernel,
+ * matching the defines used by Clang.
+ */
+#ifdef __SANITIZE_HWADDRESS__
+#define __SANITIZE_ADDRESS__
+#endif
+
+/*
+ * GCC does not support KMSAN.
+ */
+#define __no_sanitize_memory
+#define __no_kmsan_checks
+
/*
* Turn individual warnings and errors on and off locally, depending
* on version.
diff --git a/include/linux/console.h b/include/linux/console.h
index bc2a749e6f0d..a97f277cfdfa 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -62,7 +62,6 @@ struct consw {
int (*con_font_get)(struct vc_data *vc, struct console_font *font);
int (*con_font_default)(struct vc_data *vc,
struct console_font *font, char *name);
- int (*con_font_copy)(struct vc_data *vc, int con);
int (*con_resize)(struct vc_data *vc, unsigned int width,
unsigned int height, unsigned int user);
void (*con_set_palette)(struct vc_data *vc,
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 6a511a1078ca..a31e22cc839e 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -270,11 +270,11 @@ enum {
#define CPER_ARM_INFO_FLAGS_PROPAGATED BIT(2)
#define CPER_ARM_INFO_FLAGS_OVERFLOW BIT(3)
-#define CPER_ARM_CACHE_ERROR 0
-#define CPER_ARM_TLB_ERROR 1
-#define CPER_ARM_BUS_ERROR 2
-#define CPER_ARM_VENDOR_ERROR 3
-#define CPER_ARM_MAX_TYPE CPER_ARM_VENDOR_ERROR
+#define CPER_ARM_ERR_TYPE_MASK GENMASK(4,1)
+#define CPER_ARM_CACHE_ERROR BIT(1)
+#define CPER_ARM_TLB_ERROR BIT(2)
+#define CPER_ARM_BUS_ERROR BIT(3)
+#define CPER_ARM_VENDOR_ERROR BIT(4)
#define CPER_ARM_ERR_VALID_TRANSACTION_TYPE BIT(0)
#define CPER_ARM_ERR_VALID_OPERATION_TYPE BIT(1)
@@ -560,6 +560,8 @@ const char *cper_severity_str(unsigned int);
const char *cper_mem_err_type_str(unsigned int);
void cper_print_bits(const char *prefix, unsigned int bits,
const char * const strs[], unsigned int strs_size);
+int cper_bits_to_str(char *buf, int buf_size, unsigned long bits,
+ const char * const strs[], unsigned int strs_size);
void cper_mem_err_pack(const struct cper_sec_mem_err *,
struct cper_mem_err_compact *);
const char *cper_mem_err_unpack(struct trace_seq *,
diff --git a/include/linux/font.h b/include/linux/font.h
index 4f50d736ea72..abf1442ce719 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -17,6 +17,7 @@ struct font_desc {
int idx;
const char *name;
unsigned int width, height;
+ unsigned int charcount;
const void *data;
int pref;
};
diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
index 40dd74bdd9fb..9229ac6a5326 100644
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -104,7 +104,6 @@ struct fs_context {
unsigned int sb_flags; /* Proposed superblock flags (SB_*) */
unsigned int sb_flags_mask; /* Superblock flags that were changed */
unsigned int s_iflags; /* OR'd with sb->s_iflags */
- unsigned int lsm_flags; /* Information flags from the fs to the LSM */
enum fs_context_purpose purpose:8;
enum fs_context_phase phase:8; /* The phase the context is in */
bool need_free:1; /* Need to call ops->free() */
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
index 0bd581003cd5..60de63e46b33 100644
--- a/include/linux/genalloc.h
+++ b/include/linux/genalloc.h
@@ -44,6 +44,7 @@ struct gen_pool;
* @nr: The number of zeroed bits we're looking for
* @data: optional additional data used by the callback
* @pool: the pool being allocated from
+ * @start_addr: start address of memory chunk
*/
typedef unsigned long (*genpool_algo_t)(unsigned long *map,
unsigned long size,
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 770408b2fdaf..f12357c7ea36 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2627,8 +2627,8 @@ enum ieee80211_statuscode {
WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
/* 802.11ai */
- WLAN_STATUS_FILS_AUTHENTICATION_FAILURE = 108,
- WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER = 109,
+ WLAN_STATUS_FILS_AUTHENTICATION_FAILURE = 112,
+ WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER = 113,
WLAN_STATUS_SAE_HASH_TO_ELEMENT = 126,
WLAN_STATUS_SAE_PK = 127,
};
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d3a3e77a18df..dcf1b603cb51 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4890,7 +4890,8 @@ netdev_features_t netdev_increment_features(netdev_features_t all,
static inline netdev_features_t netdev_add_tso_features(netdev_features_t features,
netdev_features_t mask)
{
- return netdev_increment_features(features, NETIF_F_ALL_TSO, mask);
+ return netdev_increment_features(features, NETIF_F_ALL_TSO |
+ NETIF_F_ALL_FOR_ALL, mask);
}
int __netdev_update_features(struct net_device *dev);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 7488864589a7..8d4f019b7af8 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -591,6 +591,15 @@ nfs_fileid_to_ino_t(u64 fileid)
#define NFS_JUKEBOX_RETRY_TIME (5 * HZ)
+/* We need to block new opens while a file is being unlinked.
+ * If it is opened *before* we decide to unlink, we will silly-rename
+ * instead. If it is opened *after*, then we need to create or will fail.
+ * If we allow the two to race, we could end up with a file that is open
+ * but deleted on the server resulting in ESTALE.
+ * So use ->d_fsdata to record when the unlink is happening
+ * and block dentry revalidation while it is set.
+ */
+#define NFS_FSDATA_BLOCKED ((void*)1)
# undef ifdebug
# ifdef NFS_DEBUG
diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
index ab222dd05bbc..3b4a891acefe 100644
--- a/include/linux/platform_data/lp855x.h
+++ b/include/linux/platform_data/lp855x.h
@@ -124,12 +124,12 @@ struct lp855x_rom_data {
};
/**
- * struct lp855x_platform_data
+ * struct lp855x_platform_data - lp855 platform-specific data
* @name : Backlight driver name. If it is not defined, default name is set.
* @device_control : value of DEVICE CONTROL register
* @initial_brightness : initial value of backlight brightness
* @period_ns : platform specific pwm period value. unit is nano.
- Only valid when mode is PWM_BASED.
+ * Only valid when mode is PWM_BASED.
* @size_program : total size of lp855x_rom_data
* @rom_data : list of new eeprom/eprom registers
*/
diff --git a/include/linux/rculist_nulls.h b/include/linux/rculist_nulls.h
index ff3e94779e73..c3efa06bd1fe 100644
--- a/include/linux/rculist_nulls.h
+++ b/include/linux/rculist_nulls.h
@@ -52,6 +52,13 @@ static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n)
#define hlist_nulls_next_rcu(node) \
(*((struct hlist_nulls_node __rcu __force **)&(node)->next))
+/**
+ * hlist_nulls_pprev_rcu - returns the dereferenced pprev of @node.
+ * @node: element of the list.
+ */
+#define hlist_nulls_pprev_rcu(node) \
+ (*((struct hlist_nulls_node __rcu __force **)(node)->pprev))
+
/**
* hlist_nulls_del_rcu - deletes entry from hash list without re-initialization
* @n: the element to delete from the hash list.
@@ -152,6 +159,58 @@ static inline void hlist_nulls_add_fake(struct hlist_nulls_node *n)
n->next = (struct hlist_nulls_node *)NULLS_MARKER(NULL);
}
+/**
+ * hlist_nulls_replace_rcu - replace an old entry by a new one
+ * @old: the element to be replaced
+ * @new: the new element to insert
+ *
+ * Description:
+ * Replace the old entry with the new one in a RCU-protected hlist_nulls, while
+ * permitting racing traversals.
+ *
+ * The caller must take whatever precautions are necessary (such as holding
+ * appropriate locks) to avoid racing with another list-mutation primitive, such
+ * as hlist_nulls_add_head_rcu() or hlist_nulls_del_rcu(), running on this same
+ * list. However, it is perfectly legal to run concurrently with the _rcu
+ * list-traversal primitives, such as hlist_nulls_for_each_entry_rcu().
+ */
+static inline void hlist_nulls_replace_rcu(struct hlist_nulls_node *old,
+ struct hlist_nulls_node *new)
+{
+ struct hlist_nulls_node *next = old->next;
+
+ WRITE_ONCE(new->next, next);
+ WRITE_ONCE(new->pprev, old->pprev);
+ rcu_assign_pointer(hlist_nulls_pprev_rcu(new), new);
+ if (!is_a_nulls(next))
+ WRITE_ONCE(next->pprev, &new->next);
+}
+
+/**
+ * hlist_nulls_replace_init_rcu - replace an old entry by a new one and
+ * initialize the old
+ * @old: the element to be replaced
+ * @new: the new element to insert
+ *
+ * Description:
+ * Replace the old entry with the new one in a RCU-protected hlist_nulls, while
+ * permitting racing traversals, and reinitialize the old entry.
+ *
+ * Note: @old must be hashed.
+ *
+ * The caller must take whatever precautions are necessary (such as holding
+ * appropriate locks) to avoid racing with another list-mutation primitive, such
+ * as hlist_nulls_add_head_rcu() or hlist_nulls_del_rcu(), running on this same
+ * list. However, it is perfectly legal to run concurrently with the _rcu
+ * list-traversal primitives, such as hlist_nulls_for_each_entry_rcu().
+ */
+static inline void hlist_nulls_replace_init_rcu(struct hlist_nulls_node *old,
+ struct hlist_nulls_node *new)
+{
+ hlist_nulls_replace_rcu(old, new);
+ WRITE_ONCE(old->pprev, NULL);
+}
+
/**
* hlist_nulls_for_each_entry_rcu - iterate over rcu list of given type
* @tpos: the type * to use as a loop cursor.
diff --git a/include/linux/security.h b/include/linux/security.h
index e32e040f094c..c75dd495be77 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -68,7 +68,7 @@ struct watch_notification;
/* If capable is being called by a setid function */
#define CAP_OPT_INSETID BIT(2)
-/* LSM Agnostic defines for fs_context::lsm_flags */
+/* LSM Agnostic defines for security_sb_set_mnt_opts() flags */
#define SECURITY_LSM_NATIVE_LABELS 1
struct ctl_table;
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 7868e847eee0..6d9d90f01b63 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -25,7 +25,10 @@
#include <crypto/hash_info.h>
#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */
-#define TPM_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
+
+#define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
+#define TPM2_MAX_PCR_BANKS 8
+#define TPM_MAX_DIGEST_SIZE TPM2_MAX_DIGEST_SIZE
struct tpm_chip;
struct trusted_key_payload;
@@ -44,7 +47,7 @@ enum tpm_algorithms {
struct tpm_digest {
u16 alg_id;
- u8 digest[TPM_MAX_DIGEST_SIZE];
+ u8 digest[TPM2_MAX_DIGEST_SIZE];
} __packed;
struct tpm_bank_info {
@@ -150,7 +153,7 @@ struct tpm_chip {
unsigned int groups_cnt;
u32 nr_allocated_banks;
- struct tpm_bank_info *allocated_banks;
+ struct tpm_bank_info allocated_banks[TPM2_MAX_PCR_BANKS];
#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 11df3d5b40c6..8bdeced70a33 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -341,6 +341,9 @@ struct usb_gadget_ops {
* @max_speed: Maximal speed the UDC can handle. UDC must support this
* and all slower speeds.
* @state: the state we are now (attached, suspended, configured, etc)
+ * @state_lock: Spinlock protecting the `state` and `teardown` members.
+ * @teardown: True if the device is undergoing teardown, used to prevent
+ * new work from being scheduled during cleanup.
* @name: Identifies the controller hardware type. Used in diagnostics
* and sometimes configuration.
* @dev: Driver model state for this abstract device.
@@ -408,6 +411,8 @@ struct usb_gadget {
enum usb_device_speed speed;
enum usb_device_speed max_speed;
enum usb_device_state state;
+ spinlock_t state_lock;
+ bool teardown;
const char *name;
struct device dev;
unsigned isoch_delay;
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index b341dd62aa4d..f971986fa0e9 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -247,7 +247,7 @@ const char *virtio_bus_name(struct virtio_device *vdev)
* @vq: the virtqueue
* @cpu: the cpu no.
*
- * Pay attention the function are best-effort: the affinity hint may not be set
+ * Note that this function is best-effort: the affinity hint may not be set
* due to config support, irq type and sharing.
*
*/
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 8d52c4506762..f4ba6e27ee7d 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -185,8 +185,7 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx);
* other instances to take control of the device.
*
* This function has to be called only after &v4l2_m2m_ops->device_run
- * callback has been called on the driver. To prevent recursion, it should
- * not be called directly from the &v4l2_m2m_ops->device_run callback though.
+ * callback has been called on the driver.
*/
void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
struct v4l2_m2m_ctx *m2m_ctx);
diff --git a/include/net/netfilter/nf_conntrack_count.h b/include/net/netfilter/nf_conntrack_count.h
index 9645b47fa7e4..115bb7e572f7 100644
--- a/include/net/netfilter/nf_conntrack_count.h
+++ b/include/net/netfilter/nf_conntrack_count.h
@@ -10,6 +10,7 @@ struct nf_conncount_data;
struct nf_conncount_list {
spinlock_t list_lock;
+ u32 last_gc; /* jiffies at most recent gc */
struct list_head head; /* connections with the same filtering key */
unsigned int count; /* length of list */
};
@@ -19,15 +20,14 @@ struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family
void nf_conncount_destroy(struct net *net, unsigned int family,
struct nf_conncount_data *data);
-unsigned int nf_conncount_count(struct net *net,
- struct nf_conncount_data *data,
- const u32 *key,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_zone *zone);
+unsigned int nf_conncount_count_skb(struct net *net,
+ const struct sk_buff *skb,
+ u16 l3num,
+ struct nf_conncount_data *data,
+ const u32 *key);
-int nf_conncount_add(struct net *net, struct nf_conncount_list *list,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_zone *zone);
+int nf_conncount_add_skb(struct net *net, const struct sk_buff *skb,
+ u16 l3num, struct nf_conncount_list *list);
void nf_conncount_list_init(struct nf_conncount_list *list);
diff --git a/include/net/sock.h b/include/net/sock.h
index bfba1c312a55..4e5386cdb09c 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -769,6 +769,19 @@ static inline bool sk_nulls_del_node_init_rcu(struct sock *sk)
return rc;
}
+static inline bool sk_nulls_replace_node_init_rcu(struct sock *old,
+ struct sock *new)
+{
+ if (sk_hashed(old)) {
+ hlist_nulls_replace_init_rcu(&old->sk_nulls_node,
+ &new->sk_nulls_node);
+ __sock_put(old);
+ return true;
+ }
+
+ return false;
+}
+
static inline void __sk_add_node(struct sock *sk, struct hlist_head *list)
{
hlist_add_head(&sk->sk_node, list);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2c1feca28203..411949a66a83 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -400,7 +400,6 @@ int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo);
int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo);
void xfrm_flush_gc(void);
-void xfrm_state_delete_tunnel(struct xfrm_state *x);
struct xfrm_type {
char *description;
@@ -795,7 +794,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
xfrm_pol_put(pols[i]);
}
-void __xfrm_state_destroy(struct xfrm_state *, bool);
+void __xfrm_state_destroy(struct xfrm_state *);
static inline void __xfrm_state_put(struct xfrm_state *x)
{
@@ -805,13 +804,7 @@ static inline void __xfrm_state_put(struct xfrm_state *x)
static inline void xfrm_state_put(struct xfrm_state *x)
{
if (refcount_dec_and_test(&x->refcnt))
- __xfrm_state_destroy(x, false);
-}
-
-static inline void xfrm_state_put_sync(struct xfrm_state *x)
-{
- if (refcount_dec_and_test(&x->refcnt))
- __xfrm_state_destroy(x, true);
+ __xfrm_state_destroy(x);
}
static inline void xfrm_state_hold(struct xfrm_state *x)
@@ -1586,7 +1579,7 @@ struct xfrmk_spdinfo {
struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
int xfrm_state_delete(struct xfrm_state *x);
-int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync);
+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid);
int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index fa00e2543ad6..dd9b2bc1aea7 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -401,6 +401,8 @@ extern int iscsi_target_alloc(struct scsi_target *starget);
extern struct iscsi_cls_session *
iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
uint16_t, int, int, uint32_t, unsigned int);
+void iscsi_session_remove(struct iscsi_cls_session *cls_session);
+void iscsi_session_free(struct iscsi_cls_session *cls_session);
extern void iscsi_session_teardown(struct iscsi_cls_session *);
extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
diff --git a/include/uapi/linux/kd.h b/include/uapi/linux/kd.h
index 4616b31f84da..ee929ece4112 100644
--- a/include/uapi/linux/kd.h
+++ b/include/uapi/linux/kd.h
@@ -173,7 +173,7 @@ struct console_font {
#define KD_FONT_OP_SET 0 /* Set font */
#define KD_FONT_OP_GET 1 /* Get font */
#define KD_FONT_OP_SET_DEFAULT 2 /* Set font to default, data points to name / NULL */
-#define KD_FONT_OP_COPY 3 /* Copy from another console */
+#define KD_FONT_OP_COPY 3 /* Obsolete, do not use */
#define KD_FONT_FLAG_DONT_RECALC 1 /* Don't recalculate hw charcell size [compat] */
diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h
index 9762660df741..88877f63e12c 100644
--- a/include/uapi/linux/mptcp.h
+++ b/include/uapi/linux/mptcp.h
@@ -72,6 +72,7 @@ enum {
#define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0)
#define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1)
#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2)
+#define MPTCP_PM_ADDR_FLAGS_MASK GENMASK(2, 0)
enum {
MPTCP_PM_CMD_UNSPEC,
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index 535a7229e1d9..eef23c761ae8 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -74,7 +74,7 @@ struct snd_cea_861_aud_if {
unsigned char db2_sf_ss; /* sample frequency and size */
unsigned char db3; /* not used, all zeros */
unsigned char db4_ca; /* channel allocation code */
- unsigned char db5_dminh_lsv; /* downmix inhibit & level-shit values */
+ unsigned char db5_dminh_lsv; /* downmix inhibit & level-shift values */
};
/****************************************************************************
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 4e86da84f38a..7e228ac3342f 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -4178,13 +4178,13 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
req->open.filename = NULL;
return ret;
}
+ req->flags |= REQ_F_NEED_CLEANUP;
req->open.file_slot = READ_ONCE(sqe->file_index);
if (req->open.file_slot && (req->open.how.flags & O_CLOEXEC))
return -EINVAL;
req->open.nofile = rlimit(RLIMIT_NOFILE);
- req->flags |= REQ_F_NEED_CLEANUP;
return 0;
}
diff --git a/kernel/dma/pool.c b/kernel/dma/pool.c
index 8396a2c5fb9a..32efef166009 100644
--- a/kernel/dma/pool.c
+++ b/kernel/dma/pool.c
@@ -96,7 +96,7 @@ static int atomic_pool_expand(struct gen_pool *pool, size_t pool_size,
page = dma_alloc_from_contiguous(NULL, 1 << order,
order, false);
if (!page)
- page = alloc_pages(gfp, order);
+ page = alloc_pages(gfp | __GFP_NOWARN, order);
} while (!page && order-- > 0);
if (!page)
goto out;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 147ed154ebc7..c49042f5e71e 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -89,8 +89,14 @@ static struct klp_func *klp_find_func(struct klp_object *obj,
struct klp_func *func;
klp_for_each_func(obj, func) {
+ /*
+ * Besides identical old_sympos, also consider old_sympos
+ * of 0 and 1 are identical.
+ */
if ((strcmp(old_func->old_name, func->old_name) == 0) &&
- (old_func->old_sympos == func->old_sympos)) {
+ ((old_func->old_sympos == func->old_sympos) ||
+ (old_func->old_sympos == 0 && func->old_sympos == 1) ||
+ (old_func->old_sympos == 1 && func->old_sympos == 0))) {
return func;
}
}
diff --git a/kernel/locking/spinlock_debug.c b/kernel/locking/spinlock_debug.c
index b9d93087ee66..80b0a9e5a468 100644
--- a/kernel/locking/spinlock_debug.c
+++ b/kernel/locking/spinlock_debug.c
@@ -180,8 +180,8 @@ void do_raw_read_unlock(rwlock_t *lock)
static inline void debug_write_lock_before(rwlock_t *lock)
{
RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
- RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
- RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+ RWLOCK_BUG_ON(READ_ONCE(lock->owner) == current, lock, "recursion");
+ RWLOCK_BUG_ON(READ_ONCE(lock->owner_cpu) == raw_smp_processor_id(),
lock, "cpu recursion");
}
diff --git a/kernel/scs.c b/kernel/scs.c
index 4ff4a7ba0094..3b531c65bdc5 100644
--- a/kernel/scs.c
+++ b/kernel/scs.c
@@ -71,7 +71,7 @@ static void scs_check_usage(struct task_struct *tsk)
if (!IS_ENABLED(CONFIG_DEBUG_STACK_USAGE))
return;
- for (p = task_scs(tsk); p < __scs_magic(tsk); ++p) {
+ for (p = task_scs(tsk); p < __scs_magic(task_scs(tsk)); ++p) {
if (!READ_ONCE_NOCHECK(*p))
break;
used += sizeof(*p);
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 9cd97b274e6c..c9fc3c442681 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -303,6 +303,8 @@ int trace_event_reg(struct trace_event_call *call,
#ifdef CONFIG_PERF_EVENTS
case TRACE_REG_PERF_REGISTER:
+ if (!call->class->perf_probe)
+ return -ENODEV;
return tracepoint_probe_register(call->tp,
call->class->perf_probe,
call);
diff --git a/lib/crypto/aes.c b/lib/crypto/aes.c
index 827fe89922ff..59a1d964497d 100644
--- a/lib/crypto/aes.c
+++ b/lib/crypto/aes.c
@@ -12,7 +12,7 @@
* Emit the sbox as volatile const to prevent the compiler from doing
* constant folding on sbox references involving fixed indexes.
*/
-static volatile const u8 __cacheline_aligned aes_sbox[] = {
+static volatile const u8 ____cacheline_aligned aes_sbox[] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
@@ -47,7 +47,7 @@ static volatile const u8 __cacheline_aligned aes_sbox[] = {
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
-static volatile const u8 __cacheline_aligned aes_inv_sbox[] = {
+static volatile const u8 ____cacheline_aligned aes_inv_sbox[] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
diff --git a/lib/fonts/font_10x18.c b/lib/fonts/font_10x18.c
index e02f9df24d1e..5d940db626e7 100644
--- a/lib/fonts/font_10x18.c
+++ b/lib/fonts/font_10x18.c
@@ -5137,6 +5137,7 @@ const struct font_desc font_10x18 = {
.name = "10x18",
.width = 10,
.height = 18,
+ .charcount = 256,
.data = fontdata_10x18.data,
#ifdef __sparc__
.pref = 5,
diff --git a/lib/fonts/font_6x10.c b/lib/fonts/font_6x10.c
index 6e3c4b7691c8..e65df019e0d2 100644
--- a/lib/fonts/font_6x10.c
+++ b/lib/fonts/font_6x10.c
@@ -3083,6 +3083,7 @@ const struct font_desc font_6x10 = {
.name = "6x10",
.width = 6,
.height = 10,
+ .charcount = 256,
.data = fontdata_6x10.data,
.pref = 0,
};
diff --git a/lib/fonts/font_6x11.c b/lib/fonts/font_6x11.c
index 2d22a24e816f..bd76b3f6b635 100644
--- a/lib/fonts/font_6x11.c
+++ b/lib/fonts/font_6x11.c
@@ -3346,6 +3346,7 @@ const struct font_desc font_vga_6x11 = {
.name = "ProFont6x11",
.width = 6,
.height = 11,
+ .charcount = 256,
.data = fontdata_6x11.data,
/* Try avoiding this font if possible unless on MAC */
.pref = -2000,
diff --git a/lib/fonts/font_6x8.c b/lib/fonts/font_6x8.c
index e7442a0d183d..06ace7792521 100644
--- a/lib/fonts/font_6x8.c
+++ b/lib/fonts/font_6x8.c
@@ -2571,6 +2571,7 @@ const struct font_desc font_6x8 = {
.name = "6x8",
.width = 6,
.height = 8,
+ .charcount = 256,
.data = fontdata_6x8.data,
.pref = 0,
};
diff --git a/lib/fonts/font_7x14.c b/lib/fonts/font_7x14.c
index 9cc7ae2e03f7..a2f561c9fa04 100644
--- a/lib/fonts/font_7x14.c
+++ b/lib/fonts/font_7x14.c
@@ -4113,6 +4113,7 @@ const struct font_desc font_7x14 = {
.name = "7x14",
.width = 7,
.height = 14,
+ .charcount = 256,
.data = fontdata_7x14.data,
.pref = 0,
};
diff --git a/lib/fonts/font_8x16.c b/lib/fonts/font_8x16.c
index bab25dc59e8d..06ae14088514 100644
--- a/lib/fonts/font_8x16.c
+++ b/lib/fonts/font_8x16.c
@@ -4627,6 +4627,7 @@ const struct font_desc font_vga_8x16 = {
.name = "VGA8x16",
.width = 8,
.height = 16,
+ .charcount = 256,
.data = fontdata_8x16.data,
.pref = 0,
};
diff --git a/lib/fonts/font_8x8.c b/lib/fonts/font_8x8.c
index 109d0572368f..69570b8c31af 100644
--- a/lib/fonts/font_8x8.c
+++ b/lib/fonts/font_8x8.c
@@ -2578,6 +2578,7 @@ const struct font_desc font_vga_8x8 = {
.name = "VGA8x8",
.width = 8,
.height = 8,
+ .charcount = 256,
.data = fontdata_8x8.data,
.pref = 0,
};
diff --git a/lib/fonts/font_acorn_8x8.c b/lib/fonts/font_acorn_8x8.c
index fb395f0d4031..18755c33d249 100644
--- a/lib/fonts/font_acorn_8x8.c
+++ b/lib/fonts/font_acorn_8x8.c
@@ -270,6 +270,7 @@ const struct font_desc font_acorn_8x8 = {
.name = "Acorn8x8",
.width = 8,
.height = 8,
+ .charcount = 256,
.data = acorndata_8x8.data,
#ifdef CONFIG_ARCH_ACORN
.pref = 20,
diff --git a/lib/fonts/font_mini_4x6.c b/lib/fonts/font_mini_4x6.c
index 592774a90917..8d39fd447952 100644
--- a/lib/fonts/font_mini_4x6.c
+++ b/lib/fonts/font_mini_4x6.c
@@ -2152,6 +2152,7 @@ const struct font_desc font_mini_4x6 = {
.name = "MINI4x6",
.width = 4,
.height = 6,
+ .charcount = 256,
.data = fontdata_mini_4x6.data,
.pref = 3,
};
diff --git a/lib/fonts/font_pearl_8x8.c b/lib/fonts/font_pearl_8x8.c
index a6f95ebce950..b1678ed0017c 100644
--- a/lib/fonts/font_pearl_8x8.c
+++ b/lib/fonts/font_pearl_8x8.c
@@ -2582,6 +2582,7 @@ const struct font_desc font_pearl_8x8 = {
.name = "PEARL8x8",
.width = 8,
.height = 8,
+ .charcount = 256,
.data = fontdata_pearl8x8.data,
.pref = 2,
};
diff --git a/lib/fonts/font_sun12x22.c b/lib/fonts/font_sun12x22.c
index a5b65bd49604..91daf5ab8b6b 100644
--- a/lib/fonts/font_sun12x22.c
+++ b/lib/fonts/font_sun12x22.c
@@ -6156,6 +6156,7 @@ const struct font_desc font_sun_12x22 = {
.name = "SUN12x22",
.width = 12,
.height = 22,
+ .charcount = 256,
.data = fontdata_sun12x22.data,
#ifdef __sparc__
.pref = 5,
diff --git a/lib/fonts/font_sun8x16.c b/lib/fonts/font_sun8x16.c
index e577e76a6a7c..81bb4eeae04e 100644
--- a/lib/fonts/font_sun8x16.c
+++ b/lib/fonts/font_sun8x16.c
@@ -268,6 +268,7 @@ const struct font_desc font_sun_8x16 = {
.name = "SUN8x16",
.width = 8,
.height = 16,
+ .charcount = 256,
.data = fontdata_sun8x16.data,
#ifdef __sparc__
.pref = 10,
diff --git a/lib/fonts/font_ter16x32.c b/lib/fonts/font_ter16x32.c
index f7c3abb6b99e..1955d624177c 100644
--- a/lib/fonts/font_ter16x32.c
+++ b/lib/fonts/font_ter16x32.c
@@ -2062,6 +2062,7 @@ const struct font_desc font_ter_16x32 = {
.name = "TER16x32",
.width = 16,
.height = 32,
+ .charcount = 256,
.data = fontdata_ter16x32.data,
#ifdef __sparc__
.pref = 5,
diff --git a/lib/idr.c b/lib/idr.c
index da36054c3ca0..aad464c36369 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -40,6 +40,8 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid,
if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR)))
idr->idr_rt.xa_flags |= IDR_RT_MARKER;
+ if (max < base)
+ return -ENOSPC;
id = (id < base) ? 0 : id - base;
radix_tree_iter_init(&iter, id);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 90372391ce90..b643012ae47f 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1829,9 +1829,6 @@ char *rtc_str(char *buf, char *end, const struct rtc_time *tm,
bool raw = false;
int count = 2;
- if (check_pointer(&buf, end, tm, spec))
- return buf;
-
switch (fmt[count]) {
case 'd':
have_t = false;
@@ -1886,6 +1883,9 @@ static noinline_for_stack
char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec,
const char *fmt)
{
+ if (check_pointer(&buf, end, ptr, spec))
+ return buf;
+
switch (fmt[1]) {
case 'R':
return rtc_str(buf, end, (const struct rtc_time *)ptr, spec, fmt);
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 26de020aae7b..c187b708477b 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -93,13 +93,8 @@ size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
if (!trylock_page(page))
continue;
- if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) &&
- PageIsolated(page)) {
- /* raced with isolation */
- unlock_page(page);
- continue;
- }
- balloon_page_delete(page);
+ list_del(&page->lru);
+ balloon_page_finalize(page);
__count_vm_event(BALLOON_DEFLATE);
list_add(&page->lru, pages);
unlock_page(page);
@@ -203,7 +198,7 @@ EXPORT_SYMBOL_GPL(balloon_page_dequeue);
#ifdef CONFIG_BALLOON_COMPACTION
-bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
+static bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
{
struct balloon_dev_info *b_dev_info = balloon_page_device(page);
@@ -217,7 +212,7 @@ bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
return true;
}
-void balloon_page_putback(struct page *page)
+static void balloon_page_putback(struct page *page)
{
struct balloon_dev_info *b_dev_info = balloon_page_device(page);
unsigned long flags;
@@ -230,7 +225,7 @@ void balloon_page_putback(struct page *page)
/* move_to_new_page() counterpart for a ballooned page */
-int balloon_page_migrate(struct address_space *mapping,
+static int balloon_page_migrate(struct address_space *mapping,
struct page *newpage, struct page *page,
enum migrate_mode mode)
{
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 259b43b435a9..19d77a8721fa 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -158,6 +158,7 @@ struct net_bridge_vlan {
* struct net_bridge_vlan_group
*
* @vlan_hash: VLAN entry rhashtable
+ * @tunnel_hash: Hash table to map from tunnel key ID (e.g. VXLAN VNI) to VLAN
* @vlan_list: sorted VLAN entry list
* @num_vlans: number of total VLAN entries
* @pvid: PVID VLAN id
diff --git a/net/bridge/br_vlan_tunnel.c b/net/bridge/br_vlan_tunnel.c
index debe16720278..9e960e2ab3fa 100644
--- a/net/bridge/br_vlan_tunnel.c
+++ b/net/bridge/br_vlan_tunnel.c
@@ -189,7 +189,6 @@ int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
{
struct metadata_dst *tunnel_dst;
__be64 tunnel_id;
- int err;
if (!vlan)
return 0;
@@ -199,9 +198,13 @@ int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
return 0;
skb_dst_drop(skb);
- err = skb_vlan_pop(skb);
- if (err)
- return err;
+ /* For 802.1ad (QinQ), skb_vlan_pop() incorrectly moves the C-VLAN
+ * from payload to hwaccel after clearing S-VLAN. We only need to
+ * clear the hwaccel S-VLAN; the C-VLAN must stay in payload for
+ * correct VXLAN encapsulation. This is also correct for 802.1Q
+ * where no C-VLAN exists in payload.
+ */
+ __vlan_hwaccel_clear_tag(skb);
tunnel_dst = rcu_dereference(vlan->tinfo.tunnel_dst);
if (tunnel_dst && dst_hold_safe(&tunnel_dst->dst))
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c
index 6651a8dc62e0..d4d63586053a 100644
--- a/net/caif/cffrml.c
+++ b/net/caif/cffrml.c
@@ -92,8 +92,15 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
len = le16_to_cpu(tmp);
/* Subtract for FCS on length if FCS is not used. */
- if (!this->dofcs)
+ if (!this->dofcs) {
+ if (len < 2) {
+ ++cffrml_rcv_error;
+ pr_err("Invalid frame length (%d)\n", len);
+ cfpkt_destroy(pkt);
+ return -EPROTO;
+ }
len -= 2;
+ }
if (cfpkt_setlen(pkt, len) < 0) {
++cffrml_rcv_error;
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index c433b49f8715..25e4cdf2df22 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -1555,6 +1555,8 @@ int j1939_session_activate(struct j1939_session *session)
if (active) {
j1939_session_put(active);
ret = -EAGAIN;
+ } else if (priv->ndev->reg_state != NETREG_REGISTERED) {
+ ret = -ENODEV;
} else {
WARN_ON_ONCE(session->state != J1939_SESSION_NEW);
list_add_tail(&session->active_session_list_entry,
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index d594cd501861..89b02b8baca3 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1529,6 +1529,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
struct ceph_pg_pool_info *pi;
struct ceph_pg pgid, last_pgid;
struct ceph_osds up, acting;
+ bool should_be_paused;
bool is_read = t->flags & CEPH_OSD_FLAG_READ;
bool is_write = t->flags & CEPH_OSD_FLAG_WRITE;
bool force_resend = false;
@@ -1597,10 +1598,16 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
&last_pgid))
force_resend = true;
- if (t->paused && !target_should_be_paused(osdc, t, pi)) {
- t->paused = false;
+ should_be_paused = target_should_be_paused(osdc, t, pi);
+ if (t->paused && !should_be_paused) {
unpaused = true;
}
+ if (t->paused != should_be_paused) {
+ dout("%s t %p paused %d -> %d\n", __func__, t, t->paused,
+ should_be_paused);
+ t->paused = should_be_paused;
+ }
+
legacy_change = ceph_pg_compare(&t->pgid, &pgid) ||
ceph_osds_changed(&t->acting, &acting,
t->used_replica || any_change);
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index fa08c15be0c0..f77984b84a20 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -225,22 +225,26 @@ static struct crush_choose_arg_map *alloc_choose_arg_map(void)
static void free_choose_arg_map(struct crush_choose_arg_map *arg_map)
{
- if (arg_map) {
- int i, j;
+ int i, j;
- WARN_ON(!RB_EMPTY_NODE(&arg_map->node));
+ if (!arg_map)
+ return;
+ WARN_ON(!RB_EMPTY_NODE(&arg_map->node));
+
+ if (arg_map->args) {
for (i = 0; i < arg_map->size; i++) {
struct crush_choose_arg *arg = &arg_map->args[i];
-
- for (j = 0; j < arg->weight_set_size; j++)
- kfree(arg->weight_set[j].weights);
- kfree(arg->weight_set);
+ if (arg->weight_set) {
+ for (j = 0; j < arg->weight_set_size; j++)
+ kfree(arg->weight_set[j].weights);
+ kfree(arg->weight_set);
+ }
kfree(arg->ids);
}
kfree(arg_map->args);
- kfree(arg_map);
}
+ kfree(arg_map);
}
DEFINE_RB_FUNCS(choose_arg_map, struct crush_choose_arg_map, choose_args_index,
@@ -790,51 +794,49 @@ static int decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
ceph_decode_need(p, end, len, bad);
pool_end = *p + len;
+ ceph_decode_need(p, end, 4 + 4 + 4, bad);
pi->type = ceph_decode_8(p);
pi->size = ceph_decode_8(p);
pi->crush_ruleset = ceph_decode_8(p);
pi->object_hash = ceph_decode_8(p);
-
pi->pg_num = ceph_decode_32(p);
pi->pgp_num = ceph_decode_32(p);
- *p += 4 + 4; /* skip lpg* */
- *p += 4; /* skip last_change */
- *p += 8 + 4; /* skip snap_seq, snap_epoch */
+ /* lpg*, last_change, snap_seq, snap_epoch */
+ ceph_decode_skip_n(p, end, 8 + 4 + 8 + 4, bad);
/* skip snaps */
- num = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, num, bad);
while (num--) {
- *p += 8; /* snapid key */
- *p += 1 + 1; /* versions */
- len = ceph_decode_32(p);
- *p += len;
+ /* snapid key, pool snap (with versions) */
+ ceph_decode_skip_n(p, end, 8 + 2, bad);
+ ceph_decode_skip_string(p, end, bad);
}
- /* skip removed_snaps */
- num = ceph_decode_32(p);
- *p += num * (8 + 8);
+ /* removed_snaps */
+ ceph_decode_skip_map(p, end, 64, 64, bad);
+ ceph_decode_need(p, end, 8 + 8 + 4, bad);
*p += 8; /* skip auid */
pi->flags = ceph_decode_64(p);
*p += 4; /* skip crash_replay_interval */
if (ev >= 7)
- pi->min_size = ceph_decode_8(p);
+ ceph_decode_8_safe(p, end, pi->min_size, bad);
else
pi->min_size = pi->size - pi->size / 2;
if (ev >= 8)
- *p += 8 + 8; /* skip quota_max_* */
+ /* quota_max_* */
+ ceph_decode_skip_n(p, end, 8 + 8, bad);
if (ev >= 9) {
- /* skip tiers */
- num = ceph_decode_32(p);
- *p += num * 8;
+ /* tiers */
+ ceph_decode_skip_set(p, end, 64, bad);
+ ceph_decode_need(p, end, 8 + 1 + 8 + 8, bad);
*p += 8; /* skip tier_of */
*p += 1; /* skip cache_mode */
-
pi->read_tier = ceph_decode_64(p);
pi->write_tier = ceph_decode_64(p);
} else {
@@ -842,86 +844,76 @@ static int decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi)
pi->write_tier = -1;
}
- if (ev >= 10) {
- /* skip properties */
- num = ceph_decode_32(p);
- while (num--) {
- len = ceph_decode_32(p);
- *p += len; /* key */
- len = ceph_decode_32(p);
- *p += len; /* val */
- }
- }
+ if (ev >= 10)
+ /* properties */
+ ceph_decode_skip_map(p, end, string, string, bad);
if (ev >= 11) {
- /* skip hit_set_params */
- *p += 1 + 1; /* versions */
- len = ceph_decode_32(p);
- *p += len;
+ /* hit_set_params (with versions) */
+ ceph_decode_skip_n(p, end, 2, bad);
+ ceph_decode_skip_string(p, end, bad);
- *p += 4; /* skip hit_set_period */
- *p += 4; /* skip hit_set_count */
+ /* hit_set_period, hit_set_count */
+ ceph_decode_skip_n(p, end, 4 + 4, bad);
}
if (ev >= 12)
- *p += 4; /* skip stripe_width */
+ /* stripe_width */
+ ceph_decode_skip_32(p, end, bad);
- if (ev >= 13) {
- *p += 8; /* skip target_max_bytes */
- *p += 8; /* skip target_max_objects */
- *p += 4; /* skip cache_target_dirty_ratio_micro */
- *p += 4; /* skip cache_target_full_ratio_micro */
- *p += 4; /* skip cache_min_flush_age */
- *p += 4; /* skip cache_min_evict_age */
- }
+ if (ev >= 13)
+ /* target_max_*, cache_target_*, cache_min_* */
+ ceph_decode_skip_n(p, end, 16 + 8 + 8, bad);
- if (ev >= 14) {
- /* skip erasure_code_profile */
- len = ceph_decode_32(p);
- *p += len;
- }
+ if (ev >= 14)
+ /* erasure_code_profile */
+ ceph_decode_skip_string(p, end, bad);
/*
* last_force_op_resend_preluminous, will be overridden if the
* map was encoded with RESEND_ON_SPLIT
*/
if (ev >= 15)
- pi->last_force_request_resend = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, pi->last_force_request_resend, bad);
else
pi->last_force_request_resend = 0;
if (ev >= 16)
- *p += 4; /* skip min_read_recency_for_promote */
+ /* min_read_recency_for_promote */
+ ceph_decode_skip_32(p, end, bad);
if (ev >= 17)
- *p += 8; /* skip expected_num_objects */
+ /* expected_num_objects */
+ ceph_decode_skip_64(p, end, bad);
if (ev >= 19)
- *p += 4; /* skip cache_target_dirty_high_ratio_micro */
+ /* cache_target_dirty_high_ratio_micro */
+ ceph_decode_skip_32(p, end, bad);
if (ev >= 20)
- *p += 4; /* skip min_write_recency_for_promote */
+ /* min_write_recency_for_promote */
+ ceph_decode_skip_32(p, end, bad);
if (ev >= 21)
- *p += 1; /* skip use_gmt_hitset */
+ /* use_gmt_hitset */
+ ceph_decode_skip_8(p, end, bad);
if (ev >= 22)
- *p += 1; /* skip fast_read */
+ /* fast_read */
+ ceph_decode_skip_8(p, end, bad);
- if (ev >= 23) {
- *p += 4; /* skip hit_set_grade_decay_rate */
- *p += 4; /* skip hit_set_search_last_n */
- }
+ if (ev >= 23)
+ /* hit_set_grade_decay_rate, hit_set_search_last_n */
+ ceph_decode_skip_n(p, end, 4 + 4, bad);
if (ev >= 24) {
- /* skip opts */
- *p += 1 + 1; /* versions */
- len = ceph_decode_32(p);
- *p += len;
+ /* opts (with versions) */
+ ceph_decode_skip_n(p, end, 2, bad);
+ ceph_decode_skip_string(p, end, bad);
}
if (ev >= 25)
- pi->last_force_request_resend = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, pi->last_force_request_resend, bad);
/* ignore the rest */
@@ -1952,11 +1944,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
sizeof(u64) + sizeof(u32), e_inval);
ceph_decode_copy(p, &fsid, sizeof(fsid));
epoch = ceph_decode_32(p);
- BUG_ON(epoch != map->epoch+1);
ceph_decode_copy(p, &modified, sizeof(modified));
new_pool_max = ceph_decode_64(p);
new_flags = ceph_decode_32(p);
+ if (epoch != map->epoch + 1)
+ goto e_inval;
+
/* full map? */
ceph_decode_32_safe(p, end, len, e_inval);
if (len > 0) {
diff --git a/net/core/sock.c b/net/core/sock.c
index 6c93381cf0bd..963ea323362a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -3226,7 +3226,7 @@ void sock_enable_timestamp(struct sock *sk, enum sock_flags flag)
int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
int level, int type)
{
- struct sock_exterr_skb *serr;
+ struct sock_extended_err ee;
struct sk_buff *skb;
int copied, err;
@@ -3246,8 +3246,9 @@ int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
sock_recv_timestamp(msg, sk, skb);
- serr = SKB_EXT_ERR(skb);
- put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee);
+ /* We must use a bounce buffer for CONFIG_HARDENED_USERCOPY=y */
+ ee = SKB_EXT_ERR(skb)->ee;
+ put_cmsg(msg, level, type, sizeof(ee), &ee);
msg->msg_flags |= MSG_ERRQUEUE;
err = copied;
diff --git a/net/core/sock_map.c b/net/core/sock_map.c
index 3a9e0046a780..438bbef5ff75 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -1558,15 +1558,16 @@ void sock_map_unhash(struct sock *sk)
psock = sk_psock(sk);
if (unlikely(!psock)) {
rcu_read_unlock();
- if (sk->sk_prot->unhash)
- sk->sk_prot->unhash(sk);
- return;
+ saved_unhash = READ_ONCE(sk->sk_prot)->unhash;
+ } else {
+ saved_unhash = psock->saved_unhash;
+ sock_map_remove_links(sk, psock);
+ rcu_read_unlock();
}
-
- saved_unhash = psock->saved_unhash;
- sock_map_remove_links(sk, psock);
- rcu_read_unlock();
- saved_unhash(sk);
+ if (WARN_ON_ONCE(saved_unhash == sock_map_unhash))
+ return;
+ if (saved_unhash)
+ saved_unhash(sk);
}
void sock_map_destroy(struct sock *sk)
@@ -1578,16 +1579,17 @@ void sock_map_destroy(struct sock *sk)
psock = sk_psock_get(sk);
if (unlikely(!psock)) {
rcu_read_unlock();
- if (sk->sk_prot->destroy)
- sk->sk_prot->destroy(sk);
- return;
+ saved_destroy = READ_ONCE(sk->sk_prot)->destroy;
+ } else {
+ saved_destroy = psock->saved_destroy;
+ sock_map_remove_links(sk, psock);
+ rcu_read_unlock();
+ sk_psock_put(sk, psock);
}
-
- saved_destroy = psock->saved_destroy;
- sock_map_remove_links(sk, psock);
- rcu_read_unlock();
- sk_psock_put(sk, psock);
- saved_destroy(sk);
+ if (WARN_ON_ONCE(saved_destroy == sock_map_destroy))
+ return;
+ if (saved_destroy)
+ saved_destroy(sk);
}
EXPORT_SYMBOL_GPL(sock_map_destroy);
@@ -1602,13 +1604,18 @@ void sock_map_close(struct sock *sk, long timeout)
if (unlikely(!psock)) {
rcu_read_unlock();
release_sock(sk);
- return sk->sk_prot->close(sk, timeout);
+ saved_close = READ_ONCE(sk->sk_prot)->close;
+ } else {
+ saved_close = psock->saved_close;
+ sock_map_remove_links(sk, psock);
+ rcu_read_unlock();
+ release_sock(sk);
}
-
- saved_close = psock->saved_close;
- sock_map_remove_links(sk, psock);
- rcu_read_unlock();
- release_sock(sk);
+ /* Make sure we do not recurse. This is a bug.
+ * Leak the socket instead of crashing on a stack overflow.
+ */
+ if (WARN_ON_ONCE(saved_close == sock_map_close))
+ return;
saved_close(sk, timeout);
}
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 0a588545d352..729dfb21a4a2 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -1909,7 +1909,10 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
return -ENOMEM;
WARN_ON_ONCE(!ret);
- gstrings.len = ret;
+ if (gstrings.len && gstrings.len != ret)
+ gstrings.len = 0;
+ else
+ gstrings.len = ret;
if (gstrings.len) {
data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN));
@@ -2010,10 +2013,13 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
if (copy_from_user(&stats, useraddr, sizeof(stats)))
return -EFAULT;
- stats.n_stats = n_stats;
+ if (stats.n_stats && stats.n_stats != n_stats)
+ stats.n_stats = 0;
+ else
+ stats.n_stats = n_stats;
- if (n_stats) {
- data = vzalloc(array_size(n_stats, sizeof(u64)));
+ if (stats.n_stats) {
+ data = vzalloc(array_size(stats.n_stats, sizeof(u64)));
if (!data)
return -ENOMEM;
ops->get_ethtool_stats(dev, &stats, data);
@@ -2025,7 +2031,9 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
if (copy_to_user(useraddr, &stats, sizeof(stats)))
goto out;
useraddr += sizeof(stats);
- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64))))
+ if (stats.n_stats &&
+ copy_to_user(useraddr, data,
+ array_size(stats.n_stats, sizeof(u64))))
goto out;
ret = 0;
@@ -2034,23 +2042,8 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
return ret;
}
-static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
+static int ethtool_vzalloc_stats_array(int n_stats, u64 **data)
{
- const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops;
- const struct ethtool_ops *ops = dev->ethtool_ops;
- struct phy_device *phydev = dev->phydev;
- struct ethtool_stats stats;
- u64 *data;
- int ret, n_stats;
-
- if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count))
- return -EOPNOTSUPP;
-
- if (dev->phydev && !ops->get_ethtool_phy_stats &&
- phy_ops && phy_ops->get_sset_count)
- n_stats = phy_ops->get_sset_count(dev->phydev);
- else
- n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
if (n_stats < 0)
return n_stats;
if (n_stats > S32_MAX / sizeof(u64))
@@ -2058,35 +2051,92 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
if (WARN_ON_ONCE(!n_stats))
return -EOPNOTSUPP;
+ *data = vzalloc(array_size(n_stats, sizeof(u64)));
+ if (!*data)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int ethtool_get_phy_stats_phydev(struct phy_device *phydev,
+ struct ethtool_stats *stats,
+ u64 **data)
+ {
+ const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops;
+ int n_stats, ret;
+
+ if (!phy_ops || !phy_ops->get_sset_count || !phy_ops->get_stats)
+ return -EOPNOTSUPP;
+
+ n_stats = phy_ops->get_sset_count(phydev);
+ if (stats->n_stats && stats->n_stats != n_stats) {
+ stats->n_stats = 0;
+ return 0;
+ }
+
+ ret = ethtool_vzalloc_stats_array(n_stats, data);
+ if (ret)
+ return ret;
+
+ stats->n_stats = n_stats;
+ return phy_ops->get_stats(phydev, stats, *data);
+}
+
+static int ethtool_get_phy_stats_ethtool(struct net_device *dev,
+ struct ethtool_stats *stats,
+ u64 **data)
+{
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+ int n_stats, ret;
+
+ if (!ops || !ops->get_sset_count || !ops->get_ethtool_phy_stats)
+ return -EOPNOTSUPP;
+
+ n_stats = ops->get_sset_count(dev, ETH_SS_PHY_STATS);
+ if (stats->n_stats && stats->n_stats != n_stats) {
+ stats->n_stats = 0;
+ return 0;
+ }
+
+ ret = ethtool_vzalloc_stats_array(n_stats, data);
+ if (ret)
+ return ret;
+
+ stats->n_stats = n_stats;
+ ops->get_ethtool_phy_stats(dev, stats, *data);
+
+ return 0;
+}
+
+static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
+{
+ struct phy_device *phydev = dev->phydev;
+ struct ethtool_stats stats;
+ u64 *data = NULL;
+ int ret = -EOPNOTSUPP;
+
if (copy_from_user(&stats, useraddr, sizeof(stats)))
return -EFAULT;
- stats.n_stats = n_stats;
+ if (phydev)
+ ret = ethtool_get_phy_stats_phydev(phydev, &stats, &data);
- if (n_stats) {
- data = vzalloc(array_size(n_stats, sizeof(u64)));
- if (!data)
- return -ENOMEM;
+ if (ret == -EOPNOTSUPP)
+ ret = ethtool_get_phy_stats_ethtool(dev, &stats, &data);
- if (dev->phydev && !ops->get_ethtool_phy_stats &&
- phy_ops && phy_ops->get_stats) {
- ret = phy_ops->get_stats(dev->phydev, &stats, data);
- if (ret < 0)
- goto out;
- } else {
- ops->get_ethtool_phy_stats(dev, &stats, data);
- }
- } else {
- data = NULL;
- }
+ if (ret)
+ goto out;
- ret = -EFAULT;
- if (copy_to_user(useraddr, &stats, sizeof(stats)))
+ if (copy_to_user(useraddr, &stats, sizeof(stats))) {
+ ret = -EFAULT;
goto out;
+ }
+
useraddr += sizeof(stats);
- if (n_stats && copy_to_user(useraddr, data, array_size(n_stats, sizeof(u64))))
- goto out;
- ret = 0;
+ if (stats.n_stats &&
+ copy_to_user(useraddr, data,
+ array_size(stats.n_stats, sizeof(u64))))
+ ret = -EFAULT;
out:
vfree(data);
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
index 66df4d7cbfb1..698848e43419 100644
--- a/net/hsr/hsr_forward.c
+++ b/net/hsr/hsr_forward.c
@@ -134,6 +134,8 @@ struct sk_buff *prp_get_untagged_frame(struct hsr_frame_info *frame,
__pskb_copy(frame->skb_prp,
skb_headroom(frame->skb_prp),
GFP_ATOMIC);
+ if (!frame->skb_std)
+ return NULL;
} else {
/* Unexpected */
WARN_ONCE(1, "%s:%d: Unexpected frame received (port_src %s)\n",
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 6879e0b70c76..5f2788b87dfd 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -542,7 +542,7 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
skb_reserve(skb, hlen);
skb_reset_network_header(skb);
- arp = skb_put(skb, arp_hdr_len(dev));
+ skb_put(skb, arp_hdr_len(dev));
skb->dev = dev;
skb->protocol = htons(ETH_P_ARP);
if (!src_hw)
@@ -550,12 +550,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
if (!dest_hw)
dest_hw = dev->broadcast;
- /*
- * Fill the device header for the ARP frame
+ /* Fill the device header for the ARP frame.
+ * Note: skb->head can be changed.
*/
if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0)
goto out;
+ arp = arp_hdr(skb);
/*
* Fill out the arp protocol part.
*
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 6c53381fa36f..671178ed41d0 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2005,10 +2005,11 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
continue;
}
- /* Do not flush error routes if network namespace is
- * not being dismantled
+ /* When not flushing the entire table, skip error
+ * routes that are not marked for deletion.
*/
- if (!flush_all && fib_props[fa->fa_type].error) {
+ if (!flush_all && fib_props[fa->fa_type].error &&
+ !(fi->fib_flags & RTNH_F_DEAD)) {
slen = fa->fa_slen;
continue;
}
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ac2d185c04ef..9b7c84524527 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -578,8 +578,11 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
spin_lock(lock);
if (osk) {
WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
- ret = sk_nulls_del_node_init_rcu(osk);
- } else if (found_dup_sk) {
+ ret = sk_nulls_replace_node_init_rcu(osk, sk);
+ goto unlock;
+ }
+
+ if (found_dup_sk) {
*found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
if (*found_dup_sk)
ret = false;
@@ -588,6 +591,7 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
if (ret)
__sk_nulls_add_node_rcu(sk, list);
+unlock:
spin_unlock(lock);
return ret;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 1e430e135aa6..70c316c0537f 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1572,7 +1572,8 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
* so icmphdr does not in skb linear region and can not get icmp_type
* by icmp_hdr(skb)->type.
*/
- if (sk->sk_type == SOCK_RAW && !inet_sk(sk)->hdrincl)
+ if (sk->sk_type == SOCK_RAW &&
+ !(fl4->flowi4_flags & FLOWI_FLAG_KNOWN_NH))
icmp_type = fl4->fl4_icmp_type;
else
icmp_type = icmp_hdr(skb)->type;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index b42683212c65..1ebfab260708 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -53,6 +53,7 @@ static int ipcomp4_err(struct sk_buff *skb, u32 info)
}
/* We always hold one tunnel user reference to indicate a tunnel */
+static struct lock_class_key xfrm_state_lock_key;
static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
{
struct net *net = xs_net(x);
@@ -61,6 +62,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
t = xfrm_state_alloc(net);
if (!t)
goto out;
+ lockdep_set_class(&t->lock, &xfrm_state_lock_key);
t->id.proto = IPPROTO_IPIP;
t->id.spi = x->props.saddr.a4;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 1bad851b3fc3..69612770006e 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -842,10 +842,8 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
out_free:
if (free)
kfree(ipc.opt);
- if (!err) {
- icmp_out_count(sock_net(sk), user_icmph.type);
+ if (!err)
return len;
- }
return err;
do_confirm:
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 650da4d8f7ad..5a8d5ebe6590 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -634,6 +634,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
(hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
daddr, saddr, 0, 0, sk->sk_uid);
+ fl4.fl4_icmp_type = 0;
+ fl4.fl4_icmp_code = 0;
+
if (!hdrincl) {
rfv.msg = msg;
rfv.hlen = 0;
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index 59997e5d1343..c2e716601ed3 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -1345,7 +1345,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
/* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */
pad = ((new_end & 4) + (end & 7)) & 7;
len_delta = new_end - (int)end + pad;
- ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
+ ret_val = skb_cow(skb,
+ skb_headroom(skb) + (len_delta > 0 ? len_delta : 0));
if (ret_val < 0)
return ret_val;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 13ac0ccdc8d7..1a5b4b176e18 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1382,9 +1382,16 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev,
{
struct ip6_tnl *t = netdev_priv(dev);
struct ipv6hdr *ipv6h;
+ int needed;
__be16 *p;
- ipv6h = skb_push(skb, t->hlen + sizeof(*ipv6h));
+ needed = t->hlen + sizeof(*ipv6h);
+ if (skb_headroom(skb) < needed &&
+ pskb_expand_head(skb, HH_DATA_ALIGN(needed - skb_headroom(skb)),
+ 0, GFP_ATOMIC))
+ return -needed;
+
+ ipv6h = skb_push(skb, needed);
ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb,
t->fl.u.ip6.flowlabel,
true, &t->fl.u.ip6));
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 426330b8dfa4..99ee18b3a953 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1917,7 +1917,8 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
u8 icmp6_type;
- if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl)
+ if (sk->sk_socket->type == SOCK_RAW &&
+ !(fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH))
icmp6_type = fl6->fl6_icmp_type;
else
icmp6_type = icmp6_hdr(skb)->icmp6_type;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index daef890460b7..4bc0d4c0be14 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -71,6 +71,7 @@ static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0;
}
+static struct lock_class_key xfrm_state_lock_key;
static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
{
struct net *net = xs_net(x);
@@ -79,6 +80,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
t = xfrm_state_alloc(net);
if (!t)
goto out;
+ lockdep_set_class(&t->lock, &xfrm_state_lock_key);
t->id.proto = IPPROTO_IPV6;
t->id.spi = xfrm6_tunnel_alloc_spi(net, (xfrm_address_t *)&x->props.saddr);
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index f696d46e6910..6de3cc3ba25d 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -331,8 +331,8 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
unsigned int i;
+ xfrm_state_flush(net, 0, false);
xfrm_flush_gc();
- xfrm_state_flush(net, 0, false, true);
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i]));
diff --git a/net/key/af_key.c b/net/key/af_key.c
index f42854973ba8..de4606d2eb64 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1770,7 +1770,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_m
if (proto == 0)
return -EINVAL;
- err = xfrm_state_flush(net, proto, true, false);
+ err = xfrm_state_flush(net, proto, true);
err2 = unicast_flush_resp(sk, hdr);
if (err || err2) {
if (err == -ESRCH) /* empty table - go quietly */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 98f06563d184..8f497fe234ed 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3189,6 +3189,11 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
if (!ieee80211_is_mgmt(mgmt->frame_control))
return RX_DROP_MONITOR;
+ /* Drop non-broadcast Beacon frames */
+ if (ieee80211_is_beacon(mgmt->frame_control) &&
+ !is_broadcast_ether_addr(mgmt->da))
+ return RX_DROP_MONITOR;
+
if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
ieee80211_is_beacon(mgmt->frame_control) &&
!(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 103074e39da6..b88246b8f21c 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -721,7 +721,8 @@ static int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
entry->addr.id = nla_get_u8(tb[MPTCP_PM_ADDR_ATTR_ID]);
if (tb[MPTCP_PM_ADDR_ATTR_FLAGS])
- entry->addr.flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]);
+ entry->addr.flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]) &
+ MPTCP_PM_ADDR_FLAGS_MASK;
return 0;
}
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index c87dbc897002..f82834349ca2 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -420,6 +420,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
return -1;
err_unreach:
+ if (!skb->dev)
+ skb->dev = skb_dst(skb)->dev;
+
dst_link_failure(skb);
return -1;
}
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index a66a27fe7f45..a2c5a7ba0c6f 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -122,15 +122,68 @@ find_or_evict(struct net *net, struct nf_conncount_list *list,
return ERR_PTR(-EAGAIN);
}
+static bool get_ct_or_tuple_from_skb(struct net *net,
+ const struct sk_buff *skb,
+ u16 l3num,
+ struct nf_conn **ct,
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_zone **zone,
+ bool *refcounted)
+{
+ const struct nf_conntrack_tuple_hash *h;
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *found_ct;
+
+ found_ct = nf_ct_get(skb, &ctinfo);
+ if (found_ct && !nf_ct_is_template(found_ct)) {
+ *tuple = found_ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ *zone = nf_ct_zone(found_ct);
+ *ct = found_ct;
+ return true;
+ }
+
+ if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), l3num, net, tuple))
+ return false;
+
+ if (found_ct)
+ *zone = nf_ct_zone(found_ct);
+
+ h = nf_conntrack_find_get(net, *zone, tuple);
+ if (!h)
+ return true;
+
+ found_ct = nf_ct_tuplehash_to_ctrack(h);
+ *refcounted = true;
+ *ct = found_ct;
+
+ return true;
+}
+
static int __nf_conncount_add(struct net *net,
- struct nf_conncount_list *list,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_zone *zone)
+ const struct sk_buff *skb,
+ u16 l3num,
+ struct nf_conncount_list *list)
{
+ const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
const struct nf_conntrack_tuple_hash *found;
struct nf_conncount_tuple *conn, *conn_n;
+ struct nf_conntrack_tuple tuple;
+ struct nf_conn *ct = NULL;
struct nf_conn *found_ct;
unsigned int collect = 0;
+ bool refcounted = false;
+ int err = 0;
+
+ if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted))
+ return -ENOENT;
+
+ if (ct && nf_ct_is_confirmed(ct)) {
+ err = -EEXIST;
+ goto out_put;
+ }
+
+ if ((u32)jiffies == list->last_gc)
+ goto add_new_node;
/* check the saved connections */
list_for_each_entry_safe(conn, conn_n, &list->head, node) {
@@ -141,10 +194,10 @@ static int __nf_conncount_add(struct net *net,
if (IS_ERR(found)) {
/* Not found, but might be about to be confirmed */
if (PTR_ERR(found) == -EAGAIN) {
- if (nf_ct_tuple_equal(&conn->tuple, tuple) &&
+ if (nf_ct_tuple_equal(&conn->tuple, &tuple) &&
nf_ct_zone_id(&conn->zone, conn->zone.dir) ==
nf_ct_zone_id(zone, zone->dir))
- return 0; /* already exists */
+ goto out_put; /* already exists */
} else {
collect++;
}
@@ -153,7 +206,7 @@ static int __nf_conncount_add(struct net *net,
found_ct = nf_ct_tuplehash_to_ctrack(found);
- if (nf_ct_tuple_equal(&conn->tuple, tuple) &&
+ if (nf_ct_tuple_equal(&conn->tuple, &tuple) &&
nf_ct_zone_equal(found_ct, zone, zone->dir)) {
/*
* We should not see tuples twice unless someone hooks
@@ -162,7 +215,7 @@ static int __nf_conncount_add(struct net *net,
* Attempt to avoid a re-add in this case.
*/
nf_ct_put(found_ct);
- return 0;
+ goto out_put;
} else if (already_closed(found_ct)) {
/*
* we do not care about connections which are
@@ -176,44 +229,55 @@ static int __nf_conncount_add(struct net *net,
nf_ct_put(found_ct);
}
+ list->last_gc = (u32)jiffies;
- if (WARN_ON_ONCE(list->count > INT_MAX))
- return -EOVERFLOW;
+add_new_node:
+ if (WARN_ON_ONCE(list->count > INT_MAX)) {
+ err = -EOVERFLOW;
+ goto out_put;
+ }
conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
- if (conn == NULL)
- return -ENOMEM;
+ if (conn == NULL) {
+ err = -ENOMEM;
+ goto out_put;
+ }
- conn->tuple = *tuple;
+ conn->tuple = tuple;
conn->zone = *zone;
conn->cpu = raw_smp_processor_id();
conn->jiffies32 = (u32)jiffies;
list_add_tail(&conn->node, &list->head);
list->count++;
- return 0;
+
+out_put:
+ if (refcounted)
+ nf_ct_put(ct);
+ return err;
}
-int nf_conncount_add(struct net *net,
- struct nf_conncount_list *list,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_zone *zone)
+int nf_conncount_add_skb(struct net *net,
+ const struct sk_buff *skb,
+ u16 l3num,
+ struct nf_conncount_list *list)
{
int ret;
/* check the saved connections */
spin_lock_bh(&list->list_lock);
- ret = __nf_conncount_add(net, list, tuple, zone);
+ ret = __nf_conncount_add(net, skb, l3num, list);
spin_unlock_bh(&list->list_lock);
return ret;
}
-EXPORT_SYMBOL_GPL(nf_conncount_add);
+EXPORT_SYMBOL_GPL(nf_conncount_add_skb);
void nf_conncount_list_init(struct nf_conncount_list *list)
{
spin_lock_init(&list->list_lock);
INIT_LIST_HEAD(&list->head);
list->count = 0;
+ list->last_gc = (u32)jiffies;
}
EXPORT_SYMBOL_GPL(nf_conncount_list_init);
@@ -227,6 +291,10 @@ bool nf_conncount_gc_list(struct net *net,
unsigned int collected = 0;
bool ret = false;
+ /* don't bother if we just did GC */
+ if ((u32)jiffies == READ_ONCE(list->last_gc))
+ return false;
+
/* don't bother if other cpu is already doing GC */
if (!spin_trylock(&list->list_lock))
return false;
@@ -258,6 +326,7 @@ bool nf_conncount_gc_list(struct net *net,
if (!list->count)
ret = true;
+ list->last_gc = (u32)jiffies;
spin_unlock(&list->list_lock);
return ret;
@@ -298,19 +367,22 @@ static void schedule_gc_worker(struct nf_conncount_data *data, int tree)
static unsigned int
insert_tree(struct net *net,
+ const struct sk_buff *skb,
+ u16 l3num,
struct nf_conncount_data *data,
struct rb_root *root,
unsigned int hash,
- const u32 *key,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_zone *zone)
+ const u32 *key)
{
struct nf_conncount_rb *gc_nodes[CONNCOUNT_GC_MAX_NODES];
+ const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
+ bool do_gc = true, refcounted = false;
+ unsigned int count = 0, gc_count = 0;
struct rb_node **rbnode, *parent;
- struct nf_conncount_rb *rbconn;
+ struct nf_conntrack_tuple tuple;
struct nf_conncount_tuple *conn;
- unsigned int count = 0, gc_count = 0;
- bool do_gc = true;
+ struct nf_conncount_rb *rbconn;
+ struct nf_conn *ct = NULL;
spin_lock_bh(&nf_conncount_locks[hash]);
restart:
@@ -329,8 +401,8 @@ insert_tree(struct net *net,
} else {
int ret;
- ret = nf_conncount_add(net, &rbconn->list, tuple, zone);
- if (ret)
+ ret = nf_conncount_add_skb(net, skb, l3num, &rbconn->list);
+ if (ret && ret != -EEXIST)
count = 0; /* hotdrop */
else
count = rbconn->list.count;
@@ -353,41 +425,45 @@ insert_tree(struct net *net,
goto restart;
}
- /* expected case: match, insert new node */
- rbconn = kmem_cache_alloc(conncount_rb_cachep, GFP_ATOMIC);
- if (rbconn == NULL)
- goto out_unlock;
+ if (get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted)) {
+ /* expected case: match, insert new node */
+ rbconn = kmem_cache_alloc(conncount_rb_cachep, GFP_ATOMIC);
+ if (rbconn == NULL)
+ goto out_unlock;
- conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
- if (conn == NULL) {
- kmem_cache_free(conncount_rb_cachep, rbconn);
- goto out_unlock;
- }
+ conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
+ if (conn == NULL) {
+ kmem_cache_free(conncount_rb_cachep, rbconn);
+ goto out_unlock;
+ }
- conn->tuple = *tuple;
- conn->zone = *zone;
- conn->cpu = raw_smp_processor_id();
- conn->jiffies32 = (u32)jiffies;
- memcpy(rbconn->key, key, sizeof(u32) * data->keylen);
+ conn->tuple = tuple;
+ conn->zone = *zone;
+ conn->cpu = raw_smp_processor_id();
+ conn->jiffies32 = (u32)jiffies;
+ memcpy(rbconn->key, key, sizeof(u32) * data->keylen);
- nf_conncount_list_init(&rbconn->list);
- list_add(&conn->node, &rbconn->list.head);
- count = 1;
- rbconn->list.count = count;
+ nf_conncount_list_init(&rbconn->list);
+ list_add(&conn->node, &rbconn->list.head);
+ count = 1;
+ rbconn->list.count = count;
- rb_link_node_rcu(&rbconn->node, parent, rbnode);
- rb_insert_color(&rbconn->node, root);
+ rb_link_node_rcu(&rbconn->node, parent, rbnode);
+ rb_insert_color(&rbconn->node, root);
+ }
out_unlock:
+ if (refcounted)
+ nf_ct_put(ct);
spin_unlock_bh(&nf_conncount_locks[hash]);
return count;
}
static unsigned int
count_tree(struct net *net,
+ const struct sk_buff *skb,
+ u16 l3num,
struct nf_conncount_data *data,
- const u32 *key,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_zone *zone)
+ const u32 *key)
{
struct rb_root *root;
struct rb_node *parent;
@@ -411,7 +487,7 @@ count_tree(struct net *net,
} else {
int ret;
- if (!tuple) {
+ if (!skb) {
nf_conncount_gc_list(net, &rbconn->list);
return rbconn->list.count;
}
@@ -426,19 +502,23 @@ count_tree(struct net *net,
}
/* same source network -> be counted! */
- ret = __nf_conncount_add(net, &rbconn->list, tuple, zone);
+ ret = __nf_conncount_add(net, skb, l3num, &rbconn->list);
spin_unlock_bh(&rbconn->list.list_lock);
- if (ret)
+ if (ret && ret != -EEXIST) {
return 0; /* hotdrop */
- else
+ } else {
+ /* -EEXIST means add was skipped, update the list */
+ if (ret == -EEXIST)
+ nf_conncount_gc_list(net, &rbconn->list);
return rbconn->list.count;
+ }
}
}
- if (!tuple)
+ if (!skb)
return 0;
- return insert_tree(net, data, root, hash, key, tuple, zone);
+ return insert_tree(net, skb, l3num, data, root, hash, key);
}
static void tree_gc_worker(struct work_struct *work)
@@ -500,18 +580,19 @@ static void tree_gc_worker(struct work_struct *work)
}
/* Count and return number of conntrack entries in 'net' with particular 'key'.
- * If 'tuple' is not null, insert it into the accounting data structure.
- * Call with RCU read lock.
+ * If 'skb' is not null, insert the corresponding tuple into the accounting
+ * data structure. Call with RCU read lock.
*/
-unsigned int nf_conncount_count(struct net *net,
- struct nf_conncount_data *data,
- const u32 *key,
- const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_zone *zone)
+unsigned int nf_conncount_count_skb(struct net *net,
+ const struct sk_buff *skb,
+ u16 l3num,
+ struct nf_conncount_data *data,
+ const u32 *key)
{
- return count_tree(net, data, key, tuple, zone);
+ return count_tree(net, skb, l3num, data, key);
+
}
-EXPORT_SYMBOL_GPL(nf_conncount_count);
+EXPORT_SYMBOL_GPL(nf_conncount_count_skb);
struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
unsigned int keylen)
diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c
index 091457e5c260..9b63792dcc02 100644
--- a/net/netfilter/nft_connlimit.c
+++ b/net/netfilter/nft_connlimit.c
@@ -14,7 +14,7 @@
#include <net/netfilter/nf_conntrack_zones.h>
struct nft_connlimit {
- struct nf_conncount_list list;
+ struct nf_conncount_list *list;
u32 limit;
bool invert;
};
@@ -24,31 +24,25 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,
const struct nft_pktinfo *pkt,
const struct nft_set_ext *ext)
{
- const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
- const struct nf_conntrack_tuple *tuple_ptr;
- struct nf_conntrack_tuple tuple;
- enum ip_conntrack_info ctinfo;
- const struct nf_conn *ct;
unsigned int count;
+ int err;
- tuple_ptr = &tuple;
-
- ct = nf_ct_get(pkt->skb, &ctinfo);
- if (ct != NULL) {
- tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
- zone = nf_ct_zone(ct);
- } else if (!nf_ct_get_tuplepr(pkt->skb, skb_network_offset(pkt->skb),
- nft_pf(pkt), nft_net(pkt), &tuple)) {
- regs->verdict.code = NF_DROP;
- return;
- }
-
- if (nf_conncount_add(nft_net(pkt), &priv->list, tuple_ptr, zone)) {
- regs->verdict.code = NF_DROP;
- return;
+ err = nf_conncount_add_skb(nft_net(pkt), pkt->skb, nft_pf(pkt), priv->list);
+ if (err) {
+ if (err == -EEXIST) {
+ /* Call gc to update the list count if any connection has
+ * been closed already. This is useful for softlimit
+ * connections like limiting bandwidth based on a number
+ * of open connections.
+ */
+ nf_conncount_gc_list(nft_net(pkt), priv->list);
+ } else {
+ regs->verdict.code = NF_DROP;
+ return;
+ }
}
- count = priv->list.count;
+ count = priv->list->count;
if ((count > priv->limit) ^ priv->invert) {
regs->verdict.code = NFT_BREAK;
@@ -62,6 +56,7 @@ static int nft_connlimit_do_init(const struct nft_ctx *ctx,
{
bool invert = false;
u32 flags, limit;
+ int err;
if (!tb[NFTA_CONNLIMIT_COUNT])
return -EINVAL;
@@ -76,18 +71,31 @@ static int nft_connlimit_do_init(const struct nft_ctx *ctx,
invert = true;
}
- nf_conncount_list_init(&priv->list);
+ priv->list = kmalloc(sizeof(*priv->list), GFP_KERNEL);
+ if (!priv->list)
+ return -ENOMEM;
+
+ nf_conncount_list_init(priv->list);
priv->limit = limit;
priv->invert = invert;
- return nf_ct_netns_get(ctx->net, ctx->family);
+ err = nf_ct_netns_get(ctx->net, ctx->family);
+ if (err < 0)
+ goto err_netns;
+
+ return 0;
+err_netns:
+ kfree(priv->list);
+
+ return err;
}
static void nft_connlimit_do_destroy(const struct nft_ctx *ctx,
struct nft_connlimit *priv)
{
nf_ct_netns_put(ctx->net, ctx->family);
- nf_conncount_cache_free(&priv->list);
+ nf_conncount_cache_free(priv->list);
+ kfree(priv->list);
}
static int nft_connlimit_do_dump(struct sk_buff *skb,
@@ -200,7 +208,11 @@ static int nft_connlimit_clone(struct nft_expr *dst, const struct nft_expr *src,
struct nft_connlimit *priv_dst = nft_expr_priv(dst);
struct nft_connlimit *priv_src = nft_expr_priv(src);
- nf_conncount_list_init(&priv_dst->list);
+ priv_dst->list = kmalloc(sizeof(*priv_dst->list), GFP_ATOMIC);
+ if (priv_dst->list)
+ return -ENOMEM;
+
+ nf_conncount_list_init(priv_dst->list);
priv_dst->limit = priv_src->limit;
priv_dst->invert = priv_src->invert;
@@ -212,7 +224,8 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx,
{
struct nft_connlimit *priv = nft_expr_priv(expr);
- nf_conncount_cache_free(&priv->list);
+ nf_conncount_cache_free(priv->list);
+ kfree(priv->list);
}
static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr)
@@ -221,7 +234,7 @@ static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr)
bool ret;
local_bh_disable();
- ret = nf_conncount_gc_list(net, &priv->list);
+ ret = nf_conncount_gc_list(net, priv->list);
local_bh_enable();
return ret;
diff --git a/net/netfilter/nft_synproxy.c b/net/netfilter/nft_synproxy.c
index 0806813d3a76..46d2eefb0b21 100644
--- a/net/netfilter/nft_synproxy.c
+++ b/net/netfilter/nft_synproxy.c
@@ -48,7 +48,7 @@ static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,
struct tcphdr *_tcph,
struct synproxy_options *opts)
{
- struct nf_synproxy_info info = priv->info;
+ struct nf_synproxy_info info = READ_ONCE(priv->info);
struct net *net = nft_net(pkt);
struct synproxy_net *snet = synproxy_pernet(net);
struct sk_buff *skb = pkt->skb;
@@ -79,7 +79,7 @@ static void nft_synproxy_eval_v6(const struct nft_synproxy *priv,
struct tcphdr *_tcph,
struct synproxy_options *opts)
{
- struct nf_synproxy_info info = priv->info;
+ struct nf_synproxy_info info = READ_ONCE(priv->info);
struct net *net = nft_net(pkt);
struct synproxy_net *snet = synproxy_pernet(net);
struct sk_buff *skb = pkt->skb;
@@ -339,7 +339,7 @@ static void nft_synproxy_obj_update(struct nft_object *obj,
struct nft_synproxy *newpriv = nft_obj_data(newobj);
struct nft_synproxy *priv = nft_obj_data(obj);
- priv->info = newpriv->info;
+ WRITE_ONCE(priv->info, newpriv->info);
}
static struct nft_object_type nft_synproxy_obj_type;
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 46fcac75f726..0ee0a1cabed3 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -31,8 +31,6 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
struct net *net = xt_net(par);
const struct xt_connlimit_info *info = par->matchinfo;
- struct nf_conntrack_tuple tuple;
- const struct nf_conntrack_tuple *tuple_ptr = &tuple;
const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
enum ip_conntrack_info ctinfo;
const struct nf_conn *ct;
@@ -40,13 +38,8 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
u32 key[5];
ct = nf_ct_get(skb, &ctinfo);
- if (ct != NULL) {
- tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+ if (ct)
zone = nf_ct_zone(ct);
- } else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
- xt_family(par), net, &tuple)) {
- goto hotdrop;
- }
if (xt_family(par) == NFPROTO_IPV6) {
const struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -69,10 +62,9 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
key[1] = zone->id;
}
- connections = nf_conncount_count(net, info->data, key, tuple_ptr,
- zone);
+ connections = nf_conncount_count_skb(net, skb, xt_family(par), info->data, key);
if (connections == 0)
- /* kmalloc failed, drop it entirely */
+ /* kmalloc failed or tuple couldn't be found, drop it entirely */
goto hotdrop;
return (connections > info->limit) ^ !!(info->flags & XT_CONNLIMIT_INVERT);
diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c
index 5e531394a724..2b3cbceb0b52 100644
--- a/net/netrom/nr_out.c
+++ b/net/netrom/nr_out.c
@@ -43,8 +43,10 @@ void nr_output(struct sock *sk, struct sk_buff *skb)
frontlen = skb_headroom(skb);
while (skb->len > 0) {
- if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL)
+ if ((skbn = sock_alloc_send_skb(sk, frontlen + NR_MAX_PACKET_SIZE, 0, &err)) == NULL) {
+ kfree_skb(skb);
return;
+ }
skb_reserve(skbn, frontlen);
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 10a3d740d155..00cb55e2528d 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -1146,6 +1146,7 @@ EXPORT_SYMBOL(nfc_register_device);
void nfc_unregister_device(struct nfc_dev *dev)
{
int rc;
+ struct rfkill *rfk = NULL;
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
@@ -1156,13 +1157,17 @@ void nfc_unregister_device(struct nfc_dev *dev)
device_lock(&dev->dev);
if (dev->rfkill) {
- rfkill_unregister(dev->rfkill);
- rfkill_destroy(dev->rfkill);
+ rfk = dev->rfkill;
dev->rfkill = NULL;
}
dev->shutting_down = true;
device_unlock(&dev->dev);
+ if (rfk) {
+ rfkill_unregister(rfk);
+ rfkill_destroy(rfk);
+ }
+
if (dev->ops->check_presence) {
del_timer_sync(&dev->check_pres_timer);
cancel_work_sync(&dev->check_pres_work);
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 9e8b3b930f92..2a106d03a201 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -1152,8 +1152,8 @@ static u32 ct_limit_get(const struct ovs_ct_limit_info *info, u16 zone)
}
static int ovs_ct_check_limit(struct net *net,
- const struct ovs_conntrack_info *info,
- const struct nf_conntrack_tuple *tuple)
+ const struct sk_buff *skb,
+ const struct ovs_conntrack_info *info)
{
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
const struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
@@ -1166,8 +1166,9 @@ static int ovs_ct_check_limit(struct net *net,
if (per_zone_limit == OVS_CT_LIMIT_UNLIMITED)
return 0;
- connections = nf_conncount_count(net, ct_limit_info->data,
- &conncount_key, tuple, &info->zone);
+ connections = nf_conncount_count_skb(net, skb, info->family,
+ ct_limit_info->data,
+ &conncount_key);
if (connections > per_zone_limit)
return -ENOMEM;
@@ -1196,8 +1197,7 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
if (static_branch_unlikely(&ovs_ct_limit_enabled)) {
if (!nf_ct_is_confirmed(ct)) {
- err = ovs_ct_check_limit(net, info,
- &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+ err = ovs_ct_check_limit(net, skb, info);
if (err) {
net_warn_ratelimited("openvswitch: zone: %u "
"exceeds conntrack limit\n",
@@ -2046,8 +2046,8 @@ static int __ovs_ct_limit_get_zone_limit(struct net *net,
zone_limit.limit = limit;
nf_ct_zone_init(&ct_zone, zone_id, NF_CT_DEFAULT_ZONE_DIR, 0);
- zone_limit.count = nf_conncount_count(net, data, &conncount_key, NULL,
- &ct_zone);
+ zone_limit.count = nf_conncount_count_skb(net, NULL, 0, data,
+ &conncount_key);
return nla_put_nohdr(reply, sizeof(zone_limit), &zone_limit);
}
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index a70a87a4392a..54f952620b21 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -2760,13 +2760,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
return err;
}
-static bool validate_push_nsh(const struct nlattr *attr, bool log)
+static bool validate_push_nsh(const struct nlattr *a, bool log)
{
+ struct nlattr *nsh_key = nla_data(a);
struct sw_flow_match match;
struct sw_flow_key key;
+ /* There must be one and only one NSH header. */
+ if (!nla_ok(nsh_key, nla_len(a)) ||
+ nla_total_size(nla_len(nsh_key)) != nla_len(a) ||
+ nla_type(nsh_key) != OVS_KEY_ATTR_NSH)
+ return false;
+
ovs_match_init(&match, &key, true, NULL);
- return !nsh_key_put_from_nlattr(attr, &match, false, true, log);
+ return !nsh_key_put_from_nlattr(nsh_key, &match, false, true, log);
}
/* Return false if there are any non-masked bits set.
@@ -3320,7 +3327,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
return -EINVAL;
}
mac_proto = MAC_PROTO_NONE;
- if (!validate_push_nsh(nla_data(a), log))
+ if (!validate_push_nsh(a, log))
return -EINVAL;
break;
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 57d6436e6f6a..72cf13bbf3dd 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -155,10 +155,19 @@ void ovs_netdev_detach_dev(struct vport *vport)
static void netdev_destroy(struct vport *vport)
{
- rtnl_lock();
- if (netif_is_ovs_port(vport->dev))
- ovs_netdev_detach_dev(vport);
- rtnl_unlock();
+ /* When called from ovs_db_notify_wq() after a dp_device_event(), the
+ * port has already been detached, so we can avoid taking the RTNL by
+ * checking this first.
+ */
+ if (netif_is_ovs_port(vport->dev)) {
+ rtnl_lock();
+ /* Check again while holding the lock to ensure we don't race
+ * with the netdev notifier and detach twice.
+ */
+ if (netif_is_ovs_port(vport->dev))
+ ovs_netdev_detach_dev(vport);
+ rtnl_unlock();
+ }
call_rcu(&vport->rcu, vport_netdev_free);
}
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index f8cd085c4234..04173c85d92b 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -204,7 +204,7 @@ static void rose_kill_by_device(struct net_device *dev)
spin_unlock_bh(&rose_list_lock);
for (i = 0; i < cnt; i++) {
- sk = array[cnt];
+ sk = array[i];
rose = rose_sk(sk);
lock_sock(sk);
spin_lock_bh(&rose_list_lock);
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index 6dabe5eaa3be..edf9a6e328d2 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1608,7 +1608,6 @@ static unsigned int cake_drop(struct Qdisc *sch, struct sk_buff **to_free)
__qdisc_drop(skb, to_free);
sch->q.qlen--;
- qdisc_tree_reduce_backlog(sch, 1, len);
cake_heapify(q, 0);
@@ -1754,14 +1753,14 @@ static void cake_reconfigure(struct Qdisc *sch);
static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
+ u32 idx, tin, prev_qlen, prev_backlog, drop_id;
struct cake_sched_data *q = qdisc_priv(sch);
- int len = qdisc_pkt_len(skb);
- int ret;
+ int len = qdisc_pkt_len(skb), ret;
struct sk_buff *ack = NULL;
ktime_t now = ktime_get();
struct cake_tin_data *b;
struct cake_flow *flow;
- u32 idx, tin;
+ bool same_flow = false;
/* choose flow to insert into */
idx = cake_classify(sch, &b, skb, q->flow_mode, &ret);
@@ -1834,6 +1833,8 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
consume_skb(skb);
} else {
/* not splitting */
+ int ack_pkt_len = 0;
+
cobalt_set_enqueue_time(skb, now);
get_cobalt_cb(skb)->adjusted_len = cake_overhead(q, skb);
flow_queue_add(flow, skb);
@@ -1844,13 +1845,13 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (ack) {
b->ack_drops++;
sch->qstats.drops++;
- b->bytes += qdisc_pkt_len(ack);
- len -= qdisc_pkt_len(ack);
+ ack_pkt_len = qdisc_pkt_len(ack);
+ b->bytes += ack_pkt_len;
q->buffer_used += skb->truesize - ack->truesize;
if (q->rate_flags & CAKE_FLAG_INGRESS)
cake_advance_shaper(q, b, ack, now, true);
- qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(ack));
+ qdisc_tree_reduce_backlog(sch, 1, ack_pkt_len);
consume_skb(ack);
} else {
sch->q.qlen++;
@@ -1859,11 +1860,11 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* stats */
b->packets++;
- b->bytes += len;
- b->backlogs[idx] += len;
- b->tin_backlog += len;
- sch->qstats.backlog += len;
- q->avg_window_bytes += len;
+ b->bytes += len - ack_pkt_len;
+ b->backlogs[idx] += len - ack_pkt_len;
+ b->tin_backlog += len - ack_pkt_len;
+ sch->qstats.backlog += len - ack_pkt_len;
+ q->avg_window_bytes += len - ack_pkt_len;
}
if (q->overflow_timeout)
@@ -1938,24 +1939,29 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (q->buffer_used > q->buffer_max_used)
q->buffer_max_used = q->buffer_used;
- if (q->buffer_used > q->buffer_limit) {
- bool same_flow = false;
- u32 dropped = 0;
- u32 drop_id;
+ if (q->buffer_used <= q->buffer_limit)
+ return NET_XMIT_SUCCESS;
- while (q->buffer_used > q->buffer_limit) {
- dropped++;
- drop_id = cake_drop(sch, to_free);
+ prev_qlen = sch->q.qlen;
+ prev_backlog = sch->qstats.backlog;
- if ((drop_id >> 16) == tin &&
- (drop_id & 0xFFFF) == idx)
- same_flow = true;
- }
- b->drop_overlimit += dropped;
+ while (q->buffer_used > q->buffer_limit) {
+ drop_id = cake_drop(sch, to_free);
+ if ((drop_id >> 16) == tin &&
+ (drop_id & 0xFFFF) == idx)
+ same_flow = true;
+ }
+
+ prev_qlen -= sch->q.qlen;
+ prev_backlog -= sch->qstats.backlog;
+ b->drop_overlimit += prev_qlen;
- if (same_flow)
- return NET_XMIT_CN;
+ if (same_flow) {
+ qdisc_tree_reduce_backlog(sch, prev_qlen - 1,
+ prev_backlog - len);
+ return NET_XMIT_CN;
}
+ qdisc_tree_reduce_backlog(sch, prev_qlen, prev_backlog);
return NET_XMIT_SUCCESS;
}
diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c
index e38879e59872..c939937b2b81 100644
--- a/net/sched/sch_ets.c
+++ b/net/sched/sch_ets.c
@@ -665,7 +665,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
sch_tree_lock(sch);
for (i = nbands; i < oldbands; i++) {
- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen)
+ if (cl_is_active(&q->classes[i]))
list_del_init(&q->classes[i].alist);
qdisc_purge_queue(q->classes[i].qdisc);
}
@@ -677,6 +677,10 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
q->classes[i].deficit = quanta[i];
}
}
+ for (i = q->nstrict; i < nstrict; i++) {
+ if (cl_is_active(&q->classes[i]))
+ list_del_init(&q->classes[i].alist);
+ }
WRITE_ONCE(q->nstrict, nstrict);
memcpy(q->prio2band, priomap, sizeof(priomap));
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 3d793ace2b5b..34a6c4ec9a15 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -1490,7 +1490,7 @@ static void qfq_reset_qdisc(struct Qdisc *sch)
for (i = 0; i < q->clhash.hashsize; i++) {
hlist_for_each_entry(cl, &q->clhash.hash[i], common.hnode) {
- if (cl->qdisc->q.qlen > 0)
+ if (cl_is_active(cl))
qfq_deactivate_class(q, cl);
qdisc_reset(cl->qdisc);
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 329eac782cc5..fe85762dbd96 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1177,7 +1177,8 @@ static int gss_read_proxy_verf(struct svc_rqst *rqstp,
}
length = min_t(unsigned int, inlen, argv->iov_len);
- memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
+ if (length)
+ memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
inlen -= length;
to_offs = length;
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index a57f54bc0e1a..7aba6e1fe51d 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -1081,6 +1081,10 @@ static int compat_standard_call(struct net_device *dev,
return ioctl_standard_call(dev, iwr, cmd, info, handler);
iwp_compat = (struct compat_iw_point *) &iwr->u.data;
+
+ /* struct iw_point has a 32bit hole on 64bit arches. */
+ memset(&iwp, 0, sizeof(iwp));
+
iwp.pointer = compat_ptr(iwp_compat->pointer);
iwp.length = iwp_compat->length;
iwp.flags = iwp_compat->flags;
diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c
index 674d426a9d24..37d1147019c2 100644
--- a/net/wireless/wext-priv.c
+++ b/net/wireless/wext-priv.c
@@ -228,6 +228,10 @@ int compat_private_call(struct net_device *dev, struct iwreq *iwr,
struct iw_point iwp;
iwp_compat = (struct compat_iw_point *) &iwr->u.data;
+
+ /* struct iw_point has a 32bit hole on 64bit arches. */
+ memset(&iwp, 0, sizeof(iwp));
+
iwp.pointer = compat_ptr(iwp_compat->pointer);
iwp.length = iwp_compat->length;
iwp.flags = iwp_compat->flags;
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index 24ac6805275e..5453c038e35a 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -327,7 +327,6 @@ void ipcomp_destroy(struct xfrm_state *x)
struct ipcomp_data *ipcd = x->data;
if (!ipcd)
return;
- xfrm_state_delete_tunnel(x);
mutex_lock(&ipcomp_resource_mutex);
ipcomp_free_data(ipcd);
mutex_unlock(&ipcomp_resource_mutex);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index da2d7012e5c7..b1243edf7f3a 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -476,7 +476,8 @@ void xfrm_state_free(struct xfrm_state *x)
}
EXPORT_SYMBOL(xfrm_state_free);
-static void ___xfrm_state_destroy(struct xfrm_state *x)
+static void xfrm_state_delete_tunnel(struct xfrm_state *x);
+static void xfrm_state_gc_destroy(struct xfrm_state *x)
{
hrtimer_cancel(&x->mtimer);
del_timer_sync(&x->rtimer);
@@ -490,6 +491,7 @@ static void ___xfrm_state_destroy(struct xfrm_state *x)
kfree(x->preplay_esn);
if (x->type_offload)
xfrm_put_type_offload(x->type_offload);
+ xfrm_state_delete_tunnel(x);
if (x->type) {
x->type->destructor(x);
xfrm_put_type(x->type);
@@ -514,7 +516,7 @@ static void xfrm_state_gc_task(struct work_struct *work)
synchronize_rcu();
hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
- ___xfrm_state_destroy(x);
+ xfrm_state_gc_destroy(x);
}
static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
@@ -637,19 +639,14 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
}
EXPORT_SYMBOL(xfrm_state_alloc);
-void __xfrm_state_destroy(struct xfrm_state *x, bool sync)
+void __xfrm_state_destroy(struct xfrm_state *x)
{
WARN_ON(x->km.state != XFRM_STATE_DEAD);
- if (sync) {
- synchronize_rcu();
- ___xfrm_state_destroy(x);
- } else {
- spin_lock_bh(&xfrm_state_gc_lock);
- hlist_add_head(&x->gclist, &xfrm_state_gc_list);
- spin_unlock_bh(&xfrm_state_gc_lock);
- schedule_work(&xfrm_state_gc_work);
- }
+ spin_lock_bh(&xfrm_state_gc_lock);
+ hlist_add_head(&x->gclist, &xfrm_state_gc_list);
+ spin_unlock_bh(&xfrm_state_gc_lock);
+ schedule_work(&xfrm_state_gc_work);
}
EXPORT_SYMBOL(__xfrm_state_destroy);
@@ -674,6 +671,8 @@ int __xfrm_state_delete(struct xfrm_state *x)
xfrm_dev_state_delete(x);
+ xfrm_state_delete_tunnel(x);
+
/* All xfrm_state objects are created by xfrm_state_alloc.
* The xfrm_state_alloc call gives a reference, and that
* is what we are dropping here.
@@ -755,7 +754,7 @@ xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool
}
#endif
-int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync)
+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
{
int i, err = 0, cnt = 0;
@@ -777,10 +776,7 @@ int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync)
err = xfrm_state_delete(x);
xfrm_audit_state_delete(x, err ? 0 : 1,
task_valid);
- if (sync)
- xfrm_state_put_sync(x);
- else
- xfrm_state_put(x);
+ xfrm_state_put(x);
if (!err)
cnt++;
@@ -2535,20 +2531,17 @@ void xfrm_flush_gc(void)
}
EXPORT_SYMBOL(xfrm_flush_gc);
-/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
-void xfrm_state_delete_tunnel(struct xfrm_state *x)
+static void xfrm_state_delete_tunnel(struct xfrm_state *x)
{
if (x->tunnel) {
struct xfrm_state *t = x->tunnel;
- if (atomic_read(&t->tunnel_users) == 2)
+ if (atomic_dec_return(&t->tunnel_users) == 1)
xfrm_state_delete(t);
- atomic_dec(&t->tunnel_users);
- xfrm_state_put_sync(t);
+ xfrm_state_put(t);
x->tunnel = NULL;
}
}
-EXPORT_SYMBOL(xfrm_state_delete_tunnel);
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
{
@@ -2710,8 +2703,8 @@ void xfrm_state_fini(struct net *net)
unsigned int sz;
flush_work(&net->xfrm.state_hash_work);
+ xfrm_state_flush(net, 0, false);
flush_work(&xfrm_state_gc_work);
- xfrm_state_flush(net, 0, false, true);
WARN_ON(!list_empty(&net->xfrm.state_all));
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index aa509857b666..480da22b7ef8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2111,7 +2111,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_usersa_flush *p = nlmsg_data(nlh);
int err;
- err = xfrm_state_flush(net, p->proto, true, false);
+ err = xfrm_state_flush(net, p->proto, true);
if (err) {
if (err == -ESRCH) /* empty table */
return 0;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 8d69b2e27936..540c1ec9fe72 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -581,7 +581,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
goto retry;
}
}
- if (!rc) {
+ if (rc <= 0) {
result = false;
goto out;
}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index cb4801fcf9a8..b88bd37a6b3d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3552,8 +3552,8 @@ static int smack_setprocattr(const char *name, void *value, size_t size)
struct task_smack *tsp = smack_cred(current_cred());
struct cred *new;
struct smack_known *skp;
- struct smack_known_list_elem *sklep;
- int rc;
+ char *labelstr;
+ int rc = 0;
if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel))
return -EPERM;
@@ -3564,28 +3564,41 @@ static int smack_setprocattr(const char *name, void *value, size_t size)
if (strcmp(name, "current") != 0)
return -EINVAL;
- skp = smk_import_entry(value, size);
- if (IS_ERR(skp))
- return PTR_ERR(skp);
+ labelstr = smk_parse_smack(value, size);
+ if (IS_ERR(labelstr))
+ return PTR_ERR(labelstr);
/*
* No process is ever allowed the web ("@") label
* and the star ("*") label.
*/
- if (skp == &smack_known_web || skp == &smack_known_star)
- return -EINVAL;
+ if (labelstr[1] == '\0' /* '@', '*' */) {
+ const char c = labelstr[0];
+
+ if (c == *smack_known_web.smk_known ||
+ c == *smack_known_star.smk_known) {
+ rc = -EPERM;
+ goto free_labelstr;
+ }
+ }
if (!smack_privileged(CAP_MAC_ADMIN)) {
- rc = -EPERM;
+ const struct smack_known_list_elem *sklep;
list_for_each_entry(sklep, &tsp->smk_relabel, list)
- if (sklep->smk_label == skp) {
- rc = 0;
- break;
- }
- if (rc)
- return rc;
+ if (strcmp(sklep->smk_label->smk_known, labelstr) == 0)
+ goto free_labelstr;
+ rc = -EPERM;
}
+free_labelstr:
+ kfree(labelstr);
+ if (rc)
+ return -EPERM;
+
+ skp = smk_import_entry(value, size);
+ if (IS_ERR(skp))
+ return PTR_ERR(skp);
+
new = prepare_creds();
if (new == NULL)
return -ENOMEM;
diff --git a/sound/firewire/dice/dice-extension.c b/sound/firewire/dice/dice-extension.c
index 02f4a8318e38..48bfb3ad93ce 100644
--- a/sound/firewire/dice/dice-extension.c
+++ b/sound/firewire/dice/dice-extension.c
@@ -116,7 +116,7 @@ static int detect_stream_formats(struct snd_dice *dice, u64 section_addr)
break;
base_offset += EXT_APP_STREAM_ENTRIES;
- stream_count = be32_to_cpu(reg[0]);
+ stream_count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
err = read_stream_entries(dice, section_addr, base_offset,
stream_count, mode,
dice->tx_pcm_chs,
@@ -125,7 +125,7 @@ static int detect_stream_formats(struct snd_dice *dice, u64 section_addr)
break;
base_offset += stream_count * EXT_APP_STREAM_ENTRY_SIZE;
- stream_count = be32_to_cpu(reg[1]);
+ stream_count = min_t(unsigned int, be32_to_cpu(reg[1]), MAX_STREAMS);
err = read_stream_entries(dice, section_addr, base_offset,
stream_count,
mode, dice->rx_pcm_chs,
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index a337a86f7a65..049ff37382e7 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -291,6 +291,7 @@ static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substrea
return -EIO;
spin_lock_irqsave (&midi->open, flags);
+ midi->substream_input[mpu] = NULL;
midi->mode[mpu] &= ~MPU401_MODE_INPUT;
spin_unlock_irqrestore (&midi->open, flags);
@@ -314,6 +315,7 @@ static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substre
return -EIO;
spin_lock_irqsave (&midi->open, flags);
+ midi->substream_output[mpu] = NULL;
midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
spin_unlock_irqrestore (&midi->open, flags);
return 0;
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 09b368761cc0..23a02ab40b71 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -944,9 +944,9 @@ wavefront_send_sample (snd_wavefront_t *dev,
if (header->size) {
dev->freemem = wavefront_freemem (dev);
- if (dev->freemem < (int)header->size) {
+ if (dev->freemem < 0 || dev->freemem < header->size) {
snd_printk ("insufficient memory to "
- "load %d byte sample.\n",
+ "load %u byte sample.\n",
header->size);
return -ENOMEM;
}
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 27d9da6d61e8..3a354616af19 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -133,7 +133,13 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
link->config_index = 1;
link->config_regs = PRESENT_OPTION;
- return pdacf_config(link);
+ err = pdacf_config(link);
+ if (err < 0) {
+ card_list[i] = NULL;
+ snd_card_free(card);
+ return err;
+ }
+ return 0;
}
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index afd30a90c807..16081c51b938 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -320,7 +320,13 @@ static int vxpocket_probe(struct pcmcia_device *p_dev)
vxp->p_dev = p_dev;
- return vxpocket_config(p_dev);
+ err = vxpocket_config(p_dev);
+ if (err < 0) {
+ card_alloc &= ~(1 << i);
+ snd_card_free(card);
+ return err;
+ }
+ return 0;
}
static void vxpocket_detach(struct pcmcia_device *link)
diff --git a/sound/soc/bcm/bcm63xx-pcm-whistler.c b/sound/soc/bcm/bcm63xx-pcm-whistler.c
index 7ec8559d53a2..9bca508cd844 100644
--- a/sound/soc/bcm/bcm63xx-pcm-whistler.c
+++ b/sound/soc/bcm/bcm63xx-pcm-whistler.c
@@ -390,7 +390,9 @@ static int bcm63xx_soc_pcm_new(struct snd_soc_component *component,
i2s_priv = dev_get_drvdata(asoc_rtd_to_cpu(rtd, 0)->dev);
- of_dma_configure(pcm->card->dev, pcm->card->dev->of_node, 1);
+ ret = of_dma_configure(pcm->card->dev, pcm->card->dev->of_node, 1);
+ if (ret)
+ return ret;
ret = dma_coerce_mask_and_coherent(pcm->card->dev, DMA_BIT_MASK(32));
if (ret)
diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c
index 85a1d00894a9..af4873c97d3a 100644
--- a/sound/soc/codecs/ak4458.c
+++ b/sound/soc/codecs/ak4458.c
@@ -683,7 +683,15 @@ static int __maybe_unused ak4458_runtime_resume(struct device *dev)
regcache_cache_only(ak4458->regmap, false);
regcache_mark_dirty(ak4458->regmap);
- return regcache_sync(ak4458->regmap);
+ ret = regcache_sync(ak4458->regmap);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ regcache_cache_only(ak4458->regmap, true);
+ regulator_bulk_disable(ARRAY_SIZE(ak4458->supplies), ak4458->supplies);
+ return ret;
}
#endif /* CONFIG_PM */
diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c
index adbdfdbc7a38..60ca51845d3e 100644
--- a/sound/soc/codecs/ak5558.c
+++ b/sound/soc/codecs/ak5558.c
@@ -330,7 +330,15 @@ static int __maybe_unused ak5558_runtime_resume(struct device *dev)
regcache_cache_only(ak5558->regmap, false);
regcache_mark_dirty(ak5558->regmap);
- return regcache_sync(ak5558->regmap);
+ ret = regcache_sync(ak5558->regmap);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ regcache_cache_only(ak5558->regmap, true);
+ regulator_bulk_disable(ARRAY_SIZE(ak5558->supplies), ak5558->supplies);
+ return ret;
}
static const struct dev_pm_ops ak5558_pm = {
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 0314d4257b2d..60df490cb764 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -773,6 +773,7 @@ static struct reg_default fsl_sai_reg_defaults_ofs0[] = {
{FSL_SAI_TDR6, 0},
{FSL_SAI_TDR7, 0},
{FSL_SAI_TMR, 0},
+ {FSL_SAI_TTCTL, 0},
{FSL_SAI_RCR1(0), 0},
{FSL_SAI_RCR2(0), 0},
{FSL_SAI_RCR3(0), 0},
@@ -796,12 +797,14 @@ static struct reg_default fsl_sai_reg_defaults_ofs8[] = {
{FSL_SAI_TDR6, 0},
{FSL_SAI_TDR7, 0},
{FSL_SAI_TMR, 0},
+ {FSL_SAI_TTCTL, 0},
{FSL_SAI_RCR1(8), 0},
{FSL_SAI_RCR2(8), 0},
{FSL_SAI_RCR3(8), 0},
{FSL_SAI_RCR4(8), 0},
{FSL_SAI_RCR5(8), 0},
{FSL_SAI_RMR, 0},
+ {FSL_SAI_RTCTL, 0},
{FSL_SAI_MCTL, 0},
{FSL_SAI_MDIV, 0},
};
diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c
index 182d36a34faf..df528f7441c1 100644
--- a/sound/soc/qcom/qdsp6/q6adm.c
+++ b/sound/soc/qcom/qdsp6/q6adm.c
@@ -109,11 +109,75 @@ static struct q6copp *q6adm_find_copp(struct q6adm *adm, int port_idx,
}
+static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp,
+ struct apr_pkt *pkt, uint32_t rsp_opcode)
+{
+ struct device *dev = adm->dev;
+ uint32_t opcode = pkt->hdr.opcode;
+ int ret;
+
+ mutex_lock(&adm->lock);
+ copp->result.opcode = 0;
+ copp->result.status = 0;
+ ret = apr_send_pkt(adm->apr, pkt);
+ if (ret < 0) {
+ dev_err(dev, "Failed to send APR packet\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Wait for the callback with copp id */
+ if (rsp_opcode)
+ ret = wait_event_timeout(copp->wait,
+ (copp->result.opcode == opcode) ||
+ (copp->result.opcode == rsp_opcode),
+ msecs_to_jiffies(TIMEOUT_MS));
+ else
+ ret = wait_event_timeout(copp->wait,
+ (copp->result.opcode == opcode),
+ msecs_to_jiffies(TIMEOUT_MS));
+
+ if (!ret) {
+ dev_err(dev, "ADM copp cmd timedout\n");
+ ret = -ETIMEDOUT;
+ } else if (copp->result.status > 0) {
+ dev_err(dev, "DSP returned error[%d]\n",
+ copp->result.status);
+ ret = -EINVAL;
+ }
+
+err:
+ mutex_unlock(&adm->lock);
+ return ret;
+}
+
+static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp,
+ int port_id, int copp_idx)
+{
+ struct apr_pkt close;
+
+ close.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ close.hdr.pkt_size = sizeof(close);
+ close.hdr.src_port = port_id;
+ close.hdr.dest_port = copp->id;
+ close.hdr.token = port_id << 16 | copp_idx;
+ close.hdr.opcode = ADM_CMD_DEVICE_CLOSE_V5;
+
+ return q6adm_apr_send_copp_pkt(adm, copp, &close, 0);
+}
+
static void q6adm_free_copp(struct kref *ref)
{
struct q6copp *c = container_of(ref, struct q6copp, refcount);
struct q6adm *adm = c->adm;
unsigned long flags;
+ int ret;
+
+ ret = q6adm_device_close(adm, c, c->afe_port, c->copp_idx);
+ if (ret < 0)
+ dev_err(adm->dev, "Failed to close copp %d\n", ret);
spin_lock_irqsave(&adm->copps_list_lock, flags);
clear_bit(c->copp_idx, &adm->copp_bitmap[c->afe_port]);
@@ -155,13 +219,13 @@ static int q6adm_callback(struct apr_device *adev, struct apr_resp_pkt *data)
switch (result->opcode) {
case ADM_CMD_DEVICE_OPEN_V5:
case ADM_CMD_DEVICE_CLOSE_V5:
- copp = q6adm_find_copp(adm, port_idx, copp_idx);
- if (!copp)
- return 0;
-
- copp->result = *result;
- wake_up(&copp->wait);
- kref_put(&copp->refcount, q6adm_free_copp);
+ list_for_each_entry(copp, &adm->copps_list, node) {
+ if ((port_idx == copp->afe_port) && (copp_idx == copp->copp_idx)) {
+ copp->result = *result;
+ wake_up(&copp->wait);
+ break;
+ }
+ }
break;
case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
adm->result = *result;
@@ -234,65 +298,6 @@ static struct q6copp *q6adm_alloc_copp(struct q6adm *adm, int port_idx)
return c;
}
-static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp,
- struct apr_pkt *pkt, uint32_t rsp_opcode)
-{
- struct device *dev = adm->dev;
- uint32_t opcode = pkt->hdr.opcode;
- int ret;
-
- mutex_lock(&adm->lock);
- copp->result.opcode = 0;
- copp->result.status = 0;
- ret = apr_send_pkt(adm->apr, pkt);
- if (ret < 0) {
- dev_err(dev, "Failed to send APR packet\n");
- ret = -EINVAL;
- goto err;
- }
-
- /* Wait for the callback with copp id */
- if (rsp_opcode)
- ret = wait_event_timeout(copp->wait,
- (copp->result.opcode == opcode) ||
- (copp->result.opcode == rsp_opcode),
- msecs_to_jiffies(TIMEOUT_MS));
- else
- ret = wait_event_timeout(copp->wait,
- (copp->result.opcode == opcode),
- msecs_to_jiffies(TIMEOUT_MS));
-
- if (!ret) {
- dev_err(dev, "ADM copp cmd timedout\n");
- ret = -ETIMEDOUT;
- } else if (copp->result.status > 0) {
- dev_err(dev, "DSP returned error[%d]\n",
- copp->result.status);
- ret = -EINVAL;
- }
-
-err:
- mutex_unlock(&adm->lock);
- return ret;
-}
-
-static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp,
- int port_id, int copp_idx)
-{
- struct apr_pkt close;
-
- close.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE),
- APR_PKT_VER);
- close.hdr.pkt_size = sizeof(close);
- close.hdr.src_port = port_id;
- close.hdr.dest_port = copp->id;
- close.hdr.token = port_id << 16 | copp_idx;
- close.hdr.opcode = ADM_CMD_DEVICE_CLOSE_V5;
-
- return q6adm_apr_send_copp_pkt(adm, copp, &close, 0);
-}
-
static struct q6copp *q6adm_find_matching_copp(struct q6adm *adm,
int port_id, int topology,
int mode, int rate,
@@ -567,15 +572,6 @@ EXPORT_SYMBOL_GPL(q6adm_matrix_map);
*/
int q6adm_close(struct device *dev, struct q6copp *copp)
{
- struct q6adm *adm = dev_get_drvdata(dev->parent);
- int ret = 0;
-
- ret = q6adm_device_close(adm, copp, copp->afe_port, copp->copp_idx);
- if (ret < 0) {
- dev_err(adm->dev, "Failed to close copp %d\n", ret);
- return ret;
- }
-
kref_put(&copp->refcount, q6adm_free_copp);
return 0;
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 1bae6f70ea89..e2784daea6b0 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -237,13 +237,14 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
prtd->pcm_irq_pos = 0;
/* rate and channels are sent to audio driver */
- if (prtd->state) {
+ if (prtd->state == Q6ASM_STREAM_RUNNING) {
/* clear the previous setup if any */
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
q6asm_unmap_memory_regions(substream->stream,
prtd->audio_client);
q6routing_stream_close(soc_prtd->dai_link->id,
substream->stream);
+ prtd->state = Q6ASM_STREAM_STOPPED;
}
ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
@@ -412,13 +413,13 @@ static int q6asm_dai_open(struct snd_soc_component *component,
}
ret = snd_pcm_hw_constraint_step(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480);
if (ret < 0) {
dev_err(dev, "constraint for period bytes step ret = %d\n",
ret);
}
ret = snd_pcm_hw_constraint_step(runtime, 0,
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480);
if (ret < 0) {
dev_err(dev, "constraint for buffer bytes step ret = %d\n",
ret);
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 7c4d63c33f15..bc369d064e48 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -830,36 +830,24 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
/* Get clocks */
i2s->pclk = devm_clk_get(&pdev->dev, "pclk");
- if (IS_ERR(i2s->pclk)) {
- if (PTR_ERR(i2s->pclk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Could not get pclk: %ld\n",
- PTR_ERR(i2s->pclk));
- return PTR_ERR(i2s->pclk);
- }
+ if (IS_ERR(i2s->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(i2s->pclk),
+ "Could not get pclk\n");
i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk");
- if (IS_ERR(i2s->i2sclk)) {
- if (PTR_ERR(i2s->i2sclk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Could not get i2sclk: %ld\n",
- PTR_ERR(i2s->i2sclk));
- return PTR_ERR(i2s->i2sclk);
- }
+ if (IS_ERR(i2s->i2sclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk),
+ "Could not get i2sclk\n");
i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k");
- if (IS_ERR(i2s->x8kclk)) {
- if (PTR_ERR(i2s->x8kclk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Could not get x8k parent clock: %ld\n",
- PTR_ERR(i2s->x8kclk));
- return PTR_ERR(i2s->x8kclk);
- }
+ if (IS_ERR(i2s->x8kclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk),
+ "Could not get x8k parent clock\n");
i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k");
- if (IS_ERR(i2s->x11kclk)) {
- if (PTR_ERR(i2s->x11kclk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Could not get x11k parent clock: %ld\n",
- PTR_ERR(i2s->x11kclk));
- return PTR_ERR(i2s->x11kclk);
- }
+ if (IS_ERR(i2s->x11kclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk),
+ "Could not get x11k parent clock\n");
/* Get irqs */
irq = platform_get_irq(pdev, 0);
@@ -875,12 +863,10 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
/* Reset */
rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
- if (IS_ERR(rst)) {
- if (PTR_ERR(rst) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Reset controller error %ld\n",
- PTR_ERR(rst));
- return PTR_ERR(rst);
- }
+ if (IS_ERR(rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rst),
+ "Reset controller error\n");
+
reset_control_assert(rst);
udelay(2);
reset_control_deassert(rst);
@@ -922,19 +908,13 @@ static int stm32_i2s_probe(struct platform_device *pdev)
i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk",
i2s->base, i2s->regmap_conf);
- if (IS_ERR(i2s->regmap)) {
- if (PTR_ERR(i2s->regmap) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Regmap init error %ld\n",
- PTR_ERR(i2s->regmap));
- return PTR_ERR(i2s->regmap);
- }
+ if (IS_ERR(i2s->regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap),
+ "Regmap init error\n");
ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0);
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "PCM DMA register error\n");
ret = snd_soc_register_component(&pdev->dev, &stm32_i2s_component,
i2s->dai_drv, 1);
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index 058757c721f0..df167c389b98 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -127,6 +127,7 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,
}
sai_provider = platform_get_drvdata(pdev);
+ put_device(&pdev->dev);
if (!sai_provider) {
dev_err(&sai_client->pdev->dev,
"SAI sync provider data not found\n");
@@ -143,7 +144,6 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,
ret = stm32_sai_sync_conf_provider(sai_provider, synco);
error:
- put_device(&pdev->dev);
of_node_put(np_provider);
return ret;
}
@@ -173,29 +173,20 @@ static int stm32_sai_probe(struct platform_device *pdev)
if (!STM_SAI_IS_F4(sai)) {
sai->pclk = devm_clk_get(&pdev->dev, "pclk");
- if (IS_ERR(sai->pclk)) {
- if (PTR_ERR(sai->pclk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "missing bus clock pclk: %ld\n",
- PTR_ERR(sai->pclk));
- return PTR_ERR(sai->pclk);
- }
+ if (IS_ERR(sai->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sai->pclk),
+ "missing bus clock pclk\n");
}
sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k");
- if (IS_ERR(sai->clk_x8k)) {
- if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "missing x8k parent clock: %ld\n",
- PTR_ERR(sai->clk_x8k));
- return PTR_ERR(sai->clk_x8k);
- }
+ if (IS_ERR(sai->clk_x8k))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x8k),
+ "missing x8k parent clock\n");
sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k");
- if (IS_ERR(sai->clk_x11k)) {
- if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "missing x11k parent clock: %ld\n",
- PTR_ERR(sai->clk_x11k));
- return PTR_ERR(sai->clk_x11k);
- }
+ if (IS_ERR(sai->clk_x11k))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x11k),
+ "missing x11k parent clock\n");
/* init irqs */
sai->irq = platform_get_irq(pdev, 0);
@@ -204,12 +195,10 @@ static int stm32_sai_probe(struct platform_device *pdev)
/* reset */
rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
- if (IS_ERR(rst)) {
- if (PTR_ERR(rst) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Reset controller error %ld\n",
- PTR_ERR(rst));
- return PTR_ERR(rst);
- }
+ if (IS_ERR(rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rst),
+ "Reset controller error\n");
+
reset_control_assert(rst);
udelay(2);
reset_control_deassert(rst);
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 90e4757f76b0..1810c43d0833 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -1380,12 +1380,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
*/
sai->regmap = devm_regmap_init_mmio(&pdev->dev, base,
sai->regmap_config);
- if (IS_ERR(sai->regmap)) {
- if (PTR_ERR(sai->regmap) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Regmap init error %ld\n",
- PTR_ERR(sai->regmap));
- return PTR_ERR(sai->regmap);
- }
+ if (IS_ERR(sai->regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sai->regmap),
+ "Regmap init error\n");
/* Get direction property */
if (of_property_match_string(np, "dma-names", "tx") >= 0) {
@@ -1473,12 +1470,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
of_node_put(args.np);
sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
- if (IS_ERR(sai->sai_ck)) {
- if (PTR_ERR(sai->sai_ck) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Missing kernel clock sai_ck: %ld\n",
- PTR_ERR(sai->sai_ck));
- return PTR_ERR(sai->sai_ck);
- }
+ if (IS_ERR(sai->sai_ck))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
+ "Missing kernel clock sai_ck\n");
ret = clk_prepare(sai->pdata->pclk);
if (ret < 0)
@@ -1491,17 +1485,21 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
if (of_find_property(np, "#clock-cells", NULL)) {
ret = stm32_sai_add_mclk_provider(sai);
if (ret < 0)
- return ret;
+ goto err_unprepare_pclk;
} else {
- sai->sai_mclk = devm_clk_get(&pdev->dev, "MCLK");
+ sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
if (IS_ERR(sai->sai_mclk)) {
- if (PTR_ERR(sai->sai_mclk) != -ENOENT)
- return PTR_ERR(sai->sai_mclk);
- sai->sai_mclk = NULL;
+ ret = PTR_ERR(sai->sai_mclk);
+ goto err_unprepare_pclk;
}
}
return 0;
+
+err_unprepare_pclk:
+ clk_unprepare(sai->pdata->pclk);
+
+ return ret;
}
static int stm32_sai_sub_probe(struct platform_device *pdev)
@@ -1545,7 +1543,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
IRQF_SHARED, dev_name(&pdev->dev), sai);
if (ret) {
dev_err(&pdev->dev, "IRQ request returned %d\n", ret);
- return ret;
+ goto err_unprepare_pclk;
}
if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
@@ -1553,21 +1551,25 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Could not register pcm dma\n");
- return ret;
+ ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
+ goto err_unprepare_pclk;
}
ret = snd_soc_register_component(&pdev->dev, &stm32_component,
&sai->cpu_dai_drv, 1);
if (ret) {
snd_dmaengine_pcm_unregister(&pdev->dev);
- return ret;
+ goto err_unprepare_pclk;
}
pm_runtime_enable(&pdev->dev);
return 0;
+
+err_unprepare_pclk:
+ clk_unprepare(sai->pdata->pclk);
+
+ return ret;
}
static int stm32_sai_sub_remove(struct platform_device *pdev)
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index ef518cff84f2..2bf834800cc0 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -405,12 +405,9 @@ static int stm32_spdifrx_dma_ctrl_register(struct device *dev,
int ret;
spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl");
- if (IS_ERR(spdifrx->ctrl_chan)) {
- if (PTR_ERR(spdifrx->ctrl_chan) != -EPROBE_DEFER)
- dev_err(dev, "dma_request_slave_channel error %ld\n",
- PTR_ERR(spdifrx->ctrl_chan));
- return PTR_ERR(spdifrx->ctrl_chan);
- }
+ if (IS_ERR(spdifrx->ctrl_chan))
+ return dev_err_probe(dev, PTR_ERR(spdifrx->ctrl_chan),
+ "dma_request_slave_channel error\n");
spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer),
GFP_KERNEL);
@@ -930,12 +927,9 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev,
spdifrx->phys_addr = res->start;
spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk");
- if (IS_ERR(spdifrx->kclk)) {
- if (PTR_ERR(spdifrx->kclk) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Could not get kclk: %ld\n",
- PTR_ERR(spdifrx->kclk));
- return PTR_ERR(spdifrx->kclk);
- }
+ if (IS_ERR(spdifrx->kclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(spdifrx->kclk),
+ "Could not get kclk\n");
spdifrx->irq = platform_get_irq(pdev, 0);
if (spdifrx->irq < 0)
@@ -986,12 +980,9 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
spdifrx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "kclk",
spdifrx->base,
spdifrx->regmap_conf);
- if (IS_ERR(spdifrx->regmap)) {
- if (PTR_ERR(spdifrx->regmap) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Regmap init error %ld\n",
- PTR_ERR(spdifrx->regmap));
- return PTR_ERR(spdifrx->regmap);
- }
+ if (IS_ERR(spdifrx->regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(spdifrx->regmap),
+ "Regmap init error\n");
ret = devm_request_irq(&pdev->dev, spdifrx->irq, stm32_spdifrx_isr, 0,
dev_name(&pdev->dev), spdifrx);
@@ -1001,23 +992,18 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
}
rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
- if (IS_ERR(rst)) {
- if (PTR_ERR(rst) != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Reset controller error %ld\n",
- PTR_ERR(rst));
- return PTR_ERR(rst);
- }
+ if (IS_ERR(rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rst),
+ "Reset controller error\n");
+
reset_control_assert(rst);
udelay(2);
reset_control_deassert(rst);
pcm_config = &stm32_spdifrx_pcm_config;
ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0);
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "PCM DMA register error\n");
ret = snd_soc_register_component(&pdev->dev,
&stm32_spdifrx_component,
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index 3959bbad0c4f..723b11cb0c1b 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -656,17 +656,25 @@ static void get_meter_levels_from_urb(int s,
u8 *meter_urb)
{
int val = MUC2(meter_urb, s) + (MUC3(meter_urb, s) << 8);
+ int ch = MUB2(meter_urb, s) - 1;
+
+ if (ch < 0)
+ return;
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
- if (MUC0(meter_urb, s) == 0x72)
- store->meter_level[MUB2(meter_urb, s) - 1] = val;
- if (MUC0(meter_urb, s) == 0xb2)
- store->comp_level[MUB2(meter_urb, s) - 1] = val;
+ if (ch < SND_US16X08_MAX_CHANNELS) {
+ if (MUC0(meter_urb, s) == 0x72)
+ store->meter_level[ch] = val;
+ if (MUC0(meter_urb, s) == 0xb2)
+ store->comp_level[ch] = val;
+ }
}
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
- MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62)
- store->master_level[MUB2(meter_urb, s) - 1] = val;
+ MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62) {
+ if (ch < ARRAY_SIZE(store->master_level))
+ store->master_level[ch] = val;
+ }
}
/* Function to retrieve current meter values from the device.
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 33954835c823..40e2362096d8 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -893,11 +893,11 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta,
if (dso->kernel == DSO_SPACE__KERNEL_GUEST)
snprintf(dso_name, sizeof(dso_name),
"[guest.kernel].%d",
- kernel_range++);
+ kernel_range);
else
snprintf(dso_name, sizeof(dso_name),
"[kernel].%d",
- kernel_range++);
+ kernel_range);
ndso = dso__new(dso_name);
if (ndso == NULL)
diff --git a/tools/testing/ktest/config-bisect.pl b/tools/testing/ktest/config-bisect.pl
index 6fd864935319..bee7cb34a289 100755
--- a/tools/testing/ktest/config-bisect.pl
+++ b/tools/testing/ktest/config-bisect.pl
@@ -741,9 +741,9 @@ if ($start) {
die "Can not find file $bad\n";
}
if ($val eq "good") {
- run_command "cp $output_config $good" or die "failed to copy $config to $good\n";
+ run_command "cp $output_config $good" or die "failed to copy $output_config to $good\n";
} elsif ($val eq "bad") {
- run_command "cp $output_config $bad" or die "failed to copy $config to $bad\n";
+ run_command "cp $output_config $bad" or die "failed to copy $output_config to $bad\n";
}
}
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 2ac0fff6dad8..bf6e8f572fd6 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -673,6 +673,7 @@ static int nfit_test_search_spa(struct nvdimm_bus *bus,
.addr = spa->spa,
.region = NULL,
};
+ struct nfit_mem *nfit_mem;
u64 dpa;
ret = device_for_each_child(&bus->dev, &ctx,
@@ -690,8 +691,12 @@ static int nfit_test_search_spa(struct nvdimm_bus *bus,
*/
nd_mapping = &nd_region->mapping[nd_region->ndr_mappings - 1];
nvdimm = nd_mapping->nvdimm;
+ nfit_mem = nvdimm_provider_data(nvdimm);
+ if (!nfit_mem)
+ return -EINVAL;
- spa->devices[0].nfit_device_handle = handle[nvdimm->id];
+ spa->devices[0].nfit_device_handle =
+ __to_nfit_memdev(nfit_mem)->device_handle;
spa->num_nvdimms = 1;
spa->devices[0].dpa = dpa;
diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c
index 6ce7460f3c7a..7a0a46e3456d 100644
--- a/tools/testing/radix-tree/idr-test.c
+++ b/tools/testing/radix-tree/idr-test.c
@@ -57,6 +57,26 @@ void idr_alloc_test(void)
idr_destroy(&idr);
}
+void idr_alloc2_test(void)
+{
+ int id;
+ struct idr idr = IDR_INIT_BASE(idr, 1);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 0, 1, GFP_KERNEL);
+ assert(id == -ENOSPC);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 1, 2, GFP_KERNEL);
+ assert(id == 1);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 0, 1, GFP_KERNEL);
+ assert(id == -ENOSPC);
+
+ id = idr_alloc(&idr, idr_alloc2_test, 0, 2, GFP_KERNEL);
+ assert(id == -ENOSPC);
+
+ idr_destroy(&idr);
+}
+
void idr_replace_test(void)
{
DEFINE_IDR(idr);
@@ -400,6 +420,7 @@ void idr_checks(void)
idr_replace_test();
idr_alloc_test();
+ idr_alloc2_test();
idr_null_test();
idr_nowait_test();
idr_get_next_test(0);
diff --git a/tools/testing/selftests/bpf/prog_tests/perf_branches.c b/tools/testing/selftests/bpf/prog_tests/perf_branches.c
index e35c444902a7..464753f6e0f2 100644
--- a/tools/testing/selftests/bpf/prog_tests/perf_branches.c
+++ b/tools/testing/selftests/bpf/prog_tests/perf_branches.c
@@ -15,6 +15,10 @@ static void check_good_sample(struct test_perf_branches *skel)
int pbe_size = sizeof(struct perf_branch_entry);
int duration = 0;
+ if (CHECK(!skel->bss->run_cnt, "invalid run_cnt",
+ "checked sample validity before prog run"))
+ return;
+
if (CHECK(!skel->bss->valid, "output not valid",
"no valid sample from prog"))
return;
@@ -45,6 +49,10 @@ static void check_bad_sample(struct test_perf_branches *skel)
int written_stack = skel->bss->written_stack_out;
int duration = 0;
+ if (CHECK(!skel->bss->run_cnt, "invalid run_cnt",
+ "checked sample validity before prog run"))
+ return;
+
if (CHECK(!skel->bss->valid, "output not valid",
"no valid sample from prog"))
return;
@@ -83,8 +91,12 @@ static void test_perf_branches_common(int perf_fd,
err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);
if (CHECK(err, "set_affinity", "cpu #0, err %d\n", err))
goto out_destroy;
- /* spin the loop for a while (random high number) */
- for (i = 0; i < 1000000; ++i)
+
+ /* Spin the loop for a while by using a high iteration count, and by
+ * checking whether the specific run count marker has been explicitly
+ * incremented at least once by the backing perf_event BPF program.
+ */
+ for (i = 0; i < 100000000 && !*(volatile int *)&skel->bss->run_cnt; ++i)
++j;
test_perf_branches__detach(skel);
diff --git a/tools/testing/selftests/bpf/prog_tests/send_signal.c b/tools/testing/selftests/bpf/prog_tests/send_signal.c
index 0b6349070824..b6e09b383fdb 100644
--- a/tools/testing/selftests/bpf/prog_tests/send_signal.c
+++ b/tools/testing/selftests/bpf/prog_tests/send_signal.c
@@ -144,6 +144,11 @@ static void test_send_signal_common(struct perf_event_attr *attr,
skel_open_load_failure:
close(pipe_c2p[0]);
close(pipe_p2c[1]);
+ /*
+ * Child is either about to exit cleanly or stuck in case of errors.
+ * Nudge it to exit.
+ */
+ kill(pid, SIGKILL);
wait(NULL);
}
diff --git a/tools/testing/selftests/bpf/progs/test_perf_branches.c b/tools/testing/selftests/bpf/progs/test_perf_branches.c
index a1ccc831c882..05ac9410cd68 100644
--- a/tools/testing/selftests/bpf/progs/test_perf_branches.c
+++ b/tools/testing/selftests/bpf/progs/test_perf_branches.c
@@ -8,6 +8,7 @@
#include <bpf/bpf_tracing.h>
int valid = 0;
+int run_cnt = 0;
int required_size_out = 0;
int written_stack_out = 0;
int written_global_out = 0;
@@ -24,6 +25,8 @@ int perf_branches(void *ctx)
__u64 entries[4 * 3] = {0};
int required_size, written_stack, written_global;
+ ++run_cnt;
+
/* write to stack */
written_stack = bpf_read_branch_records(ctx, entries, sizeof(entries), 0);
/* ignore spurious events */
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
index aee22289536b..1b57771dbfdf 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
@@ -90,9 +90,10 @@ if [ $on != "0" ]; then
fail "Tracing is not off"
fi
-csum1=`md5sum trace`
+# Cannot rely on names being around as they are only cached, strip them
+csum1=`cat trace | sed -e 's/^ *[^ ]*\(-[0-9][0-9]*\)/\1/' | md5sum`
sleep $SLEEP_TIME
-csum2=`md5sum trace`
+csum2=`cat trace | sed -e 's/^ *[^ ]*\(-[0-9][0-9]*\)/\1/' | md5sum`
if [ "$csum1" != "$csum2" ]; then
fail "Tracing file is still changing"
Powered by blists - more mailing lists