mirror of
https://github.com/armbian/build.git
synced 2025-08-15 23:56:57 +02:00
12215 lines
417 KiB
Diff
12215 lines
417 KiB
Diff
diff --git a/Documentation/admin-guide/media/building.rst b/Documentation/admin-guide/media/building.rst
|
|
index a0647342991637..7a413ba07f93bb 100644
|
|
--- a/Documentation/admin-guide/media/building.rst
|
|
+++ b/Documentation/admin-guide/media/building.rst
|
|
@@ -15,7 +15,7 @@ Please notice, however, that, if:
|
|
|
|
you should use the main media development tree ``master`` branch:
|
|
|
|
- https://git.linuxtv.org/media_tree.git/
|
|
+ https://git.linuxtv.org/media.git/
|
|
|
|
In this case, you may find some useful information at the
|
|
`LinuxTv wiki pages <https://linuxtv.org/wiki>`_:
|
|
diff --git a/Documentation/admin-guide/media/saa7134.rst b/Documentation/admin-guide/media/saa7134.rst
|
|
index 51eae7eb5ab7f4..18d7cbc897db4b 100644
|
|
--- a/Documentation/admin-guide/media/saa7134.rst
|
|
+++ b/Documentation/admin-guide/media/saa7134.rst
|
|
@@ -67,7 +67,7 @@ Changes / Fixes
|
|
Please mail to linux-media AT vger.kernel.org unified diffs against
|
|
the linux media git tree:
|
|
|
|
- https://git.linuxtv.org/media_tree.git/
|
|
+ https://git.linuxtv.org/media.git/
|
|
|
|
This is done by committing a patch at a clone of the git tree and
|
|
submitting the patch using ``git send-email``. Don't forget to
|
|
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
|
|
index 3cf806733083c7..8209c7a7c3970e 100644
|
|
--- a/Documentation/arch/arm64/silicon-errata.rst
|
|
+++ b/Documentation/arch/arm64/silicon-errata.rst
|
|
@@ -244,8 +244,9 @@ stable kernels.
|
|
+----------------+-----------------+-----------------+-----------------------------+
|
|
| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
|
|
+----------------+-----------------+-----------------+-----------------------------+
|
|
-| Hisilicon | Hip08 SMMU PMCG | #162001900 | N/A |
|
|
-| | Hip09 SMMU PMCG | | |
|
|
+| Hisilicon | Hip{08,09,09A,10| #162001900 | N/A |
|
|
+| | ,10C,11} | | |
|
|
+| | SMMU PMCG | | |
|
|
+----------------+-----------------+-----------------+-----------------------------+
|
|
+----------------+-----------------+-----------------+-----------------------------+
|
|
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
|
|
diff --git a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
|
|
index 987aa83c264943..e956f524e379dc 100644
|
|
--- a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
|
|
+++ b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
|
|
@@ -87,7 +87,7 @@ properties:
|
|
adi,dsi-lanes:
|
|
description: Number of DSI data lanes connected to the DSI host.
|
|
$ref: /schemas/types.yaml#/definitions/uint32
|
|
- enum: [ 1, 2, 3, 4 ]
|
|
+ enum: [ 2, 3, 4 ]
|
|
|
|
ports:
|
|
description:
|
|
diff --git a/Documentation/i2c/busses/i2c-i801.rst b/Documentation/i2c/busses/i2c-i801.rst
|
|
index 10eced6c2e4625..47e8ac5b7099f7 100644
|
|
--- a/Documentation/i2c/busses/i2c-i801.rst
|
|
+++ b/Documentation/i2c/busses/i2c-i801.rst
|
|
@@ -48,6 +48,8 @@ Supported adapters:
|
|
* Intel Raptor Lake (PCH)
|
|
* Intel Meteor Lake (SOC and PCH)
|
|
* Intel Birch Stream (SOC)
|
|
+ * Intel Arrow Lake (SOC)
|
|
+ * Intel Panther Lake (SOC)
|
|
|
|
Datasheets: Publicly available at the Intel website
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index ec4d9d1d9b7ae7..4c0dd62e02e465 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 6
|
|
PATCHLEVEL = 6
|
|
-SUBLEVEL = 69
|
|
+SUBLEVEL = 70
|
|
EXTRAVERSION =
|
|
NAME = Pinguïn Aangedreven
|
|
|
|
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
|
|
index 2390dd042e3636..fb98478ed1ab09 100644
|
|
--- a/arch/arc/Makefile
|
|
+++ b/arch/arc/Makefile
|
|
@@ -6,7 +6,7 @@
|
|
KBUILD_DEFCONFIG := haps_hs_smp_defconfig
|
|
|
|
ifeq ($(CROSS_COMPILE),)
|
|
-CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux-)
|
|
+CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux- arc-linux-gnu-)
|
|
endif
|
|
|
|
cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__
|
|
diff --git a/arch/loongarch/kernel/numa.c b/arch/loongarch/kernel/numa.c
|
|
index 6e65ff12d5c7dc..8fe21f868f72d4 100644
|
|
--- a/arch/loongarch/kernel/numa.c
|
|
+++ b/arch/loongarch/kernel/numa.c
|
|
@@ -226,32 +226,6 @@ static void __init node_mem_init(unsigned int node)
|
|
|
|
#ifdef CONFIG_ACPI_NUMA
|
|
|
|
-/*
|
|
- * Sanity check to catch more bad NUMA configurations (they are amazingly
|
|
- * common). Make sure the nodes cover all memory.
|
|
- */
|
|
-static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
|
|
-{
|
|
- int i;
|
|
- u64 numaram, biosram;
|
|
-
|
|
- numaram = 0;
|
|
- for (i = 0; i < mi->nr_blks; i++) {
|
|
- u64 s = mi->blk[i].start >> PAGE_SHIFT;
|
|
- u64 e = mi->blk[i].end >> PAGE_SHIFT;
|
|
-
|
|
- numaram += e - s;
|
|
- numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
|
|
- if ((s64)numaram < 0)
|
|
- numaram = 0;
|
|
- }
|
|
- max_pfn = max_low_pfn;
|
|
- biosram = max_pfn - absent_pages_in_range(0, max_pfn);
|
|
-
|
|
- BUG_ON((s64)(biosram - numaram) >= (1 << (20 - PAGE_SHIFT)));
|
|
- return true;
|
|
-}
|
|
-
|
|
static void __init add_node_intersection(u32 node, u64 start, u64 size, u32 type)
|
|
{
|
|
static unsigned long num_physpages;
|
|
@@ -396,7 +370,7 @@ int __init init_numa_memory(void)
|
|
return -EINVAL;
|
|
|
|
init_node_memblock();
|
|
- if (numa_meminfo_cover_memory(&numa_meminfo) == false)
|
|
+ if (!memblock_validate_numa_coverage(SZ_1M))
|
|
return -EINVAL;
|
|
|
|
for_each_node_mask(node, node_possible_map) {
|
|
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
|
|
index d43db8150767be..dddf4f31c219ac 100644
|
|
--- a/arch/powerpc/kernel/setup-common.c
|
|
+++ b/arch/powerpc/kernel/setup-common.c
|
|
@@ -601,7 +601,6 @@ struct seq_buf ppc_hw_desc __initdata = {
|
|
.buffer = ppc_hw_desc_buf,
|
|
.size = sizeof(ppc_hw_desc_buf),
|
|
.len = 0,
|
|
- .readpos = 0,
|
|
};
|
|
|
|
static __init void probe_machine(void)
|
|
diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
|
|
index 1245000a8792fd..2fb7d53cf3338d 100644
|
|
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
|
|
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
|
|
@@ -76,7 +76,7 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
|
|
if (!show_unhandled_signals)
|
|
return;
|
|
|
|
- printk_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
|
|
+ printk_ratelimited("%s%s[%d] %s ip:%lx cs:%x sp:%lx ax:%lx si:%lx di:%lx\n",
|
|
level, current->comm, task_pid_nr(current),
|
|
message, regs->ip, regs->cs,
|
|
regs->sp, regs->ax, regs->si, regs->di);
|
|
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
|
|
index f4db78b09c8f0b..5a83fbd9bc0b44 100644
|
|
--- a/arch/x86/include/asm/ptrace.h
|
|
+++ b/arch/x86/include/asm/ptrace.h
|
|
@@ -56,18 +56,64 @@ struct pt_regs {
|
|
|
|
#else /* __i386__ */
|
|
|
|
+struct fred_cs {
|
|
+ /* CS selector */
|
|
+ u64 cs : 16,
|
|
+ /* Stack level at event time */
|
|
+ sl : 2,
|
|
+ /* IBT in WAIT_FOR_ENDBRANCH state */
|
|
+ wfe : 1,
|
|
+ : 45;
|
|
+};
|
|
+
|
|
+struct fred_ss {
|
|
+ /* SS selector */
|
|
+ u64 ss : 16,
|
|
+ /* STI state */
|
|
+ sti : 1,
|
|
+ /* Set if syscall, sysenter or INT n */
|
|
+ swevent : 1,
|
|
+ /* Event is NMI type */
|
|
+ nmi : 1,
|
|
+ : 13,
|
|
+ /* Event vector */
|
|
+ vector : 8,
|
|
+ : 8,
|
|
+ /* Event type */
|
|
+ type : 4,
|
|
+ : 4,
|
|
+ /* Event was incident to enclave execution */
|
|
+ enclave : 1,
|
|
+ /* CPU was in long mode */
|
|
+ lm : 1,
|
|
+ /*
|
|
+ * Nested exception during FRED delivery, not set
|
|
+ * for #DF.
|
|
+ */
|
|
+ nested : 1,
|
|
+ : 1,
|
|
+ /*
|
|
+ * The length of the instruction causing the event.
|
|
+ * Only set for INTO, INT1, INT3, INT n, SYSCALL
|
|
+ * and SYSENTER. 0 otherwise.
|
|
+ */
|
|
+ insnlen : 4;
|
|
+};
|
|
+
|
|
struct pt_regs {
|
|
-/*
|
|
- * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
|
|
- * unless syscall needs a complete, fully filled "struct pt_regs".
|
|
- */
|
|
+ /*
|
|
+ * C ABI says these regs are callee-preserved. They aren't saved on
|
|
+ * kernel entry unless syscall needs a complete, fully filled
|
|
+ * "struct pt_regs".
|
|
+ */
|
|
unsigned long r15;
|
|
unsigned long r14;
|
|
unsigned long r13;
|
|
unsigned long r12;
|
|
unsigned long bp;
|
|
unsigned long bx;
|
|
-/* These regs are callee-clobbered. Always saved on kernel entry. */
|
|
+
|
|
+ /* These regs are callee-clobbered. Always saved on kernel entry. */
|
|
unsigned long r11;
|
|
unsigned long r10;
|
|
unsigned long r9;
|
|
@@ -77,18 +123,50 @@ struct pt_regs {
|
|
unsigned long dx;
|
|
unsigned long si;
|
|
unsigned long di;
|
|
-/*
|
|
- * On syscall entry, this is syscall#. On CPU exception, this is error code.
|
|
- * On hw interrupt, it's IRQ number:
|
|
- */
|
|
+
|
|
+ /*
|
|
+ * orig_ax is used on entry for:
|
|
+ * - the syscall number (syscall, sysenter, int80)
|
|
+ * - error_code stored by the CPU on traps and exceptions
|
|
+ * - the interrupt number for device interrupts
|
|
+ *
|
|
+ * A FRED stack frame starts here:
|
|
+ * 1) It _always_ includes an error code;
|
|
+ *
|
|
+ * 2) The return frame for ERET[US] starts here, but
|
|
+ * the content of orig_ax is ignored.
|
|
+ */
|
|
unsigned long orig_ax;
|
|
-/* Return frame for iretq */
|
|
+
|
|
+ /* The IRETQ return frame starts here */
|
|
unsigned long ip;
|
|
- unsigned long cs;
|
|
+
|
|
+ union {
|
|
+ /* CS selector */
|
|
+ u16 cs;
|
|
+ /* The extended 64-bit data slot containing CS */
|
|
+ u64 csx;
|
|
+ /* The FRED CS extension */
|
|
+ struct fred_cs fred_cs;
|
|
+ };
|
|
+
|
|
unsigned long flags;
|
|
unsigned long sp;
|
|
- unsigned long ss;
|
|
-/* top of stack page */
|
|
+
|
|
+ union {
|
|
+ /* SS selector */
|
|
+ u16 ss;
|
|
+ /* The extended 64-bit data slot containing SS */
|
|
+ u64 ssx;
|
|
+ /* The FRED SS extension */
|
|
+ struct fred_ss fred_ss;
|
|
+ };
|
|
+
|
|
+ /*
|
|
+ * Top of stack on IDT systems, while FRED systems have extra fields
|
|
+ * defined above for storing exception related information, e.g. CR2 or
|
|
+ * DR6.
|
|
+ */
|
|
};
|
|
|
|
#endif /* !__i386__ */
|
|
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
|
|
index 580636cdc257b7..4d3c9d00d6b6b2 100644
|
|
--- a/arch/x86/include/asm/tlb.h
|
|
+++ b/arch/x86/include/asm/tlb.h
|
|
@@ -34,4 +34,8 @@ static inline void __tlb_remove_table(void *table)
|
|
free_page_and_swap_cache(table);
|
|
}
|
|
|
|
+static inline void invlpg(unsigned long addr)
|
|
+{
|
|
+ asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
|
|
+}
|
|
#endif /* _ASM_X86_TLB_H */
|
|
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
|
|
index 3269a0e23d3ab8..15fc9fc3dcf052 100644
|
|
--- a/arch/x86/kernel/Makefile
|
|
+++ b/arch/x86/kernel/Makefile
|
|
@@ -99,9 +99,9 @@ obj-$(CONFIG_TRACING) += trace.o
|
|
obj-$(CONFIG_RETHOOK) += rethook.o
|
|
obj-$(CONFIG_CRASH_CORE) += crash_core_$(BITS).o
|
|
obj-$(CONFIG_KEXEC_CORE) += machine_kexec_$(BITS).o
|
|
-obj-$(CONFIG_KEXEC_CORE) += relocate_kernel_$(BITS).o crash.o
|
|
+obj-$(CONFIG_KEXEC_CORE) += relocate_kernel_$(BITS).o
|
|
obj-$(CONFIG_KEXEC_FILE) += kexec-bzimage64.o
|
|
-obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o
|
|
+obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o crash.o
|
|
obj-y += kprobes/
|
|
obj-$(CONFIG_MODULES) += module.o
|
|
obj-$(CONFIG_X86_32) += doublefault_32.o
|
|
diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c
|
|
index d2c732a34e5d90..303bf74d175b30 100644
|
|
--- a/arch/x86/kernel/cet.c
|
|
+++ b/arch/x86/kernel/cet.c
|
|
@@ -81,6 +81,34 @@ static void do_user_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
|
|
|
static __ro_after_init bool ibt_fatal = true;
|
|
|
|
+/*
|
|
+ * By definition, all missing-ENDBRANCH #CPs are a result of WFE && !ENDBR.
|
|
+ *
|
|
+ * For the kernel IBT no ENDBR selftest where #CPs are deliberately triggered,
|
|
+ * the WFE state of the interrupted context needs to be cleared to let execution
|
|
+ * continue. Otherwise when the CPU resumes from the instruction that just
|
|
+ * caused the previous #CP, another missing-ENDBRANCH #CP is raised and the CPU
|
|
+ * enters a dead loop.
|
|
+ *
|
|
+ * This is not a problem with IDT because it doesn't preserve WFE and IRET doesn't
|
|
+ * set WFE. But FRED provides space on the entry stack (in an expanded CS area)
|
|
+ * to save and restore the WFE state, thus the WFE state is no longer clobbered,
|
|
+ * so software must clear it.
|
|
+ */
|
|
+static void ibt_clear_fred_wfe(struct pt_regs *regs)
|
|
+{
|
|
+ /*
|
|
+ * No need to do any FRED checks.
|
|
+ *
|
|
+ * For IDT event delivery, the high-order 48 bits of CS are pushed
|
|
+ * as 0s into the stack, and later IRET ignores these bits.
|
|
+ *
|
|
+ * For FRED, a test to check if fred_cs.wfe is set would be dropped
|
|
+ * by compilers.
|
|
+ */
|
|
+ regs->fred_cs.wfe = 0;
|
|
+}
|
|
+
|
|
static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
|
{
|
|
if ((error_code & CP_EC) != CP_ENDBR) {
|
|
@@ -90,6 +118,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
|
|
|
if (unlikely(regs->ip == (unsigned long)&ibt_selftest_noendbr)) {
|
|
regs->ax = 0;
|
|
+ ibt_clear_fred_wfe(regs);
|
|
return;
|
|
}
|
|
|
|
@@ -97,6 +126,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
|
if (!ibt_fatal) {
|
|
printk(KERN_DEFAULT CUT_HERE);
|
|
__warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
|
|
+ ibt_clear_fred_wfe(regs);
|
|
return;
|
|
}
|
|
BUG();
|
|
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
|
|
index bcb2d640a0cd85..6328cf56e59be2 100644
|
|
--- a/arch/x86/kernel/cpu/mshyperv.c
|
|
+++ b/arch/x86/kernel/cpu/mshyperv.c
|
|
@@ -209,7 +209,9 @@ static void hv_machine_shutdown(void)
|
|
if (kexec_in_progress)
|
|
hyperv_cleanup();
|
|
}
|
|
+#endif /* CONFIG_KEXEC_CORE */
|
|
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
static void hv_machine_crash_shutdown(struct pt_regs *regs)
|
|
{
|
|
if (hv_crash_handler)
|
|
@@ -221,7 +223,64 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs)
|
|
/* Disable the hypercall page when there is only 1 active CPU. */
|
|
hyperv_cleanup();
|
|
}
|
|
-#endif /* CONFIG_KEXEC_CORE */
|
|
+#endif /* CONFIG_CRASH_DUMP */
|
|
+
|
|
+static u64 hv_ref_counter_at_suspend;
|
|
+static void (*old_save_sched_clock_state)(void);
|
|
+static void (*old_restore_sched_clock_state)(void);
|
|
+
|
|
+/*
|
|
+ * Hyper-V clock counter resets during hibernation. Save and restore clock
|
|
+ * offset during suspend/resume, while also considering the time passed
|
|
+ * before suspend. This is to make sure that sched_clock using hv tsc page
|
|
+ * based clocksource, proceeds from where it left off during suspend and
|
|
+ * it shows correct time for the timestamps of kernel messages after resume.
|
|
+ */
|
|
+static void save_hv_clock_tsc_state(void)
|
|
+{
|
|
+ hv_ref_counter_at_suspend = hv_read_reference_counter();
|
|
+}
|
|
+
|
|
+static void restore_hv_clock_tsc_state(void)
|
|
+{
|
|
+ /*
|
|
+ * Adjust the offsets used by hv tsc clocksource to
|
|
+ * account for the time spent before hibernation.
|
|
+ * adjusted value = reference counter (time) at suspend
|
|
+ * - reference counter (time) now.
|
|
+ */
|
|
+ hv_adj_sched_clock_offset(hv_ref_counter_at_suspend - hv_read_reference_counter());
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Functions to override save_sched_clock_state and restore_sched_clock_state
|
|
+ * functions of x86_platform. The Hyper-V clock counter is reset during
|
|
+ * suspend-resume and the offset used to measure time needs to be
|
|
+ * corrected, post resume.
|
|
+ */
|
|
+static void hv_save_sched_clock_state(void)
|
|
+{
|
|
+ old_save_sched_clock_state();
|
|
+ save_hv_clock_tsc_state();
|
|
+}
|
|
+
|
|
+static void hv_restore_sched_clock_state(void)
|
|
+{
|
|
+ restore_hv_clock_tsc_state();
|
|
+ old_restore_sched_clock_state();
|
|
+}
|
|
+
|
|
+static void __init x86_setup_ops_for_tsc_pg_clock(void)
|
|
+{
|
|
+ if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
|
|
+ return;
|
|
+
|
|
+ old_save_sched_clock_state = x86_platform.save_sched_clock_state;
|
|
+ x86_platform.save_sched_clock_state = hv_save_sched_clock_state;
|
|
+
|
|
+ old_restore_sched_clock_state = x86_platform.restore_sched_clock_state;
|
|
+ x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state;
|
|
+}
|
|
#endif /* CONFIG_HYPERV */
|
|
|
|
static uint32_t __init ms_hyperv_platform(void)
|
|
@@ -493,9 +552,13 @@ static void __init ms_hyperv_init_platform(void)
|
|
no_timer_check = 1;
|
|
#endif
|
|
|
|
-#if IS_ENABLED(CONFIG_HYPERV) && defined(CONFIG_KEXEC_CORE)
|
|
+#if IS_ENABLED(CONFIG_HYPERV)
|
|
+#if defined(CONFIG_KEXEC_CORE)
|
|
machine_ops.shutdown = hv_machine_shutdown;
|
|
+#endif
|
|
+#if defined(CONFIG_CRASH_DUMP)
|
|
machine_ops.crash_shutdown = hv_machine_crash_shutdown;
|
|
+#endif
|
|
#endif
|
|
if (ms_hyperv.features & HV_ACCESS_TSC_INVARIANT) {
|
|
/*
|
|
@@ -572,6 +635,7 @@ static void __init ms_hyperv_init_platform(void)
|
|
|
|
/* Register Hyper-V specific clocksource */
|
|
hv_init_clocksource();
|
|
+ x86_setup_ops_for_tsc_pg_clock();
|
|
hv_vtl_init_platform();
|
|
#endif
|
|
/*
|
|
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
|
|
index a61c12c0127097..0de509c02d18b9 100644
|
|
--- a/arch/x86/kernel/kexec-bzimage64.c
|
|
+++ b/arch/x86/kernel/kexec-bzimage64.c
|
|
@@ -263,11 +263,13 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
|
|
memset(¶ms->hd0_info, 0, sizeof(params->hd0_info));
|
|
memset(¶ms->hd1_info, 0, sizeof(params->hd1_info));
|
|
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
if (image->type == KEXEC_TYPE_CRASH) {
|
|
ret = crash_setup_memmap_entries(image, params);
|
|
if (ret)
|
|
return ret;
|
|
} else
|
|
+#endif
|
|
setup_e820_entries(params);
|
|
|
|
nr_e820_entries = params->e820_entries;
|
|
@@ -428,12 +430,14 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
/* Allocate and load backup region */
|
|
if (image->type == KEXEC_TYPE_CRASH) {
|
|
ret = crash_load_segments(image);
|
|
if (ret)
|
|
return ERR_PTR(ret);
|
|
}
|
|
+#endif
|
|
|
|
/*
|
|
* Load purgatory. For 64bit entry point, purgatory code can be
|
|
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
|
|
index b8ab9ee5896c19..38d88c8b56ec07 100644
|
|
--- a/arch/x86/kernel/kvm.c
|
|
+++ b/arch/x86/kernel/kvm.c
|
|
@@ -769,7 +769,7 @@ static struct notifier_block kvm_pv_reboot_nb = {
|
|
* won't be valid. In cases like kexec, in which you install a new kernel, this
|
|
* means a random memory location will be kept being written.
|
|
*/
|
|
-#ifdef CONFIG_KEXEC_CORE
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
static void kvm_crash_shutdown(struct pt_regs *regs)
|
|
{
|
|
kvm_guest_cpu_offline(true);
|
|
@@ -852,7 +852,7 @@ static void __init kvm_guest_init(void)
|
|
kvm_guest_cpu_init();
|
|
#endif
|
|
|
|
-#ifdef CONFIG_KEXEC_CORE
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
machine_ops.crash_shutdown = kvm_crash_shutdown;
|
|
#endif
|
|
|
|
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
|
|
index 2fa12d1dc67602..aaeac2deb85dc6 100644
|
|
--- a/arch/x86/kernel/machine_kexec_64.c
|
|
+++ b/arch/x86/kernel/machine_kexec_64.c
|
|
@@ -545,6 +545,8 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
|
|
}
|
|
#endif /* CONFIG_KEXEC_FILE */
|
|
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
+
|
|
static int
|
|
kexec_mark_range(unsigned long start, unsigned long end, bool protect)
|
|
{
|
|
@@ -589,6 +591,7 @@ void arch_kexec_unprotect_crashkres(void)
|
|
{
|
|
kexec_mark_crashkres(false);
|
|
}
|
|
+#endif
|
|
|
|
/*
|
|
* During a traditional boot under SME, SME will encrypt the kernel,
|
|
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
|
|
index d595ef7c1de05e..dd19a4db741afd 100644
|
|
--- a/arch/x86/kernel/process_64.c
|
|
+++ b/arch/x86/kernel/process_64.c
|
|
@@ -117,7 +117,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
|
|
|
|
printk("%sFS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n",
|
|
log_lvl, fs, fsindex, gs, gsindex, shadowgs);
|
|
- printk("%sCS: %04lx DS: %04x ES: %04x CR0: %016lx\n",
|
|
+ printk("%sCS: %04x DS: %04x ES: %04x CR0: %016lx\n",
|
|
log_lvl, regs->cs, ds, es, cr0);
|
|
printk("%sCR2: %016lx CR3: %016lx CR4: %016lx\n",
|
|
log_lvl, cr2, cr3, cr4);
|
|
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
|
|
index 830425e6d38e2f..f3130f762784a1 100644
|
|
--- a/arch/x86/kernel/reboot.c
|
|
+++ b/arch/x86/kernel/reboot.c
|
|
@@ -796,7 +796,7 @@ struct machine_ops machine_ops __ro_after_init = {
|
|
.emergency_restart = native_machine_emergency_restart,
|
|
.restart = native_machine_restart,
|
|
.halt = native_machine_halt,
|
|
-#ifdef CONFIG_KEXEC_CORE
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
.crash_shutdown = native_machine_crash_shutdown,
|
|
#endif
|
|
};
|
|
@@ -826,7 +826,7 @@ void machine_halt(void)
|
|
machine_ops.halt();
|
|
}
|
|
|
|
-#ifdef CONFIG_KEXEC_CORE
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
void machine_crash_shutdown(struct pt_regs *regs)
|
|
{
|
|
machine_ops.crash_shutdown(regs);
|
|
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
|
|
index eb129277dcdd64..8bcecabd475bdf 100644
|
|
--- a/arch/x86/kernel/setup.c
|
|
+++ b/arch/x86/kernel/setup.c
|
|
@@ -547,7 +547,7 @@ static void __init reserve_crashkernel(void)
|
|
bool high = false;
|
|
int ret;
|
|
|
|
- if (!IS_ENABLED(CONFIG_KEXEC_CORE))
|
|
+ if (!IS_ENABLED(CONFIG_CRASH_RESERVE))
|
|
return;
|
|
|
|
total_mem = memblock_phys_mem_size();
|
|
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
|
|
index 96a771f9f930a6..52c3823b721191 100644
|
|
--- a/arch/x86/kernel/smp.c
|
|
+++ b/arch/x86/kernel/smp.c
|
|
@@ -282,7 +282,7 @@ struct smp_ops smp_ops = {
|
|
.smp_cpus_done = native_smp_cpus_done,
|
|
|
|
.stop_other_cpus = native_stop_other_cpus,
|
|
-#if defined(CONFIG_KEXEC_CORE)
|
|
+#if defined(CONFIG_CRASH_DUMP)
|
|
.crash_stop_other_cpus = kdump_nmi_shootdown_cpus,
|
|
#endif
|
|
.smp_send_reschedule = native_smp_send_reschedule,
|
|
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
|
|
index c7fa5396c0f05c..2c67bfc3cf3204 100644
|
|
--- a/arch/x86/mm/numa.c
|
|
+++ b/arch/x86/mm/numa.c
|
|
@@ -448,37 +448,6 @@ int __node_distance(int from, int to)
|
|
}
|
|
EXPORT_SYMBOL(__node_distance);
|
|
|
|
-/*
|
|
- * Sanity check to catch more bad NUMA configurations (they are amazingly
|
|
- * common). Make sure the nodes cover all memory.
|
|
- */
|
|
-static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
|
|
-{
|
|
- u64 numaram, e820ram;
|
|
- int i;
|
|
-
|
|
- numaram = 0;
|
|
- for (i = 0; i < mi->nr_blks; i++) {
|
|
- u64 s = mi->blk[i].start >> PAGE_SHIFT;
|
|
- u64 e = mi->blk[i].end >> PAGE_SHIFT;
|
|
- numaram += e - s;
|
|
- numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
|
|
- if ((s64)numaram < 0)
|
|
- numaram = 0;
|
|
- }
|
|
-
|
|
- e820ram = max_pfn - absent_pages_in_range(0, max_pfn);
|
|
-
|
|
- /* We seem to lose 3 pages somewhere. Allow 1M of slack. */
|
|
- if ((s64)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
|
|
- printk(KERN_ERR "NUMA: nodes only cover %LuMB of your %LuMB e820 RAM. Not used.\n",
|
|
- (numaram << PAGE_SHIFT) >> 20,
|
|
- (e820ram << PAGE_SHIFT) >> 20);
|
|
- return false;
|
|
- }
|
|
- return true;
|
|
-}
|
|
-
|
|
/*
|
|
* Mark all currently memblock-reserved physical memory (which covers the
|
|
* kernel's own memory ranges) as hot-unswappable.
|
|
@@ -584,7 +553,8 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
- if (!numa_meminfo_cover_memory(mi))
|
|
+
|
|
+ if (!memblock_validate_numa_coverage(SZ_1M))
|
|
return -EINVAL;
|
|
|
|
/* Finally register nodes. */
|
|
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
|
|
index 2fbae48f0b470a..64f594826a2822 100644
|
|
--- a/arch/x86/mm/tlb.c
|
|
+++ b/arch/x86/mm/tlb.c
|
|
@@ -19,6 +19,7 @@
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/apic.h>
|
|
#include <asm/perf_event.h>
|
|
+#include <asm/tlb.h>
|
|
|
|
#include "mm_internal.h"
|
|
|
|
@@ -1145,7 +1146,7 @@ STATIC_NOPV void native_flush_tlb_one_user(unsigned long addr)
|
|
bool cpu_pcide;
|
|
|
|
/* Flush 'addr' from the kernel PCID: */
|
|
- asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
|
|
+ invlpg(addr);
|
|
|
|
/* If PTI is off there is no user PCID and nothing to flush. */
|
|
if (!static_cpu_has(X86_FEATURE_PTI))
|
|
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
|
|
index 70be57e8f51caa..ade22feee7aeb1 100644
|
|
--- a/arch/x86/xen/enlighten_hvm.c
|
|
+++ b/arch/x86/xen/enlighten_hvm.c
|
|
@@ -141,7 +141,9 @@ static void xen_hvm_shutdown(void)
|
|
if (kexec_in_progress)
|
|
xen_reboot(SHUTDOWN_soft_reset);
|
|
}
|
|
+#endif
|
|
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
static void xen_hvm_crash_shutdown(struct pt_regs *regs)
|
|
{
|
|
native_machine_crash_shutdown(regs);
|
|
@@ -229,6 +231,8 @@ static void __init xen_hvm_guest_init(void)
|
|
|
|
#ifdef CONFIG_KEXEC_CORE
|
|
machine_ops.shutdown = xen_hvm_shutdown;
|
|
+#endif
|
|
+#ifdef CONFIG_CRASH_DUMP
|
|
machine_ops.crash_shutdown = xen_hvm_crash_shutdown;
|
|
#endif
|
|
}
|
|
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
|
|
index 6b201e64d8abc8..bfd57d07f4b5ee 100644
|
|
--- a/arch/x86/xen/mmu_pv.c
|
|
+++ b/arch/x86/xen/mmu_pv.c
|
|
@@ -2517,7 +2517,7 @@ int xen_remap_pfn(struct vm_area_struct *vma, unsigned long addr,
|
|
}
|
|
EXPORT_SYMBOL_GPL(xen_remap_pfn);
|
|
|
|
-#ifdef CONFIG_KEXEC_CORE
|
|
+#ifdef CONFIG_VMCORE_INFO
|
|
phys_addr_t paddr_vmcoreinfo_note(void)
|
|
{
|
|
if (xen_pv_domain())
|
|
diff --git a/crypto/ecc.c b/crypto/ecc.c
|
|
index f53fb4d6af992b..21504280aca2e5 100644
|
|
--- a/crypto/ecc.c
|
|
+++ b/crypto/ecc.c
|
|
@@ -66,6 +66,28 @@ const struct ecc_curve *ecc_get_curve(unsigned int curve_id)
|
|
}
|
|
EXPORT_SYMBOL(ecc_get_curve);
|
|
|
|
+void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
|
|
+ u64 *out, unsigned int ndigits)
|
|
+{
|
|
+ int diff = ndigits - DIV_ROUND_UP(nbytes, sizeof(u64));
|
|
+ unsigned int o = nbytes & 7;
|
|
+ __be64 msd = 0;
|
|
+
|
|
+ /* diff > 0: not enough input bytes: set most significant digits to 0 */
|
|
+ if (diff > 0) {
|
|
+ ndigits -= diff;
|
|
+ memset(&out[ndigits - 1], 0, diff * sizeof(u64));
|
|
+ }
|
|
+
|
|
+ if (o) {
|
|
+ memcpy((u8 *)&msd + sizeof(msd) - o, in, o);
|
|
+ out[--ndigits] = be64_to_cpu(msd);
|
|
+ in += o;
|
|
+ }
|
|
+ ecc_swap_digits(in, out, ndigits);
|
|
+}
|
|
+EXPORT_SYMBOL(ecc_digits_from_bytes);
|
|
+
|
|
static u64 *ecc_alloc_digits_space(unsigned int ndigits)
|
|
{
|
|
size_t len = ndigits * sizeof(u64);
|
|
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
|
|
index 3f9ec273a121fd..da04df3c8ecf4d 100644
|
|
--- a/crypto/ecdsa.c
|
|
+++ b/crypto/ecdsa.c
|
|
@@ -35,40 +35,27 @@ struct ecdsa_signature_ctx {
|
|
static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag,
|
|
const void *value, size_t vlen, unsigned int ndigits)
|
|
{
|
|
- size_t keylen = ndigits * sizeof(u64);
|
|
- ssize_t diff = vlen - keylen;
|
|
+ size_t bufsize = ndigits * sizeof(u64);
|
|
const char *d = value;
|
|
- u8 rs[ECC_MAX_BYTES];
|
|
|
|
- if (!value || !vlen)
|
|
+ if (!value || !vlen || vlen > bufsize + 1)
|
|
return -EINVAL;
|
|
|
|
- /* diff = 0: 'value' has exacly the right size
|
|
- * diff > 0: 'value' has too many bytes; one leading zero is allowed that
|
|
- * makes the value a positive integer; error on more
|
|
- * diff < 0: 'value' is missing leading zeros, which we add
|
|
+ /*
|
|
+ * vlen may be 1 byte larger than bufsize due to a leading zero byte
|
|
+ * (necessary if the most significant bit of the integer is set).
|
|
*/
|
|
- if (diff > 0) {
|
|
+ if (vlen > bufsize) {
|
|
/* skip over leading zeros that make 'value' a positive int */
|
|
if (*d == 0) {
|
|
vlen -= 1;
|
|
- diff--;
|
|
d++;
|
|
- }
|
|
- if (diff)
|
|
+ } else {
|
|
return -EINVAL;
|
|
+ }
|
|
}
|
|
- if (-diff >= keylen)
|
|
- return -EINVAL;
|
|
-
|
|
- if (diff) {
|
|
- /* leading zeros not given in 'value' */
|
|
- memset(rs, 0, -diff);
|
|
- }
|
|
-
|
|
- memcpy(&rs[-diff], d, vlen);
|
|
|
|
- ecc_swap_digits((u64 *)rs, dest, ndigits);
|
|
+ ecc_digits_from_bytes(d, vlen, dest, ndigits);
|
|
|
|
return 0;
|
|
}
|
|
@@ -138,7 +125,7 @@ static int ecdsa_verify(struct akcipher_request *req)
|
|
{
|
|
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
|
|
struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
|
|
- size_t keylen = ctx->curve->g.ndigits * sizeof(u64);
|
|
+ size_t bufsize = ctx->curve->g.ndigits * sizeof(u64);
|
|
struct ecdsa_signature_ctx sig_ctx = {
|
|
.curve = ctx->curve,
|
|
};
|
|
@@ -165,14 +152,14 @@ static int ecdsa_verify(struct akcipher_request *req)
|
|
goto error;
|
|
|
|
/* if the hash is shorter then we will add leading zeros to fit to ndigits */
|
|
- diff = keylen - req->dst_len;
|
|
+ diff = bufsize - req->dst_len;
|
|
if (diff >= 0) {
|
|
if (diff)
|
|
memset(rawhash, 0, diff);
|
|
memcpy(&rawhash[diff], buffer + req->src_len, req->dst_len);
|
|
} else if (diff < 0) {
|
|
/* given hash is longer, we take the left-most bytes */
|
|
- memcpy(&rawhash, buffer + req->src_len, keylen);
|
|
+ memcpy(&rawhash, buffer + req->src_len, bufsize);
|
|
}
|
|
|
|
ecc_swap_digits((u64 *)rawhash, hash, ctx->curve->g.ndigits);
|
|
@@ -222,9 +209,8 @@ static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx)
|
|
static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
|
|
{
|
|
struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
|
|
+ unsigned int digitlen, ndigits;
|
|
const unsigned char *d = key;
|
|
- const u64 *digits = (const u64 *)&d[1];
|
|
- unsigned int ndigits;
|
|
int ret;
|
|
|
|
ret = ecdsa_ecc_ctx_reset(ctx);
|
|
@@ -238,12 +224,17 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
|
|
return -EINVAL;
|
|
|
|
keylen--;
|
|
- ndigits = (keylen >> 1) / sizeof(u64);
|
|
+ digitlen = keylen >> 1;
|
|
+
|
|
+ ndigits = DIV_ROUND_UP(digitlen, sizeof(u64));
|
|
if (ndigits != ctx->curve->g.ndigits)
|
|
return -EINVAL;
|
|
|
|
- ecc_swap_digits(digits, ctx->pub_key.x, ndigits);
|
|
- ecc_swap_digits(&digits[ndigits], ctx->pub_key.y, ndigits);
|
|
+ d++;
|
|
+
|
|
+ ecc_digits_from_bytes(d, digitlen, ctx->pub_key.x, ndigits);
|
|
+ ecc_digits_from_bytes(&d[digitlen], digitlen, ctx->pub_key.y, ndigits);
|
|
+
|
|
ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key);
|
|
|
|
ctx->pub_key_set = ret == 0;
|
|
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
|
index 6496ff5a6ba20d..1a31106a14e446 100644
|
|
--- a/drivers/acpi/arm64/iort.c
|
|
+++ b/drivers/acpi/arm64/iort.c
|
|
@@ -1712,6 +1712,15 @@ static struct acpi_platform_list pmcg_plat_info[] __initdata = {
|
|
/* HiSilicon Hip09 Platform */
|
|
{"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
|
|
"Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
|
|
+ {"HISI ", "HIP09A ", 0, ACPI_SIG_IORT, greater_than_or_equal,
|
|
+ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
|
|
+ /* HiSilicon Hip10/11 Platform uses the same SMMU IP with Hip09 */
|
|
+ {"HISI ", "HIP10 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
|
|
+ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
|
|
+ {"HISI ", "HIP10C ", 0, ACPI_SIG_IORT, greater_than_or_equal,
|
|
+ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
|
|
+ {"HISI ", "HIP11 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
|
|
+ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
|
|
{ }
|
|
};
|
|
|
|
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
|
index fe5e30662017de..c80b5aa7628ae9 100644
|
|
--- a/drivers/bluetooth/btusb.c
|
|
+++ b/drivers/bluetooth/btusb.c
|
|
@@ -620,6 +620,9 @@ static const struct usb_device_id quirks_table[] = {
|
|
{ USB_DEVICE(0x0e8d, 0x0608), .driver_info = BTUSB_MEDIATEK |
|
|
BTUSB_WIDEBAND_SPEECH |
|
|
BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x13d3, 0x3606), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
|
|
/* MediaTek MT7922A Bluetooth devices */
|
|
{ USB_DEVICE(0x0489, 0xe0d8), .driver_info = BTUSB_MEDIATEK |
|
|
@@ -658,6 +661,37 @@ static const struct usb_device_id quirks_table[] = {
|
|
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
|
|
BTUSB_WIDEBAND_SPEECH |
|
|
BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x13d3, 0x3614), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x13d3, 0x3615), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x13d3, 0x3605), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x13d3, 0x3607), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+
|
|
+ /* Additional MediaTek MT7925 Bluetooth devices */
|
|
+ { USB_DEVICE(0x0489, 0xe111), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH },
|
|
+ { USB_DEVICE(0x0489, 0xe113), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
+ { USB_DEVICE(0x13d3, 0x3603), .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
|
|
/* Additional Realtek 8723AE Bluetooth devices */
|
|
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
|
|
@@ -858,6 +892,10 @@ struct btusb_data {
|
|
|
|
int (*setup_on_usb)(struct hci_dev *hdev);
|
|
|
|
+ int (*suspend)(struct hci_dev *hdev);
|
|
+ int (*resume)(struct hci_dev *hdev);
|
|
+ int (*disconnect)(struct hci_dev *hdev);
|
|
+
|
|
int oob_wake_irq; /* irq for out-of-band wake-on-bt */
|
|
unsigned cmd_timeout_cnt;
|
|
|
|
@@ -4609,6 +4647,9 @@ static void btusb_disconnect(struct usb_interface *intf)
|
|
if (data->diag)
|
|
usb_set_intfdata(data->diag, NULL);
|
|
|
|
+ if (data->disconnect)
|
|
+ data->disconnect(hdev);
|
|
+
|
|
hci_unregister_dev(hdev);
|
|
|
|
if (intf == data->intf) {
|
|
@@ -4657,6 +4698,9 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
|
|
|
cancel_work_sync(&data->work);
|
|
|
|
+ if (data->suspend)
|
|
+ data->suspend(data->hdev);
|
|
+
|
|
btusb_stop_traffic(data);
|
|
usb_kill_anchored_urbs(&data->tx_anchor);
|
|
|
|
@@ -4760,6 +4804,9 @@ static int btusb_resume(struct usb_interface *intf)
|
|
btusb_submit_isoc_urb(hdev, GFP_NOIO);
|
|
}
|
|
|
|
+ if (data->resume)
|
|
+ data->resume(hdev);
|
|
+
|
|
spin_lock_irq(&data->txlock);
|
|
play_deferred(data);
|
|
clear_bit(BTUSB_SUSPENDING, &data->flags);
|
|
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
|
|
index 8b3e5f84e89a77..ce44dbfd47e275 100644
|
|
--- a/drivers/clk/qcom/clk-alpha-pll.c
|
|
+++ b/drivers/clk/qcom/clk-alpha-pll.c
|
|
@@ -52,6 +52,7 @@
|
|
#define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL])
|
|
#define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U])
|
|
#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1])
|
|
+#define PLL_CONFIG_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U2])
|
|
#define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL])
|
|
#define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U])
|
|
#define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1])
|
|
@@ -227,6 +228,32 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
|
|
[PLL_OFF_ALPHA_VAL] = 0x24,
|
|
[PLL_OFF_ALPHA_VAL_U] = 0x28,
|
|
},
|
|
+ [CLK_ALPHA_PLL_TYPE_ZONDA_OLE] = {
|
|
+ [PLL_OFF_L_VAL] = 0x04,
|
|
+ [PLL_OFF_ALPHA_VAL] = 0x08,
|
|
+ [PLL_OFF_USER_CTL] = 0x0c,
|
|
+ [PLL_OFF_USER_CTL_U] = 0x10,
|
|
+ [PLL_OFF_CONFIG_CTL] = 0x14,
|
|
+ [PLL_OFF_CONFIG_CTL_U] = 0x18,
|
|
+ [PLL_OFF_CONFIG_CTL_U1] = 0x1c,
|
|
+ [PLL_OFF_CONFIG_CTL_U2] = 0x20,
|
|
+ [PLL_OFF_TEST_CTL] = 0x24,
|
|
+ [PLL_OFF_TEST_CTL_U] = 0x28,
|
|
+ [PLL_OFF_TEST_CTL_U1] = 0x2c,
|
|
+ [PLL_OFF_OPMODE] = 0x30,
|
|
+ [PLL_OFF_STATUS] = 0x3c,
|
|
+ },
|
|
+ [CLK_ALPHA_PLL_TYPE_NSS_HUAYRA] = {
|
|
+ [PLL_OFF_L_VAL] = 0x04,
|
|
+ [PLL_OFF_ALPHA_VAL] = 0x08,
|
|
+ [PLL_OFF_TEST_CTL] = 0x0c,
|
|
+ [PLL_OFF_TEST_CTL_U] = 0x10,
|
|
+ [PLL_OFF_USER_CTL] = 0x14,
|
|
+ [PLL_OFF_CONFIG_CTL] = 0x18,
|
|
+ [PLL_OFF_CONFIG_CTL_U] = 0x1c,
|
|
+ [PLL_OFF_STATUS] = 0x20,
|
|
+ },
|
|
+
|
|
};
|
|
EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
|
|
|
|
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
|
|
index 3fd0ef41c72c89..52dc5b9b546a15 100644
|
|
--- a/drivers/clk/qcom/clk-alpha-pll.h
|
|
+++ b/drivers/clk/qcom/clk-alpha-pll.h
|
|
@@ -21,6 +21,7 @@ enum {
|
|
CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION,
|
|
CLK_ALPHA_PLL_TYPE_AGERA,
|
|
CLK_ALPHA_PLL_TYPE_ZONDA,
|
|
+ CLK_ALPHA_PLL_TYPE_ZONDA_OLE,
|
|
CLK_ALPHA_PLL_TYPE_LUCID_EVO,
|
|
CLK_ALPHA_PLL_TYPE_LUCID_OLE,
|
|
CLK_ALPHA_PLL_TYPE_RIVIAN_EVO,
|
|
@@ -28,6 +29,7 @@ enum {
|
|
CLK_ALPHA_PLL_TYPE_BRAMMO_EVO,
|
|
CLK_ALPHA_PLL_TYPE_STROMER,
|
|
CLK_ALPHA_PLL_TYPE_STROMER_PLUS,
|
|
+ CLK_ALPHA_PLL_TYPE_NSS_HUAYRA,
|
|
CLK_ALPHA_PLL_TYPE_MAX,
|
|
};
|
|
|
|
@@ -42,6 +44,7 @@ enum {
|
|
PLL_OFF_CONFIG_CTL,
|
|
PLL_OFF_CONFIG_CTL_U,
|
|
PLL_OFF_CONFIG_CTL_U1,
|
|
+ PLL_OFF_CONFIG_CTL_U2,
|
|
PLL_OFF_TEST_CTL,
|
|
PLL_OFF_TEST_CTL_U,
|
|
PLL_OFF_TEST_CTL_U1,
|
|
@@ -119,6 +122,7 @@ struct alpha_pll_config {
|
|
u32 config_ctl_val;
|
|
u32 config_ctl_hi_val;
|
|
u32 config_ctl_hi1_val;
|
|
+ u32 config_ctl_hi2_val;
|
|
u32 user_ctl_val;
|
|
u32 user_ctl_hi_val;
|
|
u32 user_ctl_hi1_val;
|
|
@@ -173,6 +177,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops;
|
|
|
|
extern const struct clk_ops clk_alpha_pll_zonda_ops;
|
|
#define clk_alpha_pll_postdiv_zonda_ops clk_alpha_pll_postdiv_fabia_ops
|
|
+#define clk_alpha_pll_zonda_ole_ops clk_alpha_pll_zonda_ops
|
|
|
|
extern const struct clk_ops clk_alpha_pll_lucid_evo_ops;
|
|
extern const struct clk_ops clk_alpha_pll_reset_lucid_evo_ops;
|
|
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
|
|
index 8ff7cd4e20bb11..5eec1457e13967 100644
|
|
--- a/drivers/clocksource/hyperv_timer.c
|
|
+++ b/drivers/clocksource/hyperv_timer.c
|
|
@@ -27,7 +27,8 @@
|
|
#include <asm/mshyperv.h>
|
|
|
|
static struct clock_event_device __percpu *hv_clock_event;
|
|
-static u64 hv_sched_clock_offset __ro_after_init;
|
|
+/* Note: offset can hold negative values after hibernation. */
|
|
+static u64 hv_sched_clock_offset __read_mostly;
|
|
|
|
/*
|
|
* If false, we're using the old mechanism for stimer0 interrupts
|
|
@@ -456,6 +457,17 @@ static void resume_hv_clock_tsc(struct clocksource *arg)
|
|
hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);
|
|
}
|
|
|
|
+/*
|
|
+ * Called during resume from hibernation, from overridden
|
|
+ * x86_platform.restore_sched_clock_state routine. This is to adjust offsets
|
|
+ * used to calculate time for hv tsc page based sched_clock, to account for
|
|
+ * time spent before hibernation.
|
|
+ */
|
|
+void hv_adj_sched_clock_offset(u64 offset)
|
|
+{
|
|
+ hv_sched_clock_offset -= offset;
|
|
+}
|
|
+
|
|
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
|
|
static int hv_cs_enable(struct clocksource *cs)
|
|
{
|
|
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
|
|
index 3263b5fa182d20..f99e3b812ee44b 100644
|
|
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
|
|
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
|
|
@@ -319,7 +319,7 @@ svm_migrate_copy_to_vram(struct kfd_node *node, struct svm_range *prange,
|
|
spage = migrate_pfn_to_page(migrate->src[i]);
|
|
if (spage && !is_zone_device_page(spage)) {
|
|
src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE,
|
|
- DMA_TO_DEVICE);
|
|
+ DMA_BIDIRECTIONAL);
|
|
r = dma_mapping_error(dev, src[i]);
|
|
if (r) {
|
|
dev_err(dev, "%s: fail %d dma_map_page\n",
|
|
@@ -634,7 +634,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
|
|
goto out_oom;
|
|
}
|
|
|
|
- dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_FROM_DEVICE);
|
|
+ dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
|
|
r = dma_mapping_error(dev, dst[i]);
|
|
if (r) {
|
|
dev_err(adev->dev, "%s: fail %d dma_map_page\n", __func__, r);
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
index 9ec9792f115a8a..385a5a75fdf873 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
@@ -1219,10 +1219,6 @@ static bool is_dsc_need_re_compute(
|
|
if (dc_link->type != dc_connection_mst_branch)
|
|
return false;
|
|
|
|
- if (!(dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT ||
|
|
- dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
|
|
- return false;
|
|
-
|
|
for (i = 0; i < MAX_PIPES; i++)
|
|
stream_on_link[i] = NULL;
|
|
|
|
@@ -1243,6 +1239,18 @@ static bool is_dsc_need_re_compute(
|
|
if (!aconnector)
|
|
continue;
|
|
|
|
+ /*
|
|
+ * Check if cached virtual MST DSC caps are available and DSC is supported
|
|
+ * this change takes care of newer MST DSC capable devices that report their
|
|
+ * DPCD caps as per specifications in their Virtual DPCD registers.
|
|
+
|
|
+ * TODO: implement the check for older MST DSC devices that do not conform to
|
|
+ * specifications.
|
|
+ */
|
|
+ if (!(aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported ||
|
|
+ aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
|
|
+ continue;
|
|
+
|
|
stream_on_link[new_stream_on_link_num] = aconnector;
|
|
new_stream_on_link_num++;
|
|
|
|
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
|
|
index 61f4a38e7d2bf6..8f786592143b6c 100644
|
|
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
|
|
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
|
|
@@ -153,7 +153,16 @@ static int adv7511_hdmi_hw_params(struct device *dev, void *data,
|
|
ADV7511_AUDIO_CFG3_LEN_MASK, len);
|
|
regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
|
|
ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
|
|
- regmap_write(adv7511->regmap, 0x73, 0x1);
|
|
+
|
|
+ /* send current Audio infoframe values while updating */
|
|
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
|
+ BIT(5), BIT(5));
|
|
+
|
|
+ regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(0), 0x1);
|
|
+
|
|
+ /* use Audio infoframe updated info */
|
|
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
|
+ BIT(5), 0);
|
|
|
|
return 0;
|
|
}
|
|
@@ -184,8 +193,9 @@ static int audio_startup(struct device *dev, void *data)
|
|
regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
|
|
BIT(7) | BIT(6), BIT(7));
|
|
/* use Audio infoframe updated info */
|
|
- regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
|
|
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
|
|
BIT(5), 0);
|
|
+
|
|
/* enable SPDIF receiver */
|
|
if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
|
|
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
|
|
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
|
|
index ef2b6ce544d0a8..1aa4153b40e0c1 100644
|
|
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
|
|
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
|
|
@@ -1225,8 +1225,10 @@ static int adv7511_probe(struct i2c_client *i2c)
|
|
return ret;
|
|
|
|
ret = adv7511_init_regulators(adv7511);
|
|
- if (ret)
|
|
- return dev_err_probe(dev, ret, "failed to init regulators\n");
|
|
+ if (ret) {
|
|
+ dev_err_probe(dev, ret, "failed to init regulators\n");
|
|
+ goto err_of_node_put;
|
|
+ }
|
|
|
|
/*
|
|
* The power down GPIO is optional. If present, toggle it from active to
|
|
@@ -1346,6 +1348,8 @@ static int adv7511_probe(struct i2c_client *i2c)
|
|
i2c_unregister_device(adv7511->i2c_edid);
|
|
uninit_regulators:
|
|
adv7511_uninit_regulators(adv7511);
|
|
+err_of_node_put:
|
|
+ of_node_put(adv7511->host_node);
|
|
|
|
return ret;
|
|
}
|
|
@@ -1354,6 +1358,8 @@ static void adv7511_remove(struct i2c_client *i2c)
|
|
{
|
|
struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
|
|
|
|
+ of_node_put(adv7511->host_node);
|
|
+
|
|
adv7511_uninit_regulators(adv7511);
|
|
|
|
drm_bridge_remove(&adv7511->bridge);
|
|
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c
|
|
index 7e3e56441aedc5..6a4733c7082700 100644
|
|
--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
|
|
+++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
|
|
@@ -175,7 +175,7 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
|
|
|
|
of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
|
|
|
|
- if (num_lanes < 1 || num_lanes > 4)
|
|
+ if (num_lanes < 2 || num_lanes > 4)
|
|
return -EINVAL;
|
|
|
|
adv->num_dsi_lanes = num_lanes;
|
|
@@ -184,8 +184,6 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
|
|
if (!adv->host_node)
|
|
return -ENODEV;
|
|
|
|
- of_node_put(adv->host_node);
|
|
-
|
|
adv->use_timing_gen = !of_property_read_bool(np,
|
|
"adi,disable-timing-generator");
|
|
|
|
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
|
|
index 9e113e9473260a..6e8c182b2559e7 100644
|
|
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
|
|
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
|
|
@@ -133,7 +133,7 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
|
|
GEN9_MEDIA_PG_ENABLE |
|
|
GEN11_MEDIA_SAMPLER_PG_ENABLE;
|
|
|
|
- if (GRAPHICS_VER(gt->i915) >= 12) {
|
|
+ if (GRAPHICS_VER(gt->i915) >= 12 && !IS_DG1(gt->i915)) {
|
|
for (i = 0; i < I915_MAX_VCS; i++)
|
|
if (HAS_ENGINE(gt, _VCS(i)))
|
|
pg_enable |= (VDN_HCP_POWERGATE_ENABLE(i) |
|
|
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
|
|
index 97d27e01a6ee27..982007a112c2a0 100644
|
|
--- a/drivers/i2c/busses/Kconfig
|
|
+++ b/drivers/i2c/busses/Kconfig
|
|
@@ -159,6 +159,8 @@ config I2C_I801
|
|
Raptor Lake (PCH)
|
|
Meteor Lake (SOC and PCH)
|
|
Birch Stream (SOC)
|
|
+ Arrow Lake (SOC)
|
|
+ Panther Lake (SOC)
|
|
|
|
This driver can also be built as a module. If so, the module
|
|
will be called i2c-i801.
|
|
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
|
|
index 2b8bcd121ffa5d..18c04f5e41d9c5 100644
|
|
--- a/drivers/i2c/busses/i2c-i801.c
|
|
+++ b/drivers/i2c/busses/i2c-i801.c
|
|
@@ -80,6 +80,9 @@
|
|
* Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes
|
|
* Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes
|
|
* Birch Stream (SOC) 0x5796 32 hard yes yes yes
|
|
+ * Arrow Lake-H (SOC) 0x7722 32 hard yes yes yes
|
|
+ * Panther Lake-H (SOC) 0xe322 32 hard yes yes yes
|
|
+ * Panther Lake-P (SOC) 0xe422 32 hard yes yes yes
|
|
*
|
|
* Features supported by this driver:
|
|
* Software PEC no
|
|
@@ -234,6 +237,7 @@
|
|
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3
|
|
#define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796
|
|
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
|
|
+#define PCI_DEVICE_ID_INTEL_ARROW_LAKE_H_SMBUS 0x7722
|
|
#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23
|
|
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
|
|
#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_P_SMBUS 0x7e22
|
|
@@ -256,6 +260,8 @@
|
|
#define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323
|
|
#define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3
|
|
#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_SOC_S_SMBUS 0xae22
|
|
+#define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_H_SMBUS 0xe322
|
|
+#define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_P_SMBUS 0xe422
|
|
|
|
struct i801_mux_config {
|
|
char *gpio_chip;
|
|
@@ -1046,6 +1052,9 @@ static const struct pci_device_id i801_ids[] = {
|
|
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
|
{ PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
|
{ PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
|
+ { PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
|
+ { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
|
+ { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) },
|
|
{ 0, }
|
|
};
|
|
|
|
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c
|
|
index fbc1ffbd2fa7d6..658396c9eeabf9 100644
|
|
--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
|
|
+++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
|
|
@@ -91,14 +91,6 @@
|
|
|
|
#define SLIMPRO_IIC_MSG_DWORD_COUNT 3
|
|
|
|
-/* PCC related defines */
|
|
-#define PCC_SIGNATURE 0x50424300
|
|
-#define PCC_STS_CMD_COMPLETE BIT(0)
|
|
-#define PCC_STS_SCI_DOORBELL BIT(1)
|
|
-#define PCC_STS_ERR BIT(2)
|
|
-#define PCC_STS_PLAT_NOTIFY BIT(3)
|
|
-#define PCC_CMD_GENERATE_DB_INT BIT(15)
|
|
-
|
|
struct slimpro_i2c_dev {
|
|
struct i2c_adapter adapter;
|
|
struct device *dev;
|
|
@@ -160,11 +152,11 @@ static void slimpro_i2c_pcc_rx_cb(struct mbox_client *cl, void *msg)
|
|
|
|
/* Check if platform sends interrupt */
|
|
if (!xgene_word_tst_and_clr(&generic_comm_base->status,
|
|
- PCC_STS_SCI_DOORBELL))
|
|
+ PCC_STATUS_SCI_DOORBELL))
|
|
return;
|
|
|
|
if (xgene_word_tst_and_clr(&generic_comm_base->status,
|
|
- PCC_STS_CMD_COMPLETE)) {
|
|
+ PCC_STATUS_CMD_COMPLETE)) {
|
|
msg = generic_comm_base + 1;
|
|
|
|
/* Response message msg[1] contains the return value. */
|
|
@@ -186,10 +178,10 @@ static void slimpro_i2c_pcc_tx_prepare(struct slimpro_i2c_dev *ctx, u32 *msg)
|
|
cpu_to_le32(PCC_SIGNATURE | ctx->mbox_idx));
|
|
|
|
WRITE_ONCE(generic_comm_base->command,
|
|
- cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INT));
|
|
+ cpu_to_le16(SLIMPRO_MSG_TYPE(msg[0]) | PCC_CMD_GENERATE_DB_INTR));
|
|
|
|
status = le16_to_cpu(READ_ONCE(generic_comm_base->status));
|
|
- status &= ~PCC_STS_CMD_COMPLETE;
|
|
+ status &= ~PCC_STATUS_CMD_COMPLETE;
|
|
WRITE_ONCE(generic_comm_base->status, cpu_to_le16(status));
|
|
|
|
/* Copy the message to the PCC comm space */
|
|
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
|
|
index b64fd365f83fb8..fa6810aa6a4a7a 100644
|
|
--- a/drivers/iio/adc/ad7192.c
|
|
+++ b/drivers/iio/adc/ad7192.c
|
|
@@ -16,7 +16,9 @@
|
|
#include <linux/err.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/delay.h>
|
|
-#include <linux/of.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/mod_devicetable.h>
|
|
+#include <linux/property.h>
|
|
|
|
#include <linux/iio/iio.h>
|
|
#include <linux/iio/sysfs.h>
|
|
@@ -360,19 +362,19 @@ static inline bool ad7192_valid_external_frequency(u32 freq)
|
|
freq <= AD7192_EXT_FREQ_MHZ_MAX);
|
|
}
|
|
|
|
-static int ad7192_of_clock_select(struct ad7192_state *st)
|
|
+static int ad7192_clock_select(struct ad7192_state *st)
|
|
{
|
|
- struct device_node *np = st->sd.spi->dev.of_node;
|
|
+ struct device *dev = &st->sd.spi->dev;
|
|
unsigned int clock_sel;
|
|
|
|
clock_sel = AD7192_CLK_INT;
|
|
|
|
/* use internal clock */
|
|
if (!st->mclk) {
|
|
- if (of_property_read_bool(np, "adi,int-clock-output-enable"))
|
|
+ if (device_property_read_bool(dev, "adi,int-clock-output-enable"))
|
|
clock_sel = AD7192_CLK_INT_CO;
|
|
} else {
|
|
- if (of_property_read_bool(np, "adi,clock-xtal"))
|
|
+ if (device_property_read_bool(dev, "adi,clock-xtal"))
|
|
clock_sel = AD7192_CLK_EXT_MCLK1_2;
|
|
else
|
|
clock_sel = AD7192_CLK_EXT_MCLK2;
|
|
@@ -381,7 +383,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st)
|
|
return clock_sel;
|
|
}
|
|
|
|
-static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
|
|
+static int ad7192_setup(struct iio_dev *indio_dev, struct device *dev)
|
|
{
|
|
struct ad7192_state *st = iio_priv(indio_dev);
|
|
bool rej60_en, refin2_en;
|
|
@@ -403,7 +405,7 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
|
|
id &= AD7192_ID_MASK;
|
|
|
|
if (id != st->chip_info->chip_id)
|
|
- dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X != 0x%X)\n",
|
|
+ dev_warn(dev, "device ID query failed (0x%X != 0x%X)\n",
|
|
id, st->chip_info->chip_id);
|
|
|
|
st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) |
|
|
@@ -412,31 +414,31 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
|
|
|
|
st->conf = AD7192_CONF_GAIN(0);
|
|
|
|
- rej60_en = of_property_read_bool(np, "adi,rejection-60-Hz-enable");
|
|
+ rej60_en = device_property_read_bool(dev, "adi,rejection-60-Hz-enable");
|
|
if (rej60_en)
|
|
st->mode |= AD7192_MODE_REJ60;
|
|
|
|
- refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable");
|
|
+ refin2_en = device_property_read_bool(dev, "adi,refin2-pins-enable");
|
|
if (refin2_en && st->chip_info->chip_id != CHIPID_AD7195)
|
|
st->conf |= AD7192_CONF_REFSEL;
|
|
|
|
st->conf &= ~AD7192_CONF_CHOP;
|
|
st->f_order = AD7192_NO_SYNC_FILTER;
|
|
|
|
- buf_en = of_property_read_bool(np, "adi,buffer-enable");
|
|
+ buf_en = device_property_read_bool(dev, "adi,buffer-enable");
|
|
if (buf_en)
|
|
st->conf |= AD7192_CONF_BUF;
|
|
|
|
- bipolar = of_property_read_bool(np, "bipolar");
|
|
+ bipolar = device_property_read_bool(dev, "bipolar");
|
|
if (!bipolar)
|
|
st->conf |= AD7192_CONF_UNIPOLAR;
|
|
|
|
- burnout_curr_en = of_property_read_bool(np,
|
|
- "adi,burnout-currents-enable");
|
|
+ burnout_curr_en = device_property_read_bool(dev,
|
|
+ "adi,burnout-currents-enable");
|
|
if (burnout_curr_en && buf_en) {
|
|
st->conf |= AD7192_CONF_BURN;
|
|
} else if (burnout_curr_en) {
|
|
- dev_warn(&st->sd.spi->dev,
|
|
+ dev_warn(dev,
|
|
"Can't enable burnout currents: see CHOP or buffer\n");
|
|
}
|
|
|
|
@@ -1036,9 +1038,10 @@ static int ad7192_probe(struct spi_device *spi)
|
|
}
|
|
st->int_vref_mv = ret / 1000;
|
|
|
|
- st->chip_info = of_device_get_match_data(&spi->dev);
|
|
+ st->chip_info = spi_get_device_match_data(spi);
|
|
if (!st->chip_info)
|
|
- st->chip_info = (void *)spi_get_device_id(spi)->driver_data;
|
|
+ return -ENODEV;
|
|
+
|
|
indio_dev->name = st->chip_info->name;
|
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
|
|
|
@@ -1065,7 +1068,7 @@ static int ad7192_probe(struct spi_device *spi)
|
|
if (IS_ERR(st->mclk))
|
|
return PTR_ERR(st->mclk);
|
|
|
|
- st->clock_sel = ad7192_of_clock_select(st);
|
|
+ st->clock_sel = ad7192_clock_select(st);
|
|
|
|
if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 ||
|
|
st->clock_sel == AD7192_CLK_EXT_MCLK2) {
|
|
@@ -1077,7 +1080,7 @@ static int ad7192_probe(struct spi_device *spi)
|
|
}
|
|
}
|
|
|
|
- ret = ad7192_setup(indio_dev, spi->dev.of_node);
|
|
+ ret = ad7192_setup(indio_dev, &spi->dev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
|
|
index e836c9c477f675..c6053e82ecf6f3 100644
|
|
--- a/drivers/infiniband/core/uverbs_cmd.c
|
|
+++ b/drivers/infiniband/core/uverbs_cmd.c
|
|
@@ -161,7 +161,7 @@ static const void __user *uverbs_request_next_ptr(struct uverbs_req_iter *iter,
|
|
{
|
|
const void __user *res = iter->cur;
|
|
|
|
- if (iter->cur + len > iter->end)
|
|
+ if (len > iter->end - iter->cur)
|
|
return (void __force __user *)ERR_PTR(-ENOSPC);
|
|
iter->cur += len;
|
|
return res;
|
|
@@ -2009,11 +2009,13 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
|
|
ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd));
|
|
if (ret)
|
|
return ret;
|
|
- wqes = uverbs_request_next_ptr(&iter, cmd.wqe_size * cmd.wr_count);
|
|
+ wqes = uverbs_request_next_ptr(&iter, size_mul(cmd.wqe_size,
|
|
+ cmd.wr_count));
|
|
if (IS_ERR(wqes))
|
|
return PTR_ERR(wqes);
|
|
- sgls = uverbs_request_next_ptr(
|
|
- &iter, cmd.sge_count * sizeof(struct ib_uverbs_sge));
|
|
+ sgls = uverbs_request_next_ptr(&iter,
|
|
+ size_mul(cmd.sge_count,
|
|
+ sizeof(struct ib_uverbs_sge)));
|
|
if (IS_ERR(sgls))
|
|
return PTR_ERR(sgls);
|
|
ret = uverbs_request_finish(&iter);
|
|
@@ -2199,11 +2201,11 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count,
|
|
if (wqe_size < sizeof(struct ib_uverbs_recv_wr))
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
- wqes = uverbs_request_next_ptr(iter, wqe_size * wr_count);
|
|
+ wqes = uverbs_request_next_ptr(iter, size_mul(wqe_size, wr_count));
|
|
if (IS_ERR(wqes))
|
|
return ERR_CAST(wqes);
|
|
- sgls = uverbs_request_next_ptr(
|
|
- iter, sge_count * sizeof(struct ib_uverbs_sge));
|
|
+ sgls = uverbs_request_next_ptr(iter, size_mul(sge_count,
|
|
+ sizeof(struct ib_uverbs_sge)));
|
|
if (IS_ERR(sgls))
|
|
return ERR_CAST(sgls);
|
|
ret = uverbs_request_finish(iter);
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
|
|
index df589726060144..13c65ec5825687 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
|
|
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
|
|
@@ -147,7 +147,7 @@ int bnxt_re_query_device(struct ib_device *ibdev,
|
|
|
|
ib_attr->vendor_id = rdev->en_dev->pdev->vendor;
|
|
ib_attr->vendor_part_id = rdev->en_dev->pdev->device;
|
|
- ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device;
|
|
+ ib_attr->hw_ver = rdev->en_dev->pdev->revision;
|
|
ib_attr->max_qp = dev_attr->max_qp;
|
|
ib_attr->max_qp_wr = dev_attr->max_qp_wqes;
|
|
ib_attr->device_cap_flags =
|
|
@@ -992,23 +992,22 @@ static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp,
|
|
align = sizeof(struct sq_send_hdr);
|
|
ilsize = ALIGN(init_attr->cap.max_inline_data, align);
|
|
|
|
- sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge);
|
|
- if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges))
|
|
- return -EINVAL;
|
|
- /* For gen p4 and gen p5 backward compatibility mode
|
|
- * wqe size is fixed to 128 bytes
|
|
+ /* For gen p4 and gen p5 fixed wqe compatibility mode
|
|
+ * wqe size is fixed to 128 bytes - ie 6 SGEs
|
|
*/
|
|
- if (sq->wqe_size < bnxt_re_get_swqe_size(dev_attr->max_qp_sges) &&
|
|
- qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
|
|
- sq->wqe_size = bnxt_re_get_swqe_size(dev_attr->max_qp_sges);
|
|
+ if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) {
|
|
+ sq->wqe_size = bnxt_re_get_swqe_size(BNXT_STATIC_MAX_SGE);
|
|
+ sq->max_sge = BNXT_STATIC_MAX_SGE;
|
|
+ } else {
|
|
+ sq->wqe_size = bnxt_re_get_wqe_size(ilsize, sq->max_sge);
|
|
+ if (sq->wqe_size > bnxt_re_get_swqe_size(dev_attr->max_qp_sges))
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
if (init_attr->cap.max_inline_data) {
|
|
qplqp->max_inline_data = sq->wqe_size -
|
|
sizeof(struct sq_send_hdr);
|
|
init_attr->cap.max_inline_data = qplqp->max_inline_data;
|
|
- if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
|
|
- sq->max_sge = qplqp->max_inline_data /
|
|
- sizeof(struct sq_sge);
|
|
}
|
|
|
|
return 0;
|
|
@@ -1154,6 +1153,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp
|
|
/* Shadow QP SQ depth should be same as QP1 RQ depth */
|
|
qp->qplib_qp.sq.wqe_size = bnxt_re_get_wqe_size(0, 6);
|
|
qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe;
|
|
+ qp->qplib_qp.sq.max_sw_wqe = qp1_qp->rq.max_wqe;
|
|
qp->qplib_qp.sq.max_sge = 2;
|
|
/* Q full delta can be 1 since it is internal QP */
|
|
qp->qplib_qp.sq.q_full_delta = 1;
|
|
@@ -1165,6 +1165,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp
|
|
|
|
qp->qplib_qp.rq.wqe_size = bnxt_re_get_rwqe_size(6);
|
|
qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe;
|
|
+ qp->qplib_qp.rq.max_sw_wqe = qp1_qp->rq.max_wqe;
|
|
qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge;
|
|
/* Q full delta can be 1 since it is internal QP */
|
|
qp->qplib_qp.rq.q_full_delta = 1;
|
|
@@ -1226,6 +1227,7 @@ static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp,
|
|
*/
|
|
entries = bnxt_re_init_depth(init_attr->cap.max_recv_wr + 1, uctx);
|
|
rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1);
|
|
+ rq->max_sw_wqe = rq->max_wqe;
|
|
rq->q_full_delta = 0;
|
|
rq->sg_info.pgsize = PAGE_SIZE;
|
|
rq->sg_info.pgshft = PAGE_SHIFT;
|
|
@@ -1285,6 +1287,7 @@ static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp,
|
|
0 : BNXT_QPLIB_RESERVED_QP_WRS;
|
|
entries = bnxt_re_init_depth(entries + diff + 1, uctx);
|
|
sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1);
|
|
+ sq->max_sw_wqe = bnxt_qplib_get_depth(sq, qplqp->wqe_mode, true);
|
|
sq->q_full_delta = diff + 1;
|
|
/*
|
|
* Reserving one slot for Phantom WQE. Application can
|
|
@@ -2055,18 +2058,20 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
|
}
|
|
}
|
|
|
|
- if (qp_attr_mask & IB_QP_PATH_MTU) {
|
|
- qp->qplib_qp.modify_flags |=
|
|
- CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
|
|
- qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu);
|
|
- qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu);
|
|
- } else if (qp_attr->qp_state == IB_QPS_RTR) {
|
|
- qp->qplib_qp.modify_flags |=
|
|
- CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
|
|
- qp->qplib_qp.path_mtu =
|
|
- __from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu));
|
|
- qp->qplib_qp.mtu =
|
|
- ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
|
|
+ if (qp_attr->qp_state == IB_QPS_RTR) {
|
|
+ enum ib_mtu qpmtu;
|
|
+
|
|
+ qpmtu = iboe_get_mtu(rdev->netdev->mtu);
|
|
+ if (qp_attr_mask & IB_QP_PATH_MTU) {
|
|
+ if (ib_mtu_enum_to_int(qp_attr->path_mtu) >
|
|
+ ib_mtu_enum_to_int(qpmtu))
|
|
+ return -EINVAL;
|
|
+ qpmtu = qp_attr->path_mtu;
|
|
+ }
|
|
+
|
|
+ qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
|
|
+ qp->qplib_qp.path_mtu = __from_ib_mtu(qpmtu);
|
|
+ qp->qplib_qp.mtu = ib_mtu_enum_to_int(qpmtu);
|
|
}
|
|
|
|
if (qp_attr_mask & IB_QP_TIMEOUT) {
|
|
@@ -2153,6 +2158,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
|
entries = bnxt_re_init_depth(qp_attr->cap.max_recv_wr, uctx);
|
|
qp->qplib_qp.rq.max_wqe =
|
|
min_t(u32, entries, dev_attr->max_qp_wqes + 1);
|
|
+ qp->qplib_qp.rq.max_sw_wqe = qp->qplib_qp.rq.max_wqe;
|
|
qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
|
|
qp_attr->cap.max_recv_wr;
|
|
qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge;
|
|
@@ -2710,7 +2716,8 @@ static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
|
|
wr = wr->next;
|
|
}
|
|
bnxt_qplib_post_send_db(&qp->qplib_qp);
|
|
- bnxt_ud_qp_hw_stall_workaround(qp);
|
|
+ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx))
|
|
+ bnxt_ud_qp_hw_stall_workaround(qp);
|
|
spin_unlock_irqrestore(&qp->sq_lock, flags);
|
|
return rc;
|
|
}
|
|
@@ -2822,7 +2829,8 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr,
|
|
wr = wr->next;
|
|
}
|
|
bnxt_qplib_post_send_db(&qp->qplib_qp);
|
|
- bnxt_ud_qp_hw_stall_workaround(qp);
|
|
+ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx))
|
|
+ bnxt_ud_qp_hw_stall_workaround(qp);
|
|
spin_unlock_irqrestore(&qp->sq_lock, flags);
|
|
|
|
return rc;
|
|
@@ -4167,9 +4175,6 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
|
|
resp.cqe_sz = sizeof(struct cq_base);
|
|
resp.max_cqd = dev_attr->max_cq_wqes;
|
|
|
|
- resp.comp_mask |= BNXT_RE_UCNTX_CMASK_HAVE_MODE;
|
|
- resp.mode = rdev->chip_ctx->modes.wqe_mode;
|
|
-
|
|
if (rdev->chip_ctx->modes.db_push)
|
|
resp.comp_mask |= BNXT_RE_UCNTX_CMASK_WC_DPI_ENABLED;
|
|
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
|
|
index 0373d0e9db6329..c7e51cc2ea2687 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/main.c
|
|
+++ b/drivers/infiniband/hw/bnxt_re/main.c
|
|
@@ -128,13 +128,13 @@ static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev)
|
|
}
|
|
}
|
|
|
|
-static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode)
|
|
+static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev)
|
|
{
|
|
struct bnxt_qplib_chip_ctx *cctx;
|
|
|
|
cctx = rdev->chip_ctx;
|
|
- cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx) ?
|
|
- mode : BNXT_QPLIB_WQE_MODE_STATIC;
|
|
+ cctx->modes.wqe_mode = bnxt_qplib_is_chip_gen_p7(rdev->chip_ctx) ?
|
|
+ BNXT_QPLIB_WQE_MODE_VARIABLE : BNXT_QPLIB_WQE_MODE_STATIC;
|
|
if (bnxt_re_hwrm_qcaps(rdev))
|
|
dev_err(rdev_to_dev(rdev),
|
|
"Failed to query hwrm qcaps\n");
|
|
@@ -155,7 +155,7 @@ static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev)
|
|
kfree(chip_ctx);
|
|
}
|
|
|
|
-static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
|
+static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev)
|
|
{
|
|
struct bnxt_qplib_chip_ctx *chip_ctx;
|
|
struct bnxt_en_dev *en_dev;
|
|
@@ -177,7 +177,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
|
rdev->qplib_res.dattr = &rdev->dev_attr;
|
|
rdev->qplib_res.is_vf = BNXT_EN_VF(en_dev);
|
|
|
|
- bnxt_re_set_drv_mode(rdev, wqe_mode);
|
|
+ bnxt_re_set_drv_mode(rdev);
|
|
|
|
bnxt_re_set_db_offset(rdev);
|
|
rc = bnxt_qplib_map_db_bar(&rdev->qplib_res);
|
|
@@ -1440,7 +1440,7 @@ static void bnxt_re_worker(struct work_struct *work)
|
|
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
|
|
}
|
|
|
|
-static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
|
+static int bnxt_re_dev_init(struct bnxt_re_dev *rdev)
|
|
{
|
|
struct bnxt_re_ring_attr rattr = {};
|
|
struct bnxt_qplib_creq_ctx *creq;
|
|
@@ -1458,7 +1458,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
|
}
|
|
set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
|
|
|
|
- rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode);
|
|
+ rc = bnxt_re_setup_chip_ctx(rdev);
|
|
if (rc) {
|
|
bnxt_unregister_dev(rdev->en_dev);
|
|
clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
|
|
@@ -1609,7 +1609,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
|
|
return rc;
|
|
}
|
|
|
|
-static int bnxt_re_add_device(struct auxiliary_device *adev, u8 wqe_mode)
|
|
+static int bnxt_re_add_device(struct auxiliary_device *adev)
|
|
{
|
|
struct bnxt_aux_priv *aux_priv =
|
|
container_of(adev, struct bnxt_aux_priv, aux_dev);
|
|
@@ -1626,7 +1626,7 @@ static int bnxt_re_add_device(struct auxiliary_device *adev, u8 wqe_mode)
|
|
goto exit;
|
|
}
|
|
|
|
- rc = bnxt_re_dev_init(rdev, wqe_mode);
|
|
+ rc = bnxt_re_dev_init(rdev);
|
|
if (rc)
|
|
goto re_dev_dealloc;
|
|
|
|
@@ -1756,7 +1756,8 @@ static int bnxt_re_probe(struct auxiliary_device *adev,
|
|
int rc;
|
|
|
|
mutex_lock(&bnxt_re_mutex);
|
|
- rc = bnxt_re_add_device(adev, BNXT_QPLIB_WQE_MODE_STATIC);
|
|
+
|
|
+ rc = bnxt_re_add_device(adev);
|
|
if (rc) {
|
|
mutex_unlock(&bnxt_re_mutex);
|
|
return rc;
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
|
|
index b624c255eee6fa..871a49315c880f 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
|
|
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
|
|
@@ -639,13 +639,6 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
|
|
rc = bnxt_qplib_alloc_init_hwq(&srq->hwq, &hwq_attr);
|
|
if (rc)
|
|
return rc;
|
|
-
|
|
- srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq),
|
|
- GFP_KERNEL);
|
|
- if (!srq->swq) {
|
|
- rc = -ENOMEM;
|
|
- goto fail;
|
|
- }
|
|
srq->dbinfo.flags = 0;
|
|
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
|
|
CMDQ_BASE_OPCODE_CREATE_SRQ,
|
|
@@ -674,9 +667,17 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
|
|
spin_lock_init(&srq->lock);
|
|
srq->start_idx = 0;
|
|
srq->last_idx = srq->hwq.max_elements - 1;
|
|
- for (idx = 0; idx < srq->hwq.max_elements; idx++)
|
|
- srq->swq[idx].next_idx = idx + 1;
|
|
- srq->swq[srq->last_idx].next_idx = -1;
|
|
+ if (!srq->hwq.is_user) {
|
|
+ srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq),
|
|
+ GFP_KERNEL);
|
|
+ if (!srq->swq) {
|
|
+ rc = -ENOMEM;
|
|
+ goto fail;
|
|
+ }
|
|
+ for (idx = 0; idx < srq->hwq.max_elements; idx++)
|
|
+ srq->swq[idx].next_idx = idx + 1;
|
|
+ srq->swq[srq->last_idx].next_idx = -1;
|
|
+ }
|
|
|
|
srq->id = le32_to_cpu(resp.xid);
|
|
srq->dbinfo.hwq = &srq->hwq;
|
|
@@ -806,13 +807,13 @@ static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que)
|
|
{
|
|
int indx;
|
|
|
|
- que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL);
|
|
+ que->swq = kcalloc(que->max_sw_wqe, sizeof(*que->swq), GFP_KERNEL);
|
|
if (!que->swq)
|
|
return -ENOMEM;
|
|
|
|
que->swq_start = 0;
|
|
- que->swq_last = que->max_wqe - 1;
|
|
- for (indx = 0; indx < que->max_wqe; indx++)
|
|
+ que->swq_last = que->max_sw_wqe - 1;
|
|
+ for (indx = 0; indx < que->max_sw_wqe; indx++)
|
|
que->swq[indx].next_idx = indx + 1;
|
|
que->swq[que->swq_last].next_idx = 0; /* Make it circular */
|
|
que->swq_last = 0;
|
|
@@ -848,7 +849,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
hwq_attr.res = res;
|
|
hwq_attr.sginfo = &sq->sg_info;
|
|
hwq_attr.stride = sizeof(struct sq_sge);
|
|
- hwq_attr.depth = bnxt_qplib_get_depth(sq);
|
|
+ hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, false);
|
|
hwq_attr.type = HWQ_TYPE_QUEUE;
|
|
rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr);
|
|
if (rc)
|
|
@@ -876,7 +877,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
hwq_attr.res = res;
|
|
hwq_attr.sginfo = &rq->sg_info;
|
|
hwq_attr.stride = sizeof(struct sq_sge);
|
|
- hwq_attr.depth = bnxt_qplib_get_depth(rq);
|
|
+ hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false);
|
|
hwq_attr.type = HWQ_TYPE_QUEUE;
|
|
rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr);
|
|
if (rc)
|
|
@@ -980,9 +981,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
u32 tbl_indx;
|
|
u16 nsge;
|
|
|
|
- if (res->dattr)
|
|
- qp->dev_cap_flags = res->dattr->dev_cap_flags;
|
|
-
|
|
+ qp->is_host_msn_tbl = _is_host_msn_table(res->dattr->dev_cap_flags2);
|
|
sq->dbinfo.flags = 0;
|
|
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
|
|
CMDQ_BASE_OPCODE_CREATE_QP,
|
|
@@ -999,7 +998,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
sizeof(struct sq_psn_search_ext) :
|
|
sizeof(struct sq_psn_search);
|
|
|
|
- if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) {
|
|
+ if (qp->is_host_msn_tbl) {
|
|
psn_sz = sizeof(struct sq_msn_search);
|
|
qp->msn = 0;
|
|
}
|
|
@@ -1008,13 +1007,18 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
hwq_attr.res = res;
|
|
hwq_attr.sginfo = &sq->sg_info;
|
|
hwq_attr.stride = sizeof(struct sq_sge);
|
|
- hwq_attr.depth = bnxt_qplib_get_depth(sq);
|
|
+ hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, true);
|
|
hwq_attr.aux_stride = psn_sz;
|
|
hwq_attr.aux_depth = psn_sz ? bnxt_qplib_set_sq_size(sq, qp->wqe_mode)
|
|
: 0;
|
|
/* Update msn tbl size */
|
|
- if (BNXT_RE_HW_RETX(qp->dev_cap_flags) && psn_sz) {
|
|
- hwq_attr.aux_depth = roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode));
|
|
+ if (qp->is_host_msn_tbl && psn_sz) {
|
|
+ if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
|
|
+ hwq_attr.aux_depth =
|
|
+ roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode));
|
|
+ else
|
|
+ hwq_attr.aux_depth =
|
|
+ roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)) / 2;
|
|
qp->msn_tbl_sz = hwq_attr.aux_depth;
|
|
qp->msn = 0;
|
|
}
|
|
@@ -1024,13 +1028,14 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
if (rc)
|
|
return rc;
|
|
|
|
- rc = bnxt_qplib_alloc_init_swq(sq);
|
|
- if (rc)
|
|
- goto fail_sq;
|
|
-
|
|
- if (psn_sz)
|
|
- bnxt_qplib_init_psn_ptr(qp, psn_sz);
|
|
+ if (!sq->hwq.is_user) {
|
|
+ rc = bnxt_qplib_alloc_init_swq(sq);
|
|
+ if (rc)
|
|
+ goto fail_sq;
|
|
|
|
+ if (psn_sz)
|
|
+ bnxt_qplib_init_psn_ptr(qp, psn_sz);
|
|
+ }
|
|
req.sq_size = cpu_to_le32(bnxt_qplib_set_sq_size(sq, qp->wqe_mode));
|
|
pbl = &sq->hwq.pbl[PBL_LVL_0];
|
|
req.sq_pbl = cpu_to_le64(pbl->pg_map_arr[0]);
|
|
@@ -1049,16 +1054,18 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
hwq_attr.res = res;
|
|
hwq_attr.sginfo = &rq->sg_info;
|
|
hwq_attr.stride = sizeof(struct sq_sge);
|
|
- hwq_attr.depth = bnxt_qplib_get_depth(rq);
|
|
+ hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false);
|
|
hwq_attr.aux_stride = 0;
|
|
hwq_attr.aux_depth = 0;
|
|
hwq_attr.type = HWQ_TYPE_QUEUE;
|
|
rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr);
|
|
if (rc)
|
|
goto sq_swq;
|
|
- rc = bnxt_qplib_alloc_init_swq(rq);
|
|
- if (rc)
|
|
- goto fail_rq;
|
|
+ if (!rq->hwq.is_user) {
|
|
+ rc = bnxt_qplib_alloc_init_swq(rq);
|
|
+ if (rc)
|
|
+ goto fail_rq;
|
|
+ }
|
|
|
|
req.rq_size = cpu_to_le32(rq->max_wqe);
|
|
pbl = &rq->hwq.pbl[PBL_LVL_0];
|
|
@@ -1154,9 +1161,11 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
|
|
rq->dbinfo.db = qp->dpi->dbr;
|
|
rq->dbinfo.max_slot = bnxt_qplib_set_rq_max_slot(rq->wqe_size);
|
|
}
|
|
+ spin_lock_bh(&rcfw->tbl_lock);
|
|
tbl_indx = map_qp_id_to_tbl_indx(qp->id, rcfw);
|
|
rcfw->qp_tbl[tbl_indx].qp_id = qp->id;
|
|
rcfw->qp_tbl[tbl_indx].qp_handle = (void *)qp;
|
|
+ spin_unlock_bh(&rcfw->tbl_lock);
|
|
|
|
return 0;
|
|
fail:
|
|
@@ -1638,7 +1647,7 @@ static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp,
|
|
if (!swq->psn_search)
|
|
return;
|
|
/* Handle MSN differently on cap flags */
|
|
- if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) {
|
|
+ if (qp->is_host_msn_tbl) {
|
|
bnxt_qplib_fill_msn_search(qp, wqe, swq);
|
|
return;
|
|
}
|
|
@@ -1820,7 +1829,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
|
|
}
|
|
|
|
swq = bnxt_qplib_get_swqe(sq, &wqe_idx);
|
|
- bnxt_qplib_pull_psn_buff(qp, sq, swq, BNXT_RE_HW_RETX(qp->dev_cap_flags));
|
|
+ bnxt_qplib_pull_psn_buff(qp, sq, swq, qp->is_host_msn_tbl);
|
|
|
|
idx = 0;
|
|
swq->slot_idx = hwq->prod;
|
|
@@ -2010,7 +2019,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
|
|
rc = -EINVAL;
|
|
goto done;
|
|
}
|
|
- if (!BNXT_RE_HW_RETX(qp->dev_cap_flags) || msn_update) {
|
|
+ if (!qp->is_host_msn_tbl || msn_update) {
|
|
swq->next_psn = sq->psn & BTH_PSN_MASK;
|
|
bnxt_qplib_fill_psn_search(qp, wqe, swq);
|
|
}
|
|
@@ -2491,7 +2500,7 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
|
|
}
|
|
sq = &qp->sq;
|
|
|
|
- cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_wqe;
|
|
+ cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_sw_wqe;
|
|
if (qp->sq.flushed) {
|
|
dev_dbg(&cq->hwq.pdev->dev,
|
|
"%s: QP in Flush QP = %p\n", __func__, qp);
|
|
@@ -2534,10 +2543,12 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
|
|
bnxt_qplib_add_flush_qp(qp);
|
|
} else {
|
|
/* Before we complete, do WA 9060 */
|
|
- if (do_wa9060(qp, cq, cq_cons, sq->swq_last,
|
|
- cqe_sq_cons)) {
|
|
- *lib_qp = qp;
|
|
- goto out;
|
|
+ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->cctx)) {
|
|
+ if (do_wa9060(qp, cq, cq_cons, sq->swq_last,
|
|
+ cqe_sq_cons)) {
|
|
+ *lib_qp = qp;
|
|
+ goto out;
|
|
+ }
|
|
}
|
|
if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
|
|
cqe->status = CQ_REQ_STATUS_OK;
|
|
@@ -2881,7 +2892,7 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq,
|
|
cqe_cons = le16_to_cpu(hwcqe->sq_cons_idx);
|
|
if (cqe_cons == 0xFFFF)
|
|
goto do_rq;
|
|
- cqe_cons %= sq->max_wqe;
|
|
+ cqe_cons %= sq->max_sw_wqe;
|
|
|
|
if (qp->sq.flushed) {
|
|
dev_dbg(&cq->hwq.pdev->dev,
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
|
|
index 5d4c49089a20f4..b5c53e864fbb39 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
|
|
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
|
|
@@ -113,7 +113,6 @@ struct bnxt_qplib_sge {
|
|
u32 size;
|
|
};
|
|
|
|
-#define BNXT_QPLIB_QP_MAX_SGL 6
|
|
struct bnxt_qplib_swq {
|
|
u64 wr_id;
|
|
int next_idx;
|
|
@@ -153,7 +152,7 @@ struct bnxt_qplib_swqe {
|
|
#define BNXT_QPLIB_SWQE_FLAGS_UC_FENCE BIT(2)
|
|
#define BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT BIT(3)
|
|
#define BNXT_QPLIB_SWQE_FLAGS_INLINE BIT(4)
|
|
- struct bnxt_qplib_sge sg_list[BNXT_QPLIB_QP_MAX_SGL];
|
|
+ struct bnxt_qplib_sge sg_list[BNXT_VAR_MAX_SGE];
|
|
int num_sge;
|
|
/* Max inline data is 96 bytes */
|
|
u32 inline_len;
|
|
@@ -251,6 +250,7 @@ struct bnxt_qplib_q {
|
|
struct bnxt_qplib_db_info dbinfo;
|
|
struct bnxt_qplib_sg_info sg_info;
|
|
u32 max_wqe;
|
|
+ u32 max_sw_wqe;
|
|
u16 wqe_size;
|
|
u16 q_full_delta;
|
|
u16 max_sge;
|
|
@@ -340,7 +340,7 @@ struct bnxt_qplib_qp {
|
|
struct list_head rq_flush;
|
|
u32 msn;
|
|
u32 msn_tbl_sz;
|
|
- u16 dev_cap_flags;
|
|
+ bool is_host_msn_tbl;
|
|
};
|
|
|
|
#define BNXT_QPLIB_MAX_CQE_ENTRY_SIZE sizeof(struct cq_base)
|
|
@@ -585,15 +585,22 @@ static inline void bnxt_qplib_swq_mod_start(struct bnxt_qplib_q *que, u32 idx)
|
|
que->swq_start = que->swq[idx].next_idx;
|
|
}
|
|
|
|
-static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que)
|
|
+static inline u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que, u8 wqe_mode, bool is_sq)
|
|
{
|
|
- return (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge);
|
|
+ u32 slots;
|
|
+
|
|
+ /* Queue depth is the number of slots. */
|
|
+ slots = (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge);
|
|
+ /* For variable WQE mode, need to align the slots to 256 */
|
|
+ if (wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE && is_sq)
|
|
+ slots = ALIGN(slots, BNXT_VAR_MAX_SLOT_ALIGN);
|
|
+ return slots;
|
|
}
|
|
|
|
static inline u32 bnxt_qplib_set_sq_size(struct bnxt_qplib_q *que, u8 wqe_mode)
|
|
{
|
|
return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ?
|
|
- que->max_wqe : bnxt_qplib_get_depth(que);
|
|
+ que->max_wqe : bnxt_qplib_get_depth(que, wqe_mode, true);
|
|
}
|
|
|
|
static inline u32 bnxt_qplib_set_sq_max_slot(u8 wqe_mode)
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
|
|
index f9e7aa3757cfb2..c2152122a4329d 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
|
|
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
|
|
@@ -523,6 +523,12 @@ static inline bool _is_hw_retx_supported(u16 dev_cap_flags)
|
|
|
|
#define BNXT_RE_HW_RETX(a) _is_hw_retx_supported((a))
|
|
|
|
+static inline bool _is_host_msn_table(u16 dev_cap_ext_flags2)
|
|
+{
|
|
+ return (dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_MASK) ==
|
|
+ CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_MSN_TABLE;
|
|
+}
|
|
+
|
|
static inline u8 bnxt_qplib_dbr_pacing_en(struct bnxt_qplib_chip_ctx *cctx)
|
|
{
|
|
return cctx->modes.dbr_pacing;
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
|
|
index 0b98577cd7082e..74c3f6b26c4d3a 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
|
|
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
|
|
@@ -95,11 +95,13 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
|
|
struct bnxt_qplib_cmdqmsg msg = {};
|
|
struct creq_query_func_resp_sb *sb;
|
|
struct bnxt_qplib_rcfw_sbuf sbuf;
|
|
+ struct bnxt_qplib_chip_ctx *cctx;
|
|
struct cmdq_query_func req = {};
|
|
u8 *tqm_alloc;
|
|
int i, rc;
|
|
u32 temp;
|
|
|
|
+ cctx = rcfw->res->cctx;
|
|
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
|
|
CMDQ_BASE_OPCODE_QUERY_FUNC,
|
|
sizeof(req));
|
|
@@ -127,14 +129,21 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
|
|
attr->max_qp_init_rd_atom =
|
|
sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
|
|
BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
|
|
- attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr);
|
|
- /*
|
|
- * 128 WQEs needs to be reserved for the HW (8916). Prevent
|
|
- * reporting the max number
|
|
- */
|
|
- attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1;
|
|
- attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx) ?
|
|
- 6 : sb->max_sge;
|
|
+ attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr) - 1;
|
|
+ if (!bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx)) {
|
|
+ /*
|
|
+ * 128 WQEs needs to be reserved for the HW (8916). Prevent
|
|
+ * reporting the max number on legacy devices
|
|
+ */
|
|
+ attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1;
|
|
+ }
|
|
+
|
|
+ /* Adjust for max_qp_wqes for variable wqe */
|
|
+ if (cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE)
|
|
+ attr->max_qp_wqes = BNXT_VAR_MAX_WQE - 1;
|
|
+
|
|
+ attr->max_qp_sges = cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE ?
|
|
+ min_t(u32, sb->max_sge_var_wqe, BNXT_VAR_MAX_SGE) : 6;
|
|
attr->max_cq = le32_to_cpu(sb->max_cq);
|
|
attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
|
|
if (!bnxt_qplib_is_chip_gen_p7(rcfw->res->cctx))
|
|
@@ -165,6 +174,7 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
|
|
attr->max_sgid = le32_to_cpu(sb->max_gid);
|
|
attr->max_sgid = min_t(u32, BNXT_QPLIB_NUM_GIDS_SUPPORTED, 2 * attr->max_sgid);
|
|
attr->dev_cap_flags = le16_to_cpu(sb->dev_cap_flags);
|
|
+ attr->dev_cap_flags2 = le16_to_cpu(sb->dev_cap_ext_flags_2);
|
|
|
|
bnxt_qplib_query_version(rcfw, attr->fw_ver);
|
|
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
|
|
index 755765e68eaab2..aeacd0a9a92cc4 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h
|
|
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
|
|
@@ -40,6 +40,7 @@
|
|
#ifndef __BNXT_QPLIB_SP_H__
|
|
#define __BNXT_QPLIB_SP_H__
|
|
|
|
+#include <rdma/bnxt_re-abi.h>
|
|
#define BNXT_QPLIB_RESERVED_QP_WRS 128
|
|
|
|
struct bnxt_qplib_dev_attr {
|
|
@@ -73,6 +74,7 @@ struct bnxt_qplib_dev_attr {
|
|
u8 tqm_alloc_reqs[MAX_TQM_ALLOC_REQ];
|
|
bool is_atomic;
|
|
u16 dev_cap_flags;
|
|
+ u16 dev_cap_flags2;
|
|
u32 max_dpi;
|
|
};
|
|
|
|
@@ -351,4 +353,11 @@ int bnxt_qplib_qext_stat(struct bnxt_qplib_rcfw *rcfw, u32 fid,
|
|
int bnxt_qplib_modify_cc(struct bnxt_qplib_res *res,
|
|
struct bnxt_qplib_cc_param *cc_param);
|
|
|
|
+#define BNXT_VAR_MAX_WQE 4352
|
|
+#define BNXT_VAR_MAX_SLOT_ALIGN 256
|
|
+#define BNXT_VAR_MAX_SGE 13
|
|
+#define BNXT_RE_MAX_RQ_WQES 65536
|
|
+
|
|
+#define BNXT_STATIC_MAX_SGE 6
|
|
+
|
|
#endif /* __BNXT_QPLIB_SP_H__*/
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/roce_hsi.h b/drivers/infiniband/hw/bnxt_re/roce_hsi.h
|
|
index 2909608f4b5de4..cb4e7e19fbaf08 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/roce_hsi.h
|
|
+++ b/drivers/infiniband/hw/bnxt_re/roce_hsi.h
|
|
@@ -2157,8 +2157,36 @@ struct creq_query_func_resp_sb {
|
|
__le32 tqm_alloc_reqs[12];
|
|
__le32 max_dpi;
|
|
u8 max_sge_var_wqe;
|
|
- u8 reserved_8;
|
|
+ u8 dev_cap_ext_flags;
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_ATOMIC_OPS_NOT_SUPPORTED 0x1UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_DRV_VERSION_RGTR_SUPPORTED 0x2UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_CREATE_QP_BATCH_SUPPORTED 0x4UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_DESTROY_QP_BATCH_SUPPORTED 0x8UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_ROCE_STATS_EXT_CTX_SUPPORTED 0x10UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_CREATE_SRQ_SGE_SUPPORTED 0x20UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_FIXED_SIZE_WQE_DISABLED 0x40UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_DCN_SUPPORTED 0x80UL
|
|
__le16 max_inline_data_var_wqe;
|
|
+ __le32 start_qid;
|
|
+ u8 max_msn_table_size;
|
|
+ u8 reserved8_1;
|
|
+ __le16 dev_cap_ext_flags_2;
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_OPTIMIZE_MODIFY_QP_SUPPORTED 0x1UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_CHANGE_UDP_SRC_PORT_WQE_SUPPORTED 0x2UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_CQ_COALESCING_SUPPORTED 0x4UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_MEMORY_REGION_RO_SUPPORTED 0x8UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_MASK 0x30UL
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_SFT 4
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_PSN_TABLE (0x0UL << 4)
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_MSN_TABLE (0x1UL << 4)
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE (0x2UL << 4)
|
|
+ #define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_LAST \
|
|
+ CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE
|
|
+ __le16 max_xp_qp_size;
|
|
+ __le16 create_qp_batch_size;
|
|
+ __le16 destroy_qp_batch_size;
|
|
+ __le16 reserved16;
|
|
+ __le64 reserved64;
|
|
};
|
|
|
|
/* cmdq_set_func_resources (size:448b/56B) */
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_alloc.c b/drivers/infiniband/hw/hns/hns_roce_alloc.c
|
|
index 11a78ceae56891..950c133d4220e7 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
|
|
@@ -153,8 +153,7 @@ int hns_roce_get_kmem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
|
|
return total;
|
|
}
|
|
|
|
-int hns_roce_get_umem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
|
|
- int buf_cnt, struct ib_umem *umem,
|
|
+int hns_roce_get_umem_bufs(dma_addr_t *bufs, int buf_cnt, struct ib_umem *umem,
|
|
unsigned int page_shift)
|
|
{
|
|
struct ib_block_iter biter;
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c
|
|
index 9b91731a620795..5e0d78f4e54548 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_cq.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_cq.c
|
|
@@ -133,14 +133,12 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
|
|
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
|
|
struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
u64 mtts[MTT_MIN_COUNT] = {};
|
|
- dma_addr_t dma_handle;
|
|
int ret;
|
|
|
|
- ret = hns_roce_mtr_find(hr_dev, &hr_cq->mtr, 0, mtts, ARRAY_SIZE(mtts),
|
|
- &dma_handle);
|
|
- if (!ret) {
|
|
+ ret = hns_roce_mtr_find(hr_dev, &hr_cq->mtr, 0, mtts, ARRAY_SIZE(mtts));
|
|
+ if (ret) {
|
|
ibdev_err(ibdev, "failed to find CQ mtr, ret = %d.\n", ret);
|
|
- return -EINVAL;
|
|
+ return ret;
|
|
}
|
|
|
|
/* Get CQC memory HEM(Hardware Entry Memory) table */
|
|
@@ -157,7 +155,8 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
|
|
goto err_put;
|
|
}
|
|
|
|
- ret = hns_roce_create_cqc(hr_dev, hr_cq, mtts, dma_handle);
|
|
+ ret = hns_roce_create_cqc(hr_dev, hr_cq, mtts,
|
|
+ hns_roce_get_mtr_ba(&hr_cq->mtr));
|
|
if (ret)
|
|
goto err_xa;
|
|
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
|
|
index 21ef00fdb65631..03b6546f63cdc6 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
|
|
@@ -892,8 +892,7 @@ struct hns_roce_hw {
|
|
int (*rereg_write_mtpt)(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_mr *mr, int flags,
|
|
void *mb_buf);
|
|
- int (*frmr_write_mtpt)(struct hns_roce_dev *hr_dev, void *mb_buf,
|
|
- struct hns_roce_mr *mr);
|
|
+ int (*frmr_write_mtpt)(void *mb_buf, struct hns_roce_mr *mr);
|
|
int (*mw_write_mtpt)(void *mb_buf, struct hns_roce_mw *mw);
|
|
void (*write_cqc)(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts,
|
|
@@ -1129,8 +1128,13 @@ void hns_roce_cmd_use_polling(struct hns_roce_dev *hr_dev);
|
|
|
|
/* hns roce hw need current block and next block addr from mtt */
|
|
#define MTT_MIN_COUNT 2
|
|
+static inline dma_addr_t hns_roce_get_mtr_ba(struct hns_roce_mtr *mtr)
|
|
+{
|
|
+ return mtr->hem_cfg.root_ba;
|
|
+}
|
|
+
|
|
int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
- u32 offset, u64 *mtt_buf, int mtt_max, u64 *base_addr);
|
|
+ u32 offset, u64 *mtt_buf, int mtt_max);
|
|
int hns_roce_mtr_create(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
struct hns_roce_buf_attr *buf_attr,
|
|
unsigned int page_shift, struct ib_udata *udata,
|
|
@@ -1188,7 +1192,7 @@ struct hns_roce_buf *hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size,
|
|
int hns_roce_get_kmem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
|
|
int buf_cnt, struct hns_roce_buf *buf,
|
|
unsigned int page_shift);
|
|
-int hns_roce_get_umem_bufs(struct hns_roce_dev *hr_dev, dma_addr_t *bufs,
|
|
+int hns_roce_get_umem_bufs(dma_addr_t *bufs,
|
|
int buf_cnt, struct ib_umem *umem,
|
|
unsigned int page_shift);
|
|
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c
|
|
index 0ab514c49d5e6e..51ab6041ca91bc 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_hem.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_hem.c
|
|
@@ -986,6 +986,7 @@ struct hns_roce_hem_item {
|
|
size_t count; /* max ba numbers */
|
|
int start; /* start buf offset in this hem */
|
|
int end; /* end buf offset in this hem */
|
|
+ bool exist_bt;
|
|
};
|
|
|
|
/* All HEM items are linked in a tree structure */
|
|
@@ -1014,6 +1015,7 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
|
|
}
|
|
}
|
|
|
|
+ hem->exist_bt = exist_bt;
|
|
hem->count = count;
|
|
hem->start = start;
|
|
hem->end = end;
|
|
@@ -1024,34 +1026,32 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
|
|
}
|
|
|
|
static void hem_list_free_item(struct hns_roce_dev *hr_dev,
|
|
- struct hns_roce_hem_item *hem, bool exist_bt)
|
|
+ struct hns_roce_hem_item *hem)
|
|
{
|
|
- if (exist_bt)
|
|
+ if (hem->exist_bt)
|
|
dma_free_coherent(hr_dev->dev, hem->count * BA_BYTE_LEN,
|
|
hem->addr, hem->dma_addr);
|
|
kfree(hem);
|
|
}
|
|
|
|
static void hem_list_free_all(struct hns_roce_dev *hr_dev,
|
|
- struct list_head *head, bool exist_bt)
|
|
+ struct list_head *head)
|
|
{
|
|
struct hns_roce_hem_item *hem, *temp_hem;
|
|
|
|
list_for_each_entry_safe(hem, temp_hem, head, list) {
|
|
list_del(&hem->list);
|
|
- hem_list_free_item(hr_dev, hem, exist_bt);
|
|
+ hem_list_free_item(hr_dev, hem);
|
|
}
|
|
}
|
|
|
|
-static void hem_list_link_bt(struct hns_roce_dev *hr_dev, void *base_addr,
|
|
- u64 table_addr)
|
|
+static void hem_list_link_bt(void *base_addr, u64 table_addr)
|
|
{
|
|
*(u64 *)(base_addr) = table_addr;
|
|
}
|
|
|
|
/* assign L0 table address to hem from root bt */
|
|
-static void hem_list_assign_bt(struct hns_roce_dev *hr_dev,
|
|
- struct hns_roce_hem_item *hem, void *cpu_addr,
|
|
+static void hem_list_assign_bt(struct hns_roce_hem_item *hem, void *cpu_addr,
|
|
u64 phy_addr)
|
|
{
|
|
hem->addr = cpu_addr;
|
|
@@ -1141,6 +1141,10 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions,
|
|
|
|
for (i = 0; i < region_cnt; i++) {
|
|
r = (struct hns_roce_buf_region *)®ions[i];
|
|
+ /* when r->hopnum = 0, the region should not occupy root_ba. */
|
|
+ if (!r->hopnum)
|
|
+ continue;
|
|
+
|
|
if (r->hopnum > 1) {
|
|
step = hem_list_calc_ba_range(r->hopnum, 1, unit);
|
|
if (step > 0)
|
|
@@ -1222,8 +1226,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
|
|
if (level > 1) {
|
|
pre = hem_ptrs[level - 1];
|
|
step = (cur->start - pre->start) / step * BA_BYTE_LEN;
|
|
- hem_list_link_bt(hr_dev, pre->addr + step,
|
|
- cur->dma_addr);
|
|
+ hem_list_link_bt(pre->addr + step, cur->dma_addr);
|
|
}
|
|
}
|
|
|
|
@@ -1235,7 +1238,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
|
|
|
|
err_exit:
|
|
for (level = 1; level < hopnum; level++)
|
|
- hem_list_free_all(hr_dev, &temp_list[level], true);
|
|
+ hem_list_free_all(hr_dev, &temp_list[level]);
|
|
|
|
return ret;
|
|
}
|
|
@@ -1276,16 +1279,26 @@ static int alloc_fake_root_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
|
|
{
|
|
struct hns_roce_hem_item *hem;
|
|
|
|
+ /* This is on the has_mtt branch, if r->hopnum
|
|
+ * is 0, there is no root_ba to reuse for the
|
|
+ * region's fake hem, so a dma_alloc request is
|
|
+ * necessary here.
|
|
+ */
|
|
hem = hem_list_alloc_item(hr_dev, r->offset, r->offset + r->count - 1,
|
|
- r->count, false);
|
|
+ r->count, !r->hopnum);
|
|
if (!hem)
|
|
return -ENOMEM;
|
|
|
|
- hem_list_assign_bt(hr_dev, hem, cpu_base, phy_base);
|
|
+ /* The root_ba can be reused only when r->hopnum > 0. */
|
|
+ if (r->hopnum)
|
|
+ hem_list_assign_bt(hem, cpu_base, phy_base);
|
|
list_add(&hem->list, branch_head);
|
|
list_add(&hem->sibling, leaf_head);
|
|
|
|
- return r->count;
|
|
+ /* If r->hopnum == 0, 0 is returned,
|
|
+ * so that the root_bt entry is not occupied.
|
|
+ */
|
|
+ return r->hopnum ? r->count : 0;
|
|
}
|
|
|
|
static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
|
|
@@ -1304,7 +1317,7 @@ static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
|
|
/* if exist mid bt, link L1 to L0 */
|
|
list_for_each_entry_safe(hem, temp_hem, branch_head, list) {
|
|
offset = (hem->start - r->offset) / step * BA_BYTE_LEN;
|
|
- hem_list_link_bt(hr_dev, cpu_base + offset, hem->dma_addr);
|
|
+ hem_list_link_bt(cpu_base + offset, hem->dma_addr);
|
|
total++;
|
|
}
|
|
|
|
@@ -1329,7 +1342,7 @@ setup_root_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem_list *hem_list,
|
|
return -ENOMEM;
|
|
|
|
total = 0;
|
|
- for (i = 0; i < region_cnt && total < max_ba_num; i++) {
|
|
+ for (i = 0; i < region_cnt && total <= max_ba_num; i++) {
|
|
r = ®ions[i];
|
|
if (!r->count)
|
|
continue;
|
|
@@ -1395,9 +1408,9 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
|
|
region_cnt);
|
|
if (ret) {
|
|
for (i = 0; i < region_cnt; i++)
|
|
- hem_list_free_all(hr_dev, &head.branch[i], false);
|
|
+ hem_list_free_all(hr_dev, &head.branch[i]);
|
|
|
|
- hem_list_free_all(hr_dev, &head.root, true);
|
|
+ hem_list_free_all(hr_dev, &head.root);
|
|
}
|
|
|
|
return ret;
|
|
@@ -1460,10 +1473,9 @@ void hns_roce_hem_list_release(struct hns_roce_dev *hr_dev,
|
|
|
|
for (i = 0; i < HNS_ROCE_MAX_BT_REGION; i++)
|
|
for (j = 0; j < HNS_ROCE_MAX_BT_LEVEL; j++)
|
|
- hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j],
|
|
- j != 0);
|
|
+ hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j]);
|
|
|
|
- hem_list_free_all(hr_dev, &hem_list->root_bt, true);
|
|
+ hem_list_free_all(hr_dev, &hem_list->root_bt);
|
|
INIT_LIST_HEAD(&hem_list->btm_bt);
|
|
hem_list->root_ba = 0;
|
|
}
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
|
|
index 2824d390ec3161..aded0a7f42838d 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
|
|
@@ -471,7 +471,7 @@ static inline int set_ud_wqe(struct hns_roce_qp *qp,
|
|
valid_num_sge = calc_wr_sge_num(wr, &msg_len);
|
|
|
|
ret = set_ud_opcode(ud_sq_wqe, wr);
|
|
- if (WARN_ON(ret))
|
|
+ if (WARN_ON_ONCE(ret))
|
|
return ret;
|
|
|
|
ud_sq_wqe->msg_len = cpu_to_le32(msg_len);
|
|
@@ -575,7 +575,7 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp,
|
|
rc_sq_wqe->msg_len = cpu_to_le32(msg_len);
|
|
|
|
ret = set_rc_opcode(hr_dev, rc_sq_wqe, wr);
|
|
- if (WARN_ON(ret))
|
|
+ if (WARN_ON_ONCE(ret))
|
|
return ret;
|
|
|
|
hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SO,
|
|
@@ -673,6 +673,10 @@ static void write_dwqe(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp,
|
|
#define HNS_ROCE_SL_SHIFT 2
|
|
struct hns_roce_v2_rc_send_wqe *rc_sq_wqe = wqe;
|
|
|
|
+ if (unlikely(qp->state == IB_QPS_ERR)) {
|
|
+ flush_cqe(hr_dev, qp);
|
|
+ return;
|
|
+ }
|
|
/* All kinds of DirectWQE have the same header field layout */
|
|
hr_reg_enable(rc_sq_wqe, RC_SEND_WQE_FLAG);
|
|
hr_reg_write(rc_sq_wqe, RC_SEND_WQE_DB_SL_L, qp->sl);
|
|
@@ -3181,21 +3185,22 @@ static int set_mtpt_pbl(struct hns_roce_dev *hr_dev,
|
|
u64 pages[HNS_ROCE_V2_MAX_INNER_MTPT_NUM] = { 0 };
|
|
struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
dma_addr_t pbl_ba;
|
|
- int i, count;
|
|
+ int ret;
|
|
+ int i;
|
|
|
|
- count = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages,
|
|
- min_t(int, ARRAY_SIZE(pages), mr->npages),
|
|
- &pbl_ba);
|
|
- if (count < 1) {
|
|
- ibdev_err(ibdev, "failed to find PBL mtr, count = %d.\n",
|
|
- count);
|
|
- return -ENOBUFS;
|
|
+ ret = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages,
|
|
+ min_t(int, ARRAY_SIZE(pages), mr->npages));
|
|
+ if (ret) {
|
|
+ ibdev_err(ibdev, "failed to find PBL mtr, ret = %d.\n", ret);
|
|
+ return ret;
|
|
}
|
|
|
|
/* Aligned to the hardware address access unit */
|
|
- for (i = 0; i < count; i++)
|
|
+ for (i = 0; i < ARRAY_SIZE(pages); i++)
|
|
pages[i] >>= 6;
|
|
|
|
+ pbl_ba = hns_roce_get_mtr_ba(&mr->pbl_mtr);
|
|
+
|
|
mpt_entry->pbl_size = cpu_to_le32(mr->npages);
|
|
mpt_entry->pbl_ba_l = cpu_to_le32(pbl_ba >> 3);
|
|
hr_reg_write(mpt_entry, MPT_PBL_BA_H, upper_32_bits(pbl_ba >> 3));
|
|
@@ -3291,21 +3296,14 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
|
|
return ret;
|
|
}
|
|
|
|
-static int hns_roce_v2_frmr_write_mtpt(struct hns_roce_dev *hr_dev,
|
|
- void *mb_buf, struct hns_roce_mr *mr)
|
|
+static int hns_roce_v2_frmr_write_mtpt(void *mb_buf, struct hns_roce_mr *mr)
|
|
{
|
|
- struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
+ dma_addr_t pbl_ba = hns_roce_get_mtr_ba(&mr->pbl_mtr);
|
|
struct hns_roce_v2_mpt_entry *mpt_entry;
|
|
- dma_addr_t pbl_ba = 0;
|
|
|
|
mpt_entry = mb_buf;
|
|
memset(mpt_entry, 0, sizeof(*mpt_entry));
|
|
|
|
- if (hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, NULL, 0, &pbl_ba) < 0) {
|
|
- ibdev_err(ibdev, "failed to find frmr mtr.\n");
|
|
- return -ENOBUFS;
|
|
- }
|
|
-
|
|
hr_reg_write(mpt_entry, MPT_ST, V2_MPT_ST_FREE);
|
|
hr_reg_write(mpt_entry, MPT_PD, mr->pd);
|
|
|
|
@@ -4213,8 +4211,7 @@ static void set_access_flags(struct hns_roce_qp *hr_qp,
|
|
}
|
|
|
|
static void set_qpc_wqe_cnt(struct hns_roce_qp *hr_qp,
|
|
- struct hns_roce_v2_qp_context *context,
|
|
- struct hns_roce_v2_qp_context *qpc_mask)
|
|
+ struct hns_roce_v2_qp_context *context)
|
|
{
|
|
hr_reg_write(context, QPC_SGE_SHIFT,
|
|
to_hr_hem_entries_shift(hr_qp->sge.sge_cnt,
|
|
@@ -4236,7 +4233,6 @@ static inline int get_pdn(struct ib_pd *ib_pd)
|
|
}
|
|
|
|
static void modify_qp_reset_to_init(struct ib_qp *ibqp,
|
|
- const struct ib_qp_attr *attr,
|
|
struct hns_roce_v2_qp_context *context,
|
|
struct hns_roce_v2_qp_context *qpc_mask)
|
|
{
|
|
@@ -4255,7 +4251,7 @@ static void modify_qp_reset_to_init(struct ib_qp *ibqp,
|
|
|
|
hr_reg_write(context, QPC_RQWS, ilog2(hr_qp->rq.max_gs));
|
|
|
|
- set_qpc_wqe_cnt(hr_qp, context, qpc_mask);
|
|
+ set_qpc_wqe_cnt(hr_qp, context);
|
|
|
|
/* No VLAN need to set 0xFFF */
|
|
hr_reg_write(context, QPC_VLAN_ID, 0xfff);
|
|
@@ -4296,7 +4292,6 @@ static void modify_qp_reset_to_init(struct ib_qp *ibqp,
|
|
}
|
|
|
|
static void modify_qp_init_to_init(struct ib_qp *ibqp,
|
|
- const struct ib_qp_attr *attr,
|
|
struct hns_roce_v2_qp_context *context,
|
|
struct hns_roce_v2_qp_context *qpc_mask)
|
|
{
|
|
@@ -4333,17 +4328,20 @@ static int config_qp_rq_buf(struct hns_roce_dev *hr_dev,
|
|
{
|
|
u64 mtts[MTT_MIN_COUNT] = { 0 };
|
|
u64 wqe_sge_ba;
|
|
- int count;
|
|
+ int ret;
|
|
|
|
/* Search qp buf's mtts */
|
|
- count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, mtts,
|
|
- MTT_MIN_COUNT, &wqe_sge_ba);
|
|
- if (hr_qp->rq.wqe_cnt && count < 1) {
|
|
+ ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->rq.offset, mtts,
|
|
+ MTT_MIN_COUNT);
|
|
+ if (hr_qp->rq.wqe_cnt && ret) {
|
|
ibdev_err(&hr_dev->ib_dev,
|
|
- "failed to find RQ WQE, QPN = 0x%lx.\n", hr_qp->qpn);
|
|
- return -EINVAL;
|
|
+ "failed to find QP(0x%lx) RQ WQE buf, ret = %d.\n",
|
|
+ hr_qp->qpn, ret);
|
|
+ return ret;
|
|
}
|
|
|
|
+ wqe_sge_ba = hns_roce_get_mtr_ba(&hr_qp->mtr);
|
|
+
|
|
context->wqe_sge_ba = cpu_to_le32(wqe_sge_ba >> 3);
|
|
qpc_mask->wqe_sge_ba = 0;
|
|
|
|
@@ -4407,23 +4405,23 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev,
|
|
struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
u64 sge_cur_blk = 0;
|
|
u64 sq_cur_blk = 0;
|
|
- int count;
|
|
+ int ret;
|
|
|
|
/* search qp buf's mtts */
|
|
- count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, 0, &sq_cur_blk, 1, NULL);
|
|
- if (count < 1) {
|
|
- ibdev_err(ibdev, "failed to find QP(0x%lx) SQ buf.\n",
|
|
- hr_qp->qpn);
|
|
- return -EINVAL;
|
|
+ ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr, hr_qp->sq.offset,
|
|
+ &sq_cur_blk, 1);
|
|
+ if (ret) {
|
|
+ ibdev_err(ibdev, "failed to find QP(0x%lx) SQ WQE buf, ret = %d.\n",
|
|
+ hr_qp->qpn, ret);
|
|
+ return ret;
|
|
}
|
|
if (hr_qp->sge.sge_cnt > 0) {
|
|
- count = hns_roce_mtr_find(hr_dev, &hr_qp->mtr,
|
|
- hr_qp->sge.offset,
|
|
- &sge_cur_blk, 1, NULL);
|
|
- if (count < 1) {
|
|
- ibdev_err(ibdev, "failed to find QP(0x%lx) SGE buf.\n",
|
|
- hr_qp->qpn);
|
|
- return -EINVAL;
|
|
+ ret = hns_roce_mtr_find(hr_dev, &hr_qp->mtr,
|
|
+ hr_qp->sge.offset, &sge_cur_blk, 1);
|
|
+ if (ret) {
|
|
+ ibdev_err(ibdev, "failed to find QP(0x%lx) SGE buf, ret = %d.\n",
|
|
+ hr_qp->qpn, ret);
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
@@ -4614,8 +4612,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
|
|
return 0;
|
|
}
|
|
|
|
-static int modify_qp_rtr_to_rts(struct ib_qp *ibqp,
|
|
- const struct ib_qp_attr *attr, int attr_mask,
|
|
+static int modify_qp_rtr_to_rts(struct ib_qp *ibqp, int attr_mask,
|
|
struct hns_roce_v2_qp_context *context,
|
|
struct hns_roce_v2_qp_context *qpc_mask)
|
|
{
|
|
@@ -4984,15 +4981,14 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp,
|
|
|
|
if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
|
|
memset(qpc_mask, 0, hr_dev->caps.qpc_sz);
|
|
- modify_qp_reset_to_init(ibqp, attr, context, qpc_mask);
|
|
+ modify_qp_reset_to_init(ibqp, context, qpc_mask);
|
|
} else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_INIT) {
|
|
- modify_qp_init_to_init(ibqp, attr, context, qpc_mask);
|
|
+ modify_qp_init_to_init(ibqp, context, qpc_mask);
|
|
} else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
|
|
ret = modify_qp_init_to_rtr(ibqp, attr, attr_mask, context,
|
|
qpc_mask, udata);
|
|
} else if (cur_state == IB_QPS_RTR && new_state == IB_QPS_RTS) {
|
|
- ret = modify_qp_rtr_to_rts(ibqp, attr, attr_mask, context,
|
|
- qpc_mask);
|
|
+ ret = modify_qp_rtr_to_rts(ibqp, attr_mask, context, qpc_mask);
|
|
}
|
|
|
|
return ret;
|
|
@@ -5550,18 +5546,20 @@ static int hns_roce_v2_write_srqc_index_queue(struct hns_roce_srq *srq,
|
|
struct ib_device *ibdev = srq->ibsrq.device;
|
|
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
|
|
u64 mtts_idx[MTT_MIN_COUNT] = {};
|
|
- dma_addr_t dma_handle_idx = 0;
|
|
+ dma_addr_t dma_handle_idx;
|
|
int ret;
|
|
|
|
/* Get physical address of idx que buf */
|
|
ret = hns_roce_mtr_find(hr_dev, &idx_que->mtr, 0, mtts_idx,
|
|
- ARRAY_SIZE(mtts_idx), &dma_handle_idx);
|
|
- if (ret < 1) {
|
|
+ ARRAY_SIZE(mtts_idx));
|
|
+ if (ret) {
|
|
ibdev_err(ibdev, "failed to find mtr for SRQ idx, ret = %d.\n",
|
|
ret);
|
|
- return -ENOBUFS;
|
|
+ return ret;
|
|
}
|
|
|
|
+ dma_handle_idx = hns_roce_get_mtr_ba(&idx_que->mtr);
|
|
+
|
|
hr_reg_write(ctx, SRQC_IDX_HOP_NUM,
|
|
to_hr_hem_hopnum(hr_dev->caps.idx_hop_num, srq->wqe_cnt));
|
|
|
|
@@ -5593,20 +5591,22 @@ static int hns_roce_v2_write_srqc(struct hns_roce_srq *srq, void *mb_buf)
|
|
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
|
|
struct hns_roce_srq_context *ctx = mb_buf;
|
|
u64 mtts_wqe[MTT_MIN_COUNT] = {};
|
|
- dma_addr_t dma_handle_wqe = 0;
|
|
+ dma_addr_t dma_handle_wqe;
|
|
int ret;
|
|
|
|
memset(ctx, 0, sizeof(*ctx));
|
|
|
|
/* Get the physical address of srq buf */
|
|
ret = hns_roce_mtr_find(hr_dev, &srq->buf_mtr, 0, mtts_wqe,
|
|
- ARRAY_SIZE(mtts_wqe), &dma_handle_wqe);
|
|
- if (ret < 1) {
|
|
+ ARRAY_SIZE(mtts_wqe));
|
|
+ if (ret) {
|
|
ibdev_err(ibdev, "failed to find mtr for SRQ WQE, ret = %d.\n",
|
|
ret);
|
|
- return -ENOBUFS;
|
|
+ return ret;
|
|
}
|
|
|
|
+ dma_handle_wqe = hns_roce_get_mtr_ba(&srq->buf_mtr);
|
|
+
|
|
hr_reg_write(ctx, SRQC_SRQ_ST, 1);
|
|
hr_reg_write_bool(ctx, SRQC_SRQ_TYPE,
|
|
srq->ibsrq.srq_type == IB_SRQT_XRC);
|
|
@@ -6327,7 +6327,7 @@ static int config_eqc(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq,
|
|
u64 eqe_ba[MTT_MIN_COUNT] = { 0 };
|
|
struct hns_roce_eq_context *eqc;
|
|
u64 bt_ba = 0;
|
|
- int count;
|
|
+ int ret;
|
|
|
|
eqc = mb_buf;
|
|
memset(eqc, 0, sizeof(struct hns_roce_eq_context));
|
|
@@ -6335,13 +6335,15 @@ static int config_eqc(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq,
|
|
init_eq_config(hr_dev, eq);
|
|
|
|
/* if not multi-hop, eqe buffer only use one trunk */
|
|
- count = hns_roce_mtr_find(hr_dev, &eq->mtr, 0, eqe_ba, MTT_MIN_COUNT,
|
|
- &bt_ba);
|
|
- if (count < 1) {
|
|
- dev_err(hr_dev->dev, "failed to find EQE mtr\n");
|
|
- return -ENOBUFS;
|
|
+ ret = hns_roce_mtr_find(hr_dev, &eq->mtr, 0, eqe_ba,
|
|
+ ARRAY_SIZE(eqe_ba));
|
|
+ if (ret) {
|
|
+ dev_err(hr_dev->dev, "failed to find EQE mtr, ret = %d\n", ret);
|
|
+ return ret;
|
|
}
|
|
|
|
+ bt_ba = hns_roce_get_mtr_ba(&eq->mtr);
|
|
+
|
|
hr_reg_write(eqc, EQC_EQ_ST, HNS_ROCE_V2_EQ_STATE_VALID);
|
|
hr_reg_write(eqc, EQC_EQE_HOP_NUM, eq->hop_num);
|
|
hr_reg_write(eqc, EQC_OVER_IGNORE, eq->over_ignore);
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
|
|
index 7f29a55d378f02..408ef2a9614927 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
|
|
@@ -154,7 +154,7 @@ static int hns_roce_mr_enable(struct hns_roce_dev *hr_dev,
|
|
if (mr->type != MR_TYPE_FRMR)
|
|
ret = hr_dev->hw->write_mtpt(hr_dev, mailbox->buf, mr);
|
|
else
|
|
- ret = hr_dev->hw->frmr_write_mtpt(hr_dev, mailbox->buf, mr);
|
|
+ ret = hr_dev->hw->frmr_write_mtpt(mailbox->buf, mr);
|
|
if (ret) {
|
|
dev_err(dev, "failed to write mtpt, ret = %d.\n", ret);
|
|
goto err_page;
|
|
@@ -714,7 +714,7 @@ static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
return -ENOMEM;
|
|
|
|
if (mtr->umem)
|
|
- npage = hns_roce_get_umem_bufs(hr_dev, pages, page_count,
|
|
+ npage = hns_roce_get_umem_bufs(pages, page_count,
|
|
mtr->umem, page_shift);
|
|
else
|
|
npage = hns_roce_get_kmem_bufs(hr_dev, pages, page_count,
|
|
@@ -767,11 +767,6 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
for (i = 0, mapped_cnt = 0; i < mtr->hem_cfg.region_count &&
|
|
mapped_cnt < page_cnt; i++) {
|
|
r = &mtr->hem_cfg.region[i];
|
|
- /* if hopnum is 0, no need to map pages in this region */
|
|
- if (!r->hopnum) {
|
|
- mapped_cnt += r->count;
|
|
- continue;
|
|
- }
|
|
|
|
if (r->offset + r->count > page_cnt) {
|
|
ret = -EINVAL;
|
|
@@ -802,47 +797,53 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
return ret;
|
|
}
|
|
|
|
-int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
- u32 offset, u64 *mtt_buf, int mtt_max, u64 *base_addr)
|
|
+static int hns_roce_get_direct_addr_mtt(struct hns_roce_hem_cfg *cfg,
|
|
+ u32 start_index, u64 *mtt_buf,
|
|
+ int mtt_cnt)
|
|
{
|
|
- struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;
|
|
- int mtt_count, left;
|
|
- u32 start_index;
|
|
+ int mtt_count;
|
|
int total = 0;
|
|
- __le64 *mtts;
|
|
u32 npage;
|
|
u64 addr;
|
|
|
|
- if (!mtt_buf || mtt_max < 1)
|
|
- goto done;
|
|
-
|
|
- /* no mtt memory in direct mode, so just return the buffer address */
|
|
- if (cfg->is_direct) {
|
|
- start_index = offset >> HNS_HW_PAGE_SHIFT;
|
|
- for (mtt_count = 0; mtt_count < cfg->region_count &&
|
|
- total < mtt_max; mtt_count++) {
|
|
- npage = cfg->region[mtt_count].offset;
|
|
- if (npage < start_index)
|
|
- continue;
|
|
+ if (mtt_cnt > cfg->region_count)
|
|
+ return -EINVAL;
|
|
|
|
- addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT);
|
|
- mtt_buf[total] = addr;
|
|
+ for (mtt_count = 0; mtt_count < cfg->region_count && total < mtt_cnt;
|
|
+ mtt_count++) {
|
|
+ npage = cfg->region[mtt_count].offset;
|
|
+ if (npage < start_index)
|
|
+ continue;
|
|
|
|
- total++;
|
|
- }
|
|
+ addr = cfg->root_ba + (npage << HNS_HW_PAGE_SHIFT);
|
|
+ mtt_buf[total] = addr;
|
|
|
|
- goto done;
|
|
+ total++;
|
|
}
|
|
|
|
- start_index = offset >> cfg->buf_pg_shift;
|
|
- left = mtt_max;
|
|
+ if (!total)
|
|
+ return -ENOENT;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int hns_roce_get_mhop_mtt(struct hns_roce_dev *hr_dev,
|
|
+ struct hns_roce_mtr *mtr, u32 start_index,
|
|
+ u64 *mtt_buf, int mtt_cnt)
|
|
+{
|
|
+ int left = mtt_cnt;
|
|
+ int total = 0;
|
|
+ int mtt_count;
|
|
+ __le64 *mtts;
|
|
+ u32 npage;
|
|
+
|
|
while (left > 0) {
|
|
mtt_count = 0;
|
|
mtts = hns_roce_hem_list_find_mtt(hr_dev, &mtr->hem_list,
|
|
start_index + total,
|
|
&mtt_count);
|
|
if (!mtts || !mtt_count)
|
|
- goto done;
|
|
+ break;
|
|
|
|
npage = min(mtt_count, left);
|
|
left -= npage;
|
|
@@ -850,11 +851,33 @@ int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
mtt_buf[total++] = le64_to_cpu(mtts[mtt_count]);
|
|
}
|
|
|
|
-done:
|
|
- if (base_addr)
|
|
- *base_addr = cfg->root_ba;
|
|
+ if (!total)
|
|
+ return -ENOENT;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
- return total;
|
|
+int hns_roce_mtr_find(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
|
|
+ u32 offset, u64 *mtt_buf, int mtt_max)
|
|
+{
|
|
+ struct hns_roce_hem_cfg *cfg = &mtr->hem_cfg;
|
|
+ u32 start_index;
|
|
+ int ret;
|
|
+
|
|
+ if (!mtt_buf || mtt_max < 1)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* no mtt memory in direct mode, so just return the buffer address */
|
|
+ if (cfg->is_direct) {
|
|
+ start_index = offset >> HNS_HW_PAGE_SHIFT;
|
|
+ ret = hns_roce_get_direct_addr_mtt(cfg, start_index,
|
|
+ mtt_buf, mtt_max);
|
|
+ } else {
|
|
+ start_index = offset >> cfg->buf_pg_shift;
|
|
+ ret = hns_roce_get_mhop_mtt(hr_dev, mtr, start_index,
|
|
+ mtt_buf, mtt_max);
|
|
+ }
|
|
+ return ret;
|
|
}
|
|
|
|
static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev,
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
|
|
index 88a4777d29f8b8..97d79c8d5cd069 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
|
|
@@ -1075,7 +1075,6 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
|
|
}
|
|
|
|
static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
|
- struct ib_pd *ib_pd,
|
|
struct ib_qp_init_attr *init_attr,
|
|
struct ib_udata *udata,
|
|
struct hns_roce_qp *hr_qp)
|
|
@@ -1229,7 +1228,6 @@ int hns_roce_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
|
|
struct ib_device *ibdev = qp->device;
|
|
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
|
|
struct hns_roce_qp *hr_qp = to_hr_qp(qp);
|
|
- struct ib_pd *pd = qp->pd;
|
|
int ret;
|
|
|
|
ret = check_qp_type(hr_dev, init_attr->qp_type, !!udata);
|
|
@@ -1244,7 +1242,7 @@ int hns_roce_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
|
|
hr_qp->phy_port = hr_dev->iboe.phy_port[hr_qp->port];
|
|
}
|
|
|
|
- ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata, hr_qp);
|
|
+ ret = hns_roce_create_qp_common(hr_dev, init_attr, udata, hr_qp);
|
|
if (ret)
|
|
ibdev_err(ibdev, "create QP type 0x%x failed(%d)\n",
|
|
init_attr->qp_type, ret);
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c
|
|
index 652508b660a060..80fcb1b0e8fdcf 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_srq.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_srq.c
|
|
@@ -249,7 +249,7 @@ static void free_srq_wqe_buf(struct hns_roce_dev *hr_dev,
|
|
hns_roce_mtr_destroy(hr_dev, &srq->buf_mtr);
|
|
}
|
|
|
|
-static int alloc_srq_wrid(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
|
|
+static int alloc_srq_wrid(struct hns_roce_srq *srq)
|
|
{
|
|
srq->wrid = kvmalloc_array(srq->wqe_cnt, sizeof(u64), GFP_KERNEL);
|
|
if (!srq->wrid)
|
|
@@ -365,7 +365,7 @@ static int alloc_srq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq,
|
|
goto err_idx;
|
|
|
|
if (!udata) {
|
|
- ret = alloc_srq_wrid(hr_dev, srq);
|
|
+ ret = alloc_srq_wrid(srq);
|
|
if (ret)
|
|
goto err_wqe_buf;
|
|
}
|
|
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
|
|
index c510484e024b1a..ada7dbf8eb1cf5 100644
|
|
--- a/drivers/infiniband/hw/mlx5/main.c
|
|
+++ b/drivers/infiniband/hw/mlx5/main.c
|
|
@@ -3372,7 +3372,8 @@ static int mlx5_ib_init_multiport_master(struct mlx5_ib_dev *dev)
|
|
list_for_each_entry(mpi, &mlx5_ib_unaffiliated_port_list,
|
|
list) {
|
|
if (dev->sys_image_guid == mpi->sys_image_guid &&
|
|
- (mlx5_core_native_port_num(mpi->mdev) - 1) == i) {
|
|
+ (mlx5_core_native_port_num(mpi->mdev) - 1) == i &&
|
|
+ mlx5_core_same_coredev_type(dev->mdev, mpi->mdev)) {
|
|
bound = mlx5_ib_bind_slave_port(dev, mpi);
|
|
}
|
|
|
|
@@ -4406,7 +4407,8 @@ static int mlx5r_mp_probe(struct auxiliary_device *adev,
|
|
|
|
mutex_lock(&mlx5_ib_multiport_mutex);
|
|
list_for_each_entry(dev, &mlx5_ib_dev_list, ib_dev_list) {
|
|
- if (dev->sys_image_guid == mpi->sys_image_guid)
|
|
+ if (dev->sys_image_guid == mpi->sys_image_guid &&
|
|
+ mlx5_core_same_coredev_type(dev->mdev, mpi->mdev))
|
|
bound = mlx5_ib_bind_slave_port(dev, mpi);
|
|
|
|
if (bound) {
|
|
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
|
|
index 758a3d9c2844d1..84d1654148d764 100644
|
|
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
|
|
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
|
|
@@ -346,6 +346,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
|
|
struct rtrs_srv_mr *srv_mr;
|
|
bool need_inval = false;
|
|
enum ib_send_flags flags;
|
|
+ struct ib_sge list;
|
|
u32 imm;
|
|
int err;
|
|
|
|
@@ -398,7 +399,6 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
|
|
imm = rtrs_to_io_rsp_imm(id->msg_id, errno, need_inval);
|
|
imm_wr.wr.next = NULL;
|
|
if (always_invalidate) {
|
|
- struct ib_sge list;
|
|
struct rtrs_msg_rkey_rsp *msg;
|
|
|
|
srv_mr = &srv_path->mrs[id->msg_id];
|
|
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
|
|
index 412196a7dad587..2c6c50348afd19 100644
|
|
--- a/drivers/irqchip/irq-gic.c
|
|
+++ b/drivers/irqchip/irq-gic.c
|
|
@@ -64,7 +64,7 @@ static void gic_check_cpu_features(void)
|
|
|
|
union gic_base {
|
|
void __iomem *common_base;
|
|
- void __percpu * __iomem *percpu_base;
|
|
+ void __iomem * __percpu *percpu_base;
|
|
};
|
|
|
|
struct gic_chip_data {
|
|
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
|
|
index a44d4b3e5beb22..82102a4c5d6883 100644
|
|
--- a/drivers/mailbox/pcc.c
|
|
+++ b/drivers/mailbox/pcc.c
|
|
@@ -91,6 +91,14 @@ struct pcc_chan_reg {
|
|
* @cmd_update: PCC register bundle for the command complete update register
|
|
* @error: PCC register bundle for the error status register
|
|
* @plat_irq: platform interrupt
|
|
+ * @type: PCC subspace type
|
|
+ * @plat_irq_flags: platform interrupt flags
|
|
+ * @chan_in_use: this flag is used just to check if the interrupt needs
|
|
+ * handling when it is shared. Since only one transfer can occur
|
|
+ * at a time and mailbox takes care of locking, this flag can be
|
|
+ * accessed without a lock. Note: the type only support the
|
|
+ * communication from OSPM to Platform, like type3, use it, and
|
|
+ * other types completely ignore it.
|
|
*/
|
|
struct pcc_chan_info {
|
|
struct pcc_mbox_chan chan;
|
|
@@ -100,12 +108,17 @@ struct pcc_chan_info {
|
|
struct pcc_chan_reg cmd_update;
|
|
struct pcc_chan_reg error;
|
|
int plat_irq;
|
|
+ u8 type;
|
|
+ unsigned int plat_irq_flags;
|
|
+ bool chan_in_use;
|
|
};
|
|
|
|
#define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan)
|
|
static struct pcc_chan_info *chan_info;
|
|
static int pcc_chan_count;
|
|
|
|
+static int pcc_send_data(struct mbox_chan *chan, void *data);
|
|
+
|
|
/*
|
|
* PCC can be used with perf critical drivers such as CPPC
|
|
* So it makes sense to locally cache the virtual address and
|
|
@@ -221,6 +234,70 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags)
|
|
return acpi_register_gsi(NULL, interrupt, trigger, polarity);
|
|
}
|
|
|
|
+static bool pcc_chan_plat_irq_can_be_shared(struct pcc_chan_info *pchan)
|
|
+{
|
|
+ return (pchan->plat_irq_flags & ACPI_PCCT_INTERRUPT_MODE) ==
|
|
+ ACPI_LEVEL_SENSITIVE;
|
|
+}
|
|
+
|
|
+static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan)
|
|
+{
|
|
+ u64 val;
|
|
+ int ret;
|
|
+
|
|
+ ret = pcc_chan_reg_read(&pchan->cmd_complete, &val);
|
|
+ if (ret)
|
|
+ return false;
|
|
+
|
|
+ if (!pchan->cmd_complete.gas)
|
|
+ return true;
|
|
+
|
|
+ /*
|
|
+ * Judge if the channel respond the interrupt based on the value of
|
|
+ * command complete.
|
|
+ */
|
|
+ val &= pchan->cmd_complete.status_mask;
|
|
+
|
|
+ /*
|
|
+ * If this is PCC slave subspace channel, and the command complete
|
|
+ * bit 0 indicates that Platform is sending a notification and OSPM
|
|
+ * needs to respond this interrupt to process this command.
|
|
+ */
|
|
+ if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
|
|
+ return !val;
|
|
+
|
|
+ return !!val;
|
|
+}
|
|
+
|
|
+static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan)
|
|
+{
|
|
+ struct acpi_pcct_ext_pcc_shared_memory pcc_hdr;
|
|
+
|
|
+ if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
|
|
+ return;
|
|
+ /* If the memory region has not been mapped, we cannot
|
|
+ * determine if we need to send the message, but we still
|
|
+ * need to set the cmd_update flag before returning.
|
|
+ */
|
|
+ if (pchan->chan.shmem == NULL) {
|
|
+ pcc_chan_reg_read_modify_write(&pchan->cmd_update);
|
|
+ return;
|
|
+ }
|
|
+ memcpy_fromio(&pcc_hdr, pchan->chan.shmem,
|
|
+ sizeof(struct acpi_pcct_ext_pcc_shared_memory));
|
|
+ /*
|
|
+ * The PCC slave subspace channel needs to set the command complete bit
|
|
+ * after processing message. If the PCC_ACK_FLAG is set, it should also
|
|
+ * ring the doorbell.
|
|
+ *
|
|
+ * The PCC master subspace channel clears chan_in_use to free channel.
|
|
+ */
|
|
+ if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK)
|
|
+ pcc_send_data(chan, NULL);
|
|
+ else
|
|
+ pcc_chan_reg_read_modify_write(&pchan->cmd_update);
|
|
+}
|
|
+
|
|
/**
|
|
* pcc_mbox_irq - PCC mailbox interrupt handler
|
|
* @irq: interrupt number
|
|
@@ -236,16 +313,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
|
|
int ret;
|
|
|
|
pchan = chan->con_priv;
|
|
-
|
|
- ret = pcc_chan_reg_read(&pchan->cmd_complete, &val);
|
|
- if (ret)
|
|
+ if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE &&
|
|
+ !pchan->chan_in_use)
|
|
return IRQ_NONE;
|
|
|
|
- if (val) { /* Ensure GAS exists and value is non-zero */
|
|
- val &= pchan->cmd_complete.status_mask;
|
|
- if (!val)
|
|
- return IRQ_NONE;
|
|
- }
|
|
+ if (!pcc_mbox_cmd_complete_check(pchan))
|
|
+ return IRQ_NONE;
|
|
|
|
ret = pcc_chan_reg_read(&pchan->error, &val);
|
|
if (ret)
|
|
@@ -262,6 +335,9 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
|
|
|
|
mbox_chan_received_data(chan, NULL);
|
|
|
|
+ check_and_ack(pchan, chan);
|
|
+ pchan->chan_in_use = false;
|
|
+
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
@@ -311,14 +387,37 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
|
|
void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
|
|
{
|
|
struct mbox_chan *chan = pchan->mchan;
|
|
+ struct pcc_chan_info *pchan_info;
|
|
+ struct pcc_mbox_chan *pcc_mbox_chan;
|
|
|
|
if (!chan || !chan->cl)
|
|
return;
|
|
+ pchan_info = chan->con_priv;
|
|
+ pcc_mbox_chan = &pchan_info->chan;
|
|
+ if (pcc_mbox_chan->shmem) {
|
|
+ iounmap(pcc_mbox_chan->shmem);
|
|
+ pcc_mbox_chan->shmem = NULL;
|
|
+ }
|
|
|
|
mbox_free_channel(chan);
|
|
}
|
|
EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
|
|
|
|
+int pcc_mbox_ioremap(struct mbox_chan *chan)
|
|
+{
|
|
+ struct pcc_chan_info *pchan_info;
|
|
+ struct pcc_mbox_chan *pcc_mbox_chan;
|
|
+
|
|
+ if (!chan || !chan->cl)
|
|
+ return -1;
|
|
+ pchan_info = chan->con_priv;
|
|
+ pcc_mbox_chan = &pchan_info->chan;
|
|
+ pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr,
|
|
+ pcc_mbox_chan->shmem_size);
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(pcc_mbox_ioremap);
|
|
+
|
|
/**
|
|
* pcc_send_data - Called from Mailbox Controller code. Used
|
|
* here only to ring the channel doorbell. The PCC client
|
|
@@ -340,7 +439,11 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- return pcc_chan_reg_read_modify_write(&pchan->db);
|
|
+ ret = pcc_chan_reg_read_modify_write(&pchan->db);
|
|
+ if (!ret && pchan->plat_irq > 0)
|
|
+ pchan->chan_in_use = true;
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
/**
|
|
@@ -353,11 +456,14 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
|
|
static int pcc_startup(struct mbox_chan *chan)
|
|
{
|
|
struct pcc_chan_info *pchan = chan->con_priv;
|
|
+ unsigned long irqflags;
|
|
int rc;
|
|
|
|
if (pchan->plat_irq > 0) {
|
|
- rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0,
|
|
- MBOX_IRQ_NAME, chan);
|
|
+ irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ?
|
|
+ IRQF_SHARED | IRQF_ONESHOT : 0;
|
|
+ rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq,
|
|
+ irqflags, MBOX_IRQ_NAME, chan);
|
|
if (unlikely(rc)) {
|
|
dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n",
|
|
pchan->plat_irq);
|
|
@@ -463,6 +569,7 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
|
|
pcct_ss->platform_interrupt);
|
|
return -EINVAL;
|
|
}
|
|
+ pchan->plat_irq_flags = pcct_ss->flags;
|
|
|
|
if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) {
|
|
struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss;
|
|
@@ -484,6 +591,12 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan,
|
|
"PLAT IRQ ACK");
|
|
}
|
|
|
|
+ if (pcc_chan_plat_irq_can_be_shared(pchan) &&
|
|
+ !pchan->plat_irq_ack.gas) {
|
|
+ pr_err("PCC subspace has level IRQ with no ACK register\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -698,6 +811,7 @@ static int pcc_mbox_probe(struct platform_device *pdev)
|
|
|
|
pcc_parse_subspace_shmem(pchan, pcct_entry);
|
|
|
|
+ pchan->type = pcct_entry->type;
|
|
pcct_entry = (struct acpi_subtable_header *)
|
|
((unsigned long) pcct_entry + pcct_entry->length);
|
|
}
|
|
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
|
|
index 5a3e933df63352..1b05890f99f4f4 100644
|
|
--- a/drivers/media/usb/uvc/uvc_driver.c
|
|
+++ b/drivers/media/usb/uvc/uvc_driver.c
|
|
@@ -2519,6 +2519,28 @@ static const struct usb_device_id uvc_ids[] = {
|
|
.bInterfaceSubClass = 1,
|
|
.bInterfaceProtocol = UVC_PC_PROTOCOL_15,
|
|
.driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited },
|
|
+ /* Quanta ACER HD User Facing */
|
|
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
|
|
+ | USB_DEVICE_ID_MATCH_INT_INFO,
|
|
+ .idVendor = 0x0408,
|
|
+ .idProduct = 0x4033,
|
|
+ .bInterfaceClass = USB_CLASS_VIDEO,
|
|
+ .bInterfaceSubClass = 1,
|
|
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_15,
|
|
+ .driver_info = (kernel_ulong_t)&(const struct uvc_device_info){
|
|
+ .uvc_version = 0x010a,
|
|
+ } },
|
|
+ /* Quanta ACER HD User Facing */
|
|
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
|
|
+ | USB_DEVICE_ID_MATCH_INT_INFO,
|
|
+ .idVendor = 0x0408,
|
|
+ .idProduct = 0x4035,
|
|
+ .bInterfaceClass = USB_CLASS_VIDEO,
|
|
+ .bInterfaceSubClass = 1,
|
|
+ .bInterfaceProtocol = UVC_PC_PROTOCOL_15,
|
|
+ .driver_info = (kernel_ulong_t)&(const struct uvc_device_info){
|
|
+ .uvc_version = 0x010a,
|
|
+ } },
|
|
/* LogiLink Wireless Webcam */
|
|
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
|
|
| USB_DEVICE_ID_MATCH_INT_INFO,
|
|
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
|
|
index e113b99a3eab59..8716004fcf6c90 100644
|
|
--- a/drivers/mmc/host/sdhci-msm.c
|
|
+++ b/drivers/mmc/host/sdhci-msm.c
|
|
@@ -1867,20 +1867,20 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host,
|
|
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
|
|
union cqhci_crypto_cap_entry cap;
|
|
|
|
+ if (!(cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE))
|
|
+ return qcom_ice_evict_key(msm_host->ice, slot);
|
|
+
|
|
/* Only AES-256-XTS has been tested so far. */
|
|
cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx];
|
|
if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS ||
|
|
cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256)
|
|
return -EINVAL;
|
|
|
|
- if (cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)
|
|
- return qcom_ice_program_key(msm_host->ice,
|
|
- QCOM_ICE_CRYPTO_ALG_AES_XTS,
|
|
- QCOM_ICE_CRYPTO_KEY_SIZE_256,
|
|
- cfg->crypto_key,
|
|
- cfg->data_unit_size, slot);
|
|
- else
|
|
- return qcom_ice_evict_key(msm_host->ice, slot);
|
|
+ return qcom_ice_program_key(msm_host->ice,
|
|
+ QCOM_ICE_CRYPTO_ALG_AES_XTS,
|
|
+ QCOM_ICE_CRYPTO_KEY_SIZE_256,
|
|
+ cfg->crypto_key,
|
|
+ cfg->data_unit_size, slot);
|
|
}
|
|
|
|
#else /* CONFIG_MMC_CRYPTO */
|
|
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
|
|
index a7e8fcdf25768b..59134d117846d1 100644
|
|
--- a/drivers/net/dsa/microchip/ksz9477.c
|
|
+++ b/drivers/net/dsa/microchip/ksz9477.c
|
|
@@ -2,7 +2,7 @@
|
|
/*
|
|
* Microchip KSZ9477 switch driver main logic
|
|
*
|
|
- * Copyright (C) 2017-2019 Microchip Technology Inc.
|
|
+ * Copyright (C) 2017-2024 Microchip Technology Inc.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
@@ -916,26 +916,51 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
|
|
int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
|
|
{
|
|
u32 secs = msecs / 1000;
|
|
- u8 value;
|
|
- u8 data;
|
|
+ u8 data, mult, value;
|
|
+ u32 max_val;
|
|
int ret;
|
|
|
|
- value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs);
|
|
+#define MAX_TIMER_VAL ((1 << 8) - 1)
|
|
|
|
- ret = ksz_write8(dev, REG_SW_LUE_CTRL_3, value);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
+ /* The aging timer comprises a 3-bit multiplier and an 8-bit second
|
|
+ * value. Either of them cannot be zero. The maximum timer is then
|
|
+ * 7 * 255 = 1785 seconds.
|
|
+ */
|
|
+ if (!secs)
|
|
+ secs = 1;
|
|
|
|
- data = FIELD_GET(SW_AGE_PERIOD_10_8_M, secs);
|
|
+ /* Return error if too large. */
|
|
+ else if (secs > 7 * MAX_TIMER_VAL)
|
|
+ return -EINVAL;
|
|
|
|
ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- value &= ~SW_AGE_CNT_M;
|
|
- value |= FIELD_PREP(SW_AGE_CNT_M, data);
|
|
+ /* Check whether there is need to update the multiplier. */
|
|
+ mult = FIELD_GET(SW_AGE_CNT_M, value);
|
|
+ max_val = MAX_TIMER_VAL;
|
|
+ if (mult > 0) {
|
|
+ /* Try to use the same multiplier already in the register as
|
|
+ * the hardware default uses multiplier 4 and 75 seconds for
|
|
+ * 300 seconds.
|
|
+ */
|
|
+ max_val = DIV_ROUND_UP(secs, mult);
|
|
+ if (max_val > MAX_TIMER_VAL || max_val * mult != secs)
|
|
+ max_val = MAX_TIMER_VAL;
|
|
+ }
|
|
+
|
|
+ data = DIV_ROUND_UP(secs, max_val);
|
|
+ if (mult != data) {
|
|
+ value &= ~SW_AGE_CNT_M;
|
|
+ value |= FIELD_PREP(SW_AGE_CNT_M, data);
|
|
+ ret = ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ }
|
|
|
|
- return ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
|
|
+ value = DIV_ROUND_UP(secs, data);
|
|
+ return ksz_write8(dev, REG_SW_LUE_CTRL_3, value);
|
|
}
|
|
|
|
void ksz9477_port_queue_split(struct ksz_device *dev, int port)
|
|
diff --git a/drivers/net/dsa/microchip/ksz9477_reg.h b/drivers/net/dsa/microchip/ksz9477_reg.h
|
|
index a2ef4b18349c41..d0886ed984c578 100644
|
|
--- a/drivers/net/dsa/microchip/ksz9477_reg.h
|
|
+++ b/drivers/net/dsa/microchip/ksz9477_reg.h
|
|
@@ -2,7 +2,7 @@
|
|
/*
|
|
* Microchip KSZ9477 register definitions
|
|
*
|
|
- * Copyright (C) 2017-2018 Microchip Technology Inc.
|
|
+ * Copyright (C) 2017-2024 Microchip Technology Inc.
|
|
*/
|
|
|
|
#ifndef __KSZ9477_REGS_H
|
|
@@ -190,8 +190,6 @@
|
|
#define SW_VLAN_ENABLE BIT(7)
|
|
#define SW_DROP_INVALID_VID BIT(6)
|
|
#define SW_AGE_CNT_M GENMASK(5, 3)
|
|
-#define SW_AGE_CNT_S 3
|
|
-#define SW_AGE_PERIOD_10_8_M GENMASK(10, 8)
|
|
#define SW_RESV_MCAST_ENABLE BIT(2)
|
|
#define SW_HASH_OPTION_M 0x03
|
|
#define SW_HASH_OPTION_CRC 1
|
|
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
|
|
index b479a628b1ae56..dde37e61faa359 100644
|
|
--- a/drivers/net/dsa/microchip/lan937x_main.c
|
|
+++ b/drivers/net/dsa/microchip/lan937x_main.c
|
|
@@ -1,6 +1,6 @@
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
/* Microchip LAN937X switch driver main logic
|
|
- * Copyright (C) 2019-2022 Microchip Technology Inc.
|
|
+ * Copyright (C) 2019-2024 Microchip Technology Inc.
|
|
*/
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
@@ -257,10 +257,66 @@ int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu)
|
|
|
|
int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
|
|
{
|
|
- u32 secs = msecs / 1000;
|
|
- u32 value;
|
|
+ u8 data, mult, value8;
|
|
+ bool in_msec = false;
|
|
+ u32 max_val, value;
|
|
+ u32 secs = msecs;
|
|
int ret;
|
|
|
|
+#define MAX_TIMER_VAL ((1 << 20) - 1)
|
|
+
|
|
+ /* The aging timer comprises a 3-bit multiplier and a 20-bit second
|
|
+ * value. Either of them cannot be zero. The maximum timer is then
|
|
+ * 7 * 1048575 = 7340025 seconds. As this value is too large for
|
|
+ * practical use it can be interpreted as microseconds, making the
|
|
+ * maximum timer 7340 seconds with finer control. This allows for
|
|
+ * maximum 122 minutes compared to 29 minutes in KSZ9477 switch.
|
|
+ */
|
|
+ if (msecs % 1000)
|
|
+ in_msec = true;
|
|
+ else
|
|
+ secs /= 1000;
|
|
+ if (!secs)
|
|
+ secs = 1;
|
|
+
|
|
+ /* Return error if too large. */
|
|
+ else if (secs > 7 * MAX_TIMER_VAL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Configure how to interpret the number value. */
|
|
+ ret = ksz_rmw8(dev, REG_SW_LUE_CTRL_2, SW_AGE_CNT_IN_MICROSEC,
|
|
+ in_msec ? SW_AGE_CNT_IN_MICROSEC : 0);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value8);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* Check whether there is need to update the multiplier. */
|
|
+ mult = FIELD_GET(SW_AGE_CNT_M, value8);
|
|
+ max_val = MAX_TIMER_VAL;
|
|
+ if (mult > 0) {
|
|
+ /* Try to use the same multiplier already in the register as
|
|
+ * the hardware default uses multiplier 4 and 75 seconds for
|
|
+ * 300 seconds.
|
|
+ */
|
|
+ max_val = DIV_ROUND_UP(secs, mult);
|
|
+ if (max_val > MAX_TIMER_VAL || max_val * mult != secs)
|
|
+ max_val = MAX_TIMER_VAL;
|
|
+ }
|
|
+
|
|
+ data = DIV_ROUND_UP(secs, max_val);
|
|
+ if (mult != data) {
|
|
+ value8 &= ~SW_AGE_CNT_M;
|
|
+ value8 |= FIELD_PREP(SW_AGE_CNT_M, data);
|
|
+ ret = ksz_write8(dev, REG_SW_LUE_CTRL_0, value8);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ secs = DIV_ROUND_UP(secs, data);
|
|
+
|
|
value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs);
|
|
|
|
ret = ksz_write8(dev, REG_SW_AGE_PERIOD__1, value);
|
|
diff --git a/drivers/net/dsa/microchip/lan937x_reg.h b/drivers/net/dsa/microchip/lan937x_reg.h
|
|
index 45b606b6429f65..b3e536e7c68694 100644
|
|
--- a/drivers/net/dsa/microchip/lan937x_reg.h
|
|
+++ b/drivers/net/dsa/microchip/lan937x_reg.h
|
|
@@ -1,6 +1,6 @@
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Microchip LAN937X switch register definitions
|
|
- * Copyright (C) 2019-2021 Microchip Technology Inc.
|
|
+ * Copyright (C) 2019-2024 Microchip Technology Inc.
|
|
*/
|
|
#ifndef __LAN937X_REG_H
|
|
#define __LAN937X_REG_H
|
|
@@ -48,8 +48,7 @@
|
|
|
|
#define SW_VLAN_ENABLE BIT(7)
|
|
#define SW_DROP_INVALID_VID BIT(6)
|
|
-#define SW_AGE_CNT_M 0x7
|
|
-#define SW_AGE_CNT_S 3
|
|
+#define SW_AGE_CNT_M GENMASK(5, 3)
|
|
#define SW_RESV_MCAST_ENABLE BIT(2)
|
|
|
|
#define REG_SW_LUE_CTRL_1 0x0311
|
|
@@ -62,6 +61,10 @@
|
|
#define SW_FAST_AGING BIT(1)
|
|
#define SW_LINK_AUTO_AGING BIT(0)
|
|
|
|
+#define REG_SW_LUE_CTRL_2 0x0312
|
|
+
|
|
+#define SW_AGE_CNT_IN_MICROSEC BIT(7)
|
|
+
|
|
#define REG_SW_AGE_PERIOD__1 0x0313
|
|
#define SW_AGE_PERIOD_7_0_M GENMASK(7, 0)
|
|
|
|
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
|
|
index 49e890a7e04a37..23cc2d85994e42 100644
|
|
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
|
|
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
|
|
@@ -1967,7 +1967,11 @@ static int bcm_sysport_open(struct net_device *dev)
|
|
unsigned int i;
|
|
int ret;
|
|
|
|
- clk_prepare_enable(priv->clk);
|
|
+ ret = clk_prepare_enable(priv->clk);
|
|
+ if (ret) {
|
|
+ netdev_err(dev, "could not enable priv clock\n");
|
|
+ return ret;
|
|
+ }
|
|
|
|
/* Reset UniMAC */
|
|
umac_reset(priv);
|
|
@@ -2625,7 +2629,11 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|
goto err_deregister_notifier;
|
|
}
|
|
|
|
- clk_prepare_enable(priv->clk);
|
|
+ ret = clk_prepare_enable(priv->clk);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "could not enable priv clock\n");
|
|
+ goto err_deregister_netdev;
|
|
+ }
|
|
|
|
priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK;
|
|
dev_info(&pdev->dev,
|
|
@@ -2639,6 +2647,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|
|
|
return 0;
|
|
|
|
+err_deregister_netdev:
|
|
+ unregister_netdev(dev);
|
|
err_deregister_notifier:
|
|
unregister_netdevice_notifier(&priv->netdev_notifier);
|
|
err_deregister_fixed_link:
|
|
@@ -2810,7 +2820,12 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)
|
|
if (!netif_running(dev))
|
|
return 0;
|
|
|
|
- clk_prepare_enable(priv->clk);
|
|
+ ret = clk_prepare_enable(priv->clk);
|
|
+ if (ret) {
|
|
+ netdev_err(dev, "could not enable priv clock\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
if (priv->wolopts)
|
|
clk_disable_unprepare(priv->wol_clk);
|
|
|
|
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
|
|
index 5703240474e5b2..d70305654e7d07 100644
|
|
--- a/drivers/net/ethernet/google/gve/gve_main.c
|
|
+++ b/drivers/net/ethernet/google/gve/gve_main.c
|
|
@@ -1528,8 +1528,8 @@ static int gve_xsk_pool_enable(struct net_device *dev,
|
|
if (err)
|
|
return err;
|
|
|
|
- /* If XDP prog is not installed, return */
|
|
- if (!priv->xdp_prog)
|
|
+ /* If XDP prog is not installed or interface is down, return. */
|
|
+ if (!priv->xdp_prog || !netif_running(dev))
|
|
return 0;
|
|
|
|
rx = &priv->rx[qid];
|
|
@@ -1574,21 +1574,16 @@ static int gve_xsk_pool_disable(struct net_device *dev,
|
|
if (qid >= priv->rx_cfg.num_queues)
|
|
return -EINVAL;
|
|
|
|
- /* If XDP prog is not installed, unmap DMA and return */
|
|
- if (!priv->xdp_prog)
|
|
- goto done;
|
|
-
|
|
- tx_qid = gve_xdp_tx_queue_id(priv, qid);
|
|
- if (!netif_running(dev)) {
|
|
- priv->rx[qid].xsk_pool = NULL;
|
|
- xdp_rxq_info_unreg(&priv->rx[qid].xsk_rxq);
|
|
- priv->tx[tx_qid].xsk_pool = NULL;
|
|
+ /* If XDP prog is not installed or interface is down, unmap DMA and
|
|
+ * return.
|
|
+ */
|
|
+ if (!priv->xdp_prog || !netif_running(dev))
|
|
goto done;
|
|
- }
|
|
|
|
napi_rx = &priv->ntfy_blocks[priv->rx[qid].ntfy_id].napi;
|
|
napi_disable(napi_rx); /* make sure current rx poll is done */
|
|
|
|
+ tx_qid = gve_xdp_tx_queue_id(priv, qid);
|
|
napi_tx = &priv->ntfy_blocks[priv->tx[tx_qid].ntfy_id].napi;
|
|
napi_disable(napi_tx); /* make sure current tx poll is done */
|
|
|
|
@@ -1616,6 +1611,9 @@ static int gve_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
|
|
struct gve_priv *priv = netdev_priv(dev);
|
|
int tx_queue_id = gve_xdp_tx_queue_id(priv, queue_id);
|
|
|
|
+ if (!gve_get_napi_enabled(priv))
|
|
+ return -ENETDOWN;
|
|
+
|
|
if (queue_id >= priv->rx_cfg.num_queues || !priv->xdp_prog)
|
|
return -EINVAL;
|
|
|
|
@@ -1757,6 +1755,9 @@ static void gve_turndown(struct gve_priv *priv)
|
|
|
|
gve_clear_napi_enabled(priv);
|
|
gve_clear_report_stats(priv);
|
|
+
|
|
+ /* Make sure that all traffic is finished processing. */
|
|
+ synchronize_net();
|
|
}
|
|
|
|
static void gve_turnup(struct gve_priv *priv)
|
|
diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c
|
|
index 2ae891a62875c7..29987624791a68 100644
|
|
--- a/drivers/net/ethernet/google/gve/gve_tx.c
|
|
+++ b/drivers/net/ethernet/google/gve/gve_tx.c
|
|
@@ -777,9 +777,12 @@ int gve_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
|
|
struct gve_tx_ring *tx;
|
|
int i, err = 0, qid;
|
|
|
|
- if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
|
|
+ if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK) || !priv->xdp_prog)
|
|
return -EINVAL;
|
|
|
|
+ if (!gve_get_napi_enabled(priv))
|
|
+ return -ENETDOWN;
|
|
+
|
|
qid = gve_xdp_tx_queue_id(priv,
|
|
smp_processor_id() % priv->num_xdp_queues);
|
|
|
|
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
|
|
index 3b129a1c338152..07e5051171a48a 100644
|
|
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
|
|
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
|
|
@@ -2708,9 +2708,15 @@ static struct platform_device *port_platdev[3];
|
|
|
|
static void mv643xx_eth_shared_of_remove(void)
|
|
{
|
|
+ struct mv643xx_eth_platform_data *pd;
|
|
int n;
|
|
|
|
for (n = 0; n < 3; n++) {
|
|
+ if (!port_platdev[n])
|
|
+ continue;
|
|
+ pd = dev_get_platdata(&port_platdev[n]->dev);
|
|
+ if (pd)
|
|
+ of_node_put(pd->phy_node);
|
|
platform_device_del(port_platdev[n]);
|
|
port_platdev[n] = NULL;
|
|
}
|
|
@@ -2773,8 +2779,10 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
|
|
}
|
|
|
|
ppdev = platform_device_alloc(MV643XX_ETH_NAME, dev_num);
|
|
- if (!ppdev)
|
|
- return -ENOMEM;
|
|
+ if (!ppdev) {
|
|
+ ret = -ENOMEM;
|
|
+ goto put_err;
|
|
+ }
|
|
ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
|
ppdev->dev.of_node = pnp;
|
|
|
|
@@ -2796,6 +2804,8 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
|
|
|
|
port_err:
|
|
platform_device_put(ppdev);
|
|
+put_err:
|
|
+ of_node_put(ppd.phy_node);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
|
|
index 07720841a8d700..dd3d93720358bd 100644
|
|
--- a/drivers/net/ethernet/marvell/sky2.c
|
|
+++ b/drivers/net/ethernet/marvell/sky2.c
|
|
@@ -129,6 +129,7 @@ static const struct pci_device_id sky2_id_table[] = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4373) }, /* 88E8075 */
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4382) }, /* 88E8079 */
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
|
|
index cc9bcc42003242..6ab02f3fc29123 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
|
|
@@ -339,9 +339,13 @@ static int mlx5e_macsec_init_sa_fs(struct macsec_context *ctx,
|
|
{
|
|
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
|
|
struct mlx5_macsec_fs *macsec_fs = priv->mdev->macsec_fs;
|
|
+ const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
|
|
struct mlx5_macsec_rule_attrs rule_attrs;
|
|
union mlx5_macsec_rule *macsec_rule;
|
|
|
|
+ if (is_tx && tx_sc->encoding_sa != sa->assoc_num)
|
|
+ return 0;
|
|
+
|
|
rule_attrs.macsec_obj_id = sa->macsec_obj_id;
|
|
rule_attrs.sci = sa->sci;
|
|
rule_attrs.assoc_num = sa->assoc_num;
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
|
|
index 13b5916b64e224..eed8fcde261384 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
|
|
@@ -150,11 +150,11 @@ void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev)
|
|
unsigned long i;
|
|
int err;
|
|
|
|
- xa_for_each(&esw->offloads.vport_reps, i, rep) {
|
|
- rpriv = rep->rep_data[REP_ETH].priv;
|
|
- if (!rpriv || !rpriv->netdev)
|
|
+ mlx5_esw_for_each_rep(esw, i, rep) {
|
|
+ if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
|
|
continue;
|
|
|
|
+ rpriv = rep->rep_data[REP_ETH].priv;
|
|
rhashtable_walk_enter(&rpriv->tc_ht, &iter);
|
|
rhashtable_walk_start(&iter);
|
|
while ((flow = rhashtable_walk_next(&iter)) != NULL) {
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
|
|
index 9b771b572593b5..3e58e731b5697c 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
|
|
@@ -713,6 +713,9 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw);
|
|
MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base) +\
|
|
(last) - 1)
|
|
|
|
+#define mlx5_esw_for_each_rep(esw, i, rep) \
|
|
+ xa_for_each(&((esw)->offloads.vport_reps), i, rep)
|
|
+
|
|
struct mlx5_eswitch *__must_check
|
|
mlx5_devlink_eswitch_get(struct devlink *devlink);
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
|
|
index 58529d1a98b37b..7eba3a5bb97cae 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
|
|
@@ -52,9 +52,6 @@
|
|
#include "lag/lag.h"
|
|
#include "en/tc/post_meter.h"
|
|
|
|
-#define mlx5_esw_for_each_rep(esw, i, rep) \
|
|
- xa_for_each(&((esw)->offloads.vport_reps), i, rep)
|
|
-
|
|
/* There are two match-all miss flows, one for unicast dst mac and
|
|
* one for multicast.
|
|
*/
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
|
|
index 991250f44c2ed1..474e63d02ba492 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
|
|
@@ -3478,6 +3478,7 @@ void mlx5_fs_core_free(struct mlx5_core_dev *dev)
|
|
int mlx5_fs_core_alloc(struct mlx5_core_dev *dev)
|
|
{
|
|
struct mlx5_flow_steering *steering;
|
|
+ char name[80];
|
|
int err = 0;
|
|
|
|
err = mlx5_init_fc_stats(dev);
|
|
@@ -3502,10 +3503,12 @@ int mlx5_fs_core_alloc(struct mlx5_core_dev *dev)
|
|
else
|
|
steering->mode = MLX5_FLOW_STEERING_MODE_DMFS;
|
|
|
|
- steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
|
|
+ snprintf(name, sizeof(name), "%s-mlx5_fs_fgs", dev_name(dev->device));
|
|
+ steering->fgs_cache = kmem_cache_create(name,
|
|
sizeof(struct mlx5_flow_group), 0,
|
|
0, NULL);
|
|
- steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
|
|
+ snprintf(name, sizeof(name), "%s-mlx5_fs_ftes", dev_name(dev->device));
|
|
+ steering->ftes_cache = kmem_cache_create(name, sizeof(struct fs_fte), 0,
|
|
0, NULL);
|
|
if (!steering->ftes_cache || !steering->fgs_cache) {
|
|
err = -ENOMEM;
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
|
|
index 6fa06ba2d34653..f57c84e5128bc7 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
|
|
@@ -1067,7 +1067,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
|
|
int inlen, err, eqn;
|
|
void *cqc, *in;
|
|
__be64 *pas;
|
|
- int vector;
|
|
u32 i;
|
|
|
|
cq = kzalloc(sizeof(*cq), GFP_KERNEL);
|
|
@@ -1096,8 +1095,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
|
|
if (!in)
|
|
goto err_cqwq;
|
|
|
|
- vector = raw_smp_processor_id() % mlx5_comp_vectors_max(mdev);
|
|
- err = mlx5_comp_eqn_get(mdev, vector, &eqn);
|
|
+ err = mlx5_comp_eqn_get(mdev, 0, &eqn);
|
|
if (err) {
|
|
kvfree(in);
|
|
goto err_cqwq;
|
|
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
|
|
index dcd198104141f1..fa3fef2b74db0d 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
|
|
@@ -423,8 +423,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
|
|
|
|
parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
|
|
ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
|
|
- 0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0,
|
|
- 0);
|
|
+ 0, 0, tun->net, parms.link, tun->fwmark, 0, 0);
|
|
|
|
rt = ip_route_output_key(tun->net, &fl4);
|
|
if (IS_ERR(rt))
|
|
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
|
|
index 54aa56c841334c..2f483531d95cb7 100644
|
|
--- a/drivers/net/ethernet/renesas/rswitch.c
|
|
+++ b/drivers/net/ethernet/renesas/rswitch.c
|
|
@@ -1632,8 +1632,9 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
|
|
if (dma_mapping_error(ndev->dev.parent, dma_addr_orig))
|
|
goto err_kfree;
|
|
|
|
- gq->skbs[gq->cur] = skb;
|
|
- gq->unmap_addrs[gq->cur] = dma_addr_orig;
|
|
+ /* Stored the skb at the last descriptor to avoid skb free before hardware completes send */
|
|
+ gq->skbs[(gq->cur + nr_desc - 1) % gq->ring_size] = skb;
|
|
+ gq->unmap_addrs[(gq->cur + nr_desc - 1) % gq->ring_size] = dma_addr_orig;
|
|
|
|
dma_wmb();
|
|
|
|
diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c
|
|
index 44bb57670340da..109d2aa34ae332 100644
|
|
--- a/drivers/net/ethernet/sfc/tc_conntrack.c
|
|
+++ b/drivers/net/ethernet/sfc/tc_conntrack.c
|
|
@@ -16,7 +16,7 @@ static int efx_tc_flow_block(enum tc_setup_type type, void *type_data,
|
|
void *cb_priv);
|
|
|
|
static const struct rhashtable_params efx_tc_ct_zone_ht_params = {
|
|
- .key_len = offsetof(struct efx_tc_ct_zone, linkage),
|
|
+ .key_len = sizeof_field(struct efx_tc_ct_zone, zone),
|
|
.key_offset = 0,
|
|
.head_offset = offsetof(struct efx_tc_ct_zone, linkage),
|
|
};
|
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
|
index b4fdd40be63cb4..4d570efd9d4bbe 100644
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
|
|
@@ -296,62 +296,80 @@ static int stmmac_mtl_setup(struct platform_device *pdev,
|
|
}
|
|
|
|
/**
|
|
- * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources
|
|
- * @plat: driver data platform structure
|
|
- * @np: device tree node
|
|
- * @dev: device pointer
|
|
- * Description:
|
|
- * The mdio bus will be allocated in case of a phy transceiver is on board;
|
|
- * it will be NULL if the fixed-link is configured.
|
|
- * If there is the "snps,dwmac-mdio" sub-node the mdio will be allocated
|
|
- * in any case (for DSA, mdio must be registered even if fixed-link).
|
|
- * The table below sums the supported configurations:
|
|
- * -------------------------------
|
|
- * snps,phy-addr | Y
|
|
- * -------------------------------
|
|
- * phy-handle | Y
|
|
- * -------------------------------
|
|
- * fixed-link | N
|
|
- * -------------------------------
|
|
- * snps,dwmac-mdio |
|
|
- * even if | Y
|
|
- * fixed-link |
|
|
- * -------------------------------
|
|
+ * stmmac_of_get_mdio() - Gets the MDIO bus from the devicetree.
|
|
+ * @np: devicetree node
|
|
+ *
|
|
+ * The MDIO bus will be searched for in the following ways:
|
|
+ * 1. The compatible is "snps,dwc-qos-ethernet-4.10" && a "mdio" named
|
|
+ * child node exists
|
|
+ * 2. A child node with the "snps,dwmac-mdio" compatible is present
|
|
*
|
|
- * It returns 0 in case of success otherwise -ENODEV.
|
|
+ * Return: The MDIO node if present otherwise NULL
|
|
*/
|
|
-static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
|
|
- struct device_node *np, struct device *dev)
|
|
+static struct device_node *stmmac_of_get_mdio(struct device_node *np)
|
|
{
|
|
- bool mdio = !of_phy_is_fixed_link(np);
|
|
static const struct of_device_id need_mdio_ids[] = {
|
|
{ .compatible = "snps,dwc-qos-ethernet-4.10" },
|
|
{},
|
|
};
|
|
+ struct device_node *mdio_node = NULL;
|
|
|
|
if (of_match_node(need_mdio_ids, np)) {
|
|
- plat->mdio_node = of_get_child_by_name(np, "mdio");
|
|
+ mdio_node = of_get_child_by_name(np, "mdio");
|
|
} else {
|
|
/**
|
|
* If snps,dwmac-mdio is passed from DT, always register
|
|
* the MDIO
|
|
*/
|
|
- for_each_child_of_node(np, plat->mdio_node) {
|
|
- if (of_device_is_compatible(plat->mdio_node,
|
|
+ for_each_child_of_node(np, mdio_node) {
|
|
+ if (of_device_is_compatible(mdio_node,
|
|
"snps,dwmac-mdio"))
|
|
break;
|
|
}
|
|
}
|
|
|
|
- if (plat->mdio_node) {
|
|
+ return mdio_node;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * stmmac_mdio_setup() - Populate platform related MDIO structures.
|
|
+ * @plat: driver data platform structure
|
|
+ * @np: devicetree node
|
|
+ * @dev: device pointer
|
|
+ *
|
|
+ * This searches for MDIO information from the devicetree.
|
|
+ * If an MDIO node is found, it's assigned to plat->mdio_node and
|
|
+ * plat->mdio_bus_data is allocated.
|
|
+ * If no connection can be determined, just plat->mdio_bus_data is allocated
|
|
+ * to indicate a bus should be created and scanned for a phy.
|
|
+ * If it's determined there's no MDIO bus needed, both are left NULL.
|
|
+ *
|
|
+ * This expects that plat->phy_node has already been searched for.
|
|
+ *
|
|
+ * Return: 0 on success, errno otherwise.
|
|
+ */
|
|
+static int stmmac_mdio_setup(struct plat_stmmacenet_data *plat,
|
|
+ struct device_node *np, struct device *dev)
|
|
+{
|
|
+ bool legacy_mdio;
|
|
+
|
|
+ plat->mdio_node = stmmac_of_get_mdio(np);
|
|
+ if (plat->mdio_node)
|
|
dev_dbg(dev, "Found MDIO subnode\n");
|
|
- mdio = true;
|
|
- }
|
|
|
|
- if (mdio) {
|
|
- plat->mdio_bus_data =
|
|
- devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data),
|
|
- GFP_KERNEL);
|
|
+ /* Legacy devicetrees allowed for no MDIO bus description and expect
|
|
+ * the bus to be scanned for devices. If there's no phy or fixed-link
|
|
+ * described assume this is the case since there must be something
|
|
+ * connected to the MAC.
|
|
+ */
|
|
+ legacy_mdio = !of_phy_is_fixed_link(np) && !plat->phy_node;
|
|
+ if (legacy_mdio)
|
|
+ dev_info(dev, "Deprecated MDIO bus assumption used\n");
|
|
+
|
|
+ if (plat->mdio_node || legacy_mdio) {
|
|
+ plat->mdio_bus_data = devm_kzalloc(dev,
|
|
+ sizeof(*plat->mdio_bus_data),
|
|
+ GFP_KERNEL);
|
|
if (!plat->mdio_bus_data)
|
|
return -ENOMEM;
|
|
|
|
@@ -455,10 +473,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
|
if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
|
|
dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
|
|
|
|
- /* To Configure PHY by using all device-tree supported properties */
|
|
- rc = stmmac_dt_phy(plat, np, &pdev->dev);
|
|
- if (rc)
|
|
- return ERR_PTR(rc);
|
|
+ rc = stmmac_mdio_setup(plat, np, &pdev->dev);
|
|
+ if (rc) {
|
|
+ ret = ERR_PTR(rc);
|
|
+ goto error_put_phy;
|
|
+ }
|
|
|
|
of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
|
|
|
|
@@ -547,8 +566,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
|
dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
|
|
GFP_KERNEL);
|
|
if (!dma_cfg) {
|
|
- stmmac_remove_config_dt(pdev, plat);
|
|
- return ERR_PTR(-ENOMEM);
|
|
+ ret = ERR_PTR(-ENOMEM);
|
|
+ goto error_put_mdio;
|
|
}
|
|
plat->dma_cfg = dma_cfg;
|
|
|
|
@@ -576,8 +595,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
|
|
|
rc = stmmac_mtl_setup(pdev, plat);
|
|
if (rc) {
|
|
- stmmac_remove_config_dt(pdev, plat);
|
|
- return ERR_PTR(rc);
|
|
+ ret = ERR_PTR(rc);
|
|
+ goto error_put_mdio;
|
|
}
|
|
|
|
/* clock setup */
|
|
@@ -629,6 +648,10 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
|
clk_disable_unprepare(plat->pclk);
|
|
error_pclk_get:
|
|
clk_disable_unprepare(plat->stmmac_clk);
|
|
+error_put_mdio:
|
|
+ of_node_put(plat->mdio_node);
|
|
+error_put_phy:
|
|
+ of_node_put(plat->phy_node);
|
|
|
|
return ret;
|
|
}
|
|
@@ -637,16 +660,17 @@ static void devm_stmmac_remove_config_dt(void *data)
|
|
{
|
|
struct plat_stmmacenet_data *plat = data;
|
|
|
|
- /* Platform data argument is unused */
|
|
- stmmac_remove_config_dt(NULL, plat);
|
|
+ clk_disable_unprepare(plat->stmmac_clk);
|
|
+ clk_disable_unprepare(plat->pclk);
|
|
+ of_node_put(plat->mdio_node);
|
|
+ of_node_put(plat->phy_node);
|
|
}
|
|
|
|
/**
|
|
* devm_stmmac_probe_config_dt
|
|
* @pdev: platform_device structure
|
|
* @mac: MAC address to use
|
|
- * Description: Devres variant of stmmac_probe_config_dt(). Does not require
|
|
- * the user to call stmmac_remove_config_dt() at driver detach.
|
|
+ * Description: Devres variant of stmmac_probe_config_dt().
|
|
*/
|
|
struct plat_stmmacenet_data *
|
|
devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
|
|
diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
|
|
index 3025e9c189702b..f06cdec14ed7a1 100644
|
|
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
|
|
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
|
|
@@ -290,6 +290,9 @@ static void icss_iep_enable_shadow_mode(struct icss_iep *iep)
|
|
for (cmp = IEP_MIN_CMP; cmp < IEP_MAX_CMP; cmp++) {
|
|
regmap_update_bits(iep->map, ICSS_IEP_CMP_STAT_REG,
|
|
IEP_CMP_STATUS(cmp), IEP_CMP_STATUS(cmp));
|
|
+
|
|
+ regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
|
|
+ IEP_CMP_CFG_CMP_EN(cmp), 0);
|
|
}
|
|
|
|
/* enable reset counter on CMP0 event */
|
|
@@ -808,6 +811,11 @@ int icss_iep_exit(struct icss_iep *iep)
|
|
}
|
|
icss_iep_disable(iep);
|
|
|
|
+ if (iep->pps_enabled)
|
|
+ icss_iep_pps_enable(iep, false);
|
|
+ else if (iep->perout_enabled)
|
|
+ icss_iep_perout_enable(iep, NULL, false);
|
|
+
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(icss_iep_exit);
|
|
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
|
|
index 89775b6d0699a0..8e30df676ededb 100644
|
|
--- a/drivers/net/usb/qmi_wwan.c
|
|
+++ b/drivers/net/usb/qmi_wwan.c
|
|
@@ -1373,6 +1373,9 @@ static const struct usb_device_id products[] = {
|
|
{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
|
|
{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
|
|
{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
|
|
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c0, 0)}, /* Telit FE910C04 */
|
|
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c4, 0)}, /* Telit FE910C04 */
|
|
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c8, 0)}, /* Telit FE910C04 */
|
|
{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
|
|
{QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */
|
|
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
|
|
diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c
|
|
index af6546572df26b..9a4f8e815412cb 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/bmi.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/bmi.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2014,2016-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "bmi.h"
|
|
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
|
|
index c27b8204718a6d..afae4a8027f833 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/ce.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/ce.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "hif.h"
|
|
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
|
|
index 81058be3598f15..c3a8b3496be2a5 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/core.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
|
|
index 4b5239de401840..cb2359d2ee0b04 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/core.h
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _CORE_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c
|
|
index 2d1634a890dde3..bb3a276b7ed584 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/coredump.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/coredump.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "coredump.h"
|
|
diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h
|
|
index 437b9759f05d3d..e5ef0352e319c7 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/coredump.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/coredump.h
|
|
@@ -1,6 +1,7 @@
|
|
/* SPDX-License-Identifier: ISC */
|
|
/*
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _COREDUMP_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
|
|
index fe89bc61e5317d..92ad0a04bcc738 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/debug.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
|
|
index 5598cf706daabc..0f6de862c3a9ba 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "core.h"
|
|
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
|
|
index 5bfeecb95fca23..a6e21ce90bad64 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/htc.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/htc.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "core.h"
|
|
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
|
|
index 7b24297146e72a..52f6dc6b81c5ee 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/htt.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/htt.h
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _HTT_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
|
|
index 438b0caaceb79e..51855f23ea2664 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "core.h"
|
|
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
|
|
index bd603feb795314..60425d22d70790 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/etherdevice.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
|
|
index 6d32b43a4da65e..8fafe096adff53 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/hw.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/hw.c
|
|
@@ -1,6 +1,7 @@
|
|
// SPDX-License-Identifier: ISC
|
|
/*
|
|
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
|
|
index 7ecdd0011cfa48..afd336282615c6 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/hw.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/hw.h
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _HW_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
|
|
index d5e6e11f630b95..655fb5cdf01f86 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "mac.h"
|
|
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
|
|
index 23f36622193908..aaa240f3c08a9f 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/pci.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
|
|
index 480cd97ab739de..27bb4cf2dfea93 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/pci.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/pci.h
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _PCI_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
|
|
index 52c1a3de8da60a..38e939f572a9ed 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/qmi.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
|
|
@@ -1,6 +1,7 @@
|
|
// SPDX-License-Identifier: ISC
|
|
/*
|
|
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/completion.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
|
|
index 1c81e454f943fd..0e85c75d227836 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
|
|
@@ -1,6 +1,7 @@
|
|
// SPDX-License-Identifier: ISC
|
|
/*
|
|
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/soc/qcom/qmi.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
|
|
index f0db991408dc26..9f311f3bc9e7f9 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
|
|
@@ -1,6 +1,7 @@
|
|
/* SPDX-License-Identifier: ISC */
|
|
/*
|
|
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef WCN3990_QMI_SVC_V01_H
|
|
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
|
|
index 777e53aa69dc86..564293df1e9acf 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _RX_DESC_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
|
|
index 56fbcfb80bf886..850d999615a2c3 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/sdio.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2004-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
|
|
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
@@ -2647,9 +2648,9 @@ static void ath10k_sdio_remove(struct sdio_func *func)
|
|
|
|
netif_napi_del(&ar->napi);
|
|
|
|
- ath10k_core_destroy(ar);
|
|
-
|
|
destroy_workqueue(ar_sdio->workqueue);
|
|
+
|
|
+ ath10k_core_destroy(ar);
|
|
}
|
|
|
|
static const struct sdio_device_id ath10k_sdio_devices[] = {
|
|
diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c
|
|
index cefd97323dfe50..31c8d7fbb0955b 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/thermal.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/thermal.c
|
|
@@ -1,6 +1,7 @@
|
|
// SPDX-License-Identifier: ISC
|
|
/*
|
|
* Copyright (c) 2014-2015 Qualcomm Atheros, Inc.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/device.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/usb.h b/drivers/net/wireless/ath/ath10k/usb.h
|
|
index 48e066ba816249..7e4cfbb673c9a8 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/usb.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/usb.h
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2004-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _USB_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
|
|
index dbb48d70f2e93e..83a8f07a687f73 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
#ifndef _WMI_TLV_H
|
|
#define _WMI_TLV_H
|
|
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
|
|
index 1c21dbde77b84e..818aea99f85eb3 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/skbuff.h>
|
|
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
|
|
index b112e88260931c..9146df98fceeee 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/wmi.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
|
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _WMI_H_
|
|
diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c
|
|
index 20b9aa8ddf7d52..aa7b2e703f3d4b 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/wow.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/wow.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
|
|
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include "mac.h"
|
|
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
|
|
index f90191a290c26a..713899735ccc5e 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/mac.c
|
|
@@ -4945,7 +4945,7 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
|
|
if (ret) {
|
|
ath12k_warn(ar->ab, "failed to queue management frame %d\n",
|
|
ret);
|
|
- ieee80211_free_txskb(ar->hw, skb);
|
|
+ ieee80211_free_txskb(hw, skb);
|
|
}
|
|
return;
|
|
}
|
|
@@ -4953,7 +4953,7 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
|
|
ret = ath12k_dp_tx(ar, arvif, skb);
|
|
if (ret) {
|
|
ath12k_warn(ar->ab, "failed to transmit frame %d\n", ret);
|
|
- ieee80211_free_txskb(ar->hw, skb);
|
|
+ ieee80211_free_txskb(hw, skb);
|
|
}
|
|
}
|
|
|
|
@@ -5496,7 +5496,7 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
|
|
goto err_peer_del;
|
|
|
|
param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
|
|
- param_value = ar->hw->wiphy->rts_threshold;
|
|
+ param_value = hw->wiphy->rts_threshold;
|
|
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
|
param_id, param_value);
|
|
if (ret) {
|
|
@@ -6676,9 +6676,9 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
|
|
arvif->vdev_id, ret);
|
|
return ret;
|
|
}
|
|
- ieee80211_iterate_stations_atomic(ar->hw,
|
|
- ath12k_mac_disable_peer_fixed_rate,
|
|
- arvif);
|
|
+ ieee80211_iterate_stations_mtx(hw,
|
|
+ ath12k_mac_disable_peer_fixed_rate,
|
|
+ arvif);
|
|
} else if (ath12k_mac_bitrate_mask_get_single_nss(ar, band, mask,
|
|
&single_nss)) {
|
|
rate = WMI_FIXED_RATE_NONE;
|
|
@@ -6722,16 +6722,16 @@ ath12k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- ieee80211_iterate_stations_atomic(ar->hw,
|
|
- ath12k_mac_disable_peer_fixed_rate,
|
|
- arvif);
|
|
+ ieee80211_iterate_stations_mtx(hw,
|
|
+ ath12k_mac_disable_peer_fixed_rate,
|
|
+ arvif);
|
|
|
|
mutex_lock(&ar->conf_mutex);
|
|
|
|
arvif->bitrate_mask = *mask;
|
|
- ieee80211_iterate_stations_atomic(ar->hw,
|
|
- ath12k_mac_set_bitrate_mask_iter,
|
|
- arvif);
|
|
+ ieee80211_iterate_stations_mtx(hw,
|
|
+ ath12k_mac_set_bitrate_mask_iter,
|
|
+ arvif);
|
|
|
|
mutex_unlock(&ar->conf_mutex);
|
|
}
|
|
@@ -6767,7 +6767,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
|
|
ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
|
|
ar->pdev->pdev_id);
|
|
ar->state = ATH12K_STATE_ON;
|
|
- ieee80211_wake_queues(ar->hw);
|
|
+ ieee80211_wake_queues(hw);
|
|
|
|
if (ab->is_reset) {
|
|
recovery_count = atomic_inc_return(&ab->recovery_count);
|
|
diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
|
|
index 32bdefeccc2453..837a3e1ec3a49c 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/reg.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/reg.c
|
|
@@ -28,11 +28,11 @@ static const struct ieee80211_regdomain ath12k_world_regd = {
|
|
}
|
|
};
|
|
|
|
-static bool ath12k_regdom_changes(struct ath12k *ar, char *alpha2)
|
|
+static bool ath12k_regdom_changes(struct ieee80211_hw *hw, char *alpha2)
|
|
{
|
|
const struct ieee80211_regdomain *regd;
|
|
|
|
- regd = rcu_dereference_rtnl(ar->hw->wiphy->regd);
|
|
+ regd = rcu_dereference_rtnl(hw->wiphy->regd);
|
|
/* This can happen during wiphy registration where the previous
|
|
* user request is received before we update the regd received
|
|
* from firmware.
|
|
@@ -71,7 +71,7 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
|
return;
|
|
}
|
|
|
|
- if (!ath12k_regdom_changes(ar, request->alpha2)) {
|
|
+ if (!ath12k_regdom_changes(hw, request->alpha2)) {
|
|
ath12k_dbg(ar->ab, ATH12K_DBG_REG, "Country is already set\n");
|
|
return;
|
|
}
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
index 0cae5746f540fa..5bd1ee81210d1d 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
@@ -1295,12 +1295,12 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev)
|
|
struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv;
|
|
int i;
|
|
|
|
- for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
|
|
- skb_queue_purge(&rtwsdio->tx_queue[i]);
|
|
-
|
|
flush_workqueue(rtwsdio->txwq);
|
|
destroy_workqueue(rtwsdio->txwq);
|
|
kfree(rtwsdio->tx_handler_data);
|
|
+
|
|
+ for (i = 0; i < RTK_MAX_TX_QUEUE_NUM; i++)
|
|
+ ieee80211_purge_tx_queue(rtwdev->hw, &rtwsdio->tx_queue[i]);
|
|
}
|
|
|
|
int rtw_sdio_probe(struct sdio_func *sdio_func,
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
index 04a64afcbf8a2d..8f1d653282b7ec 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/usb.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
@@ -416,10 +416,11 @@ static void rtw_usb_tx_handler(struct work_struct *work)
|
|
|
|
static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb)
|
|
{
|
|
+ struct rtw_dev *rtwdev = rtwusb->rtwdev;
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
|
|
- skb_queue_purge(&rtwusb->tx_queue[i]);
|
|
+ ieee80211_purge_tx_queue(rtwdev->hw, &rtwusb->tx_queue[i]);
|
|
}
|
|
|
|
static void rtw_usb_write_port_complete(struct urb *urb)
|
|
@@ -801,9 +802,9 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev)
|
|
{
|
|
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
|
|
|
- rtw_usb_tx_queue_purge(rtwusb);
|
|
flush_workqueue(rtwusb->txwq);
|
|
destroy_workqueue(rtwusb->txwq);
|
|
+ rtw_usb_tx_queue_purge(rtwusb);
|
|
}
|
|
|
|
static int rtw_usb_intf_init(struct rtw_dev *rtwdev,
|
|
diff --git a/drivers/net/wwan/iosm/iosm_ipc_mmio.c b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
|
|
index 63eb08c43c0517..6764c13530b9bd 100644
|
|
--- a/drivers/net/wwan/iosm/iosm_ipc_mmio.c
|
|
+++ b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
|
|
@@ -104,7 +104,7 @@ struct iosm_mmio *ipc_mmio_init(void __iomem *mmio, struct device *dev)
|
|
break;
|
|
|
|
msleep(20);
|
|
- } while (retries-- > 0);
|
|
+ } while (--retries > 0);
|
|
|
|
if (!retries) {
|
|
dev_err(ipc_mmio->dev, "invalid exec stage %X", stage);
|
|
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
|
|
index 80edb8e75a6ad7..64868df3640d13 100644
|
|
--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c
|
|
+++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
|
|
@@ -97,14 +97,21 @@ void t7xx_fsm_broadcast_state(struct t7xx_fsm_ctl *ctl, enum md_state state)
|
|
fsm_state_notify(ctl->md, state);
|
|
}
|
|
|
|
+static void fsm_release_command(struct kref *ref)
|
|
+{
|
|
+ struct t7xx_fsm_command *cmd = container_of(ref, typeof(*cmd), refcnt);
|
|
+
|
|
+ kfree(cmd);
|
|
+}
|
|
+
|
|
static void fsm_finish_command(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command *cmd, int result)
|
|
{
|
|
if (cmd->flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
|
|
- *cmd->ret = result;
|
|
- complete_all(cmd->done);
|
|
+ cmd->result = result;
|
|
+ complete_all(&cmd->done);
|
|
}
|
|
|
|
- kfree(cmd);
|
|
+ kref_put(&cmd->refcnt, fsm_release_command);
|
|
}
|
|
|
|
static void fsm_del_kf_event(struct t7xx_fsm_event *event)
|
|
@@ -396,7 +403,6 @@ static int fsm_main_thread(void *data)
|
|
|
|
int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id, unsigned int flag)
|
|
{
|
|
- DECLARE_COMPLETION_ONSTACK(done);
|
|
struct t7xx_fsm_command *cmd;
|
|
unsigned long flags;
|
|
int ret;
|
|
@@ -408,11 +414,13 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
|
|
INIT_LIST_HEAD(&cmd->entry);
|
|
cmd->cmd_id = cmd_id;
|
|
cmd->flag = flag;
|
|
+ kref_init(&cmd->refcnt);
|
|
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
|
|
- cmd->done = &done;
|
|
- cmd->ret = &ret;
|
|
+ init_completion(&cmd->done);
|
|
+ kref_get(&cmd->refcnt);
|
|
}
|
|
|
|
+ kref_get(&cmd->refcnt);
|
|
spin_lock_irqsave(&ctl->command_lock, flags);
|
|
list_add_tail(&cmd->entry, &ctl->command_queue);
|
|
spin_unlock_irqrestore(&ctl->command_lock, flags);
|
|
@@ -422,11 +430,11 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
|
|
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
|
|
unsigned long wait_ret;
|
|
|
|
- wait_ret = wait_for_completion_timeout(&done,
|
|
+ wait_ret = wait_for_completion_timeout(&cmd->done,
|
|
msecs_to_jiffies(FSM_CMD_TIMEOUT_MS));
|
|
- if (!wait_ret)
|
|
- return -ETIMEDOUT;
|
|
|
|
+ ret = wait_ret ? cmd->result : -ETIMEDOUT;
|
|
+ kref_put(&cmd->refcnt, fsm_release_command);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.h b/drivers/net/wwan/t7xx/t7xx_state_monitor.h
|
|
index b6e76f3903c892..74f96fd2605e8e 100644
|
|
--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.h
|
|
+++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.h
|
|
@@ -109,8 +109,9 @@ struct t7xx_fsm_command {
|
|
struct list_head entry;
|
|
enum t7xx_fsm_cmd_state cmd_id;
|
|
unsigned int flag;
|
|
- struct completion *done;
|
|
- int *ret;
|
|
+ struct completion done;
|
|
+ int result;
|
|
+ struct kref refcnt;
|
|
};
|
|
|
|
struct t7xx_fsm_notifier {
|
|
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
|
|
index 5b6a6bd4e6e800..4aad16390d4790 100644
|
|
--- a/drivers/nvme/host/core.c
|
|
+++ b/drivers/nvme/host/core.c
|
|
@@ -1178,13 +1178,13 @@ static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
|
|
nvme_keep_alive_work_period(ctrl));
|
|
}
|
|
|
|
-static void nvme_keep_alive_finish(struct request *rq,
|
|
- blk_status_t status, struct nvme_ctrl *ctrl)
|
|
+static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
|
|
+ blk_status_t status)
|
|
{
|
|
- unsigned long flags;
|
|
- bool startka = false;
|
|
+ struct nvme_ctrl *ctrl = rq->end_io_data;
|
|
unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
|
|
unsigned long delay = nvme_keep_alive_work_period(ctrl);
|
|
+ enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);
|
|
|
|
/*
|
|
* Subtract off the keepalive RTT so nvme_keep_alive_work runs
|
|
@@ -1198,22 +1198,20 @@ static void nvme_keep_alive_finish(struct request *rq,
|
|
delay = 0;
|
|
}
|
|
|
|
+ blk_mq_free_request(rq);
|
|
+
|
|
if (status) {
|
|
dev_err(ctrl->device,
|
|
"failed nvme_keep_alive_end_io error=%d\n",
|
|
status);
|
|
- return;
|
|
+ return RQ_END_IO_NONE;
|
|
}
|
|
|
|
ctrl->ka_last_check_time = jiffies;
|
|
ctrl->comp_seen = false;
|
|
- spin_lock_irqsave(&ctrl->lock, flags);
|
|
- if (ctrl->state == NVME_CTRL_LIVE ||
|
|
- ctrl->state == NVME_CTRL_CONNECTING)
|
|
- startka = true;
|
|
- spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
- if (startka)
|
|
+ if (state == NVME_CTRL_LIVE || state == NVME_CTRL_CONNECTING)
|
|
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
|
|
+ return RQ_END_IO_NONE;
|
|
}
|
|
|
|
static void nvme_keep_alive_work(struct work_struct *work)
|
|
@@ -1222,7 +1220,6 @@ static void nvme_keep_alive_work(struct work_struct *work)
|
|
struct nvme_ctrl, ka_work);
|
|
bool comp_seen = ctrl->comp_seen;
|
|
struct request *rq;
|
|
- blk_status_t status;
|
|
|
|
ctrl->ka_last_check_time = jiffies;
|
|
|
|
@@ -1245,9 +1242,9 @@ static void nvme_keep_alive_work(struct work_struct *work)
|
|
nvme_init_request(rq, &ctrl->ka_cmd);
|
|
|
|
rq->timeout = ctrl->kato * HZ;
|
|
- status = blk_execute_rq(rq, false);
|
|
- nvme_keep_alive_finish(rq, status, ctrl);
|
|
- blk_mq_free_request(rq);
|
|
+ rq->end_io = nvme_keep_alive_end_io;
|
|
+ rq->end_io_data = ctrl;
|
|
+ blk_execute_rq_nowait(rq, false);
|
|
}
|
|
|
|
static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
|
|
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
|
|
index bddc068d58c7ea..e867ac859a878e 100644
|
|
--- a/drivers/nvme/host/nvme.h
|
|
+++ b/drivers/nvme/host/nvme.h
|
|
@@ -172,6 +172,11 @@ enum nvme_quirks {
|
|
* MSI (but not MSI-X) interrupts are broken and never fire.
|
|
*/
|
|
NVME_QUIRK_BROKEN_MSI = (1 << 21),
|
|
+
|
|
+ /*
|
|
+ * Align dma pool segment size to 512 bytes
|
|
+ */
|
|
+ NVME_QUIRK_DMAPOOL_ALIGN_512 = (1 << 22),
|
|
};
|
|
|
|
/*
|
|
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
|
|
index d525fa1229d791..52c8fd3d5c4796 100644
|
|
--- a/drivers/nvme/host/pci.c
|
|
+++ b/drivers/nvme/host/pci.c
|
|
@@ -2653,15 +2653,20 @@ static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown)
|
|
|
|
static int nvme_setup_prp_pools(struct nvme_dev *dev)
|
|
{
|
|
+ size_t small_align = 256;
|
|
+
|
|
dev->prp_page_pool = dma_pool_create("prp list page", dev->dev,
|
|
NVME_CTRL_PAGE_SIZE,
|
|
NVME_CTRL_PAGE_SIZE, 0);
|
|
if (!dev->prp_page_pool)
|
|
return -ENOMEM;
|
|
|
|
+ if (dev->ctrl.quirks & NVME_QUIRK_DMAPOOL_ALIGN_512)
|
|
+ small_align = 512;
|
|
+
|
|
/* Optimisation for I/Os between 4k and 128k */
|
|
dev->prp_small_pool = dma_pool_create("prp list 256", dev->dev,
|
|
- 256, 256, 0);
|
|
+ 256, small_align, 0);
|
|
if (!dev->prp_small_pool) {
|
|
dma_pool_destroy(dev->prp_page_pool);
|
|
return -ENOMEM;
|
|
@@ -3403,7 +3408,7 @@ static const struct pci_device_id nvme_id_table[] = {
|
|
{ PCI_VDEVICE(REDHAT, 0x0010), /* Qemu emulated controller */
|
|
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
|
{ PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */
|
|
- .driver_data = NVME_QUIRK_QDEPTH_ONE },
|
|
+ .driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, },
|
|
{ PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */
|
|
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
|
|
NVME_QUIRK_BOGUS_NID, },
|
|
diff --git a/drivers/of/address.c b/drivers/of/address.c
|
|
index dfd05cb2b2fcfa..34d880a1be0a5e 100644
|
|
--- a/drivers/of/address.c
|
|
+++ b/drivers/of/address.c
|
|
@@ -46,7 +46,7 @@ struct of_bus {
|
|
u64 (*map)(__be32 *addr, const __be32 *range,
|
|
int na, int ns, int pna);
|
|
int (*translate)(__be32 *addr, u64 offset, int na);
|
|
- bool has_flags;
|
|
+ int flag_cells;
|
|
unsigned int (*get_flags)(const __be32 *addr);
|
|
};
|
|
|
|
@@ -217,10 +217,6 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
|
|
return da - cp;
|
|
}
|
|
|
|
-static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
|
|
-{
|
|
- return of_bus_default_translate(addr + 1, offset, na - 1);
|
|
-}
|
|
#endif /* CONFIG_PCI */
|
|
|
|
/*
|
|
@@ -344,11 +340,6 @@ static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
|
|
return da - cp;
|
|
}
|
|
|
|
-static int of_bus_isa_translate(__be32 *addr, u64 offset, int na)
|
|
-{
|
|
- return of_bus_default_translate(addr + 1, offset, na - 1);
|
|
-}
|
|
-
|
|
static unsigned int of_bus_isa_get_flags(const __be32 *addr)
|
|
{
|
|
unsigned int flags = 0;
|
|
@@ -379,8 +370,8 @@ static struct of_bus of_busses[] = {
|
|
.match = of_bus_pci_match,
|
|
.count_cells = of_bus_pci_count_cells,
|
|
.map = of_bus_pci_map,
|
|
- .translate = of_bus_pci_translate,
|
|
- .has_flags = true,
|
|
+ .translate = of_bus_default_flags_translate,
|
|
+ .flag_cells = 1,
|
|
.get_flags = of_bus_pci_get_flags,
|
|
},
|
|
#endif /* CONFIG_PCI */
|
|
@@ -391,8 +382,8 @@ static struct of_bus of_busses[] = {
|
|
.match = of_bus_isa_match,
|
|
.count_cells = of_bus_isa_count_cells,
|
|
.map = of_bus_isa_map,
|
|
- .translate = of_bus_isa_translate,
|
|
- .has_flags = true,
|
|
+ .translate = of_bus_default_flags_translate,
|
|
+ .flag_cells = 1,
|
|
.get_flags = of_bus_isa_get_flags,
|
|
},
|
|
/* Default with flags cell */
|
|
@@ -403,7 +394,7 @@ static struct of_bus of_busses[] = {
|
|
.count_cells = of_bus_default_count_cells,
|
|
.map = of_bus_default_flags_map,
|
|
.translate = of_bus_default_flags_translate,
|
|
- .has_flags = true,
|
|
+ .flag_cells = 1,
|
|
.get_flags = of_bus_default_flags_get_flags,
|
|
},
|
|
/* Default */
|
|
@@ -485,7 +476,8 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
|
|
}
|
|
if (ranges == NULL || rlen == 0) {
|
|
offset = of_read_number(addr, na);
|
|
- memset(addr, 0, pna * 4);
|
|
+ /* set address to zero, pass flags through */
|
|
+ memset(addr + pbus->flag_cells, 0, (pna - pbus->flag_cells) * 4);
|
|
pr_debug("empty ranges; 1:1 translation\n");
|
|
goto finish;
|
|
}
|
|
@@ -836,7 +828,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
|
|
int na = parser->na;
|
|
int ns = parser->ns;
|
|
int np = parser->pna + na + ns;
|
|
- int busflag_na = 0;
|
|
+ int busflag_na = parser->bus->flag_cells;
|
|
|
|
if (!range)
|
|
return NULL;
|
|
@@ -846,10 +838,6 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
|
|
|
|
range->flags = parser->bus->get_flags(parser->range);
|
|
|
|
- /* A extra cell for resource flags */
|
|
- if (parser->bus->has_flags)
|
|
- busflag_na = 1;
|
|
-
|
|
range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
|
|
|
|
if (parser->dma)
|
|
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
|
|
index 4551575e4e7d7d..fd97b6ee2a8d11 100644
|
|
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
|
|
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
|
|
@@ -86,6 +86,7 @@ const struct regmap_config mcp23x08_regmap = {
|
|
.num_reg_defaults = ARRAY_SIZE(mcp23x08_defaults),
|
|
.cache_type = REGCACHE_FLAT,
|
|
.max_register = MCP_OLAT,
|
|
+ .disable_locking = true, /* mcp->lock protects the regmap */
|
|
};
|
|
EXPORT_SYMBOL_GPL(mcp23x08_regmap);
|
|
|
|
@@ -132,6 +133,7 @@ const struct regmap_config mcp23x17_regmap = {
|
|
.num_reg_defaults = ARRAY_SIZE(mcp23x17_defaults),
|
|
.cache_type = REGCACHE_FLAT,
|
|
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
|
+ .disable_locking = true, /* mcp->lock protects the regmap */
|
|
};
|
|
EXPORT_SYMBOL_GPL(mcp23x17_regmap);
|
|
|
|
@@ -228,7 +230,9 @@ static int mcp_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
|
|
|
switch (param) {
|
|
case PIN_CONFIG_BIAS_PULL_UP:
|
|
+ mutex_lock(&mcp->lock);
|
|
ret = mcp_read(mcp, MCP_GPPU, &data);
|
|
+ mutex_unlock(&mcp->lock);
|
|
if (ret < 0)
|
|
return ret;
|
|
status = (data & BIT(pin)) ? 1 : 0;
|
|
@@ -257,7 +261,9 @@ static int mcp_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
|
|
|
switch (param) {
|
|
case PIN_CONFIG_BIAS_PULL_UP:
|
|
+ mutex_lock(&mcp->lock);
|
|
ret = mcp_set_bit(mcp, MCP_GPPU, pin, arg);
|
|
+ mutex_unlock(&mcp->lock);
|
|
break;
|
|
default:
|
|
dev_dbg(mcp->dev, "Invalid config param %04x\n", param);
|
|
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
|
index a2ffe4157df10c..b8d77adc9ea145 100644
|
|
--- a/drivers/platform/x86/mlx-platform.c
|
|
+++ b/drivers/platform/x86/mlx-platform.c
|
|
@@ -6237,6 +6237,7 @@ mlxplat_pci_fpga_device_init(unsigned int device, const char *res_name, struct p
|
|
fail_pci_request_regions:
|
|
pci_disable_device(pci_dev);
|
|
fail_pci_enable_device:
|
|
+ pci_dev_put(pci_dev);
|
|
return err;
|
|
}
|
|
|
|
@@ -6247,6 +6248,7 @@ mlxplat_pci_fpga_device_exit(struct pci_dev *pci_bridge,
|
|
iounmap(pci_bridge_addr);
|
|
pci_release_regions(pci_bridge);
|
|
pci_disable_device(pci_bridge);
|
|
+ pci_dev_put(pci_bridge);
|
|
}
|
|
|
|
static int
|
|
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
|
|
index 6235721f2c1aec..fd6bf9e77afcb8 100644
|
|
--- a/drivers/remoteproc/qcom_q6v5_pas.c
|
|
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
|
|
@@ -786,6 +786,23 @@ static const struct adsp_data adsp_resource_init = {
|
|
.ssctl_id = 0x14,
|
|
};
|
|
|
|
+static const struct adsp_data sa8775p_adsp_resource = {
|
|
+ .crash_reason_smem = 423,
|
|
+ .firmware_name = "adsp.mbn",
|
|
+ .pas_id = 1,
|
|
+ .minidump_id = 5,
|
|
+ .auto_boot = true,
|
|
+ .proxy_pd_names = (char*[]){
|
|
+ "lcx",
|
|
+ "lmx",
|
|
+ NULL
|
|
+ },
|
|
+ .load_state = "adsp",
|
|
+ .ssr_name = "lpass",
|
|
+ .sysmon_name = "adsp",
|
|
+ .ssctl_id = 0x14,
|
|
+};
|
|
+
|
|
static const struct adsp_data sdm845_adsp_resource_init = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
@@ -885,6 +902,42 @@ static const struct adsp_data cdsp_resource_init = {
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
+static const struct adsp_data sa8775p_cdsp0_resource = {
|
|
+ .crash_reason_smem = 601,
|
|
+ .firmware_name = "cdsp0.mbn",
|
|
+ .pas_id = 18,
|
|
+ .minidump_id = 7,
|
|
+ .auto_boot = true,
|
|
+ .proxy_pd_names = (char*[]){
|
|
+ "cx",
|
|
+ "mxc",
|
|
+ "nsp",
|
|
+ NULL
|
|
+ },
|
|
+ .load_state = "cdsp",
|
|
+ .ssr_name = "cdsp",
|
|
+ .sysmon_name = "cdsp",
|
|
+ .ssctl_id = 0x17,
|
|
+};
|
|
+
|
|
+static const struct adsp_data sa8775p_cdsp1_resource = {
|
|
+ .crash_reason_smem = 633,
|
|
+ .firmware_name = "cdsp1.mbn",
|
|
+ .pas_id = 30,
|
|
+ .minidump_id = 20,
|
|
+ .auto_boot = true,
|
|
+ .proxy_pd_names = (char*[]){
|
|
+ "cx",
|
|
+ "mxc",
|
|
+ "nsp",
|
|
+ NULL
|
|
+ },
|
|
+ .load_state = "nsp",
|
|
+ .ssr_name = "cdsp1",
|
|
+ .sysmon_name = "cdsp1",
|
|
+ .ssctl_id = 0x20,
|
|
+};
|
|
+
|
|
static const struct adsp_data sdm845_cdsp_resource_init = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
@@ -987,6 +1040,40 @@ static const struct adsp_data sm8350_cdsp_resource = {
|
|
.ssctl_id = 0x17,
|
|
};
|
|
|
|
+static const struct adsp_data sa8775p_gpdsp0_resource = {
|
|
+ .crash_reason_smem = 640,
|
|
+ .firmware_name = "gpdsp0.mbn",
|
|
+ .pas_id = 39,
|
|
+ .minidump_id = 21,
|
|
+ .auto_boot = true,
|
|
+ .proxy_pd_names = (char*[]){
|
|
+ "cx",
|
|
+ "mxc",
|
|
+ NULL
|
|
+ },
|
|
+ .load_state = "gpdsp0",
|
|
+ .ssr_name = "gpdsp0",
|
|
+ .sysmon_name = "gpdsp0",
|
|
+ .ssctl_id = 0x21,
|
|
+};
|
|
+
|
|
+static const struct adsp_data sa8775p_gpdsp1_resource = {
|
|
+ .crash_reason_smem = 641,
|
|
+ .firmware_name = "gpdsp1.mbn",
|
|
+ .pas_id = 40,
|
|
+ .minidump_id = 22,
|
|
+ .auto_boot = true,
|
|
+ .proxy_pd_names = (char*[]){
|
|
+ "cx",
|
|
+ "mxc",
|
|
+ NULL
|
|
+ },
|
|
+ .load_state = "gpdsp1",
|
|
+ .ssr_name = "gpdsp1",
|
|
+ .sysmon_name = "gpdsp1",
|
|
+ .ssctl_id = 0x22,
|
|
+};
|
|
+
|
|
static const struct adsp_data mpss_resource_init = {
|
|
.crash_reason_smem = 421,
|
|
.firmware_name = "modem.mdt",
|
|
@@ -1163,6 +1250,13 @@ static const struct of_device_id adsp_of_match[] = {
|
|
{ .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init },
|
|
{ .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init },
|
|
{ .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },
|
|
+ { .compatible = "qcom,sa8775p-adsp-pas", .data = &sa8775p_adsp_resource},
|
|
+ { .compatible = "qcom,sa8775p-cdsp0-pas", .data = &sa8775p_cdsp0_resource},
|
|
+ { .compatible = "qcom,sa8775p-cdsp1-pas", .data = &sa8775p_cdsp1_resource},
|
|
+ { .compatible = "qcom,sa8775p-gpdsp0-pas", .data = &sa8775p_gpdsp0_resource},
|
|
+ { .compatible = "qcom,sa8775p-gpdsp1-pas", .data = &sa8775p_gpdsp1_resource},
|
|
+ { .compatible = "qcom,sar2130p-adsp-pas", .data = &sm8350_adsp_resource},
|
|
+ { .compatible = "qcom,sc7180-adsp-pas", .data = &sm8250_adsp_resource},
|
|
{ .compatible = "qcom,sc7180-mpss-pas", .data = &mpss_resource_init},
|
|
{ .compatible = "qcom,sc7280-mpss-pas", .data = &mpss_resource_init},
|
|
{ .compatible = "qcom,sc8180x-adsp-pas", .data = &sm8150_adsp_resource},
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
|
|
index 9e73e9cbbcfc6c..1e4550156b735d 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas.h
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
|
|
@@ -343,7 +343,7 @@ struct hisi_sas_hw {
|
|
u8 reg_index, u8 reg_count, u8 *write_data);
|
|
void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba,
|
|
int delay_ms, int timeout_ms);
|
|
- void (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba);
|
|
+ int (*debugfs_snapshot_regs)(struct hisi_hba *hisi_hba);
|
|
int complete_hdr_size;
|
|
const struct scsi_host_template *sht;
|
|
};
|
|
@@ -451,7 +451,6 @@ struct hisi_hba {
|
|
const struct hisi_sas_hw *hw; /* Low level hw interface */
|
|
unsigned long sata_dev_bitmap[BITS_TO_LONGS(HISI_SAS_MAX_DEVICES)];
|
|
struct work_struct rst_work;
|
|
- struct work_struct debugfs_work;
|
|
u32 phy_state;
|
|
u32 intr_coal_ticks; /* Time of interrupt coalesce in us */
|
|
u32 intr_coal_count; /* Interrupt count to coalesce */
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
index db9ae206974c21..f78c5f8a49ffac 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
@@ -1579,7 +1579,7 @@ static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba)
|
|
return -EPERM;
|
|
}
|
|
|
|
- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
|
|
+ if (hisi_sas_debugfs_enable)
|
|
hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);
|
|
|
|
return 0;
|
|
@@ -1967,8 +1967,19 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,
|
|
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
|
|
struct hisi_sas_internal_abort_data *timeout = data;
|
|
|
|
- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
|
|
- queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
|
|
+ if (hisi_sas_debugfs_enable) {
|
|
+ /*
|
|
+ * If timeout occurs in device gone scenario, to avoid
|
|
+ * circular dependency like:
|
|
+ * hisi_sas_dev_gone() -> down() -> ... ->
|
|
+ * hisi_sas_internal_abort_timeout() -> down().
|
|
+ */
|
|
+ if (!timeout->rst_ha_timeout)
|
|
+ down(&hisi_hba->sem);
|
|
+ hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);
|
|
+ if (!timeout->rst_ha_timeout)
|
|
+ up(&hisi_hba->sem);
|
|
+ }
|
|
|
|
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
|
|
pr_err("Internal abort: timeout %016llx\n",
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
index 4054659d48f74c..ff5f86867dbf06 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
@@ -558,8 +558,7 @@ static int experimental_iopoll_q_cnt;
|
|
module_param(experimental_iopoll_q_cnt, int, 0444);
|
|
MODULE_PARM_DESC(experimental_iopoll_q_cnt, "number of queues to be used as poll mode, def=0");
|
|
|
|
-static void debugfs_work_handler_v3_hw(struct work_struct *work);
|
|
-static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba);
|
|
+static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba);
|
|
|
|
static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
|
|
{
|
|
@@ -3397,7 +3396,6 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
|
|
hisi_hba = shost_priv(shost);
|
|
|
|
INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler);
|
|
- INIT_WORK(&hisi_hba->debugfs_work, debugfs_work_handler_v3_hw);
|
|
hisi_hba->hw = &hisi_sas_v3_hw;
|
|
hisi_hba->pci_dev = pdev;
|
|
hisi_hba->dev = dev;
|
|
@@ -3562,6 +3560,11 @@ debugfs_to_reg_name_v3_hw(int off, int base_off,
|
|
return NULL;
|
|
}
|
|
|
|
+static bool debugfs_dump_is_generated_v3_hw(void *p)
|
|
+{
|
|
+ return p ? true : false;
|
|
+}
|
|
+
|
|
static void debugfs_print_reg_v3_hw(u32 *regs_val, struct seq_file *s,
|
|
const struct hisi_sas_debugfs_reg *reg)
|
|
{
|
|
@@ -3587,6 +3590,9 @@ static int debugfs_global_v3_hw_show(struct seq_file *s, void *p)
|
|
{
|
|
struct hisi_sas_debugfs_regs *global = s->private;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(global->data))
|
|
+ return -EPERM;
|
|
+
|
|
debugfs_print_reg_v3_hw(global->data, s,
|
|
&debugfs_global_reg);
|
|
|
|
@@ -3598,6 +3604,9 @@ static int debugfs_axi_v3_hw_show(struct seq_file *s, void *p)
|
|
{
|
|
struct hisi_sas_debugfs_regs *axi = s->private;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(axi->data))
|
|
+ return -EPERM;
|
|
+
|
|
debugfs_print_reg_v3_hw(axi->data, s,
|
|
&debugfs_axi_reg);
|
|
|
|
@@ -3609,6 +3618,9 @@ static int debugfs_ras_v3_hw_show(struct seq_file *s, void *p)
|
|
{
|
|
struct hisi_sas_debugfs_regs *ras = s->private;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(ras->data))
|
|
+ return -EPERM;
|
|
+
|
|
debugfs_print_reg_v3_hw(ras->data, s,
|
|
&debugfs_ras_reg);
|
|
|
|
@@ -3621,6 +3633,9 @@ static int debugfs_port_v3_hw_show(struct seq_file *s, void *p)
|
|
struct hisi_sas_debugfs_port *port = s->private;
|
|
const struct hisi_sas_debugfs_reg *reg_port = &debugfs_port_reg;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(port->data))
|
|
+ return -EPERM;
|
|
+
|
|
debugfs_print_reg_v3_hw(port->data, s, reg_port);
|
|
|
|
return 0;
|
|
@@ -3676,6 +3691,9 @@ static int debugfs_cq_v3_hw_show(struct seq_file *s, void *p)
|
|
struct hisi_sas_debugfs_cq *debugfs_cq = s->private;
|
|
int slot;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(debugfs_cq->complete_hdr))
|
|
+ return -EPERM;
|
|
+
|
|
for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++)
|
|
debugfs_cq_show_slot_v3_hw(s, slot, debugfs_cq);
|
|
|
|
@@ -3697,8 +3715,12 @@ static void debugfs_dq_show_slot_v3_hw(struct seq_file *s, int slot,
|
|
|
|
static int debugfs_dq_v3_hw_show(struct seq_file *s, void *p)
|
|
{
|
|
+ struct hisi_sas_debugfs_dq *debugfs_dq = s->private;
|
|
int slot;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(debugfs_dq->hdr))
|
|
+ return -EPERM;
|
|
+
|
|
for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++)
|
|
debugfs_dq_show_slot_v3_hw(s, slot, s->private);
|
|
|
|
@@ -3712,6 +3734,9 @@ static int debugfs_iost_v3_hw_show(struct seq_file *s, void *p)
|
|
struct hisi_sas_iost *iost = debugfs_iost->iost;
|
|
int i, max_command_entries = HISI_SAS_MAX_COMMANDS;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(iost))
|
|
+ return -EPERM;
|
|
+
|
|
for (i = 0; i < max_command_entries; i++, iost++) {
|
|
__le64 *data = &iost->qw0;
|
|
|
|
@@ -3731,6 +3756,9 @@ static int debugfs_iost_cache_v3_hw_show(struct seq_file *s, void *p)
|
|
int i, tab_idx;
|
|
__le64 *iost;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(iost_cache))
|
|
+ return -EPERM;
|
|
+
|
|
for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) {
|
|
/*
|
|
* Data struct of IOST cache:
|
|
@@ -3754,6 +3782,9 @@ static int debugfs_itct_v3_hw_show(struct seq_file *s, void *p)
|
|
struct hisi_sas_debugfs_itct *debugfs_itct = s->private;
|
|
struct hisi_sas_itct *itct = debugfs_itct->itct;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(itct))
|
|
+ return -EPERM;
|
|
+
|
|
for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
|
|
__le64 *data = &itct->qw0;
|
|
|
|
@@ -3773,6 +3804,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p)
|
|
int i, tab_idx;
|
|
__le64 *itct;
|
|
|
|
+ if (!debugfs_dump_is_generated_v3_hw(itct_cache))
|
|
+ return -EPERM;
|
|
+
|
|
for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) {
|
|
/*
|
|
* Data struct of ITCT cache:
|
|
@@ -3790,10 +3824,9 @@ static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p)
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(debugfs_itct_cache_v3_hw);
|
|
|
|
-static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
|
|
+static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba, int index)
|
|
{
|
|
u64 *debugfs_timestamp;
|
|
- int dump_index = hisi_hba->debugfs_dump_index;
|
|
struct dentry *dump_dentry;
|
|
struct dentry *dentry;
|
|
char name[256];
|
|
@@ -3801,17 +3834,17 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
|
|
int c;
|
|
int d;
|
|
|
|
- snprintf(name, 256, "%d", dump_index);
|
|
+ snprintf(name, 256, "%d", index);
|
|
|
|
dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry);
|
|
|
|
- debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index];
|
|
+ debugfs_timestamp = &hisi_hba->debugfs_timestamp[index];
|
|
|
|
debugfs_create_u64("timestamp", 0400, dump_dentry,
|
|
debugfs_timestamp);
|
|
|
|
debugfs_create_file("global", 0400, dump_dentry,
|
|
- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL],
|
|
+ &hisi_hba->debugfs_regs[index][DEBUGFS_GLOBAL],
|
|
&debugfs_global_v3_hw_fops);
|
|
|
|
/* Create port dir and files */
|
|
@@ -3820,7 +3853,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
|
|
snprintf(name, 256, "%d", p);
|
|
|
|
debugfs_create_file(name, 0400, dentry,
|
|
- &hisi_hba->debugfs_port_reg[dump_index][p],
|
|
+ &hisi_hba->debugfs_port_reg[index][p],
|
|
&debugfs_port_v3_hw_fops);
|
|
}
|
|
|
|
@@ -3830,7 +3863,7 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
|
|
snprintf(name, 256, "%d", c);
|
|
|
|
debugfs_create_file(name, 0400, dentry,
|
|
- &hisi_hba->debugfs_cq[dump_index][c],
|
|
+ &hisi_hba->debugfs_cq[index][c],
|
|
&debugfs_cq_v3_hw_fops);
|
|
}
|
|
|
|
@@ -3840,66 +3873,35 @@ static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba)
|
|
snprintf(name, 256, "%d", d);
|
|
|
|
debugfs_create_file(name, 0400, dentry,
|
|
- &hisi_hba->debugfs_dq[dump_index][d],
|
|
+ &hisi_hba->debugfs_dq[index][d],
|
|
&debugfs_dq_v3_hw_fops);
|
|
}
|
|
|
|
debugfs_create_file("iost", 0400, dump_dentry,
|
|
- &hisi_hba->debugfs_iost[dump_index],
|
|
+ &hisi_hba->debugfs_iost[index],
|
|
&debugfs_iost_v3_hw_fops);
|
|
|
|
debugfs_create_file("iost_cache", 0400, dump_dentry,
|
|
- &hisi_hba->debugfs_iost_cache[dump_index],
|
|
+ &hisi_hba->debugfs_iost_cache[index],
|
|
&debugfs_iost_cache_v3_hw_fops);
|
|
|
|
debugfs_create_file("itct", 0400, dump_dentry,
|
|
- &hisi_hba->debugfs_itct[dump_index],
|
|
+ &hisi_hba->debugfs_itct[index],
|
|
&debugfs_itct_v3_hw_fops);
|
|
|
|
debugfs_create_file("itct_cache", 0400, dump_dentry,
|
|
- &hisi_hba->debugfs_itct_cache[dump_index],
|
|
+ &hisi_hba->debugfs_itct_cache[index],
|
|
&debugfs_itct_cache_v3_hw_fops);
|
|
|
|
debugfs_create_file("axi", 0400, dump_dentry,
|
|
- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI],
|
|
+ &hisi_hba->debugfs_regs[index][DEBUGFS_AXI],
|
|
&debugfs_axi_v3_hw_fops);
|
|
|
|
debugfs_create_file("ras", 0400, dump_dentry,
|
|
- &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS],
|
|
+ &hisi_hba->debugfs_regs[index][DEBUGFS_RAS],
|
|
&debugfs_ras_v3_hw_fops);
|
|
}
|
|
|
|
-static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
|
|
-{
|
|
- int debugfs_dump_index = hisi_hba->debugfs_dump_index;
|
|
- struct device *dev = hisi_hba->dev;
|
|
- u64 timestamp = local_clock();
|
|
-
|
|
- if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
|
|
- dev_warn(dev, "dump count exceeded!\n");
|
|
- return;
|
|
- }
|
|
-
|
|
- do_div(timestamp, NSEC_PER_MSEC);
|
|
- hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
|
|
-
|
|
- debugfs_snapshot_prepare_v3_hw(hisi_hba);
|
|
-
|
|
- debugfs_snapshot_global_reg_v3_hw(hisi_hba);
|
|
- debugfs_snapshot_port_reg_v3_hw(hisi_hba);
|
|
- debugfs_snapshot_axi_reg_v3_hw(hisi_hba);
|
|
- debugfs_snapshot_ras_reg_v3_hw(hisi_hba);
|
|
- debugfs_snapshot_cq_reg_v3_hw(hisi_hba);
|
|
- debugfs_snapshot_dq_reg_v3_hw(hisi_hba);
|
|
- debugfs_snapshot_itct_reg_v3_hw(hisi_hba);
|
|
- debugfs_snapshot_iost_reg_v3_hw(hisi_hba);
|
|
-
|
|
- debugfs_create_files_v3_hw(hisi_hba);
|
|
-
|
|
- debugfs_snapshot_restore_v3_hw(hisi_hba);
|
|
- hisi_hba->debugfs_dump_index++;
|
|
-}
|
|
-
|
|
static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
|
|
const char __user *user_buf,
|
|
size_t count, loff_t *ppos)
|
|
@@ -3907,9 +3909,6 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
|
|
struct hisi_hba *hisi_hba = file->f_inode->i_private;
|
|
char buf[8];
|
|
|
|
- if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count)
|
|
- return -EFAULT;
|
|
-
|
|
if (count > 8)
|
|
return -EFAULT;
|
|
|
|
@@ -3919,7 +3918,12 @@ static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file,
|
|
if (buf[0] != '1')
|
|
return -EFAULT;
|
|
|
|
- queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
|
|
+ down(&hisi_hba->sem);
|
|
+ if (debugfs_snapshot_regs_v3_hw(hisi_hba)) {
|
|
+ up(&hisi_hba->sem);
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ up(&hisi_hba->sem);
|
|
|
|
return count;
|
|
}
|
|
@@ -4670,36 +4674,40 @@ static void debugfs_fifo_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
}
|
|
}
|
|
|
|
-static void debugfs_work_handler_v3_hw(struct work_struct *work)
|
|
-{
|
|
- struct hisi_hba *hisi_hba =
|
|
- container_of(work, struct hisi_hba, debugfs_work);
|
|
-
|
|
- debugfs_snapshot_regs_v3_hw(hisi_hba);
|
|
-}
|
|
-
|
|
static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
|
|
{
|
|
struct device *dev = hisi_hba->dev;
|
|
int i;
|
|
|
|
devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache);
|
|
+ hisi_hba->debugfs_iost_cache[dump_index].cache = NULL;
|
|
devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache);
|
|
+ hisi_hba->debugfs_itct_cache[dump_index].cache = NULL;
|
|
devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost);
|
|
+ hisi_hba->debugfs_iost[dump_index].iost = NULL;
|
|
devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct);
|
|
+ hisi_hba->debugfs_itct[dump_index].itct = NULL;
|
|
|
|
- for (i = 0; i < hisi_hba->queue_count; i++)
|
|
+ for (i = 0; i < hisi_hba->queue_count; i++) {
|
|
devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr);
|
|
+ hisi_hba->debugfs_dq[dump_index][i].hdr = NULL;
|
|
+ }
|
|
|
|
- for (i = 0; i < hisi_hba->queue_count; i++)
|
|
+ for (i = 0; i < hisi_hba->queue_count; i++) {
|
|
devm_kfree(dev,
|
|
hisi_hba->debugfs_cq[dump_index][i].complete_hdr);
|
|
+ hisi_hba->debugfs_cq[dump_index][i].complete_hdr = NULL;
|
|
+ }
|
|
|
|
- for (i = 0; i < DEBUGFS_REGS_NUM; i++)
|
|
+ for (i = 0; i < DEBUGFS_REGS_NUM; i++) {
|
|
devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data);
|
|
+ hisi_hba->debugfs_regs[dump_index][i].data = NULL;
|
|
+ }
|
|
|
|
- for (i = 0; i < hisi_hba->n_phy; i++)
|
|
+ for (i = 0; i < hisi_hba->n_phy; i++) {
|
|
devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data);
|
|
+ hisi_hba->debugfs_port_reg[dump_index][i].data = NULL;
|
|
+ }
|
|
}
|
|
|
|
static const struct hisi_sas_debugfs_reg *debugfs_reg_array_v3_hw[DEBUGFS_REGS_NUM] = {
|
|
@@ -4712,7 +4720,7 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
|
|
{
|
|
const struct hisi_sas_hw *hw = hisi_hba->hw;
|
|
struct device *dev = hisi_hba->dev;
|
|
- int p, c, d, r, i;
|
|
+ int p, c, d, r;
|
|
size_t sz;
|
|
|
|
for (r = 0; r < DEBUGFS_REGS_NUM; r++) {
|
|
@@ -4792,11 +4800,46 @@ static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index)
|
|
|
|
return 0;
|
|
fail:
|
|
- for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
|
|
- debugfs_release_v3_hw(hisi_hba, i);
|
|
+ debugfs_release_v3_hw(hisi_hba, dump_index);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
+static int debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba)
|
|
+{
|
|
+ int debugfs_dump_index = hisi_hba->debugfs_dump_index;
|
|
+ struct device *dev = hisi_hba->dev;
|
|
+ u64 timestamp = local_clock();
|
|
+
|
|
+ if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
|
|
+ dev_warn(dev, "dump count exceeded!\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (debugfs_alloc_v3_hw(hisi_hba, debugfs_dump_index)) {
|
|
+ dev_warn(dev, "failed to alloc memory\n");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ do_div(timestamp, NSEC_PER_MSEC);
|
|
+ hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
|
|
+
|
|
+ debugfs_snapshot_prepare_v3_hw(hisi_hba);
|
|
+
|
|
+ debugfs_snapshot_global_reg_v3_hw(hisi_hba);
|
|
+ debugfs_snapshot_port_reg_v3_hw(hisi_hba);
|
|
+ debugfs_snapshot_axi_reg_v3_hw(hisi_hba);
|
|
+ debugfs_snapshot_ras_reg_v3_hw(hisi_hba);
|
|
+ debugfs_snapshot_cq_reg_v3_hw(hisi_hba);
|
|
+ debugfs_snapshot_dq_reg_v3_hw(hisi_hba);
|
|
+ debugfs_snapshot_itct_reg_v3_hw(hisi_hba);
|
|
+ debugfs_snapshot_iost_reg_v3_hw(hisi_hba);
|
|
+
|
|
+ debugfs_snapshot_restore_v3_hw(hisi_hba);
|
|
+ hisi_hba->debugfs_dump_index++;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void debugfs_phy_down_cnt_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
{
|
|
struct dentry *dir = debugfs_create_dir("phy_down_cnt",
|
|
@@ -4874,6 +4917,17 @@ static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS;
|
|
}
|
|
|
|
+static void debugfs_dump_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ hisi_hba->debugfs_dump_dentry =
|
|
+ debugfs_create_dir("dump", hisi_hba->debugfs_dir);
|
|
+
|
|
+ for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
|
|
+ debugfs_create_files_v3_hw(hisi_hba, i);
|
|
+}
|
|
+
|
|
static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
|
|
{
|
|
debugfs_remove_recursive(hisi_hba->debugfs_dir);
|
|
@@ -4883,7 +4937,6 @@ static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
|
|
static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
{
|
|
struct device *dev = hisi_hba->dev;
|
|
- int i;
|
|
|
|
hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
|
|
hisi_sas_debugfs_dir);
|
|
@@ -4895,19 +4948,10 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
/* create bist structures */
|
|
debugfs_bist_init_v3_hw(hisi_hba);
|
|
|
|
- hisi_hba->debugfs_dump_dentry =
|
|
- debugfs_create_dir("dump", hisi_hba->debugfs_dir);
|
|
+ debugfs_dump_init_v3_hw(hisi_hba);
|
|
|
|
debugfs_phy_down_cnt_init_v3_hw(hisi_hba);
|
|
debugfs_fifo_init_v3_hw(hisi_hba);
|
|
-
|
|
- for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
|
|
- if (debugfs_alloc_v3_hw(hisi_hba, i)) {
|
|
- debugfs_exit_v3_hw(hisi_hba);
|
|
- dev_dbg(dev, "failed to init debugfs!\n");
|
|
- break;
|
|
- }
|
|
- }
|
|
}
|
|
|
|
static int
|
|
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
|
|
index 7f32619234696f..7880675a68dba6 100644
|
|
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
|
|
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
|
|
@@ -8,11 +8,12 @@
|
|
*/
|
|
|
|
#include "mpi3mr.h"
|
|
+#include <linux/idr.h>
|
|
|
|
/* global driver scop variables */
|
|
LIST_HEAD(mrioc_list);
|
|
DEFINE_SPINLOCK(mrioc_list_lock);
|
|
-static int mrioc_ids;
|
|
+static DEFINE_IDA(mrioc_ida);
|
|
static int warn_non_secure_ctlr;
|
|
atomic64_t event_counter;
|
|
|
|
@@ -5065,7 +5066,10 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
}
|
|
|
|
mrioc = shost_priv(shost);
|
|
- mrioc->id = mrioc_ids++;
|
|
+ retval = ida_alloc_range(&mrioc_ida, 0, U8_MAX, GFP_KERNEL);
|
|
+ if (retval < 0)
|
|
+ goto id_alloc_failed;
|
|
+ mrioc->id = (u8)retval;
|
|
sprintf(mrioc->driver_name, "%s", MPI3MR_DRIVER_NAME);
|
|
sprintf(mrioc->name, "%s%d", mrioc->driver_name, mrioc->id);
|
|
INIT_LIST_HEAD(&mrioc->list);
|
|
@@ -5215,9 +5219,11 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
resource_alloc_failed:
|
|
destroy_workqueue(mrioc->fwevt_worker_thread);
|
|
fwevtthread_failed:
|
|
+ ida_free(&mrioc_ida, mrioc->id);
|
|
spin_lock(&mrioc_list_lock);
|
|
list_del(&mrioc->list);
|
|
spin_unlock(&mrioc_list_lock);
|
|
+id_alloc_failed:
|
|
scsi_host_put(shost);
|
|
shost_failed:
|
|
return retval;
|
|
@@ -5303,6 +5309,7 @@ static void mpi3mr_remove(struct pci_dev *pdev)
|
|
mrioc->sas_hba.num_phys = 0;
|
|
}
|
|
|
|
+ ida_free(&mrioc_ida, mrioc->id);
|
|
spin_lock(&mrioc_list_lock);
|
|
list_del(&mrioc->list);
|
|
spin_unlock(&mrioc_list_lock);
|
|
@@ -5518,6 +5525,7 @@ static void __exit mpi3mr_exit(void)
|
|
&driver_attr_event_counter);
|
|
pci_unregister_driver(&mpi3mr_pci_driver);
|
|
sas_release_transport(mpi3mr_transport_template);
|
|
+ ida_destroy(&mrioc_ida);
|
|
}
|
|
|
|
module_init(mpi3mr_init);
|
|
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
|
|
index 1ec6f9c82aef06..79f2bf5df19a6c 100644
|
|
--- a/drivers/thunderbolt/nhi.c
|
|
+++ b/drivers/thunderbolt/nhi.c
|
|
@@ -1524,6 +1524,18 @@ static struct pci_device_id nhi_ids[] = {
|
|
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL_P_NHI1),
|
|
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI0),
|
|
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI1),
|
|
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI0),
|
|
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI1),
|
|
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI0),
|
|
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI1),
|
|
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) },
|
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) },
|
|
|
|
diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h
|
|
index 0f029ce758825e..16744f25a9a069 100644
|
|
--- a/drivers/thunderbolt/nhi.h
|
|
+++ b/drivers/thunderbolt/nhi.h
|
|
@@ -90,6 +90,12 @@ extern const struct tb_nhi_ops icl_nhi_ops;
|
|
#define PCI_DEVICE_ID_INTEL_TGL_H_NHI1 0x9a21
|
|
#define PCI_DEVICE_ID_INTEL_RPL_NHI0 0xa73e
|
|
#define PCI_DEVICE_ID_INTEL_RPL_NHI1 0xa76d
|
|
+#define PCI_DEVICE_ID_INTEL_LNL_NHI0 0xa833
|
|
+#define PCI_DEVICE_ID_INTEL_LNL_NHI1 0xa834
|
|
+#define PCI_DEVICE_ID_INTEL_PTL_M_NHI0 0xe333
|
|
+#define PCI_DEVICE_ID_INTEL_PTL_M_NHI1 0xe334
|
|
+#define PCI_DEVICE_ID_INTEL_PTL_P_NHI0 0xe433
|
|
+#define PCI_DEVICE_ID_INTEL_PTL_P_NHI1 0xe434
|
|
|
|
#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340
|
|
|
|
diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c
|
|
index 47becb363adacb..2ee8c5ebca7c3c 100644
|
|
--- a/drivers/thunderbolt/retimer.c
|
|
+++ b/drivers/thunderbolt/retimer.c
|
|
@@ -98,6 +98,7 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt)
|
|
|
|
err_nvm:
|
|
dev_dbg(&rt->dev, "NVM upgrade disabled\n");
|
|
+ rt->no_nvm_upgrade = true;
|
|
if (!IS_ERR(nvm))
|
|
tb_nvm_free(nvm);
|
|
|
|
@@ -177,8 +178,6 @@ static ssize_t nvm_authenticate_show(struct device *dev,
|
|
|
|
if (!rt->nvm)
|
|
ret = -EAGAIN;
|
|
- else if (rt->no_nvm_upgrade)
|
|
- ret = -EOPNOTSUPP;
|
|
else
|
|
ret = sysfs_emit(buf, "%#x\n", rt->auth_status);
|
|
|
|
@@ -331,6 +330,19 @@ static ssize_t vendor_show(struct device *dev, struct device_attribute *attr,
|
|
}
|
|
static DEVICE_ATTR_RO(vendor);
|
|
|
|
+static umode_t retimer_is_visible(struct kobject *kobj, struct attribute *attr,
|
|
+ int n)
|
|
+{
|
|
+ struct device *dev = kobj_to_dev(kobj);
|
|
+ struct tb_retimer *rt = tb_to_retimer(dev);
|
|
+
|
|
+ if (attr == &dev_attr_nvm_authenticate.attr ||
|
|
+ attr == &dev_attr_nvm_version.attr)
|
|
+ return rt->no_nvm_upgrade ? 0 : attr->mode;
|
|
+
|
|
+ return attr->mode;
|
|
+}
|
|
+
|
|
static struct attribute *retimer_attrs[] = {
|
|
&dev_attr_device.attr,
|
|
&dev_attr_nvm_authenticate.attr,
|
|
@@ -340,6 +352,7 @@ static struct attribute *retimer_attrs[] = {
|
|
};
|
|
|
|
static const struct attribute_group retimer_group = {
|
|
+ .is_visible = retimer_is_visible,
|
|
.attrs = retimer_attrs,
|
|
};
|
|
|
|
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
|
|
index 2a38e1eb65466c..97437de52ef681 100644
|
|
--- a/drivers/usb/chipidea/ci.h
|
|
+++ b/drivers/usb/chipidea/ci.h
|
|
@@ -25,6 +25,7 @@
|
|
#define TD_PAGE_COUNT 5
|
|
#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
|
|
#define ENDPT_MAX 32
|
|
+#define CI_MAX_REQ_SIZE (4 * CI_HDRC_PAGE_SIZE)
|
|
#define CI_MAX_BUF_SIZE (TD_PAGE_COUNT * CI_HDRC_PAGE_SIZE)
|
|
|
|
/******************************************************************************
|
|
@@ -260,6 +261,7 @@ struct ci_hdrc {
|
|
bool b_sess_valid_event;
|
|
bool imx28_write_fix;
|
|
bool has_portsc_pec_bug;
|
|
+ bool has_short_pkt_limit;
|
|
bool supports_runtime_pm;
|
|
bool in_lpm;
|
|
bool wakeup_int;
|
|
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
|
|
index e28bb2f2612dc6..477af457c1a1f0 100644
|
|
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
|
|
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
|
|
@@ -334,6 +334,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
|
|
struct ci_hdrc_platform_data pdata = {
|
|
.name = dev_name(&pdev->dev),
|
|
.capoffset = DEF_CAPOFFSET,
|
|
+ .flags = CI_HDRC_HAS_SHORT_PKT_LIMIT,
|
|
.notify_event = ci_hdrc_imx_notify_event,
|
|
};
|
|
int ret;
|
|
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
|
|
index ca71df4f32e4cc..c161a4ee529064 100644
|
|
--- a/drivers/usb/chipidea/core.c
|
|
+++ b/drivers/usb/chipidea/core.c
|
|
@@ -1076,6 +1076,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|
CI_HDRC_SUPPORTS_RUNTIME_PM);
|
|
ci->has_portsc_pec_bug = !!(ci->platdata->flags &
|
|
CI_HDRC_HAS_PORTSC_PEC_MISSED);
|
|
+ ci->has_short_pkt_limit = !!(ci->platdata->flags &
|
|
+ CI_HDRC_HAS_SHORT_PKT_LIMIT);
|
|
platform_set_drvdata(pdev, ci);
|
|
|
|
ret = hw_device_init(ci, base);
|
|
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
|
|
index f5490f2a5b6bca..647e98f4e35110 100644
|
|
--- a/drivers/usb/chipidea/otg.c
|
|
+++ b/drivers/usb/chipidea/otg.c
|
|
@@ -130,8 +130,11 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
|
|
|
|
void ci_handle_vbus_change(struct ci_hdrc *ci)
|
|
{
|
|
- if (!ci->is_otg)
|
|
+ if (!ci->is_otg) {
|
|
+ if (ci->platdata->flags & CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS)
|
|
+ usb_gadget_vbus_connect(&ci->gadget);
|
|
return;
|
|
+ }
|
|
|
|
if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active)
|
|
usb_gadget_vbus_connect(&ci->gadget);
|
|
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
|
|
index 9f7d003e467b54..f2ae5f4c58283a 100644
|
|
--- a/drivers/usb/chipidea/udc.c
|
|
+++ b/drivers/usb/chipidea/udc.c
|
|
@@ -959,6 +959,12 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
|
|
return -EMSGSIZE;
|
|
}
|
|
|
|
+ if (ci->has_short_pkt_limit &&
|
|
+ hwreq->req.length > CI_MAX_REQ_SIZE) {
|
|
+ dev_err(hwep->ci->dev, "request length too big (max 16KB)\n");
|
|
+ return -EMSGSIZE;
|
|
+ }
|
|
+
|
|
/* first nuke then test link, e.g. previous status has not sent */
|
|
if (!list_empty(&hwreq->queue)) {
|
|
dev_err(hwep->ci->dev, "request already in queue\n");
|
|
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
|
|
index b118f4aab18984..d00bf714a7ccfb 100644
|
|
--- a/drivers/usb/dwc3/core.h
|
|
+++ b/drivers/usb/dwc3/core.h
|
|
@@ -899,6 +899,7 @@ struct dwc3_hwparams {
|
|
#define DWC3_MODE(n) ((n) & 0x7)
|
|
|
|
/* HWPARAMS1 */
|
|
+#define DWC3_SPRAM_TYPE(n) (((n) >> 23) & 1)
|
|
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
|
|
|
|
/* HWPARAMS3 */
|
|
@@ -909,6 +910,9 @@ struct dwc3_hwparams {
|
|
#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \
|
|
(DWC3_NUM_IN_EPS_MASK)) >> 18)
|
|
|
|
+/* HWPARAMS6 */
|
|
+#define DWC3_RAM0_DEPTH(n) (((n) & (0xffff0000)) >> 16)
|
|
+
|
|
/* HWPARAMS7 */
|
|
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
|
|
|
|
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
|
|
index b560996bd4218a..656460c0c1dd7e 100644
|
|
--- a/drivers/usb/dwc3/gadget.c
|
|
+++ b/drivers/usb/dwc3/gadget.c
|
|
@@ -687,6 +687,44 @@ static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
|
|
return fifo_size;
|
|
}
|
|
|
|
+/**
|
|
+ * dwc3_gadget_calc_ram_depth - calculates the ram depth for txfifo
|
|
+ * @dwc: pointer to the DWC3 context
|
|
+ */
|
|
+static int dwc3_gadget_calc_ram_depth(struct dwc3 *dwc)
|
|
+{
|
|
+ int ram_depth;
|
|
+ int fifo_0_start;
|
|
+ bool is_single_port_ram;
|
|
+
|
|
+ /* Check supporting RAM type by HW */
|
|
+ is_single_port_ram = DWC3_SPRAM_TYPE(dwc->hwparams.hwparams1);
|
|
+
|
|
+ /*
|
|
+ * If a single port RAM is utilized, then allocate TxFIFOs from
|
|
+ * RAM0. otherwise, allocate them from RAM1.
|
|
+ */
|
|
+ ram_depth = is_single_port_ram ? DWC3_RAM0_DEPTH(dwc->hwparams.hwparams6) :
|
|
+ DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
|
|
+
|
|
+ /*
|
|
+ * In a single port RAM configuration, the available RAM is shared
|
|
+ * between the RX and TX FIFOs. This means that the txfifo can begin
|
|
+ * at a non-zero address.
|
|
+ */
|
|
+ if (is_single_port_ram) {
|
|
+ u32 reg;
|
|
+
|
|
+ /* Check if TXFIFOs start at non-zero addr */
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
|
|
+ fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(reg);
|
|
+
|
|
+ ram_depth -= (fifo_0_start >> 16);
|
|
+ }
|
|
+
|
|
+ return ram_depth;
|
|
+}
|
|
+
|
|
/**
|
|
* dwc3_gadget_clear_tx_fifos - Clears txfifo allocation
|
|
* @dwc: pointer to the DWC3 context
|
|
@@ -753,7 +791,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
|
|
{
|
|
struct dwc3 *dwc = dep->dwc;
|
|
int fifo_0_start;
|
|
- int ram1_depth;
|
|
+ int ram_depth;
|
|
int fifo_size;
|
|
int min_depth;
|
|
int num_in_ep;
|
|
@@ -773,7 +811,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
|
|
if (dep->flags & DWC3_EP_TXFIFO_RESIZED)
|
|
return 0;
|
|
|
|
- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
|
|
+ ram_depth = dwc3_gadget_calc_ram_depth(dwc);
|
|
|
|
if ((dep->endpoint.maxburst > 1 &&
|
|
usb_endpoint_xfer_bulk(dep->endpoint.desc)) ||
|
|
@@ -794,7 +832,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
|
|
|
|
/* Reserve at least one FIFO for the number of IN EPs */
|
|
min_depth = num_in_ep * (fifo + 1);
|
|
- remaining = ram1_depth - min_depth - dwc->last_fifo_depth;
|
|
+ remaining = ram_depth - min_depth - dwc->last_fifo_depth;
|
|
remaining = max_t(int, 0, remaining);
|
|
/*
|
|
* We've already reserved 1 FIFO per EP, so check what we can fit in
|
|
@@ -820,9 +858,9 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
|
|
dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
|
|
|
|
/* Check fifo size allocation doesn't exceed available RAM size. */
|
|
- if (dwc->last_fifo_depth >= ram1_depth) {
|
|
+ if (dwc->last_fifo_depth >= ram_depth) {
|
|
dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
|
|
- dwc->last_fifo_depth, ram1_depth,
|
|
+ dwc->last_fifo_depth, ram_depth,
|
|
dep->endpoint.name, fifo_size);
|
|
if (DWC3_IP_IS(DWC3))
|
|
fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
|
|
@@ -3078,7 +3116,7 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
|
|
struct dwc3 *dwc = gadget_to_dwc(g);
|
|
struct usb_ep *ep;
|
|
int fifo_size = 0;
|
|
- int ram1_depth;
|
|
+ int ram_depth;
|
|
int ep_num = 0;
|
|
|
|
if (!dwc->do_fifo_resize)
|
|
@@ -3101,8 +3139,8 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
|
|
fifo_size += dwc->max_cfg_eps;
|
|
|
|
/* Check if we can fit a single fifo per endpoint */
|
|
- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
|
|
- if (fifo_size > ram1_depth)
|
|
+ ram_depth = dwc3_gadget_calc_ram_depth(dwc);
|
|
+ if (fifo_size > ram_depth)
|
|
return -ENOMEM;
|
|
|
|
return 0;
|
|
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
|
|
index 50f58801140045..0d628af5c3ba50 100644
|
|
--- a/drivers/usb/host/xhci-ring.c
|
|
+++ b/drivers/usb/host/xhci-ring.c
|
|
@@ -52,6 +52,7 @@
|
|
* endpoint rings; it generates events on the event ring for these.
|
|
*/
|
|
|
|
+#include <linux/jiffies.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/dma-mapping.h>
|
|
@@ -1091,6 +1092,19 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Erase queued TDs from transfer ring(s) and give back those the xHC didn't
|
|
+ * stop on. If necessary, queue commands to move the xHC off cancelled TDs it
|
|
+ * stopped on. Those will be given back later when the commands complete.
|
|
+ *
|
|
+ * Call under xhci->lock on a stopped endpoint.
|
|
+ */
|
|
+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep)
|
|
+{
|
|
+ xhci_invalidate_cancelled_tds(ep);
|
|
+ xhci_giveback_invalidated_tds(ep);
|
|
+}
|
|
+
|
|
/*
|
|
* Returns the TD the endpoint ring halted on.
|
|
* Only call for non-running rings without streams.
|
|
@@ -1180,9 +1194,35 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
|
|
break;
|
|
ep->ep_state &= ~EP_STOP_CMD_PENDING;
|
|
return;
|
|
+ case EP_STATE_STOPPED:
|
|
+ /*
|
|
+ * Per xHCI 4.6.9, Stop Endpoint command on a Stopped
|
|
+ * EP is a Context State Error, and EP stays Stopped.
|
|
+ *
|
|
+ * But maybe it failed on Halted, and somebody ran Reset
|
|
+ * Endpoint later. EP state is now Stopped and EP_HALTED
|
|
+ * still set because Reset EP handler will run after us.
|
|
+ */
|
|
+ if (ep->ep_state & EP_HALTED)
|
|
+ break;
|
|
+ /*
|
|
+ * On some HCs EP state remains Stopped for some tens of
|
|
+ * us to a few ms or more after a doorbell ring, and any
|
|
+ * new Stop Endpoint fails without aborting the restart.
|
|
+ * This handler may run quickly enough to still see this
|
|
+ * Stopped state, but it will soon change to Running.
|
|
+ *
|
|
+ * Assume this bug on unexpected Stop Endpoint failures.
|
|
+ * Keep retrying until the EP starts and stops again, on
|
|
+ * chips where this is known to help. Wait for 100ms.
|
|
+ */
|
|
+ if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100)))
|
|
+ break;
|
|
+ fallthrough;
|
|
case EP_STATE_RUNNING:
|
|
/* Race, HW handled stop ep cmd before ep was running */
|
|
- xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n");
|
|
+ xhci_dbg(xhci, "Stop ep completion ctx error, ctx_state %d\n",
|
|
+ GET_EP_CTX_STATE(ep_ctx));
|
|
|
|
command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
|
|
if (!command) {
|
|
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
|
|
index 3bd70e6ad64baf..70e6c240a5409f 100644
|
|
--- a/drivers/usb/host/xhci.c
|
|
+++ b/drivers/usb/host/xhci.c
|
|
@@ -8,6 +8,7 @@
|
|
* Some code borrowed from the Linux EHCI driver.
|
|
*/
|
|
|
|
+#include <linux/jiffies.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/iommu.h>
|
|
#include <linux/iopoll.h>
|
|
@@ -1737,15 +1738,27 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|
}
|
|
}
|
|
|
|
- /* Queue a stop endpoint command, but only if this is
|
|
- * the first cancellation to be handled.
|
|
- */
|
|
- if (!(ep->ep_state & EP_STOP_CMD_PENDING)) {
|
|
+ /* These completion handlers will sort out cancelled TDs for us */
|
|
+ if (ep->ep_state & (EP_STOP_CMD_PENDING | EP_HALTED | SET_DEQ_PENDING)) {
|
|
+ xhci_dbg(xhci, "Not queuing Stop Endpoint on slot %d ep %d in state 0x%x\n",
|
|
+ urb->dev->slot_id, ep_index, ep->ep_state);
|
|
+ goto done;
|
|
+ }
|
|
+
|
|
+ /* In this case no commands are pending but the endpoint is stopped */
|
|
+ if (ep->ep_state & EP_CLEARING_TT) {
|
|
+ /* and cancelled TDs can be given back right away */
|
|
+ xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n",
|
|
+ urb->dev->slot_id, ep_index, ep->ep_state);
|
|
+ xhci_process_cancelled_tds(ep);
|
|
+ } else {
|
|
+ /* Otherwise, queue a new Stop Endpoint command */
|
|
command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
|
|
if (!command) {
|
|
ret = -ENOMEM;
|
|
goto done;
|
|
}
|
|
+ ep->stop_time = jiffies;
|
|
ep->ep_state |= EP_STOP_CMD_PENDING;
|
|
xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
|
|
ep_index, 0);
|
|
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
|
|
index 4bbd12db7239ab..fddb3a90dae3df 100644
|
|
--- a/drivers/usb/host/xhci.h
|
|
+++ b/drivers/usb/host/xhci.h
|
|
@@ -717,6 +717,7 @@ struct xhci_virt_ep {
|
|
/* Bandwidth checking storage */
|
|
struct xhci_bw_info bw_info;
|
|
struct list_head bw_endpoint_list;
|
|
+ unsigned long stop_time;
|
|
/* Isoch Frame ID checking storage */
|
|
int next_frame_id;
|
|
/* Use new Isoch TRB layout needed for extended TBC support */
|
|
@@ -1951,6 +1952,7 @@ void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
|
|
void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
|
|
void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring);
|
|
unsigned int count_trbs(u64 addr, u64 len);
|
|
+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep);
|
|
|
|
/* xHCI roothub code */
|
|
void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
|
|
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
|
|
index f6fb5575d4f0ac..d6a3fd00c3a5c4 100644
|
|
--- a/drivers/usb/typec/ucsi/ucsi.c
|
|
+++ b/drivers/usb/typec/ucsi/ucsi.c
|
|
@@ -903,6 +903,9 @@ static void ucsi_handle_connector_change(struct work_struct *work)
|
|
|
|
trace_ucsi_connector_change(con->num, &con->status);
|
|
|
|
+ if (ucsi->ops->connector_status)
|
|
+ ucsi->ops->connector_status(con);
|
|
+
|
|
role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
|
|
|
|
if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
|
|
@@ -1258,6 +1261,9 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
|
|
cap->driver_data = con;
|
|
cap->ops = &ucsi_ops;
|
|
|
|
+ if (ucsi->ops->update_connector)
|
|
+ ucsi->ops->update_connector(con);
|
|
+
|
|
ret = ucsi_register_port_psy(con);
|
|
if (ret)
|
|
goto out;
|
|
@@ -1322,6 +1328,9 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
|
|
}
|
|
ret = 0; /* ucsi_send_command() returns length on success */
|
|
|
|
+ if (ucsi->ops->connector_status)
|
|
+ ucsi->ops->connector_status(con);
|
|
+
|
|
switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
|
|
case UCSI_CONSTAT_PARTNER_TYPE_UFP:
|
|
case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
|
|
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
|
|
index 42c60eba5fb6ee..921ef0e115cffc 100644
|
|
--- a/drivers/usb/typec/ucsi/ucsi.h
|
|
+++ b/drivers/usb/typec/ucsi/ucsi.h
|
|
@@ -15,6 +15,7 @@
|
|
|
|
struct ucsi;
|
|
struct ucsi_altmode;
|
|
+struct ucsi_connector;
|
|
struct dentry;
|
|
|
|
/* UCSI offsets (Bytes) */
|
|
@@ -52,6 +53,8 @@ struct dentry;
|
|
* @sync_write: Blocking write operation
|
|
* @async_write: Non-blocking write operation
|
|
* @update_altmodes: Squashes duplicate DP altmodes
|
|
+ * @update_connector: Update connector capabilities before registering
|
|
+ * @connector_status: Updates connector status, called holding connector lock
|
|
*
|
|
* Read and write routines for UCSI interface. @sync_write must wait for the
|
|
* Command Completion Event from the PPM before returning, and @async_write must
|
|
@@ -66,6 +69,8 @@ struct ucsi_operations {
|
|
const void *val, size_t val_len);
|
|
bool (*update_altmodes)(struct ucsi *ucsi, struct ucsi_altmode *orig,
|
|
struct ucsi_altmode *updated);
|
|
+ void (*update_connector)(struct ucsi_connector *con);
|
|
+ void (*connector_status)(struct ucsi_connector *con);
|
|
};
|
|
|
|
struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops);
|
|
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
|
|
index 94f2df02f06eeb..82a1081d44f1f0 100644
|
|
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
|
|
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
|
|
@@ -186,10 +186,40 @@ static int pmic_glink_ucsi_sync_write(struct ucsi *__ucsi, unsigned int offset,
|
|
return ret;
|
|
}
|
|
|
|
+static void pmic_glink_ucsi_update_connector(struct ucsi_connector *con)
|
|
+{
|
|
+ struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
|
|
+
|
|
+ if (con->num > PMIC_GLINK_MAX_PORTS ||
|
|
+ !ucsi->port_orientation[con->num - 1])
|
|
+ return;
|
|
+
|
|
+ con->typec_cap.orientation_aware = true;
|
|
+}
|
|
+
|
|
+static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
|
|
+{
|
|
+ struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
|
|
+ int orientation;
|
|
+
|
|
+ if (con->num > PMIC_GLINK_MAX_PORTS ||
|
|
+ !ucsi->port_orientation[con->num - 1])
|
|
+ return;
|
|
+
|
|
+ orientation = gpiod_get_value(ucsi->port_orientation[con->num - 1]);
|
|
+ if (orientation >= 0) {
|
|
+ typec_switch_set(ucsi->port_switch[con->num - 1],
|
|
+ orientation ? TYPEC_ORIENTATION_REVERSE
|
|
+ : TYPEC_ORIENTATION_NORMAL);
|
|
+ }
|
|
+}
|
|
+
|
|
static const struct ucsi_operations pmic_glink_ucsi_ops = {
|
|
.read = pmic_glink_ucsi_read,
|
|
.sync_write = pmic_glink_ucsi_sync_write,
|
|
- .async_write = pmic_glink_ucsi_async_write
|
|
+ .async_write = pmic_glink_ucsi_async_write,
|
|
+ .update_connector = pmic_glink_ucsi_update_connector,
|
|
+ .connector_status = pmic_glink_ucsi_connector_status,
|
|
};
|
|
|
|
static void pmic_glink_ucsi_read_ack(struct pmic_glink_ucsi *ucsi, const void *data, int len)
|
|
@@ -228,20 +258,8 @@ static void pmic_glink_ucsi_notify(struct work_struct *work)
|
|
}
|
|
|
|
con_num = UCSI_CCI_CONNECTOR(cci);
|
|
- if (con_num) {
|
|
- if (con_num <= PMIC_GLINK_MAX_PORTS &&
|
|
- ucsi->port_orientation[con_num - 1]) {
|
|
- int orientation = gpiod_get_value(ucsi->port_orientation[con_num - 1]);
|
|
-
|
|
- if (orientation >= 0) {
|
|
- typec_switch_set(ucsi->port_switch[con_num - 1],
|
|
- orientation ? TYPEC_ORIENTATION_REVERSE
|
|
- : TYPEC_ORIENTATION_NORMAL);
|
|
- }
|
|
- }
|
|
-
|
|
+ if (con_num)
|
|
ucsi_connector_change(ucsi->ucsi, con_num);
|
|
- }
|
|
|
|
if (ucsi->sync_pending &&
|
|
(cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))) {
|
|
@@ -252,20 +270,6 @@ static void pmic_glink_ucsi_notify(struct work_struct *work)
|
|
static void pmic_glink_ucsi_register(struct work_struct *work)
|
|
{
|
|
struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work);
|
|
- int orientation;
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < PMIC_GLINK_MAX_PORTS; i++) {
|
|
- if (!ucsi->port_orientation[i])
|
|
- continue;
|
|
- orientation = gpiod_get_value(ucsi->port_orientation[i]);
|
|
-
|
|
- if (orientation >= 0) {
|
|
- typec_switch_set(ucsi->port_switch[i],
|
|
- orientation ? TYPEC_ORIENTATION_REVERSE
|
|
- : TYPEC_ORIENTATION_NORMAL);
|
|
- }
|
|
- }
|
|
|
|
ucsi_register(ucsi->ucsi);
|
|
}
|
|
diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c
|
|
index 7bce093316c4d7..525a72d8d746e3 100644
|
|
--- a/drivers/watchdog/rzg2l_wdt.c
|
|
+++ b/drivers/watchdog/rzg2l_wdt.c
|
|
@@ -8,11 +8,11 @@
|
|
#include <linux/clk.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/io.h>
|
|
-#include <linux/iopoll.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of.h>
|
|
#include <linux/platform_device.h>
|
|
+#include <linux/pm_domain.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/reset.h>
|
|
#include <linux/units.h>
|
|
@@ -54,35 +54,11 @@ struct rzg2l_wdt_priv {
|
|
struct reset_control *rstc;
|
|
unsigned long osc_clk_rate;
|
|
unsigned long delay;
|
|
- unsigned long minimum_assertion_period;
|
|
struct clk *pclk;
|
|
struct clk *osc_clk;
|
|
enum rz_wdt_type devtype;
|
|
};
|
|
|
|
-static int rzg2l_wdt_reset(struct rzg2l_wdt_priv *priv)
|
|
-{
|
|
- int err, status;
|
|
-
|
|
- if (priv->devtype == WDT_RZV2M) {
|
|
- /* WDT needs TYPE-B reset control */
|
|
- err = reset_control_assert(priv->rstc);
|
|
- if (err)
|
|
- return err;
|
|
- ndelay(priv->minimum_assertion_period);
|
|
- err = reset_control_deassert(priv->rstc);
|
|
- if (err)
|
|
- return err;
|
|
- err = read_poll_timeout(reset_control_status, status,
|
|
- status != 1, 0, 1000, false,
|
|
- priv->rstc);
|
|
- } else {
|
|
- err = reset_control_reset(priv->rstc);
|
|
- }
|
|
-
|
|
- return err;
|
|
-}
|
|
-
|
|
static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
|
|
{
|
|
/* delay timer when change the setting register */
|
|
@@ -129,6 +105,12 @@ static int rzg2l_wdt_start(struct watchdog_device *wdev)
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ ret = reset_control_deassert(priv->rstc);
|
|
+ if (ret) {
|
|
+ pm_runtime_put(wdev->parent);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
/* Initialize time out */
|
|
rzg2l_wdt_init_timeout(wdev);
|
|
|
|
@@ -146,7 +128,9 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev)
|
|
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
|
int ret;
|
|
|
|
- rzg2l_wdt_reset(priv);
|
|
+ ret = reset_control_assert(priv->rstc);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
ret = pm_runtime_put(wdev->parent);
|
|
if (ret < 0)
|
|
@@ -181,11 +165,30 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
|
|
unsigned long action, void *data)
|
|
{
|
|
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
|
+ int ret;
|
|
|
|
- clk_prepare_enable(priv->pclk);
|
|
- clk_prepare_enable(priv->osc_clk);
|
|
+ /*
|
|
+ * In case of RZ/G3S the watchdog device may be part of an IRQ safe power
|
|
+ * domain that is currently powered off. In this case we need to power
|
|
+ * it on before accessing registers. Along with this the clocks will be
|
|
+ * enabled. We don't undo the pm_runtime_resume_and_get() as the device
|
|
+ * need to be on for the reboot to happen.
|
|
+ *
|
|
+ * For the rest of SoCs not registering a watchdog IRQ safe power
|
|
+ * domain it is safe to call pm_runtime_resume_and_get() as the
|
|
+ * irq_safe_dev_in_sleep_domain() call in genpd_runtime_resume()
|
|
+ * returns non zero value and the genpd_lock() is avoided, thus, there
|
|
+ * will be no invalid wait context reported by lockdep.
|
|
+ */
|
|
+ ret = pm_runtime_resume_and_get(wdev->parent);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
if (priv->devtype == WDT_RZG2L) {
|
|
+ ret = reset_control_deassert(priv->rstc);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
/* Generate Reset (WDTRSTB) Signal on parity error */
|
|
rzg2l_wdt_write(priv, 0, PECR);
|
|
|
|
@@ -193,7 +196,9 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
|
|
rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
|
|
} else {
|
|
/* RZ/V2M doesn't have parity error registers */
|
|
- rzg2l_wdt_reset(priv);
|
|
+ ret = reset_control_reset(priv->rstc);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
wdev->timeout = 0;
|
|
|
|
@@ -236,13 +241,11 @@ static const struct watchdog_ops rzg2l_wdt_ops = {
|
|
.restart = rzg2l_wdt_restart,
|
|
};
|
|
|
|
-static void rzg2l_wdt_reset_assert_pm_disable(void *data)
|
|
+static void rzg2l_wdt_pm_disable(void *data)
|
|
{
|
|
struct watchdog_device *wdev = data;
|
|
- struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
|
|
|
pm_runtime_disable(wdev->parent);
|
|
- reset_control_assert(priv->rstc);
|
|
}
|
|
|
|
static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|
@@ -285,19 +288,9 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|
return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc),
|
|
"failed to get cpg reset");
|
|
|
|
- ret = reset_control_deassert(priv->rstc);
|
|
- if (ret)
|
|
- return dev_err_probe(dev, ret, "failed to deassert");
|
|
-
|
|
priv->devtype = (uintptr_t)of_device_get_match_data(dev);
|
|
|
|
- if (priv->devtype == WDT_RZV2M) {
|
|
- priv->minimum_assertion_period = RZV2M_A_NSEC +
|
|
- 3 * F2CYCLE_NSEC(pclk_rate) + 5 *
|
|
- max(F2CYCLE_NSEC(priv->osc_clk_rate),
|
|
- F2CYCLE_NSEC(pclk_rate));
|
|
- }
|
|
-
|
|
+ pm_runtime_irq_safe(&pdev->dev);
|
|
pm_runtime_enable(&pdev->dev);
|
|
|
|
priv->wdev.info = &rzg2l_wdt_ident;
|
|
@@ -309,9 +302,7 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|
priv->wdev.timeout = WDT_DEFAULT_TIMEOUT;
|
|
|
|
watchdog_set_drvdata(&priv->wdev, priv);
|
|
- ret = devm_add_action_or_reset(&pdev->dev,
|
|
- rzg2l_wdt_reset_assert_pm_disable,
|
|
- &priv->wdev);
|
|
+ ret = devm_add_action_or_reset(&pdev->dev, rzg2l_wdt_pm_disable, &priv->wdev);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
|
|
index 25c902e7556d57..4b21ca49b6665d 100644
|
|
--- a/fs/btrfs/ctree.c
|
|
+++ b/fs/btrfs/ctree.c
|
|
@@ -526,13 +526,13 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
|
|
* bytes the allocator should try to find free next to the block it returns.
|
|
* This is just a hint and may be ignored by the allocator.
|
|
*/
|
|
-static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
- struct btrfs_root *root,
|
|
- struct extent_buffer *buf,
|
|
- struct extent_buffer *parent, int parent_slot,
|
|
- struct extent_buffer **cow_ret,
|
|
- u64 search_start, u64 empty_size,
|
|
- enum btrfs_lock_nesting nest)
|
|
+int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
|
|
+ struct btrfs_root *root,
|
|
+ struct extent_buffer *buf,
|
|
+ struct extent_buffer *parent, int parent_slot,
|
|
+ struct extent_buffer **cow_ret,
|
|
+ u64 search_start, u64 empty_size,
|
|
+ enum btrfs_lock_nesting nest)
|
|
{
|
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
struct btrfs_disk_key disk_key;
|
|
@@ -660,6 +660,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
return ret;
|
|
}
|
|
}
|
|
+
|
|
+ trace_btrfs_cow_block(root, buf, cow);
|
|
if (unlock_orig)
|
|
btrfs_tree_unlock(buf);
|
|
free_extent_buffer_stale(buf);
|
|
@@ -699,7 +701,7 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans,
|
|
}
|
|
|
|
/*
|
|
- * cows a single block, see __btrfs_cow_block for the real work.
|
|
+ * COWs a single block, see btrfs_force_cow_block() for the real work.
|
|
* This version of it has extra checks so that a block isn't COWed more than
|
|
* once per transaction, as long as it hasn't been written yet
|
|
*/
|
|
@@ -711,7 +713,6 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
{
|
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
u64 search_start;
|
|
- int ret;
|
|
|
|
if (unlikely(test_bit(BTRFS_ROOT_DELETING, &root->state))) {
|
|
btrfs_abort_transaction(trans, -EUCLEAN);
|
|
@@ -752,12 +753,8 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
* Also We don't care about the error, as it's handled internally.
|
|
*/
|
|
btrfs_qgroup_trace_subtree_after_cow(trans, root, buf);
|
|
- ret = __btrfs_cow_block(trans, root, buf, parent,
|
|
- parent_slot, cow_ret, search_start, 0, nest);
|
|
-
|
|
- trace_btrfs_cow_block(root, buf, *cow_ret);
|
|
-
|
|
- return ret;
|
|
+ return btrfs_force_cow_block(trans, root, buf, parent, parent_slot,
|
|
+ cow_ret, search_start, 0, nest);
|
|
}
|
|
ALLOW_ERROR_INJECTION(btrfs_cow_block, ERRNO);
|
|
|
|
@@ -904,11 +901,11 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
|
|
search_start = last_block;
|
|
|
|
btrfs_tree_lock(cur);
|
|
- err = __btrfs_cow_block(trans, root, cur, parent, i,
|
|
- &cur, search_start,
|
|
- min(16 * blocksize,
|
|
- (end_slot - i) * blocksize),
|
|
- BTRFS_NESTING_COW);
|
|
+ err = btrfs_force_cow_block(trans, root, cur, parent, i,
|
|
+ &cur, search_start,
|
|
+ min(16 * blocksize,
|
|
+ (end_slot - i) * blocksize),
|
|
+ BTRFS_NESTING_COW);
|
|
if (err) {
|
|
btrfs_tree_unlock(cur);
|
|
free_extent_buffer(cur);
|
|
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
|
|
index f7bb4c34b984b3..7df3ed2945b049 100644
|
|
--- a/fs/btrfs/ctree.h
|
|
+++ b/fs/btrfs/ctree.h
|
|
@@ -538,6 +538,13 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
struct extent_buffer *parent, int parent_slot,
|
|
struct extent_buffer **cow_ret,
|
|
enum btrfs_lock_nesting nest);
|
|
+int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
|
|
+ struct btrfs_root *root,
|
|
+ struct extent_buffer *buf,
|
|
+ struct extent_buffer *parent, int parent_slot,
|
|
+ struct extent_buffer **cow_ret,
|
|
+ u64 search_start, u64 empty_size,
|
|
+ enum btrfs_lock_nesting nest);
|
|
int btrfs_copy_root(struct btrfs_trans_handle *trans,
|
|
struct btrfs_root *root,
|
|
struct extent_buffer *buf,
|
|
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
|
|
index 8ec411eb9c9b0c..967c6b5dd0a434 100644
|
|
--- a/fs/btrfs/disk-io.c
|
|
+++ b/fs/btrfs/disk-io.c
|
|
@@ -4323,6 +4323,15 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
|
|
* already the cleaner, but below we run all pending delayed iputs.
|
|
*/
|
|
btrfs_flush_workqueue(fs_info->fixup_workers);
|
|
+ /*
|
|
+ * Similar case here, we have to wait for delalloc workers before we
|
|
+ * proceed below and stop the cleaner kthread, otherwise we trigger a
|
|
+ * use-after-tree on the cleaner kthread task_struct when a delalloc
|
|
+ * worker running submit_compressed_extents() adds a delayed iput, which
|
|
+ * does a wake up on the cleaner kthread, which was already freed below
|
|
+ * when we call kthread_stop().
|
|
+ */
|
|
+ btrfs_flush_workqueue(fs_info->delalloc_workers);
|
|
|
|
/*
|
|
* After we parked the cleaner kthread, ordered extents may have
|
|
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
|
index d6767f728c079d..eb9319d856f2d8 100644
|
|
--- a/fs/btrfs/inode.c
|
|
+++ b/fs/btrfs/inode.c
|
|
@@ -9972,7 +9972,7 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio)
|
|
*/
|
|
WRITE_ONCE(priv->status, bbio->bio.bi_status);
|
|
}
|
|
- if (!atomic_dec_return(&priv->pending))
|
|
+ if (atomic_dec_and_test(&priv->pending))
|
|
wake_up(&priv->wait);
|
|
bio_put(&bbio->bio);
|
|
}
|
|
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
|
|
index 11289ce8a8cc81..dfa1b3c82b53ac 100644
|
|
--- a/fs/ceph/mds_client.c
|
|
+++ b/fs/ceph/mds_client.c
|
|
@@ -2713,12 +2713,11 @@ char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
|
|
|
|
if (pos < 0) {
|
|
/*
|
|
- * A rename didn't occur, but somehow we didn't end up where
|
|
- * we thought we would. Throw a warning and try again.
|
|
+ * The path is longer than PATH_MAX and this function
|
|
+ * cannot ever succeed. Creating paths that long is
|
|
+ * possible with Ceph, but Linux cannot use them.
|
|
*/
|
|
- pr_warn("build_path did not end path lookup where expected (pos = %d)\n",
|
|
- pos);
|
|
- goto retry;
|
|
+ return ERR_PTR(-ENAMETOOLONG);
|
|
}
|
|
|
|
*pbase = base;
|
|
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
|
|
index 3db01b933c3e8b..60455c84a93742 100644
|
|
--- a/fs/ext4/ext4.h
|
|
+++ b/fs/ext4/ext4.h
|
|
@@ -891,10 +891,13 @@ do { \
|
|
(raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)); \
|
|
} while (0)
|
|
|
|
-#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
|
|
- EXT4_INODE_SET_XTIME_VAL(xtime, inode, raw_inode, (inode)->xtime)
|
|
+#define EXT4_INODE_SET_ATIME(inode, raw_inode) \
|
|
+ EXT4_INODE_SET_XTIME_VAL(i_atime, inode, raw_inode, inode_get_atime(inode))
|
|
|
|
-#define EXT4_INODE_SET_CTIME(inode, raw_inode) \
|
|
+#define EXT4_INODE_SET_MTIME(inode, raw_inode) \
|
|
+ EXT4_INODE_SET_XTIME_VAL(i_mtime, inode, raw_inode, inode_get_mtime(inode))
|
|
+
|
|
+#define EXT4_INODE_SET_CTIME(inode, raw_inode) \
|
|
EXT4_INODE_SET_XTIME_VAL(i_ctime, inode, raw_inode, inode_get_ctime(inode))
|
|
|
|
#define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \
|
|
@@ -910,9 +913,16 @@ do { \
|
|
.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime) \
|
|
})
|
|
|
|
-#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
|
|
+#define EXT4_INODE_GET_ATIME(inode, raw_inode) \
|
|
+do { \
|
|
+ inode_set_atime_to_ts(inode, \
|
|
+ EXT4_INODE_GET_XTIME_VAL(i_atime, inode, raw_inode)); \
|
|
+} while (0)
|
|
+
|
|
+#define EXT4_INODE_GET_MTIME(inode, raw_inode) \
|
|
do { \
|
|
- (inode)->xtime = EXT4_INODE_GET_XTIME_VAL(xtime, inode, raw_inode); \
|
|
+ inode_set_mtime_to_ts(inode, \
|
|
+ EXT4_INODE_GET_XTIME_VAL(i_mtime, inode, raw_inode)); \
|
|
} while (0)
|
|
|
|
#define EXT4_INODE_GET_CTIME(inode, raw_inode) \
|
|
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
|
|
index 5ea75af6ca2239..32218ac7f50fe2 100644
|
|
--- a/fs/ext4/extents.c
|
|
+++ b/fs/ext4/extents.c
|
|
@@ -4475,7 +4475,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
|
|
int depth = 0;
|
|
struct ext4_map_blocks map;
|
|
unsigned int credits;
|
|
- loff_t epos;
|
|
+ loff_t epos, old_size = i_size_read(inode);
|
|
|
|
BUG_ON(!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS));
|
|
map.m_lblk = offset;
|
|
@@ -4532,7 +4532,13 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
|
|
if (epos > new_size)
|
|
epos = new_size;
|
|
if (ext4_update_inode_size(inode, epos) & 0x1)
|
|
- inode->i_mtime = inode_get_ctime(inode);
|
|
+ inode_set_mtime_to_ts(inode,
|
|
+ inode_get_ctime(inode));
|
|
+ if (epos > old_size) {
|
|
+ pagecache_isize_extended(inode, old_size, epos);
|
|
+ ext4_zero_partial_blocks(handle, inode,
|
|
+ old_size, epos - old_size);
|
|
+ }
|
|
}
|
|
ret2 = ext4_mark_inode_dirty(handle, inode);
|
|
ext4_update_inode_fsync_trans(handle, inode, 1);
|
|
@@ -4670,7 +4676,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
|
|
|
|
/* Now release the pages and zero block aligned part of pages */
|
|
truncate_pagecache_range(inode, start, end - 1);
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
|
|
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
|
|
flags);
|
|
@@ -4695,7 +4701,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
|
|
goto out_mutex;
|
|
}
|
|
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
if (new_size)
|
|
ext4_update_inode_size(inode, new_size);
|
|
ret = ext4_mark_inode_dirty(handle, inode);
|
|
@@ -5431,7 +5437,7 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
|
|
up_write(&EXT4_I(inode)->i_data_sem);
|
|
if (IS_SYNC(inode))
|
|
ext4_handle_sync(handle);
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
ret = ext4_mark_inode_dirty(handle, inode);
|
|
ext4_update_inode_fsync_trans(handle, inode, 1);
|
|
|
|
@@ -5541,7 +5547,7 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
|
|
/* Expand file to avoid data loss if there is error while shifting */
|
|
inode->i_size += len;
|
|
EXT4_I(inode)->i_disksize += len;
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
ret = ext4_mark_inode_dirty(handle, inode);
|
|
if (ret)
|
|
goto out_stop;
|
|
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
|
|
index d4d0ad689d3c1c..52f2959d29e6e0 100644
|
|
--- a/fs/ext4/ialloc.c
|
|
+++ b/fs/ext4/ialloc.c
|
|
@@ -1255,8 +1255,8 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,
|
|
inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
|
|
/* This is the optimal IO size (for stat), not the fs block size */
|
|
inode->i_blocks = 0;
|
|
- inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode);
|
|
- ei->i_crtime = inode->i_mtime;
|
|
+ simple_inode_init_ts(inode);
|
|
+ ei->i_crtime = inode_get_mtime(inode);
|
|
|
|
memset(ei->i_data, 0, sizeof(ei->i_data));
|
|
ei->i_dir_start_lookup = 0;
|
|
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
|
|
index cb65052ee3dec6..3f363276ddd360 100644
|
|
--- a/fs/ext4/inline.c
|
|
+++ b/fs/ext4/inline.c
|
|
@@ -1037,7 +1037,7 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
|
|
* happen is that the times are slightly out of date
|
|
* and/or different from the directory change time.
|
|
*/
|
|
- dir->i_mtime = inode_set_ctime_current(dir);
|
|
+ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
|
|
ext4_update_dx_flag(dir);
|
|
inode_inc_iversion(dir);
|
|
return 1;
|
|
@@ -2010,7 +2010,7 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
|
|
ext4_orphan_del(handle, inode);
|
|
|
|
if (err == 0) {
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
err = ext4_mark_inode_dirty(handle, inode);
|
|
if (IS_SYNC(inode))
|
|
ext4_handle_sync(handle);
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index 18ec9106c5b09f..19d7bcf16ebb88 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -1328,8 +1328,10 @@ static int ext4_write_end(struct file *file,
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
|
|
- if (old_size < pos && !verity)
|
|
+ if (old_size < pos && !verity) {
|
|
pagecache_isize_extended(inode, old_size, pos);
|
|
+ ext4_zero_partial_blocks(handle, inode, old_size, pos - old_size);
|
|
+ }
|
|
/*
|
|
* Don't mark the inode dirty under folio lock. First, it unnecessarily
|
|
* makes the holding time of folio lock longer. Second, it forces lock
|
|
@@ -1445,8 +1447,10 @@ static int ext4_journalled_write_end(struct file *file,
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
|
|
- if (old_size < pos && !verity)
|
|
+ if (old_size < pos && !verity) {
|
|
pagecache_isize_extended(inode, old_size, pos);
|
|
+ ext4_zero_partial_blocks(handle, inode, old_size, pos - old_size);
|
|
+ }
|
|
|
|
if (size_changed) {
|
|
ret2 = ext4_mark_inode_dirty(handle, inode);
|
|
@@ -2971,7 +2975,8 @@ static int ext4_da_do_write_end(struct address_space *mapping,
|
|
struct inode *inode = mapping->host;
|
|
loff_t old_size = inode->i_size;
|
|
bool disksize_changed = false;
|
|
- loff_t new_i_size;
|
|
+ loff_t new_i_size, zero_len = 0;
|
|
+ handle_t *handle;
|
|
|
|
if (unlikely(!folio_buffers(folio))) {
|
|
folio_unlock(folio);
|
|
@@ -3015,18 +3020,21 @@ static int ext4_da_do_write_end(struct address_space *mapping,
|
|
folio_unlock(folio);
|
|
folio_put(folio);
|
|
|
|
- if (old_size < pos)
|
|
+ if (pos > old_size) {
|
|
pagecache_isize_extended(inode, old_size, pos);
|
|
+ zero_len = pos - old_size;
|
|
+ }
|
|
|
|
- if (disksize_changed) {
|
|
- handle_t *handle;
|
|
+ if (!disksize_changed && !zero_len)
|
|
+ return copied;
|
|
|
|
- handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
|
|
- if (IS_ERR(handle))
|
|
- return PTR_ERR(handle);
|
|
- ext4_mark_inode_dirty(handle, inode);
|
|
- ext4_journal_stop(handle);
|
|
- }
|
|
+ handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
|
|
+ if (IS_ERR(handle))
|
|
+ return PTR_ERR(handle);
|
|
+ if (zero_len)
|
|
+ ext4_zero_partial_blocks(handle, inode, old_size, zero_len);
|
|
+ ext4_mark_inode_dirty(handle, inode);
|
|
+ ext4_journal_stop(handle);
|
|
|
|
return copied;
|
|
}
|
|
@@ -4055,7 +4063,7 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
|
|
if (IS_SYNC(inode))
|
|
ext4_handle_sync(handle);
|
|
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
ret2 = ext4_mark_inode_dirty(handle, inode);
|
|
if (unlikely(ret2))
|
|
ret = ret2;
|
|
@@ -4215,7 +4223,7 @@ int ext4_truncate(struct inode *inode)
|
|
if (inode->i_nlink)
|
|
ext4_orphan_del(handle, inode);
|
|
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
err2 = ext4_mark_inode_dirty(handle, inode);
|
|
if (unlikely(err2 && !err))
|
|
err = err2;
|
|
@@ -4319,8 +4327,8 @@ static int ext4_fill_raw_inode(struct inode *inode, struct ext4_inode *raw_inode
|
|
raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
|
|
|
|
EXT4_INODE_SET_CTIME(inode, raw_inode);
|
|
- EXT4_INODE_SET_XTIME(i_mtime, inode, raw_inode);
|
|
- EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
|
|
+ EXT4_INODE_SET_MTIME(inode, raw_inode);
|
|
+ EXT4_INODE_SET_ATIME(inode, raw_inode);
|
|
EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
|
|
|
|
raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
|
|
@@ -4928,8 +4936,8 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
|
|
}
|
|
|
|
EXT4_INODE_GET_CTIME(inode, raw_inode);
|
|
- EXT4_INODE_GET_XTIME(i_mtime, inode, raw_inode);
|
|
- EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode);
|
|
+ EXT4_INODE_GET_ATIME(inode, raw_inode);
|
|
+ EXT4_INODE_GET_MTIME(inode, raw_inode);
|
|
EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode);
|
|
|
|
if (likely(!test_opt2(inode->i_sb, HURD_COMPAT))) {
|
|
@@ -5054,8 +5062,8 @@ static void __ext4_update_other_inode_time(struct super_block *sb,
|
|
|
|
spin_lock(&ei->i_raw_lock);
|
|
EXT4_INODE_SET_CTIME(inode, raw_inode);
|
|
- EXT4_INODE_SET_XTIME(i_mtime, inode, raw_inode);
|
|
- EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
|
|
+ EXT4_INODE_SET_MTIME(inode, raw_inode);
|
|
+ EXT4_INODE_SET_ATIME(inode, raw_inode);
|
|
ext4_inode_csum_set(inode, raw_inode, ei);
|
|
spin_unlock(&ei->i_raw_lock);
|
|
trace_ext4_other_inode_update_time(inode, orig_ino);
|
|
@@ -5437,6 +5445,14 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
|
}
|
|
|
|
if (attr->ia_size != inode->i_size) {
|
|
+ /* attach jbd2 jinode for EOF folio tail zeroing */
|
|
+ if (attr->ia_size & (inode->i_sb->s_blocksize - 1) ||
|
|
+ oldsize & (inode->i_sb->s_blocksize - 1)) {
|
|
+ error = ext4_inode_attach_jinode(inode);
|
|
+ if (error)
|
|
+ goto err_out;
|
|
+ }
|
|
+
|
|
handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
|
|
if (IS_ERR(handle)) {
|
|
error = PTR_ERR(handle);
|
|
@@ -5447,11 +5463,17 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
|
orphan = 1;
|
|
}
|
|
/*
|
|
- * Update c/mtime on truncate up, ext4_truncate() will
|
|
- * update c/mtime in shrink case below
|
|
+ * Update c/mtime and tail zero the EOF folio on
|
|
+ * truncate up. ext4_truncate() handles the shrink case
|
|
+ * below.
|
|
*/
|
|
- if (!shrink)
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ if (!shrink) {
|
|
+ inode_set_mtime_to_ts(inode,
|
|
+ inode_set_ctime_current(inode));
|
|
+ if (oldsize & (inode->i_sb->s_blocksize - 1))
|
|
+ ext4_block_truncate_page(handle,
|
|
+ inode->i_mapping, oldsize);
|
|
+ }
|
|
|
|
if (shrink)
|
|
ext4_fc_track_range(handle, inode,
|
|
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
|
|
index 0bfe2ce589e224..4f931f80cb3489 100644
|
|
--- a/fs/ext4/ioctl.c
|
|
+++ b/fs/ext4/ioctl.c
|
|
@@ -312,13 +312,22 @@ static void swap_inode_data(struct inode *inode1, struct inode *inode2)
|
|
struct ext4_inode_info *ei1;
|
|
struct ext4_inode_info *ei2;
|
|
unsigned long tmp;
|
|
+ struct timespec64 ts1, ts2;
|
|
|
|
ei1 = EXT4_I(inode1);
|
|
ei2 = EXT4_I(inode2);
|
|
|
|
swap(inode1->i_version, inode2->i_version);
|
|
- swap(inode1->i_atime, inode2->i_atime);
|
|
- swap(inode1->i_mtime, inode2->i_mtime);
|
|
+
|
|
+ ts1 = inode_get_atime(inode1);
|
|
+ ts2 = inode_get_atime(inode2);
|
|
+ inode_set_atime_to_ts(inode1, ts2);
|
|
+ inode_set_atime_to_ts(inode2, ts1);
|
|
+
|
|
+ ts1 = inode_get_mtime(inode1);
|
|
+ ts2 = inode_get_mtime(inode2);
|
|
+ inode_set_mtime_to_ts(inode1, ts2);
|
|
+ inode_set_mtime_to_ts(inode2, ts1);
|
|
|
|
memswap(ei1->i_data, ei2->i_data, sizeof(ei1->i_data));
|
|
tmp = ei1->i_flags & EXT4_FL_SHOULD_SWAP;
|
|
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
|
|
index 4de1f61bba76b3..96a048d3f51bf5 100644
|
|
--- a/fs/ext4/namei.c
|
|
+++ b/fs/ext4/namei.c
|
|
@@ -2210,7 +2210,7 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
|
|
* happen is that the times are slightly out of date
|
|
* and/or different from the directory change time.
|
|
*/
|
|
- dir->i_mtime = inode_set_ctime_current(dir);
|
|
+ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
|
|
ext4_update_dx_flag(dir);
|
|
inode_inc_iversion(dir);
|
|
err2 = ext4_mark_inode_dirty(handle, dir);
|
|
@@ -3248,7 +3248,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
|
|
* recovery. */
|
|
inode->i_size = 0;
|
|
ext4_orphan_add(handle, inode);
|
|
- dir->i_mtime = inode_set_ctime_current(dir);
|
|
+ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
|
|
inode_set_ctime_current(inode);
|
|
retval = ext4_mark_inode_dirty(handle, inode);
|
|
if (retval)
|
|
@@ -3323,7 +3323,7 @@ int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
|
|
retval = ext4_delete_entry(handle, dir, de, bh);
|
|
if (retval)
|
|
goto out_handle;
|
|
- dir->i_mtime = inode_set_ctime_current(dir);
|
|
+ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
|
|
ext4_update_dx_flag(dir);
|
|
retval = ext4_mark_inode_dirty(handle, dir);
|
|
if (retval)
|
|
@@ -3691,7 +3691,7 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
|
|
if (ext4_has_feature_filetype(ent->dir->i_sb))
|
|
ent->de->file_type = file_type;
|
|
inode_inc_iversion(ent->dir);
|
|
- ent->dir->i_mtime = inode_set_ctime_current(ent->dir);
|
|
+ inode_set_mtime_to_ts(ent->dir, inode_set_ctime_current(ent->dir));
|
|
retval = ext4_mark_inode_dirty(handle, ent->dir);
|
|
BUFFER_TRACE(ent->bh, "call ext4_handle_dirty_metadata");
|
|
if (!ent->inlined) {
|
|
@@ -4006,7 +4006,7 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
|
ext4_dec_count(new.inode);
|
|
inode_set_ctime_current(new.inode);
|
|
}
|
|
- old.dir->i_mtime = inode_set_ctime_current(old.dir);
|
|
+ inode_set_mtime_to_ts(old.dir, inode_set_ctime_current(old.dir));
|
|
ext4_update_dx_flag(old.dir);
|
|
if (old.dir_bh) {
|
|
retval = ext4_rename_dir_finish(handle, &old, new.dir->i_ino);
|
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
index 2346ef071b2421..71ced0ada9a2e5 100644
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -7180,7 +7180,7 @@ static int ext4_quota_off(struct super_block *sb, int type)
|
|
}
|
|
EXT4_I(inode)->i_flags &= ~(EXT4_NOATIME_FL | EXT4_IMMUTABLE_FL);
|
|
inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE);
|
|
- inode->i_mtime = inode_set_ctime_current(inode);
|
|
+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
|
err = ext4_mark_inode_dirty(handle, inode);
|
|
ext4_journal_stop(handle);
|
|
out_unlock:
|
|
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
|
|
index f40785bc4e5549..df5ab1a75fc482 100644
|
|
--- a/fs/ext4/xattr.c
|
|
+++ b/fs/ext4/xattr.c
|
|
@@ -356,7 +356,7 @@ ext4_xattr_inode_hash(struct ext4_sb_info *sbi, const void *buffer, size_t size)
|
|
|
|
static u64 ext4_xattr_inode_get_ref(struct inode *ea_inode)
|
|
{
|
|
- return ((u64) inode_get_ctime(ea_inode).tv_sec << 32) |
|
|
+ return ((u64) inode_get_ctime_sec(ea_inode) << 32) |
|
|
(u32) inode_peek_iversion_raw(ea_inode);
|
|
}
|
|
|
|
@@ -368,12 +368,12 @@ static void ext4_xattr_inode_set_ref(struct inode *ea_inode, u64 ref_count)
|
|
|
|
static u32 ext4_xattr_inode_get_hash(struct inode *ea_inode)
|
|
{
|
|
- return (u32)ea_inode->i_atime.tv_sec;
|
|
+ return (u32) inode_get_atime_sec(ea_inode);
|
|
}
|
|
|
|
static void ext4_xattr_inode_set_hash(struct inode *ea_inode, u32 hash)
|
|
{
|
|
- ea_inode->i_atime.tv_sec = hash;
|
|
+ inode_set_atime(ea_inode, hash, 0);
|
|
}
|
|
|
|
/*
|
|
@@ -418,7 +418,7 @@ static int ext4_xattr_inode_read(struct inode *ea_inode, void *buf, size_t size)
|
|
return ret;
|
|
}
|
|
|
|
-#define EXT4_XATTR_INODE_GET_PARENT(inode) ((__u32)(inode)->i_mtime.tv_sec)
|
|
+#define EXT4_XATTR_INODE_GET_PARENT(inode) ((__u32)(inode_get_mtime_sec(inode)))
|
|
|
|
static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
|
|
u32 ea_inode_hash, struct inode **ea_inode)
|
|
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
|
|
index 196755a34833d2..ae129044c52f42 100644
|
|
--- a/fs/f2fs/file.c
|
|
+++ b/fs/f2fs/file.c
|
|
@@ -1037,6 +1037,13 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
|
return err;
|
|
}
|
|
|
|
+ /*
|
|
+ * wait for inflight dio, blocks should be removed after
|
|
+ * IO completion.
|
|
+ */
|
|
+ if (attr->ia_size < old_size)
|
|
+ inode_dio_wait(inode);
|
|
+
|
|
f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
|
|
filemap_invalidate_lock(inode->i_mapping);
|
|
|
|
@@ -1873,6 +1880,12 @@ static long f2fs_fallocate(struct file *file, int mode,
|
|
if (ret)
|
|
goto out;
|
|
|
|
+ /*
|
|
+ * wait for inflight dio, blocks should be removed after IO
|
|
+ * completion.
|
|
+ */
|
|
+ inode_dio_wait(inode);
|
|
+
|
|
if (mode & FALLOC_FL_PUNCH_HOLE) {
|
|
if (offset >= inode->i_size)
|
|
goto out;
|
|
diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c
|
|
index fc6cea60044edf..e25989dd2c6bba 100644
|
|
--- a/fs/ntfs3/attrib.c
|
|
+++ b/fs/ntfs3/attrib.c
|
|
@@ -977,15 +977,17 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
|
|
goto out;
|
|
|
|
/* Check for compressed frame. */
|
|
- err = attr_is_frame_compressed(ni, attr, vcn >> NTFS_LZNT_CUNIT, &hint);
|
|
+ err = attr_is_frame_compressed(ni, attr_b, vcn >> NTFS_LZNT_CUNIT,
|
|
+ &hint, run);
|
|
if (err)
|
|
goto out;
|
|
|
|
if (hint) {
|
|
/* if frame is compressed - don't touch it. */
|
|
*lcn = COMPRESSED_LCN;
|
|
- *len = hint;
|
|
- err = -EOPNOTSUPP;
|
|
+ /* length to the end of frame. */
|
|
+ *len = NTFS_LZNT_CLUSTERS - (vcn & (NTFS_LZNT_CLUSTERS - 1));
|
|
+ err = 0;
|
|
goto out;
|
|
}
|
|
|
|
@@ -1028,16 +1030,16 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
|
|
|
|
/* Check if 'vcn' and 'vcn0' in different attribute segments. */
|
|
if (vcn < svcn || evcn1 <= vcn) {
|
|
- /* Load attribute for truncated vcn. */
|
|
- attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0,
|
|
- &vcn, &mi);
|
|
- if (!attr) {
|
|
+ struct ATTRIB *attr2;
|
|
+ /* Load runs for truncated vcn. */
|
|
+ attr2 = ni_find_attr(ni, attr_b, &le_b, ATTR_DATA, NULL,
|
|
+ 0, &vcn, &mi);
|
|
+ if (!attr2) {
|
|
err = -EINVAL;
|
|
goto out;
|
|
}
|
|
- svcn = le64_to_cpu(attr->nres.svcn);
|
|
- evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
|
|
- err = attr_load_runs(attr, ni, run, NULL);
|
|
+ evcn1 = le64_to_cpu(attr2->nres.evcn) + 1;
|
|
+ err = attr_load_runs(attr2, ni, run, NULL);
|
|
if (err)
|
|
goto out;
|
|
}
|
|
@@ -1530,15 +1532,18 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
|
|
/*
|
|
* attr_is_frame_compressed - Used to detect compressed frame.
|
|
+ *
|
|
+ * attr - base (primary) attribute segment.
|
|
+ * run - run to use, usually == &ni->file.run.
|
|
+ * Only base segments contains valid 'attr->nres.c_unit'
|
|
*/
|
|
int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
- CLST frame, CLST *clst_data)
|
|
+ CLST frame, CLST *clst_data, struct runs_tree *run)
|
|
{
|
|
int err;
|
|
u32 clst_frame;
|
|
CLST clen, lcn, vcn, alen, slen, vcn_next;
|
|
size_t idx;
|
|
- struct runs_tree *run;
|
|
|
|
*clst_data = 0;
|
|
|
|
@@ -1550,7 +1555,6 @@ int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
|
|
clst_frame = 1u << attr->nres.c_unit;
|
|
vcn = frame * clst_frame;
|
|
- run = &ni->file.run;
|
|
|
|
if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
|
|
err = attr_load_runs_vcn(ni, attr->type, attr_name(attr),
|
|
@@ -1686,7 +1690,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
|
|
if (err)
|
|
goto out;
|
|
|
|
- err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data);
|
|
+ err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data, run);
|
|
if (err)
|
|
goto out;
|
|
|
|
diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c
|
|
index 12e03feb3074a0..3c876c468c2c47 100644
|
|
--- a/fs/ntfs3/frecord.c
|
|
+++ b/fs/ntfs3/frecord.c
|
|
@@ -1900,46 +1900,6 @@ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
return REPARSE_LINK;
|
|
}
|
|
|
|
-/*
|
|
- * fiemap_fill_next_extent_k - a copy of fiemap_fill_next_extent
|
|
- * but it uses 'fe_k' instead of fieinfo->fi_extents_start
|
|
- */
|
|
-static int fiemap_fill_next_extent_k(struct fiemap_extent_info *fieinfo,
|
|
- struct fiemap_extent *fe_k, u64 logical,
|
|
- u64 phys, u64 len, u32 flags)
|
|
-{
|
|
- struct fiemap_extent extent;
|
|
-
|
|
- /* only count the extents */
|
|
- if (fieinfo->fi_extents_max == 0) {
|
|
- fieinfo->fi_extents_mapped++;
|
|
- return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
|
|
- }
|
|
-
|
|
- if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
|
|
- return 1;
|
|
-
|
|
- if (flags & FIEMAP_EXTENT_DELALLOC)
|
|
- flags |= FIEMAP_EXTENT_UNKNOWN;
|
|
- if (flags & FIEMAP_EXTENT_DATA_ENCRYPTED)
|
|
- flags |= FIEMAP_EXTENT_ENCODED;
|
|
- if (flags & (FIEMAP_EXTENT_DATA_TAIL | FIEMAP_EXTENT_DATA_INLINE))
|
|
- flags |= FIEMAP_EXTENT_NOT_ALIGNED;
|
|
-
|
|
- memset(&extent, 0, sizeof(extent));
|
|
- extent.fe_logical = logical;
|
|
- extent.fe_physical = phys;
|
|
- extent.fe_length = len;
|
|
- extent.fe_flags = flags;
|
|
-
|
|
- memcpy(fe_k + fieinfo->fi_extents_mapped, &extent, sizeof(extent));
|
|
-
|
|
- fieinfo->fi_extents_mapped++;
|
|
- if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max)
|
|
- return 1;
|
|
- return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
|
|
-}
|
|
-
|
|
/*
|
|
* ni_fiemap - Helper for file_fiemap().
|
|
*
|
|
@@ -1950,11 +1910,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
__u64 vbo, __u64 len)
|
|
{
|
|
int err = 0;
|
|
- struct fiemap_extent *fe_k = NULL;
|
|
struct ntfs_sb_info *sbi = ni->mi.sbi;
|
|
u8 cluster_bits = sbi->cluster_bits;
|
|
- struct runs_tree *run;
|
|
- struct rw_semaphore *run_lock;
|
|
+ struct runs_tree run;
|
|
struct ATTRIB *attr;
|
|
CLST vcn = vbo >> cluster_bits;
|
|
CLST lcn, clen;
|
|
@@ -1965,13 +1923,11 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
u32 flags;
|
|
bool ok;
|
|
|
|
+ run_init(&run);
|
|
if (S_ISDIR(ni->vfs_inode.i_mode)) {
|
|
- run = &ni->dir.alloc_run;
|
|
attr = ni_find_attr(ni, NULL, NULL, ATTR_ALLOC, I30_NAME,
|
|
ARRAY_SIZE(I30_NAME), NULL, NULL);
|
|
- run_lock = &ni->dir.run_lock;
|
|
} else {
|
|
- run = &ni->file.run;
|
|
attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL,
|
|
NULL);
|
|
if (!attr) {
|
|
@@ -1986,7 +1942,6 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
"fiemap is not supported for compressed file (cp -r)");
|
|
goto out;
|
|
}
|
|
- run_lock = &ni->file.run_lock;
|
|
}
|
|
|
|
if (!attr || !attr->non_res) {
|
|
@@ -1998,51 +1953,33 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
goto out;
|
|
}
|
|
|
|
- /*
|
|
- * To avoid lock problems replace pointer to user memory by pointer to kernel memory.
|
|
- */
|
|
- fe_k = kmalloc_array(fieinfo->fi_extents_max,
|
|
- sizeof(struct fiemap_extent),
|
|
- GFP_NOFS | __GFP_ZERO);
|
|
- if (!fe_k) {
|
|
- err = -ENOMEM;
|
|
- goto out;
|
|
- }
|
|
-
|
|
end = vbo + len;
|
|
alloc_size = le64_to_cpu(attr->nres.alloc_size);
|
|
if (end > alloc_size)
|
|
end = alloc_size;
|
|
|
|
- down_read(run_lock);
|
|
|
|
while (vbo < end) {
|
|
if (idx == -1) {
|
|
- ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
|
|
+ ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx);
|
|
} else {
|
|
CLST vcn_next = vcn;
|
|
|
|
- ok = run_get_entry(run, ++idx, &vcn, &lcn, &clen) &&
|
|
+ ok = run_get_entry(&run, ++idx, &vcn, &lcn, &clen) &&
|
|
vcn == vcn_next;
|
|
if (!ok)
|
|
vcn = vcn_next;
|
|
}
|
|
|
|
if (!ok) {
|
|
- up_read(run_lock);
|
|
- down_write(run_lock);
|
|
-
|
|
err = attr_load_runs_vcn(ni, attr->type,
|
|
attr_name(attr),
|
|
- attr->name_len, run, vcn);
|
|
-
|
|
- up_write(run_lock);
|
|
- down_read(run_lock);
|
|
+ attr->name_len, &run, vcn);
|
|
|
|
if (err)
|
|
break;
|
|
|
|
- ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
|
|
+ ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx);
|
|
|
|
if (!ok) {
|
|
err = -EINVAL;
|
|
@@ -2067,8 +2004,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
} else if (is_attr_compressed(attr)) {
|
|
CLST clst_data;
|
|
|
|
- err = attr_is_frame_compressed(
|
|
- ni, attr, vcn >> attr->nres.c_unit, &clst_data);
|
|
+ err = attr_is_frame_compressed(ni, attr,
|
|
+ vcn >> attr->nres.c_unit,
|
|
+ &clst_data, &run);
|
|
if (err)
|
|
break;
|
|
if (clst_data < NTFS_LZNT_CLUSTERS)
|
|
@@ -2097,8 +2035,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
if (vbo + dlen >= end)
|
|
flags |= FIEMAP_EXTENT_LAST;
|
|
|
|
- err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo,
|
|
- dlen, flags);
|
|
+ err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen,
|
|
+ flags);
|
|
|
|
if (err < 0)
|
|
break;
|
|
@@ -2119,8 +2057,7 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
if (vbo + bytes >= end)
|
|
flags |= FIEMAP_EXTENT_LAST;
|
|
|
|
- err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo, bytes,
|
|
- flags);
|
|
+ err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags);
|
|
if (err < 0)
|
|
break;
|
|
if (err == 1) {
|
|
@@ -2131,19 +2068,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
|
|
vbo += bytes;
|
|
}
|
|
|
|
- up_read(run_lock);
|
|
-
|
|
- /*
|
|
- * Copy to user memory out of lock
|
|
- */
|
|
- if (copy_to_user(fieinfo->fi_extents_start, fe_k,
|
|
- fieinfo->fi_extents_max *
|
|
- sizeof(struct fiemap_extent))) {
|
|
- err = -EFAULT;
|
|
- }
|
|
-
|
|
out:
|
|
- kfree(fe_k);
|
|
+ run_close(&run);
|
|
return err;
|
|
}
|
|
|
|
@@ -2674,7 +2600,8 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
|
|
down_write(&ni->file.run_lock);
|
|
run_truncate_around(run, le64_to_cpu(attr->nres.svcn));
|
|
frame = frame_vbo >> (cluster_bits + NTFS_LZNT_CUNIT);
|
|
- err = attr_is_frame_compressed(ni, attr, frame, &clst_data);
|
|
+ err = attr_is_frame_compressed(ni, attr, frame, &clst_data,
|
|
+ run);
|
|
up_write(&ni->file.run_lock);
|
|
if (err)
|
|
goto out1;
|
|
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
|
|
index 52b80fd1591478..af7c0cbba74e3d 100644
|
|
--- a/fs/ntfs3/inode.c
|
|
+++ b/fs/ntfs3/inode.c
|
|
@@ -604,7 +604,8 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo,
|
|
|
|
bytes = ((u64)len << cluster_bits) - off;
|
|
|
|
- if (lcn == SPARSE_LCN) {
|
|
+ if (lcn >= sbi->used.bitmap.nbits) {
|
|
+ /* This case includes resident/compressed/sparse. */
|
|
if (!create) {
|
|
if (bh->b_size > bytes)
|
|
bh->b_size = bytes;
|
|
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
|
|
index cfe9d3bf07f910..c98e6868bfbadb 100644
|
|
--- a/fs/ntfs3/ntfs_fs.h
|
|
+++ b/fs/ntfs3/ntfs_fs.h
|
|
@@ -446,7 +446,8 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
struct runs_tree *run, u64 frame, u64 frames,
|
|
u8 frame_bits, u32 *ondisk_size, u64 *vbo_data);
|
|
int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
- CLST frame, CLST *clst_data);
|
|
+ CLST frame, CLST *clst_data,
|
|
+ struct runs_tree *run);
|
|
int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
|
|
u64 new_valid);
|
|
int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes);
|
|
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
|
|
index dc9f76ab7e13c3..0dffd6a44d39dc 100644
|
|
--- a/fs/ocfs2/quota_global.c
|
|
+++ b/fs/ocfs2/quota_global.c
|
|
@@ -881,7 +881,7 @@ static int ocfs2_get_next_id(struct super_block *sb, struct kqid *qid)
|
|
int status = 0;
|
|
|
|
trace_ocfs2_get_next_id(from_kqid(&init_user_ns, *qid), type);
|
|
- if (!sb_has_quota_loaded(sb, type)) {
|
|
+ if (!sb_has_quota_active(sb, type)) {
|
|
status = -ESRCH;
|
|
goto out;
|
|
}
|
|
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
|
|
index 257f13cdd14c1f..4b4fa58cd32ff0 100644
|
|
--- a/fs/ocfs2/quota_local.c
|
|
+++ b/fs/ocfs2/quota_local.c
|
|
@@ -864,6 +864,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type)
|
|
brelse(oinfo->dqi_libh);
|
|
brelse(oinfo->dqi_lqi_bh);
|
|
kfree(oinfo);
|
|
+ info->dqi_priv = NULL;
|
|
return status;
|
|
}
|
|
|
|
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
|
|
index 59571737e16771..b8640f36ebf8ab 100644
|
|
--- a/fs/proc/task_mmu.c
|
|
+++ b/fs/proc/task_mmu.c
|
|
@@ -1516,7 +1516,7 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
|
|
flags |= PM_FILE;
|
|
|
|
for (; addr != end; addr += PAGE_SIZE, idx++) {
|
|
- unsigned long cur_flags = flags;
|
|
+ u64 cur_flags = flags;
|
|
pagemap_entry_t pme;
|
|
|
|
if (page && (flags & PM_PRESENT) &&
|
|
diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c
|
|
index f5b6df82e8570a..bff8d0dd74fe7d 100644
|
|
--- a/fs/smb/client/cifsacl.c
|
|
+++ b/fs/smb/client/cifsacl.c
|
|
@@ -27,18 +27,18 @@
|
|
#include "cifs_unicode.h"
|
|
|
|
/* security id for everyone/world system group */
|
|
-static const struct cifs_sid sid_everyone = {
|
|
+static const struct smb_sid sid_everyone = {
|
|
1, 1, {0, 0, 0, 0, 0, 1}, {0} };
|
|
/* security id for Authenticated Users system group */
|
|
-static const struct cifs_sid sid_authusers = {
|
|
+static const struct smb_sid sid_authusers = {
|
|
1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
|
|
|
|
/* S-1-22-1 Unmapped Unix users */
|
|
-static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
|
|
+static const struct smb_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
|
|
{cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
|
|
|
/* S-1-22-2 Unmapped Unix groups */
|
|
-static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
|
|
+static const struct smb_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
|
|
{cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
|
|
|
/*
|
|
@@ -48,17 +48,17 @@ static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
|
|
/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
|
|
|
|
/* S-1-5-88-1 Unix uid */
|
|
-static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
|
|
+static const struct smb_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
|
|
{cpu_to_le32(88),
|
|
cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
|
|
|
/* S-1-5-88-2 Unix gid */
|
|
-static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
|
|
+static const struct smb_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
|
|
{cpu_to_le32(88),
|
|
cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
|
|
|
/* S-1-5-88-3 Unix mode */
|
|
-static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
|
|
+static const struct smb_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
|
|
{cpu_to_le32(88),
|
|
cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
|
|
|
|
@@ -106,7 +106,7 @@ static struct key_type cifs_idmap_key_type = {
|
|
};
|
|
|
|
static char *
|
|
-sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
|
|
+sid_to_key_str(struct smb_sid *sidptr, unsigned int type)
|
|
{
|
|
int i, len;
|
|
unsigned int saval;
|
|
@@ -158,7 +158,7 @@ sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
|
|
* the same returns zero, if they do not match returns non-zero.
|
|
*/
|
|
static int
|
|
-compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
|
|
+compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid)
|
|
{
|
|
int i;
|
|
int num_subauth, num_sat, num_saw;
|
|
@@ -204,11 +204,11 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
|
|
}
|
|
|
|
static bool
|
|
-is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
|
|
+is_well_known_sid(const struct smb_sid *psid, uint32_t *puid, bool is_group)
|
|
{
|
|
int i;
|
|
int num_subauth;
|
|
- const struct cifs_sid *pwell_known_sid;
|
|
+ const struct smb_sid *pwell_known_sid;
|
|
|
|
if (!psid || (puid == NULL))
|
|
return false;
|
|
@@ -260,7 +260,7 @@ is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
|
|
}
|
|
|
|
static __u16
|
|
-cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
|
|
+cifs_copy_sid(struct smb_sid *dst, const struct smb_sid *src)
|
|
{
|
|
int i;
|
|
__u16 size = 1 + 1 + 6;
|
|
@@ -277,11 +277,11 @@ cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
|
|
}
|
|
|
|
static int
|
|
-id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
|
|
+id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
|
|
{
|
|
int rc;
|
|
struct key *sidkey;
|
|
- struct cifs_sid *ksid;
|
|
+ struct smb_sid *ksid;
|
|
unsigned int ksid_size;
|
|
char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
|
|
const struct cred *saved_cred;
|
|
@@ -312,8 +312,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
|
|
* it could be.
|
|
*/
|
|
ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
|
|
- (struct cifs_sid *)&sidkey->payload :
|
|
- (struct cifs_sid *)sidkey->payload.data[0];
|
|
+ (struct smb_sid *)&sidkey->payload :
|
|
+ (struct smb_sid *)sidkey->payload.data[0];
|
|
|
|
ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
|
|
if (ksid_size > sidkey->datalen) {
|
|
@@ -336,7 +336,7 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
|
|
}
|
|
|
|
int
|
|
-sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
|
|
+sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
|
|
struct cifs_fattr *fattr, uint sidtype)
|
|
{
|
|
int rc = 0;
|
|
@@ -515,43 +515,43 @@ exit_cifs_idmap(void)
|
|
}
|
|
|
|
/* copy ntsd, owner sid, and group sid from a security descriptor to another */
|
|
-static __u32 copy_sec_desc(const struct cifs_ntsd *pntsd,
|
|
- struct cifs_ntsd *pnntsd,
|
|
+static __u32 copy_sec_desc(const struct smb_ntsd *pntsd,
|
|
+ struct smb_ntsd *pnntsd,
|
|
__u32 sidsoffset,
|
|
- struct cifs_sid *pownersid,
|
|
- struct cifs_sid *pgrpsid)
|
|
+ struct smb_sid *pownersid,
|
|
+ struct smb_sid *pgrpsid)
|
|
{
|
|
- struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
|
- struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
|
|
+ struct smb_sid *owner_sid_ptr, *group_sid_ptr;
|
|
+ struct smb_sid *nowner_sid_ptr, *ngroup_sid_ptr;
|
|
|
|
/* copy security descriptor control portion */
|
|
pnntsd->revision = pntsd->revision;
|
|
pnntsd->type = pntsd->type;
|
|
- pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
|
|
+ pnntsd->dacloffset = cpu_to_le32(sizeof(struct smb_ntsd));
|
|
pnntsd->sacloffset = 0;
|
|
pnntsd->osidoffset = cpu_to_le32(sidsoffset);
|
|
- pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
|
|
+ pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct smb_sid));
|
|
|
|
/* copy owner sid */
|
|
if (pownersid)
|
|
owner_sid_ptr = pownersid;
|
|
else
|
|
- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
|
+ owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
|
le32_to_cpu(pntsd->osidoffset));
|
|
- nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
|
|
+ nowner_sid_ptr = (struct smb_sid *)((char *)pnntsd + sidsoffset);
|
|
cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
|
|
|
|
/* copy group sid */
|
|
if (pgrpsid)
|
|
group_sid_ptr = pgrpsid;
|
|
else
|
|
- group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
|
+ group_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
|
le32_to_cpu(pntsd->gsidoffset));
|
|
- ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
|
|
- sizeof(struct cifs_sid));
|
|
+ ngroup_sid_ptr = (struct smb_sid *)((char *)pnntsd + sidsoffset +
|
|
+ sizeof(struct smb_sid));
|
|
cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
|
|
|
|
- return sidsoffset + (2 * sizeof(struct cifs_sid));
|
|
+ return sidsoffset + (2 * sizeof(struct smb_sid));
|
|
}
|
|
|
|
|
|
@@ -666,7 +666,7 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
|
|
return;
|
|
}
|
|
|
|
-static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct cifs_sid *psid)
|
|
+static __u16 cifs_copy_ace(struct smb_ace *dst, struct smb_ace *src, struct smb_sid *psid)
|
|
{
|
|
__u16 size = 1 + 1 + 2 + 4;
|
|
|
|
@@ -685,8 +685,8 @@ static __u16 cifs_copy_ace(struct cifs_ace *dst, struct cifs_ace *src, struct ci
|
|
return size;
|
|
}
|
|
|
|
-static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
|
|
- const struct cifs_sid *psid, __u64 nmode,
|
|
+static __u16 fill_ace_for_sid(struct smb_ace *pntace,
|
|
+ const struct smb_sid *psid, __u64 nmode,
|
|
umode_t bits, __u8 access_type,
|
|
bool allow_delete_child)
|
|
{
|
|
@@ -723,7 +723,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
|
|
|
|
|
|
#ifdef CONFIG_CIFS_DEBUG2
|
|
-static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
|
|
+static void dump_ace(struct smb_ace *pace, char *end_of_acl)
|
|
{
|
|
int num_subauth;
|
|
|
|
@@ -758,15 +758,15 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
|
|
}
|
|
#endif
|
|
|
|
-static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
|
|
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
|
|
+static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
|
+ struct smb_sid *pownersid, struct smb_sid *pgrpsid,
|
|
struct cifs_fattr *fattr, bool mode_from_special_sid)
|
|
{
|
|
int i;
|
|
int num_aces = 0;
|
|
int acl_size;
|
|
char *acl_base;
|
|
- struct cifs_ace **ppace;
|
|
+ struct smb_ace **ppace;
|
|
|
|
/* BB need to add parm so we can store the SID BB */
|
|
|
|
@@ -793,21 +793,21 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
|
|
fattr->cf_mode &= ~(0777);
|
|
|
|
acl_base = (char *)pdacl;
|
|
- acl_size = sizeof(struct cifs_acl);
|
|
+ acl_size = sizeof(struct smb_acl);
|
|
|
|
num_aces = le32_to_cpu(pdacl->num_aces);
|
|
if (num_aces > 0) {
|
|
umode_t denied_mode = 0;
|
|
|
|
- if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
|
|
+ if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
|
|
return;
|
|
- ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
|
|
+ ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *),
|
|
GFP_KERNEL);
|
|
if (!ppace)
|
|
return;
|
|
|
|
for (i = 0; i < num_aces; ++i) {
|
|
- ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
|
|
+ ppace[i] = (struct smb_ace *) (acl_base + acl_size);
|
|
#ifdef CONFIG_CIFS_DEBUG2
|
|
dump_ace(ppace[i], end_of_acl);
|
|
#endif
|
|
@@ -849,7 +849,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
|
|
|
|
/* memcpy((void *)(&(cifscred->aces[i])),
|
|
(void *)ppace[i],
|
|
- sizeof(struct cifs_ace)); */
|
|
+ sizeof(struct smb_ace)); */
|
|
|
|
acl_base = (char *)ppace[i];
|
|
acl_size = le16_to_cpu(ppace[i]->size);
|
|
@@ -861,7 +861,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
|
|
return;
|
|
}
|
|
|
|
-unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
|
|
+unsigned int setup_authusers_ACE(struct smb_ace *pntace)
|
|
{
|
|
int i;
|
|
unsigned int ace_size = 20;
|
|
@@ -885,12 +885,17 @@ unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
|
|
* Fill in the special SID based on the mode. See
|
|
* https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
|
|
*/
|
|
-unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
|
|
+unsigned int setup_special_mode_ACE(struct smb_ace *pntace,
|
|
+ bool posix,
|
|
+ __u64 nmode)
|
|
{
|
|
int i;
|
|
unsigned int ace_size = 28;
|
|
|
|
- pntace->type = ACCESS_DENIED_ACE_TYPE;
|
|
+ if (posix)
|
|
+ pntace->type = ACCESS_ALLOWED_ACE_TYPE;
|
|
+ else
|
|
+ pntace->type = ACCESS_DENIED_ACE_TYPE;
|
|
pntace->flags = 0x0;
|
|
pntace->access_req = 0;
|
|
pntace->sid.num_subauth = 3;
|
|
@@ -907,7 +912,7 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
|
|
return ace_size;
|
|
}
|
|
|
|
-unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
|
|
+unsigned int setup_special_user_owner_ACE(struct smb_ace *pntace)
|
|
{
|
|
int i;
|
|
unsigned int ace_size = 28;
|
|
@@ -930,10 +935,11 @@ unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
|
|
}
|
|
|
|
static void populate_new_aces(char *nacl_base,
|
|
- struct cifs_sid *pownersid,
|
|
- struct cifs_sid *pgrpsid,
|
|
+ struct smb_sid *pownersid,
|
|
+ struct smb_sid *pgrpsid,
|
|
__u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
|
|
- bool modefromsid)
|
|
+ bool modefromsid,
|
|
+ bool posix)
|
|
{
|
|
__u64 nmode;
|
|
u32 num_aces = 0;
|
|
@@ -944,19 +950,21 @@ static void populate_new_aces(char *nacl_base,
|
|
__u64 deny_user_mode = 0;
|
|
__u64 deny_group_mode = 0;
|
|
bool sticky_set = false;
|
|
- struct cifs_ace *pnntace = NULL;
|
|
+ struct smb_ace *pnntace = NULL;
|
|
|
|
nmode = *pnmode;
|
|
num_aces = *pnum_aces;
|
|
nsize = *pnsize;
|
|
|
|
- if (modefromsid) {
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
- nsize += setup_special_mode_ACE(pnntace, nmode);
|
|
- num_aces++;
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
- nsize += setup_authusers_ACE(pnntace);
|
|
+ if (modefromsid || posix) {
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
+ nsize += setup_special_mode_ACE(pnntace, posix, nmode);
|
|
num_aces++;
|
|
+ if (modefromsid) {
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
+ nsize += setup_authusers_ACE(pnntace);
|
|
+ num_aces++;
|
|
+ }
|
|
goto set_size;
|
|
}
|
|
|
|
@@ -967,7 +975,7 @@ static void populate_new_aces(char *nacl_base,
|
|
* updated in the inode.
|
|
*/
|
|
|
|
- if (!memcmp(pownersid, pgrpsid, sizeof(struct cifs_sid))) {
|
|
+ if (!memcmp(pownersid, pgrpsid, sizeof(struct smb_sid))) {
|
|
/*
|
|
* Case when owner and group SIDs are the same.
|
|
* Set the more restrictive of the two modes.
|
|
@@ -992,7 +1000,7 @@ static void populate_new_aces(char *nacl_base,
|
|
sticky_set = true;
|
|
|
|
if (deny_user_mode) {
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
nsize += fill_ace_for_sid(pnntace, pownersid, deny_user_mode,
|
|
0700, ACCESS_DENIED, false);
|
|
num_aces++;
|
|
@@ -1000,31 +1008,31 @@ static void populate_new_aces(char *nacl_base,
|
|
|
|
/* Group DENY ACE does not conflict with owner ALLOW ACE. Keep in preferred order*/
|
|
if (deny_group_mode && !(deny_group_mode & (user_mode >> 3))) {
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
|
|
0070, ACCESS_DENIED, false);
|
|
num_aces++;
|
|
}
|
|
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
nsize += fill_ace_for_sid(pnntace, pownersid, user_mode,
|
|
0700, ACCESS_ALLOWED, true);
|
|
num_aces++;
|
|
|
|
/* Group DENY ACE conflicts with owner ALLOW ACE. So keep it after. */
|
|
if (deny_group_mode && (deny_group_mode & (user_mode >> 3))) {
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
nsize += fill_ace_for_sid(pnntace, pgrpsid, deny_group_mode,
|
|
0070, ACCESS_DENIED, false);
|
|
num_aces++;
|
|
}
|
|
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
nsize += fill_ace_for_sid(pnntace, pgrpsid, group_mode,
|
|
0070, ACCESS_ALLOWED, !sticky_set);
|
|
num_aces++;
|
|
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
nsize += fill_ace_for_sid(pnntace, &sid_everyone, other_mode,
|
|
0007, ACCESS_ALLOWED, !sticky_set);
|
|
num_aces++;
|
|
@@ -1034,31 +1042,31 @@ static void populate_new_aces(char *nacl_base,
|
|
*pnsize = nsize;
|
|
}
|
|
|
|
-static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
|
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
|
|
- struct cifs_sid *pnownersid, struct cifs_sid *pngrpsid)
|
|
+static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *pndacl,
|
|
+ struct smb_sid *pownersid, struct smb_sid *pgrpsid,
|
|
+ struct smb_sid *pnownersid, struct smb_sid *pngrpsid)
|
|
{
|
|
int i;
|
|
u16 size = 0;
|
|
- struct cifs_ace *pntace = NULL;
|
|
+ struct smb_ace *pntace = NULL;
|
|
char *acl_base = NULL;
|
|
u32 src_num_aces = 0;
|
|
u16 nsize = 0;
|
|
- struct cifs_ace *pnntace = NULL;
|
|
+ struct smb_ace *pnntace = NULL;
|
|
char *nacl_base = NULL;
|
|
u16 ace_size = 0;
|
|
|
|
acl_base = (char *)pdacl;
|
|
- size = sizeof(struct cifs_acl);
|
|
+ size = sizeof(struct smb_acl);
|
|
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
|
|
|
nacl_base = (char *)pndacl;
|
|
- nsize = sizeof(struct cifs_acl);
|
|
+ nsize = sizeof(struct smb_acl);
|
|
|
|
/* Go through all the ACEs */
|
|
for (i = 0; i < src_num_aces; ++i) {
|
|
- pntace = (struct cifs_ace *) (acl_base + size);
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pntace = (struct smb_ace *) (acl_base + size);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
|
|
if (pnownersid && compare_sids(&pntace->sid, pownersid) == 0)
|
|
ace_size = cifs_copy_ace(pnntace, pntace, pnownersid);
|
|
@@ -1074,48 +1082,48 @@ static __u16 replace_sids_and_copy_aces(struct cifs_acl *pdacl, struct cifs_acl
|
|
return nsize;
|
|
}
|
|
|
|
-static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
|
- struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
|
|
- __u64 *pnmode, bool mode_from_sid)
|
|
+static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
|
|
+ struct smb_sid *pownersid, struct smb_sid *pgrpsid,
|
|
+ __u64 *pnmode, bool mode_from_sid, bool posix)
|
|
{
|
|
int i;
|
|
u16 size = 0;
|
|
- struct cifs_ace *pntace = NULL;
|
|
+ struct smb_ace *pntace = NULL;
|
|
char *acl_base = NULL;
|
|
u32 src_num_aces = 0;
|
|
u16 nsize = 0;
|
|
- struct cifs_ace *pnntace = NULL;
|
|
+ struct smb_ace *pnntace = NULL;
|
|
char *nacl_base = NULL;
|
|
u32 num_aces = 0;
|
|
bool new_aces_set = false;
|
|
|
|
/* Assuming that pndacl and pnmode are never NULL */
|
|
nacl_base = (char *)pndacl;
|
|
- nsize = sizeof(struct cifs_acl);
|
|
+ nsize = sizeof(struct smb_acl);
|
|
|
|
/* If pdacl is NULL, we don't have a src. Simply populate new ACL. */
|
|
- if (!pdacl) {
|
|
+ if (!pdacl || posix) {
|
|
populate_new_aces(nacl_base,
|
|
pownersid, pgrpsid,
|
|
pnmode, &num_aces, &nsize,
|
|
- mode_from_sid);
|
|
+ mode_from_sid, posix);
|
|
goto finalize_dacl;
|
|
}
|
|
|
|
acl_base = (char *)pdacl;
|
|
- size = sizeof(struct cifs_acl);
|
|
+ size = sizeof(struct smb_acl);
|
|
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
|
|
|
/* Retain old ACEs which we can retain */
|
|
for (i = 0; i < src_num_aces; ++i) {
|
|
- pntace = (struct cifs_ace *) (acl_base + size);
|
|
+ pntace = (struct smb_ace *) (acl_base + size);
|
|
|
|
if (!new_aces_set && (pntace->flags & INHERITED_ACE)) {
|
|
/* Place the new ACEs in between existing explicit and inherited */
|
|
populate_new_aces(nacl_base,
|
|
pownersid, pgrpsid,
|
|
pnmode, &num_aces, &nsize,
|
|
- mode_from_sid);
|
|
+ mode_from_sid, posix);
|
|
|
|
new_aces_set = true;
|
|
}
|
|
@@ -1130,7 +1138,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
|
}
|
|
|
|
/* update the pointer to the next ACE to populate*/
|
|
- pnntace = (struct cifs_ace *) (nacl_base + nsize);
|
|
+ pnntace = (struct smb_ace *) (nacl_base + nsize);
|
|
|
|
nsize += cifs_copy_ace(pnntace, pntace, NULL);
|
|
num_aces++;
|
|
@@ -1144,7 +1152,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
|
populate_new_aces(nacl_base,
|
|
pownersid, pgrpsid,
|
|
pnmode, &num_aces, &nsize,
|
|
- mode_from_sid);
|
|
+ mode_from_sid, posix);
|
|
|
|
new_aces_set = true;
|
|
}
|
|
@@ -1156,7 +1164,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
|
return 0;
|
|
}
|
|
|
|
-static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
|
|
+static int parse_sid(struct smb_sid *psid, char *end_of_acl)
|
|
{
|
|
/* BB need to add parm so we can store the SID BB */
|
|
|
|
@@ -1191,24 +1199,24 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
|
|
|
|
/* Convert CIFS ACL to POSIX form */
|
|
static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
|
|
- struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
|
|
+ struct smb_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
|
|
bool get_mode_from_special_sid)
|
|
{
|
|
int rc = 0;
|
|
- struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
|
- struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
|
|
+ struct smb_sid *owner_sid_ptr, *group_sid_ptr;
|
|
+ struct smb_acl *dacl_ptr; /* no need for SACL ptr */
|
|
char *end_of_acl = ((char *)pntsd) + acl_len;
|
|
__u32 dacloffset;
|
|
|
|
if (pntsd == NULL)
|
|
return -EIO;
|
|
|
|
- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
|
+ owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
|
le32_to_cpu(pntsd->osidoffset));
|
|
- group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
|
+ group_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
|
le32_to_cpu(pntsd->gsidoffset));
|
|
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
|
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
|
|
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
|
|
cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
|
|
pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
|
|
le32_to_cpu(pntsd->gsidoffset),
|
|
@@ -1249,38 +1257,38 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
|
|
}
|
|
|
|
/* Convert permission bits from mode to equivalent CIFS ACL */
|
|
-static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
|
+static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd,
|
|
__u32 secdesclen, __u32 *pnsecdesclen, __u64 *pnmode, kuid_t uid, kgid_t gid,
|
|
- bool mode_from_sid, bool id_from_sid, int *aclflag)
|
|
+ bool mode_from_sid, bool id_from_sid, bool posix, int *aclflag)
|
|
{
|
|
int rc = 0;
|
|
__u32 dacloffset;
|
|
__u32 ndacloffset;
|
|
__u32 sidsoffset;
|
|
- struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
|
- struct cifs_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
|
|
- struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
|
|
- struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
|
|
+ struct smb_sid *owner_sid_ptr, *group_sid_ptr;
|
|
+ struct smb_sid *nowner_sid_ptr = NULL, *ngroup_sid_ptr = NULL;
|
|
+ struct smb_acl *dacl_ptr = NULL; /* no need for SACL ptr */
|
|
+ struct smb_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
|
|
char *end_of_acl = ((char *)pntsd) + secdesclen;
|
|
u16 size = 0;
|
|
|
|
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
|
if (dacloffset) {
|
|
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
|
|
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
|
|
if (end_of_acl < (char *)dacl_ptr + le16_to_cpu(dacl_ptr->size)) {
|
|
cifs_dbg(VFS, "Server returned illegal ACL size\n");
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
- owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
|
+ owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
|
le32_to_cpu(pntsd->osidoffset));
|
|
- group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
|
+ group_sid_ptr = (struct smb_sid *)((char *)pntsd +
|
|
le32_to_cpu(pntsd->gsidoffset));
|
|
|
|
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
|
|
- ndacloffset = sizeof(struct cifs_ntsd);
|
|
- ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
|
|
+ ndacloffset = sizeof(struct smb_ntsd);
|
|
+ ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset);
|
|
ndacl_ptr->revision =
|
|
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
|
|
|
|
@@ -1288,7 +1296,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
|
ndacl_ptr->num_aces = cpu_to_le32(0);
|
|
|
|
rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr,
|
|
- pnmode, mode_from_sid);
|
|
+ pnmode, mode_from_sid, posix);
|
|
|
|
sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
|
|
/* copy the non-dacl portion of secdesc */
|
|
@@ -1297,15 +1305,15 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
|
|
|
*aclflag |= CIFS_ACL_DACL;
|
|
} else {
|
|
- ndacloffset = sizeof(struct cifs_ntsd);
|
|
- ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
|
|
+ ndacloffset = sizeof(struct smb_ntsd);
|
|
+ ndacl_ptr = (struct smb_acl *)((char *)pnntsd + ndacloffset);
|
|
ndacl_ptr->revision =
|
|
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
|
|
ndacl_ptr->num_aces = dacl_ptr ? dacl_ptr->num_aces : 0;
|
|
|
|
if (uid_valid(uid)) { /* chown */
|
|
uid_t id;
|
|
- nowner_sid_ptr = kzalloc(sizeof(struct cifs_sid),
|
|
+ nowner_sid_ptr = kzalloc(sizeof(struct smb_sid),
|
|
GFP_KERNEL);
|
|
if (!nowner_sid_ptr) {
|
|
rc = -ENOMEM;
|
|
@@ -1334,7 +1342,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
|
}
|
|
if (gid_valid(gid)) { /* chgrp */
|
|
gid_t id;
|
|
- ngroup_sid_ptr = kzalloc(sizeof(struct cifs_sid),
|
|
+ ngroup_sid_ptr = kzalloc(sizeof(struct smb_sid),
|
|
GFP_KERNEL);
|
|
if (!ngroup_sid_ptr) {
|
|
rc = -ENOMEM;
|
|
@@ -1385,11 +1393,11 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
|
}
|
|
|
|
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
|
-struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
|
+struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
|
const struct cifs_fid *cifsfid, u32 *pacllen,
|
|
u32 __maybe_unused unused)
|
|
{
|
|
- struct cifs_ntsd *pntsd = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL;
|
|
unsigned int xid;
|
|
int rc;
|
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
|
@@ -1410,10 +1418,10 @@ struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
|
return pntsd;
|
|
}
|
|
|
|
-static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|
+static struct smb_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|
const char *path, u32 *pacllen)
|
|
{
|
|
- struct cifs_ntsd *pntsd = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL;
|
|
int oplock = 0;
|
|
unsigned int xid;
|
|
int rc;
|
|
@@ -1454,11 +1462,11 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|
}
|
|
|
|
/* Retrieve an ACL from the server */
|
|
-struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
|
+struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
|
struct inode *inode, const char *path,
|
|
u32 *pacllen, u32 info)
|
|
{
|
|
- struct cifs_ntsd *pntsd = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL;
|
|
struct cifsFileInfo *open_file = NULL;
|
|
|
|
if (inode)
|
|
@@ -1472,7 +1480,7 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
|
|
}
|
|
|
|
/* Set an ACL on the server */
|
|
-int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
|
+int set_cifs_acl(struct smb_ntsd *pnntsd, __u32 acllen,
|
|
struct inode *inode, const char *path, int aclflag)
|
|
{
|
|
int oplock = 0;
|
|
@@ -1528,7 +1536,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
|
struct inode *inode, bool mode_from_special_sid,
|
|
const char *path, const struct cifs_fid *pfid)
|
|
{
|
|
- struct cifs_ntsd *pntsd = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL;
|
|
u32 acllen = 0;
|
|
int rc = 0;
|
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
|
@@ -1580,13 +1588,14 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
|
__u32 secdesclen = 0;
|
|
__u32 nsecdesclen = 0;
|
|
__u32 dacloffset = 0;
|
|
- struct cifs_acl *dacl_ptr = NULL;
|
|
- struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
|
|
- struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
|
|
+ struct smb_acl *dacl_ptr = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL; /* acl obtained from server */
|
|
+ struct smb_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
|
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
|
struct smb_version_operations *ops;
|
|
bool mode_from_sid, id_from_sid;
|
|
+ bool posix = tlink_tcon(tlink)->posix_extensions;
|
|
const u32 info = 0;
|
|
|
|
if (IS_ERR(tlink))
|
|
@@ -1622,21 +1631,22 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
|
id_from_sid = false;
|
|
|
|
/* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */
|
|
- nsecdesclen = secdesclen;
|
|
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */
|
|
- if (mode_from_sid)
|
|
- nsecdesclen += 2 * sizeof(struct cifs_ace);
|
|
+ if (posix)
|
|
+ nsecdesclen = 1 * sizeof(struct smb_ace);
|
|
+ else if (mode_from_sid)
|
|
+ nsecdesclen = secdesclen + (2 * sizeof(struct smb_ace));
|
|
else /* cifsacl */
|
|
- nsecdesclen += 5 * sizeof(struct cifs_ace);
|
|
+ nsecdesclen = secdesclen + (5 * sizeof(struct smb_ace));
|
|
} else { /* chown */
|
|
/* When ownership changes, changes new owner sid length could be different */
|
|
- nsecdesclen = sizeof(struct cifs_ntsd) + (sizeof(struct cifs_sid) * 2);
|
|
+ nsecdesclen = sizeof(struct smb_ntsd) + (sizeof(struct smb_sid) * 2);
|
|
dacloffset = le32_to_cpu(pntsd->dacloffset);
|
|
if (dacloffset) {
|
|
- dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
|
|
+ dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
|
|
if (mode_from_sid)
|
|
nsecdesclen +=
|
|
- le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct cifs_ace);
|
|
+ le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);
|
|
else /* cifsacl */
|
|
nsecdesclen += le16_to_cpu(dacl_ptr->size);
|
|
}
|
|
@@ -1657,7 +1667,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
|
}
|
|
|
|
rc = build_sec_desc(pntsd, pnntsd, secdesclen, &nsecdesclen, pnmode, uid, gid,
|
|
- mode_from_sid, id_from_sid, &aclflag);
|
|
+ mode_from_sid, id_from_sid, posix, &aclflag);
|
|
|
|
cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
|
|
|
|
diff --git a/fs/smb/client/cifsacl.h b/fs/smb/client/cifsacl.h
|
|
index ccbfc754bd3c7f..cbaed8038e3654 100644
|
|
--- a/fs/smb/client/cifsacl.h
|
|
+++ b/fs/smb/client/cifsacl.h
|
|
@@ -33,9 +33,9 @@
|
|
* Security Descriptor length containing DACL with 3 ACEs (one each for
|
|
* owner, group and world).
|
|
*/
|
|
-#define DEFAULT_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + \
|
|
- sizeof(struct cifs_acl) + \
|
|
- (sizeof(struct cifs_ace) * 4))
|
|
+#define DEFAULT_SEC_DESC_LEN (sizeof(struct smb_ntsd) + \
|
|
+ sizeof(struct smb_acl) + \
|
|
+ (sizeof(struct smb_ace) * 4))
|
|
|
|
/*
|
|
* Maximum size of a string representation of a SID:
|
|
@@ -55,7 +55,7 @@
|
|
#define SID_STRING_BASE_SIZE (2 + 3 + 15 + 1)
|
|
#define SID_STRING_SUBAUTH_SIZE (11) /* size of a single subauth string */
|
|
|
|
-struct cifs_ntsd {
|
|
+struct smb_ntsd {
|
|
__le16 revision; /* revision level */
|
|
__le16 type;
|
|
__le32 osidoffset;
|
|
@@ -64,17 +64,17 @@ struct cifs_ntsd {
|
|
__le32 dacloffset;
|
|
} __attribute__((packed));
|
|
|
|
-struct cifs_sid {
|
|
+struct smb_sid {
|
|
__u8 revision; /* revision level */
|
|
__u8 num_subauth;
|
|
__u8 authority[NUM_AUTHS];
|
|
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
|
|
} __attribute__((packed));
|
|
|
|
-/* size of a struct cifs_sid, sans sub_auth array */
|
|
+/* size of a struct smb_sid, sans sub_auth array */
|
|
#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
|
|
|
|
-struct cifs_acl {
|
|
+struct smb_acl {
|
|
__le16 revision; /* revision level */
|
|
__le16 size;
|
|
__le32 num_aces;
|
|
@@ -111,12 +111,12 @@ struct cifs_acl {
|
|
#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
|
|
#define FAILED_ACCESS_ACE_FLAG 0x80
|
|
|
|
-struct cifs_ace {
|
|
+struct smb_ace {
|
|
__u8 type; /* see above and MS-DTYP 2.4.4.1 */
|
|
__u8 flags;
|
|
__le16 size;
|
|
__le32 access_req;
|
|
- struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
|
|
+ struct smb_sid sid; /* ie UUID of user or group who gets these perms */
|
|
} __attribute__((packed));
|
|
|
|
/*
|
|
@@ -194,6 +194,6 @@ struct owner_group_sids {
|
|
* Minimum security descriptor can be one without any SACL and DACL and can
|
|
* consist of revision, type, and two sids of minimum size for owner and group
|
|
*/
|
|
-#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
|
|
+#define MIN_SEC_DESC_LEN (sizeof(struct smb_ntsd) + (2 * MIN_SID_LEN))
|
|
|
|
#endif /* _CIFSACL_H */
|
|
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
|
|
index 6ed0f2548232f9..bbb0ef18d7b8c8 100644
|
|
--- a/fs/smb/client/cifsfs.c
|
|
+++ b/fs/smb/client/cifsfs.c
|
|
@@ -2015,6 +2015,7 @@ exit_cifs(void)
|
|
destroy_workqueue(decrypt_wq);
|
|
destroy_workqueue(fileinfo_put_wq);
|
|
destroy_workqueue(serverclose_wq);
|
|
+ destroy_workqueue(cfid_put_wq);
|
|
destroy_workqueue(cifsiod_wq);
|
|
cifs_proc_clean();
|
|
}
|
|
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
|
|
index 6b57b167a49d80..43b42eca6780cf 100644
|
|
--- a/fs/smb/client/cifsglob.h
|
|
+++ b/fs/smb/client/cifsglob.h
|
|
@@ -202,10 +202,10 @@ struct cifs_cred {
|
|
int gid;
|
|
int mode;
|
|
int cecount;
|
|
- struct cifs_sid osid;
|
|
- struct cifs_sid gsid;
|
|
+ struct smb_sid osid;
|
|
+ struct smb_sid gsid;
|
|
struct cifs_ntace *ntaces;
|
|
- struct cifs_ace *aces;
|
|
+ struct smb_ace *aces;
|
|
};
|
|
|
|
struct cifs_open_info_data {
|
|
@@ -231,8 +231,8 @@ struct cifs_open_info_data {
|
|
unsigned int eas_len;
|
|
} wsl;
|
|
char *symlink_target;
|
|
- struct cifs_sid posix_owner;
|
|
- struct cifs_sid posix_group;
|
|
+ struct smb_sid posix_owner;
|
|
+ struct smb_sid posix_group;
|
|
union {
|
|
struct smb2_file_all_info fi;
|
|
struct smb311_posix_qinfo posix_fi;
|
|
@@ -539,12 +539,12 @@ struct smb_version_operations {
|
|
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
|
|
const char *, const void *, const __u16,
|
|
const struct nls_table *, struct cifs_sb_info *);
|
|
- struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
|
|
- const char *, u32 *, u32);
|
|
- struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
|
|
- const struct cifs_fid *, u32 *, u32);
|
|
- int (*set_acl)(struct cifs_ntsd *, __u32, struct inode *, const char *,
|
|
- int);
|
|
+ struct smb_ntsd * (*get_acl)(struct cifs_sb_info *cifssb, struct inode *ino,
|
|
+ const char *patch, u32 *plen, u32 info);
|
|
+ struct smb_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *cifssmb,
|
|
+ const struct cifs_fid *pfid, u32 *plen, u32 info);
|
|
+ int (*set_acl)(struct smb_ntsd *pntsd, __u32 len, struct inode *ino, const char *path,
|
|
+ int flag);
|
|
/* writepages retry size */
|
|
unsigned int (*wp_retry_size)(struct inode *);
|
|
/* get mtu credits */
|
|
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
|
|
index 83692bf60007a0..a151ffffc6f38e 100644
|
|
--- a/fs/smb/client/cifsproto.h
|
|
+++ b/fs/smb/client/cifsproto.h
|
|
@@ -223,7 +223,7 @@ extern int cifs_set_file_info(struct inode *inode, struct iattr *attrs,
|
|
extern int cifs_rename_pending_delete(const char *full_path,
|
|
struct dentry *dentry,
|
|
const unsigned int xid);
|
|
-extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
|
|
+extern int sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
|
|
struct cifs_fattr *fattr, uint sidtype);
|
|
extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
|
struct cifs_fattr *fattr, struct inode *inode,
|
|
@@ -231,19 +231,21 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
|
|
const char *path, const struct cifs_fid *pfid);
|
|
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
|
kuid_t uid, kgid_t gid);
|
|
-extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
|
|
- const char *, u32 *, u32);
|
|
-extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
|
|
- const struct cifs_fid *, u32 *, u32);
|
|
+extern struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifssmb, struct inode *ino,
|
|
+ const char *path, u32 *plen, u32 info);
|
|
+extern struct smb_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifssb,
|
|
+ const struct cifs_fid *pfid, u32 *plen, u32 info);
|
|
extern struct posix_acl *cifs_get_acl(struct mnt_idmap *idmap,
|
|
struct dentry *dentry, int type);
|
|
extern int cifs_set_acl(struct mnt_idmap *idmap,
|
|
struct dentry *dentry, struct posix_acl *acl, int type);
|
|
-extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
|
|
- const char *, int);
|
|
-extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
|
|
-extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
|
|
-extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);
|
|
+extern int set_cifs_acl(struct smb_ntsd *pntsd, __u32 len, struct inode *ino,
|
|
+ const char *path, int flag);
|
|
+extern unsigned int setup_authusers_ACE(struct smb_ace *pace);
|
|
+extern unsigned int setup_special_mode_ACE(struct smb_ace *pace,
|
|
+ bool posix,
|
|
+ __u64 nmode);
|
|
+extern unsigned int setup_special_user_owner_ACE(struct smb_ace *pace);
|
|
|
|
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
|
|
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
|
|
@@ -568,9 +570,9 @@ extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
|
|
const struct nls_table *nls_codepage,
|
|
struct cifs_sb_info *cifs_sb);
|
|
extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
|
|
- __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
|
|
+ __u16 fid, struct smb_ntsd **acl_inf, __u32 *buflen);
|
|
extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
|
|
- struct cifs_ntsd *, __u32, int);
|
|
+ struct smb_ntsd *pntsd, __u32 len, int aclflag);
|
|
extern int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
|
const unsigned char *searchName,
|
|
struct posix_acl **acl, const int acl_type,
|
|
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
|
|
index a34db419e46f7f..2f8745736dbb02 100644
|
|
--- a/fs/smb/client/cifssmb.c
|
|
+++ b/fs/smb/client/cifssmb.c
|
|
@@ -3385,7 +3385,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
|
|
/* Get Security Descriptor (by handle) from remote server for a file or dir */
|
|
int
|
|
CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
|
|
- struct cifs_ntsd **acl_inf, __u32 *pbuflen)
|
|
+ struct smb_ntsd **acl_inf, __u32 *pbuflen)
|
|
{
|
|
int rc = 0;
|
|
int buf_type = 0;
|
|
@@ -3455,7 +3455,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
|
|
|
|
/* check if buffer is big enough for the acl
|
|
header followed by the smallest SID */
|
|
- if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
|
|
+ if ((*pbuflen < sizeof(struct smb_ntsd) + 8) ||
|
|
(*pbuflen >= 64 * 1024)) {
|
|
cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
|
|
rc = -EINVAL;
|
|
@@ -3475,7 +3475,7 @@ CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
|
|
|
|
int
|
|
CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
|
|
- struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
|
|
+ struct smb_ntsd *pntsd, __u32 acllen, int aclflag)
|
|
{
|
|
__u16 byte_count, param_count, data_count, param_offset, data_offset;
|
|
int rc = 0;
|
|
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
|
|
index ce7e0aed8f7d2b..b3e59a7c71205f 100644
|
|
--- a/fs/smb/client/inode.c
|
|
+++ b/fs/smb/client/inode.c
|
|
@@ -3087,6 +3087,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
|
int rc = -EACCES;
|
|
__u32 dosattr = 0;
|
|
__u64 mode = NO_CHANGE_64;
|
|
+ bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions;
|
|
|
|
xid = get_xid();
|
|
|
|
@@ -3177,7 +3178,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
|
mode = attrs->ia_mode;
|
|
rc = 0;
|
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
|
|
- (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
|
|
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) ||
|
|
+ posix) {
|
|
rc = id_mode_to_cifs_acl(inode, full_path, &mode,
|
|
INVALID_UID, INVALID_GID);
|
|
if (rc) {
|
|
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
|
|
index 2a292736c89a2a..e695df1dbb23b2 100644
|
|
--- a/fs/smb/client/smb2inode.c
|
|
+++ b/fs/smb/client/smb2inode.c
|
|
@@ -315,7 +315,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
|
SMB2_O_INFO_FILE, 0,
|
|
sizeof(struct smb311_posix_qinfo *) +
|
|
(PATH_MAX * 2) +
|
|
- (sizeof(struct cifs_sid) * 2), 0, NULL);
|
|
+ (sizeof(struct smb_sid) * 2), 0, NULL);
|
|
} else {
|
|
rc = SMB2_query_info_init(tcon, server,
|
|
&rqst[num_rqst],
|
|
@@ -325,7 +325,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
|
SMB2_O_INFO_FILE, 0,
|
|
sizeof(struct smb311_posix_qinfo *) +
|
|
(PATH_MAX * 2) +
|
|
- (sizeof(struct cifs_sid) * 2), 0, NULL);
|
|
+ (sizeof(struct smb_sid) * 2), 0, NULL);
|
|
}
|
|
if (!rc && (!cfile || num_rqst > 1)) {
|
|
smb2_set_next_command(tcon, &rqst[num_rqst]);
|
|
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
|
|
index 6645f147d57c29..fc6d00344c50ea 100644
|
|
--- a/fs/smb/client/smb2ops.c
|
|
+++ b/fs/smb/client/smb2ops.c
|
|
@@ -3001,11 +3001,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
|
|
return rc;
|
|
}
|
|
|
|
-static struct cifs_ntsd *
|
|
+static struct smb_ntsd *
|
|
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
|
const struct cifs_fid *cifsfid, u32 *pacllen, u32 info)
|
|
{
|
|
- struct cifs_ntsd *pntsd = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL;
|
|
unsigned int xid;
|
|
int rc = -EOPNOTSUPP;
|
|
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
|
|
@@ -3030,11 +3030,11 @@ get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
|
|
|
|
}
|
|
|
|
-static struct cifs_ntsd *
|
|
+static struct smb_ntsd *
|
|
get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|
const char *path, u32 *pacllen, u32 info)
|
|
{
|
|
- struct cifs_ntsd *pntsd = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL;
|
|
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
|
unsigned int xid;
|
|
int rc;
|
|
@@ -3097,7 +3097,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
|
|
}
|
|
|
|
static int
|
|
-set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
|
+set_smb2_acl(struct smb_ntsd *pnntsd, __u32 acllen,
|
|
struct inode *inode, const char *path, int aclflag)
|
|
{
|
|
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
|
@@ -3155,12 +3155,12 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
|
}
|
|
|
|
/* Retrieve an ACL from the server */
|
|
-static struct cifs_ntsd *
|
|
+static struct smb_ntsd *
|
|
get_smb2_acl(struct cifs_sb_info *cifs_sb,
|
|
struct inode *inode, const char *path,
|
|
u32 *pacllen, u32 info)
|
|
{
|
|
- struct cifs_ntsd *pntsd = NULL;
|
|
+ struct smb_ntsd *pntsd = NULL;
|
|
struct cifsFileInfo *open_file = NULL;
|
|
|
|
if (inode && !(info & SACL_SECINFO))
|
|
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
|
|
index 38b26468eb0c53..c012fbc2638ed5 100644
|
|
--- a/fs/smb/client/smb2pdu.c
|
|
+++ b/fs/smb/client/smb2pdu.c
|
|
@@ -2623,7 +2623,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
|
|
unsigned int group_offset = 0;
|
|
struct smb3_acl acl = {};
|
|
|
|
- *len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 4), 8);
|
|
+ *len = round_up(sizeof(struct crt_sd_ctxt) + (sizeof(struct smb_ace) * 4), 8);
|
|
|
|
if (set_owner) {
|
|
/* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
|
|
@@ -2672,21 +2672,21 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
|
|
ptr += sizeof(struct smb3_acl);
|
|
|
|
/* create one ACE to hold the mode embedded in reserved special SID */
|
|
- acelen = setup_special_mode_ACE((struct cifs_ace *)ptr, (__u64)mode);
|
|
+ acelen = setup_special_mode_ACE((struct smb_ace *)ptr, false, (__u64)mode);
|
|
ptr += acelen;
|
|
acl_size = acelen + sizeof(struct smb3_acl);
|
|
ace_count = 1;
|
|
|
|
if (set_owner) {
|
|
/* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
|
|
- acelen = setup_special_user_owner_ACE((struct cifs_ace *)ptr);
|
|
+ acelen = setup_special_user_owner_ACE((struct smb_ace *)ptr);
|
|
ptr += acelen;
|
|
acl_size += acelen;
|
|
ace_count += 1;
|
|
}
|
|
|
|
/* and one more ACE to allow access for authenticated users */
|
|
- acelen = setup_authusers_ACE((struct cifs_ace *)ptr);
|
|
+ acelen = setup_authusers_ACE((struct smb_ace *)ptr);
|
|
ptr += acelen;
|
|
acl_size += acelen;
|
|
ace_count += 1;
|
|
@@ -3915,7 +3915,7 @@ SMB311_posix_query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
u64 persistent_fid, u64 volatile_fid, struct smb311_posix_qinfo *data, u32 *plen)
|
|
{
|
|
size_t output_len = sizeof(struct smb311_posix_qinfo *) +
|
|
- (sizeof(struct cifs_sid) * 2) + (PATH_MAX * 2);
|
|
+ (sizeof(struct smb_sid) * 2) + (PATH_MAX * 2);
|
|
*plen = 0;
|
|
|
|
return query_info(xid, tcon, persistent_fid, volatile_fid,
|
|
@@ -5626,7 +5626,7 @@ SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
int
|
|
SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
|
u64 persistent_fid, u64 volatile_fid,
|
|
- struct cifs_ntsd *pnntsd, int pacllen, int aclflag)
|
|
+ struct smb_ntsd *pnntsd, int pacllen, int aclflag)
|
|
{
|
|
return send_set_info(xid, tcon, persistent_fid, volatile_fid,
|
|
current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag,
|
|
diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h
|
|
index 5c458ab3b05a44..076d9e83e1a044 100644
|
|
--- a/fs/smb/client/smb2pdu.h
|
|
+++ b/fs/smb/client/smb2pdu.h
|
|
@@ -364,8 +364,8 @@ struct create_posix_rsp {
|
|
u32 nlink;
|
|
u32 reparse_tag;
|
|
u32 mode;
|
|
- struct cifs_sid owner; /* var-sized on the wire */
|
|
- struct cifs_sid group; /* var-sized on the wire */
|
|
+ struct smb_sid owner; /* var-sized on the wire */
|
|
+ struct smb_sid group; /* var-sized on the wire */
|
|
} __packed;
|
|
|
|
#define SMB2_QUERY_DIRECTORY_IOV_SIZE 2
|
|
@@ -408,8 +408,8 @@ struct smb2_posix_info {
|
|
struct smb2_posix_info_parsed {
|
|
const struct smb2_posix_info *base;
|
|
size_t size;
|
|
- struct cifs_sid owner;
|
|
- struct cifs_sid group;
|
|
+ struct smb_sid owner;
|
|
+ struct smb_sid group;
|
|
int name_len;
|
|
const u8 *name;
|
|
};
|
|
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
|
|
index 613667b46c5802..750e4e397b1393 100644
|
|
--- a/fs/smb/client/smb2proto.h
|
|
+++ b/fs/smb/client/smb2proto.h
|
|
@@ -37,8 +37,6 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
|
|
struct smb_rqst *rqst);
|
|
extern struct mid_q_entry *smb2_setup_async_request(
|
|
struct TCP_Server_Info *server, struct smb_rqst *rqst);
|
|
-extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
|
|
- __u64 ses_id);
|
|
extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
|
|
__u64 ses_id, __u32 tid);
|
|
extern int smb2_calc_signature(struct smb_rqst *rqst,
|
|
@@ -247,7 +245,7 @@ extern int SMB2_set_info_init(struct cifs_tcon *tcon,
|
|
extern void SMB2_set_info_free(struct smb_rqst *rqst);
|
|
extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
|
u64 persistent_fid, u64 volatile_fid,
|
|
- struct cifs_ntsd *pnntsd, int pacllen, int aclflag);
|
|
+ struct smb_ntsd *pnntsd, int pacllen, int aclflag);
|
|
extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
|
|
u64 persistent_fid, u64 volatile_fid,
|
|
struct smb2_file_full_ea_info *buf, int len);
|
|
diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
|
|
index 4ca04e62a993cf..4a43802375b3a3 100644
|
|
--- a/fs/smb/client/smb2transport.c
|
|
+++ b/fs/smb/client/smb2transport.c
|
|
@@ -74,7 +74,7 @@ smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
|
|
|
|
|
|
static
|
|
-int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
|
|
+int smb3_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
|
|
{
|
|
struct cifs_chan *chan;
|
|
struct TCP_Server_Info *pserver;
|
|
@@ -168,16 +168,41 @@ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
|
|
return NULL;
|
|
}
|
|
|
|
-struct cifs_ses *
|
|
-smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
|
|
+static int smb2_get_sign_key(struct TCP_Server_Info *server,
|
|
+ __u64 ses_id, u8 *key)
|
|
{
|
|
struct cifs_ses *ses;
|
|
+ int rc = -ENOENT;
|
|
+
|
|
+ if (SERVER_IS_CHAN(server))
|
|
+ server = server->primary_server;
|
|
|
|
spin_lock(&cifs_tcp_ses_lock);
|
|
- ses = smb2_find_smb_ses_unlocked(server, ses_id);
|
|
- spin_unlock(&cifs_tcp_ses_lock);
|
|
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
|
+ if (ses->Suid != ses_id)
|
|
+ continue;
|
|
|
|
- return ses;
|
|
+ rc = 0;
|
|
+ spin_lock(&ses->ses_lock);
|
|
+ switch (ses->ses_status) {
|
|
+ case SES_EXITING: /* SMB2_LOGOFF */
|
|
+ case SES_GOOD:
|
|
+ if (likely(ses->auth_key.response)) {
|
|
+ memcpy(key, ses->auth_key.response,
|
|
+ SMB2_NTLMV2_SESSKEY_SIZE);
|
|
+ } else {
|
|
+ rc = -EIO;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ rc = -EAGAIN;
|
|
+ break;
|
|
+ }
|
|
+ spin_unlock(&ses->ses_lock);
|
|
+ break;
|
|
+ }
|
|
+ spin_unlock(&cifs_tcp_ses_lock);
|
|
+ return rc;
|
|
}
|
|
|
|
static struct cifs_tcon *
|
|
@@ -236,14 +261,16 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
|
unsigned char *sigptr = smb2_signature;
|
|
struct kvec *iov = rqst->rq_iov;
|
|
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
|
|
- struct cifs_ses *ses;
|
|
struct shash_desc *shash = NULL;
|
|
struct smb_rqst drqst;
|
|
+ __u64 sid = le64_to_cpu(shdr->SessionId);
|
|
+ u8 key[SMB2_NTLMV2_SESSKEY_SIZE];
|
|
|
|
- ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));
|
|
- if (unlikely(!ses)) {
|
|
- cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
|
|
- return -ENOENT;
|
|
+ rc = smb2_get_sign_key(server, sid, key);
|
|
+ if (unlikely(rc)) {
|
|
+ cifs_server_dbg(FYI, "%s: [sesid=0x%llx] couldn't find signing key: %d\n",
|
|
+ __func__, sid, rc);
|
|
+ return rc;
|
|
}
|
|
|
|
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
|
|
@@ -260,8 +287,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
|
shash = server->secmech.hmacsha256;
|
|
}
|
|
|
|
- rc = crypto_shash_setkey(shash->tfm, ses->auth_key.response,
|
|
- SMB2_NTLMV2_SESSKEY_SIZE);
|
|
+ rc = crypto_shash_setkey(shash->tfm, key, sizeof(key));
|
|
if (rc) {
|
|
cifs_server_dbg(VFS,
|
|
"%s: Could not update with response\n",
|
|
@@ -303,8 +329,6 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
|
out:
|
|
if (allocate_crypto)
|
|
cifs_free_hash(&shash);
|
|
- if (ses)
|
|
- cifs_put_smb_ses(ses);
|
|
return rc;
|
|
}
|
|
|
|
@@ -570,7 +594,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
|
struct smb_rqst drqst;
|
|
u8 key[SMB3_SIGN_KEY_SIZE];
|
|
|
|
- rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);
|
|
+ rc = smb3_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);
|
|
if (unlikely(rc)) {
|
|
cifs_server_dbg(FYI, "%s: Could not get signing key\n", __func__);
|
|
return rc;
|
|
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c
|
|
index c2bf829310bee2..e8696ad4da994e 100644
|
|
--- a/fs/smb/client/xattr.c
|
|
+++ b/fs/smb/client/xattr.c
|
|
@@ -162,7 +162,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
|
case XATTR_CIFS_ACL:
|
|
case XATTR_CIFS_NTSD:
|
|
case XATTR_CIFS_NTSD_FULL: {
|
|
- struct cifs_ntsd *pacl;
|
|
+ struct smb_ntsd *pacl;
|
|
|
|
if (!value)
|
|
goto out;
|
|
@@ -315,7 +315,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
|
|
* fetch owner and DACL otherwise
|
|
*/
|
|
u32 acllen, extra_info;
|
|
- struct cifs_ntsd *pacl;
|
|
+ struct smb_ntsd *pacl;
|
|
|
|
if (pTcon->ses->server->ops->get_acl == NULL)
|
|
goto out; /* rc already EOPNOTSUPP */
|
|
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
|
|
index cd530b9a00caa3..2884ebdc0eda02 100644
|
|
--- a/fs/smb/server/smb2pdu.c
|
|
+++ b/fs/smb/server/smb2pdu.c
|
|
@@ -4225,6 +4225,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
|
|
/* dot and dotdot entries are already reserved */
|
|
if (!strcmp(".", name) || !strcmp("..", name))
|
|
return true;
|
|
+ d_info->num_scan++;
|
|
if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
|
|
return true;
|
|
if (!match_pattern(name, namlen, priv->search_pattern))
|
|
@@ -4385,8 +4386,17 @@ int smb2_query_dir(struct ksmbd_work *work)
|
|
query_dir_private.info_level = req->FileInformationClass;
|
|
dir_fp->readdir_data.private = &query_dir_private;
|
|
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
|
|
-
|
|
+again:
|
|
+ d_info.num_scan = 0;
|
|
rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
|
|
+ /*
|
|
+ * num_entry can be 0 if the directory iteration stops before reaching
|
|
+ * the end of the directory and no file is matched with the search
|
|
+ * pattern.
|
|
+ */
|
|
+ if (rc >= 0 && !d_info.num_entry && d_info.num_scan &&
|
|
+ d_info.out_buf_len > 0)
|
|
+ goto again;
|
|
/*
|
|
* req->OutputBufferLength is too small to contain even one entry.
|
|
* In this case, it immediately returns OutputBufferLength 0 to client.
|
|
@@ -6007,15 +6017,13 @@ static int set_file_basic_info(struct ksmbd_file *fp,
|
|
attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
|
|
}
|
|
|
|
- attrs.ia_valid |= ATTR_CTIME;
|
|
if (file_info->ChangeTime)
|
|
- attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
|
|
- else
|
|
- attrs.ia_ctime = inode_get_ctime(inode);
|
|
+ inode_set_ctime_to_ts(inode,
|
|
+ ksmbd_NTtimeToUnix(file_info->ChangeTime));
|
|
|
|
if (file_info->LastWriteTime) {
|
|
attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
|
|
- attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
|
|
+ attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME);
|
|
}
|
|
|
|
if (file_info->Attributes) {
|
|
@@ -6057,8 +6065,6 @@ static int set_file_basic_info(struct ksmbd_file *fp,
|
|
return -EACCES;
|
|
|
|
inode_lock(inode);
|
|
- inode_set_ctime_to_ts(inode, attrs.ia_ctime);
|
|
- attrs.ia_valid &= ~ATTR_CTIME;
|
|
rc = notify_change(idmap, dentry, &attrs, NULL);
|
|
inode_unlock(inode);
|
|
}
|
|
diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h
|
|
index cb76f4b5bafe8c..06903024a2d88b 100644
|
|
--- a/fs/smb/server/vfs.h
|
|
+++ b/fs/smb/server/vfs.h
|
|
@@ -43,6 +43,7 @@ struct ksmbd_dir_info {
|
|
char *rptr;
|
|
int name_len;
|
|
int out_buf_len;
|
|
+ int num_scan;
|
|
int num_entry;
|
|
int data_count;
|
|
int last_entry_offset;
|
|
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
|
|
index b3f57ad2b869ff..8ac73f41d6ebe6 100644
|
|
--- a/fs/udf/namei.c
|
|
+++ b/fs/udf/namei.c
|
|
@@ -770,7 +770,7 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
|
struct inode *old_inode = d_inode(old_dentry);
|
|
struct inode *new_inode = d_inode(new_dentry);
|
|
struct udf_fileident_iter oiter, niter, diriter;
|
|
- bool has_diriter = false;
|
|
+ bool has_diriter = false, is_dir = false;
|
|
int retval;
|
|
struct kernel_lb_addr tloc;
|
|
|
|
@@ -792,7 +792,20 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
|
retval = -ENOTEMPTY;
|
|
if (!empty_dir(new_inode))
|
|
goto out_oiter;
|
|
+ retval = -EFSCORRUPTED;
|
|
+ if (new_inode->i_nlink != 2)
|
|
+ goto out_oiter;
|
|
}
|
|
+ retval = -EFSCORRUPTED;
|
|
+ if (old_dir->i_nlink < 3)
|
|
+ goto out_oiter;
|
|
+ is_dir = true;
|
|
+ } else if (new_inode) {
|
|
+ retval = -EFSCORRUPTED;
|
|
+ if (new_inode->i_nlink < 1)
|
|
+ goto out_oiter;
|
|
+ }
|
|
+ if (is_dir && old_dir != new_dir) {
|
|
retval = udf_fiiter_find_entry(old_inode, &dotdot_name,
|
|
&diriter);
|
|
if (retval == -ENOENT) {
|
|
@@ -880,7 +893,9 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
|
cpu_to_lelb(UDF_I(new_dir)->i_location);
|
|
udf_fiiter_write_fi(&diriter, NULL);
|
|
udf_fiiter_release(&diriter);
|
|
+ }
|
|
|
|
+ if (is_dir) {
|
|
inode_dec_link_count(old_dir);
|
|
if (new_inode)
|
|
inode_dec_link_count(new_inode);
|
|
diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h
|
|
index 73e806fe7ce707..699c1a37b8e784 100644
|
|
--- a/include/acpi/pcc.h
|
|
+++ b/include/acpi/pcc.h
|
|
@@ -12,17 +12,33 @@
|
|
struct pcc_mbox_chan {
|
|
struct mbox_chan *mchan;
|
|
u64 shmem_base_addr;
|
|
+ void __iomem *shmem;
|
|
u64 shmem_size;
|
|
u32 latency;
|
|
u32 max_access_rate;
|
|
u16 min_turnaround_time;
|
|
};
|
|
|
|
+/* Generic Communications Channel Shared Memory Region */
|
|
+#define PCC_SIGNATURE 0x50434300
|
|
+/* Generic Communications Channel Command Field */
|
|
+#define PCC_CMD_GENERATE_DB_INTR BIT(15)
|
|
+/* Generic Communications Channel Status Field */
|
|
+#define PCC_STATUS_CMD_COMPLETE BIT(0)
|
|
+#define PCC_STATUS_SCI_DOORBELL BIT(1)
|
|
+#define PCC_STATUS_ERROR BIT(2)
|
|
+#define PCC_STATUS_PLATFORM_NOTIFY BIT(3)
|
|
+/* Initiator Responder Communications Channel Flags */
|
|
+#define PCC_CMD_COMPLETION_NOTIFY BIT(0)
|
|
+
|
|
#define MAX_PCC_SUBSPACES 256
|
|
+#define PCC_ACK_FLAG_MASK 0x1
|
|
+
|
|
#ifdef CONFIG_PCC
|
|
extern struct pcc_mbox_chan *
|
|
pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id);
|
|
extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan);
|
|
+extern int pcc_mbox_ioremap(struct mbox_chan *chan);
|
|
#else
|
|
static inline struct pcc_mbox_chan *
|
|
pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
|
|
@@ -30,6 +46,10 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { }
|
|
+static inline int pcc_mbox_ioremap(struct mbox_chan *chan)
|
|
+{
|
|
+ return 0;
|
|
+};
|
|
#endif
|
|
|
|
#endif /* _PCC_H */
|
|
diff --git a/include/clocksource/hyperv_timer.h b/include/clocksource/hyperv_timer.h
|
|
index 6cdc873ac907f5..aa5233b1eba970 100644
|
|
--- a/include/clocksource/hyperv_timer.h
|
|
+++ b/include/clocksource/hyperv_timer.h
|
|
@@ -38,6 +38,8 @@ extern void hv_remap_tsc_clocksource(void);
|
|
extern unsigned long hv_get_tsc_pfn(void);
|
|
extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void);
|
|
|
|
+extern void hv_adj_sched_clock_offset(u64 offset);
|
|
+
|
|
static __always_inline bool
|
|
hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg,
|
|
u64 *cur_tsc, u64 *time)
|
|
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
|
|
index 4f6c1a68882fa1..c0b8be63cbde7c 100644
|
|
--- a/include/crypto/internal/ecc.h
|
|
+++ b/include/crypto/internal/ecc.h
|
|
@@ -56,6 +56,16 @@ static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigit
|
|
out[i] = get_unaligned_be64(&src[ndigits - 1 - i]);
|
|
}
|
|
|
|
+/**
|
|
+ * ecc_digits_from_bytes() - Create ndigits-sized digits array from byte array
|
|
+ * @in: Input byte array
|
|
+ * @nbytes Size of input byte array
|
|
+ * @out Output digits array
|
|
+ * @ndigits: Number of digits to create from byte array
|
|
+ */
|
|
+void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
|
|
+ u64 *out, unsigned int ndigits);
|
|
+
|
|
/**
|
|
* ecc_is_key_valid() - Validate a given ECDH private key
|
|
*
|
|
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
|
|
index cb8e97665eaa59..92919d52f7e1b2 100644
|
|
--- a/include/linux/bpf_verifier.h
|
|
+++ b/include/linux/bpf_verifier.h
|
|
@@ -319,34 +319,12 @@ struct bpf_func_state {
|
|
struct bpf_stack_state *stack;
|
|
};
|
|
|
|
-#define MAX_CALL_FRAMES 8
|
|
-
|
|
-/* instruction history flags, used in bpf_jmp_history_entry.flags field */
|
|
-enum {
|
|
- /* instruction references stack slot through PTR_TO_STACK register;
|
|
- * we also store stack's frame number in lower 3 bits (MAX_CALL_FRAMES is 8)
|
|
- * and accessed stack slot's index in next 6 bits (MAX_BPF_STACK is 512,
|
|
- * 8 bytes per slot, so slot index (spi) is [0, 63])
|
|
- */
|
|
- INSN_F_FRAMENO_MASK = 0x7, /* 3 bits */
|
|
-
|
|
- INSN_F_SPI_MASK = 0x3f, /* 6 bits */
|
|
- INSN_F_SPI_SHIFT = 3, /* shifted 3 bits to the left */
|
|
-
|
|
- INSN_F_STACK_ACCESS = BIT(9), /* we need 10 bits total */
|
|
-};
|
|
-
|
|
-static_assert(INSN_F_FRAMENO_MASK + 1 >= MAX_CALL_FRAMES);
|
|
-static_assert(INSN_F_SPI_MASK + 1 >= MAX_BPF_STACK / 8);
|
|
-
|
|
-struct bpf_jmp_history_entry {
|
|
+struct bpf_idx_pair {
|
|
+ u32 prev_idx;
|
|
u32 idx;
|
|
- /* insn idx can't be bigger than 1 million */
|
|
- u32 prev_idx : 22;
|
|
- /* special flags, e.g., whether insn is doing register stack spill/load */
|
|
- u32 flags : 10;
|
|
};
|
|
|
|
+#define MAX_CALL_FRAMES 8
|
|
/* Maximum number of register states that can exist at once */
|
|
#define BPF_ID_MAP_SIZE ((MAX_BPF_REG + MAX_BPF_STACK / BPF_REG_SIZE) * MAX_CALL_FRAMES)
|
|
struct bpf_verifier_state {
|
|
@@ -429,7 +407,7 @@ struct bpf_verifier_state {
|
|
* For most states jmp_history_cnt is [0-3].
|
|
* For loops can go up to ~40.
|
|
*/
|
|
- struct bpf_jmp_history_entry *jmp_history;
|
|
+ struct bpf_idx_pair *jmp_history;
|
|
u32 jmp_history_cnt;
|
|
u32 dfs_depth;
|
|
u32 callback_unroll_depth;
|
|
@@ -662,7 +640,6 @@ struct bpf_verifier_env {
|
|
int cur_stack;
|
|
} cfg;
|
|
struct backtrack_state bt;
|
|
- struct bpf_jmp_history_entry *cur_hist_ent;
|
|
u32 pass_cnt; /* number of times do_check() was called */
|
|
u32 subprog_cnt;
|
|
/* number of instructions analyzed by the verifier */
|
|
diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h
|
|
index 53f1a7a932b08c..64b8600eb8c0e4 100644
|
|
--- a/include/linux/cleanup.h
|
|
+++ b/include/linux/cleanup.h
|
|
@@ -92,26 +92,85 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
|
|
* trivial wrapper around DEFINE_CLASS() above specifically
|
|
* for locks.
|
|
*
|
|
+ * DEFINE_GUARD_COND(name, ext, condlock)
|
|
+ * wrapper around EXTEND_CLASS above to add conditional lock
|
|
+ * variants to a base class, eg. mutex_trylock() or
|
|
+ * mutex_lock_interruptible().
|
|
+ *
|
|
* guard(name):
|
|
- * an anonymous instance of the (guard) class
|
|
+ * an anonymous instance of the (guard) class, not recommended for
|
|
+ * conditional locks.
|
|
*
|
|
* scoped_guard (name, args...) { }:
|
|
* similar to CLASS(name, scope)(args), except the variable (with the
|
|
* explicit name 'scope') is declard in a for-loop such that its scope is
|
|
* bound to the next (compound) statement.
|
|
*
|
|
+ * for conditional locks the loop body is skipped when the lock is not
|
|
+ * acquired.
|
|
+ *
|
|
+ * scoped_cond_guard (name, fail, args...) { }:
|
|
+ * similar to scoped_guard(), except it does fail when the lock
|
|
+ * acquire fails.
|
|
+ *
|
|
+ * Only for conditional locks.
|
|
*/
|
|
|
|
+#define __DEFINE_CLASS_IS_CONDITIONAL(_name, _is_cond) \
|
|
+static __maybe_unused const bool class_##_name##_is_conditional = _is_cond
|
|
+
|
|
#define DEFINE_GUARD(_name, _type, _lock, _unlock) \
|
|
- DEFINE_CLASS(_name, _type, _unlock, ({ _lock; _T; }), _type _T)
|
|
+ __DEFINE_CLASS_IS_CONDITIONAL(_name, false); \
|
|
+ DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \
|
|
+ static inline void * class_##_name##_lock_ptr(class_##_name##_t *_T) \
|
|
+ { return (void *)(__force unsigned long)*_T; }
|
|
+
|
|
+#define DEFINE_GUARD_COND(_name, _ext, _condlock) \
|
|
+ __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \
|
|
+ EXTEND_CLASS(_name, _ext, \
|
|
+ ({ void *_t = _T; if (_T && !(_condlock)) _t = NULL; _t; }), \
|
|
+ class_##_name##_t _T) \
|
|
+ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
|
|
+ { return class_##_name##_lock_ptr(_T); }
|
|
|
|
#define guard(_name) \
|
|
CLASS(_name, __UNIQUE_ID(guard))
|
|
|
|
-#define scoped_guard(_name, args...) \
|
|
- for (CLASS(_name, scope)(args), \
|
|
- *done = NULL; !done; done = (void *)1)
|
|
+#define __guard_ptr(_name) class_##_name##_lock_ptr
|
|
+#define __is_cond_ptr(_name) class_##_name##_is_conditional
|
|
|
|
+/*
|
|
+ * Helper macro for scoped_guard().
|
|
+ *
|
|
+ * Note that the "!__is_cond_ptr(_name)" part of the condition ensures that
|
|
+ * compiler would be sure that for the unconditional locks the body of the
|
|
+ * loop (caller-provided code glued to the else clause) could not be skipped.
|
|
+ * It is needed because the other part - "__guard_ptr(_name)(&scope)" - is too
|
|
+ * hard to deduce (even if could be proven true for unconditional locks).
|
|
+ */
|
|
+#define __scoped_guard(_name, _label, args...) \
|
|
+ for (CLASS(_name, scope)(args); \
|
|
+ __guard_ptr(_name)(&scope) || !__is_cond_ptr(_name); \
|
|
+ ({ goto _label; })) \
|
|
+ if (0) { \
|
|
+_label: \
|
|
+ break; \
|
|
+ } else
|
|
+
|
|
+#define scoped_guard(_name, args...) \
|
|
+ __scoped_guard(_name, __UNIQUE_ID(label), args)
|
|
+
|
|
+#define __scoped_cond_guard(_name, _fail, _label, args...) \
|
|
+ for (CLASS(_name, scope)(args); true; ({ goto _label; })) \
|
|
+ if (!__guard_ptr(_name)(&scope)) { \
|
|
+ BUILD_BUG_ON(!__is_cond_ptr(_name)); \
|
|
+ _fail; \
|
|
+_label: \
|
|
+ break; \
|
|
+ } else
|
|
+
|
|
+#define scoped_cond_guard(_name, _fail, args...) \
|
|
+ __scoped_cond_guard(_name, _fail, __UNIQUE_ID(label), args)
|
|
/*
|
|
* Additional helper macros for generating lock guards with types, either for
|
|
* locks that don't have a native type (eg. RCU, preempt) or those that need a
|
|
@@ -119,6 +178,7 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
|
|
*
|
|
* DEFINE_LOCK_GUARD_0(name, lock, unlock, ...)
|
|
* DEFINE_LOCK_GUARD_1(name, type, lock, unlock, ...)
|
|
+ * DEFINE_LOCK_GUARD_1_COND(name, ext, condlock)
|
|
*
|
|
* will result in the following type:
|
|
*
|
|
@@ -140,6 +200,11 @@ typedef struct { \
|
|
static inline void class_##_name##_destructor(class_##_name##_t *_T) \
|
|
{ \
|
|
if (_T->lock) { _unlock; } \
|
|
+} \
|
|
+ \
|
|
+static inline void *class_##_name##_lock_ptr(class_##_name##_t *_T) \
|
|
+{ \
|
|
+ return (void *)(__force unsigned long)_T->lock; \
|
|
}
|
|
|
|
|
|
@@ -161,11 +226,24 @@ static inline class_##_name##_t class_##_name##_constructor(void) \
|
|
}
|
|
|
|
#define DEFINE_LOCK_GUARD_1(_name, _type, _lock, _unlock, ...) \
|
|
+__DEFINE_CLASS_IS_CONDITIONAL(_name, false); \
|
|
__DEFINE_UNLOCK_GUARD(_name, _type, _unlock, __VA_ARGS__) \
|
|
__DEFINE_LOCK_GUARD_1(_name, _type, _lock)
|
|
|
|
#define DEFINE_LOCK_GUARD_0(_name, _lock, _unlock, ...) \
|
|
+__DEFINE_CLASS_IS_CONDITIONAL(_name, false); \
|
|
__DEFINE_UNLOCK_GUARD(_name, void, _unlock, __VA_ARGS__) \
|
|
__DEFINE_LOCK_GUARD_0(_name, _lock)
|
|
|
|
+#define DEFINE_LOCK_GUARD_1_COND(_name, _ext, _condlock) \
|
|
+ __DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \
|
|
+ EXTEND_CLASS(_name, _ext, \
|
|
+ ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\
|
|
+ if (_T->lock && !(_condlock)) _T->lock = NULL; \
|
|
+ _t; }), \
|
|
+ typeof_member(class_##_name##_t, lock) l) \
|
|
+ static inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
|
|
+ { return class_##_name##_lock_ptr(_T); }
|
|
+
|
|
+
|
|
#endif /* __LINUX_GUARDS_H */
|
|
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
|
|
index 3028af87716e29..430749a0f362aa 100644
|
|
--- a/include/linux/if_vlan.h
|
|
+++ b/include/linux/if_vlan.h
|
|
@@ -585,13 +585,16 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
|
|
* vlan_get_protocol - get protocol EtherType.
|
|
* @skb: skbuff to query
|
|
* @type: first vlan protocol
|
|
+ * @mac_offset: MAC offset
|
|
* @depth: buffer to store length of eth and vlan tags in bytes
|
|
*
|
|
* Returns the EtherType of the packet, regardless of whether it is
|
|
* vlan encapsulated (normal or hardware accelerated) or not.
|
|
*/
|
|
-static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
|
|
- int *depth)
|
|
+static inline __be16 __vlan_get_protocol_offset(const struct sk_buff *skb,
|
|
+ __be16 type,
|
|
+ int mac_offset,
|
|
+ int *depth)
|
|
{
|
|
unsigned int vlan_depth = skb->mac_len, parse_depth = VLAN_MAX_DEPTH;
|
|
|
|
@@ -610,7 +613,8 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
|
|
do {
|
|
struct vlan_hdr vhdr, *vh;
|
|
|
|
- vh = skb_header_pointer(skb, vlan_depth, sizeof(vhdr), &vhdr);
|
|
+ vh = skb_header_pointer(skb, mac_offset + vlan_depth,
|
|
+ sizeof(vhdr), &vhdr);
|
|
if (unlikely(!vh || !--parse_depth))
|
|
return 0;
|
|
|
|
@@ -625,6 +629,12 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
|
|
return type;
|
|
}
|
|
|
|
+static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
|
|
+ int *depth)
|
|
+{
|
|
+ return __vlan_get_protocol_offset(skb, type, 0, depth);
|
|
+}
|
|
+
|
|
/**
|
|
* vlan_get_protocol - get protocol EtherType.
|
|
* @skb: skbuff to query
|
|
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
|
|
index ed57c23f80ac2b..ed64240041e857 100644
|
|
--- a/include/linux/memblock.h
|
|
+++ b/include/linux/memblock.h
|
|
@@ -122,6 +122,7 @@ unsigned long memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
|
|
phys_addr_t base2, phys_addr_t size2);
|
|
bool memblock_overlaps_region(struct memblock_type *type,
|
|
phys_addr_t base, phys_addr_t size);
|
|
+bool memblock_validate_numa_coverage(unsigned long threshold_bytes);
|
|
int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
|
|
int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
|
|
int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
|
|
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
|
|
index ffb98bc43b2db2..38a8ff9c685cb8 100644
|
|
--- a/include/linux/mlx5/driver.h
|
|
+++ b/include/linux/mlx5/driver.h
|
|
@@ -1225,6 +1225,12 @@ static inline bool mlx5_core_is_vf(const struct mlx5_core_dev *dev)
|
|
return dev->coredev_type == MLX5_COREDEV_VF;
|
|
}
|
|
|
|
+static inline bool mlx5_core_same_coredev_type(const struct mlx5_core_dev *dev1,
|
|
+ const struct mlx5_core_dev *dev2)
|
|
+{
|
|
+ return dev1->coredev_type == dev2->coredev_type;
|
|
+}
|
|
+
|
|
static inline bool mlx5_core_is_ecpf(const struct mlx5_core_dev *dev)
|
|
{
|
|
return dev->caps.embedded_cpu;
|
|
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
|
|
index 5b5630e58407a5..e1c323c7d75ba9 100644
|
|
--- a/include/linux/mutex.h
|
|
+++ b/include/linux/mutex.h
|
|
@@ -248,6 +248,7 @@ extern void mutex_unlock(struct mutex *lock);
|
|
extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
|
|
|
|
DEFINE_GUARD(mutex, struct mutex *, mutex_lock(_T), mutex_unlock(_T))
|
|
-DEFINE_FREE(mutex, struct mutex *, if (_T) mutex_unlock(_T))
|
|
+DEFINE_GUARD_COND(mutex, _try, mutex_trylock(_T))
|
|
+DEFINE_GUARD_COND(mutex, _intr, mutex_lock_interruptible(_T) == 0)
|
|
|
|
#endif /* __LINUX_MUTEX_H */
|
|
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
|
|
index 1dd530ce8b45b9..9c29689ff505e0 100644
|
|
--- a/include/linux/rwsem.h
|
|
+++ b/include/linux/rwsem.h
|
|
@@ -203,11 +203,11 @@ extern void up_read(struct rw_semaphore *sem);
|
|
extern void up_write(struct rw_semaphore *sem);
|
|
|
|
DEFINE_GUARD(rwsem_read, struct rw_semaphore *, down_read(_T), up_read(_T))
|
|
-DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T))
|
|
-
|
|
-DEFINE_FREE(up_read, struct rw_semaphore *, if (_T) up_read(_T))
|
|
-DEFINE_FREE(up_write, struct rw_semaphore *, if (_T) up_write(_T))
|
|
+DEFINE_GUARD_COND(rwsem_read, _try, down_read_trylock(_T))
|
|
+DEFINE_GUARD_COND(rwsem_read, _intr, down_read_interruptible(_T) == 0)
|
|
|
|
+DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T))
|
|
+DEFINE_GUARD_COND(rwsem_write, _try, down_write_trylock(_T))
|
|
|
|
/*
|
|
* downgrade write lock to read lock
|
|
diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h
|
|
index 515d7fcb9634b5..468d8c5eef4a08 100644
|
|
--- a/include/linux/seq_buf.h
|
|
+++ b/include/linux/seq_buf.h
|
|
@@ -14,19 +14,24 @@
|
|
* @buffer: pointer to the buffer
|
|
* @size: size of the buffer
|
|
* @len: the amount of data inside the buffer
|
|
- * @readpos: The next position to read in the buffer.
|
|
*/
|
|
struct seq_buf {
|
|
char *buffer;
|
|
size_t size;
|
|
size_t len;
|
|
- loff_t readpos;
|
|
};
|
|
|
|
+#define DECLARE_SEQ_BUF(NAME, SIZE) \
|
|
+ struct seq_buf NAME = { \
|
|
+ .buffer = (char[SIZE]) { 0 }, \
|
|
+ .size = SIZE, \
|
|
+ }
|
|
+
|
|
static inline void seq_buf_clear(struct seq_buf *s)
|
|
{
|
|
s->len = 0;
|
|
- s->readpos = 0;
|
|
+ if (s->size)
|
|
+ s->buffer[0] = '\0';
|
|
}
|
|
|
|
static inline void
|
|
@@ -72,8 +77,8 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)
|
|
}
|
|
|
|
/**
|
|
- * seq_buf_terminate - Make sure buffer is nul terminated
|
|
- * @s: the seq_buf descriptor to terminate.
|
|
+ * seq_buf_str - get %NUL-terminated C string from seq_buf
|
|
+ * @s: the seq_buf handle
|
|
*
|
|
* This makes sure that the buffer in @s is nul terminated and
|
|
* safe to read as a string.
|
|
@@ -84,16 +89,20 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)
|
|
*
|
|
* After this function is called, s->buffer is safe to use
|
|
* in string operations.
|
|
+ *
|
|
+ * Returns @s->buf after making sure it is terminated.
|
|
*/
|
|
-static inline void seq_buf_terminate(struct seq_buf *s)
|
|
+static inline const char *seq_buf_str(struct seq_buf *s)
|
|
{
|
|
if (WARN_ON(s->size == 0))
|
|
- return;
|
|
+ return "";
|
|
|
|
if (seq_buf_buffer_left(s))
|
|
s->buffer[s->len] = 0;
|
|
else
|
|
s->buffer[s->size - 1] = 0;
|
|
+
|
|
+ return s->buffer;
|
|
}
|
|
|
|
/**
|
|
@@ -143,7 +152,7 @@ extern __printf(2, 0)
|
|
int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args);
|
|
extern int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s);
|
|
extern int seq_buf_to_user(struct seq_buf *s, char __user *ubuf,
|
|
- int cnt);
|
|
+ size_t start, int cnt);
|
|
extern int seq_buf_puts(struct seq_buf *s, const char *str);
|
|
extern int seq_buf_putc(struct seq_buf *s, unsigned char c);
|
|
extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len);
|
|
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
|
|
index 31d3d747a9db78..ceb56b39c70f77 100644
|
|
--- a/include/linux/spinlock.h
|
|
+++ b/include/linux/spinlock.h
|
|
@@ -507,6 +507,8 @@ DEFINE_LOCK_GUARD_1(raw_spinlock, raw_spinlock_t,
|
|
raw_spin_lock(_T->lock),
|
|
raw_spin_unlock(_T->lock))
|
|
|
|
+DEFINE_LOCK_GUARD_1_COND(raw_spinlock, _try, raw_spin_trylock(_T->lock))
|
|
+
|
|
DEFINE_LOCK_GUARD_1(raw_spinlock_nested, raw_spinlock_t,
|
|
raw_spin_lock_nested(_T->lock, SINGLE_DEPTH_NESTING),
|
|
raw_spin_unlock(_T->lock))
|
|
@@ -515,23 +517,36 @@ DEFINE_LOCK_GUARD_1(raw_spinlock_irq, raw_spinlock_t,
|
|
raw_spin_lock_irq(_T->lock),
|
|
raw_spin_unlock_irq(_T->lock))
|
|
|
|
+DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irq, _try, raw_spin_trylock_irq(_T->lock))
|
|
+
|
|
DEFINE_LOCK_GUARD_1(raw_spinlock_irqsave, raw_spinlock_t,
|
|
raw_spin_lock_irqsave(_T->lock, _T->flags),
|
|
raw_spin_unlock_irqrestore(_T->lock, _T->flags),
|
|
unsigned long flags)
|
|
|
|
+DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irqsave, _try,
|
|
+ raw_spin_trylock_irqsave(_T->lock, _T->flags))
|
|
+
|
|
DEFINE_LOCK_GUARD_1(spinlock, spinlock_t,
|
|
spin_lock(_T->lock),
|
|
spin_unlock(_T->lock))
|
|
|
|
+DEFINE_LOCK_GUARD_1_COND(spinlock, _try, spin_trylock(_T->lock))
|
|
+
|
|
DEFINE_LOCK_GUARD_1(spinlock_irq, spinlock_t,
|
|
spin_lock_irq(_T->lock),
|
|
spin_unlock_irq(_T->lock))
|
|
|
|
+DEFINE_LOCK_GUARD_1_COND(spinlock_irq, _try,
|
|
+ spin_trylock_irq(_T->lock))
|
|
+
|
|
DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t,
|
|
spin_lock_irqsave(_T->lock, _T->flags),
|
|
spin_unlock_irqrestore(_T->lock, _T->flags),
|
|
unsigned long flags)
|
|
|
|
+DEFINE_LOCK_GUARD_1_COND(spinlock_irqsave, _try,
|
|
+ spin_trylock_irqsave(_T->lock, _T->flags))
|
|
+
|
|
#undef __LINUX_INSIDE_SPINLOCK_H
|
|
#endif /* __LINUX_SPINLOCK_H */
|
|
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
|
|
index 9df2524fff33ae..aa1bc417266208 100644
|
|
--- a/include/linux/trace_events.h
|
|
+++ b/include/linux/trace_events.h
|
|
@@ -279,7 +279,8 @@ struct trace_event_fields {
|
|
const char *name;
|
|
const int size;
|
|
const int align;
|
|
- const int is_signed;
|
|
+ const unsigned int is_signed:1;
|
|
+ unsigned int needs_test:1;
|
|
const int filter_type;
|
|
const int len;
|
|
};
|
|
@@ -331,6 +332,7 @@ enum {
|
|
TRACE_EVENT_FL_EPROBE_BIT,
|
|
TRACE_EVENT_FL_FPROBE_BIT,
|
|
TRACE_EVENT_FL_CUSTOM_BIT,
|
|
+ TRACE_EVENT_FL_TEST_STR_BIT,
|
|
};
|
|
|
|
/*
|
|
@@ -348,6 +350,7 @@ enum {
|
|
* CUSTOM - Event is a custom event (to be attached to an exsiting tracepoint)
|
|
* This is set when the custom event has not been attached
|
|
* to a tracepoint yet, then it is cleared when it is.
|
|
+ * TEST_STR - The event has a "%s" that points to a string outside the event
|
|
*/
|
|
enum {
|
|
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
|
|
@@ -361,6 +364,7 @@ enum {
|
|
TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT),
|
|
TRACE_EVENT_FL_FPROBE = (1 << TRACE_EVENT_FL_FPROBE_BIT),
|
|
TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT),
|
|
+ TRACE_EVENT_FL_TEST_STR = (1 << TRACE_EVENT_FL_TEST_STR_BIT),
|
|
};
|
|
|
|
#define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE)
|
|
diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h
|
|
index 6be92bf559fe7c..3691e0e76a1a20 100644
|
|
--- a/include/linux/trace_seq.h
|
|
+++ b/include/linux/trace_seq.h
|
|
@@ -14,6 +14,7 @@
|
|
struct trace_seq {
|
|
char buffer[PAGE_SIZE];
|
|
struct seq_buf seq;
|
|
+ size_t readpos;
|
|
int full;
|
|
};
|
|
|
|
@@ -22,6 +23,7 @@ trace_seq_init(struct trace_seq *s)
|
|
{
|
|
seq_buf_init(&s->seq, s->buffer, PAGE_SIZE);
|
|
s->full = 0;
|
|
+ s->readpos = 0;
|
|
}
|
|
|
|
/**
|
|
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
|
|
index 0b4f2d5faa080d..ebdfef124b2bc0 100644
|
|
--- a/include/linux/usb/chipidea.h
|
|
+++ b/include/linux/usb/chipidea.h
|
|
@@ -64,6 +64,8 @@ struct ci_hdrc_platform_data {
|
|
#define CI_HDRC_PMQOS BIT(15)
|
|
#define CI_HDRC_PHY_VBUS_CONTROL BIT(16)
|
|
#define CI_HDRC_HAS_PORTSC_PEC_MISSED BIT(17)
|
|
+#define CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS BIT(18)
|
|
+#define CI_HDRC_HAS_SHORT_PKT_LIMIT BIT(19)
|
|
enum usb_dr_mode dr_mode;
|
|
#define CI_HDRC_CONTROLLER_RESET_EVENT 0
|
|
#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
|
|
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
|
|
index e9214ccfde2d72..4fcee6b734b74c 100644
|
|
--- a/include/net/bluetooth/hci_core.h
|
|
+++ b/include/net/bluetooth/hci_core.h
|
|
@@ -800,7 +800,6 @@ struct hci_conn_params {
|
|
extern struct list_head hci_dev_list;
|
|
extern struct list_head hci_cb_list;
|
|
extern rwlock_t hci_dev_list_lock;
|
|
-extern struct mutex hci_cb_list_lock;
|
|
|
|
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
|
|
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
|
|
@@ -1949,24 +1948,47 @@ struct hci_cb {
|
|
|
|
char *name;
|
|
|
|
+ bool (*match) (struct hci_conn *conn);
|
|
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
|
|
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
|
|
void (*security_cfm) (struct hci_conn *conn, __u8 status,
|
|
- __u8 encrypt);
|
|
+ __u8 encrypt);
|
|
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
|
|
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
|
|
};
|
|
|
|
+static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
|
|
+{
|
|
+ struct hci_cb *cb, *cpy;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ list_for_each_entry_rcu(cb, &hci_cb_list, list) {
|
|
+ if (cb->match && cb->match(conn)) {
|
|
+ cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
|
|
+ if (!cpy)
|
|
+ break;
|
|
+
|
|
+ *cpy = *cb;
|
|
+ INIT_LIST_HEAD(&cpy->list);
|
|
+ list_add_rcu(&cpy->list, list);
|
|
+ }
|
|
+ }
|
|
+ rcu_read_unlock();
|
|
+}
|
|
+
|
|
static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
|
|
{
|
|
- struct hci_cb *cb;
|
|
+ struct list_head list;
|
|
+ struct hci_cb *cb, *tmp;
|
|
+
|
|
+ INIT_LIST_HEAD(&list);
|
|
+ hci_cb_lookup(conn, &list);
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_for_each_entry(cb, &hci_cb_list, list) {
|
|
+ list_for_each_entry_safe(cb, tmp, &list, list) {
|
|
if (cb->connect_cfm)
|
|
cb->connect_cfm(conn, status);
|
|
+ kfree(cb);
|
|
}
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
|
|
if (conn->connect_cfm_cb)
|
|
conn->connect_cfm_cb(conn, status);
|
|
@@ -1974,43 +1996,55 @@ static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
|
|
|
|
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
|
|
{
|
|
- struct hci_cb *cb;
|
|
+ struct list_head list;
|
|
+ struct hci_cb *cb, *tmp;
|
|
+
|
|
+ INIT_LIST_HEAD(&list);
|
|
+ hci_cb_lookup(conn, &list);
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_for_each_entry(cb, &hci_cb_list, list) {
|
|
+ list_for_each_entry_safe(cb, tmp, &list, list) {
|
|
if (cb->disconn_cfm)
|
|
cb->disconn_cfm(conn, reason);
|
|
+ kfree(cb);
|
|
}
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
|
|
if (conn->disconn_cfm_cb)
|
|
conn->disconn_cfm_cb(conn, reason);
|
|
}
|
|
|
|
-static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
|
+static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
|
|
+ __u8 encrypt)
|
|
{
|
|
- struct hci_cb *cb;
|
|
- __u8 encrypt;
|
|
-
|
|
- if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
|
|
- return;
|
|
+ struct list_head list;
|
|
+ struct hci_cb *cb, *tmp;
|
|
|
|
- encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
|
|
+ INIT_LIST_HEAD(&list);
|
|
+ hci_cb_lookup(conn, &list);
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_for_each_entry(cb, &hci_cb_list, list) {
|
|
+ list_for_each_entry_safe(cb, tmp, &list, list) {
|
|
if (cb->security_cfm)
|
|
cb->security_cfm(conn, status, encrypt);
|
|
+ kfree(cb);
|
|
}
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
|
|
if (conn->security_cfm_cb)
|
|
conn->security_cfm_cb(conn, status);
|
|
}
|
|
|
|
+static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
|
|
+{
|
|
+ __u8 encrypt;
|
|
+
|
|
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
|
|
+ return;
|
|
+
|
|
+ encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
|
|
+
|
|
+ hci_security_cfm(conn, status, encrypt);
|
|
+}
|
|
+
|
|
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
|
|
{
|
|
- struct hci_cb *cb;
|
|
__u8 encrypt;
|
|
|
|
if (conn->state == BT_CONFIG) {
|
|
@@ -2037,40 +2071,38 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
|
|
conn->sec_level = conn->pending_sec_level;
|
|
}
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_for_each_entry(cb, &hci_cb_list, list) {
|
|
- if (cb->security_cfm)
|
|
- cb->security_cfm(conn, status, encrypt);
|
|
- }
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
-
|
|
- if (conn->security_cfm_cb)
|
|
- conn->security_cfm_cb(conn, status);
|
|
+ hci_security_cfm(conn, status, encrypt);
|
|
}
|
|
|
|
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
|
|
{
|
|
- struct hci_cb *cb;
|
|
+ struct list_head list;
|
|
+ struct hci_cb *cb, *tmp;
|
|
+
|
|
+ INIT_LIST_HEAD(&list);
|
|
+ hci_cb_lookup(conn, &list);
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_for_each_entry(cb, &hci_cb_list, list) {
|
|
+ list_for_each_entry_safe(cb, tmp, &list, list) {
|
|
if (cb->key_change_cfm)
|
|
cb->key_change_cfm(conn, status);
|
|
+ kfree(cb);
|
|
}
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
}
|
|
|
|
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
|
|
__u8 role)
|
|
{
|
|
- struct hci_cb *cb;
|
|
+ struct list_head list;
|
|
+ struct hci_cb *cb, *tmp;
|
|
+
|
|
+ INIT_LIST_HEAD(&list);
|
|
+ hci_cb_lookup(conn, &list);
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_for_each_entry(cb, &hci_cb_list, list) {
|
|
+ list_for_each_entry_safe(cb, tmp, &list, list) {
|
|
if (cb->role_switch_cfm)
|
|
cb->role_switch_cfm(conn, status, role);
|
|
+ kfree(cb);
|
|
}
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
}
|
|
|
|
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
|
|
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
|
index 47ade676565dbc..835a58ce9ca57c 100644
|
|
--- a/include/net/mac80211.h
|
|
+++ b/include/net/mac80211.h
|
|
@@ -3039,6 +3039,19 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
|
|
*/
|
|
void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
|
|
|
|
+/**
|
|
+ * ieee80211_purge_tx_queue - purge TX skb queue
|
|
+ * @hw: the hardware
|
|
+ * @skbs: the skbs
|
|
+ *
|
|
+ * Free a set of transmit skbs. Use this function when device is going to stop
|
|
+ * but some transmit skbs without TX status are still queued.
|
|
+ * This function does not take the list lock and the caller must hold the
|
|
+ * relevant locks to use it.
|
|
+ */
|
|
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
|
|
+ struct sk_buff_head *skbs);
|
|
+
|
|
/**
|
|
* DOC: Hardware crypto acceleration
|
|
*
|
|
@@ -6067,6 +6080,24 @@ void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
|
|
void (*iterator)(void *data,
|
|
struct ieee80211_sta *sta),
|
|
void *data);
|
|
+
|
|
+/**
|
|
+ * ieee80211_iterate_stations_mtx - iterate stations
|
|
+ *
|
|
+ * This function iterates over all stations associated with a given
|
|
+ * hardware that are currently uploaded to the driver and calls the callback
|
|
+ * function for them. This version can only be used while holding the wiphy
|
|
+ * mutex.
|
|
+ *
|
|
+ * @hw: the hardware struct of which the interfaces should be iterated over
|
|
+ * @iterator: the iterator function to call
|
|
+ * @data: first argument of the iterator function
|
|
+ */
|
|
+void ieee80211_iterate_stations_mtx(struct ieee80211_hw *hw,
|
|
+ void (*iterator)(void *data,
|
|
+ struct ieee80211_sta *sta),
|
|
+ void *data);
|
|
+
|
|
/**
|
|
* ieee80211_queue_work - add work onto the mac80211 workqueue
|
|
*
|
|
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
|
|
index b5f9ee5810a347..8321915dddb284 100644
|
|
--- a/include/net/netfilter/nf_tables.h
|
|
+++ b/include/net/netfilter/nf_tables.h
|
|
@@ -721,15 +721,18 @@ struct nft_set_ext_tmpl {
|
|
/**
|
|
* struct nft_set_ext - set extensions
|
|
*
|
|
- * @genmask: generation mask
|
|
+ * @genmask: generation mask, but also flags (see NFT_SET_ELEM_DEAD_BIT)
|
|
* @offset: offsets of individual extension types
|
|
* @data: beginning of extension data
|
|
+ *
|
|
+ * This structure must be aligned to word size, otherwise atomic bitops
|
|
+ * on genmask field can cause alignment failure on some archs.
|
|
*/
|
|
struct nft_set_ext {
|
|
u8 genmask;
|
|
u8 offset[NFT_SET_EXT_NUM];
|
|
char data[];
|
|
-};
|
|
+} __aligned(BITS_PER_LONG / 8);
|
|
|
|
static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl)
|
|
{
|
|
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
|
|
index 58ee17f429a33a..02f327f05fd619 100644
|
|
--- a/kernel/bpf/core.c
|
|
+++ b/kernel/bpf/core.c
|
|
@@ -529,6 +529,8 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
|
|
|
|
int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
|
|
{
|
|
+ int err;
|
|
+
|
|
/* Branch offsets can't overflow when program is shrinking, no need
|
|
* to call bpf_adj_branches(..., true) here
|
|
*/
|
|
@@ -536,7 +538,9 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
|
|
sizeof(struct bpf_insn) * (prog->len - off - cnt));
|
|
prog->len -= cnt;
|
|
|
|
- return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false));
|
|
+ err = bpf_adj_branches(prog, off, off + cnt, off, false);
|
|
+ WARN_ON_ONCE(err);
|
|
+ return err;
|
|
}
|
|
|
|
static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
|
|
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
|
|
index a3c3c66ca04759..d6a4102312fadd 100644
|
|
--- a/kernel/bpf/verifier.c
|
|
+++ b/kernel/bpf/verifier.c
|
|
@@ -1762,8 +1762,8 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
|
|
int i, err;
|
|
|
|
dst_state->jmp_history = copy_array(dst_state->jmp_history, src->jmp_history,
|
|
- src->jmp_history_cnt, sizeof(*dst_state->jmp_history),
|
|
- GFP_USER);
|
|
+ src->jmp_history_cnt, sizeof(struct bpf_idx_pair),
|
|
+ GFP_USER);
|
|
if (!dst_state->jmp_history)
|
|
return -ENOMEM;
|
|
dst_state->jmp_history_cnt = src->jmp_history_cnt;
|
|
@@ -3397,21 +3397,6 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
|
|
return __check_reg_arg(env, state->regs, regno, t);
|
|
}
|
|
|
|
-static int insn_stack_access_flags(int frameno, int spi)
|
|
-{
|
|
- return INSN_F_STACK_ACCESS | (spi << INSN_F_SPI_SHIFT) | frameno;
|
|
-}
|
|
-
|
|
-static int insn_stack_access_spi(int insn_flags)
|
|
-{
|
|
- return (insn_flags >> INSN_F_SPI_SHIFT) & INSN_F_SPI_MASK;
|
|
-}
|
|
-
|
|
-static int insn_stack_access_frameno(int insn_flags)
|
|
-{
|
|
- return insn_flags & INSN_F_FRAMENO_MASK;
|
|
-}
|
|
-
|
|
static void mark_jmp_point(struct bpf_verifier_env *env, int idx)
|
|
{
|
|
env->insn_aux_data[idx].jmp_point = true;
|
|
@@ -3423,51 +3408,28 @@ static bool is_jmp_point(struct bpf_verifier_env *env, int insn_idx)
|
|
}
|
|
|
|
/* for any branch, call, exit record the history of jmps in the given state */
|
|
-static int push_jmp_history(struct bpf_verifier_env *env, struct bpf_verifier_state *cur,
|
|
- int insn_flags)
|
|
+static int push_jmp_history(struct bpf_verifier_env *env,
|
|
+ struct bpf_verifier_state *cur)
|
|
{
|
|
u32 cnt = cur->jmp_history_cnt;
|
|
- struct bpf_jmp_history_entry *p;
|
|
+ struct bpf_idx_pair *p;
|
|
size_t alloc_size;
|
|
|
|
- /* combine instruction flags if we already recorded this instruction */
|
|
- if (env->cur_hist_ent) {
|
|
- /* atomic instructions push insn_flags twice, for READ and
|
|
- * WRITE sides, but they should agree on stack slot
|
|
- */
|
|
- WARN_ONCE((env->cur_hist_ent->flags & insn_flags) &&
|
|
- (env->cur_hist_ent->flags & insn_flags) != insn_flags,
|
|
- "verifier insn history bug: insn_idx %d cur flags %x new flags %x\n",
|
|
- env->insn_idx, env->cur_hist_ent->flags, insn_flags);
|
|
- env->cur_hist_ent->flags |= insn_flags;
|
|
+ if (!is_jmp_point(env, env->insn_idx))
|
|
return 0;
|
|
- }
|
|
|
|
cnt++;
|
|
alloc_size = kmalloc_size_roundup(size_mul(cnt, sizeof(*p)));
|
|
p = krealloc(cur->jmp_history, alloc_size, GFP_USER);
|
|
if (!p)
|
|
return -ENOMEM;
|
|
+ p[cnt - 1].idx = env->insn_idx;
|
|
+ p[cnt - 1].prev_idx = env->prev_insn_idx;
|
|
cur->jmp_history = p;
|
|
-
|
|
- p = &cur->jmp_history[cnt - 1];
|
|
- p->idx = env->insn_idx;
|
|
- p->prev_idx = env->prev_insn_idx;
|
|
- p->flags = insn_flags;
|
|
cur->jmp_history_cnt = cnt;
|
|
- env->cur_hist_ent = p;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
-static struct bpf_jmp_history_entry *get_jmp_hist_entry(struct bpf_verifier_state *st,
|
|
- u32 hist_end, int insn_idx)
|
|
-{
|
|
- if (hist_end > 0 && st->jmp_history[hist_end - 1].idx == insn_idx)
|
|
- return &st->jmp_history[hist_end - 1];
|
|
- return NULL;
|
|
-}
|
|
-
|
|
/* Backtrack one insn at a time. If idx is not at the top of recorded
|
|
* history then previous instruction came from straight line execution.
|
|
* Return -ENOENT if we exhausted all instructions within given state.
|
|
@@ -3629,14 +3591,9 @@ static inline bool bt_is_reg_set(struct backtrack_state *bt, u32 reg)
|
|
return bt->reg_masks[bt->frame] & (1 << reg);
|
|
}
|
|
|
|
-static inline bool bt_is_frame_slot_set(struct backtrack_state *bt, u32 frame, u32 slot)
|
|
-{
|
|
- return bt->stack_masks[frame] & (1ull << slot);
|
|
-}
|
|
-
|
|
static inline bool bt_is_slot_set(struct backtrack_state *bt, u32 slot)
|
|
{
|
|
- return bt_is_frame_slot_set(bt, bt->frame, slot);
|
|
+ return bt->stack_masks[bt->frame] & (1ull << slot);
|
|
}
|
|
|
|
/* format registers bitmask, e.g., "r0,r2,r4" for 0x15 mask */
|
|
@@ -3690,7 +3647,7 @@ static bool calls_callback(struct bpf_verifier_env *env, int insn_idx);
|
|
* - *was* processed previously during backtracking.
|
|
*/
|
|
static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
- struct bpf_jmp_history_entry *hist, struct backtrack_state *bt)
|
|
+ struct backtrack_state *bt)
|
|
{
|
|
const struct bpf_insn_cbs cbs = {
|
|
.cb_call = disasm_kfunc_name,
|
|
@@ -3703,7 +3660,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
u8 mode = BPF_MODE(insn->code);
|
|
u32 dreg = insn->dst_reg;
|
|
u32 sreg = insn->src_reg;
|
|
- u32 spi, i, fr;
|
|
+ u32 spi, i;
|
|
|
|
if (insn->code == 0)
|
|
return 0;
|
|
@@ -3766,15 +3723,20 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
* by 'precise' mark in corresponding register of this state.
|
|
* No further tracking necessary.
|
|
*/
|
|
- if (!hist || !(hist->flags & INSN_F_STACK_ACCESS))
|
|
+ if (insn->src_reg != BPF_REG_FP)
|
|
return 0;
|
|
+
|
|
/* dreg = *(u64 *)[fp - off] was a fill from the stack.
|
|
* that [fp - off] slot contains scalar that needs to be
|
|
* tracked with precision
|
|
*/
|
|
- spi = insn_stack_access_spi(hist->flags);
|
|
- fr = insn_stack_access_frameno(hist->flags);
|
|
- bt_set_frame_slot(bt, fr, spi);
|
|
+ spi = (-insn->off - 1) / BPF_REG_SIZE;
|
|
+ if (spi >= 64) {
|
|
+ verbose(env, "BUG spi %d\n", spi);
|
|
+ WARN_ONCE(1, "verifier backtracking bug");
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ bt_set_slot(bt, spi);
|
|
} else if (class == BPF_STX || class == BPF_ST) {
|
|
if (bt_is_reg_set(bt, dreg))
|
|
/* stx & st shouldn't be using _scalar_ dst_reg
|
|
@@ -3783,13 +3745,17 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
*/
|
|
return -ENOTSUPP;
|
|
/* scalars can only be spilled into stack */
|
|
- if (!hist || !(hist->flags & INSN_F_STACK_ACCESS))
|
|
+ if (insn->dst_reg != BPF_REG_FP)
|
|
return 0;
|
|
- spi = insn_stack_access_spi(hist->flags);
|
|
- fr = insn_stack_access_frameno(hist->flags);
|
|
- if (!bt_is_frame_slot_set(bt, fr, spi))
|
|
+ spi = (-insn->off - 1) / BPF_REG_SIZE;
|
|
+ if (spi >= 64) {
|
|
+ verbose(env, "BUG spi %d\n", spi);
|
|
+ WARN_ONCE(1, "verifier backtracking bug");
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ if (!bt_is_slot_set(bt, spi))
|
|
return 0;
|
|
- bt_clear_frame_slot(bt, fr, spi);
|
|
+ bt_clear_slot(bt, spi);
|
|
if (class == BPF_STX)
|
|
bt_set_reg(bt, sreg);
|
|
} else if (class == BPF_JMP || class == BPF_JMP32) {
|
|
@@ -3833,14 +3799,10 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
WARN_ONCE(1, "verifier backtracking bug");
|
|
return -EFAULT;
|
|
}
|
|
- /* we are now tracking register spills correctly,
|
|
- * so any instance of leftover slots is a bug
|
|
- */
|
|
- if (bt_stack_mask(bt) != 0) {
|
|
- verbose(env, "BUG stack slots %llx\n", bt_stack_mask(bt));
|
|
- WARN_ONCE(1, "verifier backtracking bug (subprog leftover stack slots)");
|
|
- return -EFAULT;
|
|
- }
|
|
+ /* we don't track register spills perfectly,
|
|
+ * so fallback to force-precise instead of failing */
|
|
+ if (bt_stack_mask(bt) != 0)
|
|
+ return -ENOTSUPP;
|
|
/* propagate r1-r5 to the caller */
|
|
for (i = BPF_REG_1; i <= BPF_REG_5; i++) {
|
|
if (bt_is_reg_set(bt, i)) {
|
|
@@ -3865,11 +3827,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
WARN_ONCE(1, "verifier backtracking bug");
|
|
return -EFAULT;
|
|
}
|
|
- if (bt_stack_mask(bt) != 0) {
|
|
- verbose(env, "BUG stack slots %llx\n", bt_stack_mask(bt));
|
|
- WARN_ONCE(1, "verifier backtracking bug (callback leftover stack slots)");
|
|
- return -EFAULT;
|
|
- }
|
|
+ if (bt_stack_mask(bt) != 0)
|
|
+ return -ENOTSUPP;
|
|
/* clear r1-r5 in callback subprog's mask */
|
|
for (i = BPF_REG_1; i <= BPF_REG_5; i++)
|
|
bt_clear_reg(bt, i);
|
|
@@ -4306,7 +4265,6 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
|
for (;;) {
|
|
DECLARE_BITMAP(mask, 64);
|
|
u32 history = st->jmp_history_cnt;
|
|
- struct bpf_jmp_history_entry *hist;
|
|
|
|
if (env->log.level & BPF_LOG_LEVEL2) {
|
|
verbose(env, "mark_precise: frame%d: last_idx %d first_idx %d subseq_idx %d \n",
|
|
@@ -4370,8 +4328,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
|
err = 0;
|
|
skip_first = false;
|
|
} else {
|
|
- hist = get_jmp_hist_entry(st, history, i);
|
|
- err = backtrack_insn(env, i, subseq_idx, hist, bt);
|
|
+ err = backtrack_insn(env, i, subseq_idx, bt);
|
|
}
|
|
if (err == -ENOTSUPP) {
|
|
mark_all_scalars_precise(env, env->cur_state);
|
|
@@ -4424,10 +4381,22 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
|
bitmap_from_u64(mask, bt_frame_stack_mask(bt, fr));
|
|
for_each_set_bit(i, mask, 64) {
|
|
if (i >= func->allocated_stack / BPF_REG_SIZE) {
|
|
- verbose(env, "BUG backtracking (stack slot %d, total slots %d)\n",
|
|
- i, func->allocated_stack / BPF_REG_SIZE);
|
|
- WARN_ONCE(1, "verifier backtracking bug (stack slot out of bounds)");
|
|
- return -EFAULT;
|
|
+ /* the sequence of instructions:
|
|
+ * 2: (bf) r3 = r10
|
|
+ * 3: (7b) *(u64 *)(r3 -8) = r0
|
|
+ * 4: (79) r4 = *(u64 *)(r10 -8)
|
|
+ * doesn't contain jmps. It's backtracked
|
|
+ * as a single block.
|
|
+ * During backtracking insn 3 is not recognized as
|
|
+ * stack access, so at the end of backtracking
|
|
+ * stack slot fp-8 is still marked in stack_mask.
|
|
+ * However the parent state may not have accessed
|
|
+ * fp-8 and it's "unallocated" stack space.
|
|
+ * In such case fallback to conservative.
|
|
+ */
|
|
+ mark_all_scalars_precise(env, env->cur_state);
|
|
+ bt_reset(bt);
|
|
+ return 0;
|
|
}
|
|
|
|
if (!is_spilled_scalar_reg(&func->stack[i])) {
|
|
@@ -4592,7 +4561,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
int i, slot = -off - 1, spi = slot / BPF_REG_SIZE, err;
|
|
struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
|
|
struct bpf_reg_state *reg = NULL;
|
|
- int insn_flags = insn_stack_access_flags(state->frameno, spi);
|
|
+ u32 dst_reg = insn->dst_reg;
|
|
|
|
/* caller checked that off % size == 0 and -MAX_BPF_STACK <= off < 0,
|
|
* so it's aligned access and [off, off + size) are within stack limits
|
|
@@ -4631,6 +4600,17 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
mark_stack_slot_scratched(env, spi);
|
|
if (reg && !(off % BPF_REG_SIZE) && register_is_bounded(reg) &&
|
|
!register_is_null(reg) && env->bpf_capable) {
|
|
+ if (dst_reg != BPF_REG_FP) {
|
|
+ /* The backtracking logic can only recognize explicit
|
|
+ * stack slot address like [fp - 8]. Other spill of
|
|
+ * scalar via different register has to be conservative.
|
|
+ * Backtrack from here and mark all registers as precise
|
|
+ * that contributed into 'reg' being a constant.
|
|
+ */
|
|
+ err = mark_chain_precision(env, value_regno);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
save_register_state(state, spi, reg, size);
|
|
/* Break the relation on a narrowing spill. */
|
|
if (fls64(reg->umax_value) > BITS_PER_BYTE * size)
|
|
@@ -4642,7 +4622,6 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
__mark_reg_known(&fake_reg, insn->imm);
|
|
fake_reg.type = SCALAR_VALUE;
|
|
save_register_state(state, spi, &fake_reg, size);
|
|
- insn_flags = 0; /* not a register spill */
|
|
} else if (reg && is_spillable_regtype(reg->type)) {
|
|
/* register containing pointer is being spilled into stack */
|
|
if (size != BPF_REG_SIZE) {
|
|
@@ -4688,12 +4667,9 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
|
|
/* Mark slots affected by this stack write. */
|
|
for (i = 0; i < size; i++)
|
|
- state->stack[spi].slot_type[(slot - i) % BPF_REG_SIZE] = type;
|
|
- insn_flags = 0; /* not a register spill */
|
|
+ state->stack[spi].slot_type[(slot - i) % BPF_REG_SIZE] =
|
|
+ type;
|
|
}
|
|
-
|
|
- if (insn_flags)
|
|
- return push_jmp_history(env, env->cur_state, insn_flags);
|
|
return 0;
|
|
}
|
|
|
|
@@ -4882,7 +4858,6 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
|
int i, slot = -off - 1, spi = slot / BPF_REG_SIZE;
|
|
struct bpf_reg_state *reg;
|
|
u8 *stype, type;
|
|
- int insn_flags = insn_stack_access_flags(reg_state->frameno, spi);
|
|
|
|
stype = reg_state->stack[spi].slot_type;
|
|
reg = ®_state->stack[spi].spilled_ptr;
|
|
@@ -4928,10 +4903,12 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
|
return -EACCES;
|
|
}
|
|
mark_reg_unknown(env, state->regs, dst_regno);
|
|
- insn_flags = 0; /* not restoring original register state */
|
|
}
|
|
state->regs[dst_regno].live |= REG_LIVE_WRITTEN;
|
|
- } else if (dst_regno >= 0) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (dst_regno >= 0) {
|
|
/* restore register state from stack */
|
|
copy_register_state(&state->regs[dst_regno], reg);
|
|
/* mark reg as written since spilled pointer state likely
|
|
@@ -4967,10 +4944,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
|
mark_reg_read(env, reg, reg->parent, REG_LIVE_READ64);
|
|
if (dst_regno >= 0)
|
|
mark_reg_stack_read(env, reg_state, off, off + size, dst_regno);
|
|
- insn_flags = 0; /* we are not restoring spilled register */
|
|
}
|
|
- if (insn_flags)
|
|
- return push_jmp_history(env, env->cur_state, insn_flags);
|
|
return 0;
|
|
}
|
|
|
|
@@ -7054,6 +7028,7 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
|
|
BPF_SIZE(insn->code), BPF_WRITE, -1, true, false);
|
|
if (err)
|
|
return err;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -16802,8 +16777,7 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
|
|
* the precision needs to be propagated back in
|
|
* the current state.
|
|
*/
|
|
- if (is_jmp_point(env, env->insn_idx))
|
|
- err = err ? : push_jmp_history(env, cur, 0);
|
|
+ err = err ? : push_jmp_history(env, cur);
|
|
err = err ? : propagate_precision(env, &sl->state);
|
|
if (err)
|
|
return err;
|
|
@@ -17027,9 +17001,6 @@ static int do_check(struct bpf_verifier_env *env)
|
|
u8 class;
|
|
int err;
|
|
|
|
- /* reset current history entry on each new instruction */
|
|
- env->cur_hist_ent = NULL;
|
|
-
|
|
env->prev_insn_idx = prev_insn_idx;
|
|
if (env->insn_idx >= insn_cnt) {
|
|
verbose(env, "invalid insn idx %d insn_cnt %d\n",
|
|
@@ -17069,7 +17040,7 @@ static int do_check(struct bpf_verifier_env *env)
|
|
}
|
|
|
|
if (is_jmp_point(env, env->insn_idx)) {
|
|
- err = push_jmp_history(env, state, 0);
|
|
+ err = push_jmp_history(env, state);
|
|
if (err)
|
|
return err;
|
|
}
|
|
diff --git a/kernel/kcov.c b/kernel/kcov.c
|
|
index 72d9aa6fb50c3e..097c8afa675578 100644
|
|
--- a/kernel/kcov.c
|
|
+++ b/kernel/kcov.c
|
|
@@ -165,7 +165,7 @@ static void kcov_remote_area_put(struct kcov_remote_area *area,
|
|
* Unlike in_serving_softirq(), this function returns false when called during
|
|
* a hardirq or an NMI that happened in the softirq context.
|
|
*/
|
|
-static inline bool in_softirq_really(void)
|
|
+static __always_inline bool in_softirq_really(void)
|
|
{
|
|
return in_serving_softirq() && !in_hardirq() && !in_nmi();
|
|
}
|
|
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
|
index 228f7c07da7284..86606fb9e6bc6c 100644
|
|
--- a/kernel/sched/core.c
|
|
+++ b/kernel/sched/core.c
|
|
@@ -4488,7 +4488,8 @@ int wake_up_state(struct task_struct *p, unsigned int state)
|
|
* Perform scheduler related setup for a newly forked process p.
|
|
* p is forked by current.
|
|
*
|
|
- * __sched_fork() is basic setup used by init_idle() too:
|
|
+ * __sched_fork() is basic setup which is also used by sched_init() to
|
|
+ * initialize the boot CPU's idle task.
|
|
*/
|
|
static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
|
|
{
|
|
@@ -9257,8 +9258,6 @@ void __init init_idle(struct task_struct *idle, int cpu)
|
|
struct rq *rq = cpu_rq(cpu);
|
|
unsigned long flags;
|
|
|
|
- __sched_fork(0, idle);
|
|
-
|
|
raw_spin_lock_irqsave(&idle->pi_lock, flags);
|
|
raw_spin_rq_lock(rq);
|
|
|
|
@@ -9273,10 +9272,8 @@ void __init init_idle(struct task_struct *idle, int cpu)
|
|
|
|
#ifdef CONFIG_SMP
|
|
/*
|
|
- * It's possible that init_idle() gets called multiple times on a task,
|
|
- * in that case do_set_cpus_allowed() will not do the right thing.
|
|
- *
|
|
- * And since this is boot we can forgo the serialization.
|
|
+ * No validation and serialization required at boot time and for
|
|
+ * setting up the idle tasks of not yet online CPUs.
|
|
*/
|
|
set_cpus_allowed_common(idle, &ac);
|
|
#endif
|
|
@@ -10105,6 +10102,7 @@ void __init sched_init(void)
|
|
* but because we are the idle thread, we just pick up running again
|
|
* when this runqueue becomes "idle".
|
|
*/
|
|
+ __sched_fork(0, current);
|
|
init_idle(current, smp_processor_id());
|
|
|
|
calc_load_update = jiffies + LOAD_FREQ;
|
|
diff --git a/kernel/softirq.c b/kernel/softirq.c
|
|
index bd9716d7bb6383..f24d80cf20bd35 100644
|
|
--- a/kernel/softirq.c
|
|
+++ b/kernel/softirq.c
|
|
@@ -279,17 +279,24 @@ static inline void invoke_softirq(void)
|
|
wakeup_softirqd();
|
|
}
|
|
|
|
+#define SCHED_SOFTIRQ_MASK BIT(SCHED_SOFTIRQ)
|
|
+
|
|
/*
|
|
* flush_smp_call_function_queue() can raise a soft interrupt in a function
|
|
- * call. On RT kernels this is undesired and the only known functionality
|
|
- * in the block layer which does this is disabled on RT. If soft interrupts
|
|
- * get raised which haven't been raised before the flush, warn so it can be
|
|
+ * call. On RT kernels this is undesired and the only known functionalities
|
|
+ * are in the block layer which is disabled on RT, and in the scheduler for
|
|
+ * idle load balancing. If soft interrupts get raised which haven't been
|
|
+ * raised before the flush, warn if it is not a SCHED_SOFTIRQ so it can be
|
|
* investigated.
|
|
*/
|
|
void do_softirq_post_smp_call_flush(unsigned int was_pending)
|
|
{
|
|
- if (WARN_ON_ONCE(was_pending != local_softirq_pending()))
|
|
+ unsigned int is_pending = local_softirq_pending();
|
|
+
|
|
+ if (unlikely(was_pending != is_pending)) {
|
|
+ WARN_ON_ONCE(was_pending != (is_pending & ~SCHED_SOFTIRQ_MASK));
|
|
invoke_softirq();
|
|
+ }
|
|
}
|
|
|
|
#else /* CONFIG_PREEMPT_RT */
|
|
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
|
|
index 220903117c5139..9d9af60b238e27 100644
|
|
--- a/kernel/trace/trace.c
|
|
+++ b/kernel/trace/trace.c
|
|
@@ -1731,15 +1731,15 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
|
|
{
|
|
int len;
|
|
|
|
- if (trace_seq_used(s) <= s->seq.readpos)
|
|
+ if (trace_seq_used(s) <= s->readpos)
|
|
return -EBUSY;
|
|
|
|
- len = trace_seq_used(s) - s->seq.readpos;
|
|
+ len = trace_seq_used(s) - s->readpos;
|
|
if (cnt > len)
|
|
cnt = len;
|
|
- memcpy(buf, s->buffer + s->seq.readpos, cnt);
|
|
+ memcpy(buf, s->buffer + s->readpos, cnt);
|
|
|
|
- s->seq.readpos += cnt;
|
|
+ s->readpos += cnt;
|
|
return cnt;
|
|
}
|
|
|
|
@@ -3760,17 +3760,12 @@ char *trace_iter_expand_format(struct trace_iterator *iter)
|
|
}
|
|
|
|
/* Returns true if the string is safe to dereference from an event */
|
|
-static bool trace_safe_str(struct trace_iterator *iter, const char *str,
|
|
- bool star, int len)
|
|
+static bool trace_safe_str(struct trace_iterator *iter, const char *str)
|
|
{
|
|
unsigned long addr = (unsigned long)str;
|
|
struct trace_event *trace_event;
|
|
struct trace_event_call *event;
|
|
|
|
- /* Ignore strings with no length */
|
|
- if (star && !len)
|
|
- return true;
|
|
-
|
|
/* OK if part of the event data */
|
|
if ((addr >= (unsigned long)iter->ent) &&
|
|
(addr < (unsigned long)iter->ent + iter->ent_size))
|
|
@@ -3810,142 +3805,69 @@ static bool trace_safe_str(struct trace_iterator *iter, const char *str,
|
|
return false;
|
|
}
|
|
|
|
-static const char *show_buffer(struct trace_seq *s)
|
|
-{
|
|
- struct seq_buf *seq = &s->seq;
|
|
-
|
|
- seq_buf_terminate(seq);
|
|
-
|
|
- return seq->buffer;
|
|
-}
|
|
-
|
|
-static DEFINE_STATIC_KEY_FALSE(trace_no_verify);
|
|
-
|
|
-static int test_can_verify_check(const char *fmt, ...)
|
|
-{
|
|
- char buf[16];
|
|
- va_list ap;
|
|
- int ret;
|
|
-
|
|
- /*
|
|
- * The verifier is dependent on vsnprintf() modifies the va_list
|
|
- * passed to it, where it is sent as a reference. Some architectures
|
|
- * (like x86_32) passes it by value, which means that vsnprintf()
|
|
- * does not modify the va_list passed to it, and the verifier
|
|
- * would then need to be able to understand all the values that
|
|
- * vsnprintf can use. If it is passed by value, then the verifier
|
|
- * is disabled.
|
|
- */
|
|
- va_start(ap, fmt);
|
|
- vsnprintf(buf, 16, "%d", ap);
|
|
- ret = va_arg(ap, int);
|
|
- va_end(ap);
|
|
-
|
|
- return ret;
|
|
-}
|
|
-
|
|
-static void test_can_verify(void)
|
|
-{
|
|
- if (!test_can_verify_check("%d %d", 0, 1)) {
|
|
- pr_info("trace event string verifier disabled\n");
|
|
- static_branch_inc(&trace_no_verify);
|
|
- }
|
|
-}
|
|
-
|
|
/**
|
|
- * trace_check_vprintf - Check dereferenced strings while writing to the seq buffer
|
|
+ * ignore_event - Check dereferenced fields while writing to the seq buffer
|
|
* @iter: The iterator that holds the seq buffer and the event being printed
|
|
- * @fmt: The format used to print the event
|
|
- * @ap: The va_list holding the data to print from @fmt.
|
|
*
|
|
- * This writes the data into the @iter->seq buffer using the data from
|
|
- * @fmt and @ap. If the format has a %s, then the source of the string
|
|
- * is examined to make sure it is safe to print, otherwise it will
|
|
- * warn and print "[UNSAFE MEMORY]" in place of the dereferenced string
|
|
- * pointer.
|
|
+ * At boot up, test_event_printk() will flag any event that dereferences
|
|
+ * a string with "%s" that does exist in the ring buffer. It may still
|
|
+ * be valid, as the string may point to a static string in the kernel
|
|
+ * rodata that never gets freed. But if the string pointer is pointing
|
|
+ * to something that was allocated, there's a chance that it can be freed
|
|
+ * by the time the user reads the trace. This would cause a bad memory
|
|
+ * access by the kernel and possibly crash the system.
|
|
+ *
|
|
+ * This function will check if the event has any fields flagged as needing
|
|
+ * to be checked at runtime and perform those checks.
|
|
+ *
|
|
+ * If it is found that a field is unsafe, it will write into the @iter->seq
|
|
+ * a message stating what was found to be unsafe.
|
|
+ *
|
|
+ * @return: true if the event is unsafe and should be ignored,
|
|
+ * false otherwise.
|
|
*/
|
|
-void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
|
|
- va_list ap)
|
|
+bool ignore_event(struct trace_iterator *iter)
|
|
{
|
|
- const char *p = fmt;
|
|
- const char *str;
|
|
- int i, j;
|
|
+ struct ftrace_event_field *field;
|
|
+ struct trace_event *trace_event;
|
|
+ struct trace_event_call *event;
|
|
+ struct list_head *head;
|
|
+ struct trace_seq *seq;
|
|
+ const void *ptr;
|
|
|
|
- if (WARN_ON_ONCE(!fmt))
|
|
- return;
|
|
+ trace_event = ftrace_find_event(iter->ent->type);
|
|
|
|
- if (static_branch_unlikely(&trace_no_verify))
|
|
- goto print;
|
|
+ seq = &iter->seq;
|
|
|
|
- /* Don't bother checking when doing a ftrace_dump() */
|
|
- if (iter->fmt == static_fmt_buf)
|
|
- goto print;
|
|
+ if (!trace_event) {
|
|
+ trace_seq_printf(seq, "EVENT ID %d NOT FOUND?\n", iter->ent->type);
|
|
+ return true;
|
|
+ }
|
|
|
|
- while (*p) {
|
|
- bool star = false;
|
|
- int len = 0;
|
|
-
|
|
- j = 0;
|
|
-
|
|
- /* We only care about %s and variants */
|
|
- for (i = 0; p[i]; i++) {
|
|
- if (i + 1 >= iter->fmt_size) {
|
|
- /*
|
|
- * If we can't expand the copy buffer,
|
|
- * just print it.
|
|
- */
|
|
- if (!trace_iter_expand_format(iter))
|
|
- goto print;
|
|
- }
|
|
+ event = container_of(trace_event, struct trace_event_call, event);
|
|
+ if (!(event->flags & TRACE_EVENT_FL_TEST_STR))
|
|
+ return false;
|
|
|
|
- if (p[i] == '\\' && p[i+1]) {
|
|
- i++;
|
|
- continue;
|
|
- }
|
|
- if (p[i] == '%') {
|
|
- /* Need to test cases like %08.*s */
|
|
- for (j = 1; p[i+j]; j++) {
|
|
- if (isdigit(p[i+j]) ||
|
|
- p[i+j] == '.')
|
|
- continue;
|
|
- if (p[i+j] == '*') {
|
|
- star = true;
|
|
- continue;
|
|
- }
|
|
- break;
|
|
- }
|
|
- if (p[i+j] == 's')
|
|
- break;
|
|
- star = false;
|
|
- }
|
|
- j = 0;
|
|
- }
|
|
- /* If no %s found then just print normally */
|
|
- if (!p[i])
|
|
- break;
|
|
+ head = trace_get_fields(event);
|
|
+ if (!head) {
|
|
+ trace_seq_printf(seq, "FIELDS FOR EVENT '%s' NOT FOUND?\n",
|
|
+ trace_event_name(event));
|
|
+ return true;
|
|
+ }
|
|
|
|
- /* Copy up to the %s, and print that */
|
|
- strncpy(iter->fmt, p, i);
|
|
- iter->fmt[i] = '\0';
|
|
- trace_seq_vprintf(&iter->seq, iter->fmt, ap);
|
|
+ /* Offsets are from the iter->ent that points to the raw event */
|
|
+ ptr = iter->ent;
|
|
|
|
- /*
|
|
- * If iter->seq is full, the above call no longer guarantees
|
|
- * that ap is in sync with fmt processing, and further calls
|
|
- * to va_arg() can return wrong positional arguments.
|
|
- *
|
|
- * Ensure that ap is no longer used in this case.
|
|
- */
|
|
- if (iter->seq.full) {
|
|
- p = "";
|
|
- break;
|
|
- }
|
|
+ list_for_each_entry(field, head, link) {
|
|
+ const char *str;
|
|
+ bool good;
|
|
+
|
|
+ if (!field->needs_test)
|
|
+ continue;
|
|
|
|
- if (star)
|
|
- len = va_arg(ap, int);
|
|
+ str = *(const char **)(ptr + field->offset);
|
|
|
|
- /* The ap now points to the string data of the %s */
|
|
- str = va_arg(ap, const char *);
|
|
+ good = trace_safe_str(iter, str);
|
|
|
|
/*
|
|
* If you hit this warning, it is likely that the
|
|
@@ -3956,45 +3878,14 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
|
|
* instead. See samples/trace_events/trace-events-sample.h
|
|
* for reference.
|
|
*/
|
|
- if (WARN_ONCE(!trace_safe_str(iter, str, star, len),
|
|
- "fmt: '%s' current_buffer: '%s'",
|
|
- fmt, show_buffer(&iter->seq))) {
|
|
- int ret;
|
|
-
|
|
- /* Try to safely read the string */
|
|
- if (star) {
|
|
- if (len + 1 > iter->fmt_size)
|
|
- len = iter->fmt_size - 1;
|
|
- if (len < 0)
|
|
- len = 0;
|
|
- ret = copy_from_kernel_nofault(iter->fmt, str, len);
|
|
- iter->fmt[len] = 0;
|
|
- star = false;
|
|
- } else {
|
|
- ret = strncpy_from_kernel_nofault(iter->fmt, str,
|
|
- iter->fmt_size);
|
|
- }
|
|
- if (ret < 0)
|
|
- trace_seq_printf(&iter->seq, "(0x%px)", str);
|
|
- else
|
|
- trace_seq_printf(&iter->seq, "(0x%px:%s)",
|
|
- str, iter->fmt);
|
|
- str = "[UNSAFE-MEMORY]";
|
|
- strcpy(iter->fmt, "%s");
|
|
- } else {
|
|
- strncpy(iter->fmt, p + i, j + 1);
|
|
- iter->fmt[j+1] = '\0';
|
|
+ if (WARN_ONCE(!good, "event '%s' has unsafe pointer field '%s'",
|
|
+ trace_event_name(event), field->name)) {
|
|
+ trace_seq_printf(seq, "EVENT %s: HAS UNSAFE POINTER FIELD '%s'\n",
|
|
+ trace_event_name(event), field->name);
|
|
+ return true;
|
|
}
|
|
- if (star)
|
|
- trace_seq_printf(&iter->seq, iter->fmt, len, str);
|
|
- else
|
|
- trace_seq_printf(&iter->seq, iter->fmt, str);
|
|
-
|
|
- p += i + j + 1;
|
|
}
|
|
- print:
|
|
- if (*p)
|
|
- trace_seq_vprintf(&iter->seq, p, ap);
|
|
+ return false;
|
|
}
|
|
|
|
const char *trace_event_format(struct trace_iterator *iter, const char *fmt)
|
|
@@ -7011,7 +6902,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
|
|
|
|
/* Now copy what we have to the user */
|
|
sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
|
|
- if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq))
|
|
+ if (iter->seq.readpos >= trace_seq_used(&iter->seq))
|
|
trace_seq_init(&iter->seq);
|
|
|
|
/*
|
|
@@ -10539,8 +10430,6 @@ __init static int tracer_alloc_buffers(void)
|
|
|
|
register_snapshot_cmd();
|
|
|
|
- test_can_verify();
|
|
-
|
|
return 0;
|
|
|
|
out_free_pipe_cpumask:
|
|
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
|
|
index 3db42bae73f8e0..e45756f1ac2b12 100644
|
|
--- a/kernel/trace/trace.h
|
|
+++ b/kernel/trace/trace.h
|
|
@@ -644,9 +644,8 @@ void trace_buffer_unlock_commit_nostack(struct trace_buffer *buffer,
|
|
|
|
bool trace_is_tracepoint_string(const char *str);
|
|
const char *trace_event_format(struct trace_iterator *iter, const char *fmt);
|
|
-void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
|
|
- va_list ap) __printf(2, 0);
|
|
char *trace_iter_expand_format(struct trace_iterator *iter);
|
|
+bool ignore_event(struct trace_iterator *iter);
|
|
|
|
int trace_empty(struct trace_iterator *iter);
|
|
|
|
@@ -1323,7 +1322,8 @@ struct ftrace_event_field {
|
|
int filter_type;
|
|
int offset;
|
|
int size;
|
|
- int is_signed;
|
|
+ unsigned int is_signed:1;
|
|
+ unsigned int needs_test:1;
|
|
int len;
|
|
};
|
|
|
|
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
|
|
index 64cd856308e77c..9d22745cdea5aa 100644
|
|
--- a/kernel/trace/trace_events.c
|
|
+++ b/kernel/trace/trace_events.c
|
|
@@ -82,7 +82,7 @@ static int system_refcount_dec(struct event_subsystem *system)
|
|
}
|
|
|
|
static struct ftrace_event_field *
|
|
-__find_event_field(struct list_head *head, char *name)
|
|
+__find_event_field(struct list_head *head, const char *name)
|
|
{
|
|
struct ftrace_event_field *field;
|
|
|
|
@@ -114,7 +114,8 @@ trace_find_event_field(struct trace_event_call *call, char *name)
|
|
|
|
static int __trace_define_field(struct list_head *head, const char *type,
|
|
const char *name, int offset, int size,
|
|
- int is_signed, int filter_type, int len)
|
|
+ int is_signed, int filter_type, int len,
|
|
+ int need_test)
|
|
{
|
|
struct ftrace_event_field *field;
|
|
|
|
@@ -133,6 +134,7 @@ static int __trace_define_field(struct list_head *head, const char *type,
|
|
field->offset = offset;
|
|
field->size = size;
|
|
field->is_signed = is_signed;
|
|
+ field->needs_test = need_test;
|
|
field->len = len;
|
|
|
|
list_add(&field->link, head);
|
|
@@ -151,13 +153,13 @@ int trace_define_field(struct trace_event_call *call, const char *type,
|
|
|
|
head = trace_get_fields(call);
|
|
return __trace_define_field(head, type, name, offset, size,
|
|
- is_signed, filter_type, 0);
|
|
+ is_signed, filter_type, 0, 0);
|
|
}
|
|
EXPORT_SYMBOL_GPL(trace_define_field);
|
|
|
|
static int trace_define_field_ext(struct trace_event_call *call, const char *type,
|
|
const char *name, int offset, int size, int is_signed,
|
|
- int filter_type, int len)
|
|
+ int filter_type, int len, int need_test)
|
|
{
|
|
struct list_head *head;
|
|
|
|
@@ -166,13 +168,13 @@ static int trace_define_field_ext(struct trace_event_call *call, const char *typ
|
|
|
|
head = trace_get_fields(call);
|
|
return __trace_define_field(head, type, name, offset, size,
|
|
- is_signed, filter_type, len);
|
|
+ is_signed, filter_type, len, need_test);
|
|
}
|
|
|
|
#define __generic_field(type, item, filter_type) \
|
|
ret = __trace_define_field(&ftrace_generic_fields, #type, \
|
|
#item, 0, 0, is_signed_type(type), \
|
|
- filter_type, 0); \
|
|
+ filter_type, 0, 0); \
|
|
if (ret) \
|
|
return ret;
|
|
|
|
@@ -181,7 +183,8 @@ static int trace_define_field_ext(struct trace_event_call *call, const char *typ
|
|
"common_" #item, \
|
|
offsetof(typeof(ent), item), \
|
|
sizeof(ent.item), \
|
|
- is_signed_type(type), FILTER_OTHER, 0); \
|
|
+ is_signed_type(type), FILTER_OTHER, \
|
|
+ 0, 0); \
|
|
if (ret) \
|
|
return ret;
|
|
|
|
@@ -332,6 +335,7 @@ static bool process_pointer(const char *fmt, int len, struct trace_event_call *c
|
|
/* Return true if the string is safe */
|
|
static bool process_string(const char *fmt, int len, struct trace_event_call *call)
|
|
{
|
|
+ struct trace_event_fields *field;
|
|
const char *r, *e, *s;
|
|
|
|
e = fmt + len;
|
|
@@ -360,6 +364,18 @@ static bool process_string(const char *fmt, int len, struct trace_event_call *ca
|
|
s = r + 1;
|
|
} while (s < e);
|
|
|
|
+ /*
|
|
+ * Check for arrays. If the argument has: foo[REC->val]
|
|
+ * then it is very likely that foo is an array of strings
|
|
+ * that are safe to use.
|
|
+ */
|
|
+ r = strstr(s, "[");
|
|
+ if (r && r < e) {
|
|
+ r = strstr(r, "REC->");
|
|
+ if (r && r < e)
|
|
+ return true;
|
|
+ }
|
|
+
|
|
/*
|
|
* If there's any strings in the argument consider this arg OK as it
|
|
* could be: REC->field ? "foo" : "bar" and we don't want to get into
|
|
@@ -372,8 +388,16 @@ static bool process_string(const char *fmt, int len, struct trace_event_call *ca
|
|
if (process_pointer(fmt, len, call))
|
|
return true;
|
|
|
|
- /* Make sure the field is found, and consider it OK for now if it is */
|
|
- return find_event_field(fmt, call) != NULL;
|
|
+ /* Make sure the field is found */
|
|
+ field = find_event_field(fmt, call);
|
|
+ if (!field)
|
|
+ return false;
|
|
+
|
|
+ /* Test this field's string before printing the event */
|
|
+ call->flags |= TRACE_EVENT_FL_TEST_STR;
|
|
+ field->needs_test = 1;
|
|
+
|
|
+ return true;
|
|
}
|
|
|
|
/*
|
|
@@ -2552,7 +2576,7 @@ event_define_fields(struct trace_event_call *call)
|
|
ret = trace_define_field_ext(call, field->type, field->name,
|
|
offset, field->size,
|
|
field->is_signed, field->filter_type,
|
|
- field->len);
|
|
+ field->len, field->needs_test);
|
|
if (WARN_ON_ONCE(ret)) {
|
|
pr_err("error code is %d\n", ret);
|
|
break;
|
|
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
|
|
index db575094c49825..2b948d35fb59ea 100644
|
|
--- a/kernel/trace/trace_output.c
|
|
+++ b/kernel/trace/trace_output.c
|
|
@@ -317,10 +317,14 @@ EXPORT_SYMBOL(trace_raw_output_prep);
|
|
|
|
void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...)
|
|
{
|
|
+ struct trace_seq *s = &iter->seq;
|
|
va_list ap;
|
|
|
|
+ if (ignore_event(iter))
|
|
+ return;
|
|
+
|
|
va_start(ap, fmt);
|
|
- trace_check_vprintf(iter, trace_event_format(iter, fmt), ap);
|
|
+ trace_seq_vprintf(s, trace_event_format(iter, fmt), ap);
|
|
va_end(ap);
|
|
}
|
|
EXPORT_SYMBOL(trace_event_printf);
|
|
diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c
|
|
index bac06ee3b98b81..7be97229ddf860 100644
|
|
--- a/kernel/trace/trace_seq.c
|
|
+++ b/kernel/trace/trace_seq.c
|
|
@@ -370,8 +370,12 @@ EXPORT_SYMBOL_GPL(trace_seq_path);
|
|
*/
|
|
int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
|
|
{
|
|
+ int ret;
|
|
__trace_seq_init(s);
|
|
- return seq_buf_to_user(&s->seq, ubuf, cnt);
|
|
+ ret = seq_buf_to_user(&s->seq, ubuf, s->readpos, cnt);
|
|
+ if (ret > 0)
|
|
+ s->readpos += ret;
|
|
+ return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(trace_seq_to_user);
|
|
|
|
diff --git a/lib/seq_buf.c b/lib/seq_buf.c
|
|
index 45c450f423fa87..23518f77ea9c53 100644
|
|
--- a/lib/seq_buf.c
|
|
+++ b/lib/seq_buf.c
|
|
@@ -109,9 +109,7 @@ void seq_buf_do_printk(struct seq_buf *s, const char *lvl)
|
|
if (s->size == 0 || s->len == 0)
|
|
return;
|
|
|
|
- seq_buf_terminate(s);
|
|
-
|
|
- start = s->buffer;
|
|
+ start = seq_buf_str(s);
|
|
while ((lf = strchr(start, '\n'))) {
|
|
int len = lf - start + 1;
|
|
|
|
@@ -324,23 +322,24 @@ int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc)
|
|
* seq_buf_to_user - copy the sequence buffer to user space
|
|
* @s: seq_buf descriptor
|
|
* @ubuf: The userspace memory location to copy to
|
|
+ * @start: The first byte in the buffer to copy
|
|
* @cnt: The amount to copy
|
|
*
|
|
* Copies the sequence buffer into the userspace memory pointed to
|
|
- * by @ubuf. It starts from the last read position (@s->readpos)
|
|
- * and writes up to @cnt characters or till it reaches the end of
|
|
- * the content in the buffer (@s->len), which ever comes first.
|
|
+ * by @ubuf. It starts from @start and writes up to @cnt characters
|
|
+ * or until it reaches the end of the content in the buffer (@s->len),
|
|
+ * whichever comes first.
|
|
*
|
|
* On success, it returns a positive number of the number of bytes
|
|
* it copied.
|
|
*
|
|
* On failure it returns -EBUSY if all of the content in the
|
|
* sequence has been already read, which includes nothing in the
|
|
- * sequence (@s->len == @s->readpos).
|
|
+ * sequence (@s->len == @start).
|
|
*
|
|
* Returns -EFAULT if the copy to userspace fails.
|
|
*/
|
|
-int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt)
|
|
+int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, size_t start, int cnt)
|
|
{
|
|
int len;
|
|
int ret;
|
|
@@ -350,20 +349,17 @@ int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt)
|
|
|
|
len = seq_buf_used(s);
|
|
|
|
- if (len <= s->readpos)
|
|
+ if (len <= start)
|
|
return -EBUSY;
|
|
|
|
- len -= s->readpos;
|
|
+ len -= start;
|
|
if (cnt > len)
|
|
cnt = len;
|
|
- ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
|
|
+ ret = copy_to_user(ubuf, s->buffer + start, cnt);
|
|
if (ret == cnt)
|
|
return -EFAULT;
|
|
|
|
- cnt -= ret;
|
|
-
|
|
- s->readpos += cnt;
|
|
- return cnt;
|
|
+ return cnt - ret;
|
|
}
|
|
|
|
/**
|
|
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
|
|
index 54c2c90d3abc9d..5811a11cc53a6d 100644
|
|
--- a/mm/kmemleak.c
|
|
+++ b/mm/kmemleak.c
|
|
@@ -368,7 +368,7 @@ static void print_unreferenced(struct seq_file *seq,
|
|
|
|
for (i = 0; i < nr_entries; i++) {
|
|
void *ptr = (void *)entries[i];
|
|
- warn_or_seq_printf(seq, " [<%pK>] %pS\n", ptr, ptr);
|
|
+ warn_or_seq_printf(seq, " %pS\n", ptr);
|
|
}
|
|
}
|
|
|
|
diff --git a/mm/memblock.c b/mm/memblock.c
|
|
index d630f5c2bdb90e..87a2b4340ce4ea 100644
|
|
--- a/mm/memblock.c
|
|
+++ b/mm/memblock.c
|
|
@@ -735,6 +735,40 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
|
|
return memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0);
|
|
}
|
|
|
|
+/**
|
|
+ * memblock_validate_numa_coverage - check if amount of memory with
|
|
+ * no node ID assigned is less than a threshold
|
|
+ * @threshold_bytes: maximal memory size that can have unassigned node
|
|
+ * ID (in bytes).
|
|
+ *
|
|
+ * A buggy firmware may report memory that does not belong to any node.
|
|
+ * Check if amount of such memory is below @threshold_bytes.
|
|
+ *
|
|
+ * Return: true on success, false on failure.
|
|
+ */
|
|
+bool __init_memblock memblock_validate_numa_coverage(unsigned long threshold_bytes)
|
|
+{
|
|
+ unsigned long nr_pages = 0;
|
|
+ unsigned long start_pfn, end_pfn, mem_size_mb;
|
|
+ int nid, i;
|
|
+
|
|
+ /* calculate lose page */
|
|
+ for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid) {
|
|
+ if (nid == NUMA_NO_NODE)
|
|
+ nr_pages += end_pfn - start_pfn;
|
|
+ }
|
|
+
|
|
+ if ((nr_pages << PAGE_SHIFT) > threshold_bytes) {
|
|
+ mem_size_mb = memblock_phys_mem_size() >> 20;
|
|
+ pr_err("NUMA: no nodes coverage for %luMB of %luMB RAM\n",
|
|
+ (nr_pages << PAGE_SHIFT) >> 20, mem_size_mb);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+
|
|
/**
|
|
* memblock_isolate_range - isolate given range into disjoint memblocks
|
|
* @type: memblock type to isolate range for
|
|
diff --git a/mm/readahead.c b/mm/readahead.c
|
|
index e9b11d928b0c48..f1595c032ce7e3 100644
|
|
--- a/mm/readahead.c
|
|
+++ b/mm/readahead.c
|
|
@@ -580,7 +580,11 @@ static void ondemand_readahead(struct readahead_control *ractl,
|
|
1UL << order);
|
|
if (index == expected || index == (ra->start + ra->size)) {
|
|
ra->start += ra->size;
|
|
- ra->size = get_next_ra_size(ra, max_pages);
|
|
+ /*
|
|
+ * In the case of MADV_HUGEPAGE, the actual size might exceed
|
|
+ * the readahead window.
|
|
+ */
|
|
+ ra->size = max(ra->size, get_next_ra_size(ra, max_pages));
|
|
ra->async_size = ra->size;
|
|
goto readit;
|
|
}
|
|
diff --git a/mm/vmscan.c b/mm/vmscan.c
|
|
index 3c91b86d59e935..49456b72575529 100644
|
|
--- a/mm/vmscan.c
|
|
+++ b/mm/vmscan.c
|
|
@@ -641,7 +641,14 @@ unsigned long zone_reclaimable_pages(struct zone *zone)
|
|
if (can_reclaim_anon_pages(NULL, zone_to_nid(zone), NULL))
|
|
nr += zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_ANON) +
|
|
zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_ANON);
|
|
-
|
|
+ /*
|
|
+ * If there are no reclaimable file-backed or anonymous pages,
|
|
+ * ensure zones with sufficient free pages are not skipped.
|
|
+ * This prevents zones like DMA32 from being ignored in reclaim
|
|
+ * scenarios where they can still help alleviate memory pressure.
|
|
+ */
|
|
+ if (nr == 0)
|
|
+ nr = zone_page_state_snapshot(zone, NR_FREE_PAGES);
|
|
return nr;
|
|
}
|
|
|
|
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
|
|
index 6178ae8feafc0f..549ee9e87d6366 100644
|
|
--- a/net/bluetooth/hci_conn.c
|
|
+++ b/net/bluetooth/hci_conn.c
|
|
@@ -2178,13 +2178,9 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
|
|
conn->iso_qos.bcast.big);
|
|
if (parent && parent != conn) {
|
|
link = hci_conn_link(parent, conn);
|
|
- if (!link) {
|
|
- hci_conn_drop(conn);
|
|
- return ERR_PTR(-ENOLINK);
|
|
- }
|
|
-
|
|
- /* Link takes the refcount */
|
|
hci_conn_drop(conn);
|
|
+ if (!link)
|
|
+ return ERR_PTR(-ENOLINK);
|
|
}
|
|
|
|
return conn;
|
|
@@ -2274,15 +2270,12 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
|
|
}
|
|
|
|
link = hci_conn_link(le, cis);
|
|
+ hci_conn_drop(cis);
|
|
if (!link) {
|
|
hci_conn_drop(le);
|
|
- hci_conn_drop(cis);
|
|
return ERR_PTR(-ENOLINK);
|
|
}
|
|
|
|
- /* Link takes the refcount */
|
|
- hci_conn_drop(cis);
|
|
-
|
|
cis->state = BT_CONNECT;
|
|
|
|
hci_le_create_cis_pending(hdev);
|
|
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
|
|
index 30519d47e8a695..f29fd326440115 100644
|
|
--- a/net/bluetooth/hci_core.c
|
|
+++ b/net/bluetooth/hci_core.c
|
|
@@ -58,7 +58,6 @@ DEFINE_RWLOCK(hci_dev_list_lock);
|
|
|
|
/* HCI callback list */
|
|
LIST_HEAD(hci_cb_list);
|
|
-DEFINE_MUTEX(hci_cb_list_lock);
|
|
|
|
/* HCI ID Numbering */
|
|
static DEFINE_IDA(hci_index_ida);
|
|
@@ -2957,9 +2956,7 @@ int hci_register_cb(struct hci_cb *cb)
|
|
{
|
|
BT_DBG("%p name %s", cb, cb->name);
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_add_tail(&cb->list, &hci_cb_list);
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
+ list_add_tail_rcu(&cb->list, &hci_cb_list);
|
|
|
|
return 0;
|
|
}
|
|
@@ -2969,9 +2966,8 @@ int hci_unregister_cb(struct hci_cb *cb)
|
|
{
|
|
BT_DBG("%p name %s", cb, cb->name);
|
|
|
|
- mutex_lock(&hci_cb_list_lock);
|
|
- list_del(&cb->list);
|
|
- mutex_unlock(&hci_cb_list_lock);
|
|
+ list_del_rcu(&cb->list);
|
|
+ synchronize_rcu();
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
|
|
index b94d202bf3745c..f165cafa3aa98b 100644
|
|
--- a/net/bluetooth/iso.c
|
|
+++ b/net/bluetooth/iso.c
|
|
@@ -1929,6 +1929,11 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|
return lm;
|
|
}
|
|
|
|
+static bool iso_match(struct hci_conn *hcon)
|
|
+{
|
|
+ return hcon->type == ISO_LINK || hcon->type == LE_LINK;
|
|
+}
|
|
+
|
|
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
|
|
{
|
|
if (hcon->type != ISO_LINK) {
|
|
@@ -2110,6 +2115,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
|
|
|
|
static struct hci_cb iso_cb = {
|
|
.name = "ISO",
|
|
+ .match = iso_match,
|
|
.connect_cfm = iso_connect_cfm,
|
|
.disconn_cfm = iso_disconn_cfm,
|
|
};
|
|
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
|
|
index 93651c421767a0..acb148759bd049 100644
|
|
--- a/net/bluetooth/l2cap_core.c
|
|
+++ b/net/bluetooth/l2cap_core.c
|
|
@@ -7223,6 +7223,11 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
|
|
return NULL;
|
|
}
|
|
|
|
+static bool l2cap_match(struct hci_conn *hcon)
|
|
+{
|
|
+ return hcon->type == ACL_LINK || hcon->type == LE_LINK;
|
|
+}
|
|
+
|
|
static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
|
{
|
|
struct hci_dev *hdev = hcon->hdev;
|
|
@@ -7230,9 +7235,6 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
|
|
struct l2cap_chan *pchan;
|
|
u8 dst_type;
|
|
|
|
- if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
|
|
- return;
|
|
-
|
|
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
|
|
|
|
if (status) {
|
|
@@ -7297,9 +7299,6 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
|
|
|
|
static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
|
|
{
|
|
- if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
|
|
- return;
|
|
-
|
|
BT_DBG("hcon %p reason %d", hcon, reason);
|
|
|
|
l2cap_conn_del(hcon, bt_to_errno(reason));
|
|
@@ -7578,6 +7577,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
|
|
|
|
static struct hci_cb l2cap_cb = {
|
|
.name = "L2CAP",
|
|
+ .match = l2cap_match,
|
|
.connect_cfm = l2cap_connect_cfm,
|
|
.disconn_cfm = l2cap_disconn_cfm,
|
|
.security_cfm = l2cap_security_cfm,
|
|
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
|
|
index 1d34d849703329..9d46afb24caf07 100644
|
|
--- a/net/bluetooth/rfcomm/core.c
|
|
+++ b/net/bluetooth/rfcomm/core.c
|
|
@@ -2134,6 +2134,11 @@ static int rfcomm_run(void *unused)
|
|
return 0;
|
|
}
|
|
|
|
+static bool rfcomm_match(struct hci_conn *hcon)
|
|
+{
|
|
+ return hcon->type == ACL_LINK;
|
|
+}
|
|
+
|
|
static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
|
|
{
|
|
struct rfcomm_session *s;
|
|
@@ -2180,6 +2185,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
|
|
|
|
static struct hci_cb rfcomm_cb = {
|
|
.name = "RFCOMM",
|
|
+ .match = rfcomm_match,
|
|
.security_cfm = rfcomm_security_cfm
|
|
};
|
|
|
|
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
|
|
index 64d4d57c7033a3..c4c36ff25fb202 100644
|
|
--- a/net/bluetooth/sco.c
|
|
+++ b/net/bluetooth/sco.c
|
|
@@ -1353,11 +1353,13 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
|
|
return lm;
|
|
}
|
|
|
|
-static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
|
+static bool sco_match(struct hci_conn *hcon)
|
|
{
|
|
- if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
|
|
- return;
|
|
+ return hcon->type == SCO_LINK || hcon->type == ESCO_LINK;
|
|
+}
|
|
|
|
+static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
|
+{
|
|
BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status);
|
|
|
|
if (!status) {
|
|
@@ -1372,9 +1374,6 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
|
|
|
|
static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
|
|
{
|
|
- if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
|
|
- return;
|
|
-
|
|
BT_DBG("hcon %p reason %d", hcon, reason);
|
|
|
|
sco_conn_del(hcon, bt_to_errno(reason));
|
|
@@ -1400,6 +1399,7 @@ void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
|
|
|
|
static struct hci_cb sco_cb = {
|
|
.name = "SCO",
|
|
+ .match = sco_match,
|
|
.connect_cfm = sco_connect_cfm,
|
|
.disconn_cfm = sco_disconn_cfm,
|
|
};
|
|
diff --git a/net/core/dev.c b/net/core/dev.c
|
|
index 4beb9acf2c1839..69da7b009f8b98 100644
|
|
--- a/net/core/dev.c
|
|
+++ b/net/core/dev.c
|
|
@@ -3628,8 +3628,10 @@ int skb_csum_hwoffload_help(struct sk_buff *skb,
|
|
|
|
if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
|
|
if (vlan_get_protocol(skb) == htons(ETH_P_IPV6) &&
|
|
- skb_network_header_len(skb) != sizeof(struct ipv6hdr))
|
|
+ skb_network_header_len(skb) != sizeof(struct ipv6hdr) &&
|
|
+ !ipv6_has_hopopt_jumbo(skb))
|
|
goto sw_checksum;
|
|
+
|
|
switch (skb->csum_offset) {
|
|
case offsetof(struct tcphdr, check):
|
|
case offsetof(struct udphdr, check):
|
|
diff --git a/net/core/sock.c b/net/core/sock.c
|
|
index bc2a4e38dcea8e..84ba3f67bca97b 100644
|
|
--- a/net/core/sock.c
|
|
+++ b/net/core/sock.c
|
|
@@ -1133,7 +1133,10 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
|
|
sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE);
|
|
break;
|
|
case SO_REUSEPORT:
|
|
- sk->sk_reuseport = valbool;
|
|
+ if (valbool && !sk_is_inet(sk))
|
|
+ ret = -EOPNOTSUPP;
|
|
+ else
|
|
+ sk->sk_reuseport = valbool;
|
|
break;
|
|
case SO_TYPE:
|
|
case SO_PROTOCOL:
|
|
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
|
|
index 72b2d68ef4da5f..dd1803bf9c5c63 100644
|
|
--- a/net/ipv4/ip_tunnel.c
|
|
+++ b/net/ipv4/ip_tunnel.c
|
|
@@ -43,6 +43,7 @@
|
|
#include <net/rtnetlink.h>
|
|
#include <net/udp.h>
|
|
#include <net/dst_metadata.h>
|
|
+#include <net/inet_dscp.h>
|
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
#include <net/ipv6.h>
|
|
@@ -102,10 +103,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
|
|
if (!ip_tunnel_key_match(&t->parms, flags, key))
|
|
continue;
|
|
|
|
- if (t->parms.link == link)
|
|
+ if (READ_ONCE(t->parms.link) == link)
|
|
return t;
|
|
- else
|
|
- cand = t;
|
|
+ cand = t;
|
|
}
|
|
|
|
hlist_for_each_entry_rcu(t, head, hash_node) {
|
|
@@ -117,9 +117,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
|
|
if (!ip_tunnel_key_match(&t->parms, flags, key))
|
|
continue;
|
|
|
|
- if (t->parms.link == link)
|
|
+ if (READ_ONCE(t->parms.link) == link)
|
|
return t;
|
|
- else if (!cand)
|
|
+ if (!cand)
|
|
cand = t;
|
|
}
|
|
|
|
@@ -137,9 +137,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
|
|
if (!ip_tunnel_key_match(&t->parms, flags, key))
|
|
continue;
|
|
|
|
- if (t->parms.link == link)
|
|
+ if (READ_ONCE(t->parms.link) == link)
|
|
return t;
|
|
- else if (!cand)
|
|
+ if (!cand)
|
|
cand = t;
|
|
}
|
|
|
|
@@ -150,9 +150,9 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
|
|
!(t->dev->flags & IFF_UP))
|
|
continue;
|
|
|
|
- if (t->parms.link == link)
|
|
+ if (READ_ONCE(t->parms.link) == link)
|
|
return t;
|
|
- else if (!cand)
|
|
+ if (!cand)
|
|
cand = t;
|
|
}
|
|
|
|
@@ -221,7 +221,7 @@ static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
|
|
hlist_for_each_entry_rcu(t, head, hash_node) {
|
|
if (local == t->parms.iph.saddr &&
|
|
remote == t->parms.iph.daddr &&
|
|
- link == t->parms.link &&
|
|
+ link == READ_ONCE(t->parms.link) &&
|
|
type == t->dev->type &&
|
|
ip_tunnel_key_match(&t->parms, flags, key))
|
|
break;
|
|
@@ -294,7 +294,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
|
|
|
|
ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
|
|
iph->saddr, tunnel->parms.o_key,
|
|
- RT_TOS(iph->tos), dev_net(dev),
|
|
+ iph->tos & INET_DSCP_MASK, tunnel->net,
|
|
tunnel->parms.link, tunnel->fwmark, 0, 0);
|
|
rt = ip_route_output_key(tunnel->net, &fl4);
|
|
|
|
@@ -610,9 +610,9 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
|
tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
|
|
}
|
|
ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
|
|
- tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
|
|
- dev_net(dev), 0, skb->mark, skb_get_hash(skb),
|
|
- key->flow_flags);
|
|
+ tunnel_id_to_key32(key->tun_id),
|
|
+ tos & INET_DSCP_MASK, tunnel->net, 0, skb->mark,
|
|
+ skb_get_hash(skb), key->flow_flags);
|
|
|
|
if (!tunnel_hlen)
|
|
tunnel_hlen = ip_encap_hlen(&tun_info->encap);
|
|
@@ -773,8 +773,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
|
}
|
|
|
|
ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
|
|
- tunnel->parms.o_key, RT_TOS(tos),
|
|
- dev_net(dev), tunnel->parms.link,
|
|
+ tunnel->parms.o_key, tos & INET_DSCP_MASK,
|
|
+ tunnel->net, READ_ONCE(tunnel->parms.link),
|
|
tunnel->fwmark, skb_get_hash(skb), 0);
|
|
|
|
if (ip_tunnel_encap(skb, &tunnel->encap, &protocol, &fl4) < 0)
|
|
@@ -894,7 +894,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
|
|
if (t->parms.link != p->link || t->fwmark != fwmark) {
|
|
int mtu;
|
|
|
|
- t->parms.link = p->link;
|
|
+ WRITE_ONCE(t->parms.link, p->link);
|
|
t->fwmark = fwmark;
|
|
mtu = ip_tunnel_bind_dev(dev);
|
|
if (set_mtu)
|
|
@@ -1084,9 +1084,9 @@ EXPORT_SYMBOL(ip_tunnel_get_link_net);
|
|
|
|
int ip_tunnel_get_iflink(const struct net_device *dev)
|
|
{
|
|
- struct ip_tunnel *tunnel = netdev_priv(dev);
|
|
+ const struct ip_tunnel *tunnel = netdev_priv(dev);
|
|
|
|
- return tunnel->parms.link;
|
|
+ return READ_ONCE(tunnel->parms.link);
|
|
}
|
|
EXPORT_SYMBOL(ip_tunnel_get_iflink);
|
|
|
|
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
|
|
index fb053942dba2a1..f6a213bae5cccb 100644
|
|
--- a/net/ipv4/tcp_input.c
|
|
+++ b/net/ipv4/tcp_input.c
|
|
@@ -7192,6 +7192,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
|
|
if (unlikely(!inet_csk_reqsk_queue_hash_add(sk, req,
|
|
req->timeout))) {
|
|
reqsk_free(req);
|
|
+ dst_release(dst);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
|
|
index 534a4498e280d7..fff09f5a796a75 100644
|
|
--- a/net/ipv6/ila/ila_xlat.c
|
|
+++ b/net/ipv6/ila/ila_xlat.c
|
|
@@ -200,6 +200,8 @@ static const struct nf_hook_ops ila_nf_hook_ops[] = {
|
|
},
|
|
};
|
|
|
|
+static DEFINE_MUTEX(ila_mutex);
|
|
+
|
|
static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
|
|
{
|
|
struct ila_net *ilan = net_generic(net, ila_net_id);
|
|
@@ -207,16 +209,20 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
|
|
spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
|
|
int err = 0, order;
|
|
|
|
- if (!ilan->xlat.hooks_registered) {
|
|
+ if (!READ_ONCE(ilan->xlat.hooks_registered)) {
|
|
/* We defer registering net hooks in the namespace until the
|
|
* first mapping is added.
|
|
*/
|
|
- err = nf_register_net_hooks(net, ila_nf_hook_ops,
|
|
- ARRAY_SIZE(ila_nf_hook_ops));
|
|
+ mutex_lock(&ila_mutex);
|
|
+ if (!ilan->xlat.hooks_registered) {
|
|
+ err = nf_register_net_hooks(net, ila_nf_hook_ops,
|
|
+ ARRAY_SIZE(ila_nf_hook_ops));
|
|
+ if (!err)
|
|
+ WRITE_ONCE(ilan->xlat.hooks_registered, true);
|
|
+ }
|
|
+ mutex_unlock(&ila_mutex);
|
|
if (err)
|
|
return err;
|
|
-
|
|
- ilan->xlat.hooks_registered = true;
|
|
}
|
|
|
|
ila = kzalloc(sizeof(*ila), GFP_KERNEL);
|
|
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
|
|
index 51bccfb00a9cd9..61b0159b2fbee6 100644
|
|
--- a/net/llc/llc_input.c
|
|
+++ b/net/llc/llc_input.c
|
|
@@ -124,8 +124,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
|
|
if (unlikely(!pskb_may_pull(skb, llc_len)))
|
|
return 0;
|
|
|
|
- skb->transport_header += llc_len;
|
|
skb_pull(skb, llc_len);
|
|
+ skb_reset_transport_header(skb);
|
|
if (skb->protocol == htons(ETH_P_802_2)) {
|
|
__be16 pdulen;
|
|
s32 data_size;
|
|
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
|
|
index daea061d0fc136..04c876d78d3bf0 100644
|
|
--- a/net/mac80211/ieee80211_i.h
|
|
+++ b/net/mac80211/ieee80211_i.h
|
|
@@ -2057,8 +2057,6 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
|
u32 info_flags,
|
|
u32 ctrl_flags,
|
|
u64 *cookie);
|
|
-void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
|
|
- struct sk_buff_head *skbs);
|
|
struct sk_buff *
|
|
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
|
struct sk_buff *skb, u32 info_flags);
|
|
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
|
|
index 25223184d6e5b0..a5e7edd2f2d137 100644
|
|
--- a/net/mac80211/mesh.c
|
|
+++ b/net/mac80211/mesh.c
|
|
@@ -1173,14 +1173,14 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
|
u64 changed)
|
|
{
|
|
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
|
- unsigned long bits = changed;
|
|
+ unsigned long bits[] = { BITMAP_FROM_U64(changed) };
|
|
u32 bit;
|
|
|
|
- if (!bits)
|
|
+ if (!changed)
|
|
return;
|
|
|
|
/* if we race with running work, worst case this work becomes a noop */
|
|
- for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
|
|
+ for_each_set_bit(bit, bits, sizeof(changed) * BITS_PER_BYTE)
|
|
set_bit(bit, ifmsh->mbss_changed);
|
|
set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
|
|
wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
|
|
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
|
|
index 44d83da60aee44..9676ed15efecc8 100644
|
|
--- a/net/mac80211/status.c
|
|
+++ b/net/mac80211/status.c
|
|
@@ -1270,3 +1270,4 @@ void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
|
|
while ((skb = __skb_dequeue(skbs)))
|
|
ieee80211_free_txskb(hw, skb);
|
|
}
|
|
+EXPORT_SYMBOL(ieee80211_purge_tx_queue);
|
|
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
|
|
index d682c32821a110..154b41af4157d0 100644
|
|
--- a/net/mac80211/util.c
|
|
+++ b/net/mac80211/util.c
|
|
@@ -827,7 +827,8 @@ static void __iterate_stations(struct ieee80211_local *local,
|
|
{
|
|
struct sta_info *sta;
|
|
|
|
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
|
|
+ list_for_each_entry_rcu(sta, &local->sta_list, list,
|
|
+ lockdep_is_held(&local->hw.wiphy->mtx)) {
|
|
if (!sta->uploaded)
|
|
continue;
|
|
|
|
@@ -848,6 +849,19 @@ void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
|
|
}
|
|
EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_atomic);
|
|
|
|
+void ieee80211_iterate_stations_mtx(struct ieee80211_hw *hw,
|
|
+ void (*iterator)(void *data,
|
|
+ struct ieee80211_sta *sta),
|
|
+ void *data)
|
|
+{
|
|
+ struct ieee80211_local *local = hw_to_local(hw);
|
|
+
|
|
+ lockdep_assert_wiphy(local->hw.wiphy);
|
|
+
|
|
+ __iterate_stations(local, iterator, data);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_mtx);
|
|
+
|
|
struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
|
|
{
|
|
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
|
@@ -2572,6 +2586,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
|
WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
|
|
else
|
|
WARN(1, "Hardware became unavailable during restart.\n");
|
|
+ ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
|
+ IEEE80211_QUEUE_STOP_REASON_SUSPEND,
|
|
+ false);
|
|
ieee80211_handle_reconfig_failure(local);
|
|
return res;
|
|
}
|
|
diff --git a/net/mctp/route.c b/net/mctp/route.c
|
|
index c6a815df9d358c..d3c1f54386efc1 100644
|
|
--- a/net/mctp/route.c
|
|
+++ b/net/mctp/route.c
|
|
@@ -334,8 +334,13 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
|
|
msk = NULL;
|
|
rc = -EINVAL;
|
|
|
|
- /* we may be receiving a locally-routed packet; drop source sk
|
|
- * accounting
|
|
+ /* We may be receiving a locally-routed packet; drop source sk
|
|
+ * accounting.
|
|
+ *
|
|
+ * From here, we will either queue the skb - either to a frag_queue, or
|
|
+ * to a receiving socket. When that succeeds, we clear the skb pointer;
|
|
+ * a non-NULL skb on exit will be otherwise unowned, and hence
|
|
+ * kfree_skb()-ed.
|
|
*/
|
|
skb_orphan(skb);
|
|
|
|
@@ -389,7 +394,9 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
|
|
* pending key.
|
|
*/
|
|
if (flags & MCTP_HDR_FLAG_EOM) {
|
|
- sock_queue_rcv_skb(&msk->sk, skb);
|
|
+ rc = sock_queue_rcv_skb(&msk->sk, skb);
|
|
+ if (!rc)
|
|
+ skb = NULL;
|
|
if (key) {
|
|
/* we've hit a pending reassembly; not much we
|
|
* can do but drop it
|
|
@@ -398,7 +405,6 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
|
|
MCTP_TRACE_KEY_REPLIED);
|
|
key = NULL;
|
|
}
|
|
- rc = 0;
|
|
goto out_unlock;
|
|
}
|
|
|
|
@@ -425,8 +431,10 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
|
|
* this function.
|
|
*/
|
|
rc = mctp_key_add(key, msk);
|
|
- if (!rc)
|
|
+ if (!rc) {
|
|
trace_mctp_key_acquire(key);
|
|
+ skb = NULL;
|
|
+ }
|
|
|
|
/* we don't need to release key->lock on exit, so
|
|
* clean up here and suppress the unlock via
|
|
@@ -444,6 +452,8 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
|
|
key = NULL;
|
|
} else {
|
|
rc = mctp_frag_queue(key, skb);
|
|
+ if (!rc)
|
|
+ skb = NULL;
|
|
}
|
|
}
|
|
|
|
@@ -458,12 +468,19 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
|
|
else
|
|
rc = mctp_frag_queue(key, skb);
|
|
|
|
+ if (rc)
|
|
+ goto out_unlock;
|
|
+
|
|
+ /* we've queued; the queue owns the skb now */
|
|
+ skb = NULL;
|
|
+
|
|
/* end of message? deliver to socket, and we're done with
|
|
* the reassembly/response key
|
|
*/
|
|
- if (!rc && flags & MCTP_HDR_FLAG_EOM) {
|
|
- sock_queue_rcv_skb(key->sk, key->reasm_head);
|
|
- key->reasm_head = NULL;
|
|
+ if (flags & MCTP_HDR_FLAG_EOM) {
|
|
+ rc = sock_queue_rcv_skb(key->sk, key->reasm_head);
|
|
+ if (!rc)
|
|
+ key->reasm_head = NULL;
|
|
__mctp_key_done_in(key, net, f, MCTP_TRACE_KEY_REPLIED);
|
|
key = NULL;
|
|
}
|
|
@@ -482,8 +499,7 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
|
|
if (any_key)
|
|
mctp_key_unref(any_key);
|
|
out:
|
|
- if (rc)
|
|
- kfree_skb(skb);
|
|
+ kfree_skb(skb);
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
|
|
index 2ad9006a157aef..2e1539027e6d33 100644
|
|
--- a/net/mptcp/options.c
|
|
+++ b/net/mptcp/options.c
|
|
@@ -667,8 +667,15 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
|
|
&echo, &drop_other_suboptions))
|
|
return false;
|
|
|
|
+ /*
|
|
+ * Later on, mptcp_write_options() will enforce mutually exclusion with
|
|
+ * DSS, bail out if such option is set and we can't drop it.
|
|
+ */
|
|
if (drop_other_suboptions)
|
|
remaining += opt_size;
|
|
+ else if (opts->suboptions & OPTION_MPTCP_DSS)
|
|
+ return false;
|
|
+
|
|
len = mptcp_add_addr_len(opts->addr.family, echo, !!opts->addr.port);
|
|
if (remaining < len)
|
|
return false;
|
|
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
|
|
index 01f6ce970918c5..07f3a9703312e5 100644
|
|
--- a/net/mptcp/protocol.c
|
|
+++ b/net/mptcp/protocol.c
|
|
@@ -528,13 +528,13 @@ static void mptcp_send_ack(struct mptcp_sock *msk)
|
|
mptcp_subflow_send_ack(mptcp_subflow_tcp_sock(subflow));
|
|
}
|
|
|
|
-static void mptcp_subflow_cleanup_rbuf(struct sock *ssk)
|
|
+static void mptcp_subflow_cleanup_rbuf(struct sock *ssk, int copied)
|
|
{
|
|
bool slow;
|
|
|
|
slow = lock_sock_fast(ssk);
|
|
if (tcp_can_send_ack(ssk))
|
|
- tcp_cleanup_rbuf(ssk, 1);
|
|
+ tcp_cleanup_rbuf(ssk, copied);
|
|
unlock_sock_fast(ssk, slow);
|
|
}
|
|
|
|
@@ -551,7 +551,7 @@ static bool mptcp_subflow_could_cleanup(const struct sock *ssk, bool rx_empty)
|
|
(ICSK_ACK_PUSHED2 | ICSK_ACK_PUSHED)));
|
|
}
|
|
|
|
-static void mptcp_cleanup_rbuf(struct mptcp_sock *msk)
|
|
+static void mptcp_cleanup_rbuf(struct mptcp_sock *msk, int copied)
|
|
{
|
|
int old_space = READ_ONCE(msk->old_wspace);
|
|
struct mptcp_subflow_context *subflow;
|
|
@@ -559,14 +559,14 @@ static void mptcp_cleanup_rbuf(struct mptcp_sock *msk)
|
|
int space = __mptcp_space(sk);
|
|
bool cleanup, rx_empty;
|
|
|
|
- cleanup = (space > 0) && (space >= (old_space << 1));
|
|
- rx_empty = !__mptcp_rmem(sk);
|
|
+ cleanup = (space > 0) && (space >= (old_space << 1)) && copied;
|
|
+ rx_empty = !__mptcp_rmem(sk) && copied;
|
|
|
|
mptcp_for_each_subflow(msk, subflow) {
|
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
|
|
|
if (cleanup || mptcp_subflow_could_cleanup(ssk, rx_empty))
|
|
- mptcp_subflow_cleanup_rbuf(ssk);
|
|
+ mptcp_subflow_cleanup_rbuf(ssk, copied);
|
|
}
|
|
}
|
|
|
|
@@ -1902,6 +1902,8 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|
goto out;
|
|
}
|
|
|
|
+static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied);
|
|
+
|
|
static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk,
|
|
struct msghdr *msg,
|
|
size_t len, int flags,
|
|
@@ -1955,6 +1957,7 @@ static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk,
|
|
break;
|
|
}
|
|
|
|
+ mptcp_rcv_space_adjust(msk, copied);
|
|
return copied;
|
|
}
|
|
|
|
@@ -2180,9 +2183,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
|
|
|
copied += bytes_read;
|
|
|
|
- /* be sure to advertise window change */
|
|
- mptcp_cleanup_rbuf(msk);
|
|
-
|
|
if (skb_queue_empty(&msk->receive_queue) && __mptcp_move_skbs(msk))
|
|
continue;
|
|
|
|
@@ -2231,7 +2231,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
|
}
|
|
|
|
pr_debug("block timeout %ld\n", timeo);
|
|
- mptcp_rcv_space_adjust(msk, copied);
|
|
+ mptcp_cleanup_rbuf(msk, copied);
|
|
err = sk_wait_data(sk, &timeo, NULL);
|
|
if (err < 0) {
|
|
err = copied ? : err;
|
|
@@ -2239,7 +2239,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
|
}
|
|
}
|
|
|
|
- mptcp_rcv_space_adjust(msk, copied);
|
|
+ mptcp_cleanup_rbuf(msk, copied);
|
|
|
|
out_err:
|
|
if (cmsg_flags && copied >= 0) {
|
|
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
|
|
index bd2b17b219ae90..0b270893ee14c5 100644
|
|
--- a/net/netrom/nr_route.c
|
|
+++ b/net/netrom/nr_route.c
|
|
@@ -754,6 +754,12 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
|
|
int ret;
|
|
struct sk_buff *skbn;
|
|
|
|
+ /*
|
|
+ * Reject malformed packets early. Check that it contains at least 2
|
|
+ * addresses and 1 byte more for Time-To-Live
|
|
+ */
|
|
+ if (skb->len < 2 * sizeof(ax25_address) + 1)
|
|
+ return 0;
|
|
|
|
nr_src = (ax25_address *)(skb->data + 0);
|
|
nr_dest = (ax25_address *)(skb->data + 7);
|
|
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
|
|
index 56e3ae3b6be93f..4abf7e9ac4f2f7 100644
|
|
--- a/net/packet/af_packet.c
|
|
+++ b/net/packet/af_packet.c
|
|
@@ -538,10 +538,8 @@ static void *packet_current_frame(struct packet_sock *po,
|
|
return packet_lookup_frame(po, rb, rb->head, status);
|
|
}
|
|
|
|
-static u16 vlan_get_tci(struct sk_buff *skb, struct net_device *dev)
|
|
+static u16 vlan_get_tci(const struct sk_buff *skb, struct net_device *dev)
|
|
{
|
|
- u8 *skb_orig_data = skb->data;
|
|
- int skb_orig_len = skb->len;
|
|
struct vlan_hdr vhdr, *vh;
|
|
unsigned int header_len;
|
|
|
|
@@ -562,33 +560,21 @@ static u16 vlan_get_tci(struct sk_buff *skb, struct net_device *dev)
|
|
else
|
|
return 0;
|
|
|
|
- skb_push(skb, skb->data - skb_mac_header(skb));
|
|
- vh = skb_header_pointer(skb, header_len, sizeof(vhdr), &vhdr);
|
|
- if (skb_orig_data != skb->data) {
|
|
- skb->data = skb_orig_data;
|
|
- skb->len = skb_orig_len;
|
|
- }
|
|
+ vh = skb_header_pointer(skb, skb_mac_offset(skb) + header_len,
|
|
+ sizeof(vhdr), &vhdr);
|
|
if (unlikely(!vh))
|
|
return 0;
|
|
|
|
return ntohs(vh->h_vlan_TCI);
|
|
}
|
|
|
|
-static __be16 vlan_get_protocol_dgram(struct sk_buff *skb)
|
|
+static __be16 vlan_get_protocol_dgram(const struct sk_buff *skb)
|
|
{
|
|
__be16 proto = skb->protocol;
|
|
|
|
- if (unlikely(eth_type_vlan(proto))) {
|
|
- u8 *skb_orig_data = skb->data;
|
|
- int skb_orig_len = skb->len;
|
|
-
|
|
- skb_push(skb, skb->data - skb_mac_header(skb));
|
|
- proto = __vlan_get_protocol(skb, proto, NULL);
|
|
- if (skb_orig_data != skb->data) {
|
|
- skb->data = skb_orig_data;
|
|
- skb->len = skb_orig_len;
|
|
- }
|
|
- }
|
|
+ if (unlikely(eth_type_vlan(proto)))
|
|
+ proto = __vlan_get_protocol_offset(skb, proto,
|
|
+ skb_mac_offset(skb), NULL);
|
|
|
|
return proto;
|
|
}
|
|
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
|
|
index c45c192b787873..0b0794f164cf2e 100644
|
|
--- a/net/sctp/associola.c
|
|
+++ b/net/sctp/associola.c
|
|
@@ -137,7 +137,8 @@ static struct sctp_association *sctp_association_init(
|
|
= 5 * asoc->rto_max;
|
|
|
|
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
|
|
- asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
|
|
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
|
|
+ (unsigned long)sp->autoclose * HZ;
|
|
|
|
/* Initializes the timers */
|
|
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
|
|
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
|
|
index efbb4836ec668f..ea498eff1f2ae5 100644
|
|
--- a/scripts/mod/file2alias.c
|
|
+++ b/scripts/mod/file2alias.c
|
|
@@ -742,8 +742,8 @@ static void do_input(char *alias,
|
|
|
|
for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
|
|
arr[i] = TO_NATIVE(arr[i]);
|
|
- for (i = min; i < max; i++)
|
|
- if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
|
|
+ for (i = min; i <= max; i++)
|
|
+ if (arr[i / BITS_PER_LONG] & (1ULL << (i%BITS_PER_LONG)))
|
|
sprintf(alias + strlen(alias), "%X,*", i);
|
|
}
|
|
|
|
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
|
|
index 7bd0184380d3b9..a7c5445baf0027 100644
|
|
--- a/scripts/sorttable.h
|
|
+++ b/scripts/sorttable.h
|
|
@@ -110,7 +110,7 @@ static inline unsigned long orc_ip(const int *ip)
|
|
|
|
static int orc_sort_cmp(const void *_a, const void *_b)
|
|
{
|
|
- struct orc_entry *orc_a;
|
|
+ struct orc_entry *orc_a, *orc_b;
|
|
const int *a = g_orc_ip_table + *(int *)_a;
|
|
const int *b = g_orc_ip_table + *(int *)_b;
|
|
unsigned long a_val = orc_ip(a);
|
|
@@ -128,6 +128,9 @@ static int orc_sort_cmp(const void *_a, const void *_b)
|
|
* whitelisted .o files which didn't get objtool generation.
|
|
*/
|
|
orc_a = g_orc_table + (a - g_orc_ip_table);
|
|
+ orc_b = g_orc_table + (b - g_orc_ip_table);
|
|
+ if (orc_a->type == ORC_TYPE_UNDEFINED && orc_b->type == ORC_TYPE_UNDEFINED)
|
|
+ return 0;
|
|
return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
|
|
}
|
|
|
|
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
|
|
index 379ac7b5c7098c..f5eead8af2e210 100644
|
|
--- a/security/selinux/ss/services.c
|
|
+++ b/security/selinux/ss/services.c
|
|
@@ -956,7 +956,10 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
|
|
xpermd->driver))
|
|
return;
|
|
} else {
|
|
- BUG();
|
|
+ pr_warn_once(
|
|
+ "SELinux: unknown extended permission (%u) will be ignored\n",
|
|
+ node->datum.u.xperms->specified);
|
|
+ return;
|
|
}
|
|
|
|
if (node->key.specified == AVTAB_XPERMS_ALLOWED) {
|
|
@@ -993,7 +996,8 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
|
|
node->datum.u.xperms->perms.p[i];
|
|
}
|
|
} else {
|
|
- BUG();
|
|
+ pr_warn_once("SELinux: unknown specified key (%u)\n",
|
|
+ node->key.specified);
|
|
}
|
|
}
|
|
|
|
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
|
|
index e3394919daa09a..51ee4c00a84310 100644
|
|
--- a/sound/core/seq/oss/seq_oss_synth.c
|
|
+++ b/sound/core/seq/oss/seq_oss_synth.c
|
|
@@ -66,6 +66,7 @@ static struct seq_oss_synth midi_synth_dev = {
|
|
};
|
|
|
|
static DEFINE_SPINLOCK(register_lock);
|
|
+static DEFINE_MUTEX(sysex_mutex);
|
|
|
|
/*
|
|
* prototypes
|
|
@@ -497,6 +498,7 @@ snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf,
|
|
if (!info)
|
|
return -ENXIO;
|
|
|
|
+ guard(mutex)(&sysex_mutex);
|
|
sysex = info->sysex;
|
|
if (sysex == NULL) {
|
|
sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
|
|
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
|
|
index e115fe18363495..8b7dfbc8e82075 100644
|
|
--- a/sound/core/seq/seq_clientmgr.c
|
|
+++ b/sound/core/seq/seq_clientmgr.c
|
|
@@ -1280,10 +1280,16 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
|
|
if (client->type != client_info->type)
|
|
return -EINVAL;
|
|
|
|
- /* check validity of midi_version field */
|
|
- if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3) &&
|
|
- client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0)
|
|
- return -EINVAL;
|
|
+ if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3)) {
|
|
+ /* check validity of midi_version field */
|
|
+ if (client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* check if UMP is supported in kernel */
|
|
+ if (!IS_ENABLED(CONFIG_SND_SEQ_UMP) &&
|
|
+ client_info->midi_version > 0)
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
/* fill the info fields */
|
|
if (client_info->name[0])
|
|
diff --git a/sound/core/ump.c b/sound/core/ump.c
|
|
index 83856b2f88b89f..32d27e58416aa3 100644
|
|
--- a/sound/core/ump.c
|
|
+++ b/sound/core/ump.c
|
|
@@ -37,6 +37,7 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
|
|
u32 *buffer, int count);
|
|
static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
|
|
int words);
|
|
+static void update_legacy_names(struct snd_ump_endpoint *ump);
|
|
#else
|
|
static inline int process_legacy_output(struct snd_ump_endpoint *ump,
|
|
u32 *buffer, int count)
|
|
@@ -47,6 +48,9 @@ static inline void process_legacy_input(struct snd_ump_endpoint *ump,
|
|
const u32 *src, int words)
|
|
{
|
|
}
|
|
+static inline void update_legacy_names(struct snd_ump_endpoint *ump)
|
|
+{
|
|
+}
|
|
#endif
|
|
|
|
static const struct snd_rawmidi_global_ops snd_ump_rawmidi_ops = {
|
|
@@ -850,6 +854,7 @@ static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump,
|
|
fill_fb_info(ump, &fb->info, buf);
|
|
if (ump->parsed) {
|
|
snd_ump_update_group_attrs(ump);
|
|
+ update_legacy_names(ump);
|
|
seq_notify_fb_change(ump, fb);
|
|
}
|
|
}
|
|
@@ -882,6 +887,7 @@ static int ump_handle_fb_name_msg(struct snd_ump_endpoint *ump,
|
|
/* notify the FB name update to sequencer, too */
|
|
if (ret > 0 && ump->parsed) {
|
|
snd_ump_update_group_attrs(ump);
|
|
+ update_legacy_names(ump);
|
|
seq_notify_fb_change(ump, fb);
|
|
}
|
|
return ret;
|
|
@@ -1076,13 +1082,13 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
|
|
struct snd_ump_endpoint *ump = substream->rmidi->private_data;
|
|
int dir = substream->stream;
|
|
int group = ump->legacy_mapping[substream->number];
|
|
- int err = 0;
|
|
+ int err;
|
|
|
|
- mutex_lock(&ump->open_mutex);
|
|
- if (ump->legacy_substreams[dir][group]) {
|
|
- err = -EBUSY;
|
|
- goto unlock;
|
|
- }
|
|
+ guard(mutex)(&ump->open_mutex);
|
|
+ if (ump->legacy_substreams[dir][group])
|
|
+ return -EBUSY;
|
|
+ if (!ump->groups[group].active)
|
|
+ return -ENODEV;
|
|
if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) {
|
|
if (!ump->legacy_out_opens) {
|
|
err = snd_rawmidi_kernel_open(&ump->core, 0,
|
|
@@ -1090,17 +1096,14 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
|
|
SNDRV_RAWMIDI_LFLG_APPEND,
|
|
&ump->legacy_out_rfile);
|
|
if (err < 0)
|
|
- goto unlock;
|
|
+ return err;
|
|
}
|
|
ump->legacy_out_opens++;
|
|
snd_ump_convert_reset(&ump->out_cvts[group]);
|
|
}
|
|
- spin_lock_irq(&ump->legacy_locks[dir]);
|
|
+ guard(spinlock_irq)(&ump->legacy_locks[dir]);
|
|
ump->legacy_substreams[dir][group] = substream;
|
|
- spin_unlock_irq(&ump->legacy_locks[dir]);
|
|
- unlock:
|
|
- mutex_unlock(&ump->open_mutex);
|
|
- return err;
|
|
+ return 0;
|
|
}
|
|
|
|
static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream)
|
|
@@ -1109,15 +1112,13 @@ static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream)
|
|
int dir = substream->stream;
|
|
int group = ump->legacy_mapping[substream->number];
|
|
|
|
- mutex_lock(&ump->open_mutex);
|
|
- spin_lock_irq(&ump->legacy_locks[dir]);
|
|
- ump->legacy_substreams[dir][group] = NULL;
|
|
- spin_unlock_irq(&ump->legacy_locks[dir]);
|
|
+ guard(mutex)(&ump->open_mutex);
|
|
+ scoped_guard(spinlock_irq, &ump->legacy_locks[dir])
|
|
+ ump->legacy_substreams[dir][group] = NULL;
|
|
if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) {
|
|
if (!--ump->legacy_out_opens)
|
|
snd_rawmidi_kernel_release(&ump->legacy_out_rfile);
|
|
}
|
|
- mutex_unlock(&ump->open_mutex);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1169,12 +1170,11 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
|
|
const int dir = SNDRV_RAWMIDI_STREAM_OUTPUT;
|
|
unsigned char c;
|
|
int group, size = 0;
|
|
- unsigned long flags;
|
|
|
|
if (!ump->out_cvts || !ump->legacy_out_opens)
|
|
return 0;
|
|
|
|
- spin_lock_irqsave(&ump->legacy_locks[dir], flags);
|
|
+ guard(spinlock_irqsave)(&ump->legacy_locks[dir]);
|
|
for (group = 0; group < SNDRV_UMP_MAX_GROUPS; group++) {
|
|
substream = ump->legacy_substreams[dir][group];
|
|
if (!substream)
|
|
@@ -1190,7 +1190,6 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
|
|
break;
|
|
}
|
|
}
|
|
- spin_unlock_irqrestore(&ump->legacy_locks[dir], flags);
|
|
return size;
|
|
}
|
|
|
|
@@ -1200,18 +1199,16 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
|
|
struct snd_rawmidi_substream *substream;
|
|
unsigned char buf[16];
|
|
unsigned char group;
|
|
- unsigned long flags;
|
|
const int dir = SNDRV_RAWMIDI_STREAM_INPUT;
|
|
int size;
|
|
|
|
size = snd_ump_convert_from_ump(src, buf, &group);
|
|
if (size <= 0)
|
|
return;
|
|
- spin_lock_irqsave(&ump->legacy_locks[dir], flags);
|
|
+ guard(spinlock_irqsave)(&ump->legacy_locks[dir]);
|
|
substream = ump->legacy_substreams[dir][group];
|
|
if (substream)
|
|
snd_rawmidi_receive(substream, buf, size);
|
|
- spin_unlock_irqrestore(&ump->legacy_locks[dir], flags);
|
|
}
|
|
|
|
/* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */
|
|
@@ -1254,11 +1251,20 @@ static void fill_substream_names(struct snd_ump_endpoint *ump,
|
|
name = ump->groups[idx].name;
|
|
if (!*name)
|
|
name = ump->info.name;
|
|
- snprintf(s->name, sizeof(s->name), "Group %d (%.16s)",
|
|
- idx + 1, name);
|
|
+ scnprintf(s->name, sizeof(s->name), "Group %d (%.16s)%s",
|
|
+ idx + 1, name,
|
|
+ ump->groups[idx].active ? "" : " [Inactive]");
|
|
}
|
|
}
|
|
|
|
+static void update_legacy_names(struct snd_ump_endpoint *ump)
|
|
+{
|
|
+ struct snd_rawmidi *rmidi = ump->legacy_rmidi;
|
|
+
|
|
+ fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT);
|
|
+ fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT);
|
|
+}
|
|
+
|
|
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
|
|
char *id, int device)
|
|
{
|
|
@@ -1295,10 +1301,7 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
|
|
rmidi->ops = &snd_ump_legacy_ops;
|
|
rmidi->private_data = ump;
|
|
ump->legacy_rmidi = rmidi;
|
|
- if (input)
|
|
- fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT);
|
|
- if (output)
|
|
- fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT);
|
|
+ update_legacy_names(ump);
|
|
|
|
ump_dbg(ump, "Created a legacy rawmidi #%d (%s)\n", device, id);
|
|
return 0;
|
|
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
|
|
index 748a3c40966e97..27e48fdbbf3aa0 100644
|
|
--- a/sound/pci/hda/patch_ca0132.c
|
|
+++ b/sound/pci/hda/patch_ca0132.c
|
|
@@ -1134,7 +1134,6 @@ struct ca0132_spec {
|
|
|
|
struct hda_codec *codec;
|
|
struct delayed_work unsol_hp_work;
|
|
- int quirk;
|
|
|
|
#ifdef ENABLE_TUNING_CONTROLS
|
|
long cur_ctl_vals[TUNING_CTLS_COUNT];
|
|
@@ -1166,7 +1165,6 @@ struct ca0132_spec {
|
|
* CA0132 quirks table
|
|
*/
|
|
enum {
|
|
- QUIRK_NONE,
|
|
QUIRK_ALIENWARE,
|
|
QUIRK_ALIENWARE_M17XR4,
|
|
QUIRK_SBZ,
|
|
@@ -1176,10 +1174,11 @@ enum {
|
|
QUIRK_R3D,
|
|
QUIRK_AE5,
|
|
QUIRK_AE7,
|
|
+ QUIRK_NONE = HDA_FIXUP_ID_NOT_SET,
|
|
};
|
|
|
|
#ifdef CONFIG_PCI
|
|
-#define ca0132_quirk(spec) ((spec)->quirk)
|
|
+#define ca0132_quirk(spec) ((spec)->codec->fixup_id)
|
|
#define ca0132_use_pci_mmio(spec) ((spec)->use_pci_mmio)
|
|
#define ca0132_use_alt_functions(spec) ((spec)->use_alt_functions)
|
|
#define ca0132_use_alt_controls(spec) ((spec)->use_alt_controls)
|
|
@@ -1293,7 +1292,7 @@ static const struct hda_pintbl ae7_pincfgs[] = {
|
|
{}
|
|
};
|
|
|
|
-static const struct snd_pci_quirk ca0132_quirks[] = {
|
|
+static const struct hda_quirk ca0132_quirks[] = {
|
|
SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4),
|
|
SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
|
|
SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
|
|
@@ -1316,6 +1315,19 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
|
|
{}
|
|
};
|
|
|
|
+static const struct hda_model_fixup ca0132_quirk_models[] = {
|
|
+ { .id = QUIRK_ALIENWARE, .name = "alienware" },
|
|
+ { .id = QUIRK_ALIENWARE_M17XR4, .name = "alienware-m17xr4" },
|
|
+ { .id = QUIRK_SBZ, .name = "sbz" },
|
|
+ { .id = QUIRK_ZXR, .name = "zxr" },
|
|
+ { .id = QUIRK_ZXR_DBPRO, .name = "zxr-dbpro" },
|
|
+ { .id = QUIRK_R3DI, .name = "r3di" },
|
|
+ { .id = QUIRK_R3D, .name = "r3d" },
|
|
+ { .id = QUIRK_AE5, .name = "ae5" },
|
|
+ { .id = QUIRK_AE7, .name = "ae7" },
|
|
+ {}
|
|
+};
|
|
+
|
|
/* Output selection quirk info structures. */
|
|
#define MAX_QUIRK_MMIO_GPIO_SET_VALS 3
|
|
#define MAX_QUIRK_SCP_SET_VALS 2
|
|
@@ -9962,17 +9974,15 @@ static int ca0132_prepare_verbs(struct hda_codec *codec)
|
|
*/
|
|
static void sbz_detect_quirk(struct hda_codec *codec)
|
|
{
|
|
- struct ca0132_spec *spec = codec->spec;
|
|
-
|
|
switch (codec->core.subsystem_id) {
|
|
case 0x11020033:
|
|
- spec->quirk = QUIRK_ZXR;
|
|
+ codec->fixup_id = QUIRK_ZXR;
|
|
break;
|
|
case 0x1102003f:
|
|
- spec->quirk = QUIRK_ZXR_DBPRO;
|
|
+ codec->fixup_id = QUIRK_ZXR_DBPRO;
|
|
break;
|
|
default:
|
|
- spec->quirk = QUIRK_SBZ;
|
|
+ codec->fixup_id = QUIRK_SBZ;
|
|
break;
|
|
}
|
|
}
|
|
@@ -9981,7 +9991,6 @@ static int patch_ca0132(struct hda_codec *codec)
|
|
{
|
|
struct ca0132_spec *spec;
|
|
int err;
|
|
- const struct snd_pci_quirk *quirk;
|
|
|
|
codec_dbg(codec, "patch_ca0132\n");
|
|
|
|
@@ -9992,11 +10001,7 @@ static int patch_ca0132(struct hda_codec *codec)
|
|
spec->codec = codec;
|
|
|
|
/* Detect codec quirk */
|
|
- quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
|
|
- if (quirk)
|
|
- spec->quirk = quirk->value;
|
|
- else
|
|
- spec->quirk = QUIRK_NONE;
|
|
+ snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL);
|
|
if (ca0132_quirk(spec) == QUIRK_SBZ)
|
|
sbz_detect_quirk(codec);
|
|
|
|
@@ -10073,7 +10078,7 @@ static int patch_ca0132(struct hda_codec *codec)
|
|
spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20);
|
|
if (spec->mem_base == NULL) {
|
|
codec_warn(codec, "pci_iomap failed! Setting quirk to QUIRK_NONE.");
|
|
- spec->quirk = QUIRK_NONE;
|
|
+ codec->fixup_id = QUIRK_NONE;
|
|
}
|
|
}
|
|
#endif
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 29d7eb8c6bec3e..fc93af80f0bffe 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -10443,6 +10443,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
|
|
+ SND_PCI_QUIRK(0xf111, 0x000c, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
|
|
|
|
#if 0
|
|
/* Below is a quirk table taken from the old code.
|
|
@@ -10631,6 +10632,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
|
|
{.id = ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, .name = "alc255-acer-headphone-and-mic"},
|
|
{.id = ALC285_FIXUP_HP_GPIO_AMP_INIT, .name = "alc285-hp-amp-init"},
|
|
{.id = ALC236_FIXUP_LENOVO_INV_DMIC, .name = "alc236-fixup-lenovo-inv-mic"},
|
|
+ {.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"},
|
|
{}
|
|
};
|
|
#define ALC225_STANDARD_PINS \
|
|
diff --git a/sound/usb/format.c b/sound/usb/format.c
|
|
index 3b45d0ee769389..3b3a5ea6fcbfc0 100644
|
|
--- a/sound/usb/format.c
|
|
+++ b/sound/usb/format.c
|
|
@@ -60,6 +60,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
|
|
pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL;
|
|
/* flag potentially raw DSD capable altsettings */
|
|
fp->dsd_raw = true;
|
|
+ /* clear special format bit to avoid "unsupported format" msg below */
|
|
+ format &= ~UAC2_FORMAT_TYPE_I_RAW_DATA;
|
|
}
|
|
|
|
format <<= 1;
|
|
@@ -71,8 +73,11 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
|
|
sample_width = as->bBitResolution;
|
|
sample_bytes = as->bSubslotSize;
|
|
|
|
- if (format & UAC3_FORMAT_TYPE_I_RAW_DATA)
|
|
+ if (format & UAC3_FORMAT_TYPE_I_RAW_DATA) {
|
|
pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL;
|
|
+ /* clear special format bit to avoid "unsupported format" msg below */
|
|
+ format &= ~UAC3_FORMAT_TYPE_I_RAW_DATA;
|
|
+ }
|
|
|
|
format <<= 1;
|
|
break;
|
|
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
|
|
index 6eb7d93b358d99..20ac32635f1f50 100644
|
|
--- a/sound/usb/mixer_us16x08.c
|
|
+++ b/sound/usb/mixer_us16x08.c
|
|
@@ -687,7 +687,7 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
|
|
struct usb_mixer_elem_info *elem = kcontrol->private_data;
|
|
struct snd_usb_audio *chip = elem->head.mixer->chip;
|
|
struct snd_us16x08_meter_store *store = elem->private_data;
|
|
- u8 meter_urb[64];
|
|
+ u8 meter_urb[64] = {0};
|
|
|
|
switch (kcontrol->private_value) {
|
|
case 0: {
|
|
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
|
|
index 8eed8d9742fda9..ec81b47c41c9ea 100644
|
|
--- a/sound/usb/quirks.c
|
|
+++ b/sound/usb/quirks.c
|
|
@@ -2225,6 +2225,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
|
|
QUIRK_FLAG_DSD_RAW),
|
|
DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
|
|
QUIRK_FLAG_SET_IFACE_FIRST),
|
|
+ DEVICE_FLG(0x262a, 0x9302, /* ddHiFi TC44C */
|
|
+ QUIRK_FLAG_DSD_RAW),
|
|
DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
|
|
QUIRK_FLAG_IGNORE_CTL_ERROR),
|
|
DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
|
|
diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
|
|
index f87365f7599bf7..f61d623b1ce8df 100644
|
|
--- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
|
|
+++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
|
|
@@ -541,24 +541,11 @@ static __u64 subprog_spill_reg_precise(void)
|
|
|
|
SEC("?raw_tp")
|
|
__success __log_level(2)
|
|
-__msg("10: (0f) r1 += r7")
|
|
-__msg("mark_precise: frame0: last_idx 10 first_idx 7 subseq_idx -1")
|
|
-__msg("mark_precise: frame0: regs=r7 stack= before 9: (bf) r1 = r8")
|
|
-__msg("mark_precise: frame0: regs=r7 stack= before 8: (27) r7 *= 4")
|
|
-__msg("mark_precise: frame0: regs=r7 stack= before 7: (79) r7 = *(u64 *)(r10 -8)")
|
|
-__msg("mark_precise: frame0: parent state regs= stack=-8: R0_w=2 R6_w=1 R8_rw=map_value(map=.data.vals,ks=4,vs=16) R10=fp0 fp-8_rw=P1")
|
|
-__msg("mark_precise: frame0: last_idx 18 first_idx 0 subseq_idx 7")
|
|
-__msg("mark_precise: frame0: regs= stack=-8 before 18: (95) exit")
|
|
-__msg("mark_precise: frame1: regs= stack= before 17: (0f) r0 += r2")
|
|
-__msg("mark_precise: frame1: regs= stack= before 16: (79) r2 = *(u64 *)(r1 +0)")
|
|
-__msg("mark_precise: frame1: regs= stack= before 15: (79) r0 = *(u64 *)(r10 -16)")
|
|
-__msg("mark_precise: frame1: regs= stack= before 14: (7b) *(u64 *)(r10 -16) = r2")
|
|
-__msg("mark_precise: frame1: regs= stack= before 13: (7b) *(u64 *)(r1 +0) = r2")
|
|
-__msg("mark_precise: frame1: regs=r2 stack= before 6: (85) call pc+6")
|
|
-__msg("mark_precise: frame0: regs=r2 stack= before 5: (bf) r2 = r6")
|
|
-__msg("mark_precise: frame0: regs=r6 stack= before 4: (07) r1 += -8")
|
|
-__msg("mark_precise: frame0: regs=r6 stack= before 3: (bf) r1 = r10")
|
|
-__msg("mark_precise: frame0: regs=r6 stack= before 2: (b7) r6 = 1")
|
|
+/* precision backtracking can't currently handle stack access not through r10,
|
|
+ * so we won't be able to mark stack slot fp-8 as precise, and so will
|
|
+ * fallback to forcing all as precise
|
|
+ */
|
|
+__msg("mark_precise: frame0: falling back to forcing all scalars precise")
|
|
__naked int subprog_spill_into_parent_stack_slot_precise(void)
|
|
{
|
|
asm volatile (
|
|
diff --git a/tools/testing/selftests/bpf/verifier/precise.c b/tools/testing/selftests/bpf/verifier/precise.c
|
|
index 8a2ff81d835088..0d84dd1f38b6b0 100644
|
|
--- a/tools/testing/selftests/bpf/verifier/precise.c
|
|
+++ b/tools/testing/selftests/bpf/verifier/precise.c
|
|
@@ -140,11 +140,10 @@
|
|
.result = REJECT,
|
|
},
|
|
{
|
|
- "precise: ST zero to stack insn is supported",
|
|
+ "precise: ST insn causing spi > allocated_stack",
|
|
.insns = {
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
|
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0),
|
|
- /* not a register spill, so we stop precision propagation for R4 here */
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_3, -8, 0),
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
|
|
BPF_MOV64_IMM(BPF_REG_0, -1),
|
|
@@ -158,11 +157,11 @@
|
|
mark_precise: frame0: last_idx 4 first_idx 2\
|
|
mark_precise: frame0: regs=r4 stack= before 4\
|
|
mark_precise: frame0: regs=r4 stack= before 3\
|
|
+ mark_precise: frame0: regs= stack=-8 before 2\
|
|
+ mark_precise: frame0: falling back to forcing all scalars precise\
|
|
+ force_precise: frame0: forcing r0 to be precise\
|
|
mark_precise: frame0: last_idx 5 first_idx 5\
|
|
- mark_precise: frame0: parent state regs=r0 stack=:\
|
|
- mark_precise: frame0: last_idx 4 first_idx 2\
|
|
- mark_precise: frame0: regs=r0 stack= before 4\
|
|
- 5: R0=-1 R4=0",
|
|
+ mark_precise: frame0: parent state regs= stack=:",
|
|
.result = VERBOSE_ACCEPT,
|
|
.retval = -1,
|
|
},
|
|
@@ -170,8 +169,6 @@
|
|
"precise: STX insn causing spi > allocated_stack",
|
|
.insns = {
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
|
|
- /* make later reg spill more interesting by having somewhat known scalar */
|
|
- BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xff),
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
|
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0),
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, -8),
|
|
@@ -182,21 +179,18 @@
|
|
},
|
|
.prog_type = BPF_PROG_TYPE_XDP,
|
|
.flags = BPF_F_TEST_STATE_FREQ,
|
|
- .errstr = "mark_precise: frame0: last_idx 7 first_idx 7\
|
|
+ .errstr = "mark_precise: frame0: last_idx 6 first_idx 6\
|
|
mark_precise: frame0: parent state regs=r4 stack=:\
|
|
- mark_precise: frame0: last_idx 6 first_idx 4\
|
|
- mark_precise: frame0: regs=r4 stack= before 6: (b7) r0 = -1\
|
|
- mark_precise: frame0: regs=r4 stack= before 5: (79) r4 = *(u64 *)(r10 -8)\
|
|
- mark_precise: frame0: regs= stack=-8 before 4: (7b) *(u64 *)(r3 -8) = r0\
|
|
- mark_precise: frame0: parent state regs=r0 stack=:\
|
|
- mark_precise: frame0: last_idx 3 first_idx 3\
|
|
- mark_precise: frame0: regs=r0 stack= before 3: (55) if r3 != 0x7b goto pc+0\
|
|
- mark_precise: frame0: regs=r0 stack= before 2: (bf) r3 = r10\
|
|
- mark_precise: frame0: regs=r0 stack= before 1: (57) r0 &= 255\
|
|
- mark_precise: frame0: parent state regs=r0 stack=:\
|
|
- mark_precise: frame0: last_idx 0 first_idx 0\
|
|
- mark_precise: frame0: regs=r0 stack= before 0: (85) call bpf_get_prandom_u32#7\
|
|
- mark_precise: frame0: last_idx 7 first_idx 7\
|
|
+ mark_precise: frame0: last_idx 5 first_idx 3\
|
|
+ mark_precise: frame0: regs=r4 stack= before 5\
|
|
+ mark_precise: frame0: regs=r4 stack= before 4\
|
|
+ mark_precise: frame0: regs= stack=-8 before 3\
|
|
+ mark_precise: frame0: falling back to forcing all scalars precise\
|
|
+ force_precise: frame0: forcing r0 to be precise\
|
|
+ force_precise: frame0: forcing r0 to be precise\
|
|
+ force_precise: frame0: forcing r0 to be precise\
|
|
+ force_precise: frame0: forcing r0 to be precise\
|
|
+ mark_precise: frame0: last_idx 6 first_idx 6\
|
|
mark_precise: frame0: parent state regs= stack=:",
|
|
.result = VERBOSE_ACCEPT,
|
|
.retval = -1,
|