12541 lines
421 KiB
Diff
12541 lines
421 KiB
Diff
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index 31af352b4762d..4ad60e127e048 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -5671,6 +5671,13 @@
|
|
This feature may be more efficiently disabled
|
|
using the csdlock_debug- kernel parameter.
|
|
|
|
+ smp.panic_on_ipistall= [KNL]
|
|
+ If a csd_lock_timeout extends for more than
|
|
+ the specified number of milliseconds, panic the
|
|
+ system. By default, let CSD-lock acquisition
|
|
+ take as long as they take. Specifying 300,000
|
|
+ for this value provides a 5-minute timeout.
|
|
+
|
|
smsc-ircc2.nopnp [HW] Don't use PNP to discover SMC devices
|
|
smsc-ircc2.ircc_cfg= [HW] Device configuration I/O port
|
|
smsc-ircc2.ircc_sir= [HW] SIR base I/O port
|
|
diff --git a/Makefile b/Makefile
|
|
index 7c69293b7e059..97c75ae364cdf 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 6
|
|
PATCHLEVEL = 1
|
|
-SUBLEVEL = 63
|
|
+SUBLEVEL = 64
|
|
EXTRAVERSION =
|
|
NAME = Curry Ramen
|
|
|
|
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h
|
|
index 58e039a851af0..3c82975d46db3 100644
|
|
--- a/arch/arm/include/asm/exception.h
|
|
+++ b/arch/arm/include/asm/exception.h
|
|
@@ -10,10 +10,6 @@
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
#define __exception_irq_entry __irq_entry
|
|
-#else
|
|
-#define __exception_irq_entry
|
|
-#endif
|
|
|
|
#endif /* __ASM_ARM_EXCEPTION_H */
|
|
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
|
|
index 9ee9e17eb2ca0..ea70eb960565e 100644
|
|
--- a/arch/arm64/Kconfig
|
|
+++ b/arch/arm64/Kconfig
|
|
@@ -1304,6 +1304,8 @@ choice
|
|
config CPU_BIG_ENDIAN
|
|
bool "Build big-endian kernel"
|
|
depends on !LD_IS_LLD || LLD_VERSION >= 130000
|
|
+ # https://github.com/llvm/llvm-project/commit/1379b150991f70a5782e9a143c2ba5308da1161c
|
|
+ depends on AS_IS_GNU || AS_VERSION >= 150000
|
|
help
|
|
Say Y if you plan on running a kernel with a big-endian userspace.
|
|
|
|
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
|
|
index 348d9e3a91252..b53d74aee12ad 100644
|
|
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
|
|
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
|
|
@@ -1186,26 +1186,34 @@
|
|
dma-coherent;
|
|
};
|
|
|
|
- usb0: usb@3100000 {
|
|
- status = "disabled";
|
|
- compatible = "snps,dwc3";
|
|
- reg = <0x0 0x3100000 0x0 0x10000>;
|
|
- interrupts = <0 80 0x4>; /* Level high type */
|
|
- dr_mode = "host";
|
|
- snps,quirk-frame-length-adjustment = <0x20>;
|
|
- snps,dis_rxdet_inp3_quirk;
|
|
- snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
|
|
- };
|
|
+ bus: bus {
|
|
+ #address-cells = <2>;
|
|
+ #size-cells = <2>;
|
|
+ compatible = "simple-bus";
|
|
+ ranges;
|
|
+ dma-ranges = <0x0 0x0 0x0 0x0 0x100 0x00000000>;
|
|
+
|
|
+ usb0: usb@3100000 {
|
|
+ compatible = "snps,dwc3";
|
|
+ reg = <0x0 0x3100000 0x0 0x10000>;
|
|
+ interrupts = <0 80 0x4>; /* Level high type */
|
|
+ dr_mode = "host";
|
|
+ snps,quirk-frame-length-adjustment = <0x20>;
|
|
+ snps,dis_rxdet_inp3_quirk;
|
|
+ snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
|
|
+ status = "disabled";
|
|
+ };
|
|
|
|
- usb1: usb@3110000 {
|
|
- status = "disabled";
|
|
- compatible = "snps,dwc3";
|
|
- reg = <0x0 0x3110000 0x0 0x10000>;
|
|
- interrupts = <0 81 0x4>; /* Level high type */
|
|
- dr_mode = "host";
|
|
- snps,quirk-frame-length-adjustment = <0x20>;
|
|
- snps,dis_rxdet_inp3_quirk;
|
|
- snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
|
|
+ usb1: usb@3110000 {
|
|
+ compatible = "snps,dwc3";
|
|
+ reg = <0x0 0x3110000 0x0 0x10000>;
|
|
+ interrupts = <0 81 0x4>; /* Level high type */
|
|
+ dr_mode = "host";
|
|
+ snps,quirk-frame-length-adjustment = <0x20>;
|
|
+ snps,dis_rxdet_inp3_quirk;
|
|
+ snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
|
|
+ status = "disabled";
|
|
+ };
|
|
};
|
|
|
|
ccn@4000000 {
|
|
diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
|
|
index c3492a3831558..43ff8f1f1475c 100644
|
|
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
|
|
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
|
|
@@ -169,7 +169,7 @@
|
|
smem {
|
|
compatible = "qcom,smem";
|
|
memory-region = <&smem_region>;
|
|
- hwlocks = <&tcsr_mutex 0>;
|
|
+ hwlocks = <&tcsr_mutex 3>;
|
|
};
|
|
|
|
soc: soc {
|
|
@@ -248,7 +248,7 @@
|
|
|
|
tcsr_mutex: hwlock@1905000 {
|
|
compatible = "qcom,ipq6018-tcsr-mutex", "qcom,tcsr-mutex";
|
|
- reg = <0x0 0x01905000 0x0 0x1000>;
|
|
+ reg = <0x0 0x01905000 0x0 0x20000>;
|
|
#hwlock-cells = <1>;
|
|
};
|
|
|
|
diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
|
|
index 3f7cf3fdd319f..3d8e5ba51ce0d 100644
|
|
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
|
|
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
|
|
@@ -90,7 +90,7 @@
|
|
reg = <0x0 0x4ab00000 0x0 0x00100000>;
|
|
no-map;
|
|
|
|
- hwlocks = <&tcsr_mutex 0>;
|
|
+ hwlocks = <&tcsr_mutex 3>;
|
|
};
|
|
|
|
memory@4ac00000 {
|
|
diff --git a/arch/loongarch/include/asm/percpu.h b/arch/loongarch/include/asm/percpu.h
|
|
index ad8d88494554a..302f0e33975a2 100644
|
|
--- a/arch/loongarch/include/asm/percpu.h
|
|
+++ b/arch/loongarch/include/asm/percpu.h
|
|
@@ -28,7 +28,7 @@ static inline void set_my_cpu_offset(unsigned long off)
|
|
#define __my_cpu_offset __my_cpu_offset
|
|
|
|
#define PERCPU_OP(op, asm_op, c_op) \
|
|
-static inline unsigned long __percpu_##op(void *ptr, \
|
|
+static __always_inline unsigned long __percpu_##op(void *ptr, \
|
|
unsigned long val, int size) \
|
|
{ \
|
|
unsigned long ret; \
|
|
@@ -59,7 +59,7 @@ PERCPU_OP(and, and, &)
|
|
PERCPU_OP(or, or, |)
|
|
#undef PERCPU_OP
|
|
|
|
-static inline unsigned long __percpu_read(void *ptr, int size)
|
|
+static __always_inline unsigned long __percpu_read(void *ptr, int size)
|
|
{
|
|
unsigned long ret;
|
|
|
|
@@ -96,7 +96,7 @@ static inline unsigned long __percpu_read(void *ptr, int size)
|
|
return ret;
|
|
}
|
|
|
|
-static inline void __percpu_write(void *ptr, unsigned long val, int size)
|
|
+static __always_inline void __percpu_write(void *ptr, unsigned long val, int size)
|
|
{
|
|
switch (size) {
|
|
case 1:
|
|
@@ -128,8 +128,8 @@ static inline void __percpu_write(void *ptr, unsigned long val, int size)
|
|
}
|
|
}
|
|
|
|
-static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
|
|
- int size)
|
|
+static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
|
|
+ int size)
|
|
{
|
|
switch (size) {
|
|
case 1:
|
|
diff --git a/arch/parisc/include/uapi/asm/pdc.h b/arch/parisc/include/uapi/asm/pdc.h
|
|
index 7a90070136e82..8e38a86996fc6 100644
|
|
--- a/arch/parisc/include/uapi/asm/pdc.h
|
|
+++ b/arch/parisc/include/uapi/asm/pdc.h
|
|
@@ -472,6 +472,7 @@ struct pdc_model { /* for PDC_MODEL */
|
|
unsigned long arch_rev;
|
|
unsigned long pot_key;
|
|
unsigned long curr_key;
|
|
+ unsigned long width; /* default of PSW_W bit (1=enabled) */
|
|
};
|
|
|
|
struct pdc_cache_cf { /* for PDC_CACHE (I/D-caches) */
|
|
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
|
|
index 0e5ebfe8d9d29..335887673c656 100644
|
|
--- a/arch/parisc/kernel/entry.S
|
|
+++ b/arch/parisc/kernel/entry.S
|
|
@@ -462,13 +462,13 @@
|
|
* to a CPU TLB 4k PFN (4k => 12 bits to shift) */
|
|
#define PAGE_ADD_SHIFT (PAGE_SHIFT-12)
|
|
#define PAGE_ADD_HUGE_SHIFT (REAL_HPAGE_SHIFT-12)
|
|
+ #define PFN_START_BIT (63-ASM_PFN_PTE_SHIFT+(63-58)-PAGE_ADD_SHIFT)
|
|
|
|
/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
|
|
.macro convert_for_tlb_insert20 pte,tmp
|
|
#ifdef CONFIG_HUGETLB_PAGE
|
|
copy \pte,\tmp
|
|
- extrd,u \tmp,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
|
|
- 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
|
|
+ extrd,u \tmp,PFN_START_BIT,PFN_START_BIT+1,\pte
|
|
|
|
depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
|
|
(63-58)+PAGE_ADD_SHIFT,\pte
|
|
@@ -476,8 +476,7 @@
|
|
depdi _HUGE_PAGE_SIZE_ENCODING_DEFAULT,63,\
|
|
(63-58)+PAGE_ADD_HUGE_SHIFT,\pte
|
|
#else /* Huge pages disabled */
|
|
- extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
|
|
- 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
|
|
+ extrd,u \pte,PFN_START_BIT,PFN_START_BIT+1,\pte
|
|
depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\
|
|
(63-58)+PAGE_ADD_SHIFT,\pte
|
|
#endif
|
|
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
|
|
index fd15fd4bbb61b..5a7d43c0f469c 100644
|
|
--- a/arch/parisc/kernel/head.S
|
|
+++ b/arch/parisc/kernel/head.S
|
|
@@ -70,9 +70,8 @@ $bss_loop:
|
|
stw,ma %arg2,4(%r1)
|
|
stw,ma %arg3,4(%r1)
|
|
|
|
-#if !defined(CONFIG_64BIT) && defined(CONFIG_PA20)
|
|
- /* This 32-bit kernel was compiled for PA2.0 CPUs. Check current CPU
|
|
- * and halt kernel if we detect a PA1.x CPU. */
|
|
+#if defined(CONFIG_PA20)
|
|
+ /* check for 64-bit capable CPU as required by current kernel */
|
|
ldi 32,%r10
|
|
mtctl %r10,%cr11
|
|
.level 2.0
|
|
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
|
|
index 942aa830e110e..e3c31c771ce91 100644
|
|
--- a/arch/powerpc/perf/core-book3s.c
|
|
+++ b/arch/powerpc/perf/core-book3s.c
|
|
@@ -1371,8 +1371,7 @@ static void power_pmu_disable(struct pmu *pmu)
|
|
/*
|
|
* Disable instruction sampling if it was enabled
|
|
*/
|
|
- if (cpuhw->mmcr.mmcra & MMCRA_SAMPLE_ENABLE)
|
|
- val &= ~MMCRA_SAMPLE_ENABLE;
|
|
+ val &= ~MMCRA_SAMPLE_ENABLE;
|
|
|
|
/* Disable BHRB via mmcra (BHRBRD) for p10 */
|
|
if (ppmu->flags & PPMU_ARCH_31)
|
|
@@ -1383,7 +1382,7 @@ static void power_pmu_disable(struct pmu *pmu)
|
|
* instruction sampling or BHRB.
|
|
*/
|
|
if (val != mmcra) {
|
|
- mtspr(SPRN_MMCRA, mmcra);
|
|
+ mtspr(SPRN_MMCRA, val);
|
|
mb();
|
|
isync();
|
|
}
|
|
diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c
|
|
index 113bdb151f687..40e26e9f318fd 100644
|
|
--- a/arch/powerpc/platforms/powernv/opal-prd.c
|
|
+++ b/arch/powerpc/platforms/powernv/opal-prd.c
|
|
@@ -24,13 +24,20 @@
|
|
#include <linux/uaccess.h>
|
|
|
|
|
|
+struct opal_prd_msg {
|
|
+ union {
|
|
+ struct opal_prd_msg_header header;
|
|
+ DECLARE_FLEX_ARRAY(u8, data);
|
|
+ };
|
|
+};
|
|
+
|
|
/*
|
|
* The msg member must be at the end of the struct, as it's followed by the
|
|
* message data.
|
|
*/
|
|
struct opal_prd_msg_queue_item {
|
|
- struct list_head list;
|
|
- struct opal_prd_msg_header msg;
|
|
+ struct list_head list;
|
|
+ struct opal_prd_msg msg;
|
|
};
|
|
|
|
static struct device_node *prd_node;
|
|
@@ -156,7 +163,7 @@ static ssize_t opal_prd_read(struct file *file, char __user *buf,
|
|
int rc;
|
|
|
|
/* we need at least a header's worth of data */
|
|
- if (count < sizeof(item->msg))
|
|
+ if (count < sizeof(item->msg.header))
|
|
return -EINVAL;
|
|
|
|
if (*ppos)
|
|
@@ -186,7 +193,7 @@ static ssize_t opal_prd_read(struct file *file, char __user *buf,
|
|
return -EINTR;
|
|
}
|
|
|
|
- size = be16_to_cpu(item->msg.size);
|
|
+ size = be16_to_cpu(item->msg.header.size);
|
|
if (size > count) {
|
|
err = -EINVAL;
|
|
goto err_requeue;
|
|
@@ -352,7 +359,7 @@ static int opal_prd_msg_notifier(struct notifier_block *nb,
|
|
if (!item)
|
|
return -ENOMEM;
|
|
|
|
- memcpy(&item->msg, msg->params, msg_size);
|
|
+ memcpy(&item->msg.data, msg->params, msg_size);
|
|
|
|
spin_lock_irqsave(&opal_prd_msg_queue_lock, flags);
|
|
list_add_tail(&item->list, &opal_prd_msg_queue);
|
|
diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
|
|
index ac70b0fd9a9a3..86048c60f7002 100644
|
|
--- a/arch/riscv/include/asm/page.h
|
|
+++ b/arch/riscv/include/asm/page.h
|
|
@@ -38,8 +38,8 @@
|
|
#define PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL)
|
|
#endif
|
|
/*
|
|
- * By default, CONFIG_PAGE_OFFSET value corresponds to SV48 address space so
|
|
- * define the PAGE_OFFSET value for SV39.
|
|
+ * By default, CONFIG_PAGE_OFFSET value corresponds to SV57 address space so
|
|
+ * define the PAGE_OFFSET value for SV48 and SV39.
|
|
*/
|
|
#define PAGE_OFFSET_L4 _AC(0xffffaf8000000000, UL)
|
|
#define PAGE_OFFSET_L3 _AC(0xffffffd800000000, UL)
|
|
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
|
|
index a20568bd1f1a8..41bf1eb0110dd 100644
|
|
--- a/arch/riscv/kernel/probes/simulate-insn.c
|
|
+++ b/arch/riscv/kernel/probes/simulate-insn.c
|
|
@@ -24,7 +24,7 @@ static inline bool rv_insn_reg_set_val(struct pt_regs *regs, u32 index,
|
|
unsigned long val)
|
|
{
|
|
if (index == 0)
|
|
- return false;
|
|
+ return true;
|
|
else if (index <= 31)
|
|
*((unsigned long *)regs + index) = val;
|
|
else
|
|
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
|
|
index 8c3b59f1f9b80..7f534023f4ffe 100644
|
|
--- a/arch/riscv/kernel/smp.c
|
|
+++ b/arch/riscv/kernel/smp.c
|
|
@@ -58,7 +58,6 @@ int riscv_hartid_to_cpuid(unsigned long hartid)
|
|
if (cpuid_to_hartid_map(i) == hartid)
|
|
return i;
|
|
|
|
- pr_err("Couldn't find cpu id for hartid [%lu]\n", hartid);
|
|
return -ENOENT;
|
|
}
|
|
|
|
diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c
|
|
index 20a9f991a6d74..e9090b38f8117 100644
|
|
--- a/arch/riscv/mm/ptdump.c
|
|
+++ b/arch/riscv/mm/ptdump.c
|
|
@@ -384,6 +384,9 @@ static int __init ptdump_init(void)
|
|
|
|
kernel_ptd_info.base_addr = KERN_VIRT_START;
|
|
|
|
+ pg_level[1].name = pgtable_l5_enabled ? "P4D" : "PGD";
|
|
+ pg_level[2].name = pgtable_l4_enabled ? "PUD" : "PGD";
|
|
+
|
|
for (i = 0; i < ARRAY_SIZE(pg_level); i++)
|
|
for (j = 0; j < ARRAY_SIZE(pte_bits); j++)
|
|
pg_level[i].mask |= pte_bits[j].mask;
|
|
diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c
|
|
index d5ea09d78938b..7bea3be8b8280 100644
|
|
--- a/arch/s390/mm/page-states.c
|
|
+++ b/arch/s390/mm/page-states.c
|
|
@@ -132,7 +132,7 @@ static void mark_kernel_pud(p4d_t *p4d, unsigned long addr, unsigned long end)
|
|
continue;
|
|
if (!pud_folded(*pud)) {
|
|
page = phys_to_page(pud_val(*pud));
|
|
- for (i = 0; i < 3; i++)
|
|
+ for (i = 0; i < 4; i++)
|
|
set_bit(PG_arch_1, &page[i].flags);
|
|
}
|
|
mark_kernel_pmd(pud, addr, next);
|
|
@@ -153,7 +153,7 @@ static void mark_kernel_p4d(pgd_t *pgd, unsigned long addr, unsigned long end)
|
|
continue;
|
|
if (!p4d_folded(*p4d)) {
|
|
page = phys_to_page(p4d_val(*p4d));
|
|
- for (i = 0; i < 3; i++)
|
|
+ for (i = 0; i < 4; i++)
|
|
set_bit(PG_arch_1, &page[i].flags);
|
|
}
|
|
mark_kernel_pud(p4d, addr, next);
|
|
@@ -175,7 +175,7 @@ static void mark_kernel_pgd(void)
|
|
continue;
|
|
if (!pgd_folded(*pgd)) {
|
|
page = phys_to_page(pgd_val(*pgd));
|
|
- for (i = 0; i < 3; i++)
|
|
+ for (i = 0; i < 4; i++)
|
|
set_bit(PG_arch_1, &page[i].flags);
|
|
}
|
|
mark_kernel_p4d(pgd, addr, next);
|
|
diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c
|
|
index 44340a1139e0b..959afa705e95c 100644
|
|
--- a/arch/x86/crypto/sha1_ssse3_glue.c
|
|
+++ b/arch/x86/crypto/sha1_ssse3_glue.c
|
|
@@ -24,8 +24,17 @@
|
|
#include <linux/types.h>
|
|
#include <crypto/sha1.h>
|
|
#include <crypto/sha1_base.h>
|
|
+#include <asm/cpu_device_id.h>
|
|
#include <asm/simd.h>
|
|
|
|
+static const struct x86_cpu_id module_cpu_ids[] = {
|
|
+ X86_MATCH_FEATURE(X86_FEATURE_AVX2, NULL),
|
|
+ X86_MATCH_FEATURE(X86_FEATURE_AVX, NULL),
|
|
+ X86_MATCH_FEATURE(X86_FEATURE_SSSE3, NULL),
|
|
+ {}
|
|
+};
|
|
+MODULE_DEVICE_TABLE(x86cpu, module_cpu_ids);
|
|
+
|
|
static int sha1_update(struct shash_desc *desc, const u8 *data,
|
|
unsigned int len, sha1_block_fn *sha1_xform)
|
|
{
|
|
@@ -301,6 +310,9 @@ static inline void unregister_sha1_ni(void) { }
|
|
|
|
static int __init sha1_ssse3_mod_init(void)
|
|
{
|
|
+ if (!x86_match_cpu(module_cpu_ids))
|
|
+ return -ENODEV;
|
|
+
|
|
if (register_sha1_ssse3())
|
|
goto fail;
|
|
|
|
diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c
|
|
index 3a5f6be7dbba4..d25235f0ccafc 100644
|
|
--- a/arch/x86/crypto/sha256_ssse3_glue.c
|
|
+++ b/arch/x86/crypto/sha256_ssse3_glue.c
|
|
@@ -38,11 +38,20 @@
|
|
#include <crypto/sha2.h>
|
|
#include <crypto/sha256_base.h>
|
|
#include <linux/string.h>
|
|
+#include <asm/cpu_device_id.h>
|
|
#include <asm/simd.h>
|
|
|
|
asmlinkage void sha256_transform_ssse3(struct sha256_state *state,
|
|
const u8 *data, int blocks);
|
|
|
|
+static const struct x86_cpu_id module_cpu_ids[] = {
|
|
+ X86_MATCH_FEATURE(X86_FEATURE_AVX2, NULL),
|
|
+ X86_MATCH_FEATURE(X86_FEATURE_AVX, NULL),
|
|
+ X86_MATCH_FEATURE(X86_FEATURE_SSSE3, NULL),
|
|
+ {}
|
|
+};
|
|
+MODULE_DEVICE_TABLE(x86cpu, module_cpu_ids);
|
|
+
|
|
static int _sha256_update(struct shash_desc *desc, const u8 *data,
|
|
unsigned int len, sha256_block_fn *sha256_xform)
|
|
{
|
|
@@ -366,6 +375,9 @@ static inline void unregister_sha256_ni(void) { }
|
|
|
|
static int __init sha256_ssse3_mod_init(void)
|
|
{
|
|
+ if (!x86_match_cpu(module_cpu_ids))
|
|
+ return -ENODEV;
|
|
+
|
|
if (register_sha256_ssse3())
|
|
goto fail;
|
|
|
|
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
|
|
index 016fb500b3a6f..ec955ab2ff034 100644
|
|
--- a/arch/x86/include/asm/msr-index.h
|
|
+++ b/arch/x86/include/asm/msr-index.h
|
|
@@ -551,6 +551,7 @@
|
|
#define MSR_AMD64_CPUID_FN_1 0xc0011004
|
|
#define MSR_AMD64_LS_CFG 0xc0011020
|
|
#define MSR_AMD64_DC_CFG 0xc0011022
|
|
+#define MSR_AMD64_TW_CFG 0xc0011023
|
|
|
|
#define MSR_AMD64_DE_CFG 0xc0011029
|
|
#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1
|
|
diff --git a/arch/x86/include/asm/numa.h b/arch/x86/include/asm/numa.h
|
|
index e3bae2b60a0db..ef2844d691735 100644
|
|
--- a/arch/x86/include/asm/numa.h
|
|
+++ b/arch/x86/include/asm/numa.h
|
|
@@ -12,13 +12,6 @@
|
|
|
|
#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
|
|
|
|
-/*
|
|
- * Too small node sizes may confuse the VM badly. Usually they
|
|
- * result from BIOS bugs. So dont recognize nodes as standalone
|
|
- * NUMA entities that have less than this amount of RAM listed:
|
|
- */
|
|
-#define NODE_MIN_SIZE (4*1024*1024)
|
|
-
|
|
extern int numa_off;
|
|
|
|
/*
|
|
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
|
|
index c393b8773ace6..9e8380bd4fb9f 100644
|
|
--- a/arch/x86/kernel/cpu/hygon.c
|
|
+++ b/arch/x86/kernel/cpu/hygon.c
|
|
@@ -86,8 +86,12 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
|
|
if (!err)
|
|
c->x86_coreid_bits = get_count_order(c->x86_max_cores);
|
|
|
|
- /* Socket ID is ApicId[6] for these processors. */
|
|
- c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
|
|
+ /*
|
|
+ * Socket ID is ApicId[6] for the processors with model <= 0x3
|
|
+ * when running on host.
|
|
+ */
|
|
+ if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && c->x86_model <= 0x3)
|
|
+ c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
|
|
|
|
cacheinfo_hygon_init_llc_id(c, cpu);
|
|
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
|
|
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
|
|
index 0adf4a437e85f..04cca46fed1e8 100644
|
|
--- a/arch/x86/kvm/hyperv.c
|
|
+++ b/arch/x86/kvm/hyperv.c
|
|
@@ -705,10 +705,12 @@ static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count,
|
|
|
|
stimer_cleanup(stimer);
|
|
stimer->count = count;
|
|
- if (stimer->count == 0)
|
|
- stimer->config.enable = 0;
|
|
- else if (stimer->config.auto_enable)
|
|
- stimer->config.enable = 1;
|
|
+ if (!host) {
|
|
+ if (stimer->count == 0)
|
|
+ stimer->config.enable = 0;
|
|
+ else if (stimer->config.auto_enable)
|
|
+ stimer->config.enable = 1;
|
|
+ }
|
|
|
|
if (stimer->config.enable)
|
|
stimer_mark_pending(stimer, false);
|
|
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
|
|
index 7e8dbd54869a6..4dba0a84ba2f3 100644
|
|
--- a/arch/x86/kvm/lapic.c
|
|
+++ b/arch/x86/kvm/lapic.c
|
|
@@ -2294,22 +2294,22 @@ EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
|
|
void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
|
|
{
|
|
struct kvm_lapic *apic = vcpu->arch.apic;
|
|
- u64 val;
|
|
|
|
/*
|
|
- * ICR is a single 64-bit register when x2APIC is enabled. For legacy
|
|
- * xAPIC, ICR writes need to go down the common (slightly slower) path
|
|
- * to get the upper half from ICR2.
|
|
+ * ICR is a single 64-bit register when x2APIC is enabled, all others
|
|
+ * registers hold 32-bit values. For legacy xAPIC, ICR writes need to
|
|
+ * go down the common path to get the upper half from ICR2.
|
|
+ *
|
|
+ * Note, using the write helpers may incur an unnecessary write to the
|
|
+ * virtual APIC state, but KVM needs to conditionally modify the value
|
|
+ * in certain cases, e.g. to clear the ICR busy bit. The cost of extra
|
|
+ * conditional branches is likely a wash relative to the cost of the
|
|
+ * maybe-unecessary write, and both are in the noise anyways.
|
|
*/
|
|
- if (apic_x2apic_mode(apic) && offset == APIC_ICR) {
|
|
- val = kvm_lapic_get_reg64(apic, APIC_ICR);
|
|
- kvm_apic_send_ipi(apic, (u32)val, (u32)(val >> 32));
|
|
- trace_kvm_apic_write(APIC_ICR, val);
|
|
- } else {
|
|
- /* TODO: optimize to just emulate side effect w/o one more write */
|
|
- val = kvm_lapic_get_reg(apic, offset);
|
|
- kvm_lapic_reg_write(apic, offset, (u32)val);
|
|
- }
|
|
+ if (apic_x2apic_mode(apic) && offset == APIC_ICR)
|
|
+ kvm_x2apic_icr_write(apic, kvm_lapic_get_reg64(apic, APIC_ICR));
|
|
+ else
|
|
+ kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset));
|
|
}
|
|
EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode);
|
|
|
|
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
|
index 4d6baae1ae748..7144e51668136 100644
|
|
--- a/arch/x86/kvm/x86.c
|
|
+++ b/arch/x86/kvm/x86.c
|
|
@@ -3582,6 +3582,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|
case MSR_AMD64_PATCH_LOADER:
|
|
case MSR_AMD64_BU_CFG2:
|
|
case MSR_AMD64_DC_CFG:
|
|
+ case MSR_AMD64_TW_CFG:
|
|
case MSR_F15H_EX_CFG:
|
|
break;
|
|
|
|
@@ -3982,6 +3983,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|
case MSR_AMD64_BU_CFG2:
|
|
case MSR_IA32_PERF_CTL:
|
|
case MSR_AMD64_DC_CFG:
|
|
+ case MSR_AMD64_TW_CFG:
|
|
case MSR_F15H_EX_CFG:
|
|
/*
|
|
* Intel Sandy Bridge CPUs must support the RAPL (running average power
|
|
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
|
|
index c01c5506fd4ae..aa39d678fe81d 100644
|
|
--- a/arch/x86/mm/numa.c
|
|
+++ b/arch/x86/mm/numa.c
|
|
@@ -602,13 +602,6 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
|
|
if (start >= end)
|
|
continue;
|
|
|
|
- /*
|
|
- * Don't confuse VM with a node that doesn't have the
|
|
- * minimum amount of memory:
|
|
- */
|
|
- if (end && (end - start) < NODE_MIN_SIZE)
|
|
- continue;
|
|
-
|
|
alloc_node_data(nid);
|
|
}
|
|
|
|
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
|
|
index 9d10b846ccf73..005a36cb21bc4 100644
|
|
--- a/crypto/pcrypt.c
|
|
+++ b/crypto/pcrypt.c
|
|
@@ -117,6 +117,8 @@ static int pcrypt_aead_encrypt(struct aead_request *req)
|
|
err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu);
|
|
if (!err)
|
|
return -EINPROGRESS;
|
|
+ if (err == -EBUSY)
|
|
+ return -EAGAIN;
|
|
|
|
return err;
|
|
}
|
|
@@ -164,6 +166,8 @@ static int pcrypt_aead_decrypt(struct aead_request *req)
|
|
err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu);
|
|
if (!err)
|
|
return -EINPROGRESS;
|
|
+ if (err == -EBUSY)
|
|
+ return -EAGAIN;
|
|
|
|
return err;
|
|
}
|
|
diff --git a/drivers/acpi/acpi_fpdt.c b/drivers/acpi/acpi_fpdt.c
|
|
index a2056c4c8cb70..271092f2700a1 100644
|
|
--- a/drivers/acpi/acpi_fpdt.c
|
|
+++ b/drivers/acpi/acpi_fpdt.c
|
|
@@ -194,12 +194,19 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
|
record_header = (void *)subtable_header + offset;
|
|
offset += record_header->length;
|
|
|
|
+ if (!record_header->length) {
|
|
+ pr_err(FW_BUG "Zero-length record found in FPTD.\n");
|
|
+ result = -EINVAL;
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
switch (record_header->type) {
|
|
case RECORD_S3_RESUME:
|
|
if (subtable_type != SUBTABLE_S3PT) {
|
|
pr_err(FW_BUG "Invalid record %d for subtable %s\n",
|
|
record_header->type, signature);
|
|
- return -EINVAL;
|
|
+ result = -EINVAL;
|
|
+ goto err;
|
|
}
|
|
if (record_resume) {
|
|
pr_err("Duplicate resume performance record found.\n");
|
|
@@ -208,7 +215,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
|
record_resume = (struct resume_performance_record *)record_header;
|
|
result = sysfs_create_group(fpdt_kobj, &resume_attr_group);
|
|
if (result)
|
|
- return result;
|
|
+ goto err;
|
|
break;
|
|
case RECORD_S3_SUSPEND:
|
|
if (subtable_type != SUBTABLE_S3PT) {
|
|
@@ -223,13 +230,14 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
|
record_suspend = (struct suspend_performance_record *)record_header;
|
|
result = sysfs_create_group(fpdt_kobj, &suspend_attr_group);
|
|
if (result)
|
|
- return result;
|
|
+ goto err;
|
|
break;
|
|
case RECORD_BOOT:
|
|
if (subtable_type != SUBTABLE_FBPT) {
|
|
pr_err(FW_BUG "Invalid %d for subtable %s\n",
|
|
record_header->type, signature);
|
|
- return -EINVAL;
|
|
+ result = -EINVAL;
|
|
+ goto err;
|
|
}
|
|
if (record_boot) {
|
|
pr_err("Duplicate boot performance record found.\n");
|
|
@@ -238,7 +246,7 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
|
record_boot = (struct boot_performance_record *)record_header;
|
|
result = sysfs_create_group(fpdt_kobj, &boot_attr_group);
|
|
if (result)
|
|
- return result;
|
|
+ goto err;
|
|
break;
|
|
|
|
default:
|
|
@@ -247,6 +255,18 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type)
|
|
}
|
|
}
|
|
return 0;
|
|
+
|
|
+err:
|
|
+ if (record_boot)
|
|
+ sysfs_remove_group(fpdt_kobj, &boot_attr_group);
|
|
+
|
|
+ if (record_suspend)
|
|
+ sysfs_remove_group(fpdt_kobj, &suspend_attr_group);
|
|
+
|
|
+ if (record_resume)
|
|
+ sysfs_remove_group(fpdt_kobj, &resume_attr_group);
|
|
+
|
|
+ return result;
|
|
}
|
|
|
|
static int __init acpi_init_fpdt(void)
|
|
@@ -255,6 +275,7 @@ static int __init acpi_init_fpdt(void)
|
|
struct acpi_table_header *header;
|
|
struct fpdt_subtable_entry *subtable;
|
|
u32 offset = sizeof(*header);
|
|
+ int result;
|
|
|
|
status = acpi_get_table(ACPI_SIG_FPDT, 0, &header);
|
|
|
|
@@ -263,8 +284,8 @@ static int __init acpi_init_fpdt(void)
|
|
|
|
fpdt_kobj = kobject_create_and_add("fpdt", acpi_kobj);
|
|
if (!fpdt_kobj) {
|
|
- acpi_put_table(header);
|
|
- return -ENOMEM;
|
|
+ result = -ENOMEM;
|
|
+ goto err_nomem;
|
|
}
|
|
|
|
while (offset < header->length) {
|
|
@@ -272,8 +293,10 @@ static int __init acpi_init_fpdt(void)
|
|
switch (subtable->type) {
|
|
case SUBTABLE_FBPT:
|
|
case SUBTABLE_S3PT:
|
|
- fpdt_process_subtable(subtable->address,
|
|
+ result = fpdt_process_subtable(subtable->address,
|
|
subtable->type);
|
|
+ if (result)
|
|
+ goto err_subtable;
|
|
break;
|
|
default:
|
|
/* Other types are reserved in ACPI 6.4 spec. */
|
|
@@ -282,6 +305,12 @@ static int __init acpi_init_fpdt(void)
|
|
offset += sizeof(*subtable);
|
|
}
|
|
return 0;
|
|
+err_subtable:
|
|
+ kobject_put(fpdt_kobj);
|
|
+
|
|
+err_nomem:
|
|
+ acpi_put_table(header);
|
|
+ return result;
|
|
}
|
|
|
|
fs_initcall(acpi_init_fpdt);
|
|
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
|
|
index 8bb233d2d1e48..77d1f2cb89ef3 100644
|
|
--- a/drivers/acpi/ec.c
|
|
+++ b/drivers/acpi/ec.c
|
|
@@ -1897,6 +1897,16 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-dk1xxx"),
|
|
},
|
|
},
|
|
+ {
|
|
+ /*
|
|
+ * HP 250 G7 Notebook PC
|
|
+ */
|
|
+ .callback = ec_honor_dsdt_gpe,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP 250 G7 Notebook PC"),
|
|
+ },
|
|
+ },
|
|
{
|
|
/*
|
|
* Samsung hardware
|
|
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
|
|
index af6fa801d1ed8..99bab31919e4c 100644
|
|
--- a/drivers/acpi/resource.c
|
|
+++ b/drivers/acpi/resource.c
|
|
@@ -499,6 +499,18 @@ static const struct dmi_system_id maingear_laptop[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"),
|
|
}
|
|
},
|
|
+ {
|
|
+ /* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
|
|
+ },
|
|
+ },
|
|
{
|
|
.ident = "MAINGEAR Vector Pro 2 17",
|
|
.matches = {
|
|
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
|
|
index 3241486869530..9bba8f280a4d4 100644
|
|
--- a/drivers/atm/iphase.c
|
|
+++ b/drivers/atm/iphase.c
|
|
@@ -2291,19 +2291,21 @@ static int get_esi(struct atm_dev *dev)
|
|
static int reset_sar(struct atm_dev *dev)
|
|
{
|
|
IADEV *iadev;
|
|
- int i, error = 1;
|
|
+ int i, error;
|
|
unsigned int pci[64];
|
|
|
|
iadev = INPH_IA_DEV(dev);
|
|
- for(i=0; i<64; i++)
|
|
- if ((error = pci_read_config_dword(iadev->pci,
|
|
- i*4, &pci[i])) != PCIBIOS_SUCCESSFUL)
|
|
- return error;
|
|
+ for (i = 0; i < 64; i++) {
|
|
+ error = pci_read_config_dword(iadev->pci, i * 4, &pci[i]);
|
|
+ if (error != PCIBIOS_SUCCESSFUL)
|
|
+ return error;
|
|
+ }
|
|
writel(0, iadev->reg+IPHASE5575_EXT_RESET);
|
|
- for(i=0; i<64; i++)
|
|
- if ((error = pci_write_config_dword(iadev->pci,
|
|
- i*4, pci[i])) != PCIBIOS_SUCCESSFUL)
|
|
- return error;
|
|
+ for (i = 0; i < 64; i++) {
|
|
+ error = pci_write_config_dword(iadev->pci, i * 4, pci[i]);
|
|
+ if (error != PCIBIOS_SUCCESSFUL)
|
|
+ return error;
|
|
+ }
|
|
udelay(5);
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
|
|
index 380a53b6aee81..dbbe2cebb8917 100644
|
|
--- a/drivers/base/dd.c
|
|
+++ b/drivers/base/dd.c
|
|
@@ -1262,8 +1262,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
|
|
if (dev->bus && dev->bus->dma_cleanup)
|
|
dev->bus->dma_cleanup(dev);
|
|
|
|
- device_links_driver_cleanup(dev);
|
|
device_unbind_cleanup(dev);
|
|
+ device_links_driver_cleanup(dev);
|
|
|
|
klist_remove(&dev->p->knode_driver);
|
|
device_pm_check_callbacks(dev);
|
|
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
|
|
index 8031007b4887d..cf3fa998093de 100644
|
|
--- a/drivers/base/regmap/regcache.c
|
|
+++ b/drivers/base/regmap/regcache.c
|
|
@@ -331,6 +331,11 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
|
|
return 0;
|
|
}
|
|
|
|
+static int rbtree_all(const void *key, const struct rb_node *node)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/**
|
|
* regcache_sync - Sync the register cache with the hardware.
|
|
*
|
|
@@ -348,6 +353,7 @@ int regcache_sync(struct regmap *map)
|
|
unsigned int i;
|
|
const char *name;
|
|
bool bypass;
|
|
+ struct rb_node *node;
|
|
|
|
if (WARN_ON(map->cache_type == REGCACHE_NONE))
|
|
return -EINVAL;
|
|
@@ -392,6 +398,30 @@ out:
|
|
map->async = false;
|
|
map->cache_bypass = bypass;
|
|
map->no_sync_defaults = false;
|
|
+
|
|
+ /*
|
|
+ * If we did any paging with cache bypassed and a cached
|
|
+ * paging register then the register and cache state might
|
|
+ * have gone out of sync, force writes of all the paging
|
|
+ * registers.
|
|
+ */
|
|
+ rb_for_each(node, 0, &map->range_tree, rbtree_all) {
|
|
+ struct regmap_range_node *this =
|
|
+ rb_entry(node, struct regmap_range_node, node);
|
|
+
|
|
+ /* If there's nothing in the cache there's nothing to sync */
|
|
+ ret = regcache_read(map, this->selector_reg, &i);
|
|
+ if (ret != 0)
|
|
+ continue;
|
|
+
|
|
+ ret = _regmap_write(map, this->selector_reg, i);
|
|
+ if (ret != 0) {
|
|
+ dev_err(map->dev, "Failed to write %x = %x: %d\n",
|
|
+ this->selector_reg, i, ret);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
map->unlock(map->lock_arg);
|
|
|
|
regmap_async_complete(map);
|
|
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
|
|
index a7697027ce43b..efa5535a8e1d8 100644
|
|
--- a/drivers/block/virtio_blk.c
|
|
+++ b/drivers/block/virtio_blk.c
|
|
@@ -900,6 +900,7 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|
u16 min_io_size;
|
|
u8 physical_block_exp, alignment_offset;
|
|
unsigned int queue_depth;
|
|
+ size_t max_dma_size;
|
|
|
|
if (!vdev->config->get) {
|
|
dev_err(&vdev->dev, "%s failure: config access disabled\n",
|
|
@@ -998,7 +999,8 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|
/* No real sector limit. */
|
|
blk_queue_max_hw_sectors(q, -1U);
|
|
|
|
- max_size = virtio_max_dma_size(vdev);
|
|
+ max_dma_size = virtio_max_dma_size(vdev);
|
|
+ max_size = max_dma_size > U32_MAX ? U32_MAX : max_dma_size;
|
|
|
|
/* Host can optionally specify maximum segment size and number of
|
|
* segments. */
|
|
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
|
index 96d4f48e36011..954f7f3b5cc30 100644
|
|
--- a/drivers/bluetooth/btusb.c
|
|
+++ b/drivers/bluetooth/btusb.c
|
|
@@ -532,6 +532,18 @@ static const struct usb_device_id blacklist_table[] = {
|
|
{ USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK |
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
+ /* Realtek 8852BE Bluetooth devices */
|
|
+ { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
|
|
+ BTUSB_WIDEBAND_SPEECH },
|
|
+ { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
|
|
+ BTUSB_WIDEBAND_SPEECH },
|
|
+ { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
|
|
+ BTUSB_WIDEBAND_SPEECH },
|
|
+ { USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK |
|
|
+ BTUSB_WIDEBAND_SPEECH },
|
|
+ { USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
|
|
+ BTUSB_WIDEBAND_SPEECH },
|
|
+
|
|
/* Realtek Bluetooth devices */
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
|
|
.driver_info = BTUSB_REALTEK },
|
|
@@ -2638,6 +2650,9 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
|
|
goto err_free_wc;
|
|
}
|
|
|
|
+ if (data->evt_skb == NULL)
|
|
+ goto err_free_wc;
|
|
+
|
|
/* Parse and handle the return WMT event */
|
|
wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
|
|
if (wmt_evt->whdr.op != hdr->op) {
|
|
diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c
|
|
index cde62a11f5736..4c5c7a8f41d08 100644
|
|
--- a/drivers/clk/qcom/gcc-ipq6018.c
|
|
+++ b/drivers/clk/qcom/gcc-ipq6018.c
|
|
@@ -75,7 +75,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
|
|
&gpll0_main.clkr.hw },
|
|
.num_parents = 1,
|
|
.ops = &clk_fixed_factor_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -89,7 +88,6 @@ static struct clk_alpha_pll_postdiv gpll0 = {
|
|
&gpll0_main.clkr.hw },
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -164,7 +162,6 @@ static struct clk_alpha_pll_postdiv gpll6 = {
|
|
&gpll6_main.clkr.hw },
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -195,7 +192,6 @@ static struct clk_alpha_pll_postdiv gpll4 = {
|
|
&gpll4_main.clkr.hw },
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -246,7 +242,6 @@ static struct clk_alpha_pll_postdiv gpll2 = {
|
|
&gpll2_main.clkr.hw },
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -277,7 +272,6 @@ static struct clk_alpha_pll_postdiv nss_crypto_pll = {
|
|
&nss_crypto_pll_main.clkr.hw },
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c
|
|
index 42d185fe19c8c..b2e83b38976e5 100644
|
|
--- a/drivers/clk/qcom/gcc-ipq8074.c
|
|
+++ b/drivers/clk/qcom/gcc-ipq8074.c
|
|
@@ -419,7 +419,6 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
|
|
},
|
|
.num_parents = 1,
|
|
.ops = &clk_fixed_factor_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -466,7 +465,6 @@ static struct clk_alpha_pll_postdiv gpll2 = {
|
|
},
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -499,7 +497,6 @@ static struct clk_alpha_pll_postdiv gpll4 = {
|
|
},
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -533,7 +530,6 @@ static struct clk_alpha_pll_postdiv gpll6 = {
|
|
},
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -547,7 +543,6 @@ static struct clk_fixed_factor gpll6_out_main_div2 = {
|
|
},
|
|
.num_parents = 1,
|
|
.ops = &clk_fixed_factor_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
@@ -612,7 +607,6 @@ static struct clk_alpha_pll_postdiv nss_crypto_pll = {
|
|
},
|
|
.num_parents = 1,
|
|
.ops = &clk_alpha_pll_postdiv_ro_ops,
|
|
- .flags = CLK_SET_RATE_PARENT,
|
|
},
|
|
};
|
|
|
|
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
|
|
index 75234e0783e1c..83fe4eb3133cb 100644
|
|
--- a/drivers/clk/socfpga/stratix10-clk.h
|
|
+++ b/drivers/clk/socfpga/stratix10-clk.h
|
|
@@ -7,8 +7,10 @@
|
|
#define __STRATIX10_CLK_H
|
|
|
|
struct stratix10_clock_data {
|
|
- struct clk_hw_onecell_data clk_data;
|
|
void __iomem *base;
|
|
+
|
|
+ /* Must be last */
|
|
+ struct clk_hw_onecell_data clk_data;
|
|
};
|
|
|
|
struct stratix10_pll_clock {
|
|
diff --git a/drivers/clk/visconti/pll.h b/drivers/clk/visconti/pll.h
|
|
index 16dae35ab3701..c4bd40676da4b 100644
|
|
--- a/drivers/clk/visconti/pll.h
|
|
+++ b/drivers/clk/visconti/pll.h
|
|
@@ -15,9 +15,10 @@
|
|
|
|
struct visconti_pll_provider {
|
|
void __iomem *reg_base;
|
|
- struct regmap *regmap;
|
|
- struct clk_hw_onecell_data clk_data;
|
|
struct device_node *node;
|
|
+
|
|
+ /* Must be last */
|
|
+ struct clk_hw_onecell_data clk_data;
|
|
};
|
|
|
|
#define VISCONTI_PLL_RATE(_rate, _dacen, _dsmen, \
|
|
diff --git a/drivers/clocksource/timer-atmel-tcb.c b/drivers/clocksource/timer-atmel-tcb.c
|
|
index 27af17c995900..2a90c92a9182a 100644
|
|
--- a/drivers/clocksource/timer-atmel-tcb.c
|
|
+++ b/drivers/clocksource/timer-atmel-tcb.c
|
|
@@ -315,6 +315,7 @@ static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx)
|
|
writel(mck_divisor_idx /* likely divide-by-8 */
|
|
| ATMEL_TC_WAVE
|
|
| ATMEL_TC_WAVESEL_UP /* free-run */
|
|
+ | ATMEL_TC_ASWTRG_SET /* TIOA0 rises at software trigger */
|
|
| ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
|
|
| ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
|
|
tcaddr + ATMEL_TC_REG(0, CMR));
|
|
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
|
|
index 7b2c70f2f353b..fabff69e52e58 100644
|
|
--- a/drivers/clocksource/timer-imx-gpt.c
|
|
+++ b/drivers/clocksource/timer-imx-gpt.c
|
|
@@ -454,12 +454,16 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
|
|
return -ENOMEM;
|
|
|
|
imxtm->base = of_iomap(np, 0);
|
|
- if (!imxtm->base)
|
|
- return -ENXIO;
|
|
+ if (!imxtm->base) {
|
|
+ ret = -ENXIO;
|
|
+ goto err_kfree;
|
|
+ }
|
|
|
|
imxtm->irq = irq_of_parse_and_map(np, 0);
|
|
- if (imxtm->irq <= 0)
|
|
- return -EINVAL;
|
|
+ if (imxtm->irq <= 0) {
|
|
+ ret = -EINVAL;
|
|
+ goto err_kfree;
|
|
+ }
|
|
|
|
imxtm->clk_ipg = of_clk_get_by_name(np, "ipg");
|
|
|
|
@@ -472,11 +476,15 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
|
|
|
|
ret = _mxc_timer_init(imxtm);
|
|
if (ret)
|
|
- return ret;
|
|
+ goto err_kfree;
|
|
|
|
initialized = 1;
|
|
|
|
return 0;
|
|
+
|
|
+err_kfree:
|
|
+ kfree(imxtm);
|
|
+ return ret;
|
|
}
|
|
|
|
static int __init imx1_timer_init_dt(struct device_node *np)
|
|
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
|
|
index 1570d6f3e75d3..6e57df7a2249f 100644
|
|
--- a/drivers/cpufreq/cpufreq_stats.c
|
|
+++ b/drivers/cpufreq/cpufreq_stats.c
|
|
@@ -131,25 +131,25 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
|
len += scnprintf(buf + len, PAGE_SIZE - len, " From : To\n");
|
|
len += scnprintf(buf + len, PAGE_SIZE - len, " : ");
|
|
for (i = 0; i < stats->state_num; i++) {
|
|
- if (len >= PAGE_SIZE)
|
|
+ if (len >= PAGE_SIZE - 1)
|
|
break;
|
|
len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ",
|
|
stats->freq_table[i]);
|
|
}
|
|
- if (len >= PAGE_SIZE)
|
|
- return PAGE_SIZE;
|
|
+ if (len >= PAGE_SIZE - 1)
|
|
+ return PAGE_SIZE - 1;
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
|
|
|
|
for (i = 0; i < stats->state_num; i++) {
|
|
- if (len >= PAGE_SIZE)
|
|
+ if (len >= PAGE_SIZE - 1)
|
|
break;
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE - len, "%9u: ",
|
|
stats->freq_table[i]);
|
|
|
|
for (j = 0; j < stats->state_num; j++) {
|
|
- if (len >= PAGE_SIZE)
|
|
+ if (len >= PAGE_SIZE - 1)
|
|
break;
|
|
|
|
if (pending)
|
|
@@ -159,12 +159,12 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
|
|
|
len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ", count);
|
|
}
|
|
- if (len >= PAGE_SIZE)
|
|
+ if (len >= PAGE_SIZE - 1)
|
|
break;
|
|
len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
|
|
}
|
|
|
|
- if (len >= PAGE_SIZE) {
|
|
+ if (len >= PAGE_SIZE - 1) {
|
|
pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n");
|
|
return -EFBIG;
|
|
}
|
|
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
|
|
index a4a3895c74181..f9acf7ecc41be 100644
|
|
--- a/drivers/crypto/hisilicon/qm.c
|
|
+++ b/drivers/crypto/hisilicon/qm.c
|
|
@@ -841,6 +841,8 @@ static void qm_poll_req_cb(struct hisi_qp *qp)
|
|
qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ,
|
|
qp->qp_status.cq_head, 0);
|
|
atomic_dec(&qp->qp_status.used);
|
|
+
|
|
+ cond_resched();
|
|
}
|
|
|
|
/* set c_flag */
|
|
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
|
|
index 07b184382707e..dd610556a3afa 100644
|
|
--- a/drivers/cxl/acpi.c
|
|
+++ b/drivers/cxl/acpi.c
|
|
@@ -219,7 +219,6 @@ static int add_host_bridge_uport(struct device *match, void *arg)
|
|
port = devm_cxl_add_port(host, match, dport->component_reg_phys, dport);
|
|
if (IS_ERR(port))
|
|
return PTR_ERR(port);
|
|
- dev_dbg(host, "%s: add: %s\n", dev_name(match), dev_name(&port->dev));
|
|
|
|
return 0;
|
|
}
|
|
@@ -465,7 +464,6 @@ static int cxl_acpi_probe(struct platform_device *pdev)
|
|
root_port = devm_cxl_add_port(host, host, CXL_RESOURCE_NONE, NULL);
|
|
if (IS_ERR(root_port))
|
|
return PTR_ERR(root_port);
|
|
- dev_dbg(host, "add: %s\n", dev_name(&root_port->dev));
|
|
|
|
rc = bus_for_each_dev(adev->dev.bus, NULL, root_port,
|
|
add_host_bridge_dport);
|
|
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
|
|
index 1d8f87be283fb..cbee2340f1bce 100644
|
|
--- a/drivers/cxl/core/core.h
|
|
+++ b/drivers/cxl/core/core.h
|
|
@@ -56,17 +56,6 @@ resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled);
|
|
resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled);
|
|
extern struct rw_semaphore cxl_dpa_rwsem;
|
|
|
|
-bool is_switch_decoder(struct device *dev);
|
|
-struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
|
|
-static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port,
|
|
- struct cxl_memdev *cxlmd)
|
|
-{
|
|
- if (!port)
|
|
- return NULL;
|
|
-
|
|
- return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev);
|
|
-}
|
|
-
|
|
int cxl_memdev_init(void);
|
|
void cxl_memdev_exit(void);
|
|
void cxl_mbox_init(void);
|
|
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
|
|
index 5aa0726aafe6f..8c1db4e1b816d 100644
|
|
--- a/drivers/cxl/core/hdm.c
|
|
+++ b/drivers/cxl/core/hdm.c
|
|
@@ -276,7 +276,7 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
|
|
return 0;
|
|
}
|
|
|
|
-static int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
|
|
+int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
|
|
resource_size_t base, resource_size_t len,
|
|
resource_size_t skipped)
|
|
{
|
|
@@ -292,6 +292,7 @@ static int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
|
|
|
|
return devm_add_action_or_reset(&port->dev, cxl_dpa_release, cxled);
|
|
}
|
|
+EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, CXL);
|
|
|
|
resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled)
|
|
{
|
|
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
|
|
index e7556864ea808..bd41424319807 100644
|
|
--- a/drivers/cxl/core/port.c
|
|
+++ b/drivers/cxl/core/port.c
|
|
@@ -455,6 +455,7 @@ bool is_switch_decoder(struct device *dev)
|
|
{
|
|
return is_root_decoder(dev) || dev->type == &cxl_decoder_switch_type;
|
|
}
|
|
+EXPORT_SYMBOL_NS_GPL(is_switch_decoder, CXL);
|
|
|
|
struct cxl_decoder *to_cxl_decoder(struct device *dev)
|
|
{
|
|
@@ -482,6 +483,7 @@ struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
|
|
return NULL;
|
|
return container_of(dev, struct cxl_switch_decoder, cxld.dev);
|
|
}
|
|
+EXPORT_SYMBOL_NS_GPL(to_cxl_switch_decoder, CXL);
|
|
|
|
static void cxl_ep_release(struct cxl_ep *ep)
|
|
{
|
|
@@ -655,16 +657,10 @@ err:
|
|
return ERR_PTR(rc);
|
|
}
|
|
|
|
-/**
|
|
- * devm_cxl_add_port - register a cxl_port in CXL memory decode hierarchy
|
|
- * @host: host device for devm operations
|
|
- * @uport: "physical" device implementing this upstream port
|
|
- * @component_reg_phys: (optional) for configurable cxl_port instances
|
|
- * @parent_dport: next hop up in the CXL memory decode hierarchy
|
|
- */
|
|
-struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
|
|
- resource_size_t component_reg_phys,
|
|
- struct cxl_dport *parent_dport)
|
|
+static struct cxl_port *__devm_cxl_add_port(struct device *host,
|
|
+ struct device *uport,
|
|
+ resource_size_t component_reg_phys,
|
|
+ struct cxl_dport *parent_dport)
|
|
{
|
|
struct cxl_port *port;
|
|
struct device *dev;
|
|
@@ -702,6 +698,40 @@ err:
|
|
put_device(dev);
|
|
return ERR_PTR(rc);
|
|
}
|
|
+
|
|
+/**
|
|
+ * devm_cxl_add_port - register a cxl_port in CXL memory decode hierarchy
|
|
+ * @host: host device for devm operations
|
|
+ * @uport: "physical" device implementing this upstream port
|
|
+ * @component_reg_phys: (optional) for configurable cxl_port instances
|
|
+ * @parent_dport: next hop up in the CXL memory decode hierarchy
|
|
+ */
|
|
+struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
|
|
+ resource_size_t component_reg_phys,
|
|
+ struct cxl_dport *parent_dport)
|
|
+{
|
|
+ struct cxl_port *port, *parent_port;
|
|
+
|
|
+ port = __devm_cxl_add_port(host, uport, component_reg_phys,
|
|
+ parent_dport);
|
|
+
|
|
+ parent_port = parent_dport ? parent_dport->port : NULL;
|
|
+ if (IS_ERR(port)) {
|
|
+ dev_dbg(uport, "Failed to add%s%s%s: %ld\n",
|
|
+ parent_port ? " port to " : "",
|
|
+ parent_port ? dev_name(&parent_port->dev) : "",
|
|
+ parent_port ? "" : " root port",
|
|
+ PTR_ERR(port));
|
|
+ } else {
|
|
+ dev_dbg(uport, "%s added%s%s%s\n",
|
|
+ dev_name(&port->dev),
|
|
+ parent_port ? " to " : "",
|
|
+ parent_port ? dev_name(&parent_port->dev) : "",
|
|
+ parent_port ? "" : " (root port)");
|
|
+ }
|
|
+
|
|
+ return port;
|
|
+}
|
|
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_port, CXL);
|
|
|
|
struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port)
|
|
@@ -1122,47 +1152,6 @@ static void reap_dports(struct cxl_port *port)
|
|
}
|
|
}
|
|
|
|
-int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
|
|
- struct cxl_dport *parent_dport)
|
|
-{
|
|
- struct cxl_port *parent_port = parent_dport->port;
|
|
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
|
|
- struct cxl_port *endpoint, *iter, *down;
|
|
- int rc;
|
|
-
|
|
- /*
|
|
- * Now that the path to the root is established record all the
|
|
- * intervening ports in the chain.
|
|
- */
|
|
- for (iter = parent_port, down = NULL; !is_cxl_root(iter);
|
|
- down = iter, iter = to_cxl_port(iter->dev.parent)) {
|
|
- struct cxl_ep *ep;
|
|
-
|
|
- ep = cxl_ep_load(iter, cxlmd);
|
|
- ep->next = down;
|
|
- }
|
|
-
|
|
- endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
|
|
- cxlds->component_reg_phys, parent_dport);
|
|
- if (IS_ERR(endpoint))
|
|
- return PTR_ERR(endpoint);
|
|
-
|
|
- dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev));
|
|
-
|
|
- rc = cxl_endpoint_autoremove(cxlmd, endpoint);
|
|
- if (rc)
|
|
- return rc;
|
|
-
|
|
- if (!endpoint->dev.driver) {
|
|
- dev_err(&cxlmd->dev, "%s failed probe\n",
|
|
- dev_name(&endpoint->dev));
|
|
- return -ENXIO;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_endpoint, CXL);
|
|
-
|
|
static void cxl_detach_ep(void *data)
|
|
{
|
|
struct cxl_memdev *cxlmd = data;
|
|
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
|
|
index 9709bbf773b72..ebc1b028555ca 100644
|
|
--- a/drivers/cxl/core/region.c
|
|
+++ b/drivers/cxl/core/region.c
|
|
@@ -1012,7 +1012,14 @@ static int cxl_port_setup_targets(struct cxl_port *port,
|
|
}
|
|
|
|
if (is_cxl_root(parent_port)) {
|
|
- parent_ig = cxlrd->cxlsd.cxld.interleave_granularity;
|
|
+ /*
|
|
+ * Root decoder IG is always set to value in CFMWS which
|
|
+ * may be different than this region's IG. We can use the
|
|
+ * region's IG here since interleave_granularity_store()
|
|
+ * does not allow interleaved host-bridges with
|
|
+ * root IG != region IG.
|
|
+ */
|
|
+ parent_ig = p->interleave_granularity;
|
|
parent_iw = cxlrd->cxlsd.cxld.interleave_ways;
|
|
/*
|
|
* For purposes of address bit routing, use power-of-2 math for
|
|
@@ -1181,29 +1188,13 @@ static int cxl_region_setup_targets(struct cxl_region *cxlr)
|
|
return 0;
|
|
}
|
|
|
|
-static int cxl_region_attach(struct cxl_region *cxlr,
|
|
- struct cxl_endpoint_decoder *cxled, int pos)
|
|
+static int cxl_region_validate_position(struct cxl_region *cxlr,
|
|
+ struct cxl_endpoint_decoder *cxled,
|
|
+ int pos)
|
|
{
|
|
- struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
|
|
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
|
|
- struct cxl_port *ep_port, *root_port, *iter;
|
|
struct cxl_region_params *p = &cxlr->params;
|
|
- struct cxl_dport *dport;
|
|
- int i, rc = -ENXIO;
|
|
-
|
|
- if (cxled->mode == CXL_DECODER_DEAD) {
|
|
- dev_dbg(&cxlr->dev, "%s dead\n", dev_name(&cxled->cxld.dev));
|
|
- return -ENODEV;
|
|
- }
|
|
-
|
|
- /* all full of members, or interleave config not established? */
|
|
- if (p->state > CXL_CONFIG_INTERLEAVE_ACTIVE) {
|
|
- dev_dbg(&cxlr->dev, "region already active\n");
|
|
- return -EBUSY;
|
|
- } else if (p->state < CXL_CONFIG_INTERLEAVE_ACTIVE) {
|
|
- dev_dbg(&cxlr->dev, "interleave config missing\n");
|
|
- return -ENXIO;
|
|
- }
|
|
+ int i;
|
|
|
|
if (pos < 0 || pos >= p->interleave_ways) {
|
|
dev_dbg(&cxlr->dev, "position %d out of range %d\n", pos,
|
|
@@ -1242,6 +1233,77 @@ static int cxl_region_attach(struct cxl_region *cxlr,
|
|
}
|
|
}
|
|
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int cxl_region_attach_position(struct cxl_region *cxlr,
|
|
+ struct cxl_root_decoder *cxlrd,
|
|
+ struct cxl_endpoint_decoder *cxled,
|
|
+ const struct cxl_dport *dport, int pos)
|
|
+{
|
|
+ struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
|
|
+ struct cxl_port *iter;
|
|
+ int rc;
|
|
+
|
|
+ if (cxlrd->calc_hb(cxlrd, pos) != dport) {
|
|
+ dev_dbg(&cxlr->dev, "%s:%s invalid target position for %s\n",
|
|
+ dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
|
|
+ dev_name(&cxlrd->cxlsd.cxld.dev));
|
|
+ return -ENXIO;
|
|
+ }
|
|
+
|
|
+ for (iter = cxled_to_port(cxled); !is_cxl_root(iter);
|
|
+ iter = to_cxl_port(iter->dev.parent)) {
|
|
+ rc = cxl_port_attach_region(iter, cxlr, cxled, pos);
|
|
+ if (rc)
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err:
|
|
+ for (iter = cxled_to_port(cxled); !is_cxl_root(iter);
|
|
+ iter = to_cxl_port(iter->dev.parent))
|
|
+ cxl_port_detach_region(iter, cxlr, cxled);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+static int cxl_region_attach(struct cxl_region *cxlr,
|
|
+ struct cxl_endpoint_decoder *cxled, int pos)
|
|
+{
|
|
+ struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
|
|
+ struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
|
|
+ struct cxl_region_params *p = &cxlr->params;
|
|
+ struct cxl_port *ep_port, *root_port;
|
|
+ struct cxl_dport *dport;
|
|
+ int rc = -ENXIO;
|
|
+
|
|
+ if (cxled->mode != cxlr->mode) {
|
|
+ dev_dbg(&cxlr->dev, "%s region mode: %d mismatch: %d\n",
|
|
+ dev_name(&cxled->cxld.dev), cxlr->mode, cxled->mode);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (cxled->mode == CXL_DECODER_DEAD) {
|
|
+ dev_dbg(&cxlr->dev, "%s dead\n", dev_name(&cxled->cxld.dev));
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ /* all full of members, or interleave config not established? */
|
|
+ if (p->state > CXL_CONFIG_INTERLEAVE_ACTIVE) {
|
|
+ dev_dbg(&cxlr->dev, "region already active\n");
|
|
+ return -EBUSY;
|
|
+ } else if (p->state < CXL_CONFIG_INTERLEAVE_ACTIVE) {
|
|
+ dev_dbg(&cxlr->dev, "interleave config missing\n");
|
|
+ return -ENXIO;
|
|
+ }
|
|
+
|
|
+ if (p->nr_targets >= p->interleave_ways) {
|
|
+ dev_dbg(&cxlr->dev, "region already has %d endpoints\n",
|
|
+ p->nr_targets);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
ep_port = cxled_to_port(cxled);
|
|
root_port = cxlrd_to_port(cxlrd);
|
|
dport = cxl_find_dport_by_dev(root_port, ep_port->host_bridge);
|
|
@@ -1252,13 +1314,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
|
|
return -ENXIO;
|
|
}
|
|
|
|
- if (cxlrd->calc_hb(cxlrd, pos) != dport) {
|
|
- dev_dbg(&cxlr->dev, "%s:%s invalid target position for %s\n",
|
|
- dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
|
|
- dev_name(&cxlrd->cxlsd.cxld.dev));
|
|
- return -ENXIO;
|
|
- }
|
|
-
|
|
if (cxled->cxld.target_type != cxlr->type) {
|
|
dev_dbg(&cxlr->dev, "%s:%s type mismatch: %d vs %d\n",
|
|
dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
|
|
@@ -1282,12 +1337,13 @@ static int cxl_region_attach(struct cxl_region *cxlr,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- for (iter = ep_port; !is_cxl_root(iter);
|
|
- iter = to_cxl_port(iter->dev.parent)) {
|
|
- rc = cxl_port_attach_region(iter, cxlr, cxled, pos);
|
|
- if (rc)
|
|
- goto err;
|
|
- }
|
|
+ rc = cxl_region_validate_position(cxlr, cxled, pos);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
+ rc = cxl_region_attach_position(cxlr, cxlrd, cxled, dport, pos);
|
|
+ if (rc)
|
|
+ return rc;
|
|
|
|
p->targets[pos] = cxled;
|
|
cxled->pos = pos;
|
|
@@ -1296,7 +1352,7 @@ static int cxl_region_attach(struct cxl_region *cxlr,
|
|
if (p->nr_targets == p->interleave_ways) {
|
|
rc = cxl_region_setup_targets(cxlr);
|
|
if (rc)
|
|
- goto err_decrement;
|
|
+ return rc;
|
|
p->state = CXL_CONFIG_ACTIVE;
|
|
}
|
|
|
|
@@ -1308,14 +1364,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
|
|
};
|
|
|
|
return 0;
|
|
-
|
|
-err_decrement:
|
|
- p->nr_targets--;
|
|
-err:
|
|
- for (iter = ep_port; !is_cxl_root(iter);
|
|
- iter = to_cxl_port(iter->dev.parent))
|
|
- cxl_port_detach_region(iter, cxlr, cxled);
|
|
- return rc;
|
|
}
|
|
|
|
static int cxl_region_detach(struct cxl_endpoint_decoder *cxled)
|
|
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
|
|
index ac75554b5d763..7750ccb7652db 100644
|
|
--- a/drivers/cxl/cxl.h
|
|
+++ b/drivers/cxl/cxl.h
|
|
@@ -562,8 +562,6 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port);
|
|
struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
|
|
resource_size_t component_reg_phys,
|
|
struct cxl_dport *parent_dport);
|
|
-int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
|
|
- struct cxl_dport *parent_dport);
|
|
struct cxl_port *find_cxl_root(struct device *dev);
|
|
int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
|
|
int cxl_bus_rescan(void);
|
|
@@ -577,8 +575,10 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
|
|
|
|
struct cxl_decoder *to_cxl_decoder(struct device *dev);
|
|
struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
|
|
+struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
|
|
struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
|
|
bool is_root_decoder(struct device *dev);
|
|
+bool is_switch_decoder(struct device *dev);
|
|
bool is_endpoint_decoder(struct device *dev);
|
|
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
|
|
unsigned int nr_targets);
|
|
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
|
|
index 88e3a8e54b6a4..b58a5b782e5dc 100644
|
|
--- a/drivers/cxl/cxlmem.h
|
|
+++ b/drivers/cxl/cxlmem.h
|
|
@@ -75,6 +75,18 @@ static inline bool is_cxl_endpoint(struct cxl_port *port)
|
|
}
|
|
|
|
struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds);
|
|
+int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
|
|
+ resource_size_t base, resource_size_t len,
|
|
+ resource_size_t skipped);
|
|
+
|
|
+static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port,
|
|
+ struct cxl_memdev *cxlmd)
|
|
+{
|
|
+ if (!port)
|
|
+ return NULL;
|
|
+
|
|
+ return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev);
|
|
+}
|
|
|
|
/**
|
|
* struct cxl_mbox_cmd - A command to be submitted to hardware.
|
|
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
|
|
index 64ccf053d32c3..80263d12a8541 100644
|
|
--- a/drivers/cxl/mem.c
|
|
+++ b/drivers/cxl/mem.c
|
|
@@ -45,6 +45,44 @@ static int cxl_mem_dpa_show(struct seq_file *file, void *data)
|
|
return 0;
|
|
}
|
|
|
|
+static int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
|
|
+ struct cxl_dport *parent_dport)
|
|
+{
|
|
+ struct cxl_port *parent_port = parent_dport->port;
|
|
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
|
|
+ struct cxl_port *endpoint, *iter, *down;
|
|
+ int rc;
|
|
+
|
|
+ /*
|
|
+ * Now that the path to the root is established record all the
|
|
+ * intervening ports in the chain.
|
|
+ */
|
|
+ for (iter = parent_port, down = NULL; !is_cxl_root(iter);
|
|
+ down = iter, iter = to_cxl_port(iter->dev.parent)) {
|
|
+ struct cxl_ep *ep;
|
|
+
|
|
+ ep = cxl_ep_load(iter, cxlmd);
|
|
+ ep->next = down;
|
|
+ }
|
|
+
|
|
+ endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
|
|
+ cxlds->component_reg_phys, parent_dport);
|
|
+ if (IS_ERR(endpoint))
|
|
+ return PTR_ERR(endpoint);
|
|
+
|
|
+ rc = cxl_endpoint_autoremove(cxlmd, endpoint);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+
|
|
+ if (!endpoint->dev.driver) {
|
|
+ dev_err(&cxlmd->dev, "%s failed probe\n",
|
|
+ dev_name(&endpoint->dev));
|
|
+ return -ENXIO;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int cxl_mem_probe(struct device *dev)
|
|
{
|
|
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
|
|
diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c
|
|
index 4e9bab61f4663..65ef1f5ca6b89 100644
|
|
--- a/drivers/dma/stm32-mdma.c
|
|
+++ b/drivers/dma/stm32-mdma.c
|
|
@@ -490,7 +490,7 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan,
|
|
src_maxburst = chan->dma_config.src_maxburst;
|
|
dst_maxburst = chan->dma_config.dst_maxburst;
|
|
|
|
- ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
|
|
+ ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & ~STM32_MDMA_CCR_EN;
|
|
ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
|
|
ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
|
|
|
|
@@ -966,7 +966,7 @@ stm32_mdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest, dma_addr_t src,
|
|
if (!desc)
|
|
return NULL;
|
|
|
|
- ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
|
|
+ ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & ~STM32_MDMA_CCR_EN;
|
|
ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
|
|
ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
|
|
cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id));
|
|
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
|
|
index 51eb85354c058..58f1a86065dc9 100644
|
|
--- a/drivers/firmware/qcom_scm.c
|
|
+++ b/drivers/firmware/qcom_scm.c
|
|
@@ -164,6 +164,12 @@ static enum qcom_scm_convention __get_convention(void)
|
|
if (likely(qcom_scm_convention != SMC_CONVENTION_UNKNOWN))
|
|
return qcom_scm_convention;
|
|
|
|
+ /*
|
|
+ * Per the "SMC calling convention specification", the 64-bit calling
|
|
+ * convention can only be used when the client is 64-bit, otherwise
|
|
+ * system will encounter the undefined behaviour.
|
|
+ */
|
|
+#if IS_ENABLED(CONFIG_ARM64)
|
|
/*
|
|
* Device isn't required as there is only one argument - no device
|
|
* needed to dma_map_single to secure world
|
|
@@ -184,6 +190,7 @@ static enum qcom_scm_convention __get_convention(void)
|
|
forced = true;
|
|
goto found;
|
|
}
|
|
+#endif
|
|
|
|
probed_convention = SMC_CONVENTION_ARM_32;
|
|
ret = __scm_smc_call(NULL, &desc, probed_convention, &res, true);
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
|
|
index 30c28a69e847d..e4ad2bd8d8110 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
|
|
@@ -29,6 +29,7 @@
|
|
#include "amdgpu.h"
|
|
#include "atom.h"
|
|
|
|
+#include <linux/device.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/acpi.h>
|
|
@@ -289,6 +290,10 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
|
|
if (adev->flags & AMD_IS_APU)
|
|
return false;
|
|
|
|
+ /* ATRM is for on-platform devices only */
|
|
+ if (dev_is_removable(&adev->pdev->dev))
|
|
+ return false;
|
|
+
|
|
while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
|
|
dhandle = ACPI_HANDLE(&pdev->dev);
|
|
if (!dhandle)
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
|
|
index 252a876b07258..fdc302aa59e7b 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
|
|
@@ -179,6 +179,7 @@ int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id,
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
+ *result = NULL;
|
|
return -ENOENT;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
|
|
index 4624160315648..ced4e7e8f98b5 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
|
|
@@ -1391,7 +1391,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|
if (r == -ENOMEM)
|
|
DRM_ERROR("Not enough memory for command submission!\n");
|
|
else if (r != -ERESTARTSYS && r != -EAGAIN)
|
|
- DRM_ERROR("Failed to process the buffer list %d!\n", r);
|
|
+ DRM_DEBUG("Failed to process the buffer list %d!\n", r);
|
|
goto error_fini;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
|
|
index de61a85c4b022..fd796574f87a5 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
|
|
@@ -589,6 +589,9 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf,
|
|
ssize_t result = 0;
|
|
int r;
|
|
|
|
+ if (!adev->smc_rreg)
|
|
+ return -EPERM;
|
|
+
|
|
if (size & 0x3 || *pos & 0x3)
|
|
return -EINVAL;
|
|
|
|
@@ -645,6 +648,9 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *
|
|
ssize_t result = 0;
|
|
int r;
|
|
|
|
+ if (!adev->smc_wreg)
|
|
+ return -EPERM;
|
|
+
|
|
if (size & 0x3 || *pos & 0x3)
|
|
return -EINVAL;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
index 92fa2faf63e41..8a1b84aaaf717 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
@@ -41,6 +41,7 @@
|
|
#include <drm/drm_atomic_helper.h>
|
|
#include <drm/drm_probe_helper.h>
|
|
#include <drm/amdgpu_drm.h>
|
|
+#include <linux/device.h>
|
|
#include <linux/vgaarb.h>
|
|
#include <linux/vga_switcheroo.h>
|
|
#include <linux/efi.h>
|
|
@@ -2105,7 +2106,6 @@ out:
|
|
*/
|
|
static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|
{
|
|
- struct drm_device *dev = adev_to_drm(adev);
|
|
struct pci_dev *parent;
|
|
int i, r;
|
|
|
|
@@ -2175,7 +2175,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
|
(amdgpu_is_atpx_hybrid() ||
|
|
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
|
((adev->flags & AMD_IS_APU) == 0) &&
|
|
- !pci_is_thunderbolt_attached(to_pci_dev(dev->dev)))
|
|
+ !dev_is_removable(&adev->pdev->dev))
|
|
adev->flags |= AMD_IS_PX;
|
|
|
|
if (!(adev->flags & AMD_IS_APU)) {
|
|
@@ -3968,7 +3968,7 @@ fence_driver_init:
|
|
|
|
px = amdgpu_device_supports_px(ddev);
|
|
|
|
- if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
|
|
+ if (px || (!dev_is_removable(&adev->pdev->dev) &&
|
|
apple_gmux_detect(NULL, NULL)))
|
|
vga_switcheroo_register_client(adev->pdev,
|
|
&amdgpu_switcheroo_ops, px);
|
|
@@ -4117,7 +4117,7 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
|
|
|
px = amdgpu_device_supports_px(adev_to_drm(adev));
|
|
|
|
- if (px || (!pci_is_thunderbolt_attached(adev->pdev) &&
|
|
+ if (px || (!dev_is_removable(&adev->pdev->dev) &&
|
|
apple_gmux_detect(NULL, NULL)))
|
|
vga_switcheroo_unregister_client(adev->pdev);
|
|
|
|
@@ -5330,7 +5330,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|
* Flush RAM to disk so that after reboot
|
|
* the user can read log and see why the system rebooted.
|
|
*/
|
|
- if (need_emergency_restart && amdgpu_ras_get_context(adev)->reboot) {
|
|
+ if (need_emergency_restart && amdgpu_ras_get_context(adev) &&
|
|
+ amdgpu_ras_get_context(adev)->reboot) {
|
|
DRM_WARN("Emergency reboot.");
|
|
|
|
ksys_sync_helper();
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
index 09fc464f5f128..9fe2eae88ec17 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
|
|
@@ -1273,7 +1273,8 @@ static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev)
|
|
{
|
|
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
|
|
|
|
- sysfs_remove_file_from_group(&adev->dev->kobj,
|
|
+ if (adev->dev->kobj.sd)
|
|
+ sysfs_remove_file_from_group(&adev->dev->kobj,
|
|
&con->badpages_attr.attr,
|
|
RAS_FS_NAME);
|
|
}
|
|
@@ -1290,7 +1291,8 @@ static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev)
|
|
.attrs = attrs,
|
|
};
|
|
|
|
- sysfs_remove_group(&adev->dev->kobj, &group);
|
|
+ if (adev->dev->kobj.sd)
|
|
+ sysfs_remove_group(&adev->dev->kobj, &group);
|
|
|
|
return 0;
|
|
}
|
|
@@ -1337,7 +1339,8 @@ int amdgpu_ras_sysfs_remove(struct amdgpu_device *adev,
|
|
if (!obj || !obj->attr_inuse)
|
|
return -EINVAL;
|
|
|
|
- sysfs_remove_file_from_group(&adev->dev->kobj,
|
|
+ if (adev->dev->kobj.sd)
|
|
+ sysfs_remove_file_from_group(&adev->dev->kobj,
|
|
&obj->sysfs_attr.attr,
|
|
RAS_FS_NAME);
|
|
obj->attr_inuse = 0;
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
|
|
index 5c1193dd7d88c..48e612023d0c7 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
|
|
@@ -391,8 +391,15 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
|
|
void *ptr;
|
|
int i, idx;
|
|
|
|
+ bool in_ras_intr = amdgpu_ras_intr_triggered();
|
|
+
|
|
cancel_delayed_work_sync(&adev->vcn.idle_work);
|
|
|
|
+ /* err_event_athub will corrupt VCPU buffer, so we need to
|
|
+ * restore fw data and clear buffer in amdgpu_vcn_resume() */
|
|
+ if (in_ras_intr)
|
|
+ return 0;
|
|
+
|
|
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
|
|
if (adev->vcn.harvest_config & (1 << i))
|
|
continue;
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
|
|
index d60c4a2eeb0c5..06980b8527ff8 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
|
|
@@ -239,6 +239,8 @@ static int amdgpu_vkms_conn_get_modes(struct drm_connector *connector)
|
|
|
|
for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
|
|
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
|
|
+ if (!mode)
|
|
+ continue;
|
|
drm_mode_probed_add(connector, mode);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
|
|
index 7ba47fc1917b2..73937ce8829cc 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v2_3.c
|
|
@@ -28,6 +28,7 @@
|
|
#include "nbio/nbio_2_3_offset.h"
|
|
#include "nbio/nbio_2_3_sh_mask.h"
|
|
#include <uapi/linux/kfd_ioctl.h>
|
|
+#include <linux/device.h>
|
|
#include <linux/pci.h>
|
|
|
|
#define smnPCIE_CONFIG_CNTL 0x11180044
|
|
@@ -361,7 +362,7 @@ static void nbio_v2_3_enable_aspm(struct amdgpu_device *adev,
|
|
|
|
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
|
|
|
|
- if (pci_is_thunderbolt_attached(adev->pdev))
|
|
+ if (dev_is_removable(&adev->pdev->dev))
|
|
data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
|
|
else
|
|
data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
|
|
@@ -480,7 +481,7 @@ static void nbio_v2_3_program_aspm(struct amdgpu_device *adev)
|
|
|
|
def = data = RREG32_PCIE(smnPCIE_LC_CNTL);
|
|
data |= NAVI10_PCIE__LC_L0S_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT;
|
|
- if (pci_is_thunderbolt_attached(adev->pdev))
|
|
+ if (dev_is_removable(&adev->pdev->dev))
|
|
data |= NAVI10_PCIE__LC_L1_INACTIVITY_TBT_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
|
|
else
|
|
data |= NAVI10_PCIE__LC_L1_INACTIVITY_DEFAULT << PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT;
|
|
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
|
|
index d7e758c86a0b8..208812512d8a8 100644
|
|
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
|
|
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
|
|
@@ -612,8 +612,15 @@ create_bo_failed:
|
|
|
|
void svm_range_vram_node_free(struct svm_range *prange)
|
|
{
|
|
- svm_range_bo_unref(prange->svm_bo);
|
|
- prange->ttm_res = NULL;
|
|
+ /* serialize prange->svm_bo unref */
|
|
+ mutex_lock(&prange->lock);
|
|
+ /* prange->svm_bo has not been unref */
|
|
+ if (prange->ttm_res) {
|
|
+ prange->ttm_res = NULL;
|
|
+ mutex_unlock(&prange->lock);
|
|
+ svm_range_bo_unref(prange->svm_bo);
|
|
+ } else
|
|
+ mutex_unlock(&prange->lock);
|
|
}
|
|
|
|
struct amdgpu_device *
|
|
@@ -757,7 +764,7 @@ svm_range_apply_attrs(struct kfd_process *p, struct svm_range *prange,
|
|
prange->flags &= ~attrs[i].value;
|
|
break;
|
|
case KFD_IOCTL_SVM_ATTR_GRANULARITY:
|
|
- prange->granularity = attrs[i].value;
|
|
+ prange->granularity = min_t(uint32_t, attrs[i].value, 0x3F);
|
|
break;
|
|
default:
|
|
WARN_ONCE(1, "svm_range_check_attrs wasn't called?");
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
index 42e266e074d1d..001932cb813dc 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
@@ -2057,7 +2057,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
|
struct dmub_srv_create_params create_params;
|
|
struct dmub_srv_region_params region_params;
|
|
struct dmub_srv_region_info region_info;
|
|
- struct dmub_srv_fb_params fb_params;
|
|
+ struct dmub_srv_memory_params memory_params;
|
|
struct dmub_srv_fb_info *fb_info;
|
|
struct dmub_srv *dmub_srv;
|
|
const struct dmcub_firmware_header_v1_0 *hdr;
|
|
@@ -2188,6 +2188,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
|
adev->dm.dmub_fw->data +
|
|
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
|
|
PSP_HEADER_BYTES;
|
|
+ region_params.is_mailbox_in_inbox = false;
|
|
|
|
status = dmub_srv_calc_region_info(dmub_srv, ®ion_params,
|
|
®ion_info);
|
|
@@ -2209,10 +2210,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
|
return r;
|
|
|
|
/* Rebase the regions on the framebuffer address. */
|
|
- memset(&fb_params, 0, sizeof(fb_params));
|
|
- fb_params.cpu_addr = adev->dm.dmub_bo_cpu_addr;
|
|
- fb_params.gpu_addr = adev->dm.dmub_bo_gpu_addr;
|
|
- fb_params.region_info = ®ion_info;
|
|
+ memset(&memory_params, 0, sizeof(memory_params));
|
|
+ memory_params.cpu_fb_addr = adev->dm.dmub_bo_cpu_addr;
|
|
+ memory_params.gpu_fb_addr = adev->dm.dmub_bo_gpu_addr;
|
|
+ memory_params.region_info = ®ion_info;
|
|
|
|
adev->dm.dmub_fb_info =
|
|
kzalloc(sizeof(*adev->dm.dmub_fb_info), GFP_KERNEL);
|
|
@@ -2224,7 +2225,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- status = dmub_srv_calc_fb_info(dmub_srv, &fb_params, fb_info);
|
|
+ status = dmub_srv_calc_mem_info(dmub_srv, &memory_params, fb_info);
|
|
if (status != DMUB_STATUS_OK) {
|
|
DRM_ERROR("Error calculating DMUB FB info: %d\n", status);
|
|
return -EINVAL;
|
|
@@ -7219,6 +7220,9 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
|
|
int i;
|
|
int result = -EIO;
|
|
|
|
+ if (!ddc_service->ddc_pin || !ddc_service->ddc_pin->hw_info.hw_supported)
|
|
+ return result;
|
|
+
|
|
cmd.payloads = kcalloc(num, sizeof(struct i2c_payload), GFP_KERNEL);
|
|
|
|
if (!cmd.payloads)
|
|
@@ -9282,14 +9286,14 @@ static bool should_reset_plane(struct drm_atomic_state *state,
|
|
struct drm_plane *other;
|
|
struct drm_plane_state *old_other_state, *new_other_state;
|
|
struct drm_crtc_state *new_crtc_state;
|
|
+ struct amdgpu_device *adev = drm_to_adev(plane->dev);
|
|
int i;
|
|
|
|
/*
|
|
- * TODO: Remove this hack once the checks below are sufficient
|
|
- * enough to determine when we need to reset all the planes on
|
|
- * the stream.
|
|
+ * TODO: Remove this hack for all asics once it proves that the
|
|
+ * fast updates works fine on DCN3.2+.
|
|
*/
|
|
- if (state->allow_modeset)
|
|
+ if (adev->ip_versions[DCE_HWIP][0] < IP_VERSION(3, 2, 0) && state->allow_modeset)
|
|
return true;
|
|
|
|
/* Exit early if we know that we're adding or removing the plane. */
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
|
|
index 15d3caf3d6d72..7a309547c2b3f 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
|
|
@@ -996,7 +996,8 @@ static bool dc_construct(struct dc *dc,
|
|
/* set i2c speed if not done by the respective dcnxxx__resource.c */
|
|
if (dc->caps.i2c_speed_in_khz_hdcp == 0)
|
|
dc->caps.i2c_speed_in_khz_hdcp = dc->caps.i2c_speed_in_khz;
|
|
-
|
|
+ if (dc->caps.max_optimizable_video_width == 0)
|
|
+ dc->caps.max_optimizable_video_width = 5120;
|
|
dc->clk_mgr = dc_clk_mgr_create(dc->ctx, dc->res_pool->pp_smu, dc->res_pool->dccg);
|
|
if (!dc->clk_mgr)
|
|
goto fail;
|
|
@@ -1805,7 +1806,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
|
if (dc->hwss.subvp_pipe_control_lock)
|
|
dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use);
|
|
|
|
- if (dc->debug.enable_double_buffered_dsc_pg_support)
|
|
+ if (dc->hwss.update_dsc_pg)
|
|
dc->hwss.update_dsc_pg(dc, context, false);
|
|
|
|
disable_dangling_plane(dc, context);
|
|
@@ -1904,7 +1905,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
|
dc->hwss.optimize_bandwidth(dc, context);
|
|
}
|
|
|
|
- if (dc->debug.enable_double_buffered_dsc_pg_support)
|
|
+ if (dc->hwss.update_dsc_pg)
|
|
dc->hwss.update_dsc_pg(dc, context, true);
|
|
|
|
if (dc->ctx->dce_version >= DCE_VERSION_MAX)
|
|
@@ -2192,7 +2193,7 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
|
|
|
|
dc->hwss.optimize_bandwidth(dc, context);
|
|
|
|
- if (dc->debug.enable_double_buffered_dsc_pg_support)
|
|
+ if (dc->hwss.update_dsc_pg)
|
|
dc->hwss.update_dsc_pg(dc, context, true);
|
|
}
|
|
|
|
@@ -2438,6 +2439,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
|
|
}
|
|
|
|
static enum surface_update_type get_scaling_info_update_type(
|
|
+ const struct dc *dc,
|
|
const struct dc_surface_update *u)
|
|
{
|
|
union surface_update_flags *update_flags = &u->surface->update_flags;
|
|
@@ -2472,6 +2474,12 @@ static enum surface_update_type get_scaling_info_update_type(
|
|
update_flags->bits.clock_change = 1;
|
|
}
|
|
|
|
+ if (u->scaling_info->src_rect.width > dc->caps.max_optimizable_video_width &&
|
|
+ (u->scaling_info->clip_rect.width > u->surface->clip_rect.width ||
|
|
+ u->scaling_info->clip_rect.height > u->surface->clip_rect.height))
|
|
+ /* Changing clip size of a large surface may result in MPC slice count change */
|
|
+ update_flags->bits.bandwidth_change = 1;
|
|
+
|
|
if (u->scaling_info->src_rect.x != u->surface->src_rect.x
|
|
|| u->scaling_info->src_rect.y != u->surface->src_rect.y
|
|
|| u->scaling_info->clip_rect.x != u->surface->clip_rect.x
|
|
@@ -2509,7 +2517,7 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
|
|
type = get_plane_info_update_type(u);
|
|
elevate_update_type(&overall_type, type);
|
|
|
|
- type = get_scaling_info_update_type(u);
|
|
+ type = get_scaling_info_update_type(dc, u);
|
|
elevate_update_type(&overall_type, type);
|
|
|
|
if (u->flip_addr) {
|
|
@@ -3445,7 +3453,7 @@ static void commit_planes_for_stream(struct dc *dc,
|
|
if (get_seamless_boot_stream_count(context) == 0)
|
|
dc->hwss.prepare_bandwidth(dc, context);
|
|
|
|
- if (dc->debug.enable_double_buffered_dsc_pg_support)
|
|
+ if (dc->hwss.update_dsc_pg)
|
|
dc->hwss.update_dsc_pg(dc, context, false);
|
|
|
|
context_clock_trace(dc, context);
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
|
|
index 38d71b5c1f2d5..556c57c390ffd 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
|
|
@@ -567,7 +567,7 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
|
|
for (i = 0; i < MAX_PIPES; i++) {
|
|
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
|
|
|
|
- if (res_ctx->pipe_ctx[i].stream != stream)
|
|
+ if (res_ctx->pipe_ctx[i].stream != stream || !tg)
|
|
continue;
|
|
|
|
return tg->funcs->get_frame_count(tg);
|
|
@@ -626,7 +626,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
|
|
for (i = 0; i < MAX_PIPES; i++) {
|
|
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
|
|
|
|
- if (res_ctx->pipe_ctx[i].stream != stream)
|
|
+ if (res_ctx->pipe_ctx[i].stream != stream || !tg)
|
|
continue;
|
|
|
|
tg->funcs->get_scanoutpos(tg,
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
|
|
index a4540f83aae59..f773a467fef54 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dc.h
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
|
|
@@ -230,6 +230,11 @@ struct dc_caps {
|
|
uint32_t dmdata_alloc_size;
|
|
unsigned int max_cursor_size;
|
|
unsigned int max_video_width;
|
|
+ /*
|
|
+ * max video plane width that can be safely assumed to be always
|
|
+ * supported by single DPP pipe.
|
|
+ */
|
|
+ unsigned int max_optimizable_video_width;
|
|
unsigned int min_horizontal_blanking_period;
|
|
int linear_pitch_alignment;
|
|
bool dcc_const_color;
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
|
|
index d477dcc9149fa..50b3547977281 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
|
|
@@ -79,6 +79,9 @@ void dcn32_dsc_pg_control(
|
|
if (hws->ctx->dc->debug.disable_dsc_power_gate)
|
|
return;
|
|
|
|
+ if (!hws->ctx->dc->debug.enable_double_buffered_dsc_pg_support)
|
|
+ return;
|
|
+
|
|
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
|
|
if (org_ip_request_cntl == 0)
|
|
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
|
|
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
|
|
index 5f17b252e9be4..a21fe7b037d1f 100644
|
|
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
|
|
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
|
|
@@ -174,6 +174,7 @@ struct dmub_srv_region_params {
|
|
uint32_t vbios_size;
|
|
const uint8_t *fw_inst_const;
|
|
const uint8_t *fw_bss_data;
|
|
+ bool is_mailbox_in_inbox;
|
|
};
|
|
|
|
/**
|
|
@@ -193,20 +194,25 @@ struct dmub_srv_region_params {
|
|
*/
|
|
struct dmub_srv_region_info {
|
|
uint32_t fb_size;
|
|
+ uint32_t inbox_size;
|
|
uint8_t num_regions;
|
|
struct dmub_region regions[DMUB_WINDOW_TOTAL];
|
|
};
|
|
|
|
/**
|
|
- * struct dmub_srv_fb_params - parameters used for driver fb setup
|
|
+ * struct dmub_srv_memory_params - parameters used for driver fb setup
|
|
* @region_info: region info calculated by dmub service
|
|
- * @cpu_addr: base cpu address for the framebuffer
|
|
- * @gpu_addr: base gpu virtual address for the framebuffer
|
|
+ * @cpu_fb_addr: base cpu address for the framebuffer
|
|
+ * @cpu_inbox_addr: base cpu address for the gart
|
|
+ * @gpu_fb_addr: base gpu virtual address for the framebuffer
|
|
+ * @gpu_inbox_addr: base gpu virtual address for the gart
|
|
*/
|
|
-struct dmub_srv_fb_params {
|
|
+struct dmub_srv_memory_params {
|
|
const struct dmub_srv_region_info *region_info;
|
|
- void *cpu_addr;
|
|
- uint64_t gpu_addr;
|
|
+ void *cpu_fb_addr;
|
|
+ void *cpu_inbox_addr;
|
|
+ uint64_t gpu_fb_addr;
|
|
+ uint64_t gpu_inbox_addr;
|
|
};
|
|
|
|
/**
|
|
@@ -524,8 +530,8 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub,
|
|
* DMUB_STATUS_OK - success
|
|
* DMUB_STATUS_INVALID - unspecified error
|
|
*/
|
|
-enum dmub_status dmub_srv_calc_fb_info(struct dmub_srv *dmub,
|
|
- const struct dmub_srv_fb_params *params,
|
|
+enum dmub_status dmub_srv_calc_mem_info(struct dmub_srv *dmub,
|
|
+ const struct dmub_srv_memory_params *params,
|
|
struct dmub_srv_fb_info *out);
|
|
|
|
/**
|
|
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
|
|
index 0dab22d794808..c3327875933e9 100644
|
|
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
|
|
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
|
|
@@ -384,7 +384,7 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub,
|
|
uint32_t fw_state_size = DMUB_FW_STATE_SIZE;
|
|
uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE;
|
|
uint32_t scratch_mem_size = DMUB_SCRATCH_MEM_SIZE;
|
|
-
|
|
+ uint32_t previous_top = 0;
|
|
if (!dmub->sw_init)
|
|
return DMUB_STATUS_INVALID;
|
|
|
|
@@ -409,8 +409,15 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub,
|
|
bios->base = dmub_align(stack->top, 256);
|
|
bios->top = bios->base + params->vbios_size;
|
|
|
|
- mail->base = dmub_align(bios->top, 256);
|
|
- mail->top = mail->base + DMUB_MAILBOX_SIZE;
|
|
+ if (params->is_mailbox_in_inbox) {
|
|
+ mail->base = 0;
|
|
+ mail->top = mail->base + DMUB_MAILBOX_SIZE;
|
|
+ previous_top = bios->top;
|
|
+ } else {
|
|
+ mail->base = dmub_align(bios->top, 256);
|
|
+ mail->top = mail->base + DMUB_MAILBOX_SIZE;
|
|
+ previous_top = mail->top;
|
|
+ }
|
|
|
|
fw_info = dmub_get_fw_meta_info(params);
|
|
|
|
@@ -429,7 +436,7 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub,
|
|
dmub->fw_version = fw_info->fw_version;
|
|
}
|
|
|
|
- trace_buff->base = dmub_align(mail->top, 256);
|
|
+ trace_buff->base = dmub_align(previous_top, 256);
|
|
trace_buff->top = trace_buff->base + dmub_align(trace_buffer_size, 64);
|
|
|
|
fw_state->base = dmub_align(trace_buff->top, 256);
|
|
@@ -440,11 +447,14 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub,
|
|
|
|
out->fb_size = dmub_align(scratch_mem->top, 4096);
|
|
|
|
+ if (params->is_mailbox_in_inbox)
|
|
+ out->inbox_size = dmub_align(mail->top, 4096);
|
|
+
|
|
return DMUB_STATUS_OK;
|
|
}
|
|
|
|
-enum dmub_status dmub_srv_calc_fb_info(struct dmub_srv *dmub,
|
|
- const struct dmub_srv_fb_params *params,
|
|
+enum dmub_status dmub_srv_calc_mem_info(struct dmub_srv *dmub,
|
|
+ const struct dmub_srv_memory_params *params,
|
|
struct dmub_srv_fb_info *out)
|
|
{
|
|
uint8_t *cpu_base;
|
|
@@ -459,8 +469,8 @@ enum dmub_status dmub_srv_calc_fb_info(struct dmub_srv *dmub,
|
|
if (params->region_info->num_regions != DMUB_NUM_WINDOWS)
|
|
return DMUB_STATUS_INVALID;
|
|
|
|
- cpu_base = (uint8_t *)params->cpu_addr;
|
|
- gpu_base = params->gpu_addr;
|
|
+ cpu_base = (uint8_t *)params->cpu_fb_addr;
|
|
+ gpu_base = params->gpu_fb_addr;
|
|
|
|
for (i = 0; i < DMUB_NUM_WINDOWS; ++i) {
|
|
const struct dmub_region *reg =
|
|
@@ -468,6 +478,12 @@ enum dmub_status dmub_srv_calc_fb_info(struct dmub_srv *dmub,
|
|
|
|
out->fb[i].cpu_addr = cpu_base + reg->base;
|
|
out->fb[i].gpu_addr = gpu_base + reg->base;
|
|
+
|
|
+ if (i == DMUB_WINDOW_4_MAILBOX && params->cpu_inbox_addr != 0) {
|
|
+ out->fb[i].cpu_addr = (uint8_t *)params->cpu_inbox_addr + reg->base;
|
|
+ out->fb[i].gpu_addr = params->gpu_inbox_addr + reg->base;
|
|
+ }
|
|
+
|
|
out->fb[i].size = reg->top - reg->base;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/include/pptable.h b/drivers/gpu/drm/amd/include/pptable.h
|
|
index 0b6a057e0a4c4..5aac8d545bdc6 100644
|
|
--- a/drivers/gpu/drm/amd/include/pptable.h
|
|
+++ b/drivers/gpu/drm/amd/include/pptable.h
|
|
@@ -78,7 +78,7 @@ typedef struct _ATOM_PPLIB_THERMALCONTROLLER
|
|
typedef struct _ATOM_PPLIB_STATE
|
|
{
|
|
UCHAR ucNonClockStateIndex;
|
|
- UCHAR ucClockStateIndices[1]; // variable-sized
|
|
+ UCHAR ucClockStateIndices[]; // variable-sized
|
|
} ATOM_PPLIB_STATE;
|
|
|
|
|
|
@@ -473,7 +473,7 @@ typedef struct _ATOM_PPLIB_STATE_V2
|
|
/**
|
|
* Driver will read the first ucNumDPMLevels in this array
|
|
*/
|
|
- UCHAR clockInfoIndex[1];
|
|
+ UCHAR clockInfoIndex[];
|
|
} ATOM_PPLIB_STATE_V2;
|
|
|
|
typedef struct _StateArray{
|
|
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
index 0e78437c8389d..29f3d8431089e 100644
|
|
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
|
|
@@ -758,7 +758,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
|
|
if (adev->in_suspend && !adev->in_runpm)
|
|
return -EPERM;
|
|
|
|
- if (count > 127)
|
|
+ if (count > 127 || count == 0)
|
|
return -EINVAL;
|
|
|
|
if (*buf == 's')
|
|
@@ -778,7 +778,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
|
|
else
|
|
return -EINVAL;
|
|
|
|
- memcpy(buf_cpy, buf, count+1);
|
|
+ memcpy(buf_cpy, buf, count);
|
|
+ buf_cpy[count] = 0;
|
|
|
|
tmp_str = buf_cpy;
|
|
|
|
@@ -795,6 +796,9 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev,
|
|
return -EINVAL;
|
|
parameter_size++;
|
|
|
|
+ if (!tmp_str)
|
|
+ break;
|
|
+
|
|
while (isspace(*tmp_str))
|
|
tmp_str++;
|
|
}
|
|
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h
|
|
index b0ac4d121adca..e0e40b054c08b 100644
|
|
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h
|
|
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h
|
|
@@ -164,7 +164,7 @@ typedef struct _ATOM_Tonga_State {
|
|
typedef struct _ATOM_Tonga_State_Array {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Tonga_State entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Tonga_State entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Tonga_State_Array;
|
|
|
|
typedef struct _ATOM_Tonga_MCLK_Dependency_Record {
|
|
@@ -179,7 +179,7 @@ typedef struct _ATOM_Tonga_MCLK_Dependency_Record {
|
|
typedef struct _ATOM_Tonga_MCLK_Dependency_Table {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Tonga_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Tonga_MCLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Tonga_MCLK_Dependency_Table;
|
|
|
|
typedef struct _ATOM_Tonga_SCLK_Dependency_Record {
|
|
@@ -194,7 +194,7 @@ typedef struct _ATOM_Tonga_SCLK_Dependency_Record {
|
|
typedef struct _ATOM_Tonga_SCLK_Dependency_Table {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Tonga_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Tonga_SCLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Tonga_SCLK_Dependency_Table;
|
|
|
|
typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
|
|
@@ -210,7 +210,7 @@ typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
|
|
typedef struct _ATOM_Polaris_SCLK_Dependency_Table {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Polaris_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Polaris_SCLK_Dependency_Record entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Polaris_SCLK_Dependency_Table;
|
|
|
|
typedef struct _ATOM_Tonga_PCIE_Record {
|
|
@@ -222,7 +222,7 @@ typedef struct _ATOM_Tonga_PCIE_Record {
|
|
typedef struct _ATOM_Tonga_PCIE_Table {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Tonga_PCIE_Record entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Tonga_PCIE_Table;
|
|
|
|
typedef struct _ATOM_Polaris10_PCIE_Record {
|
|
@@ -235,7 +235,7 @@ typedef struct _ATOM_Polaris10_PCIE_Record {
|
|
typedef struct _ATOM_Polaris10_PCIE_Table {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Polaris10_PCIE_Record entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Polaris10_PCIE_Record entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Polaris10_PCIE_Table;
|
|
|
|
|
|
@@ -252,7 +252,7 @@ typedef struct _ATOM_Tonga_MM_Dependency_Record {
|
|
typedef struct _ATOM_Tonga_MM_Dependency_Table {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Tonga_MM_Dependency_Record entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Tonga_MM_Dependency_Record entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Tonga_MM_Dependency_Table;
|
|
|
|
typedef struct _ATOM_Tonga_Voltage_Lookup_Record {
|
|
@@ -265,7 +265,7 @@ typedef struct _ATOM_Tonga_Voltage_Lookup_Record {
|
|
typedef struct _ATOM_Tonga_Voltage_Lookup_Table {
|
|
UCHAR ucRevId;
|
|
UCHAR ucNumEntries; /* Number of entries. */
|
|
- ATOM_Tonga_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries. */
|
|
+ ATOM_Tonga_Voltage_Lookup_Record entries[]; /* Dynamically allocate entries. */
|
|
} ATOM_Tonga_Voltage_Lookup_Table;
|
|
|
|
typedef struct _ATOM_Tonga_Fan_Table {
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
|
|
index a664a0a284784..47ff3694ffa57 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
|
|
@@ -1221,7 +1221,7 @@ static int smu_smc_hw_setup(struct smu_context *smu)
|
|
{
|
|
struct smu_feature *feature = &smu->smu_feature;
|
|
struct amdgpu_device *adev = smu->adev;
|
|
- uint32_t pcie_gen = 0, pcie_width = 0;
|
|
+ uint8_t pcie_gen = 0, pcie_width = 0;
|
|
uint64_t features_supported;
|
|
int ret = 0;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
|
|
index 1ab77a6cdb653..4174cb295dd0b 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
|
|
@@ -844,7 +844,7 @@ struct pptable_funcs {
|
|
* &pcie_gen_cap: Maximum allowed PCIe generation.
|
|
* &pcie_width_cap: Maximum allowed PCIe width.
|
|
*/
|
|
- int (*update_pcie_parameters)(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap);
|
|
+ int (*update_pcie_parameters)(struct smu_context *smu, uint8_t pcie_gen_cap, uint8_t pcie_width_cap);
|
|
|
|
/**
|
|
* @i2c_init: Initialize i2c.
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
|
|
index d6479a8088554..636b9579b96b0 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
|
|
@@ -298,8 +298,8 @@ int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu,
|
|
uint32_t pptable_id);
|
|
|
|
int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
|
|
- uint32_t pcie_gen_cap,
|
|
- uint32_t pcie_width_cap);
|
|
+ uint8_t pcie_gen_cap,
|
|
+ uint8_t pcie_width_cap);
|
|
|
|
#endif
|
|
#endif
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
|
|
index ca278280865fa..ed2112efc6c68 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
|
|
@@ -2368,8 +2368,8 @@ static int navi10_get_power_limit(struct smu_context *smu,
|
|
}
|
|
|
|
static int navi10_update_pcie_parameters(struct smu_context *smu,
|
|
- uint32_t pcie_gen_cap,
|
|
- uint32_t pcie_width_cap)
|
|
+ uint8_t pcie_gen_cap,
|
|
+ uint8_t pcie_width_cap)
|
|
{
|
|
struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
|
|
PPTable_t *pptable = smu->smu_table.driver_pptable;
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
|
|
index fbc4d706748b7..cfd41d56e9701 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
|
|
@@ -2084,14 +2084,14 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu,
|
|
- uint32_t pcie_gen_cap,
|
|
- uint32_t pcie_width_cap)
|
|
+ uint8_t pcie_gen_cap,
|
|
+ uint8_t pcie_width_cap)
|
|
{
|
|
struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
|
|
struct smu_11_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table;
|
|
uint8_t *table_member1, *table_member2;
|
|
- uint32_t min_gen_speed, max_gen_speed;
|
|
- uint32_t min_lane_width, max_lane_width;
|
|
+ uint8_t min_gen_speed, max_gen_speed;
|
|
+ uint8_t min_lane_width, max_lane_width;
|
|
uint32_t smu_pcie_arg;
|
|
int ret, i;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
|
|
index 3104d49379090..1b0fb93539ec4 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
|
|
@@ -2486,8 +2486,8 @@ int smu_v13_0_mode1_reset(struct smu_context *smu)
|
|
}
|
|
|
|
int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
|
|
- uint32_t pcie_gen_cap,
|
|
- uint32_t pcie_width_cap)
|
|
+ uint8_t pcie_gen_cap,
|
|
+ uint8_t pcie_width_cap)
|
|
{
|
|
struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
|
|
struct smu_13_0_pcie_table *pcie_table =
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
|
|
index 503e844baede2..af244def4801b 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
|
|
@@ -324,12 +324,12 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
|
|
if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
|
|
smu->dc_controlled_by_gpio = true;
|
|
|
|
- if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_BACO ||
|
|
- powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
|
|
+ if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_BACO) {
|
|
smu_baco->platform_support = true;
|
|
|
|
- if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
|
|
- smu_baco->maco_support = true;
|
|
+ if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
|
|
+ smu_baco->maco_support = true;
|
|
+ }
|
|
|
|
table_context->thermal_controller_type =
|
|
powerplay_table->thermal_controller_type;
|
|
@@ -1645,38 +1645,10 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
|
|
}
|
|
}
|
|
|
|
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE &&
|
|
- (((smu->adev->pdev->device == 0x744C) && (smu->adev->pdev->revision == 0xC8)) ||
|
|
- ((smu->adev->pdev->device == 0x744C) && (smu->adev->pdev->revision == 0xCC)))) {
|
|
- ret = smu_cmn_update_table(smu,
|
|
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
|
|
- WORKLOAD_PPLIB_COMPUTE_BIT,
|
|
- (void *)(&activity_monitor_external),
|
|
- false);
|
|
- if (ret) {
|
|
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ret = smu_cmn_update_table(smu,
|
|
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
|
|
- WORKLOAD_PPLIB_CUSTOM_BIT,
|
|
- (void *)(&activity_monitor_external),
|
|
- true);
|
|
- if (ret) {
|
|
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- workload_type = smu_cmn_to_asic_specific_index(smu,
|
|
- CMN2ASIC_MAPPING_WORKLOAD,
|
|
- PP_SMC_POWER_PROFILE_CUSTOM);
|
|
- } else {
|
|
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
|
|
- workload_type = smu_cmn_to_asic_specific_index(smu,
|
|
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
|
|
+ workload_type = smu_cmn_to_asic_specific_index(smu,
|
|
CMN2ASIC_MAPPING_WORKLOAD,
|
|
smu->power_profile_mode);
|
|
- }
|
|
|
|
if (workload_type < 0)
|
|
return -EINVAL;
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
|
|
index bf24850027dab..bd065f1c699f5 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
|
|
@@ -326,12 +326,13 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
|
|
if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
|
|
smu->dc_controlled_by_gpio = true;
|
|
|
|
- if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_BACO ||
|
|
- powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_MACO)
|
|
+ if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_BACO) {
|
|
smu_baco->platform_support = true;
|
|
|
|
- if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
|
|
- smu_baco->maco_support = true;
|
|
+ if ((powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_MACO)
|
|
+ && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled))
|
|
+ smu_baco->maco_support = true;
|
|
+ }
|
|
|
|
table_context->thermal_controller_type =
|
|
powerplay_table->thermal_controller_type;
|
|
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
|
|
index 3276a3e82c628..916f2c36bf2f7 100644
|
|
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
|
|
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
|
|
@@ -1223,7 +1223,7 @@ int komeda_build_display_data_flow(struct komeda_crtc *kcrtc,
|
|
return 0;
|
|
}
|
|
|
|
-static void
|
|
+static int
|
|
komeda_pipeline_unbound_components(struct komeda_pipeline *pipe,
|
|
struct komeda_pipeline_state *new)
|
|
{
|
|
@@ -1243,8 +1243,12 @@ komeda_pipeline_unbound_components(struct komeda_pipeline *pipe,
|
|
c = komeda_pipeline_get_component(pipe, id);
|
|
c_st = komeda_component_get_state_and_set_user(c,
|
|
drm_st, NULL, new->crtc);
|
|
+ if (PTR_ERR(c_st) == -EDEADLK)
|
|
+ return -EDEADLK;
|
|
WARN_ON(IS_ERR(c_st));
|
|
}
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/* release unclaimed pipeline resource */
|
|
@@ -1266,9 +1270,8 @@ int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
|
|
if (WARN_ON(IS_ERR_OR_NULL(st)))
|
|
return -EINVAL;
|
|
|
|
- komeda_pipeline_unbound_components(pipe, st);
|
|
+ return komeda_pipeline_unbound_components(pipe, st);
|
|
|
|
- return 0;
|
|
}
|
|
|
|
/* Since standalone disabled components must be disabled separately and in the
|
|
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
|
|
index d72c2fac0ff1a..b7362356e5448 100644
|
|
--- a/drivers/gpu/drm/drm_lease.c
|
|
+++ b/drivers/gpu/drm/drm_lease.c
|
|
@@ -507,8 +507,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
|
/* Handle leased objects, if any */
|
|
idr_init(&leases);
|
|
if (object_count != 0) {
|
|
- object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
|
|
- array_size(object_count, sizeof(__u32)));
|
|
+ object_ids = memdup_array_user(u64_to_user_ptr(cl->object_ids),
|
|
+ object_count, sizeof(__u32));
|
|
if (IS_ERR(object_ids)) {
|
|
ret = PTR_ERR(object_ids);
|
|
idr_destroy(&leases);
|
|
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
|
|
index ae544b69fc475..52f9ed3c24b8e 100644
|
|
--- a/drivers/gpu/drm/gma500/psb_drv.h
|
|
+++ b/drivers/gpu/drm/gma500/psb_drv.h
|
|
@@ -426,6 +426,7 @@ struct drm_psb_private {
|
|
uint32_t pipestat[PSB_NUM_PIPE];
|
|
|
|
spinlock_t irqmask_lock;
|
|
+ bool irq_enabled;
|
|
|
|
/* Power */
|
|
bool pm_initialized;
|
|
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
|
|
index d421031462df6..ab2d49dab35a0 100644
|
|
--- a/drivers/gpu/drm/gma500/psb_irq.c
|
|
+++ b/drivers/gpu/drm/gma500/psb_irq.c
|
|
@@ -338,6 +338,8 @@ int gma_irq_install(struct drm_device *dev)
|
|
|
|
gma_irq_postinstall(dev);
|
|
|
|
+ dev_priv->irq_enabled = true;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -348,6 +350,9 @@ void gma_irq_uninstall(struct drm_device *dev)
|
|
unsigned long irqflags;
|
|
unsigned int i;
|
|
|
|
+ if (!dev_priv->irq_enabled)
|
|
+ return;
|
|
+
|
|
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
|
|
|
|
if (dev_priv->ops->hotplug_enable)
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
|
|
index 92925f0f72396..25dcdde5feb69 100644
|
|
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
|
|
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
|
|
@@ -2368,6 +2368,18 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
|
|
for_each_pipe(dev_priv, pipe)
|
|
min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
|
|
|
|
+ /*
|
|
+ * Avoid glk_force_audio_cdclk() causing excessive screen
|
|
+ * blinking when multiple pipes are active by making sure
|
|
+ * CDCLK frequency is always high enough for audio. With a
|
|
+ * single active pipe we can always change CDCLK frequency
|
|
+ * by changing the cd2x divider (see glk_cdclk_table[]) and
|
|
+ * thus a full modeset won't be needed then.
|
|
+ */
|
|
+ if (IS_GEMINILAKE(dev_priv) && cdclk_state->active_pipes &&
|
|
+ !is_power_of_2(cdclk_state->active_pipes))
|
|
+ min_cdclk = max(2 * 96000, min_cdclk);
|
|
+
|
|
if (min_cdclk > dev_priv->display.cdclk.max_cdclk_freq) {
|
|
drm_dbg_kms(&dev_priv->drm,
|
|
"required cdclk (%d kHz) exceeds max (%d kHz)\n",
|
|
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
|
|
index 598028870124d..5e1b11db74816 100644
|
|
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
|
|
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
|
|
@@ -844,6 +844,7 @@ static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
|
|
if (idx >= pc->num_user_engines)
|
|
return -EINVAL;
|
|
|
|
+ idx = array_index_nospec(idx, pc->num_user_engines);
|
|
pe = &pc->user_engines[idx];
|
|
|
|
/* Only render engine supports RPCS configuration. */
|
|
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
|
|
index 3ce49c118b83f..2d4f09813a15b 100644
|
|
--- a/drivers/gpu/drm/i915/i915_perf.c
|
|
+++ b/drivers/gpu/drm/i915/i915_perf.c
|
|
@@ -3809,11 +3809,8 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
|
|
u32 known_open_flags;
|
|
int ret;
|
|
|
|
- if (!perf->i915) {
|
|
- drm_dbg(&perf->i915->drm,
|
|
- "i915 perf interface not available for this system\n");
|
|
+ if (!perf->i915)
|
|
return -ENOTSUPP;
|
|
- }
|
|
|
|
known_open_flags = I915_PERF_FLAG_FD_CLOEXEC |
|
|
I915_PERF_FLAG_FD_NONBLOCK |
|
|
@@ -4140,11 +4137,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
|
|
struct i915_oa_reg *regs;
|
|
int err, id;
|
|
|
|
- if (!perf->i915) {
|
|
- drm_dbg(&perf->i915->drm,
|
|
- "i915 perf interface not available for this system\n");
|
|
+ if (!perf->i915)
|
|
return -ENOTSUPP;
|
|
- }
|
|
|
|
if (!perf->metrics_kobj) {
|
|
drm_dbg(&perf->i915->drm,
|
|
@@ -4306,11 +4300,8 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data,
|
|
struct i915_oa_config *oa_config;
|
|
int ret;
|
|
|
|
- if (!perf->i915) {
|
|
- drm_dbg(&perf->i915->drm,
|
|
- "i915 perf interface not available for this system\n");
|
|
+ if (!perf->i915)
|
|
return -ENOTSUPP;
|
|
- }
|
|
|
|
if (i915_perf_stream_paranoid && !perfmon_capable()) {
|
|
drm_dbg(&perf->i915->drm,
|
|
diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
|
|
index 395a190274cfb..2c850b6d945bc 100644
|
|
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
|
|
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
|
|
@@ -1983,7 +1983,6 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
|
|
bool enabled = mtk_dp->enabled;
|
|
struct edid *new_edid = NULL;
|
|
struct mtk_dp_audio_cfg *audio_caps = &mtk_dp->info.audio_cur_cfg;
|
|
- struct cea_sad *sads;
|
|
|
|
if (!enabled) {
|
|
drm_bridge_chain_pre_enable(bridge);
|
|
@@ -2006,11 +2005,16 @@ static struct edid *mtk_dp_get_edid(struct drm_bridge *bridge,
|
|
*/
|
|
if (mtk_dp_parse_capabilities(mtk_dp)) {
|
|
drm_err(mtk_dp->drm_dev, "Can't parse capabilities\n");
|
|
+ kfree(new_edid);
|
|
new_edid = NULL;
|
|
}
|
|
|
|
if (new_edid) {
|
|
+ struct cea_sad *sads;
|
|
+
|
|
audio_caps->sad_count = drm_edid_to_sad(new_edid, &sads);
|
|
+ kfree(sads);
|
|
+
|
|
audio_caps->detect_monitor = drm_detect_monitor_audio(new_edid);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
|
|
index 5149cebc93f61..d38086650fcf7 100644
|
|
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
|
|
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
|
|
@@ -266,26 +266,9 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
|
|
|
|
static u8 dp_panel_get_edid_checksum(struct edid *edid)
|
|
{
|
|
- struct edid *last_block;
|
|
- u8 *raw_edid;
|
|
- bool is_edid_corrupt = false;
|
|
+ edid += edid->extensions;
|
|
|
|
- if (!edid) {
|
|
- DRM_ERROR("invalid edid input\n");
|
|
- return 0;
|
|
- }
|
|
-
|
|
- raw_edid = (u8 *)edid;
|
|
- raw_edid += (edid->extensions * EDID_LENGTH);
|
|
- last_block = (struct edid *)raw_edid;
|
|
-
|
|
- /* block type extension */
|
|
- drm_edid_block_valid(raw_edid, 1, false, &is_edid_corrupt);
|
|
- if (!is_edid_corrupt)
|
|
- return last_block->checksum;
|
|
-
|
|
- DRM_ERROR("Invalid block, no checksum\n");
|
|
- return 0;
|
|
+ return edid->checksum;
|
|
}
|
|
|
|
void dp_panel_handle_sink_request(struct dp_panel *dp_panel)
|
|
diff --git a/drivers/gpu/drm/panel/panel-arm-versatile.c b/drivers/gpu/drm/panel/panel-arm-versatile.c
|
|
index abb0788843c60..503ecea72c5ea 100644
|
|
--- a/drivers/gpu/drm/panel/panel-arm-versatile.c
|
|
+++ b/drivers/gpu/drm/panel/panel-arm-versatile.c
|
|
@@ -267,6 +267,8 @@ static int versatile_panel_get_modes(struct drm_panel *panel,
|
|
connector->display_info.bus_flags = vpanel->panel_type->bus_flags;
|
|
|
|
mode = drm_mode_duplicate(connector->dev, &vpanel->panel_type->mode);
|
|
+ if (!mode)
|
|
+ return -ENOMEM;
|
|
drm_mode_set_name(mode);
|
|
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
|
|
|
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
|
index 86a472b01360b..b6e514aabe1d3 100644
|
|
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
|
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
|
|
@@ -428,29 +428,30 @@ static int st7703_prepare(struct drm_panel *panel)
|
|
return 0;
|
|
|
|
dev_dbg(ctx->dev, "Resetting the panel\n");
|
|
- ret = regulator_enable(ctx->vcc);
|
|
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
|
+
|
|
+ ret = regulator_enable(ctx->iovcc);
|
|
if (ret < 0) {
|
|
- dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
|
|
+ dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
|
|
return ret;
|
|
}
|
|
- ret = regulator_enable(ctx->iovcc);
|
|
+
|
|
+ ret = regulator_enable(ctx->vcc);
|
|
if (ret < 0) {
|
|
- dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
|
|
- goto disable_vcc;
|
|
+ dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
|
|
+ regulator_disable(ctx->iovcc);
|
|
+ return ret;
|
|
}
|
|
|
|
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
|
- usleep_range(20, 40);
|
|
+ /* Give power supplies time to stabilize before deasserting reset. */
|
|
+ usleep_range(10000, 20000);
|
|
+
|
|
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
|
|
- msleep(20);
|
|
+ usleep_range(15000, 20000);
|
|
|
|
ctx->prepared = true;
|
|
|
|
return 0;
|
|
-
|
|
-disable_vcc:
|
|
- regulator_disable(ctx->vcc);
|
|
- return ret;
|
|
}
|
|
|
|
static const u32 mantix_bus_formats[] = {
|
|
diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c
|
|
index 0b1f5a11a0554..735f1ea25c121 100644
|
|
--- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c
|
|
+++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c
|
|
@@ -379,6 +379,8 @@ static int tpg110_get_modes(struct drm_panel *panel,
|
|
connector->display_info.bus_flags = tpg->panel_mode->bus_flags;
|
|
|
|
mode = drm_mode_duplicate(connector->dev, &tpg->panel_mode->mode);
|
|
+ if (!mode)
|
|
+ return -ENOMEM;
|
|
drm_mode_set_name(mode);
|
|
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
|
|
|
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
|
|
index a152a7c6db215..f91a86225d5e7 100644
|
|
--- a/drivers/gpu/drm/qxl/qxl_display.c
|
|
+++ b/drivers/gpu/drm/qxl/qxl_display.c
|
|
@@ -1229,6 +1229,9 @@ int qxl_destroy_monitors_object(struct qxl_device *qdev)
|
|
if (!qdev->monitors_config_bo)
|
|
return 0;
|
|
|
|
+ kfree(qdev->dumb_heads);
|
|
+ qdev->dumb_heads = NULL;
|
|
+
|
|
qdev->monitors_config = NULL;
|
|
qdev->ram_header->monitors_config = 0;
|
|
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
index f7431d2246044..5837af5123a9f 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
@@ -1122,6 +1122,8 @@ static int radeon_tv_get_modes(struct drm_connector *connector)
|
|
else {
|
|
/* only 800x600 is supported right now on pre-avivo chips */
|
|
tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false);
|
|
+ if (!tv_mode)
|
|
+ return 0;
|
|
tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
|
drm_mode_probed_add(connector, tv_mode);
|
|
}
|
|
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
|
index 591c301e6cf21..1a1a286bc749f 100644
|
|
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
|
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
|
@@ -774,9 +774,9 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
|
|
sizeof(metadata->mip_levels));
|
|
metadata->num_sizes = num_sizes;
|
|
metadata->sizes =
|
|
- memdup_user((struct drm_vmw_size __user *)(unsigned long)
|
|
+ memdup_array_user((struct drm_vmw_size __user *)(unsigned long)
|
|
req->size_addr,
|
|
- sizeof(*metadata->sizes) * metadata->num_sizes);
|
|
+ metadata->num_sizes, sizeof(*metadata->sizes));
|
|
if (IS_ERR(metadata->sizes)) {
|
|
ret = PTR_ERR(metadata->sizes);
|
|
goto out_no_sizes;
|
|
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
|
index 9a17e5cc3539b..130fc5f341422 100644
|
|
--- a/drivers/hid/hid-ids.h
|
|
+++ b/drivers/hid/hid-ids.h
|
|
@@ -365,6 +365,7 @@
|
|
|
|
#define USB_VENDOR_ID_DELL 0x413c
|
|
#define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE 0x301a
|
|
+#define USB_DEVICE_ID_DELL_PRO_WIRELESS_KM5221W 0x4503
|
|
|
|
#define USB_VENDOR_ID_DELORME 0x1163
|
|
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
|
|
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
|
|
index 44763c0da4441..7c1b33be9d134 100644
|
|
--- a/drivers/hid/hid-lenovo.c
|
|
+++ b/drivers/hid/hid-lenovo.c
|
|
@@ -51,7 +51,12 @@ struct lenovo_drvdata {
|
|
int select_right;
|
|
int sensitivity;
|
|
int press_speed;
|
|
- u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
|
|
+ /* 0: Up
|
|
+ * 1: Down (undecided)
|
|
+ * 2: Scrolling
|
|
+ * 3: Patched firmware, disable workaround
|
|
+ */
|
|
+ u8 middlebutton_state;
|
|
bool fn_lock;
|
|
};
|
|
|
|
@@ -521,6 +526,19 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev)
|
|
int ret;
|
|
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
|
|
|
|
+ /*
|
|
+ * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
|
|
+ * regular keys
|
|
+ */
|
|
+ ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
|
|
+ if (ret)
|
|
+ hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
|
|
+
|
|
+ /* Switch middle button to native mode */
|
|
+ ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
|
|
+ if (ret)
|
|
+ hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
|
|
+
|
|
ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock);
|
|
if (ret)
|
|
hid_err(hdev, "Fn-lock setting failed: %d\n", ret);
|
|
@@ -668,31 +686,48 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
|
|
{
|
|
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
|
|
|
|
- /* "wheel" scroll events */
|
|
- if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
|
|
- usage->code == REL_HWHEEL)) {
|
|
- /* Scroll events disable middle-click event */
|
|
- cptkbd_data->middlebutton_state = 2;
|
|
- return 0;
|
|
- }
|
|
+ if (cptkbd_data->middlebutton_state != 3) {
|
|
+ /* REL_X and REL_Y events during middle button pressed
|
|
+ * are only possible on patched, bug-free firmware
|
|
+ * so set middlebutton_state to 3
|
|
+ * to never apply workaround anymore
|
|
+ */
|
|
+ if (cptkbd_data->middlebutton_state == 1 &&
|
|
+ usage->type == EV_REL &&
|
|
+ (usage->code == REL_X || usage->code == REL_Y)) {
|
|
+ cptkbd_data->middlebutton_state = 3;
|
|
+ /* send middle button press which was hold before */
|
|
+ input_event(field->hidinput->input,
|
|
+ EV_KEY, BTN_MIDDLE, 1);
|
|
+ input_sync(field->hidinput->input);
|
|
+ }
|
|
+
|
|
+ /* "wheel" scroll events */
|
|
+ if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
|
|
+ usage->code == REL_HWHEEL)) {
|
|
+ /* Scroll events disable middle-click event */
|
|
+ cptkbd_data->middlebutton_state = 2;
|
|
+ return 0;
|
|
+ }
|
|
|
|
- /* Middle click events */
|
|
- if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
|
|
- if (value == 1) {
|
|
- cptkbd_data->middlebutton_state = 1;
|
|
- } else if (value == 0) {
|
|
- if (cptkbd_data->middlebutton_state == 1) {
|
|
- /* No scrolling inbetween, send middle-click */
|
|
- input_event(field->hidinput->input,
|
|
- EV_KEY, BTN_MIDDLE, 1);
|
|
- input_sync(field->hidinput->input);
|
|
- input_event(field->hidinput->input,
|
|
- EV_KEY, BTN_MIDDLE, 0);
|
|
- input_sync(field->hidinput->input);
|
|
+ /* Middle click events */
|
|
+ if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
|
|
+ if (value == 1) {
|
|
+ cptkbd_data->middlebutton_state = 1;
|
|
+ } else if (value == 0) {
|
|
+ if (cptkbd_data->middlebutton_state == 1) {
|
|
+ /* No scrolling inbetween, send middle-click */
|
|
+ input_event(field->hidinput->input,
|
|
+ EV_KEY, BTN_MIDDLE, 1);
|
|
+ input_sync(field->hidinput->input);
|
|
+ input_event(field->hidinput->input,
|
|
+ EV_KEY, BTN_MIDDLE, 0);
|
|
+ input_sync(field->hidinput->input);
|
|
+ }
|
|
+ cptkbd_data->middlebutton_state = 0;
|
|
}
|
|
- cptkbd_data->middlebutton_state = 0;
|
|
+ return 1;
|
|
}
|
|
- return 1;
|
|
}
|
|
|
|
if (usage->type == EV_KEY && usage->code == KEY_FN_ESC && value == 1) {
|
|
@@ -1126,22 +1161,6 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
|
|
}
|
|
hid_set_drvdata(hdev, cptkbd_data);
|
|
|
|
- /*
|
|
- * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
|
|
- * regular keys (Compact only)
|
|
- */
|
|
- if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD ||
|
|
- hdev->product == USB_DEVICE_ID_LENOVO_CBTKBD) {
|
|
- ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
|
|
- if (ret)
|
|
- hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret);
|
|
- }
|
|
-
|
|
- /* Switch middle button to native mode */
|
|
- ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01);
|
|
- if (ret)
|
|
- hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
|
|
-
|
|
/* Set keyboard settings to known state */
|
|
cptkbd_data->middlebutton_state = 0;
|
|
cptkbd_data->fn_lock = true;
|
|
@@ -1264,6 +1283,24 @@ err:
|
|
return ret;
|
|
}
|
|
|
|
+#ifdef CONFIG_PM
|
|
+static int lenovo_reset_resume(struct hid_device *hdev)
|
|
+{
|
|
+ switch (hdev->product) {
|
|
+ case USB_DEVICE_ID_LENOVO_CUSBKBD:
|
|
+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD:
|
|
+ if (hdev->type == HID_TYPE_USBMOUSE)
|
|
+ lenovo_features_set_cptkbd(hdev);
|
|
+
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
static void lenovo_remove_tpkbd(struct hid_device *hdev)
|
|
{
|
|
struct lenovo_drvdata *data_pointer = hid_get_drvdata(hdev);
|
|
@@ -1380,6 +1417,9 @@ static struct hid_driver lenovo_driver = {
|
|
.raw_event = lenovo_raw_event,
|
|
.event = lenovo_event,
|
|
.report_fixup = lenovo_report_fixup,
|
|
+#ifdef CONFIG_PM
|
|
+ .reset_resume = lenovo_reset_resume,
|
|
+#endif
|
|
};
|
|
module_hid_driver(lenovo_driver);
|
|
|
|
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
|
|
index f8f20a7c24b17..056bb32091285 100644
|
|
--- a/drivers/hid/hid-quirks.c
|
|
+++ b/drivers/hid/hid-quirks.c
|
|
@@ -66,6 +66,7 @@ static const struct hid_device_id hid_quirks[] = {
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51), HID_QUIRK_NOGET },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
|
|
+ { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PRO_WIRELESS_KM5221W), HID_QUIRK_ALWAYS_POLL },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC), HID_QUIRK_NOGET },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES), HID_QUIRK_MULTI_INPUT },
|
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES), HID_QUIRK_MULTI_INPUT },
|
|
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
|
|
index 004ccb2d9f369..948d547690c64 100644
|
|
--- a/drivers/i2c/busses/i2c-designware-master.c
|
|
+++ b/drivers/i2c/busses/i2c-designware-master.c
|
|
@@ -456,10 +456,16 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
|
|
|
/*
|
|
* Because we don't know the buffer length in the
|
|
- * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop
|
|
- * the transaction here.
|
|
+ * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop the
|
|
+ * transaction here. Also disable the TX_EMPTY IRQ
|
|
+ * while waiting for the data length byte to avoid the
|
|
+ * bogus interrupts flood.
|
|
*/
|
|
- if (buf_len > 0 || flags & I2C_M_RECV_LEN) {
|
|
+ if (flags & I2C_M_RECV_LEN) {
|
|
+ dev->status |= STATUS_WRITE_IN_PROGRESS;
|
|
+ intr_mask &= ~DW_IC_INTR_TX_EMPTY;
|
|
+ break;
|
|
+ } else if (buf_len > 0) {
|
|
/* more bytes to be written */
|
|
dev->status |= STATUS_WRITE_IN_PROGRESS;
|
|
break;
|
|
@@ -495,6 +501,13 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
|
|
msgs[dev->msg_read_idx].len = len;
|
|
msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN;
|
|
|
|
+ /*
|
|
+ * Received buffer length, re-enable TX_EMPTY interrupt
|
|
+ * to resume the SMBUS transaction.
|
|
+ */
|
|
+ regmap_update_bits(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY,
|
|
+ DW_IC_INTR_TX_EMPTY);
|
|
+
|
|
return len;
|
|
}
|
|
|
|
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
|
|
index da1f6b60f9c9a..3159ffbb77a20 100644
|
|
--- a/drivers/i2c/busses/i2c-i801.c
|
|
+++ b/drivers/i2c/busses/i2c-i801.c
|
|
@@ -690,15 +690,11 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
|
|
return i801_check_post(priv, result ? priv->status : -ETIMEDOUT);
|
|
}
|
|
|
|
- for (i = 1; i <= len; i++) {
|
|
- if (i == len && read_write == I2C_SMBUS_READ)
|
|
- smbcmd |= SMBHSTCNT_LAST_BYTE;
|
|
- outb_p(smbcmd, SMBHSTCNT(priv));
|
|
-
|
|
- if (i == 1)
|
|
- outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
|
|
- SMBHSTCNT(priv));
|
|
+ if (len == 1 && read_write == I2C_SMBUS_READ)
|
|
+ smbcmd |= SMBHSTCNT_LAST_BYTE;
|
|
+ outb_p(smbcmd | SMBHSTCNT_START, SMBHSTCNT(priv));
|
|
|
|
+ for (i = 1; i <= len; i++) {
|
|
status = i801_wait_byte_done(priv);
|
|
if (status)
|
|
goto exit;
|
|
@@ -721,9 +717,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
|
|
data->block[0] = len;
|
|
}
|
|
|
|
- /* Retrieve/store value in SMBBLKDAT */
|
|
- if (read_write == I2C_SMBUS_READ)
|
|
+ if (read_write == I2C_SMBUS_READ) {
|
|
data->block[i] = inb_p(SMBBLKDAT(priv));
|
|
+ if (i == len - 1)
|
|
+ outb_p(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv));
|
|
+ }
|
|
+
|
|
if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
|
|
outb_p(data->block[i+1], SMBBLKDAT(priv));
|
|
|
|
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
|
|
index b605b6e43cb90..ade3f0ea59551 100644
|
|
--- a/drivers/i2c/busses/i2c-pxa.c
|
|
+++ b/drivers/i2c/busses/i2c-pxa.c
|
|
@@ -264,6 +264,9 @@ struct pxa_i2c {
|
|
u32 hs_mask;
|
|
|
|
struct i2c_bus_recovery_info recovery;
|
|
+ struct pinctrl *pinctrl;
|
|
+ struct pinctrl_state *pinctrl_default;
|
|
+ struct pinctrl_state *pinctrl_recovery;
|
|
};
|
|
|
|
#define _IBMR(i2c) ((i2c)->reg_ibmr)
|
|
@@ -1302,12 +1305,13 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter *adap)
|
|
*/
|
|
gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS);
|
|
gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS);
|
|
+
|
|
+ WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery));
|
|
}
|
|
|
|
static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
|
|
{
|
|
struct pxa_i2c *i2c = adap->algo_data;
|
|
- struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
|
|
u32 isr;
|
|
|
|
/*
|
|
@@ -1321,7 +1325,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap)
|
|
i2c_pxa_do_reset(i2c);
|
|
}
|
|
|
|
- WARN_ON(pinctrl_select_state(bri->pinctrl, bri->pins_default));
|
|
+ WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default));
|
|
|
|
dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n",
|
|
readl(_IBMR(i2c)), readl(_ISR(i2c)));
|
|
@@ -1343,20 +1347,76 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c)
|
|
if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE))
|
|
return 0;
|
|
|
|
- bri->pinctrl = devm_pinctrl_get(dev);
|
|
- if (PTR_ERR(bri->pinctrl) == -ENODEV) {
|
|
- bri->pinctrl = NULL;
|
|
+ i2c->pinctrl = devm_pinctrl_get(dev);
|
|
+ if (PTR_ERR(i2c->pinctrl) == -ENODEV)
|
|
+ i2c->pinctrl = NULL;
|
|
+ if (IS_ERR(i2c->pinctrl))
|
|
+ return PTR_ERR(i2c->pinctrl);
|
|
+
|
|
+ if (!i2c->pinctrl)
|
|
+ return 0;
|
|
+
|
|
+ i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl,
|
|
+ PINCTRL_STATE_DEFAULT);
|
|
+ i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery");
|
|
+
|
|
+ if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) {
|
|
+ dev_info(dev, "missing pinmux recovery information: %ld %ld\n",
|
|
+ PTR_ERR(i2c->pinctrl_default),
|
|
+ PTR_ERR(i2c->pinctrl_recovery));
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Claiming GPIOs can influence the pinmux state, and may glitch the
|
|
+ * I2C bus. Do this carefully.
|
|
+ */
|
|
+ bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
|
|
+ if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER))
|
|
+ return -EPROBE_DEFER;
|
|
+ if (IS_ERR(bri->scl_gpiod)) {
|
|
+ dev_info(dev, "missing scl gpio recovery information: %pe\n",
|
|
+ bri->scl_gpiod);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * We have SCL. Pull SCL low and wait a bit so that SDA glitches
|
|
+ * have no effect.
|
|
+ */
|
|
+ gpiod_direction_output(bri->scl_gpiod, 0);
|
|
+ udelay(10);
|
|
+ bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN);
|
|
+
|
|
+ /* Wait a bit in case of a SDA glitch, and then release SCL. */
|
|
+ udelay(10);
|
|
+ gpiod_direction_output(bri->scl_gpiod, 1);
|
|
+
|
|
+ if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER))
|
|
+ return -EPROBE_DEFER;
|
|
+
|
|
+ if (IS_ERR(bri->sda_gpiod)) {
|
|
+ dev_info(dev, "missing sda gpio recovery information: %pe\n",
|
|
+ bri->sda_gpiod);
|
|
return 0;
|
|
}
|
|
- if (IS_ERR(bri->pinctrl))
|
|
- return PTR_ERR(bri->pinctrl);
|
|
|
|
bri->prepare_recovery = i2c_pxa_prepare_recovery;
|
|
bri->unprepare_recovery = i2c_pxa_unprepare_recovery;
|
|
+ bri->recover_bus = i2c_generic_scl_recovery;
|
|
|
|
i2c->adap.bus_recovery_info = bri;
|
|
|
|
- return 0;
|
|
+ /*
|
|
+ * Claiming GPIOs can change the pinmux state, which confuses the
|
|
+ * pinctrl since pinctrl's idea of the current setting is unaffected
|
|
+ * by the pinmux change caused by claiming the GPIO. Work around that
|
|
+ * by switching pinctrl to the GPIO state here. We do it this way to
|
|
+ * avoid glitching the I2C bus.
|
|
+ */
|
|
+ pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery);
|
|
+
|
|
+ return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default);
|
|
}
|
|
|
|
static int i2c_pxa_probe(struct platform_device *dev)
|
|
diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c
|
|
index 9e3483f507ff5..f2ed13b551088 100644
|
|
--- a/drivers/i2c/busses/i2c-sun6i-p2wi.c
|
|
+++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c
|
|
@@ -201,6 +201,11 @@ static int p2wi_probe(struct platform_device *pdev)
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ if (clk_freq == 0) {
|
|
+ dev_err(dev, "clock-frequency is set to 0 in DT\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
if (of_get_child_count(np) > 1) {
|
|
dev_err(dev, "P2WI only supports one slave device\n");
|
|
return -EINVAL;
|
|
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
|
|
index 7539b0740351d..5e3976ba52650 100644
|
|
--- a/drivers/i2c/i2c-core-base.c
|
|
+++ b/drivers/i2c/i2c-core-base.c
|
|
@@ -916,8 +916,9 @@ int i2c_dev_irq_from_resources(const struct resource *resources,
|
|
struct i2c_client *
|
|
i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
|
|
{
|
|
- struct i2c_client *client;
|
|
- int status;
|
|
+ struct i2c_client *client;
|
|
+ bool need_put = false;
|
|
+ int status;
|
|
|
|
client = kzalloc(sizeof *client, GFP_KERNEL);
|
|
if (!client)
|
|
@@ -955,7 +956,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
|
|
client->dev.fwnode = info->fwnode;
|
|
|
|
device_enable_async_suspend(&client->dev);
|
|
- i2c_dev_set_name(adap, client, info);
|
|
|
|
if (info->swnode) {
|
|
status = device_add_software_node(&client->dev, info->swnode);
|
|
@@ -967,6 +967,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
|
|
}
|
|
}
|
|
|
|
+ i2c_dev_set_name(adap, client, info);
|
|
status = device_register(&client->dev);
|
|
if (status)
|
|
goto out_remove_swnode;
|
|
@@ -978,6 +979,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
|
|
|
|
out_remove_swnode:
|
|
device_remove_software_node(&client->dev);
|
|
+ need_put = true;
|
|
out_err_put_of_node:
|
|
of_node_put(info->of_node);
|
|
out_err:
|
|
@@ -985,7 +987,10 @@ out_err:
|
|
"Failed to register i2c client %s at 0x%02x (%d)\n",
|
|
client->name, client->addr, status);
|
|
out_err_silent:
|
|
- kfree(client);
|
|
+ if (need_put)
|
|
+ put_device(&client->dev);
|
|
+ else
|
|
+ kfree(client);
|
|
return ERR_PTR(status);
|
|
}
|
|
EXPORT_SYMBOL_GPL(i2c_new_client_device);
|
|
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
|
|
index 1247e6e6e9751..05b8b8dfa9bdd 100644
|
|
--- a/drivers/i2c/i2c-core.h
|
|
+++ b/drivers/i2c/i2c-core.h
|
|
@@ -29,7 +29,7 @@ int i2c_dev_irq_from_resources(const struct resource *resources,
|
|
*/
|
|
static inline bool i2c_in_atomic_xfer_mode(void)
|
|
{
|
|
- return system_state > SYSTEM_RUNNING && irqs_disabled();
|
|
+ return system_state > SYSTEM_RUNNING && !preemptible();
|
|
}
|
|
|
|
static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
|
|
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
|
|
index ab0adaa130dae..dd35f341b16fd 100644
|
|
--- a/drivers/i2c/i2c-dev.c
|
|
+++ b/drivers/i2c/i2c-dev.c
|
|
@@ -450,8 +450,8 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
|
|
return -EINVAL;
|
|
|
|
- rdwr_pa = memdup_user(rdwr_arg.msgs,
|
|
- rdwr_arg.nmsgs * sizeof(struct i2c_msg));
|
|
+ rdwr_pa = memdup_array_user(rdwr_arg.msgs,
|
|
+ rdwr_arg.nmsgs, sizeof(struct i2c_msg));
|
|
if (IS_ERR(rdwr_pa))
|
|
return PTR_ERR(rdwr_pa);
|
|
|
|
diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
|
|
index 5b37ffe5ad5be..4a49c75a9408c 100644
|
|
--- a/drivers/i3c/master/i3c-master-cdns.c
|
|
+++ b/drivers/i3c/master/i3c-master-cdns.c
|
|
@@ -192,7 +192,7 @@
|
|
#define SLV_STATUS1_HJ_DIS BIT(18)
|
|
#define SLV_STATUS1_MR_DIS BIT(17)
|
|
#define SLV_STATUS1_PROT_ERR BIT(16)
|
|
-#define SLV_STATUS1_DA(x) (((s) & GENMASK(15, 9)) >> 9)
|
|
+#define SLV_STATUS1_DA(s) (((s) & GENMASK(15, 9)) >> 9)
|
|
#define SLV_STATUS1_HAS_DA BIT(8)
|
|
#define SLV_STATUS1_DDR_RX_FULL BIT(7)
|
|
#define SLV_STATUS1_DDR_TX_FULL BIT(6)
|
|
@@ -1624,13 +1624,13 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
|
|
/* Device ID0 is reserved to describe this master. */
|
|
master->maxdevs = CONF_STATUS0_DEVS_NUM(val);
|
|
master->free_rr_slots = GENMASK(master->maxdevs, 1);
|
|
+ master->caps.ibirfifodepth = CONF_STATUS0_IBIR_DEPTH(val);
|
|
+ master->caps.cmdrfifodepth = CONF_STATUS0_CMDR_DEPTH(val);
|
|
|
|
val = readl(master->regs + CONF_STATUS1);
|
|
master->caps.cmdfifodepth = CONF_STATUS1_CMD_DEPTH(val);
|
|
master->caps.rxfifodepth = CONF_STATUS1_RX_DEPTH(val);
|
|
master->caps.txfifodepth = CONF_STATUS1_TX_DEPTH(val);
|
|
- master->caps.ibirfifodepth = CONF_STATUS0_IBIR_DEPTH(val);
|
|
- master->caps.cmdrfifodepth = CONF_STATUS0_CMDR_DEPTH(val);
|
|
|
|
spin_lock_init(&master->ibi.lock);
|
|
master->ibi.num_slots = CONF_STATUS1_IBI_HW_RES(val);
|
|
diff --git a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
|
|
index 97bb49ff5b53b..47b9b4d4ed3fc 100644
|
|
--- a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
|
|
+++ b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
|
|
@@ -64,15 +64,17 @@ static int hci_dat_v1_init(struct i3c_hci *hci)
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
- /* use a bitmap for faster free slot search */
|
|
- hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL);
|
|
- if (!hci->DAT_data)
|
|
- return -ENOMEM;
|
|
-
|
|
- /* clear them */
|
|
- for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
|
|
- dat_w0_write(dat_idx, 0);
|
|
- dat_w1_write(dat_idx, 0);
|
|
+ if (!hci->DAT_data) {
|
|
+ /* use a bitmap for faster free slot search */
|
|
+ hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL);
|
|
+ if (!hci->DAT_data)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ /* clear them */
|
|
+ for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
|
|
+ dat_w0_write(dat_idx, 0);
|
|
+ dat_w1_write(dat_idx, 0);
|
|
+ }
|
|
}
|
|
|
|
return 0;
|
|
@@ -87,7 +89,13 @@ static void hci_dat_v1_cleanup(struct i3c_hci *hci)
|
|
static int hci_dat_v1_alloc_entry(struct i3c_hci *hci)
|
|
{
|
|
unsigned int dat_idx;
|
|
+ int ret;
|
|
|
|
+ if (!hci->DAT_data) {
|
|
+ ret = hci_dat_v1_init(hci);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
dat_idx = find_first_zero_bit(hci->DAT_data, hci->DAT_entries);
|
|
if (dat_idx >= hci->DAT_entries)
|
|
return -ENOENT;
|
|
@@ -103,7 +111,8 @@ static void hci_dat_v1_free_entry(struct i3c_hci *hci, unsigned int dat_idx)
|
|
{
|
|
dat_w0_write(dat_idx, 0);
|
|
dat_w1_write(dat_idx, 0);
|
|
- __clear_bit(dat_idx, hci->DAT_data);
|
|
+ if (hci->DAT_data)
|
|
+ __clear_bit(dat_idx, hci->DAT_data);
|
|
}
|
|
|
|
static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,
|
|
diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
|
|
index 2990ac9eaade7..71b5dbe45c45c 100644
|
|
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
|
|
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
|
|
@@ -734,7 +734,7 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci, unsigned int mask)
|
|
unsigned int i;
|
|
bool handled = false;
|
|
|
|
- for (i = 0; mask && i < 8; i++) {
|
|
+ for (i = 0; mask && i < rings->total; i++) {
|
|
struct hci_rh_data *rh;
|
|
u32 status;
|
|
|
|
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
|
|
index 4eebf15f685a3..f30d457e91196 100644
|
|
--- a/drivers/i3c/master/svc-i3c-master.c
|
|
+++ b/drivers/i3c/master/svc-i3c-master.c
|
|
@@ -92,6 +92,8 @@
|
|
#define SVC_I3C_MINTCLR 0x094
|
|
#define SVC_I3C_MINTMASKED 0x098
|
|
#define SVC_I3C_MERRWARN 0x09C
|
|
+#define SVC_I3C_MERRWARN_NACK BIT(2)
|
|
+#define SVC_I3C_MERRWARN_TIMEOUT BIT(20)
|
|
#define SVC_I3C_MDMACTRL 0x0A0
|
|
#define SVC_I3C_MDATACTRL 0x0AC
|
|
#define SVC_I3C_MDATACTRL_FLUSHTB BIT(0)
|
|
@@ -168,6 +170,7 @@ struct svc_i3c_xfer {
|
|
* @ibi.slots: Available IBI slots
|
|
* @ibi.tbq_slot: To be queued IBI slot
|
|
* @ibi.lock: IBI lock
|
|
+ * @lock: Transfer lock, protect between IBI work thread and callbacks from master
|
|
*/
|
|
struct svc_i3c_master {
|
|
struct i3c_master_controller base;
|
|
@@ -195,6 +198,7 @@ struct svc_i3c_master {
|
|
/* Prevent races within IBI handlers */
|
|
spinlock_t lock;
|
|
} ibi;
|
|
+ struct mutex lock;
|
|
};
|
|
|
|
/**
|
|
@@ -217,6 +221,14 @@ static bool svc_i3c_master_error(struct svc_i3c_master *master)
|
|
if (SVC_I3C_MSTATUS_ERRWARN(mstatus)) {
|
|
merrwarn = readl(master->regs + SVC_I3C_MERRWARN);
|
|
writel(merrwarn, master->regs + SVC_I3C_MERRWARN);
|
|
+
|
|
+ /* Ignore timeout error */
|
|
+ if (merrwarn & SVC_I3C_MERRWARN_TIMEOUT) {
|
|
+ dev_dbg(master->dev, "Warning condition: MSTATUS 0x%08x, MERRWARN 0x%08x\n",
|
|
+ mstatus, merrwarn);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
dev_err(master->dev,
|
|
"Error condition: MSTATUS 0x%08x, MERRWARN 0x%08x\n",
|
|
mstatus, merrwarn);
|
|
@@ -323,6 +335,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
|
|
struct i3c_ibi_slot *slot;
|
|
unsigned int count;
|
|
u32 mdatactrl;
|
|
+ int ret, val;
|
|
u8 *buf;
|
|
|
|
slot = i3c_generic_ibi_get_free_slot(data->ibi_pool);
|
|
@@ -332,6 +345,13 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
|
|
slot->len = 0;
|
|
buf = slot->data;
|
|
|
|
+ ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val,
|
|
+ SVC_I3C_MSTATUS_COMPLETE(val), 0, 1000);
|
|
+ if (ret) {
|
|
+ dev_err(master->dev, "Timeout when polling for COMPLETE\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
while (SVC_I3C_MSTATUS_RXPEND(readl(master->regs + SVC_I3C_MSTATUS)) &&
|
|
slot->len < SVC_I3C_FIFO_SIZE) {
|
|
mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL);
|
|
@@ -376,6 +396,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
|
|
u32 status, val;
|
|
int ret;
|
|
|
|
+ mutex_lock(&master->lock);
|
|
/* Acknowledge the incoming interrupt with the AUTOIBI mechanism */
|
|
writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI |
|
|
SVC_I3C_MCTRL_IBIRESP_AUTO,
|
|
@@ -386,6 +407,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
|
|
SVC_I3C_MSTATUS_IBIWON(val), 0, 1000);
|
|
if (ret) {
|
|
dev_err(master->dev, "Timeout when polling for IBIWON\n");
|
|
+ svc_i3c_master_emit_stop(master);
|
|
goto reenable_ibis;
|
|
}
|
|
|
|
@@ -452,12 +474,13 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
|
|
|
|
reenable_ibis:
|
|
svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
|
|
+ mutex_unlock(&master->lock);
|
|
}
|
|
|
|
static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
|
|
{
|
|
struct svc_i3c_master *master = (struct svc_i3c_master *)dev_id;
|
|
- u32 active = readl(master->regs + SVC_I3C_MINTMASKED);
|
|
+ u32 active = readl(master->regs + SVC_I3C_MSTATUS);
|
|
|
|
if (!SVC_I3C_MSTATUS_SLVSTART(active))
|
|
return IRQ_NONE;
|
|
@@ -999,6 +1022,9 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
|
|
u32 reg;
|
|
int ret;
|
|
|
|
+ /* clean SVC_I3C_MINT_IBIWON w1c bits */
|
|
+ writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
|
|
+
|
|
writel(SVC_I3C_MCTRL_REQUEST_START_ADDR |
|
|
xfer_type |
|
|
SVC_I3C_MCTRL_IBIRESP_NACK |
|
|
@@ -1012,6 +1038,11 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
|
|
if (ret)
|
|
goto emit_stop;
|
|
|
|
+ if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) {
|
|
+ ret = -ENXIO;
|
|
+ goto emit_stop;
|
|
+ }
|
|
+
|
|
if (rnw)
|
|
ret = svc_i3c_master_read(master, in, xfer_len);
|
|
else
|
|
@@ -1019,6 +1050,23 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
|
|
if (ret < 0)
|
|
goto emit_stop;
|
|
|
|
+ /*
|
|
+ * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a Frame
|
|
+ * with I3C Target Address.
|
|
+ *
|
|
+ * The I3C Controller normally should start a Frame, the Address may be arbitrated, and so
|
|
+ * the Controller shall monitor to see whether an In-Band Interrupt request, a Controller
|
|
+ * Role Request (i.e., Secondary Controller requests to become the Active Controller), or
|
|
+ * a Hot-Join Request has been made.
|
|
+ *
|
|
+ * If missed IBIWON check, the wrong data will be return. When IBIWON happen, return failure
|
|
+ * and yield the above events handler.
|
|
+ */
|
|
+ if (SVC_I3C_MSTATUS_IBIWON(reg)) {
|
|
+ ret = -ENXIO;
|
|
+ goto emit_stop;
|
|
+ }
|
|
+
|
|
if (rnw)
|
|
*read_len = ret;
|
|
|
|
@@ -1191,9 +1239,11 @@ static int svc_i3c_master_send_bdcast_ccc_cmd(struct svc_i3c_master *master,
|
|
cmd->read_len = 0;
|
|
cmd->continued = false;
|
|
|
|
+ mutex_lock(&master->lock);
|
|
svc_i3c_master_enqueue_xfer(master, xfer);
|
|
if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)))
|
|
svc_i3c_master_dequeue_xfer(master, xfer);
|
|
+ mutex_unlock(&master->lock);
|
|
|
|
ret = xfer->ret;
|
|
kfree(buf);
|
|
@@ -1237,9 +1287,11 @@ static int svc_i3c_master_send_direct_ccc_cmd(struct svc_i3c_master *master,
|
|
cmd->read_len = read_len;
|
|
cmd->continued = false;
|
|
|
|
+ mutex_lock(&master->lock);
|
|
svc_i3c_master_enqueue_xfer(master, xfer);
|
|
if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)))
|
|
svc_i3c_master_dequeue_xfer(master, xfer);
|
|
+ mutex_unlock(&master->lock);
|
|
|
|
if (cmd->read_len != xfer_len)
|
|
ccc->dests[0].payload.len = cmd->read_len;
|
|
@@ -1296,9 +1348,11 @@ static int svc_i3c_master_priv_xfers(struct i3c_dev_desc *dev,
|
|
cmd->continued = (i + 1) < nxfers;
|
|
}
|
|
|
|
+ mutex_lock(&master->lock);
|
|
svc_i3c_master_enqueue_xfer(master, xfer);
|
|
if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)))
|
|
svc_i3c_master_dequeue_xfer(master, xfer);
|
|
+ mutex_unlock(&master->lock);
|
|
|
|
ret = xfer->ret;
|
|
svc_i3c_master_free_xfer(xfer);
|
|
@@ -1334,9 +1388,11 @@ static int svc_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
|
|
cmd->continued = (i + 1 < nxfers);
|
|
}
|
|
|
|
+ mutex_lock(&master->lock);
|
|
svc_i3c_master_enqueue_xfer(master, xfer);
|
|
if (!wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000)))
|
|
svc_i3c_master_dequeue_xfer(master, xfer);
|
|
+ mutex_unlock(&master->lock);
|
|
|
|
ret = xfer->ret;
|
|
svc_i3c_master_free_xfer(xfer);
|
|
@@ -1527,6 +1583,8 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
|
|
|
|
INIT_WORK(&master->hj_work, svc_i3c_master_hj_work);
|
|
INIT_WORK(&master->ibi_work, svc_i3c_master_ibi_work);
|
|
+ mutex_init(&master->lock);
|
|
+
|
|
ret = devm_request_irq(dev, master->irq, svc_i3c_master_irq_handler,
|
|
IRQF_NO_SUSPEND, "svc-i3c-irq", master);
|
|
if (ret)
|
|
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
|
|
index 81d5db91c67bf..dee47b899e5df 100644
|
|
--- a/drivers/iio/adc/stm32-adc-core.c
|
|
+++ b/drivers/iio/adc/stm32-adc-core.c
|
|
@@ -695,6 +695,8 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
|
struct stm32_adc_priv *priv;
|
|
struct device *dev = &pdev->dev;
|
|
struct device_node *np = pdev->dev.of_node;
|
|
+ const struct of_device_id *of_id;
|
|
+
|
|
struct resource *res;
|
|
u32 max_rate;
|
|
int ret;
|
|
@@ -707,8 +709,11 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
|
return -ENOMEM;
|
|
platform_set_drvdata(pdev, &priv->common);
|
|
|
|
- priv->cfg = (const struct stm32_adc_priv_cfg *)
|
|
- of_match_device(dev->driver->of_match_table, dev)->data;
|
|
+ of_id = of_match_device(dev->driver->of_match_table, dev);
|
|
+ if (!of_id)
|
|
+ return -ENODEV;
|
|
+
|
|
+ priv->cfg = (const struct stm32_adc_priv_cfg *)of_id->data;
|
|
priv->nb_adc_max = priv->cfg->num_adcs;
|
|
spin_lock_init(&priv->common.lock);
|
|
|
|
diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
|
|
index a0802332c8cb3..5395cf56fbd90 100644
|
|
--- a/drivers/infiniband/hw/hfi1/pcie.c
|
|
+++ b/drivers/infiniband/hw/hfi1/pcie.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright(c) 2015 - 2019 Intel Corporation.
|
|
*/
|
|
|
|
+#include <linux/bitfield.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/io.h>
|
|
#include <linux/delay.h>
|
|
@@ -212,12 +213,6 @@ static u32 extract_speed(u16 linkstat)
|
|
return speed;
|
|
}
|
|
|
|
-/* return the PCIe link speed from the given link status */
|
|
-static u32 extract_width(u16 linkstat)
|
|
-{
|
|
- return (linkstat & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
|
|
-}
|
|
-
|
|
/* read the link status and set dd->{lbus_width,lbus_speed,lbus_info} */
|
|
static void update_lbus_info(struct hfi1_devdata *dd)
|
|
{
|
|
@@ -230,7 +225,7 @@ static void update_lbus_info(struct hfi1_devdata *dd)
|
|
return;
|
|
}
|
|
|
|
- dd->lbus_width = extract_width(linkstat);
|
|
+ dd->lbus_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, linkstat);
|
|
dd->lbus_speed = extract_speed(linkstat);
|
|
snprintf(dd->lbus_info, sizeof(dd->lbus_info),
|
|
"PCIe,%uMHz,x%u", dd->lbus_speed, dd->lbus_width);
|
|
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
|
|
index c19a4d2023805..fc6957fddce8e 100644
|
|
--- a/drivers/input/joystick/xpad.c
|
|
+++ b/drivers/input/joystick/xpad.c
|
|
@@ -474,6 +474,7 @@ static const struct usb_device_id xpad_table[] = {
|
|
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
|
|
XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
|
|
XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
|
|
+ XPAD_XBOXONE_VENDOR(0x10f5), /* Turtle Beach Controllers */
|
|
XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
|
|
XPAD_XBOX360_VENDOR(0x11ff), /* PXN V900 */
|
|
XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */
|
|
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c
|
|
index e7b6989d8b4a8..a6b4ccc314cac 100644
|
|
--- a/drivers/mcb/mcb-core.c
|
|
+++ b/drivers/mcb/mcb-core.c
|
|
@@ -246,6 +246,7 @@ int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev)
|
|
return 0;
|
|
|
|
out:
|
|
+ put_device(&dev->dev);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
|
|
index 656b6b71c7682..1ae37e693de04 100644
|
|
--- a/drivers/mcb/mcb-parse.c
|
|
+++ b/drivers/mcb/mcb-parse.c
|
|
@@ -106,7 +106,7 @@ static int chameleon_parse_gdd(struct mcb_bus *bus,
|
|
return 0;
|
|
|
|
err:
|
|
- put_device(&mdev->dev);
|
|
+ mcb_free_dev(mdev);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c
|
|
index 962fc32c947c5..9eb03bb224698 100644
|
|
--- a/drivers/md/dm-verity-fec.c
|
|
+++ b/drivers/md/dm-verity-fec.c
|
|
@@ -185,7 +185,7 @@ static int fec_is_erasure(struct dm_verity *v, struct dm_verity_io *io,
|
|
{
|
|
if (unlikely(verity_hash(v, verity_io_hash_req(v, io),
|
|
data, 1 << v->data_dev_block_bits,
|
|
- verity_io_real_digest(v, io))))
|
|
+ verity_io_real_digest(v, io), true)))
|
|
return 0;
|
|
|
|
return memcmp(verity_io_real_digest(v, io), want_digest,
|
|
@@ -386,7 +386,7 @@ static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
|
|
/* Always re-validate the corrected block against the expected hash */
|
|
r = verity_hash(v, verity_io_hash_req(v, io), fio->output,
|
|
1 << v->data_dev_block_bits,
|
|
- verity_io_real_digest(v, io));
|
|
+ verity_io_real_digest(v, io), true);
|
|
if (unlikely(r < 0))
|
|
return r;
|
|
|
|
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
|
|
index 14a9988ec30ba..b86d41219ba9c 100644
|
|
--- a/drivers/md/dm-verity-target.c
|
|
+++ b/drivers/md/dm-verity-target.c
|
|
@@ -132,20 +132,21 @@ static int verity_hash_update(struct dm_verity *v, struct ahash_request *req,
|
|
* Wrapper for crypto_ahash_init, which handles verity salting.
|
|
*/
|
|
static int verity_hash_init(struct dm_verity *v, struct ahash_request *req,
|
|
- struct crypto_wait *wait)
|
|
+ struct crypto_wait *wait, bool may_sleep)
|
|
{
|
|
int r;
|
|
|
|
ahash_request_set_tfm(req, v->tfm);
|
|
- ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP |
|
|
- CRYPTO_TFM_REQ_MAY_BACKLOG,
|
|
- crypto_req_done, (void *)wait);
|
|
+ ahash_request_set_callback(req,
|
|
+ may_sleep ? CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG : 0,
|
|
+ crypto_req_done, (void *)wait);
|
|
crypto_init_wait(wait);
|
|
|
|
r = crypto_wait_req(crypto_ahash_init(req), wait);
|
|
|
|
if (unlikely(r < 0)) {
|
|
- DMERR("crypto_ahash_init failed: %d", r);
|
|
+ if (r != -ENOMEM)
|
|
+ DMERR("crypto_ahash_init failed: %d", r);
|
|
return r;
|
|
}
|
|
|
|
@@ -176,12 +177,12 @@ out:
|
|
}
|
|
|
|
int verity_hash(struct dm_verity *v, struct ahash_request *req,
|
|
- const u8 *data, size_t len, u8 *digest)
|
|
+ const u8 *data, size_t len, u8 *digest, bool may_sleep)
|
|
{
|
|
int r;
|
|
struct crypto_wait wait;
|
|
|
|
- r = verity_hash_init(v, req, &wait);
|
|
+ r = verity_hash_init(v, req, &wait, may_sleep);
|
|
if (unlikely(r < 0))
|
|
goto out;
|
|
|
|
@@ -317,7 +318,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
|
|
|
|
r = verity_hash(v, verity_io_hash_req(v, io),
|
|
data, 1 << v->hash_dev_block_bits,
|
|
- verity_io_real_digest(v, io));
|
|
+ verity_io_real_digest(v, io), !io->in_tasklet);
|
|
if (unlikely(r < 0))
|
|
goto release_ret_r;
|
|
|
|
@@ -548,7 +549,7 @@ static int verity_verify_io(struct dm_verity_io *io)
|
|
continue;
|
|
}
|
|
|
|
- r = verity_hash_init(v, req, &wait);
|
|
+ r = verity_hash_init(v, req, &wait, !io->in_tasklet);
|
|
if (unlikely(r < 0))
|
|
return r;
|
|
|
|
@@ -641,7 +642,7 @@ static void verity_tasklet(unsigned long data)
|
|
|
|
io->in_tasklet = true;
|
|
err = verity_verify_io(io);
|
|
- if (err == -EAGAIN) {
|
|
+ if (err == -EAGAIN || err == -ENOMEM) {
|
|
/* fallback to retrying with work-queue */
|
|
INIT_WORK(&io->work, verity_work);
|
|
queue_work(io->v->verify_wq, &io->work);
|
|
@@ -1018,7 +1019,7 @@ static int verity_alloc_zero_digest(struct dm_verity *v)
|
|
goto out;
|
|
|
|
r = verity_hash(v, req, zero_data, 1 << v->data_dev_block_bits,
|
|
- v->zero_digest);
|
|
+ v->zero_digest, true);
|
|
|
|
out:
|
|
kfree(req);
|
|
diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h
|
|
index 2f555b4203679..f96f4e281ee4a 100644
|
|
--- a/drivers/md/dm-verity.h
|
|
+++ b/drivers/md/dm-verity.h
|
|
@@ -128,7 +128,7 @@ extern int verity_for_bv_block(struct dm_verity *v, struct dm_verity_io *io,
|
|
u8 *data, size_t len));
|
|
|
|
extern int verity_hash(struct dm_verity *v, struct ahash_request *req,
|
|
- const u8 *data, size_t len, u8 *digest);
|
|
+ const u8 *data, size_t len, u8 *digest, bool may_sleep);
|
|
|
|
extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,
|
|
sector_t block, u8 *digest, bool *is_zero);
|
|
diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c
|
|
index 4a14d7e5d9f25..5fdb922d24e05 100644
|
|
--- a/drivers/media/i2c/ccs/ccs-core.c
|
|
+++ b/drivers/media/i2c/ccs/ccs-core.c
|
|
@@ -3088,7 +3088,7 @@ static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
|
try_fmt->code = sensor->internal_csi_format->code;
|
|
try_fmt->field = V4L2_FIELD_NONE;
|
|
|
|
- if (ssd != sensor->pixel_array)
|
|
+ if (ssd == sensor->pixel_array)
|
|
continue;
|
|
|
|
try_comp = v4l2_subdev_get_try_compose(sd, fh->state, i);
|
|
diff --git a/drivers/media/i2c/ccs/ccs-quirk.h b/drivers/media/i2c/ccs/ccs-quirk.h
|
|
index 5838fcda92fd4..0b1a64958d714 100644
|
|
--- a/drivers/media/i2c/ccs/ccs-quirk.h
|
|
+++ b/drivers/media/i2c/ccs/ccs-quirk.h
|
|
@@ -32,12 +32,10 @@ struct ccs_sensor;
|
|
* @reg: Pointer to the register to access
|
|
* @value: Register value, set by the caller on write, or
|
|
* by the quirk on read
|
|
- *
|
|
- * @flags: Quirk flags
|
|
- *
|
|
* @return: 0 on success, -ENOIOCTLCMD if no register
|
|
* access may be done by the caller (default read
|
|
* value is zero), else negative error code on error
|
|
+ * @flags: Quirk flags
|
|
*/
|
|
struct ccs_quirk {
|
|
int (*limits)(struct ccs_sensor *sensor);
|
|
diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c
|
|
index 74edcc76d12f4..6e1a0614e6d06 100644
|
|
--- a/drivers/media/pci/cobalt/cobalt-driver.c
|
|
+++ b/drivers/media/pci/cobalt/cobalt-driver.c
|
|
@@ -8,6 +8,7 @@
|
|
* All rights reserved.
|
|
*/
|
|
|
|
+#include <linux/bitfield.h>
|
|
#include <linux/delay.h>
|
|
#include <media/i2c/adv7604.h>
|
|
#include <media/i2c/adv7842.h>
|
|
@@ -210,17 +211,17 @@ void cobalt_pcie_status_show(struct cobalt *cobalt)
|
|
pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &stat);
|
|
cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n",
|
|
capa, get_link_speed(capa),
|
|
- (capa & PCI_EXP_LNKCAP_MLW) >> 4);
|
|
+ FIELD_GET(PCI_EXP_LNKCAP_MLW, capa));
|
|
cobalt_info("PCIe link control 0x%04x\n", ctrl);
|
|
cobalt_info("PCIe link status 0x%04x: %s per lane and %u lanes\n",
|
|
stat, get_link_speed(stat),
|
|
- (stat & PCI_EXP_LNKSTA_NLW) >> 4);
|
|
+ FIELD_GET(PCI_EXP_LNKSTA_NLW, stat));
|
|
|
|
/* Bus */
|
|
pcie_capability_read_dword(pci_bus_dev, PCI_EXP_LNKCAP, &capa);
|
|
cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n",
|
|
capa, get_link_speed(capa),
|
|
- (capa & PCI_EXP_LNKCAP_MLW) >> 4);
|
|
+ FIELD_GET(PCI_EXP_LNKCAP_MLW, capa));
|
|
|
|
/* Slot */
|
|
pcie_capability_read_dword(pci_dev, PCI_EXP_SLTCAP, &capa);
|
|
@@ -239,7 +240,7 @@ static unsigned pcie_link_get_lanes(struct cobalt *cobalt)
|
|
if (!pci_is_pcie(pci_dev))
|
|
return 0;
|
|
pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &link);
|
|
- return (link & PCI_EXP_LNKSTA_NLW) >> 4;
|
|
+ return FIELD_GET(PCI_EXP_LNKSTA_NLW, link);
|
|
}
|
|
|
|
static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt)
|
|
@@ -250,7 +251,7 @@ static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt)
|
|
if (!pci_is_pcie(pci_dev))
|
|
return 0;
|
|
pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &link);
|
|
- return (link & PCI_EXP_LNKCAP_MLW) >> 4;
|
|
+ return FIELD_GET(PCI_EXP_LNKCAP_MLW, link);
|
|
}
|
|
|
|
static void msi_config_show(struct cobalt *cobalt, struct pci_dev *pci_dev)
|
|
diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen2.c b/drivers/media/platform/qcom/camss/camss-csid-gen2.c
|
|
index 2031bde13a939..904208f6f9546 100644
|
|
--- a/drivers/media/platform/qcom/camss/camss-csid-gen2.c
|
|
+++ b/drivers/media/platform/qcom/camss/camss-csid-gen2.c
|
|
@@ -355,9 +355,6 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
|
|
u8 dt_id = vc * 4;
|
|
|
|
if (tg->enabled) {
|
|
- /* Config Test Generator */
|
|
- vc = 0xa;
|
|
-
|
|
/* configure one DT, infinite frames */
|
|
val = vc << TPG_VC_CFG0_VC_NUM;
|
|
val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE;
|
|
@@ -370,14 +367,14 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable)
|
|
|
|
writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED);
|
|
|
|
- val = input_format->height & 0x1fff << TPG_DT_n_CFG_0_FRAME_HEIGHT;
|
|
- val |= input_format->width & 0x1fff << TPG_DT_n_CFG_0_FRAME_WIDTH;
|
|
+ val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT;
|
|
+ val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH;
|
|
writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0));
|
|
|
|
val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE;
|
|
writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0));
|
|
|
|
- val = tg->mode << TPG_DT_n_CFG_2_PAYLOAD_MODE;
|
|
+ val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE;
|
|
val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD;
|
|
val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT;
|
|
writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0));
|
|
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c
|
|
index 04baa80494c66..4dba61b8d3f2a 100644
|
|
--- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c
|
|
+++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c
|
|
@@ -476,7 +476,7 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy,
|
|
|
|
settle_cnt = csiphy_settle_cnt_calc(link_freq, csiphy->timer_clk_rate);
|
|
|
|
- val = is_gen2 ? BIT(7) : CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE;
|
|
+ val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE;
|
|
for (i = 0; i < c->num_data; i++)
|
|
val |= BIT(c->data[i].pos * 2);
|
|
|
|
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-170.c b/drivers/media/platform/qcom/camss/camss-vfe-170.c
|
|
index 600150cfc4f70..07b64d257512c 100644
|
|
--- a/drivers/media/platform/qcom/camss/camss-vfe-170.c
|
|
+++ b/drivers/media/platform/qcom/camss/camss-vfe-170.c
|
|
@@ -7,7 +7,6 @@
|
|
* Copyright (C) 2020-2021 Linaro Ltd.
|
|
*/
|
|
|
|
-#include <linux/delay.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/io.h>
|
|
#include <linux/iopoll.h>
|
|
@@ -494,35 +493,20 @@ static int vfe_enable_output(struct vfe_line *line)
|
|
return 0;
|
|
}
|
|
|
|
-static int vfe_disable_output(struct vfe_line *line)
|
|
+static void vfe_disable_output(struct vfe_line *line)
|
|
{
|
|
struct vfe_device *vfe = to_vfe(line);
|
|
struct vfe_output *output = &line->output;
|
|
unsigned long flags;
|
|
unsigned int i;
|
|
- bool done;
|
|
- int timeout = 0;
|
|
-
|
|
- do {
|
|
- spin_lock_irqsave(&vfe->output_lock, flags);
|
|
- done = !output->gen2.active_num;
|
|
- spin_unlock_irqrestore(&vfe->output_lock, flags);
|
|
- usleep_range(10000, 20000);
|
|
-
|
|
- if (timeout++ == 100) {
|
|
- dev_err(vfe->camss->dev, "VFE idle timeout - resetting\n");
|
|
- vfe_reset(vfe);
|
|
- output->gen2.active_num = 0;
|
|
- return 0;
|
|
- }
|
|
- } while (!done);
|
|
|
|
spin_lock_irqsave(&vfe->output_lock, flags);
|
|
for (i = 0; i < output->wm_num; i++)
|
|
vfe_wm_stop(vfe, output->wm_idx[i]);
|
|
+ output->gen2.active_num = 0;
|
|
spin_unlock_irqrestore(&vfe->output_lock, flags);
|
|
|
|
- return 0;
|
|
+ vfe_reset(vfe);
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-480.c b/drivers/media/platform/qcom/camss/camss-vfe-480.c
|
|
index 1295851103931..ab42600f7a745 100644
|
|
--- a/drivers/media/platform/qcom/camss/camss-vfe-480.c
|
|
+++ b/drivers/media/platform/qcom/camss/camss-vfe-480.c
|
|
@@ -8,7 +8,6 @@
|
|
* Copyright (C) 2021 Jonathan Marek
|
|
*/
|
|
|
|
-#include <linux/delay.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/io.h>
|
|
#include <linux/iopoll.h>
|
|
@@ -311,35 +310,20 @@ static int vfe_enable_output(struct vfe_line *line)
|
|
return 0;
|
|
}
|
|
|
|
-static int vfe_disable_output(struct vfe_line *line)
|
|
+static void vfe_disable_output(struct vfe_line *line)
|
|
{
|
|
struct vfe_device *vfe = to_vfe(line);
|
|
struct vfe_output *output = &line->output;
|
|
unsigned long flags;
|
|
unsigned int i;
|
|
- bool done;
|
|
- int timeout = 0;
|
|
-
|
|
- do {
|
|
- spin_lock_irqsave(&vfe->output_lock, flags);
|
|
- done = !output->gen2.active_num;
|
|
- spin_unlock_irqrestore(&vfe->output_lock, flags);
|
|
- usleep_range(10000, 20000);
|
|
-
|
|
- if (timeout++ == 100) {
|
|
- dev_err(vfe->camss->dev, "VFE idle timeout - resetting\n");
|
|
- vfe_reset(vfe);
|
|
- output->gen2.active_num = 0;
|
|
- return 0;
|
|
- }
|
|
- } while (!done);
|
|
|
|
spin_lock_irqsave(&vfe->output_lock, flags);
|
|
for (i = 0; i < output->wm_num; i++)
|
|
vfe_wm_stop(vfe, output->wm_idx[i]);
|
|
+ output->gen2.active_num = 0;
|
|
spin_unlock_irqrestore(&vfe->output_lock, flags);
|
|
|
|
- return 0;
|
|
+ vfe_reset(vfe);
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
|
|
index d8cd9b09c20de..ee4d7dccefe16 100644
|
|
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
|
|
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
|
|
@@ -535,7 +535,8 @@ static int vfe_check_clock_rates(struct vfe_device *vfe)
|
|
struct camss_clock *clock = &vfe->clock[i];
|
|
|
|
if (!strcmp(clock->name, "vfe0") ||
|
|
- !strcmp(clock->name, "vfe1")) {
|
|
+ !strcmp(clock->name, "vfe1") ||
|
|
+ !strcmp(clock->name, "vfe_lite")) {
|
|
u64 min_rate = 0;
|
|
unsigned long rate;
|
|
|
|
@@ -611,7 +612,7 @@ int vfe_get(struct vfe_device *vfe)
|
|
} else {
|
|
ret = vfe_check_clock_rates(vfe);
|
|
if (ret < 0)
|
|
- goto error_pm_runtime_get;
|
|
+ goto error_pm_domain;
|
|
}
|
|
vfe->power_count++;
|
|
|
|
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
|
|
index a157cac72e0ab..5057b2c4cf6c4 100644
|
|
--- a/drivers/media/platform/qcom/camss/camss.c
|
|
+++ b/drivers/media/platform/qcom/camss/camss.c
|
|
@@ -1624,6 +1624,12 @@ static int camss_probe(struct platform_device *pdev)
|
|
if (ret < 0)
|
|
goto err_cleanup;
|
|
|
|
+ ret = camss_configure_pd(camss);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "Failed to configure power domains: %d\n", ret);
|
|
+ goto err_cleanup;
|
|
+ }
|
|
+
|
|
ret = camss_init_subdevices(camss);
|
|
if (ret < 0)
|
|
goto err_cleanup;
|
|
@@ -1676,12 +1682,6 @@ static int camss_probe(struct platform_device *pdev)
|
|
}
|
|
}
|
|
|
|
- ret = camss_configure_pd(camss);
|
|
- if (ret < 0) {
|
|
- dev_err(dev, "Failed to configure power domains: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
pm_runtime_enable(dev);
|
|
|
|
return 0;
|
|
diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c
|
|
index df96db3761a72..1c5cc5a5f89a6 100644
|
|
--- a/drivers/media/platform/qcom/venus/hfi_msgs.c
|
|
+++ b/drivers/media/platform/qcom/venus/hfi_msgs.c
|
|
@@ -374,7 +374,7 @@ session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt,
|
|
memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
|
|
idx++;
|
|
|
|
- if (idx > HFI_BUFFER_TYPE_MAX)
|
|
+ if (idx >= HFI_BUFFER_TYPE_MAX)
|
|
return HFI_ERR_SESSION_INVALID_PARAMETER;
|
|
|
|
req_bytes -= sizeof(struct hfi_buffer_requirements);
|
|
diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c
|
|
index 6cf74b2bc5ae3..c43839539d4dd 100644
|
|
--- a/drivers/media/platform/qcom/venus/hfi_parser.c
|
|
+++ b/drivers/media/platform/qcom/venus/hfi_parser.c
|
|
@@ -19,6 +19,9 @@ static void init_codecs(struct venus_core *core)
|
|
struct hfi_plat_caps *caps = core->caps, *cap;
|
|
unsigned long bit;
|
|
|
|
+ if (hweight_long(core->dec_codecs) + hweight_long(core->enc_codecs) > MAX_CODEC_NUM)
|
|
+ return;
|
|
+
|
|
for_each_set_bit(bit, &core->dec_codecs, MAX_CODEC_NUM) {
|
|
cap = &caps[core->codecs_count++];
|
|
cap->codec = BIT(bit);
|
|
@@ -86,6 +89,9 @@ static void fill_profile_level(struct hfi_plat_caps *cap, const void *data,
|
|
{
|
|
const struct hfi_profile_level *pl = data;
|
|
|
|
+ if (cap->num_pl + num >= HFI_MAX_PROFILE_COUNT)
|
|
+ return;
|
|
+
|
|
memcpy(&cap->pl[cap->num_pl], pl, num * sizeof(*pl));
|
|
cap->num_pl += num;
|
|
}
|
|
@@ -111,6 +117,9 @@ fill_caps(struct hfi_plat_caps *cap, const void *data, unsigned int num)
|
|
{
|
|
const struct hfi_capability *caps = data;
|
|
|
|
+ if (cap->num_caps + num >= MAX_CAP_ENTRIES)
|
|
+ return;
|
|
+
|
|
memcpy(&cap->caps[cap->num_caps], caps, num * sizeof(*caps));
|
|
cap->num_caps += num;
|
|
}
|
|
@@ -137,6 +146,9 @@ static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts,
|
|
{
|
|
const struct raw_formats *formats = fmts;
|
|
|
|
+ if (cap->num_fmts + num_fmts >= MAX_FMT_ENTRIES)
|
|
+ return;
|
|
+
|
|
memcpy(&cap->fmts[cap->num_fmts], formats, num_fmts * sizeof(*formats));
|
|
cap->num_fmts += num_fmts;
|
|
}
|
|
@@ -159,6 +171,9 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data)
|
|
rawfmts[i].buftype = fmt->buffer_type;
|
|
i++;
|
|
|
|
+ if (i >= MAX_FMT_ENTRIES)
|
|
+ return;
|
|
+
|
|
if (pinfo->num_planes > MAX_PLANES)
|
|
break;
|
|
|
|
diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
|
|
index 8fc8f46dc3908..d46938aab26b7 100644
|
|
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
|
|
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
|
|
@@ -205,6 +205,11 @@ static int venus_write_queue(struct venus_hfi_device *hdev,
|
|
|
|
new_wr_idx = wr_idx + dwords;
|
|
wr_ptr = (u32 *)(queue->qmem.kva + (wr_idx << 2));
|
|
+
|
|
+ if (wr_ptr < (u32 *)queue->qmem.kva ||
|
|
+ wr_ptr > (u32 *)(queue->qmem.kva + queue->qmem.size - sizeof(*wr_ptr)))
|
|
+ return -EINVAL;
|
|
+
|
|
if (new_wr_idx < qsize) {
|
|
memcpy(wr_ptr, packet, dwords << 2);
|
|
} else {
|
|
@@ -272,6 +277,11 @@ static int venus_read_queue(struct venus_hfi_device *hdev,
|
|
}
|
|
|
|
rd_ptr = (u32 *)(queue->qmem.kva + (rd_idx << 2));
|
|
+
|
|
+ if (rd_ptr < (u32 *)queue->qmem.kva ||
|
|
+ rd_ptr > (u32 *)(queue->qmem.kva + queue->qmem.size - sizeof(*rd_ptr)))
|
|
+ return -EINVAL;
|
|
+
|
|
dwords = *rd_ptr >> 2;
|
|
if (!dwords)
|
|
return -EINVAL;
|
|
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
|
|
index 74546f7e34691..5719dda6e0f0e 100644
|
|
--- a/drivers/media/rc/imon.c
|
|
+++ b/drivers/media/rc/imon.c
|
|
@@ -2427,6 +2427,12 @@ static int imon_probe(struct usb_interface *interface,
|
|
goto fail;
|
|
}
|
|
|
|
+ if (first_if->dev.driver != interface->dev.driver) {
|
|
+ dev_err(&interface->dev, "inconsistent driver matching\n");
|
|
+ ret = -EINVAL;
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
if (ifnum == 0) {
|
|
ictx = imon_init_intf0(interface, id);
|
|
if (!ictx) {
|
|
diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c
|
|
index 3d8488c39c561..3311099cbd573 100644
|
|
--- a/drivers/media/rc/ir-sharp-decoder.c
|
|
+++ b/drivers/media/rc/ir-sharp-decoder.c
|
|
@@ -15,7 +15,9 @@
|
|
#define SHARP_UNIT 40 /* us */
|
|
#define SHARP_BIT_PULSE (8 * SHARP_UNIT) /* 320us */
|
|
#define SHARP_BIT_0_PERIOD (25 * SHARP_UNIT) /* 1ms (680us space) */
|
|
-#define SHARP_BIT_1_PERIOD (50 * SHARP_UNIT) /* 2ms (1680ms space) */
|
|
+#define SHARP_BIT_1_PERIOD (50 * SHARP_UNIT) /* 2ms (1680us space) */
|
|
+#define SHARP_BIT_0_SPACE (17 * SHARP_UNIT) /* 680us space */
|
|
+#define SHARP_BIT_1_SPACE (42 * SHARP_UNIT) /* 1680us space */
|
|
#define SHARP_ECHO_SPACE (1000 * SHARP_UNIT) /* 40 ms */
|
|
#define SHARP_TRAILER_SPACE (125 * SHARP_UNIT) /* 5 ms (even longer) */
|
|
|
|
@@ -168,8 +170,8 @@ static const struct ir_raw_timings_pd ir_sharp_timings = {
|
|
.header_pulse = 0,
|
|
.header_space = 0,
|
|
.bit_pulse = SHARP_BIT_PULSE,
|
|
- .bit_space[0] = SHARP_BIT_0_PERIOD,
|
|
- .bit_space[1] = SHARP_BIT_1_PERIOD,
|
|
+ .bit_space[0] = SHARP_BIT_0_SPACE,
|
|
+ .bit_space[1] = SHARP_BIT_1_SPACE,
|
|
.trailer_pulse = SHARP_BIT_PULSE,
|
|
.trailer_space = SHARP_ECHO_SPACE,
|
|
.msb_first = 1,
|
|
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
|
|
index 25ab61dae126d..184e0b35744f3 100644
|
|
--- a/drivers/media/rc/lirc_dev.c
|
|
+++ b/drivers/media/rc/lirc_dev.c
|
|
@@ -276,7 +276,11 @@ static ssize_t lirc_transmit(struct file *file, const char __user *buf,
|
|
if (ret < 0)
|
|
goto out_kfree_raw;
|
|
|
|
- count = ret;
|
|
+ /* drop trailing space */
|
|
+ if (!(ret % 2))
|
|
+ count = ret - 1;
|
|
+ else
|
|
+ count = ret;
|
|
|
|
txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL);
|
|
if (!txbuf) {
|
|
diff --git a/drivers/media/test-drivers/vivid/vivid-rds-gen.c b/drivers/media/test-drivers/vivid/vivid-rds-gen.c
|
|
index b5b104ee64c99..c57771119a34b 100644
|
|
--- a/drivers/media/test-drivers/vivid/vivid-rds-gen.c
|
|
+++ b/drivers/media/test-drivers/vivid/vivid-rds-gen.c
|
|
@@ -145,7 +145,7 @@ void vivid_rds_gen_fill(struct vivid_rds_gen *rds, unsigned freq,
|
|
rds->ta = alt;
|
|
rds->ms = true;
|
|
snprintf(rds->psname, sizeof(rds->psname), "%6d.%1d",
|
|
- freq / 16, ((freq & 0xf) * 10) / 16);
|
|
+ (freq / 16) % 1000000, (((freq & 0xf) * 10) / 16) % 10);
|
|
if (alt)
|
|
strscpy(rds->radiotext,
|
|
" The Radio Data System can switch between different Radio Texts ",
|
|
diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
|
|
index 46ed95483e222..5f5fa851ca640 100644
|
|
--- a/drivers/media/usb/gspca/cpia1.c
|
|
+++ b/drivers/media/usb/gspca/cpia1.c
|
|
@@ -18,6 +18,7 @@
|
|
|
|
#include <linux/input.h>
|
|
#include <linux/sched/signal.h>
|
|
+#include <linux/bitops.h>
|
|
|
|
#include "gspca.h"
|
|
|
|
@@ -1028,6 +1029,8 @@ static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
|
|
sd->params.exposure.expMode = 2;
|
|
sd->exposure_status = EXPOSURE_NORMAL;
|
|
}
|
|
+ if (sd->params.exposure.gain >= BITS_PER_TYPE(currentexp))
|
|
+ return -EINVAL;
|
|
currentexp = currentexp << sd->params.exposure.gain;
|
|
sd->params.exposure.gain = 0;
|
|
/* round down current exposure to nearest value */
|
|
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
|
|
index 699f44ffff0e4..ae5759200622c 100644
|
|
--- a/drivers/mfd/intel-lpss-pci.c
|
|
+++ b/drivers/mfd/intel-lpss-pci.c
|
|
@@ -561,6 +561,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
|
|
{ PCI_VDEVICE(INTEL, 0xa3e2), (kernel_ulong_t)&spt_i2c_info },
|
|
{ PCI_VDEVICE(INTEL, 0xa3e3), (kernel_ulong_t)&spt_i2c_info },
|
|
{ PCI_VDEVICE(INTEL, 0xa3e6), (kernel_ulong_t)&spt_uart_info },
|
|
+ /* LNL-M */
|
|
+ { PCI_VDEVICE(INTEL, 0xa825), (kernel_ulong_t)&bxt_uart_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa826), (kernel_ulong_t)&bxt_uart_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa827), (kernel_ulong_t)&tgl_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa830), (kernel_ulong_t)&tgl_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa846), (kernel_ulong_t)&tgl_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa850), (kernel_ulong_t)&ehl_i2c_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa851), (kernel_ulong_t)&ehl_i2c_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa852), (kernel_ulong_t)&bxt_uart_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa878), (kernel_ulong_t)&ehl_i2c_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa879), (kernel_ulong_t)&ehl_i2c_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa87a), (kernel_ulong_t)&ehl_i2c_info },
|
|
+ { PCI_VDEVICE(INTEL, 0xa87b), (kernel_ulong_t)&ehl_i2c_info },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids);
|
|
diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c
|
|
index 7e2cd79d17ebf..8e449cff5cec4 100644
|
|
--- a/drivers/mfd/qcom-spmi-pmic.c
|
|
+++ b/drivers/mfd/qcom-spmi-pmic.c
|
|
@@ -30,6 +30,8 @@ struct qcom_spmi_dev {
|
|
struct qcom_spmi_pmic pmic;
|
|
};
|
|
|
|
+static DEFINE_MUTEX(pmic_spmi_revid_lock);
|
|
+
|
|
#define N_USIDS(n) ((void *)n)
|
|
|
|
static const struct of_device_id pmic_spmi_id_table[] = {
|
|
@@ -76,24 +78,21 @@ static const struct of_device_id pmic_spmi_id_table[] = {
|
|
*
|
|
* This only supports PMICs with 1 or 2 USIDs.
|
|
*/
|
|
-static struct spmi_device *qcom_pmic_get_base_usid(struct device *dev)
|
|
+static struct spmi_device *qcom_pmic_get_base_usid(struct spmi_device *sdev, struct qcom_spmi_dev *ctx)
|
|
{
|
|
- struct spmi_device *sdev;
|
|
- struct qcom_spmi_dev *ctx;
|
|
struct device_node *spmi_bus;
|
|
- struct device_node *other_usid = NULL;
|
|
+ struct device_node *child;
|
|
int function_parent_usid, ret;
|
|
u32 pmic_addr;
|
|
|
|
- sdev = to_spmi_device(dev);
|
|
- ctx = dev_get_drvdata(&sdev->dev);
|
|
-
|
|
/*
|
|
* Quick return if the function device is already in the base
|
|
* USID. This will always be hit for PMICs with only 1 USID.
|
|
*/
|
|
- if (sdev->usid % ctx->num_usids == 0)
|
|
+ if (sdev->usid % ctx->num_usids == 0) {
|
|
+ get_device(&sdev->dev);
|
|
return sdev;
|
|
+ }
|
|
|
|
function_parent_usid = sdev->usid;
|
|
|
|
@@ -105,28 +104,61 @@ static struct spmi_device *qcom_pmic_get_base_usid(struct device *dev)
|
|
* device for USID 2.
|
|
*/
|
|
spmi_bus = of_get_parent(sdev->dev.of_node);
|
|
- do {
|
|
- other_usid = of_get_next_child(spmi_bus, other_usid);
|
|
-
|
|
- ret = of_property_read_u32_index(other_usid, "reg", 0, &pmic_addr);
|
|
- if (ret)
|
|
- return ERR_PTR(ret);
|
|
+ sdev = ERR_PTR(-ENODATA);
|
|
+ for_each_child_of_node(spmi_bus, child) {
|
|
+ ret = of_property_read_u32_index(child, "reg", 0, &pmic_addr);
|
|
+ if (ret) {
|
|
+ of_node_put(child);
|
|
+ sdev = ERR_PTR(ret);
|
|
+ break;
|
|
+ }
|
|
|
|
- sdev = spmi_device_from_of(other_usid);
|
|
if (pmic_addr == function_parent_usid - (ctx->num_usids - 1)) {
|
|
- if (!sdev)
|
|
+ sdev = spmi_device_from_of(child);
|
|
+ if (!sdev) {
|
|
/*
|
|
- * If the base USID for this PMIC hasn't probed yet
|
|
- * but the secondary USID has, then we need to defer
|
|
- * the function driver so that it will attempt to
|
|
- * probe again when the base USID is ready.
|
|
+ * If the base USID for this PMIC hasn't been
|
|
+ * registered yet then we need to defer.
|
|
*/
|
|
- return ERR_PTR(-EPROBE_DEFER);
|
|
- return sdev;
|
|
+ sdev = ERR_PTR(-EPROBE_DEFER);
|
|
+ }
|
|
+ of_node_put(child);
|
|
+ break;
|
|
}
|
|
- } while (other_usid->sibling);
|
|
+ }
|
|
|
|
- return ERR_PTR(-ENODATA);
|
|
+ of_node_put(spmi_bus);
|
|
+
|
|
+ return sdev;
|
|
+}
|
|
+
|
|
+static int pmic_spmi_get_base_revid(struct spmi_device *sdev, struct qcom_spmi_dev *ctx)
|
|
+{
|
|
+ struct qcom_spmi_dev *base_ctx;
|
|
+ struct spmi_device *base;
|
|
+ int ret = 0;
|
|
+
|
|
+ base = qcom_pmic_get_base_usid(sdev, ctx);
|
|
+ if (IS_ERR(base))
|
|
+ return PTR_ERR(base);
|
|
+
|
|
+ /*
|
|
+ * Copy revid info from base device if it has probed and is still
|
|
+ * bound to its driver.
|
|
+ */
|
|
+ mutex_lock(&pmic_spmi_revid_lock);
|
|
+ base_ctx = spmi_device_get_drvdata(base);
|
|
+ if (!base_ctx) {
|
|
+ ret = -EPROBE_DEFER;
|
|
+ goto out_unlock;
|
|
+ }
|
|
+ memcpy(&ctx->pmic, &base_ctx->pmic, sizeof(ctx->pmic));
|
|
+out_unlock:
|
|
+ mutex_unlock(&pmic_spmi_revid_lock);
|
|
+
|
|
+ put_device(&base->dev);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int pmic_spmi_load_revid(struct regmap *map, struct device *dev,
|
|
@@ -204,11 +236,7 @@ const struct qcom_spmi_pmic *qcom_pmic_get(struct device *dev)
|
|
if (!of_match_device(pmic_spmi_id_table, dev->parent))
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
- sdev = qcom_pmic_get_base_usid(dev->parent);
|
|
-
|
|
- if (IS_ERR(sdev))
|
|
- return ERR_CAST(sdev);
|
|
-
|
|
+ sdev = to_spmi_device(dev->parent);
|
|
spmi = dev_get_drvdata(&sdev->dev);
|
|
|
|
return &spmi->pmic;
|
|
@@ -243,16 +271,31 @@ static int pmic_spmi_probe(struct spmi_device *sdev)
|
|
ret = pmic_spmi_load_revid(regmap, &sdev->dev, &ctx->pmic);
|
|
if (ret < 0)
|
|
return ret;
|
|
+ } else {
|
|
+ ret = pmic_spmi_get_base_revid(sdev, ctx);
|
|
+ if (ret)
|
|
+ return ret;
|
|
}
|
|
+
|
|
+ mutex_lock(&pmic_spmi_revid_lock);
|
|
spmi_device_set_drvdata(sdev, ctx);
|
|
+ mutex_unlock(&pmic_spmi_revid_lock);
|
|
|
|
return devm_of_platform_populate(&sdev->dev);
|
|
}
|
|
|
|
+static void pmic_spmi_remove(struct spmi_device *sdev)
|
|
+{
|
|
+ mutex_lock(&pmic_spmi_revid_lock);
|
|
+ spmi_device_set_drvdata(sdev, NULL);
|
|
+ mutex_unlock(&pmic_spmi_revid_lock);
|
|
+}
|
|
+
|
|
MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
|
|
|
|
static struct spmi_driver pmic_spmi_driver = {
|
|
.probe = pmic_spmi_probe,
|
|
+ .remove = pmic_spmi_remove,
|
|
.driver = {
|
|
.name = "pmic-spmi",
|
|
.of_match_table = pmic_spmi_id_table,
|
|
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
|
|
index 55dc16d8f6adb..18059a12d4e18 100644
|
|
--- a/drivers/misc/pci_endpoint_test.c
|
|
+++ b/drivers/misc/pci_endpoint_test.c
|
|
@@ -81,6 +81,7 @@
|
|
#define PCI_DEVICE_ID_RENESAS_R8A774B1 0x002b
|
|
#define PCI_DEVICE_ID_RENESAS_R8A774C0 0x002d
|
|
#define PCI_DEVICE_ID_RENESAS_R8A774E1 0x0025
|
|
+#define PCI_DEVICE_ID_RENESAS_R8A779F0 0x0031
|
|
|
|
static DEFINE_IDA(pci_endpoint_test_ida);
|
|
|
|
@@ -996,6 +997,9 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774B1),},
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774C0),},
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A774E1),},
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_R8A779F0),
|
|
+ .driver_data = (kernel_ulong_t)&default_data,
|
|
+ },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_J721E),
|
|
.driver_data = (kernel_ulong_t)&j721e_data,
|
|
},
|
|
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
|
|
index 1fc6767f18782..67a7ae9b997aa 100644
|
|
--- a/drivers/mmc/core/block.c
|
|
+++ b/drivers/mmc/core/block.c
|
|
@@ -2404,8 +2404,10 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req)
|
|
}
|
|
ret = mmc_blk_cqe_issue_flush(mq, req);
|
|
break;
|
|
- case REQ_OP_READ:
|
|
case REQ_OP_WRITE:
|
|
+ card->written_flag = true;
|
|
+ fallthrough;
|
|
+ case REQ_OP_READ:
|
|
if (host->cqe_enabled)
|
|
ret = mmc_blk_cqe_issue_rw_rq(mq, req);
|
|
else
|
|
diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
|
|
index 4edf9057fa79d..b7754a1b8d978 100644
|
|
--- a/drivers/mmc/core/card.h
|
|
+++ b/drivers/mmc/core/card.h
|
|
@@ -280,4 +280,8 @@ static inline int mmc_card_broken_sd_cache(const struct mmc_card *c)
|
|
return c->quirks & MMC_QUIRK_BROKEN_SD_CACHE;
|
|
}
|
|
|
|
+static inline int mmc_card_broken_cache_flush(const struct mmc_card *c)
|
|
+{
|
|
+ return c->quirks & MMC_QUIRK_BROKEN_CACHE_FLUSH;
|
|
+}
|
|
#endif
|
|
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
|
|
index 89cd48fcec79f..a46ce0868fe1f 100644
|
|
--- a/drivers/mmc/core/mmc.c
|
|
+++ b/drivers/mmc/core/mmc.c
|
|
@@ -2081,13 +2081,17 @@ static int _mmc_flush_cache(struct mmc_host *host)
|
|
{
|
|
int err = 0;
|
|
|
|
+ if (mmc_card_broken_cache_flush(host->card) && !host->card->written_flag)
|
|
+ return 0;
|
|
+
|
|
if (_mmc_cache_enabled(host)) {
|
|
err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL,
|
|
EXT_CSD_FLUSH_CACHE, 1,
|
|
CACHE_FLUSH_TIMEOUT_MS);
|
|
if (err)
|
|
- pr_err("%s: cache flush error %d\n",
|
|
- mmc_hostname(host), err);
|
|
+ pr_err("%s: cache flush error %d\n", mmc_hostname(host), err);
|
|
+ else
|
|
+ host->card->written_flag = false;
|
|
}
|
|
|
|
return err;
|
|
diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
|
|
index 857315f185fcf..ec760ac0b3977 100644
|
|
--- a/drivers/mmc/core/quirks.h
|
|
+++ b/drivers/mmc/core/quirks.h
|
|
@@ -117,11 +117,12 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
|
|
MMC_QUIRK_TRIM_BROKEN),
|
|
|
|
/*
|
|
- * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to
|
|
- * support being used to offload WRITE_ZEROES.
|
|
+ * Micron MTFC4GACAJCN-1M supports TRIM but does not appear to support
|
|
+ * WRITE_ZEROES offloading. It also supports caching, but the cache can
|
|
+ * only be flushed after a write has occurred.
|
|
*/
|
|
MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc,
|
|
- MMC_QUIRK_TRIM_BROKEN),
|
|
+ MMC_QUIRK_TRIM_BROKEN | MMC_QUIRK_BROKEN_CACHE_FLUSH),
|
|
|
|
/*
|
|
* Some SD cards reports discard support while they don't
|
|
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
|
|
index 0f39f86bd0c26..7e571cc719605 100644
|
|
--- a/drivers/mmc/host/meson-gx-mmc.c
|
|
+++ b/drivers/mmc/host/meson-gx-mmc.c
|
|
@@ -817,7 +817,6 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
|
|
|
|
cmd_cfg |= FIELD_PREP(CMD_CFG_CMD_INDEX_MASK, cmd->opcode);
|
|
cmd_cfg |= CMD_CFG_OWNER; /* owned by CPU */
|
|
- cmd_cfg |= CMD_CFG_ERROR; /* stop in case of error */
|
|
|
|
meson_mmc_set_response_bits(cmd, &cmd_cfg);
|
|
|
|
diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
|
|
index c580ba089a261..33d7039c19169 100644
|
|
--- a/drivers/mmc/host/sdhci-pci-gli.c
|
|
+++ b/drivers/mmc/host/sdhci-pci-gli.c
|
|
@@ -24,6 +24,12 @@
|
|
#define GLI_9750_WT_EN_ON 0x1
|
|
#define GLI_9750_WT_EN_OFF 0x0
|
|
|
|
+#define PCI_GLI_9750_PM_CTRL 0xFC
|
|
+#define PCI_GLI_9750_PM_STATE GENMASK(1, 0)
|
|
+
|
|
+#define PCI_GLI_9750_CORRERR_MASK 0x214
|
|
+#define PCI_GLI_9750_CORRERR_MASK_REPLAY_TIMER_TIMEOUT BIT(12)
|
|
+
|
|
#define SDHCI_GLI_9750_CFG2 0x848
|
|
#define SDHCI_GLI_9750_CFG2_L1DLY GENMASK(28, 24)
|
|
#define GLI_9750_CFG2_L1DLY_VALUE 0x1F
|
|
@@ -148,6 +154,9 @@
|
|
#define PCI_GLI_9755_PM_CTRL 0xFC
|
|
#define PCI_GLI_9755_PM_STATE GENMASK(1, 0)
|
|
|
|
+#define PCI_GLI_9755_CORRERR_MASK 0x214
|
|
+#define PCI_GLI_9755_CORRERR_MASK_REPLAY_TIMER_TIMEOUT BIT(12)
|
|
+
|
|
#define GLI_MAX_TUNING_LOOP 40
|
|
|
|
/* Genesys Logic chipset */
|
|
@@ -469,8 +478,12 @@ static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock)
|
|
|
|
static void gl9750_hw_setting(struct sdhci_host *host)
|
|
{
|
|
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
|
|
+ struct pci_dev *pdev;
|
|
u32 value;
|
|
|
|
+ pdev = slot->chip->pdev;
|
|
+
|
|
gl9750_wt_on(host);
|
|
|
|
value = sdhci_readl(host, SDHCI_GLI_9750_CFG2);
|
|
@@ -480,6 +493,18 @@ static void gl9750_hw_setting(struct sdhci_host *host)
|
|
GLI_9750_CFG2_L1DLY_VALUE);
|
|
sdhci_writel(host, value, SDHCI_GLI_9750_CFG2);
|
|
|
|
+ /* toggle PM state to allow GL9750 to enter ASPM L1.2 */
|
|
+ pci_read_config_dword(pdev, PCI_GLI_9750_PM_CTRL, &value);
|
|
+ value |= PCI_GLI_9750_PM_STATE;
|
|
+ pci_write_config_dword(pdev, PCI_GLI_9750_PM_CTRL, value);
|
|
+ value &= ~PCI_GLI_9750_PM_STATE;
|
|
+ pci_write_config_dword(pdev, PCI_GLI_9750_PM_CTRL, value);
|
|
+
|
|
+ /* mask the replay timer timeout of AER */
|
|
+ pci_read_config_dword(pdev, PCI_GLI_9750_CORRERR_MASK, &value);
|
|
+ value |= PCI_GLI_9750_CORRERR_MASK_REPLAY_TIMER_TIMEOUT;
|
|
+ pci_write_config_dword(pdev, PCI_GLI_9750_CORRERR_MASK, value);
|
|
+
|
|
gl9750_wt_off(host);
|
|
}
|
|
|
|
@@ -689,6 +714,11 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
|
|
value &= ~PCI_GLI_9755_PM_STATE;
|
|
pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value);
|
|
|
|
+ /* mask the replay timer timeout of AER */
|
|
+ pci_read_config_dword(pdev, PCI_GLI_9755_CORRERR_MASK, &value);
|
|
+ value |= PCI_GLI_9755_CORRERR_MASK_REPLAY_TIMER_TIMEOUT;
|
|
+ pci_write_config_dword(pdev, PCI_GLI_9755_CORRERR_MASK, value);
|
|
+
|
|
gl9755_wt_off(pdev);
|
|
}
|
|
|
|
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
|
|
index 8e22b375247ef..c16dbe64859e6 100644
|
|
--- a/drivers/mmc/host/sdhci_am654.c
|
|
+++ b/drivers/mmc/host/sdhci_am654.c
|
|
@@ -597,7 +597,7 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host,
|
|
return 0;
|
|
}
|
|
|
|
- for (i = MMC_TIMING_MMC_HS; i <= MMC_TIMING_MMC_HS400; i++) {
|
|
+ for (i = MMC_TIMING_LEGACY; i <= MMC_TIMING_MMC_HS400; i++) {
|
|
|
|
ret = device_property_read_u32(dev, td[i].otap_binding,
|
|
&sdhci_am654->otap_del_sel[i]);
|
|
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
|
|
index 7dc0e91dabfc7..05ffd5bf5a6f0 100644
|
|
--- a/drivers/mmc/host/vub300.c
|
|
+++ b/drivers/mmc/host/vub300.c
|
|
@@ -2311,6 +2311,7 @@ static int vub300_probe(struct usb_interface *interface,
|
|
vub300->read_only =
|
|
(0x0010 & vub300->system_port_status.port_flags) ? 1 : 0;
|
|
} else {
|
|
+ retval = -EINVAL;
|
|
goto error5;
|
|
}
|
|
usb_set_intfdata(interface, vub300);
|
|
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
|
|
index 54f92d09d9cf4..02aaf09d6f5cd 100644
|
|
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
|
|
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
|
|
@@ -421,9 +421,25 @@ read_pri_intelext(struct map_info *map, __u16 adr)
|
|
extra_size = 0;
|
|
|
|
/* Protection Register info */
|
|
- if (extp->NumProtectionFields)
|
|
+ if (extp->NumProtectionFields) {
|
|
+ struct cfi_intelext_otpinfo *otp =
|
|
+ (struct cfi_intelext_otpinfo *)&extp->extra[0];
|
|
+
|
|
extra_size += (extp->NumProtectionFields - 1) *
|
|
- sizeof(struct cfi_intelext_otpinfo);
|
|
+ sizeof(struct cfi_intelext_otpinfo);
|
|
+
|
|
+ if (extp_size >= sizeof(*extp) + extra_size) {
|
|
+ int i;
|
|
+
|
|
+ /* Do some byteswapping if necessary */
|
|
+ for (i = 0; i < extp->NumProtectionFields - 1; i++) {
|
|
+ otp->ProtRegAddr = le32_to_cpu(otp->ProtRegAddr);
|
|
+ otp->FactGroups = le16_to_cpu(otp->FactGroups);
|
|
+ otp->UserGroups = le16_to_cpu(otp->UserGroups);
|
|
+ otp++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
if (extp->MinorVersion >= '1') {
|
|
diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c
|
|
index 6f4cea81f97c0..1f8a33fb84607 100644
|
|
--- a/drivers/mtd/nand/raw/intel-nand-controller.c
|
|
+++ b/drivers/mtd/nand/raw/intel-nand-controller.c
|
|
@@ -619,6 +619,11 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
|
ebu_host->cs_num = cs;
|
|
|
|
resname = devm_kasprintf(dev, GFP_KERNEL, "nand_cs%d", cs);
|
|
+ if (!resname) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_of_node_put;
|
|
+ }
|
|
+
|
|
ebu_host->cs[cs].chipaddr = devm_platform_ioremap_resource_byname(pdev,
|
|
resname);
|
|
if (IS_ERR(ebu_host->cs[cs].chipaddr)) {
|
|
@@ -655,6 +660,11 @@ static int ebu_nand_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
resname = devm_kasprintf(dev, GFP_KERNEL, "addr_sel%d", cs);
|
|
+ if (!resname) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_cleanup_dma;
|
|
+ }
|
|
+
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resname);
|
|
if (!res) {
|
|
ret = -EINVAL;
|
|
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
|
|
index ac4947f720478..0aeac8ccbd0ee 100644
|
|
--- a/drivers/mtd/nand/raw/meson_nand.c
|
|
+++ b/drivers/mtd/nand/raw/meson_nand.c
|
|
@@ -1021,6 +1021,9 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
|
|
init.name = devm_kasprintf(nfc->dev,
|
|
GFP_KERNEL, "%s#div",
|
|
dev_name(nfc->dev));
|
|
+ if (!init.name)
|
|
+ return -ENOMEM;
|
|
+
|
|
init.ops = &clk_divider_ops;
|
|
nfc_divider_parent_data[0].fw_name = "device";
|
|
init.parent_data = nfc_divider_parent_data;
|
|
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c
|
|
index a9b9031ce6167..d33030b68ac44 100644
|
|
--- a/drivers/mtd/nand/raw/tegra_nand.c
|
|
+++ b/drivers/mtd/nand/raw/tegra_nand.c
|
|
@@ -1197,6 +1197,10 @@ static int tegra_nand_probe(struct platform_device *pdev)
|
|
init_completion(&ctrl->dma_complete);
|
|
|
|
ctrl->irq = platform_get_irq(pdev, 0);
|
|
+ if (ctrl->irq < 0) {
|
|
+ err = ctrl->irq;
|
|
+ goto err_put_pm;
|
|
+ }
|
|
err = devm_request_irq(&pdev->dev, ctrl->irq, tegra_nand_irq, 0,
|
|
dev_name(&pdev->dev), ctrl);
|
|
if (err) {
|
|
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
|
|
index b170a3d8d007e..710734a5af9bf 100644
|
|
--- a/drivers/net/bonding/bond_main.c
|
|
+++ b/drivers/net/bonding/bond_main.c
|
|
@@ -1503,6 +1503,10 @@ done:
|
|
static void bond_setup_by_slave(struct net_device *bond_dev,
|
|
struct net_device *slave_dev)
|
|
{
|
|
+ bool was_up = !!(bond_dev->flags & IFF_UP);
|
|
+
|
|
+ dev_close(bond_dev);
|
|
+
|
|
bond_dev->header_ops = slave_dev->header_ops;
|
|
|
|
bond_dev->type = slave_dev->type;
|
|
@@ -1517,6 +1521,8 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
|
|
bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
|
|
bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
|
|
}
|
|
+ if (was_up)
|
|
+ dev_open(bond_dev, NULL);
|
|
}
|
|
|
|
/* On bonding slaves other than the currently active slave, suppress
|
|
diff --git a/drivers/net/dsa/lan9303_mdio.c b/drivers/net/dsa/lan9303_mdio.c
|
|
index 4f33369a2de52..47484f55e2aba 100644
|
|
--- a/drivers/net/dsa/lan9303_mdio.c
|
|
+++ b/drivers/net/dsa/lan9303_mdio.c
|
|
@@ -32,7 +32,7 @@ static int lan9303_mdio_write(void *ctx, uint32_t reg, uint32_t val)
|
|
struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
|
|
|
|
reg <<= 2; /* reg num to offset */
|
|
- mutex_lock(&sw_dev->device->bus->mdio_lock);
|
|
+ mutex_lock_nested(&sw_dev->device->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
|
lan9303_mdio_real_write(sw_dev->device, reg, val & 0xffff);
|
|
lan9303_mdio_real_write(sw_dev->device, reg + 2, (val >> 16) & 0xffff);
|
|
mutex_unlock(&sw_dev->device->bus->mdio_lock);
|
|
@@ -50,7 +50,7 @@ static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val)
|
|
struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
|
|
|
|
reg <<= 2; /* reg num to offset */
|
|
- mutex_lock(&sw_dev->device->bus->mdio_lock);
|
|
+ mutex_lock_nested(&sw_dev->device->bus->mdio_lock, MDIO_MUTEX_NESTED);
|
|
*val = lan9303_mdio_real_read(sw_dev->device, reg);
|
|
*val |= (lan9303_mdio_real_read(sw_dev->device, reg + 2) << 16);
|
|
mutex_unlock(&sw_dev->device->bus->mdio_lock);
|
|
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
|
|
index 43d821fe7a542..63ba64dbb7310 100644
|
|
--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
|
|
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
|
|
@@ -504,15 +504,12 @@ struct atl1c_rrd_ring {
|
|
u16 next_to_use;
|
|
u16 next_to_clean;
|
|
struct napi_struct napi;
|
|
- struct page *rx_page;
|
|
- unsigned int rx_page_offset;
|
|
};
|
|
|
|
/* board specific private data structure */
|
|
struct atl1c_adapter {
|
|
struct net_device *netdev;
|
|
struct pci_dev *pdev;
|
|
- unsigned int rx_frag_size;
|
|
struct atl1c_hw hw;
|
|
struct atl1c_hw_stats hw_stats;
|
|
struct mii_if_info mii; /* MII interface info */
|
|
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
|
index 7762e532c6a4f..6eb86d75955fe 100644
|
|
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
|
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
|
|
@@ -493,15 +493,10 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
|
|
static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
|
|
struct net_device *dev)
|
|
{
|
|
- unsigned int head_size;
|
|
int mtu = dev->mtu;
|
|
|
|
adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ?
|
|
roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE;
|
|
-
|
|
- head_size = SKB_DATA_ALIGN(adapter->rx_buffer_len + NET_SKB_PAD + NET_IP_ALIGN) +
|
|
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
|
- adapter->rx_frag_size = roundup_pow_of_two(head_size);
|
|
}
|
|
|
|
static netdev_features_t atl1c_fix_features(struct net_device *netdev,
|
|
@@ -974,7 +969,6 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
|
|
static void atl1c_free_ring_resources(struct atl1c_adapter *adapter)
|
|
{
|
|
struct pci_dev *pdev = adapter->pdev;
|
|
- int i;
|
|
|
|
dma_free_coherent(&pdev->dev, adapter->ring_header.size,
|
|
adapter->ring_header.desc, adapter->ring_header.dma);
|
|
@@ -987,12 +981,6 @@ static void atl1c_free_ring_resources(struct atl1c_adapter *adapter)
|
|
kfree(adapter->tpd_ring[0].buffer_info);
|
|
adapter->tpd_ring[0].buffer_info = NULL;
|
|
}
|
|
- for (i = 0; i < adapter->rx_queue_count; ++i) {
|
|
- if (adapter->rrd_ring[i].rx_page) {
|
|
- put_page(adapter->rrd_ring[i].rx_page);
|
|
- adapter->rrd_ring[i].rx_page = NULL;
|
|
- }
|
|
- }
|
|
}
|
|
|
|
/**
|
|
@@ -1764,48 +1752,11 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
|
|
skb_checksum_none_assert(skb);
|
|
}
|
|
|
|
-static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter,
|
|
- u32 queue, bool napi_mode)
|
|
-{
|
|
- struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[queue];
|
|
- struct sk_buff *skb;
|
|
- struct page *page;
|
|
-
|
|
- if (adapter->rx_frag_size > PAGE_SIZE) {
|
|
- if (likely(napi_mode))
|
|
- return napi_alloc_skb(&rrd_ring->napi,
|
|
- adapter->rx_buffer_len);
|
|
- else
|
|
- return netdev_alloc_skb_ip_align(adapter->netdev,
|
|
- adapter->rx_buffer_len);
|
|
- }
|
|
-
|
|
- page = rrd_ring->rx_page;
|
|
- if (!page) {
|
|
- page = alloc_page(GFP_ATOMIC);
|
|
- if (unlikely(!page))
|
|
- return NULL;
|
|
- rrd_ring->rx_page = page;
|
|
- rrd_ring->rx_page_offset = 0;
|
|
- }
|
|
-
|
|
- skb = build_skb(page_address(page) + rrd_ring->rx_page_offset,
|
|
- adapter->rx_frag_size);
|
|
- if (likely(skb)) {
|
|
- skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
|
|
- rrd_ring->rx_page_offset += adapter->rx_frag_size;
|
|
- if (rrd_ring->rx_page_offset >= PAGE_SIZE)
|
|
- rrd_ring->rx_page = NULL;
|
|
- else
|
|
- get_page(page);
|
|
- }
|
|
- return skb;
|
|
-}
|
|
-
|
|
static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, u32 queue,
|
|
bool napi_mode)
|
|
{
|
|
struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[queue];
|
|
+ struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[queue];
|
|
struct pci_dev *pdev = adapter->pdev;
|
|
struct atl1c_buffer *buffer_info, *next_info;
|
|
struct sk_buff *skb;
|
|
@@ -1824,13 +1775,27 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, u32 queue,
|
|
while (next_info->flags & ATL1C_BUFFER_FREE) {
|
|
rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use);
|
|
|
|
- skb = atl1c_alloc_skb(adapter, queue, napi_mode);
|
|
+ /* When DMA RX address is set to something like
|
|
+ * 0x....fc0, it will be very likely to cause DMA
|
|
+ * RFD overflow issue.
|
|
+ *
|
|
+ * To work around it, we apply rx skb with 64 bytes
|
|
+ * longer space, and offset the address whenever
|
|
+ * 0x....fc0 is detected.
|
|
+ */
|
|
+ if (likely(napi_mode))
|
|
+ skb = napi_alloc_skb(&rrd_ring->napi, adapter->rx_buffer_len + 64);
|
|
+ else
|
|
+ skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len + 64);
|
|
if (unlikely(!skb)) {
|
|
if (netif_msg_rx_err(adapter))
|
|
dev_warn(&pdev->dev, "alloc rx buffer failed\n");
|
|
break;
|
|
}
|
|
|
|
+ if (((unsigned long)skb->data & 0xfff) == 0xfc0)
|
|
+ skb_reserve(skb, 64);
|
|
+
|
|
/*
|
|
* Make buffer alignment 2 beyond a 16 byte boundary
|
|
* this will result in a 16 byte aligned IP header after
|
|
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
|
|
index fdf10318758b4..7c0b0bc033c9c 100644
|
|
--- a/drivers/net/ethernet/cortina/gemini.c
|
|
+++ b/drivers/net/ethernet/cortina/gemini.c
|
|
@@ -432,8 +432,8 @@ static const struct gmac_max_framelen gmac_maxlens[] = {
|
|
.val = CONFIG0_MAXLEN_1536,
|
|
},
|
|
{
|
|
- .max_l3_len = 1542,
|
|
- .val = CONFIG0_MAXLEN_1542,
|
|
+ .max_l3_len = 1548,
|
|
+ .val = CONFIG0_MAXLEN_1548,
|
|
},
|
|
{
|
|
.max_l3_len = 9212,
|
|
@@ -1145,6 +1145,7 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb,
|
|
dma_addr_t mapping;
|
|
unsigned short mtu;
|
|
void *buffer;
|
|
+ int ret;
|
|
|
|
mtu = ETH_HLEN;
|
|
mtu += netdev->mtu;
|
|
@@ -1159,9 +1160,30 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb,
|
|
word3 |= mtu;
|
|
}
|
|
|
|
- if (skb->ip_summed != CHECKSUM_NONE) {
|
|
+ if (skb->len >= ETH_FRAME_LEN) {
|
|
+ /* Hardware offloaded checksumming isn't working on frames
|
|
+ * bigger than 1514 bytes. A hypothesis about this is that the
|
|
+ * checksum buffer is only 1518 bytes, so when the frames get
|
|
+ * bigger they get truncated, or the last few bytes get
|
|
+ * overwritten by the FCS.
|
|
+ *
|
|
+ * Just use software checksumming and bypass on bigger frames.
|
|
+ */
|
|
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
+ ret = skb_checksum_help(skb);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+ word1 |= TSS_BYPASS_BIT;
|
|
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
int tcp = 0;
|
|
|
|
+ /* We do not switch off the checksumming on non TCP/UDP
|
|
+ * frames: as is shown from tests, the checksumming engine
|
|
+ * is smart enough to see that a frame is not actually TCP
|
|
+ * or UDP and then just pass it through without any changes
|
|
+ * to the frame.
|
|
+ */
|
|
if (skb->protocol == htons(ETH_P_IP)) {
|
|
word1 |= TSS_IP_CHKSUM_BIT;
|
|
tcp = ip_hdr(skb)->protocol == IPPROTO_TCP;
|
|
@@ -1978,15 +2000,6 @@ static int gmac_change_mtu(struct net_device *netdev, int new_mtu)
|
|
return 0;
|
|
}
|
|
|
|
-static netdev_features_t gmac_fix_features(struct net_device *netdev,
|
|
- netdev_features_t features)
|
|
-{
|
|
- if (netdev->mtu + ETH_HLEN + VLAN_HLEN > MTU_SIZE_BIT_MASK)
|
|
- features &= ~GMAC_OFFLOAD_FEATURES;
|
|
-
|
|
- return features;
|
|
-}
|
|
-
|
|
static int gmac_set_features(struct net_device *netdev,
|
|
netdev_features_t features)
|
|
{
|
|
@@ -2212,7 +2225,6 @@ static const struct net_device_ops gmac_351x_ops = {
|
|
.ndo_set_mac_address = gmac_set_mac_address,
|
|
.ndo_get_stats64 = gmac_get_stats64,
|
|
.ndo_change_mtu = gmac_change_mtu,
|
|
- .ndo_fix_features = gmac_fix_features,
|
|
.ndo_set_features = gmac_set_features,
|
|
};
|
|
|
|
@@ -2464,11 +2476,12 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev)
|
|
|
|
netdev->hw_features = GMAC_OFFLOAD_FEATURES;
|
|
netdev->features |= GMAC_OFFLOAD_FEATURES | NETIF_F_GRO;
|
|
- /* We can handle jumbo frames up to 10236 bytes so, let's accept
|
|
- * payloads of 10236 bytes minus VLAN and ethernet header
|
|
+ /* We can receive jumbo frames up to 10236 bytes but only
|
|
+ * transmit 2047 bytes so, let's accept payloads of 2047
|
|
+ * bytes minus VLAN and ethernet header
|
|
*/
|
|
netdev->min_mtu = ETH_MIN_MTU;
|
|
- netdev->max_mtu = 10236 - VLAN_ETH_HLEN;
|
|
+ netdev->max_mtu = MTU_SIZE_BIT_MASK - VLAN_ETH_HLEN;
|
|
|
|
port->freeq_refill = 0;
|
|
netif_napi_add(netdev, &port->napi, gmac_napi_poll);
|
|
diff --git a/drivers/net/ethernet/cortina/gemini.h b/drivers/net/ethernet/cortina/gemini.h
|
|
index 9fdf77d5eb374..24bb989981f23 100644
|
|
--- a/drivers/net/ethernet/cortina/gemini.h
|
|
+++ b/drivers/net/ethernet/cortina/gemini.h
|
|
@@ -502,7 +502,7 @@ union gmac_txdesc_3 {
|
|
#define SOF_BIT 0x80000000
|
|
#define EOF_BIT 0x40000000
|
|
#define EOFIE_BIT BIT(29)
|
|
-#define MTU_SIZE_BIT_MASK 0x1fff
|
|
+#define MTU_SIZE_BIT_MASK 0x7ff /* Max MTU 2047 bytes */
|
|
|
|
/* GMAC Tx Descriptor */
|
|
struct gmac_txdesc {
|
|
@@ -787,7 +787,7 @@ union gmac_config0 {
|
|
#define CONFIG0_MAXLEN_1536 0
|
|
#define CONFIG0_MAXLEN_1518 1
|
|
#define CONFIG0_MAXLEN_1522 2
|
|
-#define CONFIG0_MAXLEN_1542 3
|
|
+#define CONFIG0_MAXLEN_1548 3
|
|
#define CONFIG0_MAXLEN_9k 4 /* 9212 */
|
|
#define CONFIG0_MAXLEN_10k 5 /* 10236 */
|
|
#define CONFIG0_MAXLEN_1518__6 6
|
|
diff --git a/drivers/net/ethernet/engleder/tsnep.h b/drivers/net/ethernet/engleder/tsnep.h
|
|
index 09a723b827c77..0a0d3d7ba63b3 100644
|
|
--- a/drivers/net/ethernet/engleder/tsnep.h
|
|
+++ b/drivers/net/ethernet/engleder/tsnep.h
|
|
@@ -123,7 +123,7 @@ struct tsnep_rx {
|
|
|
|
struct tsnep_queue {
|
|
struct tsnep_adapter *adapter;
|
|
- char name[IFNAMSIZ + 9];
|
|
+ char name[IFNAMSIZ + 16];
|
|
|
|
struct tsnep_tx *tx;
|
|
struct tsnep_rx *rx;
|
|
diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
|
|
index 2be518db04270..c86dfbce787f1 100644
|
|
--- a/drivers/net/ethernet/engleder/tsnep_main.c
|
|
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
|
|
@@ -973,14 +973,14 @@ static int tsnep_request_irq(struct tsnep_queue *queue, bool first)
|
|
dev = queue->adapter;
|
|
} else {
|
|
if (queue->tx && queue->rx)
|
|
- sprintf(queue->name, "%s-txrx-%d", name,
|
|
- queue->rx->queue_index);
|
|
+ snprintf(queue->name, sizeof(queue->name), "%s-txrx-%d",
|
|
+ name, queue->rx->queue_index);
|
|
else if (queue->tx)
|
|
- sprintf(queue->name, "%s-tx-%d", name,
|
|
- queue->tx->queue_index);
|
|
+ snprintf(queue->name, sizeof(queue->name), "%s-tx-%d",
|
|
+ name, queue->tx->queue_index);
|
|
else
|
|
- sprintf(queue->name, "%s-rx-%d", name,
|
|
- queue->rx->queue_index);
|
|
+ snprintf(queue->name, sizeof(queue->name), "%s-rx-%d",
|
|
+ name, queue->rx->queue_index);
|
|
handler = tsnep_irq_txrx;
|
|
dev = queue;
|
|
}
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
|
|
index 00eed9835cb55..d2603cfc122c8 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
|
|
@@ -494,11 +494,14 @@ static void hns3_get_coal_info(struct hns3_enet_tqp_vector *tqp_vector,
|
|
}
|
|
|
|
sprintf(result[j++], "%d", i);
|
|
- sprintf(result[j++], "%s", dim_state_str[dim->state]);
|
|
+ sprintf(result[j++], "%s", dim->state < ARRAY_SIZE(dim_state_str) ?
|
|
+ dim_state_str[dim->state] : "unknown");
|
|
sprintf(result[j++], "%u", dim->profile_ix);
|
|
- sprintf(result[j++], "%s", dim_cqe_mode_str[dim->mode]);
|
|
+ sprintf(result[j++], "%s", dim->mode < ARRAY_SIZE(dim_cqe_mode_str) ?
|
|
+ dim_cqe_mode_str[dim->mode] : "unknown");
|
|
sprintf(result[j++], "%s",
|
|
- dim_tune_stat_str[dim->tune_state]);
|
|
+ dim->tune_state < ARRAY_SIZE(dim_tune_stat_str) ?
|
|
+ dim_tune_stat_str[dim->tune_state] : "unknown");
|
|
sprintf(result[j++], "%u", dim->steps_left);
|
|
sprintf(result[j++], "%u", dim->steps_right);
|
|
sprintf(result[j++], "%u", dim->tired);
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
index 04c9baca1b0f8..5ad22b815b2f0 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
@@ -5139,7 +5139,7 @@ static int hns3_init_mac_addr(struct net_device *netdev)
|
|
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
|
char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
|
|
struct hnae3_handle *h = priv->ae_handle;
|
|
- u8 mac_addr_temp[ETH_ALEN];
|
|
+ u8 mac_addr_temp[ETH_ALEN] = {0};
|
|
int ret = 0;
|
|
|
|
if (h->ae_algo->ops->get_mac_addr)
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
index 3e1d202d60ce1..48b0cb5ec5d29 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -74,6 +74,7 @@ static void hclge_sync_fd_table(struct hclge_dev *hdev);
|
|
static void hclge_update_fec_stats(struct hclge_dev *hdev);
|
|
static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret,
|
|
int wait_cnt);
|
|
+static int hclge_update_port_info(struct hclge_dev *hdev);
|
|
|
|
static struct hnae3_ae_algo ae_algo;
|
|
|
|
@@ -3141,6 +3142,9 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
|
|
|
|
if (state != hdev->hw.mac.link) {
|
|
hdev->hw.mac.link = state;
|
|
+ if (state == HCLGE_LINK_STATUS_UP)
|
|
+ hclge_update_port_info(hdev);
|
|
+
|
|
client->ops->link_status_change(handle, state);
|
|
hclge_config_mac_tnl_int(hdev, state);
|
|
if (rclient && rclient->ops->link_status_change)
|
|
@@ -10132,8 +10136,6 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
|
|
struct hclge_vport_vlan_cfg *vlan, *tmp;
|
|
struct hclge_dev *hdev = vport->back;
|
|
|
|
- mutex_lock(&hdev->vport_lock);
|
|
-
|
|
list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
|
|
if (vlan->vlan_id == vlan_id) {
|
|
if (is_write_tbl && vlan->hd_tbl_status)
|
|
@@ -10148,8 +10150,6 @@ static void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
|
|
break;
|
|
}
|
|
}
|
|
-
|
|
- mutex_unlock(&hdev->vport_lock);
|
|
}
|
|
|
|
void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
|
|
@@ -10558,11 +10558,16 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
|
|
* handle mailbox. Just record the vlan id, and remove it after
|
|
* reset finished.
|
|
*/
|
|
+ mutex_lock(&hdev->vport_lock);
|
|
if ((test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) ||
|
|
test_bit(HCLGE_STATE_RST_FAIL, &hdev->state)) && is_kill) {
|
|
set_bit(vlan_id, vport->vlan_del_fail_bmap);
|
|
+ mutex_unlock(&hdev->vport_lock);
|
|
return -EBUSY;
|
|
+ } else if (!is_kill && test_bit(vlan_id, vport->vlan_del_fail_bmap)) {
|
|
+ clear_bit(vlan_id, vport->vlan_del_fail_bmap);
|
|
}
|
|
+ mutex_unlock(&hdev->vport_lock);
|
|
|
|
/* when port base vlan enabled, we use port base vlan as the vlan
|
|
* filter entry. In this case, we don't update vlan filter table
|
|
@@ -10577,17 +10582,22 @@ int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
|
|
}
|
|
|
|
if (!ret) {
|
|
- if (!is_kill)
|
|
+ if (!is_kill) {
|
|
hclge_add_vport_vlan_table(vport, vlan_id,
|
|
writen_to_tbl);
|
|
- else if (is_kill && vlan_id != 0)
|
|
+ } else if (is_kill && vlan_id != 0) {
|
|
+ mutex_lock(&hdev->vport_lock);
|
|
hclge_rm_vport_vlan_table(vport, vlan_id, false);
|
|
+ mutex_unlock(&hdev->vport_lock);
|
|
+ }
|
|
} else if (is_kill) {
|
|
/* when remove hw vlan filter failed, record the vlan id,
|
|
* and try to remove it from hw later, to be consistence
|
|
* with stack
|
|
*/
|
|
+ mutex_lock(&hdev->vport_lock);
|
|
set_bit(vlan_id, vport->vlan_del_fail_bmap);
|
|
+ mutex_unlock(&hdev->vport_lock);
|
|
}
|
|
|
|
hclge_set_vport_vlan_fltr_change(vport);
|
|
@@ -10627,6 +10637,7 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev)
|
|
int i, ret, sync_cnt = 0;
|
|
u16 vlan_id;
|
|
|
|
+ mutex_lock(&hdev->vport_lock);
|
|
/* start from vport 1 for PF is always alive */
|
|
for (i = 0; i < hdev->num_alloc_vport; i++) {
|
|
struct hclge_vport *vport = &hdev->vport[i];
|
|
@@ -10637,21 +10648,26 @@ static void hclge_sync_vlan_filter(struct hclge_dev *hdev)
|
|
ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
|
|
vport->vport_id, vlan_id,
|
|
true);
|
|
- if (ret && ret != -EINVAL)
|
|
+ if (ret && ret != -EINVAL) {
|
|
+ mutex_unlock(&hdev->vport_lock);
|
|
return;
|
|
+ }
|
|
|
|
clear_bit(vlan_id, vport->vlan_del_fail_bmap);
|
|
hclge_rm_vport_vlan_table(vport, vlan_id, false);
|
|
hclge_set_vport_vlan_fltr_change(vport);
|
|
|
|
sync_cnt++;
|
|
- if (sync_cnt >= HCLGE_MAX_SYNC_COUNT)
|
|
+ if (sync_cnt >= HCLGE_MAX_SYNC_COUNT) {
|
|
+ mutex_unlock(&hdev->vport_lock);
|
|
return;
|
|
+ }
|
|
|
|
vlan_id = find_first_bit(vport->vlan_del_fail_bmap,
|
|
VLAN_N_VID);
|
|
}
|
|
}
|
|
+ mutex_unlock(&hdev->vport_lock);
|
|
|
|
hclge_sync_vlan_fltr_state(hdev);
|
|
}
|
|
@@ -11642,6 +11658,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
|
|
goto err_msi_irq_uninit;
|
|
|
|
if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_COPPER) {
|
|
+ clear_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps);
|
|
if (hnae3_dev_phy_imp_supported(hdev))
|
|
ret = hclge_update_tp_port_info(hdev);
|
|
else
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
index 72cf5145e15a2..5a978ea101a90 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
@@ -1258,6 +1258,8 @@ static int hclgevf_set_vlan_filter(struct hnae3_handle *handle,
|
|
test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) && is_kill) {
|
|
set_bit(vlan_id, hdev->vlan_del_fail_bmap);
|
|
return -EBUSY;
|
|
+ } else if (!is_kill && test_bit(vlan_id, hdev->vlan_del_fail_bmap)) {
|
|
+ clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
|
|
}
|
|
|
|
hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
|
|
@@ -1285,20 +1287,25 @@ static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev)
|
|
int ret, sync_cnt = 0;
|
|
u16 vlan_id;
|
|
|
|
+ if (bitmap_empty(hdev->vlan_del_fail_bmap, VLAN_N_VID))
|
|
+ return;
|
|
+
|
|
+ rtnl_lock();
|
|
vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
|
|
while (vlan_id != VLAN_N_VID) {
|
|
ret = hclgevf_set_vlan_filter(handle, htons(ETH_P_8021Q),
|
|
vlan_id, true);
|
|
if (ret)
|
|
- return;
|
|
+ break;
|
|
|
|
clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
|
|
sync_cnt++;
|
|
if (sync_cnt >= HCLGEVF_MAX_SYNC_COUNT)
|
|
- return;
|
|
+ break;
|
|
|
|
vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
|
|
}
|
|
+ rtnl_unlock();
|
|
}
|
|
|
|
static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
|
|
@@ -2028,8 +2035,18 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
|
|
return HCLGEVF_VECTOR0_EVENT_OTHER;
|
|
}
|
|
|
|
+static void hclgevf_reset_timer(struct timer_list *t)
|
|
+{
|
|
+ struct hclgevf_dev *hdev = from_timer(hdev, t, reset_timer);
|
|
+
|
|
+ hclgevf_clear_event_cause(hdev, HCLGEVF_VECTOR0_EVENT_RST);
|
|
+ hclgevf_reset_task_schedule(hdev);
|
|
+}
|
|
+
|
|
static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
|
|
{
|
|
+#define HCLGEVF_RESET_DELAY 5
|
|
+
|
|
enum hclgevf_evt_cause event_cause;
|
|
struct hclgevf_dev *hdev = data;
|
|
u32 clearval;
|
|
@@ -2041,7 +2058,8 @@ static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
|
|
|
|
switch (event_cause) {
|
|
case HCLGEVF_VECTOR0_EVENT_RST:
|
|
- hclgevf_reset_task_schedule(hdev);
|
|
+ mod_timer(&hdev->reset_timer,
|
|
+ jiffies + msecs_to_jiffies(HCLGEVF_RESET_DELAY));
|
|
break;
|
|
case HCLGEVF_VECTOR0_EVENT_MBX:
|
|
hclgevf_mbx_handler(hdev);
|
|
@@ -2987,6 +3005,7 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
|
|
HCLGEVF_DRIVER_NAME);
|
|
|
|
hclgevf_task_schedule(hdev, round_jiffies_relative(HZ));
|
|
+ timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0);
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
index 59ca6c794d6db..d65ace07b4569 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
@@ -219,6 +219,7 @@ struct hclgevf_dev {
|
|
enum hnae3_reset_type reset_level;
|
|
unsigned long reset_pending;
|
|
enum hnae3_reset_type reset_type;
|
|
+ struct timer_list reset_timer;
|
|
|
|
#define HCLGEVF_RESET_REQUESTED 0
|
|
#define HCLGEVF_RESET_PENDING 1
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
|
|
index bbf7b14079de3..85c2a634c8f96 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
|
|
@@ -63,6 +63,9 @@ static int hclgevf_get_mbx_resp(struct hclgevf_dev *hdev, u16 code0, u16 code1,
|
|
i++;
|
|
}
|
|
|
|
+ /* ensure additional_info will be seen after received_resp */
|
|
+ smp_rmb();
|
|
+
|
|
if (i >= HCLGEVF_MAX_TRY_TIMES) {
|
|
dev_err(&hdev->pdev->dev,
|
|
"VF could not get mbx(%u,%u) resp(=%d) from PF in %d tries\n",
|
|
@@ -178,6 +181,10 @@ static void hclgevf_handle_mbx_response(struct hclgevf_dev *hdev,
|
|
resp->resp_status = hclgevf_resp_to_errno(resp_status);
|
|
memcpy(resp->additional_info, req->msg.resp_data,
|
|
HCLGE_MBX_MAX_RESP_DATA_SIZE * sizeof(u8));
|
|
+
|
|
+ /* ensure additional_info will be seen before setting received_resp */
|
|
+ smp_wmb();
|
|
+
|
|
if (match_id) {
|
|
/* If match_id is not zero, it means PF support match_id.
|
|
* if the match_id is right, VF get the right response, or
|
|
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
|
|
index aca5b72cfeec6..eb4ebaa1c92ff 100644
|
|
--- a/drivers/net/ethernet/marvell/mvneta.c
|
|
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
|
@@ -4730,14 +4730,17 @@ static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
|
|
u8 *data)
|
|
{
|
|
if (sset == ETH_SS_STATS) {
|
|
+ struct mvneta_port *pp = netdev_priv(netdev);
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
|
|
memcpy(data + i * ETH_GSTRING_LEN,
|
|
mvneta_statistics[i].name, ETH_GSTRING_LEN);
|
|
|
|
- data += ETH_GSTRING_LEN * ARRAY_SIZE(mvneta_statistics);
|
|
- page_pool_ethtool_stats_get_strings(data);
|
|
+ if (!pp->bm_priv) {
|
|
+ data += ETH_GSTRING_LEN * ARRAY_SIZE(mvneta_statistics);
|
|
+ page_pool_ethtool_stats_get_strings(data);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -4855,8 +4858,10 @@ static void mvneta_ethtool_pp_stats(struct mvneta_port *pp, u64 *data)
|
|
struct page_pool_stats stats = {};
|
|
int i;
|
|
|
|
- for (i = 0; i < rxq_number; i++)
|
|
- page_pool_get_stats(pp->rxqs[i].page_pool, &stats);
|
|
+ for (i = 0; i < rxq_number; i++) {
|
|
+ if (pp->rxqs[i].page_pool)
|
|
+ page_pool_get_stats(pp->rxqs[i].page_pool, &stats);
|
|
+ }
|
|
|
|
page_pool_ethtool_stats_get(data, &stats);
|
|
}
|
|
@@ -4872,14 +4877,21 @@ static void mvneta_ethtool_get_stats(struct net_device *dev,
|
|
for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++)
|
|
*data++ = pp->ethtool_stats[i];
|
|
|
|
- mvneta_ethtool_pp_stats(pp, data);
|
|
+ if (!pp->bm_priv)
|
|
+ mvneta_ethtool_pp_stats(pp, data);
|
|
}
|
|
|
|
static int mvneta_ethtool_get_sset_count(struct net_device *dev, int sset)
|
|
{
|
|
- if (sset == ETH_SS_STATS)
|
|
- return ARRAY_SIZE(mvneta_statistics) +
|
|
- page_pool_ethtool_stats_get_count();
|
|
+ if (sset == ETH_SS_STATS) {
|
|
+ int count = ARRAY_SIZE(mvneta_statistics);
|
|
+ struct mvneta_port *pp = netdev_priv(dev);
|
|
+
|
|
+ if (!pp->bm_priv)
|
|
+ count += page_pool_ethtool_stats_get_count();
|
|
+
|
|
+ return count;
|
|
+ }
|
|
|
|
return -EOPNOTSUPP;
|
|
}
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
|
|
index 1ae15b8536a85..9b1f1369ac4d8 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
|
|
@@ -668,11 +668,11 @@ static int mlx5e_rx_reporter_dump(struct devlink_health_reporter *reporter,
|
|
|
|
void mlx5e_reporter_rx_timeout(struct mlx5e_rq *rq)
|
|
{
|
|
- char icosq_str[MLX5E_REPORTER_PER_Q_MAX_LEN] = {};
|
|
char err_str[MLX5E_REPORTER_PER_Q_MAX_LEN];
|
|
struct mlx5e_icosq *icosq = rq->icosq;
|
|
struct mlx5e_priv *priv = rq->priv;
|
|
struct mlx5e_err_ctx err_ctx = {};
|
|
+ char icosq_str[32] = {};
|
|
|
|
err_ctx.ctx = rq;
|
|
err_ctx.recover = mlx5e_rx_reporter_timeout_recover;
|
|
@@ -681,7 +681,7 @@ void mlx5e_reporter_rx_timeout(struct mlx5e_rq *rq)
|
|
if (icosq)
|
|
snprintf(icosq_str, sizeof(icosq_str), "ICOSQ: 0x%x, ", icosq->sqn);
|
|
snprintf(err_str, sizeof(err_str),
|
|
- "RX timeout on channel: %d, %sRQ: 0x%x, CQ: 0x%x",
|
|
+ "RX timeout on channel: %d, %s RQ: 0x%x, CQ: 0x%x",
|
|
rq->ix, icosq_str, rq->rqn, rq->cq.mcq.cqn);
|
|
|
|
mlx5e_health_report(priv, priv->rx_reporter, err_str, &err_ctx);
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
|
|
index 83bb0811e7741..4db0483c066a8 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
|
|
@@ -300,9 +300,6 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
|
|
if (err)
|
|
goto destroy_neigh_entry;
|
|
|
|
- e->encap_size = ipv4_encap_size;
|
|
- e->encap_header = encap_header;
|
|
-
|
|
if (!(nud_state & NUD_VALID)) {
|
|
neigh_event_send(attr.n, NULL);
|
|
/* the encap entry will be made valid on neigh update event
|
|
@@ -322,6 +319,8 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
|
|
goto destroy_neigh_entry;
|
|
}
|
|
|
|
+ e->encap_size = ipv4_encap_size;
|
|
+ e->encap_header = encap_header;
|
|
e->flags |= MLX5_ENCAP_ENTRY_VALID;
|
|
mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev));
|
|
mlx5e_route_lookup_ipv4_put(&attr);
|
|
@@ -404,16 +403,12 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv,
|
|
if (err)
|
|
goto free_encap;
|
|
|
|
- e->encap_size = ipv4_encap_size;
|
|
- kfree(e->encap_header);
|
|
- e->encap_header = encap_header;
|
|
-
|
|
if (!(nud_state & NUD_VALID)) {
|
|
neigh_event_send(attr.n, NULL);
|
|
/* the encap entry will be made valid on neigh update event
|
|
* and not used before that.
|
|
*/
|
|
- goto release_neigh;
|
|
+ goto free_encap;
|
|
}
|
|
|
|
memset(&reformat_params, 0, sizeof(reformat_params));
|
|
@@ -427,6 +422,10 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv,
|
|
goto free_encap;
|
|
}
|
|
|
|
+ e->encap_size = ipv4_encap_size;
|
|
+ kfree(e->encap_header);
|
|
+ e->encap_header = encap_header;
|
|
+
|
|
e->flags |= MLX5_ENCAP_ENTRY_VALID;
|
|
mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev));
|
|
mlx5e_route_lookup_ipv4_put(&attr);
|
|
@@ -568,9 +567,6 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
|
|
if (err)
|
|
goto destroy_neigh_entry;
|
|
|
|
- e->encap_size = ipv6_encap_size;
|
|
- e->encap_header = encap_header;
|
|
-
|
|
if (!(nud_state & NUD_VALID)) {
|
|
neigh_event_send(attr.n, NULL);
|
|
/* the encap entry will be made valid on neigh update event
|
|
@@ -590,6 +586,8 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
|
|
goto destroy_neigh_entry;
|
|
}
|
|
|
|
+ e->encap_size = ipv6_encap_size;
|
|
+ e->encap_header = encap_header;
|
|
e->flags |= MLX5_ENCAP_ENTRY_VALID;
|
|
mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev));
|
|
mlx5e_route_lookup_ipv6_put(&attr);
|
|
@@ -671,16 +669,12 @@ int mlx5e_tc_tun_update_header_ipv6(struct mlx5e_priv *priv,
|
|
if (err)
|
|
goto free_encap;
|
|
|
|
- e->encap_size = ipv6_encap_size;
|
|
- kfree(e->encap_header);
|
|
- e->encap_header = encap_header;
|
|
-
|
|
if (!(nud_state & NUD_VALID)) {
|
|
neigh_event_send(attr.n, NULL);
|
|
/* the encap entry will be made valid on neigh update event
|
|
* and not used before that.
|
|
*/
|
|
- goto release_neigh;
|
|
+ goto free_encap;
|
|
}
|
|
|
|
memset(&reformat_params, 0, sizeof(reformat_params));
|
|
@@ -694,6 +688,10 @@ int mlx5e_tc_tun_update_header_ipv6(struct mlx5e_priv *priv,
|
|
goto free_encap;
|
|
}
|
|
|
|
+ e->encap_size = ipv6_encap_size;
|
|
+ kfree(e->encap_header);
|
|
+ e->encap_header = encap_header;
|
|
+
|
|
e->flags |= MLX5_ENCAP_ENTRY_VALID;
|
|
mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev));
|
|
mlx5e_route_lookup_ipv6_put(&attr);
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
|
|
index 1728e197558d0..eeba91d9c5211 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
|
|
@@ -43,12 +43,17 @@ void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
|
|
struct ethtool_drvinfo *drvinfo)
|
|
{
|
|
struct mlx5_core_dev *mdev = priv->mdev;
|
|
+ int count;
|
|
|
|
strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
|
|
- snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
|
- "%d.%d.%04d (%.16s)",
|
|
- fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev),
|
|
- mdev->board_id);
|
|
+ count = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
|
+ "%d.%d.%04d (%.16s)", fw_rev_maj(mdev),
|
|
+ fw_rev_min(mdev), fw_rev_sub(mdev), mdev->board_id);
|
|
+ if (count == sizeof(drvinfo->fw_version))
|
|
+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
|
+ "%d.%d.%04d", fw_rev_maj(mdev),
|
|
+ fw_rev_min(mdev), fw_rev_sub(mdev));
|
|
+
|
|
strscpy(drvinfo->bus_info, dev_name(mdev->device),
|
|
sizeof(drvinfo->bus_info));
|
|
}
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
|
|
index bd895ef341a0b..2653cb96c3105 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
|
|
@@ -69,13 +69,17 @@ static void mlx5e_rep_get_drvinfo(struct net_device *dev,
|
|
{
|
|
struct mlx5e_priv *priv = netdev_priv(dev);
|
|
struct mlx5_core_dev *mdev = priv->mdev;
|
|
+ int count;
|
|
|
|
strscpy(drvinfo->driver, mlx5e_rep_driver_name,
|
|
sizeof(drvinfo->driver));
|
|
- snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
|
- "%d.%d.%04d (%.16s)",
|
|
- fw_rev_maj(mdev), fw_rev_min(mdev),
|
|
- fw_rev_sub(mdev), mdev->board_id);
|
|
+ count = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
|
+ "%d.%d.%04d (%.16s)", fw_rev_maj(mdev),
|
|
+ fw_rev_min(mdev), fw_rev_sub(mdev), mdev->board_id);
|
|
+ if (count == sizeof(drvinfo->fw_version))
|
|
+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
|
+ "%d.%d.%04d", fw_rev_maj(mdev),
|
|
+ fw_rev_min(mdev), fw_rev_sub(mdev));
|
|
}
|
|
|
|
static const struct counter_desc sw_rep_stats_desc[] = {
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
|
|
index 7ab489520a873..43239555f7850 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
|
|
@@ -3102,7 +3102,7 @@ static struct mlx5_fields fields[] = {
|
|
OFFLOAD(DIPV6_31_0, 32, U32_MAX, ip6.daddr.s6_addr32[3], 0,
|
|
dst_ipv4_dst_ipv6.ipv6_layout.ipv6[12]),
|
|
OFFLOAD(IPV6_HOPLIMIT, 8, U8_MAX, ip6.hop_limit, 0, ttl_hoplimit),
|
|
- OFFLOAD(IP_DSCP, 16, 0xc00f, ip6, 0, ip_dscp),
|
|
+ OFFLOAD(IP_DSCP, 16, 0x0fc0, ip6, 0, ip_dscp),
|
|
|
|
OFFLOAD(TCP_SPORT, 16, U16_MAX, tcp.source, 0, tcp_sport),
|
|
OFFLOAD(TCP_DPORT, 16, U16_MAX, tcp.dest, 0, tcp_dport),
|
|
@@ -3113,21 +3113,31 @@ static struct mlx5_fields fields[] = {
|
|
OFFLOAD(UDP_DPORT, 16, U16_MAX, udp.dest, 0, udp_dport),
|
|
};
|
|
|
|
-static unsigned long mask_to_le(unsigned long mask, int size)
|
|
+static u32 mask_field_get(void *mask, struct mlx5_fields *f)
|
|
{
|
|
- __be32 mask_be32;
|
|
- __be16 mask_be16;
|
|
-
|
|
- if (size == 32) {
|
|
- mask_be32 = (__force __be32)(mask);
|
|
- mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
|
|
- } else if (size == 16) {
|
|
- mask_be32 = (__force __be32)(mask);
|
|
- mask_be16 = *(__be16 *)&mask_be32;
|
|
- mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
|
|
+ switch (f->field_bsize) {
|
|
+ case 32:
|
|
+ return be32_to_cpu(*(__be32 *)mask) & f->field_mask;
|
|
+ case 16:
|
|
+ return be16_to_cpu(*(__be16 *)mask) & (u16)f->field_mask;
|
|
+ default:
|
|
+ return *(u8 *)mask & (u8)f->field_mask;
|
|
}
|
|
+}
|
|
|
|
- return mask;
|
|
+static void mask_field_clear(void *mask, struct mlx5_fields *f)
|
|
+{
|
|
+ switch (f->field_bsize) {
|
|
+ case 32:
|
|
+ *(__be32 *)mask &= ~cpu_to_be32(f->field_mask);
|
|
+ break;
|
|
+ case 16:
|
|
+ *(__be16 *)mask &= ~cpu_to_be16((u16)f->field_mask);
|
|
+ break;
|
|
+ default:
|
|
+ *(u8 *)mask &= ~(u8)f->field_mask;
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
static int offload_pedit_fields(struct mlx5e_priv *priv,
|
|
@@ -3139,11 +3149,12 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
|
|
struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
|
|
struct pedit_headers_action *hdrs = parse_attr->hdrs;
|
|
void *headers_c, *headers_v, *action, *vals_p;
|
|
- u32 *s_masks_p, *a_masks_p, s_mask, a_mask;
|
|
struct mlx5e_tc_mod_hdr_acts *mod_acts;
|
|
- unsigned long mask, field_mask;
|
|
+ void *s_masks_p, *a_masks_p;
|
|
int i, first, last, next_z;
|
|
struct mlx5_fields *f;
|
|
+ unsigned long mask;
|
|
+ u32 s_mask, a_mask;
|
|
u8 cmd;
|
|
|
|
mod_acts = &parse_attr->mod_hdr_acts;
|
|
@@ -3159,15 +3170,11 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
|
|
bool skip;
|
|
|
|
f = &fields[i];
|
|
- /* avoid seeing bits set from previous iterations */
|
|
- s_mask = 0;
|
|
- a_mask = 0;
|
|
-
|
|
s_masks_p = (void *)set_masks + f->offset;
|
|
a_masks_p = (void *)add_masks + f->offset;
|
|
|
|
- s_mask = *s_masks_p & f->field_mask;
|
|
- a_mask = *a_masks_p & f->field_mask;
|
|
+ s_mask = mask_field_get(s_masks_p, f);
|
|
+ a_mask = mask_field_get(a_masks_p, f);
|
|
|
|
if (!s_mask && !a_mask) /* nothing to offload here */
|
|
continue;
|
|
@@ -3194,22 +3201,20 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
|
|
match_mask, f->field_bsize))
|
|
skip = true;
|
|
/* clear to denote we consumed this field */
|
|
- *s_masks_p &= ~f->field_mask;
|
|
+ mask_field_clear(s_masks_p, f);
|
|
} else {
|
|
cmd = MLX5_ACTION_TYPE_ADD;
|
|
mask = a_mask;
|
|
vals_p = (void *)add_vals + f->offset;
|
|
/* add 0 is no change */
|
|
- if ((*(u32 *)vals_p & f->field_mask) == 0)
|
|
+ if (!mask_field_get(vals_p, f))
|
|
skip = true;
|
|
/* clear to denote we consumed this field */
|
|
- *a_masks_p &= ~f->field_mask;
|
|
+ mask_field_clear(a_masks_p, f);
|
|
}
|
|
if (skip)
|
|
continue;
|
|
|
|
- mask = mask_to_le(mask, f->field_bsize);
|
|
-
|
|
first = find_first_bit(&mask, f->field_bsize);
|
|
next_z = find_next_zero_bit(&mask, f->field_bsize, first);
|
|
last = find_last_bit(&mask, f->field_bsize);
|
|
@@ -3236,10 +3241,9 @@ static int offload_pedit_fields(struct mlx5e_priv *priv,
|
|
MLX5_SET(set_action_in, action, field, f->field);
|
|
|
|
if (cmd == MLX5_ACTION_TYPE_SET) {
|
|
+ unsigned long field_mask = f->field_mask;
|
|
int start;
|
|
|
|
- field_mask = mask_to_le(f->field_mask, f->field_bsize);
|
|
-
|
|
/* if field is bit sized it can start not from first bit */
|
|
start = find_first_bit(&field_mask, f->field_bsize);
|
|
|
|
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
|
|
index d14706265d9cb..770391cefb4e4 100644
|
|
--- a/drivers/net/ethernet/realtek/r8169_main.c
|
|
+++ b/drivers/net/ethernet/realtek/r8169_main.c
|
|
@@ -614,6 +614,7 @@ struct rtl8169_private {
|
|
|
|
unsigned supports_gmii:1;
|
|
unsigned aspm_manageable:1;
|
|
+ unsigned dash_enabled:1;
|
|
dma_addr_t counters_phys_addr;
|
|
struct rtl8169_counters *counters;
|
|
struct rtl8169_tc_offsets tc_offset;
|
|
@@ -1186,14 +1187,26 @@ static bool r8168ep_check_dash(struct rtl8169_private *tp)
|
|
return r8168ep_ocp_read(tp, 0x128) & BIT(0);
|
|
}
|
|
|
|
-static enum rtl_dash_type rtl_check_dash(struct rtl8169_private *tp)
|
|
+static bool rtl_dash_is_enabled(struct rtl8169_private *tp)
|
|
+{
|
|
+ switch (tp->dash_type) {
|
|
+ case RTL_DASH_DP:
|
|
+ return r8168dp_check_dash(tp);
|
|
+ case RTL_DASH_EP:
|
|
+ return r8168ep_check_dash(tp);
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp)
|
|
{
|
|
switch (tp->mac_version) {
|
|
case RTL_GIGA_MAC_VER_28:
|
|
case RTL_GIGA_MAC_VER_31:
|
|
- return r8168dp_check_dash(tp) ? RTL_DASH_DP : RTL_DASH_NONE;
|
|
+ return RTL_DASH_DP;
|
|
case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
|
|
- return r8168ep_check_dash(tp) ? RTL_DASH_EP : RTL_DASH_NONE;
|
|
+ return RTL_DASH_EP;
|
|
default:
|
|
return RTL_DASH_NONE;
|
|
}
|
|
@@ -1383,7 +1396,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
|
|
|
|
device_set_wakeup_enable(tp_to_dev(tp), wolopts);
|
|
|
|
- if (tp->dash_type == RTL_DASH_NONE) {
|
|
+ if (!tp->dash_enabled) {
|
|
rtl_set_d3_pll_down(tp, !wolopts);
|
|
tp->dev->wol_enabled = wolopts ? 1 : 0;
|
|
}
|
|
@@ -2442,7 +2455,7 @@ static void rtl_wol_enable_rx(struct rtl8169_private *tp)
|
|
|
|
static void rtl_prepare_power_down(struct rtl8169_private *tp)
|
|
{
|
|
- if (tp->dash_type != RTL_DASH_NONE)
|
|
+ if (tp->dash_enabled)
|
|
return;
|
|
|
|
if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
|
|
@@ -2516,9 +2529,7 @@ static void rtl_set_rx_mode(struct net_device *dev)
|
|
rx_mode &= ~AcceptMulticast;
|
|
} else if (netdev_mc_count(dev) > MC_FILTER_LIMIT ||
|
|
dev->flags & IFF_ALLMULTI ||
|
|
- tp->mac_version == RTL_GIGA_MAC_VER_35 ||
|
|
- tp->mac_version == RTL_GIGA_MAC_VER_46 ||
|
|
- tp->mac_version == RTL_GIGA_MAC_VER_48) {
|
|
+ tp->mac_version == RTL_GIGA_MAC_VER_35) {
|
|
/* accept all multicasts */
|
|
} else if (netdev_mc_empty(dev)) {
|
|
rx_mode &= ~AcceptMulticast;
|
|
@@ -4613,10 +4624,16 @@ static void rtl8169_down(struct rtl8169_private *tp)
|
|
rtl8169_cleanup(tp);
|
|
rtl_disable_exit_l1(tp);
|
|
rtl_prepare_power_down(tp);
|
|
+
|
|
+ if (tp->dash_type != RTL_DASH_NONE)
|
|
+ rtl8168_driver_stop(tp);
|
|
}
|
|
|
|
static void rtl8169_up(struct rtl8169_private *tp)
|
|
{
|
|
+ if (tp->dash_type != RTL_DASH_NONE)
|
|
+ rtl8168_driver_start(tp);
|
|
+
|
|
pci_set_master(tp->pci_dev);
|
|
phy_init_hw(tp->phydev);
|
|
phy_resume(tp->phydev);
|
|
@@ -4834,7 +4851,7 @@ static int rtl8169_runtime_idle(struct device *device)
|
|
{
|
|
struct rtl8169_private *tp = dev_get_drvdata(device);
|
|
|
|
- if (tp->dash_type != RTL_DASH_NONE)
|
|
+ if (tp->dash_enabled)
|
|
return -EBUSY;
|
|
|
|
if (!netif_running(tp->dev) || !netif_carrier_ok(tp->dev))
|
|
@@ -4860,8 +4877,7 @@ static void rtl_shutdown(struct pci_dev *pdev)
|
|
/* Restore original MAC address */
|
|
rtl_rar_set(tp, tp->dev->perm_addr);
|
|
|
|
- if (system_state == SYSTEM_POWER_OFF &&
|
|
- tp->dash_type == RTL_DASH_NONE) {
|
|
+ if (system_state == SYSTEM_POWER_OFF && !tp->dash_enabled) {
|
|
pci_wake_from_d3(pdev, tp->saved_wolopts);
|
|
pci_set_power_state(pdev, PCI_D3hot);
|
|
}
|
|
@@ -5217,7 +5233,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
|
|
tp->aspm_manageable = !rc;
|
|
|
|
- tp->dash_type = rtl_check_dash(tp);
|
|
+ tp->dash_type = rtl_get_dash_type(tp);
|
|
+ tp->dash_enabled = rtl_dash_is_enabled(tp);
|
|
|
|
tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
|
|
|
|
@@ -5287,7 +5304,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
/* configure chip for default features */
|
|
rtl8169_set_features(dev, dev->features);
|
|
|
|
- if (tp->dash_type == RTL_DASH_NONE) {
|
|
+ if (!tp->dash_enabled) {
|
|
rtl_set_d3_pll_down(tp, true);
|
|
} else {
|
|
rtl_set_d3_pll_down(tp, false);
|
|
@@ -5327,7 +5344,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
"ok" : "ko");
|
|
|
|
if (tp->dash_type != RTL_DASH_NONE) {
|
|
- netdev_info(dev, "DASH enabled\n");
|
|
+ netdev_info(dev, "DASH %s\n",
|
|
+ tp->dash_enabled ? "enabled" : "disabled");
|
|
rtl8168_driver_start(tp);
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
|
index 1559a4dafd413..9f76c2f7d513b 100644
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
|
@@ -5198,6 +5198,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|
|
|
dma_dir = page_pool_get_dma_dir(rx_q->page_pool);
|
|
buf_sz = DIV_ROUND_UP(priv->dma_conf.dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
|
|
+ limit = min(priv->dma_conf.dma_rx_size - 1, (unsigned int)limit);
|
|
|
|
if (netif_msg_rx_status(priv)) {
|
|
void *rx_head;
|
|
@@ -5233,10 +5234,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|
len = 0;
|
|
}
|
|
|
|
+read_again:
|
|
if (count >= limit)
|
|
break;
|
|
|
|
-read_again:
|
|
buf1_len = 0;
|
|
buf2_len = 0;
|
|
entry = next_entry;
|
|
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
|
|
index b29b7d97b7739..d447f3076e24a 100644
|
|
--- a/drivers/net/ipvlan/ipvlan_core.c
|
|
+++ b/drivers/net/ipvlan/ipvlan_core.c
|
|
@@ -411,7 +411,7 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
|
|
return addr;
|
|
}
|
|
|
|
-static int ipvlan_process_v4_outbound(struct sk_buff *skb)
|
|
+static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb)
|
|
{
|
|
const struct iphdr *ip4h = ip_hdr(skb);
|
|
struct net_device *dev = skb->dev;
|
|
@@ -453,13 +453,11 @@ out:
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
-static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
|
+
|
|
+static noinline_for_stack int
|
|
+ipvlan_route_v6_outbound(struct net_device *dev, struct sk_buff *skb)
|
|
{
|
|
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
|
- struct net_device *dev = skb->dev;
|
|
- struct net *net = dev_net(dev);
|
|
- struct dst_entry *dst;
|
|
- int err, ret = NET_XMIT_DROP;
|
|
struct flowi6 fl6 = {
|
|
.flowi6_oif = dev->ifindex,
|
|
.daddr = ip6h->daddr,
|
|
@@ -469,27 +467,38 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
|
.flowi6_mark = skb->mark,
|
|
.flowi6_proto = ip6h->nexthdr,
|
|
};
|
|
+ struct dst_entry *dst;
|
|
+ int err;
|
|
|
|
- dst = ip6_route_output(net, NULL, &fl6);
|
|
- if (dst->error) {
|
|
- ret = dst->error;
|
|
+ dst = ip6_route_output(dev_net(dev), NULL, &fl6);
|
|
+ err = dst->error;
|
|
+ if (err) {
|
|
dst_release(dst);
|
|
- goto err;
|
|
+ return err;
|
|
}
|
|
skb_dst_set(skb, dst);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
|
+{
|
|
+ struct net_device *dev = skb->dev;
|
|
+ int err, ret = NET_XMIT_DROP;
|
|
+
|
|
+ err = ipvlan_route_v6_outbound(dev, skb);
|
|
+ if (unlikely(err)) {
|
|
+ DEV_STATS_INC(dev, tx_errors);
|
|
+ kfree_skb(skb);
|
|
+ return err;
|
|
+ }
|
|
|
|
memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
|
|
|
|
- err = ip6_local_out(net, skb->sk, skb);
|
|
+ err = ip6_local_out(dev_net(dev), skb->sk, skb);
|
|
if (unlikely(net_xmit_eval(err)))
|
|
DEV_STATS_INC(dev, tx_errors);
|
|
else
|
|
ret = NET_XMIT_SUCCESS;
|
|
- goto out;
|
|
-err:
|
|
- DEV_STATS_INC(dev, tx_errors);
|
|
- kfree_skb(skb);
|
|
-out:
|
|
return ret;
|
|
}
|
|
#else
|
|
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
|
|
index b8cc55b2d721c..012830d12fde6 100644
|
|
--- a/drivers/net/macvlan.c
|
|
+++ b/drivers/net/macvlan.c
|
|
@@ -771,7 +771,7 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change)
|
|
if (dev->flags & IFF_UP) {
|
|
if (change & IFF_ALLMULTI)
|
|
dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
|
|
- if (change & IFF_PROMISC)
|
|
+ if (!macvlan_passthru(vlan->port) && change & IFF_PROMISC)
|
|
dev_set_promiscuity(lowerdev,
|
|
dev->flags & IFF_PROMISC ? 1 : -1);
|
|
|
|
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
|
|
index 5b064a1de92f0..fc58e4afb38dd 100644
|
|
--- a/drivers/net/phy/phylink.c
|
|
+++ b/drivers/net/phy/phylink.c
|
|
@@ -1479,6 +1479,7 @@ struct phylink *phylink_create(struct phylink_config *config,
|
|
pl->config = config;
|
|
if (config->type == PHYLINK_NETDEV) {
|
|
pl->netdev = to_net_dev(config->dev);
|
|
+ netif_carrier_off(pl->netdev);
|
|
} else if (config->type == PHYLINK_DEV) {
|
|
pl->dev = config->dev;
|
|
} else {
|
|
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
|
|
index 18283b7b94bcd..94ef6f9ca5103 100644
|
|
--- a/drivers/net/ppp/ppp_synctty.c
|
|
+++ b/drivers/net/ppp/ppp_synctty.c
|
|
@@ -462,6 +462,10 @@ ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
|
|
case PPPIOCSMRU:
|
|
if (get_user(val, (int __user *) argp))
|
|
break;
|
|
+ if (val > U16_MAX) {
|
|
+ err = -EINVAL;
|
|
+ break;
|
|
+ }
|
|
if (val < PPP_MRU)
|
|
val = PPP_MRU;
|
|
ap->mru = val;
|
|
@@ -697,7 +701,7 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
|
|
|
|
/* strip address/control field if present */
|
|
p = skb->data;
|
|
- if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
|
|
+ if (skb->len >= 2 && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
|
|
/* chop off address/control */
|
|
if (skb->len < 3)
|
|
goto err;
|
|
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
|
|
index c861e66ef6bc5..41f387e15dcd0 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/debug.c
|
|
@@ -1139,7 +1139,7 @@ void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
|
|
u32 sset, u8 *data)
|
|
{
|
|
if (sset == ETH_SS_STATS)
|
|
- memcpy(data, *ath10k_gstrings_stats,
|
|
+ memcpy(data, ath10k_gstrings_stats,
|
|
sizeof(ath10k_gstrings_stats));
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
|
|
index cfcb759a87dea..4b7266d928470 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/snoc.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
|
|
@@ -828,12 +828,20 @@ static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar,
|
|
|
|
static inline void ath10k_snoc_irq_disable(struct ath10k *ar)
|
|
{
|
|
- ath10k_ce_disable_interrupts(ar);
|
|
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
|
+ int id;
|
|
+
|
|
+ for (id = 0; id < CE_COUNT_MAX; id++)
|
|
+ disable_irq(ar_snoc->ce_irqs[id].irq_line);
|
|
}
|
|
|
|
static inline void ath10k_snoc_irq_enable(struct ath10k *ar)
|
|
{
|
|
- ath10k_ce_enable_interrupts(ar);
|
|
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
|
+ int id;
|
|
+
|
|
+ for (id = 0; id < CE_COUNT_MAX; id++)
|
|
+ enable_irq(ar_snoc->ce_irqs[id].irq_line);
|
|
}
|
|
|
|
static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)
|
|
@@ -1089,6 +1097,8 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar,
|
|
goto err_free_rri;
|
|
}
|
|
|
|
+ ath10k_ce_enable_interrupts(ar);
|
|
+
|
|
return 0;
|
|
|
|
err_free_rri:
|
|
@@ -1252,8 +1262,8 @@ static int ath10k_snoc_request_irq(struct ath10k *ar)
|
|
|
|
for (id = 0; id < CE_COUNT_MAX; id++) {
|
|
ret = request_irq(ar_snoc->ce_irqs[id].irq_line,
|
|
- ath10k_snoc_per_engine_handler, 0,
|
|
- ce_name[id], ar);
|
|
+ ath10k_snoc_per_engine_handler,
|
|
+ IRQF_NO_AUTOEN, ce_name[id], ar);
|
|
if (ret) {
|
|
ath10k_err(ar,
|
|
"failed to register IRQ handler for CE %d: %d\n",
|
|
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
index 38be646bc0214..b1067bcdf88a5 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
@@ -1621,14 +1621,20 @@ static void ath11k_htt_pktlog(struct ath11k_base *ab, struct sk_buff *skb)
|
|
u8 pdev_id;
|
|
|
|
pdev_id = FIELD_GET(HTT_T2H_PPDU_STATS_INFO_PDEV_ID, data->hdr);
|
|
+
|
|
+ rcu_read_lock();
|
|
+
|
|
ar = ath11k_mac_get_ar_by_pdev_id(ab, pdev_id);
|
|
if (!ar) {
|
|
ath11k_warn(ab, "invalid pdev id %d on htt pktlog\n", pdev_id);
|
|
- return;
|
|
+ goto out;
|
|
}
|
|
|
|
trace_ath11k_htt_pktlog(ar, data->payload, hdr->size,
|
|
ar->ab->pktlog_defs_checksum);
|
|
+
|
|
+out:
|
|
+ rcu_read_unlock();
|
|
}
|
|
|
|
static void ath11k_htt_backpressure_event_handler(struct ath11k_base *ab,
|
|
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
index 3e0a47f4a3ebd..142b201052660 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -7729,6 +7729,8 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
|
|
ev->detector_id, ev->segment_id, ev->timestamp, ev->is_chirp,
|
|
ev->freq_offset, ev->sidx);
|
|
|
|
+ rcu_read_lock();
|
|
+
|
|
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
|
|
|
if (!ar) {
|
|
@@ -7746,6 +7748,8 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff
|
|
ieee80211_radar_detected(ar->hw);
|
|
|
|
exit:
|
|
+ rcu_read_unlock();
|
|
+
|
|
kfree(tb);
|
|
}
|
|
|
|
@@ -7775,15 +7779,19 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
|
|
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
|
"pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id);
|
|
|
|
+ rcu_read_lock();
|
|
+
|
|
ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
|
if (!ar) {
|
|
ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev->pdev_id);
|
|
- kfree(tb);
|
|
- return;
|
|
+ goto exit;
|
|
}
|
|
|
|
ath11k_thermal_event_temperature(ar, ev->temp);
|
|
|
|
+exit:
|
|
+ rcu_read_unlock();
|
|
+
|
|
kfree(tb);
|
|
}
|
|
|
|
@@ -7993,12 +8001,13 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
|
|
return;
|
|
}
|
|
|
|
+ rcu_read_lock();
|
|
+
|
|
arvif = ath11k_mac_get_arvif_by_vdev_id(ab, ev->vdev_id);
|
|
if (!arvif) {
|
|
ath11k_warn(ab, "failed to get arvif for vdev_id:%d\n",
|
|
ev->vdev_id);
|
|
- kfree(tb);
|
|
- return;
|
|
+ goto exit;
|
|
}
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi gtk offload event refresh_cnt %d\n",
|
|
@@ -8015,6 +8024,8 @@ static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab,
|
|
|
|
ieee80211_gtk_rekey_notify(arvif->vif, arvif->bssid,
|
|
(void *)&replay_ctr_be, GFP_ATOMIC);
|
|
+exit:
|
|
+ rcu_read_unlock();
|
|
|
|
kfree(tb);
|
|
}
|
|
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
|
|
index fb7a2952d0ce8..d9bac1c343490 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
|
@@ -1333,7 +1333,7 @@ void ath9k_get_et_strings(struct ieee80211_hw *hw,
|
|
u32 sset, u8 *data)
|
|
{
|
|
if (sset == ETH_SS_STATS)
|
|
- memcpy(data, *ath9k_gstrings_stats,
|
|
+ memcpy(data, ath9k_gstrings_stats,
|
|
sizeof(ath9k_gstrings_stats));
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
|
|
index c55aab01fff5d..e79bbcd3279af 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
|
|
@@ -428,7 +428,7 @@ void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
|
|
u32 sset, u8 *data)
|
|
{
|
|
if (sset == ETH_SS_STATS)
|
|
- memcpy(data, *ath9k_htc_gstrings_stats,
|
|
+ memcpy(data, ath9k_htc_gstrings_stats,
|
|
sizeof(ath9k_htc_gstrings_stats));
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
|
|
index 618355ecd9d7b..caaf4d52e2c64 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
|
|
@@ -524,16 +524,20 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|
flags |= IWL_TX_FLAGS_ENCRYPT_DIS;
|
|
|
|
/*
|
|
- * For data packets rate info comes from the fw. Only
|
|
- * set rate/antenna during connection establishment or in case
|
|
- * no station is given.
|
|
+ * For data and mgmt packets rate info comes from the fw. Only
|
|
+ * set rate/antenna for injected frames with fixed rate, or
|
|
+ * when no sta is given.
|
|
*/
|
|
- if (!sta || !ieee80211_is_data(hdr->frame_control) ||
|
|
- mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) {
|
|
+ if (unlikely(!sta ||
|
|
+ info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) {
|
|
flags |= IWL_TX_FLAGS_CMD_RATE;
|
|
rate_n_flags =
|
|
iwl_mvm_get_tx_rate_n_flags(mvm, info, sta,
|
|
hdr->frame_control);
|
|
+ } else if (!ieee80211_is_data(hdr->frame_control) ||
|
|
+ mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) {
|
|
+ /* These are important frames */
|
|
+ flags |= IWL_TX_FLAGS_HIGH_PRI;
|
|
}
|
|
|
|
if (mvm->trans->trans_cfg->device_family >=
|
|
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
|
|
index db70cef854bc4..abcd165a62cfe 100644
|
|
--- a/drivers/net/wireless/mac80211_hwsim.c
|
|
+++ b/drivers/net/wireless/mac80211_hwsim.c
|
|
@@ -3021,7 +3021,7 @@ static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw,
|
|
u32 sset, u8 *data)
|
|
{
|
|
if (sset == ETH_SS_STATS)
|
|
- memcpy(data, *mac80211_hwsim_gstrings_stats,
|
|
+ memcpy(data, mac80211_hwsim_gstrings_stats,
|
|
sizeof(mac80211_hwsim_gstrings_stats));
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
|
|
index 58bbf50081e47..9eb115c79c90a 100644
|
|
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
|
|
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
|
|
@@ -1492,7 +1492,7 @@ int wilc_wlan_init(struct net_device *dev)
|
|
}
|
|
|
|
if (!wilc->vmm_table)
|
|
- wilc->vmm_table = kzalloc(WILC_VMM_TBL_SIZE, GFP_KERNEL);
|
|
+ wilc->vmm_table = kcalloc(WILC_VMM_TBL_SIZE, sizeof(u32), GFP_KERNEL);
|
|
|
|
if (!wilc->vmm_table) {
|
|
ret = -ENOBUFS;
|
|
diff --git a/drivers/net/wireless/purelifi/plfxlc/mac.c b/drivers/net/wireless/purelifi/plfxlc/mac.c
|
|
index d3cdffbded693..87a4ff888ddd4 100644
|
|
--- a/drivers/net/wireless/purelifi/plfxlc/mac.c
|
|
+++ b/drivers/net/wireless/purelifi/plfxlc/mac.c
|
|
@@ -666,7 +666,7 @@ static void plfxlc_get_et_strings(struct ieee80211_hw *hw,
|
|
u32 sset, u8 *data)
|
|
{
|
|
if (sset == ETH_SS_STATS)
|
|
- memcpy(data, *et_strings, sizeof(et_strings));
|
|
+ memcpy(data, et_strings, sizeof(et_strings));
|
|
}
|
|
|
|
static void plfxlc_get_et_stats(struct ieee80211_hw *hw,
|
|
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
|
|
index 6f5e5f0230d39..332bcc0053a5e 100644
|
|
--- a/drivers/parisc/power.c
|
|
+++ b/drivers/parisc/power.c
|
|
@@ -197,6 +197,14 @@ static struct notifier_block parisc_panic_block = {
|
|
.priority = INT_MAX,
|
|
};
|
|
|
|
+/* qemu soft power-off function */
|
|
+static int qemu_power_off(struct sys_off_data *data)
|
|
+{
|
|
+ /* this turns the system off via SeaBIOS */
|
|
+ gsc_writel(0, (unsigned long) data->cb_data);
|
|
+ pdc_soft_power_button(1);
|
|
+ return NOTIFY_DONE;
|
|
+}
|
|
|
|
static int __init power_init(void)
|
|
{
|
|
@@ -226,7 +234,13 @@ static int __init power_init(void)
|
|
soft_power_reg);
|
|
}
|
|
|
|
- power_task = kthread_run(kpowerswd, (void*)soft_power_reg, KTHREAD_NAME);
|
|
+ power_task = NULL;
|
|
+ if (running_on_qemu && soft_power_reg)
|
|
+ register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_DEFAULT,
|
|
+ qemu_power_off, (void *)soft_power_reg);
|
|
+ else
|
|
+ power_task = kthread_run(kpowerswd, (void*)soft_power_reg,
|
|
+ KTHREAD_NAME);
|
|
if (IS_ERR(power_task)) {
|
|
printk(KERN_ERR DRIVER_NAME ": thread creation failed. Driver not loaded.\n");
|
|
pdc_soft_power_button(0);
|
|
diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c
|
|
index ec56110055665..e5519978ba475 100644
|
|
--- a/drivers/pci/controller/dwc/pci-exynos.c
|
|
+++ b/drivers/pci/controller/dwc/pci-exynos.c
|
|
@@ -375,7 +375,7 @@ fail_probe:
|
|
return ret;
|
|
}
|
|
|
|
-static int __exit exynos_pcie_remove(struct platform_device *pdev)
|
|
+static int exynos_pcie_remove(struct platform_device *pdev)
|
|
{
|
|
struct exynos_pcie *ep = platform_get_drvdata(pdev);
|
|
|
|
@@ -431,7 +431,7 @@ static const struct of_device_id exynos_pcie_of_match[] = {
|
|
|
|
static struct platform_driver exynos_pcie_driver = {
|
|
.probe = exynos_pcie_probe,
|
|
- .remove = __exit_p(exynos_pcie_remove),
|
|
+ .remove = exynos_pcie_remove,
|
|
.driver = {
|
|
.name = "exynos-pcie",
|
|
.of_match_table = exynos_pcie_of_match,
|
|
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
|
|
index 78818853af9e4..d2634dafb68e5 100644
|
|
--- a/drivers/pci/controller/dwc/pci-keystone.c
|
|
+++ b/drivers/pci/controller/dwc/pci-keystone.c
|
|
@@ -1101,7 +1101,7 @@ static const struct of_device_id ks_pcie_of_match[] = {
|
|
{ },
|
|
};
|
|
|
|
-static int __init ks_pcie_probe(struct platform_device *pdev)
|
|
+static int ks_pcie_probe(struct platform_device *pdev)
|
|
{
|
|
const struct dw_pcie_host_ops *host_ops;
|
|
const struct dw_pcie_ep_ops *ep_ops;
|
|
@@ -1303,7 +1303,7 @@ err_link:
|
|
return ret;
|
|
}
|
|
|
|
-static int __exit ks_pcie_remove(struct platform_device *pdev)
|
|
+static int ks_pcie_remove(struct platform_device *pdev)
|
|
{
|
|
struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
|
|
struct device_link **link = ks_pcie->link;
|
|
@@ -1319,9 +1319,9 @@ static int __exit ks_pcie_remove(struct platform_device *pdev)
|
|
return 0;
|
|
}
|
|
|
|
-static struct platform_driver ks_pcie_driver __refdata = {
|
|
+static struct platform_driver ks_pcie_driver = {
|
|
.probe = ks_pcie_probe,
|
|
- .remove = __exit_p(ks_pcie_remove),
|
|
+ .remove = ks_pcie_remove,
|
|
.driver = {
|
|
.name = "keystone-pcie",
|
|
.of_match_table = ks_pcie_of_match,
|
|
diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c
|
|
index d09507f822a7d..a824d8e8edb9d 100644
|
|
--- a/drivers/pci/controller/dwc/pcie-kirin.c
|
|
+++ b/drivers/pci/controller/dwc/pcie-kirin.c
|
|
@@ -742,7 +742,7 @@ err:
|
|
return ret;
|
|
}
|
|
|
|
-static int __exit kirin_pcie_remove(struct platform_device *pdev)
|
|
+static int kirin_pcie_remove(struct platform_device *pdev)
|
|
{
|
|
struct kirin_pcie *kirin_pcie = platform_get_drvdata(pdev);
|
|
|
|
@@ -819,7 +819,7 @@ static int kirin_pcie_probe(struct platform_device *pdev)
|
|
|
|
static struct platform_driver kirin_pcie_driver = {
|
|
.probe = kirin_pcie_probe,
|
|
- .remove = __exit_p(kirin_pcie_remove),
|
|
+ .remove = kirin_pcie_remove,
|
|
.driver = {
|
|
.name = "kirin-pcie",
|
|
.of_match_table = kirin_pcie_match,
|
|
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
|
|
index 2241029537a03..5d1ae2706f6ea 100644
|
|
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
|
|
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
|
|
@@ -9,6 +9,7 @@
|
|
* Author: Vidya Sagar <vidyas@nvidia.com>
|
|
*/
|
|
|
|
+#include <linux/bitfield.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/delay.h>
|
|
@@ -324,8 +325,7 @@ static void apply_bad_link_workaround(struct dw_pcie_rp *pp)
|
|
*/
|
|
val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
|
|
if (val & PCI_EXP_LNKSTA_LBMS) {
|
|
- current_link_width = (val & PCI_EXP_LNKSTA_NLW) >>
|
|
- PCI_EXP_LNKSTA_NLW_SHIFT;
|
|
+ current_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val);
|
|
if (pcie->init_link_width > current_link_width) {
|
|
dev_warn(pci->dev, "PCIe link is bad, width reduced\n");
|
|
val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
|
|
@@ -740,8 +740,7 @@ static void tegra_pcie_enable_system_interrupts(struct dw_pcie_rp *pp)
|
|
|
|
val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base +
|
|
PCI_EXP_LNKSTA);
|
|
- pcie->init_link_width = (val_w & PCI_EXP_LNKSTA_NLW) >>
|
|
- PCI_EXP_LNKSTA_NLW_SHIFT;
|
|
+ pcie->init_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val_w);
|
|
|
|
val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base +
|
|
PCI_EXP_LNKCTL);
|
|
@@ -900,7 +899,7 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
|
|
/* Configure Max lane width from DT */
|
|
val = dw_pcie_readl_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP);
|
|
val &= ~PCI_EXP_LNKCAP_MLW;
|
|
- val |= (pcie->num_lanes << PCI_EXP_LNKSTA_NLW_SHIFT);
|
|
+ val |= FIELD_PREP(PCI_EXP_LNKCAP_MLW, pcie->num_lanes);
|
|
dw_pcie_writel_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP, val);
|
|
|
|
/* Clear Slot Clock Configuration bit if SRNS configuration */
|
|
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
|
|
index 1ced73726a267..668601fd0b296 100644
|
|
--- a/drivers/pci/controller/pci-mvebu.c
|
|
+++ b/drivers/pci/controller/pci-mvebu.c
|
|
@@ -264,7 +264,7 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
|
|
*/
|
|
lnkcap = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
|
|
lnkcap &= ~PCI_EXP_LNKCAP_MLW;
|
|
- lnkcap |= (port->is_x4 ? 4 : 1) << 4;
|
|
+ lnkcap |= FIELD_PREP(PCI_EXP_LNKCAP_MLW, port->is_x4 ? 4 : 1);
|
|
mvebu_writel(port, lnkcap, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP);
|
|
|
|
/* Disable Root Bridge I/O space, memory space and bus mastering. */
|
|
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
|
|
index 7aa1c20582ab8..2f5eddf03ac6a 100644
|
|
--- a/drivers/pci/pci-acpi.c
|
|
+++ b/drivers/pci/pci-acpi.c
|
|
@@ -911,7 +911,7 @@ pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
|
{
|
|
int acpi_state, d_max;
|
|
|
|
- if (pdev->no_d3cold)
|
|
+ if (pdev->no_d3cold || !pdev->d3cold_allowed)
|
|
d_max = ACPI_STATE_D3_HOT;
|
|
else
|
|
d_max = ACPI_STATE_D3_COLD;
|
|
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
|
|
index dd0d9d9bc5097..df1c44a5c886c 100644
|
|
--- a/drivers/pci/pci-sysfs.c
|
|
+++ b/drivers/pci/pci-sysfs.c
|
|
@@ -12,7 +12,7 @@
|
|
* Modeled after usb's driverfs.c
|
|
*/
|
|
|
|
-
|
|
+#include <linux/bitfield.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/pci.h>
|
|
@@ -230,8 +230,7 @@ static ssize_t current_link_width_show(struct device *dev,
|
|
if (err)
|
|
return -EINVAL;
|
|
|
|
- return sysfs_emit(buf, "%u\n",
|
|
- (linkstat & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT);
|
|
+ return sysfs_emit(buf, "%u\n", FIELD_GET(PCI_EXP_LNKSTA_NLW, linkstat));
|
|
}
|
|
static DEVICE_ATTR_RO(current_link_width);
|
|
|
|
@@ -530,10 +529,7 @@ static ssize_t d3cold_allowed_store(struct device *dev,
|
|
return -EINVAL;
|
|
|
|
pdev->d3cold_allowed = !!val;
|
|
- if (pdev->d3cold_allowed)
|
|
- pci_d3cold_enable(pdev);
|
|
- else
|
|
- pci_d3cold_disable(pdev);
|
|
+ pci_bridge_d3_update(pdev);
|
|
|
|
pm_runtime_resume(dev);
|
|
|
|
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
|
|
index 835e9ea14b3a1..8df156c28aade 100644
|
|
--- a/drivers/pci/pci.c
|
|
+++ b/drivers/pci/pci.c
|
|
@@ -717,15 +717,18 @@ u16 pci_find_vsec_capability(struct pci_dev *dev, u16 vendor, int cap)
|
|
{
|
|
u16 vsec = 0;
|
|
u32 header;
|
|
+ int ret;
|
|
|
|
if (vendor != dev->vendor)
|
|
return 0;
|
|
|
|
while ((vsec = pci_find_next_ext_capability(dev, vsec,
|
|
PCI_EXT_CAP_ID_VNDR))) {
|
|
- if (pci_read_config_dword(dev, vsec + PCI_VNDR_HEADER,
|
|
- &header) == PCIBIOS_SUCCESSFUL &&
|
|
- PCI_VNDR_HEADER_ID(header) == cap)
|
|
+ ret = pci_read_config_dword(dev, vsec + PCI_VNDR_HEADER, &header);
|
|
+ if (ret != PCIBIOS_SUCCESSFUL)
|
|
+ continue;
|
|
+
|
|
+ if (PCI_VNDR_HEADER_ID(header) == cap)
|
|
return vsec;
|
|
}
|
|
|
|
@@ -3710,14 +3713,14 @@ u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar)
|
|
return 0;
|
|
|
|
pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap);
|
|
- cap &= PCI_REBAR_CAP_SIZES;
|
|
+ cap = FIELD_GET(PCI_REBAR_CAP_SIZES, cap);
|
|
|
|
/* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */
|
|
if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f &&
|
|
- bar == 0 && cap == 0x7000)
|
|
- cap = 0x3f000;
|
|
+ bar == 0 && cap == 0x700)
|
|
+ return 0x3f00;
|
|
|
|
- return cap >> 4;
|
|
+ return cap;
|
|
}
|
|
EXPORT_SYMBOL(pci_rebar_get_possible_sizes);
|
|
|
|
@@ -6135,8 +6138,7 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
|
|
pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
|
|
|
|
next_speed = pcie_link_speed[lnksta & PCI_EXP_LNKSTA_CLS];
|
|
- next_width = (lnksta & PCI_EXP_LNKSTA_NLW) >>
|
|
- PCI_EXP_LNKSTA_NLW_SHIFT;
|
|
+ next_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
|
|
|
|
next_bw = next_width * PCIE_SPEED2MBS_ENC(next_speed);
|
|
|
|
@@ -6208,7 +6210,7 @@ enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev)
|
|
|
|
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
|
|
if (lnkcap)
|
|
- return (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4;
|
|
+ return FIELD_GET(PCI_EXP_LNKCAP_MLW, lnkcap);
|
|
|
|
return PCIE_LNK_WIDTH_UNKNOWN;
|
|
}
|
|
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
|
|
index 7e89cdbd446fc..5d1756f53ba84 100644
|
|
--- a/drivers/pci/pcie/aspm.c
|
|
+++ b/drivers/pci/pcie/aspm.c
|
|
@@ -1248,6 +1248,8 @@ static ssize_t aspm_attr_store_common(struct device *dev,
|
|
link->aspm_disable &= ~ASPM_STATE_L1;
|
|
} else {
|
|
link->aspm_disable |= state;
|
|
+ if (state & ASPM_STATE_L1)
|
|
+ link->aspm_disable |= ASPM_STATE_L1SS;
|
|
}
|
|
|
|
pcie_config_aspm_link(link, policy_to_aspm_state(link));
|
|
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
|
|
index 0945f50fe94ff..e19b79821dd6d 100644
|
|
--- a/drivers/pci/probe.c
|
|
+++ b/drivers/pci/probe.c
|
|
@@ -1643,15 +1643,15 @@ static void pci_set_removable(struct pci_dev *dev)
|
|
static bool pci_ext_cfg_is_aliased(struct pci_dev *dev)
|
|
{
|
|
#ifdef CONFIG_PCI_QUIRKS
|
|
- int pos;
|
|
+ int pos, ret;
|
|
u32 header, tmp;
|
|
|
|
pci_read_config_dword(dev, PCI_VENDOR_ID, &header);
|
|
|
|
for (pos = PCI_CFG_SPACE_SIZE;
|
|
pos < PCI_CFG_SPACE_EXP_SIZE; pos += PCI_CFG_SPACE_SIZE) {
|
|
- if (pci_read_config_dword(dev, pos, &tmp) != PCIBIOS_SUCCESSFUL
|
|
- || header != tmp)
|
|
+ ret = pci_read_config_dword(dev, pos, &tmp);
|
|
+ if ((ret != PCIBIOS_SUCCESSFUL) || (header != tmp))
|
|
return false;
|
|
}
|
|
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index 30e7c627f21a7..48389785d9247 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -5288,7 +5288,7 @@ int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
|
|
*/
|
|
static void quirk_intel_qat_vf_cap(struct pci_dev *pdev)
|
|
{
|
|
- int pos, i = 0;
|
|
+ int pos, i = 0, ret;
|
|
u8 next_cap;
|
|
u16 reg16, *cap;
|
|
struct pci_cap_saved_state *state;
|
|
@@ -5334,8 +5334,8 @@ static void quirk_intel_qat_vf_cap(struct pci_dev *pdev)
|
|
pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
|
|
|
|
pdev->cfg_size = PCI_CFG_SPACE_EXP_SIZE;
|
|
- if (pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &status) !=
|
|
- PCIBIOS_SUCCESSFUL || (status == 0xffffffff))
|
|
+ ret = pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &status);
|
|
+ if ((ret != PCIBIOS_SUCCESSFUL) || (PCI_POSSIBLE_ERROR(status)))
|
|
pdev->cfg_size = PCI_CFG_SPACE_SIZE;
|
|
|
|
if (pci_find_saved_cap(pdev, PCI_CAP_ID_EXP))
|
|
@@ -5404,6 +5404,12 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0420, quirk_no_ext_tags);
|
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0422, quirk_no_ext_tags);
|
|
|
|
#ifdef CONFIG_PCI_ATS
|
|
+static void quirk_no_ats(struct pci_dev *pdev)
|
|
+{
|
|
+ pci_info(pdev, "disabling ATS\n");
|
|
+ pdev->ats_cap = 0;
|
|
+}
|
|
+
|
|
/*
|
|
* Some devices require additional driver setup to enable ATS. Don't use
|
|
* ATS for those devices as ATS will be enabled before the driver has had a
|
|
@@ -5417,14 +5423,10 @@ static void quirk_amd_harvest_no_ats(struct pci_dev *pdev)
|
|
(pdev->subsystem_device == 0xce19 ||
|
|
pdev->subsystem_device == 0xcc10 ||
|
|
pdev->subsystem_device == 0xcc08))
|
|
- goto no_ats;
|
|
- else
|
|
- return;
|
|
+ quirk_no_ats(pdev);
|
|
+ } else {
|
|
+ quirk_no_ats(pdev);
|
|
}
|
|
-
|
|
-no_ats:
|
|
- pci_info(pdev, "disabling ATS\n");
|
|
- pdev->ats_cap = 0;
|
|
}
|
|
|
|
/* AMD Stoney platform GPU */
|
|
@@ -5447,6 +5449,25 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7347, quirk_amd_harvest_no_ats);
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x734f, quirk_amd_harvest_no_ats);
|
|
/* AMD Raven platform iGPU */
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x15d8, quirk_amd_harvest_no_ats);
|
|
+
|
|
+/*
|
|
+ * Intel IPU E2000 revisions before C0 implement incorrect endianness
|
|
+ * in ATS Invalidate Request message body. Disable ATS for those devices.
|
|
+ */
|
|
+static void quirk_intel_e2000_no_ats(struct pci_dev *pdev)
|
|
+{
|
|
+ if (pdev->revision < 0x20)
|
|
+ quirk_no_ats(pdev);
|
|
+}
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1451, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1452, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1453, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1454, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1455, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1457, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1459, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145a, quirk_intel_e2000_no_ats);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145c, quirk_intel_e2000_no_ats);
|
|
#endif /* CONFIG_PCI_ATS */
|
|
|
|
/* Freescale PCIe doesn't support MSI in RC mode */
|
|
diff --git a/drivers/platform/chrome/cros_ec_proto_test.c b/drivers/platform/chrome/cros_ec_proto_test.c
|
|
index c6a83df91ae1e..b46a8bc2196fe 100644
|
|
--- a/drivers/platform/chrome/cros_ec_proto_test.c
|
|
+++ b/drivers/platform/chrome/cros_ec_proto_test.c
|
|
@@ -2667,6 +2667,7 @@ static int cros_ec_proto_test_init(struct kunit *test)
|
|
ec_dev->dev->release = cros_ec_proto_test_release;
|
|
ec_dev->cmd_xfer = cros_kunit_ec_xfer_mock;
|
|
ec_dev->pkt_xfer = cros_kunit_ec_xfer_mock;
|
|
+ mutex_init(&ec_dev->lock);
|
|
|
|
priv->msg = (struct cros_ec_command *)priv->_msg;
|
|
|
|
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
|
|
index 3bb60687f2e42..05a55bc31c796 100644
|
|
--- a/drivers/platform/x86/thinkpad_acpi.c
|
|
+++ b/drivers/platform/x86/thinkpad_acpi.c
|
|
@@ -10019,6 +10019,7 @@ static const struct tpacpi_quirk battery_quirk_table[] __initconst = {
|
|
* Individual addressing is broken on models that expose the
|
|
* primary battery as BAT1.
|
|
*/
|
|
+ TPACPI_Q_LNV('8', 'F', true), /* Thinkpad X120e */
|
|
TPACPI_Q_LNV('J', '7', true), /* B5400 */
|
|
TPACPI_Q_LNV('J', 'I', true), /* Thinkpad 11e */
|
|
TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */
|
|
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
|
|
index af3bc65c4595d..9311f3d09c8fc 100644
|
|
--- a/drivers/ptp/ptp_chardev.c
|
|
+++ b/drivers/ptp/ptp_chardev.c
|
|
@@ -487,7 +487,8 @@ ssize_t ptp_read(struct posix_clock *pc,
|
|
|
|
for (i = 0; i < cnt; i++) {
|
|
event[i] = queue->buf[queue->head];
|
|
- queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
|
|
+ /* Paired with READ_ONCE() in queue_cnt() */
|
|
+ WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS);
|
|
}
|
|
|
|
spin_unlock_irqrestore(&queue->lock, flags);
|
|
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
|
|
index 51cae72bb6db2..3c3e4fbefebaf 100644
|
|
--- a/drivers/ptp/ptp_clock.c
|
|
+++ b/drivers/ptp/ptp_clock.c
|
|
@@ -56,10 +56,11 @@ static void enqueue_external_timestamp(struct timestamp_event_queue *queue,
|
|
dst->t.sec = seconds;
|
|
dst->t.nsec = remainder;
|
|
|
|
+ /* Both WRITE_ONCE() are paired with READ_ONCE() in queue_cnt() */
|
|
if (!queue_free(queue))
|
|
- queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
|
|
+ WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS);
|
|
|
|
- queue->tail = (queue->tail + 1) % PTP_MAX_TIMESTAMPS;
|
|
+ WRITE_ONCE(queue->tail, (queue->tail + 1) % PTP_MAX_TIMESTAMPS);
|
|
|
|
spin_unlock_irqrestore(&queue->lock, flags);
|
|
}
|
|
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
|
|
index 75f58fc468a71..b8d4f61f14be4 100644
|
|
--- a/drivers/ptp/ptp_private.h
|
|
+++ b/drivers/ptp/ptp_private.h
|
|
@@ -76,9 +76,13 @@ struct ptp_vclock {
|
|
* that a writer might concurrently increment the tail does not
|
|
* matter, since the queue remains nonempty nonetheless.
|
|
*/
|
|
-static inline int queue_cnt(struct timestamp_event_queue *q)
|
|
+static inline int queue_cnt(const struct timestamp_event_queue *q)
|
|
{
|
|
- int cnt = q->tail - q->head;
|
|
+ /*
|
|
+ * Paired with WRITE_ONCE() in enqueue_external_timestamp(),
|
|
+ * ptp_read(), extts_fifo_show().
|
|
+ */
|
|
+ int cnt = READ_ONCE(q->tail) - READ_ONCE(q->head);
|
|
return cnt < 0 ? PTP_MAX_TIMESTAMPS + cnt : cnt;
|
|
}
|
|
|
|
diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c
|
|
index f30b0a4394705..74b9c794d6363 100644
|
|
--- a/drivers/ptp/ptp_sysfs.c
|
|
+++ b/drivers/ptp/ptp_sysfs.c
|
|
@@ -79,7 +79,8 @@ static ssize_t extts_fifo_show(struct device *dev,
|
|
qcnt = queue_cnt(queue);
|
|
if (qcnt) {
|
|
event = queue->buf[queue->head];
|
|
- queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
|
|
+ /* Paired with READ_ONCE() in queue_cnt() */
|
|
+ WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS);
|
|
}
|
|
spin_unlock_irqrestore(&queue->lock, flags);
|
|
|
|
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
|
|
index b02c631f3b71a..4c0f9fe1ba779 100644
|
|
--- a/drivers/s390/crypto/ap_bus.c
|
|
+++ b/drivers/s390/crypto/ap_bus.c
|
|
@@ -1012,6 +1012,10 @@ EXPORT_SYMBOL(ap_driver_unregister);
|
|
|
|
void ap_bus_force_rescan(void)
|
|
{
|
|
+ /* Only trigger AP bus scans after the initial scan is done */
|
|
+ if (atomic64_read(&ap_scan_bus_count) <= 0)
|
|
+ return;
|
|
+
|
|
/* processing a asynchronous bus rescan */
|
|
del_timer(&ap_config_timer);
|
|
queue_work(system_long_wq, &ap_scan_work);
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
index c0e74d768716d..c4305ec38ebf3 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
|
|
@@ -4717,6 +4717,12 @@ 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_exit_v3_hw(struct hisi_hba *hisi_hba)
|
|
+{
|
|
+ debugfs_remove_recursive(hisi_hba->debugfs_dir);
|
|
+ hisi_hba->debugfs_dir = NULL;
|
|
+}
|
|
+
|
|
static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
{
|
|
struct device *dev = hisi_hba->dev;
|
|
@@ -4740,18 +4746,13 @@ static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba)
|
|
|
|
for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
|
|
if (debugfs_alloc_v3_hw(hisi_hba, i)) {
|
|
- debugfs_remove_recursive(hisi_hba->debugfs_dir);
|
|
+ debugfs_exit_v3_hw(hisi_hba);
|
|
dev_dbg(dev, "failed to init debugfs!\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
-static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba)
|
|
-{
|
|
- debugfs_remove_recursive(hisi_hba->debugfs_dir);
|
|
-}
|
|
-
|
|
static int
|
|
hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
{
|
|
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
|
|
index 41148b0430df9..013f5c05e9f39 100644
|
|
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
|
|
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
|
|
@@ -1518,7 +1518,11 @@ static struct ibmvfc_event *ibmvfc_get_event(struct ibmvfc_queue *queue)
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&queue->l_lock, flags);
|
|
- BUG_ON(list_empty(&queue->free));
|
|
+ if (list_empty(&queue->free)) {
|
|
+ ibmvfc_log(queue->vhost, 4, "empty event pool on queue:%ld\n", queue->hwq_id);
|
|
+ spin_unlock_irqrestore(&queue->l_lock, flags);
|
|
+ return NULL;
|
|
+ }
|
|
evt = list_entry(queue->free.next, struct ibmvfc_event, queue_list);
|
|
atomic_set(&evt->free, 0);
|
|
list_del(&evt->queue_list);
|
|
@@ -1947,9 +1951,15 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
|
|
if (vhost->using_channels) {
|
|
scsi_channel = hwq % vhost->scsi_scrqs.active_queues;
|
|
evt = ibmvfc_get_event(&vhost->scsi_scrqs.scrqs[scsi_channel]);
|
|
+ if (!evt)
|
|
+ return SCSI_MLQUEUE_HOST_BUSY;
|
|
+
|
|
evt->hwq = hwq % vhost->scsi_scrqs.active_queues;
|
|
- } else
|
|
+ } else {
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt)
|
|
+ return SCSI_MLQUEUE_HOST_BUSY;
|
|
+ }
|
|
|
|
ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT);
|
|
evt->cmnd = cmnd;
|
|
@@ -2037,6 +2047,11 @@ static int ibmvfc_bsg_timeout(struct bsg_job *job)
|
|
|
|
vhost->aborting_passthru = 1;
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
ibmvfc_init_event(evt, ibmvfc_bsg_timeout_done, IBMVFC_MAD_FORMAT);
|
|
|
|
tmf = &evt->iu.tmf;
|
|
@@ -2095,6 +2110,10 @@ static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id)
|
|
goto unlock_out;
|
|
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ rc = -ENOMEM;
|
|
+ goto unlock_out;
|
|
+ }
|
|
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
|
|
plogi = &evt->iu.plogi;
|
|
memset(plogi, 0, sizeof(*plogi));
|
|
@@ -2213,6 +2232,11 @@ static int ibmvfc_bsg_request(struct bsg_job *job)
|
|
}
|
|
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
|
+ rc = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
|
|
mad = &evt->iu.passthru;
|
|
|
|
@@ -2301,6 +2325,11 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
|
|
else
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
|
|
+ if (!evt) {
|
|
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
|
|
tmf = ibmvfc_init_vfc_cmd(evt, sdev);
|
|
iu = ibmvfc_get_fcp_iu(vhost, tmf);
|
|
@@ -2504,6 +2533,8 @@ static struct ibmvfc_event *ibmvfc_init_tmf(struct ibmvfc_queue *queue,
|
|
struct ibmvfc_tmf *tmf;
|
|
|
|
evt = ibmvfc_get_event(queue);
|
|
+ if (!evt)
|
|
+ return NULL;
|
|
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
|
|
|
|
tmf = &evt->iu.tmf;
|
|
@@ -2560,6 +2591,11 @@ static int ibmvfc_cancel_all_mq(struct scsi_device *sdev, int type)
|
|
|
|
if (found_evt && vhost->logged_in) {
|
|
evt = ibmvfc_init_tmf(&queues[i], sdev, type);
|
|
+ if (!evt) {
|
|
+ spin_unlock(queues[i].q_lock);
|
|
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
evt->sync_iu = &queues[i].cancel_rsp;
|
|
ibmvfc_send_event(evt, vhost, default_timeout);
|
|
list_add_tail(&evt->cancel, &cancelq);
|
|
@@ -2773,6 +2809,10 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
|
|
|
|
if (vhost->state == IBMVFC_ACTIVE) {
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
|
|
tmf = ibmvfc_init_vfc_cmd(evt, sdev);
|
|
iu = ibmvfc_get_fcp_iu(vhost, tmf);
|
|
@@ -4031,6 +4071,12 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt)
|
|
|
|
kref_get(&tgt->kref);
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
|
|
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
|
|
+ __ibmvfc_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
vhost->discovery_threads++;
|
|
ibmvfc_init_event(evt, ibmvfc_tgt_prli_done, IBMVFC_MAD_FORMAT);
|
|
evt->tgt = tgt;
|
|
@@ -4138,6 +4184,12 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt)
|
|
kref_get(&tgt->kref);
|
|
tgt->logo_rcvd = 0;
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
|
|
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
|
|
+ __ibmvfc_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
vhost->discovery_threads++;
|
|
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
|
|
ibmvfc_init_event(evt, ibmvfc_tgt_plogi_done, IBMVFC_MAD_FORMAT);
|
|
@@ -4214,6 +4266,8 @@ static struct ibmvfc_event *__ibmvfc_tgt_get_implicit_logout_evt(struct ibmvfc_t
|
|
|
|
kref_get(&tgt->kref);
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt)
|
|
+ return NULL;
|
|
ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT);
|
|
evt->tgt = tgt;
|
|
mad = &evt->iu.implicit_logout;
|
|
@@ -4241,6 +4295,13 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
|
|
vhost->discovery_threads++;
|
|
evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt,
|
|
ibmvfc_tgt_implicit_logout_done);
|
|
+ if (!evt) {
|
|
+ vhost->discovery_threads--;
|
|
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
|
|
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
|
|
+ __ibmvfc_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
|
|
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
|
|
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
|
|
@@ -4380,6 +4441,12 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt)
|
|
|
|
kref_get(&tgt->kref);
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
|
|
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
|
|
+ __ibmvfc_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
vhost->discovery_threads++;
|
|
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
|
|
ibmvfc_init_event(evt, ibmvfc_tgt_move_login_done, IBMVFC_MAD_FORMAT);
|
|
@@ -4546,6 +4613,14 @@ static void ibmvfc_adisc_timeout(struct timer_list *t)
|
|
vhost->abort_threads++;
|
|
kref_get(&tgt->kref);
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ tgt_err(tgt, "Failed to get cancel event for ADISC.\n");
|
|
+ vhost->abort_threads--;
|
|
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
|
|
+ __ibmvfc_reset_host(vhost);
|
|
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
|
+ return;
|
|
+ }
|
|
ibmvfc_init_event(evt, ibmvfc_tgt_adisc_cancel_done, IBMVFC_MAD_FORMAT);
|
|
|
|
evt->tgt = tgt;
|
|
@@ -4596,6 +4671,12 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
|
|
|
|
kref_get(&tgt->kref);
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
|
|
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
|
|
+ __ibmvfc_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
vhost->discovery_threads++;
|
|
ibmvfc_init_event(evt, ibmvfc_tgt_adisc_done, IBMVFC_MAD_FORMAT);
|
|
evt->tgt = tgt;
|
|
@@ -4699,6 +4780,12 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt)
|
|
|
|
kref_get(&tgt->kref);
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
|
|
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
|
|
+ __ibmvfc_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
vhost->discovery_threads++;
|
|
evt->tgt = tgt;
|
|
ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT);
|
|
@@ -4871,6 +4958,13 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost)
|
|
{
|
|
struct ibmvfc_discover_targets *mad;
|
|
struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
|
|
+ int level = IBMVFC_DEFAULT_LOG_LEVEL;
|
|
+
|
|
+ if (!evt) {
|
|
+ ibmvfc_log(vhost, level, "Discover Targets failed: no available events\n");
|
|
+ ibmvfc_hard_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
|
|
ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT);
|
|
mad = &evt->iu.discover_targets;
|
|
@@ -4948,8 +5042,15 @@ static void ibmvfc_channel_setup(struct ibmvfc_host *vhost)
|
|
struct ibmvfc_scsi_channels *scrqs = &vhost->scsi_scrqs;
|
|
unsigned int num_channels =
|
|
min(vhost->client_scsi_channels, vhost->max_vios_scsi_channels);
|
|
+ int level = IBMVFC_DEFAULT_LOG_LEVEL;
|
|
int i;
|
|
|
|
+ if (!evt) {
|
|
+ ibmvfc_log(vhost, level, "Channel Setup failed: no available events\n");
|
|
+ ibmvfc_hard_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
+
|
|
memset(setup_buf, 0, sizeof(*setup_buf));
|
|
if (num_channels == 0)
|
|
setup_buf->flags = cpu_to_be32(IBMVFC_CANCEL_CHANNELS);
|
|
@@ -5011,6 +5112,13 @@ static void ibmvfc_channel_enquiry(struct ibmvfc_host *vhost)
|
|
{
|
|
struct ibmvfc_channel_enquiry *mad;
|
|
struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
|
|
+ int level = IBMVFC_DEFAULT_LOG_LEVEL;
|
|
+
|
|
+ if (!evt) {
|
|
+ ibmvfc_log(vhost, level, "Channel Enquiry failed: no available events\n");
|
|
+ ibmvfc_hard_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
|
|
ibmvfc_init_event(evt, ibmvfc_channel_enquiry_done, IBMVFC_MAD_FORMAT);
|
|
mad = &evt->iu.channel_enquiry;
|
|
@@ -5133,6 +5241,12 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
|
|
struct ibmvfc_npiv_login_mad *mad;
|
|
struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
|
|
|
|
+ if (!evt) {
|
|
+ ibmvfc_dbg(vhost, "NPIV Login failed: no available events\n");
|
|
+ ibmvfc_hard_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
+
|
|
ibmvfc_gather_partition_info(vhost);
|
|
ibmvfc_set_login_info(vhost);
|
|
ibmvfc_init_event(evt, ibmvfc_npiv_login_done, IBMVFC_MAD_FORMAT);
|
|
@@ -5197,6 +5311,12 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost)
|
|
struct ibmvfc_event *evt;
|
|
|
|
evt = ibmvfc_get_event(&vhost->crq);
|
|
+ if (!evt) {
|
|
+ ibmvfc_dbg(vhost, "NPIV Logout failed: no available events\n");
|
|
+ ibmvfc_hard_reset_host(vhost);
|
|
+ return;
|
|
+ }
|
|
+
|
|
ibmvfc_init_event(evt, ibmvfc_npiv_logout_done, IBMVFC_MAD_FORMAT);
|
|
|
|
mad = &evt->iu.npiv_logout;
|
|
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
|
|
index 9c02c9523c4d4..ab06e9aeb613e 100644
|
|
--- a/drivers/scsi/libfc/fc_lport.c
|
|
+++ b/drivers/scsi/libfc/fc_lport.c
|
|
@@ -241,6 +241,12 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
|
|
}
|
|
mutex_lock(&lport->disc.disc_mutex);
|
|
lport->ptp_rdata = fc_rport_create(lport, remote_fid);
|
|
+ if (!lport->ptp_rdata) {
|
|
+ printk(KERN_WARNING "libfc: Failed to setup lport 0x%x\n",
|
|
+ lport->port_id);
|
|
+ mutex_unlock(&lport->disc.disc_mutex);
|
|
+ return;
|
|
+ }
|
|
kref_get(&lport->ptp_rdata->kref);
|
|
lport->ptp_rdata->ids.port_name = remote_wwpn;
|
|
lport->ptp_rdata->ids.node_name = remote_wwnn;
|
|
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
index e392a984c7b87..37208bc08c667 100644
|
|
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
|
|
@@ -263,13 +263,13 @@ u32 megasas_readl(struct megasas_instance *instance,
|
|
* Fusion registers could intermittently return all zeroes.
|
|
* This behavior is transient in nature and subsequent reads will
|
|
* return valid value. As a workaround in driver, retry readl for
|
|
- * upto three times until a non-zero value is read.
|
|
+ * up to thirty times until a non-zero value is read.
|
|
*/
|
|
if (instance->adapter_type == AERO_SERIES) {
|
|
do {
|
|
ret_val = readl(addr);
|
|
i++;
|
|
- } while (ret_val == 0 && i < 3);
|
|
+ } while (ret_val == 0 && i < 30);
|
|
return ret_val;
|
|
} else {
|
|
return readl(addr);
|
|
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
index 2093888f154e0..809be43f440dc 100644
|
|
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
|
|
@@ -224,8 +224,8 @@ _base_readl_ext_retry(const volatile void __iomem *addr)
|
|
|
|
for (i = 0 ; i < 30 ; i++) {
|
|
ret_val = readl(addr);
|
|
- if (ret_val == 0)
|
|
- continue;
|
|
+ if (ret_val != 0)
|
|
+ break;
|
|
}
|
|
|
|
return ret_val;
|
|
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
|
|
index b33ffec1cb75e..25ca0544b9639 100644
|
|
--- a/drivers/scsi/qla2xxx/qla_os.c
|
|
+++ b/drivers/scsi/qla2xxx/qla_os.c
|
|
@@ -1831,8 +1831,16 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res,
|
|
}
|
|
|
|
spin_lock_irqsave(qp->qp_lock_ptr, *flags);
|
|
- if (ret_cmd && blk_mq_request_started(scsi_cmd_to_rq(cmd)))
|
|
- sp->done(sp, res);
|
|
+ switch (sp->type) {
|
|
+ case SRB_SCSI_CMD:
|
|
+ if (ret_cmd && blk_mq_request_started(scsi_cmd_to_rq(cmd)))
|
|
+ sp->done(sp, res);
|
|
+ break;
|
|
+ default:
|
|
+ if (ret_cmd)
|
|
+ sp->done(sp, res);
|
|
+ break;
|
|
+ }
|
|
} else {
|
|
sp->done(sp, res);
|
|
}
|
|
diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c
|
|
index 5bcd047768b60..cbcd1298ef5bd 100644
|
|
--- a/drivers/soc/bcm/bcm2835-power.c
|
|
+++ b/drivers/soc/bcm/bcm2835-power.c
|
|
@@ -175,7 +175,7 @@ static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable
|
|
}
|
|
writel(PM_PASSWORD | val, base + reg);
|
|
|
|
- while (readl(base + reg) & ASB_ACK) {
|
|
+ while (!!(readl(base + reg) & ASB_ACK) == enable) {
|
|
cpu_relax();
|
|
if (ktime_get_ns() - start >= 1000)
|
|
return -ETIMEDOUT;
|
|
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
|
|
index 90a8b2c0676ff..419ed15cc10c4 100644
|
|
--- a/drivers/soc/imx/gpc.c
|
|
+++ b/drivers/soc/imx/gpc.c
|
|
@@ -498,6 +498,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
|
|
|
|
pd_pdev->dev.parent = &pdev->dev;
|
|
pd_pdev->dev.of_node = np;
|
|
+ pd_pdev->dev.fwnode = of_fwnode_handle(np);
|
|
|
|
ret = platform_device_add(pd_pdev);
|
|
if (ret) {
|
|
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
|
|
index 2a1096dab63d3..9ebdd0cd0b1cf 100644
|
|
--- a/drivers/soundwire/dmi-quirks.c
|
|
+++ b/drivers/soundwire/dmi-quirks.c
|
|
@@ -141,7 +141,7 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
|
|
{
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"),
|
|
},
|
|
.driver_data = (void *)hp_omen_16,
|
|
},
|
|
diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c
|
|
index 8c2ee431fcde8..4ab3803e10c83 100644
|
|
--- a/drivers/thunderbolt/quirks.c
|
|
+++ b/drivers/thunderbolt/quirks.c
|
|
@@ -30,6 +30,9 @@ static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw)
|
|
{
|
|
struct tb_port *port;
|
|
|
|
+ if (tb_switch_is_icm(sw))
|
|
+ return;
|
|
+
|
|
tb_switch_for_each_port(sw, port) {
|
|
if (!tb_port_is_usb3_down(port))
|
|
continue;
|
|
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
|
|
index d9d0232753286..281bc83acfadd 100644
|
|
--- a/drivers/tty/hvc/hvc_xen.c
|
|
+++ b/drivers/tty/hvc/hvc_xen.c
|
|
@@ -377,18 +377,21 @@ void xen_console_resume(void)
|
|
#ifdef CONFIG_HVC_XEN_FRONTEND
|
|
static void xencons_disconnect_backend(struct xencons_info *info)
|
|
{
|
|
- if (info->irq > 0)
|
|
- unbind_from_irqhandler(info->irq, NULL);
|
|
- info->irq = 0;
|
|
+ if (info->hvc != NULL)
|
|
+ hvc_remove(info->hvc);
|
|
+ info->hvc = NULL;
|
|
+ if (info->irq > 0) {
|
|
+ evtchn_put(info->evtchn);
|
|
+ info->irq = 0;
|
|
+ info->evtchn = 0;
|
|
+ }
|
|
+ /* evtchn_put() will also close it so this is only an error path */
|
|
if (info->evtchn > 0)
|
|
xenbus_free_evtchn(info->xbdev, info->evtchn);
|
|
info->evtchn = 0;
|
|
if (info->gntref > 0)
|
|
gnttab_free_grant_references(info->gntref);
|
|
info->gntref = 0;
|
|
- if (info->hvc != NULL)
|
|
- hvc_remove(info->hvc);
|
|
- info->hvc = NULL;
|
|
}
|
|
|
|
static void xencons_free(struct xencons_info *info)
|
|
@@ -433,7 +436,7 @@ static int xencons_connect_backend(struct xenbus_device *dev,
|
|
if (ret)
|
|
return ret;
|
|
info->evtchn = evtchn;
|
|
- irq = bind_interdomain_evtchn_to_irq_lateeoi(dev, evtchn);
|
|
+ irq = bind_evtchn_to_irq_lateeoi(evtchn);
|
|
if (irq < 0)
|
|
return irq;
|
|
info->irq = irq;
|
|
@@ -553,10 +556,23 @@ static void xencons_backend_changed(struct xenbus_device *dev,
|
|
if (dev->state == XenbusStateClosed)
|
|
break;
|
|
fallthrough; /* Missed the backend's CLOSING state */
|
|
- case XenbusStateClosing:
|
|
+ case XenbusStateClosing: {
|
|
+ struct xencons_info *info = dev_get_drvdata(&dev->dev);;
|
|
+
|
|
+ /*
|
|
+ * Don't tear down the evtchn and grant ref before the other
|
|
+ * end has disconnected, but do stop userspace from trying
|
|
+ * to use the device before we allow the backend to close.
|
|
+ */
|
|
+ if (info->hvc) {
|
|
+ hvc_remove(info->hvc);
|
|
+ info->hvc = NULL;
|
|
+ }
|
|
+
|
|
xenbus_frontend_closed(dev);
|
|
break;
|
|
}
|
|
+ }
|
|
}
|
|
|
|
static const struct xenbus_device_id xencons_ids[] = {
|
|
@@ -588,7 +604,7 @@ static int __init xen_hvc_init(void)
|
|
ops = &dom0_hvc_ops;
|
|
r = xen_initial_domain_console_init();
|
|
if (r < 0)
|
|
- return r;
|
|
+ goto register_fe;
|
|
info = vtermno_to_xencons(HVC_COOKIE);
|
|
} else {
|
|
ops = &domU_hvc_ops;
|
|
@@ -597,7 +613,7 @@ static int __init xen_hvc_init(void)
|
|
else
|
|
r = xen_pv_console_init();
|
|
if (r < 0)
|
|
- return r;
|
|
+ goto register_fe;
|
|
|
|
info = vtermno_to_xencons(HVC_COOKIE);
|
|
info->irq = bind_evtchn_to_irq_lateeoi(info->evtchn);
|
|
@@ -616,12 +632,13 @@ static int __init xen_hvc_init(void)
|
|
list_del(&info->list);
|
|
spin_unlock_irqrestore(&xencons_lock, flags);
|
|
if (info->irq)
|
|
- unbind_from_irqhandler(info->irq, NULL);
|
|
+ evtchn_put(info->evtchn);
|
|
kfree(info);
|
|
return r;
|
|
}
|
|
|
|
r = 0;
|
|
+ register_fe:
|
|
#ifdef CONFIG_HVC_XEN_FRONTEND
|
|
r = xenbus_register_frontend(&xencons_driver);
|
|
#endif
|
|
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
|
|
index 056243c12836c..8f6d54c04b9ba 100644
|
|
--- a/drivers/tty/serial/meson_uart.c
|
|
+++ b/drivers/tty/serial/meson_uart.c
|
|
@@ -380,10 +380,14 @@ static void meson_uart_set_termios(struct uart_port *port,
|
|
else
|
|
val |= AML_UART_STOP_BIT_1SB;
|
|
|
|
- if (cflags & CRTSCTS)
|
|
- val &= ~AML_UART_TWO_WIRE_EN;
|
|
- else
|
|
+ if (cflags & CRTSCTS) {
|
|
+ if (port->flags & UPF_HARD_FLOW)
|
|
+ val &= ~AML_UART_TWO_WIRE_EN;
|
|
+ else
|
|
+ termios->c_cflag &= ~CRTSCTS;
|
|
+ } else {
|
|
val |= AML_UART_TWO_WIRE_EN;
|
|
+ }
|
|
|
|
writel(val, port->membase + AML_UART_CONTROL);
|
|
|
|
@@ -698,6 +702,7 @@ static int meson_uart_probe(struct platform_device *pdev)
|
|
u32 fifosize = 64; /* Default is 64, 128 for EE UART_0 */
|
|
int ret = 0;
|
|
int irq;
|
|
+ bool has_rtscts;
|
|
|
|
if (pdev->dev.of_node)
|
|
pdev->id = of_alias_get_id(pdev->dev.of_node, "serial");
|
|
@@ -725,6 +730,7 @@ static int meson_uart_probe(struct platform_device *pdev)
|
|
return irq;
|
|
|
|
of_property_read_u32(pdev->dev.of_node, "fifo-size", &fifosize);
|
|
+ has_rtscts = of_property_read_bool(pdev->dev.of_node, "uart-has-rtscts");
|
|
|
|
if (meson_ports[pdev->id]) {
|
|
dev_err(&pdev->dev, "port %d already allocated\n", pdev->id);
|
|
@@ -744,6 +750,8 @@ static int meson_uart_probe(struct platform_device *pdev)
|
|
port->mapsize = resource_size(res_mem);
|
|
port->irq = irq;
|
|
port->flags = UPF_BOOT_AUTOCONF | UPF_LOW_LATENCY;
|
|
+ if (has_rtscts)
|
|
+ port->flags |= UPF_HARD_FLOW;
|
|
port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MESON_CONSOLE);
|
|
port->dev = &pdev->dev;
|
|
port->line = pdev->id;
|
|
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
|
|
index d2b2720db6ca7..248067197287a 100644
|
|
--- a/drivers/tty/sysrq.c
|
|
+++ b/drivers/tty/sysrq.c
|
|
@@ -263,13 +263,14 @@ static void sysrq_handle_showallcpus(int key)
|
|
if (in_hardirq())
|
|
regs = get_irq_regs();
|
|
|
|
- pr_info("CPU%d:\n", smp_processor_id());
|
|
+ pr_info("CPU%d:\n", get_cpu());
|
|
if (regs)
|
|
show_regs(regs);
|
|
else
|
|
show_stack(NULL, NULL, KERN_INFO);
|
|
|
|
schedule_work(&sysrq_showallcpus);
|
|
+ put_cpu();
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/tty/vcc.c b/drivers/tty/vcc.c
|
|
index 34ba6e54789a7..b8b832c75b856 100644
|
|
--- a/drivers/tty/vcc.c
|
|
+++ b/drivers/tty/vcc.c
|
|
@@ -579,18 +579,22 @@ static int vcc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|
return -ENOMEM;
|
|
|
|
name = kstrdup(dev_name(&vdev->dev), GFP_KERNEL);
|
|
+ if (!name) {
|
|
+ rv = -ENOMEM;
|
|
+ goto free_port;
|
|
+ }
|
|
|
|
rv = vio_driver_init(&port->vio, vdev, VDEV_CONSOLE_CON, vcc_versions,
|
|
ARRAY_SIZE(vcc_versions), NULL, name);
|
|
if (rv)
|
|
- goto free_port;
|
|
+ goto free_name;
|
|
|
|
port->vio.debug = vcc_dbg_vio;
|
|
vcc_ldc_cfg.debug = vcc_dbg_ldc;
|
|
|
|
rv = vio_ldc_alloc(&port->vio, &vcc_ldc_cfg, port);
|
|
if (rv)
|
|
- goto free_port;
|
|
+ goto free_name;
|
|
|
|
spin_lock_init(&port->lock);
|
|
|
|
@@ -624,6 +628,11 @@ static int vcc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|
goto unreg_tty;
|
|
}
|
|
port->domain = kstrdup(domain, GFP_KERNEL);
|
|
+ if (!port->domain) {
|
|
+ rv = -ENOMEM;
|
|
+ goto unreg_tty;
|
|
+ }
|
|
+
|
|
|
|
mdesc_release(hp);
|
|
|
|
@@ -653,8 +662,9 @@ free_table:
|
|
vcc_table_remove(port->index);
|
|
free_ldc:
|
|
vio_ldc_free(&port->vio);
|
|
-free_port:
|
|
+free_name:
|
|
kfree(name);
|
|
+free_port:
|
|
kfree(port);
|
|
|
|
return rv;
|
|
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
|
|
index 57e2f4cc744f7..a811db88eedae 100644
|
|
--- a/drivers/usb/dwc3/core.c
|
|
+++ b/drivers/usb/dwc3/core.c
|
|
@@ -1111,6 +1111,111 @@ static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc)
|
|
}
|
|
}
|
|
|
|
+static void dwc3_config_threshold(struct dwc3 *dwc)
|
|
+{
|
|
+ u32 reg;
|
|
+ u8 rx_thr_num;
|
|
+ u8 rx_maxburst;
|
|
+ u8 tx_thr_num;
|
|
+ u8 tx_maxburst;
|
|
+
|
|
+ /*
|
|
+ * Must config both number of packets and max burst settings to enable
|
|
+ * RX and/or TX threshold.
|
|
+ */
|
|
+ if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) {
|
|
+ rx_thr_num = dwc->rx_thr_num_pkt_prd;
|
|
+ rx_maxburst = dwc->rx_max_burst_prd;
|
|
+ tx_thr_num = dwc->tx_thr_num_pkt_prd;
|
|
+ tx_maxburst = dwc->tx_max_burst_prd;
|
|
+
|
|
+ if (rx_thr_num && rx_maxburst) {
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
|
|
+ reg |= DWC31_RXTHRNUMPKTSEL_PRD;
|
|
+
|
|
+ reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
|
|
+ reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num);
|
|
+
|
|
+ reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
|
|
+ reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
|
|
+
|
|
+ dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
|
|
+ }
|
|
+
|
|
+ if (tx_thr_num && tx_maxburst) {
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
|
|
+ reg |= DWC31_TXTHRNUMPKTSEL_PRD;
|
|
+
|
|
+ reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
|
|
+ reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num);
|
|
+
|
|
+ reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
|
|
+ reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
|
|
+
|
|
+ dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ rx_thr_num = dwc->rx_thr_num_pkt;
|
|
+ rx_maxburst = dwc->rx_max_burst;
|
|
+ tx_thr_num = dwc->tx_thr_num_pkt;
|
|
+ tx_maxburst = dwc->tx_max_burst;
|
|
+
|
|
+ if (DWC3_IP_IS(DWC3)) {
|
|
+ if (rx_thr_num && rx_maxburst) {
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
|
|
+ reg |= DWC3_GRXTHRCFG_PKTCNTSEL;
|
|
+
|
|
+ reg &= ~DWC3_GRXTHRCFG_RXPKTCNT(~0);
|
|
+ reg |= DWC3_GRXTHRCFG_RXPKTCNT(rx_thr_num);
|
|
+
|
|
+ reg &= ~DWC3_GRXTHRCFG_MAXRXBURSTSIZE(~0);
|
|
+ reg |= DWC3_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
|
|
+
|
|
+ dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
|
|
+ }
|
|
+
|
|
+ if (tx_thr_num && tx_maxburst) {
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
|
|
+ reg |= DWC3_GTXTHRCFG_PKTCNTSEL;
|
|
+
|
|
+ reg &= ~DWC3_GTXTHRCFG_TXPKTCNT(~0);
|
|
+ reg |= DWC3_GTXTHRCFG_TXPKTCNT(tx_thr_num);
|
|
+
|
|
+ reg &= ~DWC3_GTXTHRCFG_MAXTXBURSTSIZE(~0);
|
|
+ reg |= DWC3_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
|
|
+
|
|
+ dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
|
|
+ }
|
|
+ } else {
|
|
+ if (rx_thr_num && rx_maxburst) {
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
|
|
+ reg |= DWC31_GRXTHRCFG_PKTCNTSEL;
|
|
+
|
|
+ reg &= ~DWC31_GRXTHRCFG_RXPKTCNT(~0);
|
|
+ reg |= DWC31_GRXTHRCFG_RXPKTCNT(rx_thr_num);
|
|
+
|
|
+ reg &= ~DWC31_GRXTHRCFG_MAXRXBURSTSIZE(~0);
|
|
+ reg |= DWC31_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
|
|
+
|
|
+ dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
|
|
+ }
|
|
+
|
|
+ if (tx_thr_num && tx_maxburst) {
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
|
|
+ reg |= DWC31_GTXTHRCFG_PKTCNTSEL;
|
|
+
|
|
+ reg &= ~DWC31_GTXTHRCFG_TXPKTCNT(~0);
|
|
+ reg |= DWC31_GTXTHRCFG_TXPKTCNT(tx_thr_num);
|
|
+
|
|
+ reg &= ~DWC31_GTXTHRCFG_MAXTXBURSTSIZE(~0);
|
|
+ reg |= DWC31_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
|
|
+
|
|
+ dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
/**
|
|
* dwc3_core_init - Low-level initialization of DWC3 Core
|
|
* @dwc: Pointer to our controller context structure
|
|
@@ -1278,42 +1383,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
|
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
|
|
}
|
|
|
|
- /*
|
|
- * Must config both number of packets and max burst settings to enable
|
|
- * RX and/or TX threshold.
|
|
- */
|
|
- if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) {
|
|
- u8 rx_thr_num = dwc->rx_thr_num_pkt_prd;
|
|
- u8 rx_maxburst = dwc->rx_max_burst_prd;
|
|
- u8 tx_thr_num = dwc->tx_thr_num_pkt_prd;
|
|
- u8 tx_maxburst = dwc->tx_max_burst_prd;
|
|
-
|
|
- if (rx_thr_num && rx_maxburst) {
|
|
- reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
|
|
- reg |= DWC31_RXTHRNUMPKTSEL_PRD;
|
|
-
|
|
- reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
|
|
- reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num);
|
|
-
|
|
- reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
|
|
- reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
|
|
-
|
|
- dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
|
|
- }
|
|
-
|
|
- if (tx_thr_num && tx_maxburst) {
|
|
- reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
|
|
- reg |= DWC31_TXTHRNUMPKTSEL_PRD;
|
|
-
|
|
- reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
|
|
- reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num);
|
|
-
|
|
- reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
|
|
- reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
|
|
-
|
|
- dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
|
|
- }
|
|
- }
|
|
+ dwc3_config_threshold(dwc);
|
|
|
|
return 0;
|
|
|
|
@@ -1462,6 +1532,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
|
|
u8 lpm_nyet_threshold;
|
|
u8 tx_de_emphasis;
|
|
u8 hird_threshold;
|
|
+ u8 rx_thr_num_pkt = 0;
|
|
+ u8 rx_max_burst = 0;
|
|
+ u8 tx_thr_num_pkt = 0;
|
|
+ u8 tx_max_burst = 0;
|
|
u8 rx_thr_num_pkt_prd = 0;
|
|
u8 rx_max_burst_prd = 0;
|
|
u8 tx_thr_num_pkt_prd = 0;
|
|
@@ -1524,6 +1598,14 @@ static void dwc3_get_properties(struct dwc3 *dwc)
|
|
"snps,usb2-lpm-disable");
|
|
dwc->usb2_gadget_lpm_disable = device_property_read_bool(dev,
|
|
"snps,usb2-gadget-lpm-disable");
|
|
+ device_property_read_u8(dev, "snps,rx-thr-num-pkt",
|
|
+ &rx_thr_num_pkt);
|
|
+ device_property_read_u8(dev, "snps,rx-max-burst",
|
|
+ &rx_max_burst);
|
|
+ device_property_read_u8(dev, "snps,tx-thr-num-pkt",
|
|
+ &tx_thr_num_pkt);
|
|
+ device_property_read_u8(dev, "snps,tx-max-burst",
|
|
+ &tx_max_burst);
|
|
device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd",
|
|
&rx_thr_num_pkt_prd);
|
|
device_property_read_u8(dev, "snps,rx-max-burst-prd",
|
|
@@ -1601,6 +1683,12 @@ static void dwc3_get_properties(struct dwc3 *dwc)
|
|
|
|
dwc->hird_threshold = hird_threshold;
|
|
|
|
+ dwc->rx_thr_num_pkt = rx_thr_num_pkt;
|
|
+ dwc->rx_max_burst = rx_max_burst;
|
|
+
|
|
+ dwc->tx_thr_num_pkt = tx_thr_num_pkt;
|
|
+ dwc->tx_max_burst = tx_max_burst;
|
|
+
|
|
dwc->rx_thr_num_pkt_prd = rx_thr_num_pkt_prd;
|
|
dwc->rx_max_burst_prd = rx_max_burst_prd;
|
|
|
|
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
|
|
index 80cc532ba9d55..889c122dad457 100644
|
|
--- a/drivers/usb/dwc3/core.h
|
|
+++ b/drivers/usb/dwc3/core.h
|
|
@@ -209,6 +209,11 @@
|
|
#define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24)
|
|
#define DWC3_GRXTHRCFG_PKTCNTSEL BIT(29)
|
|
|
|
+/* Global TX Threshold Configuration Register */
|
|
+#define DWC3_GTXTHRCFG_MAXTXBURSTSIZE(n) (((n) & 0xff) << 16)
|
|
+#define DWC3_GTXTHRCFG_TXPKTCNT(n) (((n) & 0xf) << 24)
|
|
+#define DWC3_GTXTHRCFG_PKTCNTSEL BIT(29)
|
|
+
|
|
/* Global RX Threshold Configuration Register for DWC_usb31 only */
|
|
#define DWC31_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 16)
|
|
#define DWC31_GRXTHRCFG_RXPKTCNT(n) (((n) & 0x1f) << 21)
|
|
@@ -1041,6 +1046,10 @@ struct dwc3_scratchpad_array {
|
|
* @test_mode_nr: test feature selector
|
|
* @lpm_nyet_threshold: LPM NYET response threshold
|
|
* @hird_threshold: HIRD threshold
|
|
+ * @rx_thr_num_pkt: USB receive packet count
|
|
+ * @rx_max_burst: max USB receive burst size
|
|
+ * @tx_thr_num_pkt: USB transmit packet count
|
|
+ * @tx_max_burst: max USB transmit burst size
|
|
* @rx_thr_num_pkt_prd: periodic ESS receive packet count
|
|
* @rx_max_burst_prd: max periodic ESS receive burst size
|
|
* @tx_thr_num_pkt_prd: periodic ESS transmit packet count
|
|
@@ -1268,6 +1277,10 @@ struct dwc3 {
|
|
u8 test_mode_nr;
|
|
u8 lpm_nyet_threshold;
|
|
u8 hird_threshold;
|
|
+ u8 rx_thr_num_pkt;
|
|
+ u8 rx_max_burst;
|
|
+ u8 tx_thr_num_pkt;
|
|
+ u8 tx_max_burst;
|
|
u8 rx_thr_num_pkt_prd;
|
|
u8 rx_max_burst_prd;
|
|
u8 tx_thr_num_pkt_prd;
|
|
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
|
|
index faf90a2174194..bbb6ff6b11aa1 100644
|
|
--- a/drivers/usb/gadget/function/f_ncm.c
|
|
+++ b/drivers/usb/gadget/function/f_ncm.c
|
|
@@ -1425,7 +1425,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
|
|
struct usb_composite_dev *cdev = c->cdev;
|
|
struct f_ncm *ncm = func_to_ncm(f);
|
|
struct usb_string *us;
|
|
- int status;
|
|
+ int status = 0;
|
|
struct usb_ep *ep;
|
|
struct f_ncm_opts *ncm_opts;
|
|
|
|
@@ -1443,22 +1443,17 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
|
|
f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc;
|
|
}
|
|
|
|
- /*
|
|
- * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
|
|
- * configurations are bound in sequence with list_for_each_entry,
|
|
- * in each configuration its functions are bound in sequence
|
|
- * with list_for_each_entry, so we assume no race condition
|
|
- * with regard to ncm_opts->bound access
|
|
- */
|
|
- if (!ncm_opts->bound) {
|
|
- mutex_lock(&ncm_opts->lock);
|
|
- gether_set_gadget(ncm_opts->net, cdev->gadget);
|
|
+ mutex_lock(&ncm_opts->lock);
|
|
+ gether_set_gadget(ncm_opts->net, cdev->gadget);
|
|
+ if (!ncm_opts->bound)
|
|
status = gether_register_netdev(ncm_opts->net);
|
|
- mutex_unlock(&ncm_opts->lock);
|
|
- if (status)
|
|
- goto fail;
|
|
- ncm_opts->bound = true;
|
|
- }
|
|
+ mutex_unlock(&ncm_opts->lock);
|
|
+
|
|
+ if (status)
|
|
+ goto fail;
|
|
+
|
|
+ ncm_opts->bound = true;
|
|
+
|
|
us = usb_gstrings_attach(cdev, ncm_strings,
|
|
ARRAY_SIZE(ncm_string_defs));
|
|
if (IS_ERR(us)) {
|
|
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
|
|
index c4dd648710ae0..24bcf6ab12d8a 100644
|
|
--- a/drivers/usb/host/xhci-pci.c
|
|
+++ b/drivers/usb/host/xhci-pci.c
|
|
@@ -508,7 +508,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|
/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
|
|
pm_runtime_put_noidle(&dev->dev);
|
|
|
|
- if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
|
|
+ if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
|
|
+ pm_runtime_forbid(&dev->dev);
|
|
+ else if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
|
|
pm_runtime_allow(&dev->dev);
|
|
|
|
dma_set_max_seg_size(&dev->dev, UINT_MAX);
|
|
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
|
|
index 31a156669a531..c8374527a27d9 100644
|
|
--- a/drivers/vhost/vdpa.c
|
|
+++ b/drivers/vhost/vdpa.c
|
|
@@ -1427,7 +1427,6 @@ static int vhost_vdpa_probe(struct vdpa_device *vdpa)
|
|
|
|
err:
|
|
put_device(&v->dev);
|
|
- ida_simple_remove(&vhost_vdpa_ida, v->minor);
|
|
return r;
|
|
}
|
|
|
|
diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
|
|
index 63862803421f1..7bf28545b47a0 100644
|
|
--- a/drivers/watchdog/sbsa_gwdt.c
|
|
+++ b/drivers/watchdog/sbsa_gwdt.c
|
|
@@ -153,14 +153,14 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
|
|
timeout = clamp_t(unsigned int, timeout, 1, wdd->max_hw_heartbeat_ms / 1000);
|
|
|
|
if (action)
|
|
- sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt);
|
|
+ sbsa_gwdt_reg_write((u64)gwdt->clk * timeout, gwdt);
|
|
else
|
|
/*
|
|
* In the single stage mode, The first signal (WS0) is ignored,
|
|
* the timeout is (WOR * 2), so the WOR should be configured
|
|
* to half value of timeout.
|
|
*/
|
|
- sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt);
|
|
+ sbsa_gwdt_reg_write(((u64)gwdt->clk / 2) * timeout, gwdt);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
|
|
index 80b46de14f413..af9115d648092 100644
|
|
--- a/drivers/xen/events/events_base.c
|
|
+++ b/drivers/xen/events/events_base.c
|
|
@@ -600,7 +600,9 @@ static void lateeoi_list_add(struct irq_info *info)
|
|
|
|
spin_lock_irqsave(&eoi->eoi_list_lock, flags);
|
|
|
|
- if (list_empty(&eoi->eoi_list)) {
|
|
+ elem = list_first_entry_or_null(&eoi->eoi_list, struct irq_info,
|
|
+ eoi_list);
|
|
+ if (!elem || info->eoi_time < elem->eoi_time) {
|
|
list_add(&info->eoi_list, &eoi->eoi_list);
|
|
mod_delayed_work_on(info->eoi_cpu, system_wq,
|
|
&eoi->delayed, delay);
|
|
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
|
|
index 2807bb63f7802..3b9aa61de8c2d 100644
|
|
--- a/fs/9p/xattr.c
|
|
+++ b/fs/9p/xattr.c
|
|
@@ -65,7 +65,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
|
|
struct p9_fid *fid;
|
|
int ret;
|
|
|
|
- p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu\n",
|
|
+ p9_debug(P9_DEBUG_VFS, "name = '%s' value_len = %zu\n",
|
|
name, buffer_size);
|
|
fid = v9fs_fid_lookup(dentry);
|
|
if (IS_ERR(fid))
|
|
@@ -136,7 +136,8 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
|
|
|
|
ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
|
{
|
|
- return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
|
|
+ /* Txattrwalk with an empty string lists xattrs instead */
|
|
+ return v9fs_xattr_get(dentry, "", buffer, buffer_size);
|
|
}
|
|
|
|
static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
|
|
diff --git a/fs/btrfs/delalloc-space.c b/fs/btrfs/delalloc-space.c
|
|
index 118b2e20b2e19..0b62ce77053f5 100644
|
|
--- a/fs/btrfs/delalloc-space.c
|
|
+++ b/fs/btrfs/delalloc-space.c
|
|
@@ -320,9 +320,6 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
|
|
} else {
|
|
if (current->journal_info)
|
|
flush = BTRFS_RESERVE_FLUSH_LIMIT;
|
|
-
|
|
- if (btrfs_transaction_in_commit(fs_info))
|
|
- schedule_timeout(1);
|
|
}
|
|
|
|
num_bytes = ALIGN(num_bytes, fs_info->sectorsize);
|
|
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
|
index 4063447217f92..81eac121c6b23 100644
|
|
--- a/fs/btrfs/inode.c
|
|
+++ b/fs/btrfs/inode.c
|
|
@@ -7166,8 +7166,15 @@ static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode,
|
|
int ret;
|
|
|
|
alloc_hint = get_extent_allocation_hint(inode, start, len);
|
|
+again:
|
|
ret = btrfs_reserve_extent(root, len, len, fs_info->sectorsize,
|
|
0, alloc_hint, &ins, 1, 1);
|
|
+ if (ret == -EAGAIN) {
|
|
+ ASSERT(btrfs_is_zoned(fs_info));
|
|
+ wait_on_bit_io(&inode->root->fs_info->flags, BTRFS_FS_NEED_ZONE_FINISH,
|
|
+ TASK_UNINTERRUPTIBLE);
|
|
+ goto again;
|
|
+ }
|
|
if (ret)
|
|
return ERR_PTR(ret);
|
|
|
|
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
|
|
index 90b0477911449..30e97c51f0e14 100644
|
|
--- a/fs/exfat/namei.c
|
|
+++ b/fs/exfat/namei.c
|
|
@@ -338,14 +338,20 @@ static int exfat_find_empty_entry(struct inode *inode,
|
|
if (exfat_check_max_dentries(inode))
|
|
return -ENOSPC;
|
|
|
|
- /* we trust p_dir->size regardless of FAT type */
|
|
- if (exfat_find_last_cluster(sb, p_dir, &last_clu))
|
|
- return -EIO;
|
|
-
|
|
/*
|
|
* Allocate new cluster to this directory
|
|
*/
|
|
- exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags);
|
|
+ if (ei->start_clu != EXFAT_EOF_CLUSTER) {
|
|
+ /* we trust p_dir->size regardless of FAT type */
|
|
+ if (exfat_find_last_cluster(sb, p_dir, &last_clu))
|
|
+ return -EIO;
|
|
+
|
|
+ exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags);
|
|
+ } else {
|
|
+ /* This directory is empty */
|
|
+ exfat_chain_set(&clu, EXFAT_EOF_CLUSTER, 0,
|
|
+ ALLOC_NO_FAT_CHAIN);
|
|
+ }
|
|
|
|
/* allocate a cluster */
|
|
ret = exfat_alloc_cluster(inode, 1, &clu, IS_DIRSYNC(inode));
|
|
@@ -355,6 +361,11 @@ static int exfat_find_empty_entry(struct inode *inode,
|
|
if (exfat_zeroed_cluster(inode, clu.dir))
|
|
return -EIO;
|
|
|
|
+ if (ei->start_clu == EXFAT_EOF_CLUSTER) {
|
|
+ ei->start_clu = clu.dir;
|
|
+ p_dir->dir = clu.dir;
|
|
+ }
|
|
+
|
|
/* append to the FAT chain */
|
|
if (clu.flags != p_dir->flags) {
|
|
/* no-fat-chain bit is disabled,
|
|
@@ -644,7 +655,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
|
|
info->type = exfat_get_entry_type(ep);
|
|
info->attr = le16_to_cpu(ep->dentry.file.attr);
|
|
info->size = le64_to_cpu(ep2->dentry.stream.valid_size);
|
|
- if ((info->type == TYPE_FILE) && (info->size == 0)) {
|
|
+ if (info->size == 0) {
|
|
info->flags = ALLOC_NO_FAT_CHAIN;
|
|
info->start_clu = EXFAT_EOF_CLUSTER;
|
|
} else {
|
|
@@ -888,6 +899,9 @@ static int exfat_check_dir_empty(struct super_block *sb,
|
|
|
|
dentries_per_clu = sbi->dentries_per_clu;
|
|
|
|
+ if (p_dir->dir == EXFAT_EOF_CLUSTER)
|
|
+ return 0;
|
|
+
|
|
exfat_chain_dup(&clu, p_dir);
|
|
|
|
while (clu.dir != EXFAT_EOF_CLUSTER) {
|
|
@@ -1262,7 +1276,8 @@ static int __exfat_rename(struct inode *old_parent_inode,
|
|
}
|
|
|
|
/* Free the clusters if new_inode is a dir(as if exfat_rmdir) */
|
|
- if (new_entry_type == TYPE_DIR) {
|
|
+ if (new_entry_type == TYPE_DIR &&
|
|
+ new_ei->start_clu != EXFAT_EOF_CLUSTER) {
|
|
/* new_ei, new_clu_to_free */
|
|
struct exfat_chain new_clu_to_free;
|
|
|
|
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
|
|
index 3219669732bf4..0db6ae0ca9369 100644
|
|
--- a/fs/ext4/acl.h
|
|
+++ b/fs/ext4/acl.h
|
|
@@ -68,6 +68,11 @@ extern int ext4_init_acl(handle_t *, struct inode *, struct inode *);
|
|
static inline int
|
|
ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
|
|
{
|
|
+ /* usually, the umask is applied by posix_acl_create(), but if
|
|
+ ext4 ACL support is disabled at compile time, we need to do
|
|
+ it here, because posix_acl_create() will never be called */
|
|
+ inode->i_mode &= ~current_umask();
|
|
+
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_EXT4_FS_POSIX_ACL */
|
|
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
|
|
index 44e83521bfded..b57e497679ef9 100644
|
|
--- a/fs/ext4/extents_status.c
|
|
+++ b/fs/ext4/extents_status.c
|
|
@@ -1365,8 +1365,8 @@ retry:
|
|
}
|
|
}
|
|
if (count_reserved)
|
|
- count_rsvd(inode, lblk, orig_es.es_len - len1 - len2,
|
|
- &orig_es, &rc);
|
|
+ count_rsvd(inode, orig_es.es_lblk + len1,
|
|
+ orig_es.es_len - len1 - len2, &orig_es, &rc);
|
|
goto out_get_reserved;
|
|
}
|
|
|
|
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
|
|
index a7a597c727e63..8ebe4dc7b0170 100644
|
|
--- a/fs/ext4/file.c
|
|
+++ b/fs/ext4/file.c
|
|
@@ -296,80 +296,38 @@ out:
|
|
}
|
|
|
|
static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
|
|
- ssize_t written, size_t count)
|
|
+ ssize_t count)
|
|
{
|
|
handle_t *handle;
|
|
- bool truncate = false;
|
|
- u8 blkbits = inode->i_blkbits;
|
|
- ext4_lblk_t written_blk, end_blk;
|
|
- int ret;
|
|
-
|
|
- /*
|
|
- * Note that EXT4_I(inode)->i_disksize can get extended up to
|
|
- * inode->i_size while the I/O was running due to writeback of delalloc
|
|
- * blocks. But, the code in ext4_iomap_alloc() is careful to use
|
|
- * zeroed/unwritten extents if this is possible; thus we won't leave
|
|
- * uninitialized blocks in a file even if we didn't succeed in writing
|
|
- * as much as we intended.
|
|
- */
|
|
- WARN_ON_ONCE(i_size_read(inode) < EXT4_I(inode)->i_disksize);
|
|
- if (offset + count <= EXT4_I(inode)->i_disksize) {
|
|
- /*
|
|
- * We need to ensure that the inode is removed from the orphan
|
|
- * list if it has been added prematurely, due to writeback of
|
|
- * delalloc blocks.
|
|
- */
|
|
- if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
|
|
- handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
|
|
-
|
|
- if (IS_ERR(handle)) {
|
|
- ext4_orphan_del(NULL, inode);
|
|
- return PTR_ERR(handle);
|
|
- }
|
|
-
|
|
- ext4_orphan_del(handle, inode);
|
|
- ext4_journal_stop(handle);
|
|
- }
|
|
-
|
|
- return written;
|
|
- }
|
|
-
|
|
- if (written < 0)
|
|
- goto truncate;
|
|
|
|
+ lockdep_assert_held_write(&inode->i_rwsem);
|
|
handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
|
|
- if (IS_ERR(handle)) {
|
|
- written = PTR_ERR(handle);
|
|
- goto truncate;
|
|
- }
|
|
+ if (IS_ERR(handle))
|
|
+ return PTR_ERR(handle);
|
|
|
|
- if (ext4_update_inode_size(inode, offset + written)) {
|
|
- ret = ext4_mark_inode_dirty(handle, inode);
|
|
+ if (ext4_update_inode_size(inode, offset + count)) {
|
|
+ int ret = ext4_mark_inode_dirty(handle, inode);
|
|
if (unlikely(ret)) {
|
|
- written = ret;
|
|
ext4_journal_stop(handle);
|
|
- goto truncate;
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
- /*
|
|
- * We may need to truncate allocated but not written blocks beyond EOF.
|
|
- */
|
|
- written_blk = ALIGN(offset + written, 1 << blkbits);
|
|
- end_blk = ALIGN(offset + count, 1 << blkbits);
|
|
- if (written_blk < end_blk && ext4_can_truncate(inode))
|
|
- truncate = true;
|
|
-
|
|
- /*
|
|
- * Remove the inode from the orphan list if it has been extended and
|
|
- * everything went OK.
|
|
- */
|
|
- if (!truncate && inode->i_nlink)
|
|
+ if (inode->i_nlink)
|
|
ext4_orphan_del(handle, inode);
|
|
ext4_journal_stop(handle);
|
|
|
|
- if (truncate) {
|
|
-truncate:
|
|
+ return count;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Clean up the inode after DIO or DAX extending write has completed and the
|
|
+ * inode size has been updated using ext4_handle_inode_extension().
|
|
+ */
|
|
+static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
|
|
+{
|
|
+ lockdep_assert_held_write(&inode->i_rwsem);
|
|
+ if (count < 0) {
|
|
ext4_truncate_failed_write(inode);
|
|
/*
|
|
* If the truncate operation failed early, then the inode may
|
|
@@ -378,9 +336,28 @@ truncate:
|
|
*/
|
|
if (inode->i_nlink)
|
|
ext4_orphan_del(NULL, inode);
|
|
+ return;
|
|
}
|
|
+ /*
|
|
+ * If i_disksize got extended due to writeback of delalloc blocks while
|
|
+ * the DIO was running we could fail to cleanup the orphan list in
|
|
+ * ext4_handle_inode_extension(). Do it now.
|
|
+ */
|
|
+ if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
|
|
+ handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
|
|
|
|
- return written;
|
|
+ if (IS_ERR(handle)) {
|
|
+ /*
|
|
+ * The write has successfully completed. Not much to
|
|
+ * do with the error here so just cleanup the orphan
|
|
+ * list and hope for the best.
|
|
+ */
|
|
+ ext4_orphan_del(NULL, inode);
|
|
+ return;
|
|
+ }
|
|
+ ext4_orphan_del(handle, inode);
|
|
+ ext4_journal_stop(handle);
|
|
+ }
|
|
}
|
|
|
|
static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
|
|
@@ -389,31 +366,22 @@ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
|
|
loff_t pos = iocb->ki_pos;
|
|
struct inode *inode = file_inode(iocb->ki_filp);
|
|
|
|
+ if (!error && size && flags & IOMAP_DIO_UNWRITTEN)
|
|
+ error = ext4_convert_unwritten_extents(NULL, inode, pos, size);
|
|
if (error)
|
|
return error;
|
|
-
|
|
- if (size && flags & IOMAP_DIO_UNWRITTEN) {
|
|
- error = ext4_convert_unwritten_extents(NULL, inode, pos, size);
|
|
- if (error < 0)
|
|
- return error;
|
|
- }
|
|
/*
|
|
- * If we are extending the file, we have to update i_size here before
|
|
- * page cache gets invalidated in iomap_dio_rw(). Otherwise racing
|
|
- * buffered reads could zero out too much from page cache pages. Update
|
|
- * of on-disk size will happen later in ext4_dio_write_iter() where
|
|
- * we have enough information to also perform orphan list handling etc.
|
|
- * Note that we perform all extending writes synchronously under
|
|
- * i_rwsem held exclusively so i_size update is safe here in that case.
|
|
- * If the write was not extending, we cannot see pos > i_size here
|
|
- * because operations reducing i_size like truncate wait for all
|
|
- * outstanding DIO before updating i_size.
|
|
+ * Note that EXT4_I(inode)->i_disksize can get extended up to
|
|
+ * inode->i_size while the I/O was running due to writeback of delalloc
|
|
+ * blocks. But the code in ext4_iomap_alloc() is careful to use
|
|
+ * zeroed/unwritten extents if this is possible; thus we won't leave
|
|
+ * uninitialized blocks in a file even if we didn't succeed in writing
|
|
+ * as much as we intended.
|
|
*/
|
|
- pos += size;
|
|
- if (pos > i_size_read(inode))
|
|
- i_size_write(inode, pos);
|
|
-
|
|
- return 0;
|
|
+ WARN_ON_ONCE(i_size_read(inode) < READ_ONCE(EXT4_I(inode)->i_disksize));
|
|
+ if (pos + size <= READ_ONCE(EXT4_I(inode)->i_disksize))
|
|
+ return size;
|
|
+ return ext4_handle_inode_extension(inode, pos, size);
|
|
}
|
|
|
|
static const struct iomap_dio_ops ext4_dio_write_ops = {
|
|
@@ -589,9 +557,16 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
|
NULL, 0);
|
|
if (ret == -ENOTBLK)
|
|
ret = 0;
|
|
-
|
|
- if (extend)
|
|
- ret = ext4_handle_inode_extension(inode, offset, ret, count);
|
|
+ if (extend) {
|
|
+ /*
|
|
+ * We always perform extending DIO write synchronously so by
|
|
+ * now the IO is completed and ext4_handle_inode_extension()
|
|
+ * was called. Cleanup the inode in case of error or race with
|
|
+ * writeback of delalloc blocks.
|
|
+ */
|
|
+ WARN_ON_ONCE(ret == -EIOCBQUEUED);
|
|
+ ext4_inode_extension_cleanup(inode, ret);
|
|
+ }
|
|
|
|
out:
|
|
if (ilock_shared)
|
|
@@ -672,8 +647,10 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
|
|
|
ret = dax_iomap_rw(iocb, from, &ext4_iomap_ops);
|
|
|
|
- if (extend)
|
|
- ret = ext4_handle_inode_extension(inode, offset, ret, count);
|
|
+ if (extend) {
|
|
+ ret = ext4_handle_inode_extension(inode, offset, ret);
|
|
+ ext4_inode_extension_cleanup(inode, ret);
|
|
+ }
|
|
out:
|
|
inode_unlock(inode);
|
|
if (ret > 0)
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index 5aa3003cfc688..2479508deab3b 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -824,10 +824,22 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
|
|
int ext4_get_block_unwritten(struct inode *inode, sector_t iblock,
|
|
struct buffer_head *bh_result, int create)
|
|
{
|
|
+ int ret = 0;
|
|
+
|
|
ext4_debug("ext4_get_block_unwritten: inode %lu, create flag %d\n",
|
|
inode->i_ino, create);
|
|
- return _ext4_get_block(inode, iblock, bh_result,
|
|
+ ret = _ext4_get_block(inode, iblock, bh_result,
|
|
EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT);
|
|
+
|
|
+ /*
|
|
+ * If the buffer is marked unwritten, mark it as new to make sure it is
|
|
+ * zeroed out correctly in case of partial writes. Otherwise, there is
|
|
+ * a chance of stale data getting exposed.
|
|
+ */
|
|
+ if (ret == 0 && buffer_unwritten(bh_result))
|
|
+ set_buffer_new(bh_result);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
/* Maximum number of blocks we map for direct IO at once. */
|
|
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
|
|
index b493233750ab2..9833ab6db117c 100644
|
|
--- a/fs/ext4/resize.c
|
|
+++ b/fs/ext4/resize.c
|
|
@@ -560,13 +560,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
|
|
if (meta_bg == 0 && !ext4_bg_has_super(sb, group))
|
|
goto handle_itb;
|
|
|
|
- if (meta_bg == 1) {
|
|
- ext4_group_t first_group;
|
|
- first_group = ext4_meta_bg_first_group(sb, group);
|
|
- if (first_group != group + 1 &&
|
|
- first_group != group + EXT4_DESC_PER_BLOCK(sb) - 1)
|
|
- goto handle_itb;
|
|
- }
|
|
+ if (meta_bg == 1)
|
|
+ goto handle_itb;
|
|
|
|
block = start + ext4_bg_has_super(sb, group);
|
|
/* Copy all of the GDT blocks into the backup in this group */
|
|
@@ -1191,8 +1186,10 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
|
|
ext4_group_first_block_no(sb, group));
|
|
BUFFER_TRACE(bh, "get_write_access");
|
|
if ((err = ext4_journal_get_write_access(handle, sb, bh,
|
|
- EXT4_JTR_NONE)))
|
|
+ EXT4_JTR_NONE))) {
|
|
+ brelse(bh);
|
|
break;
|
|
+ }
|
|
lock_buffer(bh);
|
|
memcpy(bh->b_data, data, size);
|
|
if (rest)
|
|
@@ -1602,6 +1599,8 @@ exit_journal:
|
|
int gdb_num_end = ((group + flex_gd->count - 1) /
|
|
EXT4_DESC_PER_BLOCK(sb));
|
|
int meta_bg = ext4_has_feature_meta_bg(sb);
|
|
+ sector_t padding_blocks = meta_bg ? 0 : sbi->s_sbh->b_blocknr -
|
|
+ ext4_group_first_block_no(sb, 0);
|
|
sector_t old_gdb = 0;
|
|
|
|
update_backups(sb, ext4_group_first_block_no(sb, 0),
|
|
@@ -1613,8 +1612,8 @@ exit_journal:
|
|
gdb_num);
|
|
if (old_gdb == gdb_bh->b_blocknr)
|
|
continue;
|
|
- update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,
|
|
- gdb_bh->b_size, meta_bg);
|
|
+ update_backups(sb, gdb_bh->b_blocknr - padding_blocks,
|
|
+ gdb_bh->b_data, gdb_bh->b_size, meta_bg);
|
|
old_gdb = gdb_bh->b_blocknr;
|
|
}
|
|
}
|
|
@@ -1983,9 +1982,7 @@ static int ext4_convert_meta_bg(struct super_block *sb, struct inode *inode)
|
|
|
|
errout:
|
|
ret = ext4_journal_stop(handle);
|
|
- if (!err)
|
|
- err = ret;
|
|
- return ret;
|
|
+ return err ? err : ret;
|
|
|
|
invalid_resize_inode:
|
|
ext4_error(sb, "corrupted/inconsistent resize inode");
|
|
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
|
|
index fb75ff7b3448d..11d9dce994dbe 100644
|
|
--- a/fs/f2fs/compress.c
|
|
+++ b/fs/f2fs/compress.c
|
|
@@ -1983,7 +1983,7 @@ void f2fs_destroy_compress_inode(struct f2fs_sb_info *sbi)
|
|
int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi)
|
|
{
|
|
dev_t dev = sbi->sb->s_bdev->bd_dev;
|
|
- char slab_name[32];
|
|
+ char slab_name[35];
|
|
|
|
if (!f2fs_sb_has_compression(sbi))
|
|
return 0;
|
|
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
|
|
index a010b4bc36d2c..6efccd7ccfe1b 100644
|
|
--- a/fs/f2fs/node.c
|
|
+++ b/fs/f2fs/node.c
|
|
@@ -1455,7 +1455,8 @@ page_hit:
|
|
ofs_of_node(page), cpver_of_node(page),
|
|
next_blkaddr_of_node(page));
|
|
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
|
- err = -EINVAL;
|
|
+ f2fs_handle_error(sbi, ERROR_INCONSISTENT_FOOTER);
|
|
+ err = -EFSCORRUPTED;
|
|
out_err:
|
|
ClearPageUptodate(page);
|
|
out_put_err:
|
|
@@ -2737,7 +2738,9 @@ recover_xnid:
|
|
f2fs_update_inode_page(inode);
|
|
|
|
/* 3: update and set xattr node page dirty */
|
|
- memcpy(F2FS_NODE(xpage), F2FS_NODE(page), VALID_XATTR_BLOCK_SIZE);
|
|
+ if (page)
|
|
+ memcpy(F2FS_NODE(xpage), F2FS_NODE(page),
|
|
+ VALID_XATTR_BLOCK_SIZE);
|
|
|
|
set_page_dirty(xpage);
|
|
f2fs_put_page(xpage, 1);
|
|
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
|
|
index db3b641f2158c..adaad16468d8a 100644
|
|
--- a/fs/f2fs/xattr.c
|
|
+++ b/fs/f2fs/xattr.c
|
|
@@ -363,10 +363,10 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage,
|
|
|
|
*xe = __find_xattr(cur_addr, last_txattr_addr, NULL, index, len, name);
|
|
if (!*xe) {
|
|
- f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
|
|
+ f2fs_err(F2FS_I_SB(inode), "lookup inode (%lu) has corrupted xattr",
|
|
inode->i_ino);
|
|
set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
|
|
- err = -EFSCORRUPTED;
|
|
+ err = -ENODATA;
|
|
f2fs_handle_error(F2FS_I_SB(inode),
|
|
ERROR_CORRUPTED_XATTR);
|
|
goto out;
|
|
@@ -583,13 +583,12 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
|
|
|
if ((void *)(entry) + sizeof(__u32) > last_base_addr ||
|
|
(void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) {
|
|
- f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
|
|
+ f2fs_err(F2FS_I_SB(inode), "list inode (%lu) has corrupted xattr",
|
|
inode->i_ino);
|
|
set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
|
|
- error = -EFSCORRUPTED;
|
|
f2fs_handle_error(F2FS_I_SB(inode),
|
|
ERROR_CORRUPTED_XATTR);
|
|
- goto cleanup;
|
|
+ break;
|
|
}
|
|
|
|
if (!handler || (handler->list && !handler->list(dentry)))
|
|
@@ -650,7 +649,7 @@ static int __f2fs_setxattr(struct inode *inode, int index,
|
|
|
|
if (size > MAX_VALUE_LEN(inode))
|
|
return -E2BIG;
|
|
-
|
|
+retry:
|
|
error = read_all_xattrs(inode, ipage, &base_addr);
|
|
if (error)
|
|
return error;
|
|
@@ -660,7 +659,14 @@ static int __f2fs_setxattr(struct inode *inode, int index,
|
|
/* find entry with wanted name. */
|
|
here = __find_xattr(base_addr, last_base_addr, NULL, index, len, name);
|
|
if (!here) {
|
|
- f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
|
|
+ if (!F2FS_I(inode)->i_xattr_nid) {
|
|
+ f2fs_notice(F2FS_I_SB(inode),
|
|
+ "recover xattr in inode (%lu)", inode->i_ino);
|
|
+ f2fs_recover_xattr_data(inode, NULL);
|
|
+ kfree(base_addr);
|
|
+ goto retry;
|
|
+ }
|
|
+ f2fs_err(F2FS_I_SB(inode), "set inode (%lu) has corrupted xattr",
|
|
inode->i_ino);
|
|
set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
|
|
error = -EFSCORRUPTED;
|
|
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
|
|
index 04a201584fa7c..23e6962cdd6e3 100644
|
|
--- a/fs/gfs2/inode.c
|
|
+++ b/fs/gfs2/inode.c
|
|
@@ -1845,16 +1845,24 @@ out:
|
|
int gfs2_permission(struct user_namespace *mnt_userns, struct inode *inode,
|
|
int mask)
|
|
{
|
|
+ int may_not_block = mask & MAY_NOT_BLOCK;
|
|
struct gfs2_inode *ip;
|
|
struct gfs2_holder i_gh;
|
|
+ struct gfs2_glock *gl;
|
|
int error;
|
|
|
|
gfs2_holder_mark_uninitialized(&i_gh);
|
|
ip = GFS2_I(inode);
|
|
- if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
|
|
- if (mask & MAY_NOT_BLOCK)
|
|
+ gl = rcu_dereference_check(ip->i_gl, !may_not_block);
|
|
+ if (unlikely(!gl)) {
|
|
+ /* inode is getting torn down, must be RCU mode */
|
|
+ WARN_ON_ONCE(!may_not_block);
|
|
+ return -ECHILD;
|
|
+ }
|
|
+ if (gfs2_glock_is_locked_by_me(gl) == NULL) {
|
|
+ if (may_not_block)
|
|
return -ECHILD;
|
|
- error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
|
|
+ error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
|
|
if (error)
|
|
return error;
|
|
}
|
|
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
|
|
index 1ed17226d9ede..86bc73bd770b4 100644
|
|
--- a/fs/gfs2/quota.c
|
|
+++ b/fs/gfs2/quota.c
|
|
@@ -438,6 +438,17 @@ static int qd_check_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd,
|
|
(sync_gen && (qd->qd_sync_gen >= *sync_gen)))
|
|
return 0;
|
|
|
|
+ /*
|
|
+ * If qd_change is 0 it means a pending quota change was negated.
|
|
+ * We should not sync it, but we still have a qd reference and slot
|
|
+ * reference taken by gfs2_quota_change -> do_qc that need to be put.
|
|
+ */
|
|
+ if (!qd->qd_change && test_and_clear_bit(QDF_CHANGE, &qd->qd_flags)) {
|
|
+ slot_put(qd);
|
|
+ qd_put(qd);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
if (!lockref_get_not_dead(&qd->qd_lockref))
|
|
return 0;
|
|
|
|
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
|
|
index 44c564f0bc622..302d1e43d7012 100644
|
|
--- a/fs/gfs2/super.c
|
|
+++ b/fs/gfs2/super.c
|
|
@@ -1435,7 +1435,7 @@ out:
|
|
wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE);
|
|
gfs2_glock_add_to_lru(ip->i_gl);
|
|
gfs2_glock_put_eventually(ip->i_gl);
|
|
- ip->i_gl = NULL;
|
|
+ rcu_assign_pointer(ip->i_gl, NULL);
|
|
}
|
|
}
|
|
|
|
diff --git a/fs/inode.c b/fs/inode.c
|
|
index 6ae760db13116..73ad1b0d47758 100644
|
|
--- a/fs/inode.c
|
|
+++ b/fs/inode.c
|
|
@@ -2501,6 +2501,22 @@ struct timespec64 current_time(struct inode *inode)
|
|
}
|
|
EXPORT_SYMBOL(current_time);
|
|
|
|
+/**
|
|
+ * inode_set_ctime_current - set the ctime to current_time
|
|
+ * @inode: inode
|
|
+ *
|
|
+ * Set the inode->i_ctime to the current value for the inode. Returns
|
|
+ * the current value that was assigned to i_ctime.
|
|
+ */
|
|
+struct timespec64 inode_set_ctime_current(struct inode *inode)
|
|
+{
|
|
+ struct timespec64 now = current_time(inode);
|
|
+
|
|
+ inode_set_ctime(inode, now.tv_sec, now.tv_nsec);
|
|
+ return now;
|
|
+}
|
|
+EXPORT_SYMBOL(inode_set_ctime_current);
|
|
+
|
|
/**
|
|
* in_group_or_capable - check whether caller is CAP_FSETID privileged
|
|
* @mnt_userns: user namespace of the mount @inode was found from
|
|
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
|
|
index 357a3f7632e39..2426b89f1576f 100644
|
|
--- a/fs/jbd2/recovery.c
|
|
+++ b/fs/jbd2/recovery.c
|
|
@@ -288,6 +288,8 @@ int jbd2_journal_recover(journal_t *journal)
|
|
journal_superblock_t * sb;
|
|
|
|
struct recovery_info info;
|
|
+ errseq_t wb_err;
|
|
+ struct address_space *mapping;
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
sb = journal->j_superblock;
|
|
@@ -305,6 +307,9 @@ int jbd2_journal_recover(journal_t *journal)
|
|
return 0;
|
|
}
|
|
|
|
+ wb_err = 0;
|
|
+ mapping = journal->j_fs_dev->bd_inode->i_mapping;
|
|
+ errseq_check_and_advance(&mapping->wb_err, &wb_err);
|
|
err = do_one_pass(journal, &info, PASS_SCAN);
|
|
if (!err)
|
|
err = do_one_pass(journal, &info, PASS_REVOKE);
|
|
@@ -323,6 +328,9 @@ int jbd2_journal_recover(journal_t *journal)
|
|
|
|
jbd2_journal_clear_revoke(journal);
|
|
err2 = sync_blockdev(journal->j_fs_dev);
|
|
+ if (!err)
|
|
+ err = err2;
|
|
+ err2 = errseq_check_and_advance(&mapping->wb_err, &wb_err);
|
|
if (!err)
|
|
err = err2;
|
|
/* Make sure all replayed data is on permanent storage */
|
|
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
|
|
index e9d075cbd71ad..4d56f6081a5d2 100644
|
|
--- a/fs/jfs/jfs_dmap.c
|
|
+++ b/fs/jfs/jfs_dmap.c
|
|
@@ -87,7 +87,7 @@ static int dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno,
|
|
static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks);
|
|
static int dbFindBits(u32 word, int l2nb);
|
|
static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno);
|
|
-static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx);
|
|
+static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl);
|
|
static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
int nblocks);
|
|
static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
|
|
@@ -180,7 +180,8 @@ int dbMount(struct inode *ipbmap)
|
|
bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
|
|
|
|
bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
|
|
- if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE) {
|
|
+ if (bmp->db_l2nbperpage > L2PSIZE - L2MINBLOCKSIZE ||
|
|
+ bmp->db_l2nbperpage < 0) {
|
|
err = -EINVAL;
|
|
goto err_release_metapage;
|
|
}
|
|
@@ -194,6 +195,12 @@ int dbMount(struct inode *ipbmap)
|
|
bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel);
|
|
bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag);
|
|
bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref);
|
|
+ if (bmp->db_maxag >= MAXAG || bmp->db_maxag < 0 ||
|
|
+ bmp->db_agpref >= MAXAG || bmp->db_agpref < 0) {
|
|
+ err = -EINVAL;
|
|
+ goto err_release_metapage;
|
|
+ }
|
|
+
|
|
bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel);
|
|
bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight);
|
|
bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth);
|
|
@@ -1710,7 +1717,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
|
|
* dbFindLeaf() returns the index of the leaf at which
|
|
* free space was found.
|
|
*/
|
|
- rc = dbFindLeaf((dmtree_t *) dcp, l2nb, &leafidx);
|
|
+ rc = dbFindLeaf((dmtree_t *) dcp, l2nb, &leafidx, true);
|
|
|
|
/* release the buffer.
|
|
*/
|
|
@@ -1957,7 +1964,7 @@ dbAllocDmapLev(struct bmap * bmp,
|
|
* free space. if sufficient free space is found, dbFindLeaf()
|
|
* returns the index of the leaf at which free space was found.
|
|
*/
|
|
- if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx))
|
|
+ if (dbFindLeaf((dmtree_t *) &dp->tree, l2nb, &leafidx, false))
|
|
return -ENOSPC;
|
|
|
|
if (leafidx < 0)
|
|
@@ -2921,14 +2928,18 @@ static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
|
|
* leafidx - return pointer to be set to the index of the leaf
|
|
* describing at least l2nb free blocks if sufficient
|
|
* free blocks are found.
|
|
+ * is_ctl - determines if the tree is of type ctl
|
|
*
|
|
* RETURN VALUES:
|
|
* 0 - success
|
|
* -ENOSPC - insufficient free blocks.
|
|
*/
|
|
-static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
|
|
+static int dbFindLeaf(dmtree_t *tp, int l2nb, int *leafidx, bool is_ctl)
|
|
{
|
|
int ti, n = 0, k, x = 0;
|
|
+ int max_size;
|
|
+
|
|
+ max_size = is_ctl ? CTLTREESIZE : TREESIZE;
|
|
|
|
/* first check the root of the tree to see if there is
|
|
* sufficient free space.
|
|
@@ -2949,6 +2960,8 @@ static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
|
|
/* sufficient free space found. move to the next
|
|
* level (or quit if this is the last level).
|
|
*/
|
|
+ if (x + n > max_size)
|
|
+ return -ENOSPC;
|
|
if (l2nb <= tp->dmt_stree[x + n])
|
|
break;
|
|
}
|
|
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
|
|
index 4899663996d81..6ed2e1d4c894f 100644
|
|
--- a/fs/jfs/jfs_imap.c
|
|
+++ b/fs/jfs/jfs_imap.c
|
|
@@ -1320,7 +1320,7 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
|
|
int diAlloc(struct inode *pip, bool dir, struct inode *ip)
|
|
{
|
|
int rc, ino, iagno, addext, extno, bitno, sword;
|
|
- int nwords, rem, i, agno;
|
|
+ int nwords, rem, i, agno, dn_numag;
|
|
u32 mask, inosmap, extsmap;
|
|
struct inode *ipimap;
|
|
struct metapage *mp;
|
|
@@ -1356,6 +1356,9 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
|
|
|
|
/* get the ag number of this iag */
|
|
agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb));
|
|
+ dn_numag = JFS_SBI(pip->i_sb)->bmap->db_numag;
|
|
+ if (agno < 0 || agno > dn_numag)
|
|
+ return -EIO;
|
|
|
|
if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) {
|
|
/*
|
|
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
|
|
index 5cf53def987e5..85a952143e9fb 100644
|
|
--- a/fs/nfs/nfs4proc.c
|
|
+++ b/fs/nfs/nfs4proc.c
|
|
@@ -5628,7 +5628,7 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
|
|
|
|
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
|
|
nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0, 0);
|
|
- nfs4_state_protect_write(server->nfs_client, clnt, msg, hdr);
|
|
+ nfs4_state_protect_write(hdr->ds_clp ? hdr->ds_clp : server->nfs_client, clnt, msg, hdr);
|
|
}
|
|
|
|
static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
|
|
@@ -5669,7 +5669,8 @@ static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_mess
|
|
data->res.server = server;
|
|
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
|
|
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
|
|
- nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_COMMIT, clnt, msg);
|
|
+ nfs4_state_protect(data->ds_clp ? data->ds_clp : server->nfs_client,
|
|
+ NFS_SP4_MACH_CRED_COMMIT, clnt, msg);
|
|
}
|
|
|
|
static int _nfs4_proc_commit(struct file *dst, struct nfs_commitargs *args,
|
|
@@ -8939,6 +8940,7 @@ void nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt,
|
|
|
|
sp4_how = (adata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED);
|
|
|
|
+try_again:
|
|
/* Test connection for session trunking. Async exchange_id call */
|
|
task = nfs4_run_exchange_id(adata->clp, adata->cred, sp4_how, xprt);
|
|
if (IS_ERR(task))
|
|
@@ -8951,11 +8953,15 @@ void nfs4_test_session_trunk(struct rpc_clnt *clnt, struct rpc_xprt *xprt,
|
|
|
|
if (status == 0)
|
|
rpc_clnt_xprt_switch_add_xprt(clnt, xprt);
|
|
- else if (rpc_clnt_xprt_switch_has_addr(clnt,
|
|
+ else if (status != -NFS4ERR_DELAY && rpc_clnt_xprt_switch_has_addr(clnt,
|
|
(struct sockaddr *)&xprt->addr))
|
|
rpc_clnt_xprt_switch_remove_xprt(clnt, xprt);
|
|
|
|
rpc_put_task(task);
|
|
+ if (status == -NFS4ERR_DELAY) {
|
|
+ ssleep(1);
|
|
+ goto try_again;
|
|
+ }
|
|
}
|
|
EXPORT_SYMBOL_GPL(nfs4_test_session_trunk);
|
|
|
|
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
|
|
index 96714e105d7bf..faecdbfa01a29 100644
|
|
--- a/fs/nfsd/nfs4state.c
|
|
+++ b/fs/nfsd/nfs4state.c
|
|
@@ -2799,7 +2799,7 @@ static int client_opens_release(struct inode *inode, struct file *file)
|
|
|
|
/* XXX: alternatively, we could get/drop in seq start/stop */
|
|
drop_client(clp);
|
|
- return 0;
|
|
+ return seq_release(inode, file);
|
|
}
|
|
|
|
static const struct file_operations client_states_fops = {
|
|
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
|
|
index 08d3a1f34ac6c..51eec4a8e82b2 100644
|
|
--- a/fs/overlayfs/super.c
|
|
+++ b/fs/overlayfs/super.c
|
|
@@ -2155,7 +2155,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
|
|
ovl_trusted_xattr_handlers;
|
|
sb->s_fs_info = ofs;
|
|
sb->s_flags |= SB_POSIXACL;
|
|
- sb->s_iflags |= SB_I_SKIP_SYNC | SB_I_IMA_UNVERIFIABLE_SIGNATURE;
|
|
+ sb->s_iflags |= SB_I_SKIP_SYNC;
|
|
|
|
err = -ENOMEM;
|
|
root_dentry = ovl_get_root(sb, upperpath.dentry, oe);
|
|
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
|
|
index 72f2b373221ed..4a4c04a3b1a0a 100644
|
|
--- a/fs/proc/proc_sysctl.c
|
|
+++ b/fs/proc/proc_sysctl.c
|
|
@@ -1814,7 +1814,6 @@ static const struct sysctl_alias sysctl_aliases[] = {
|
|
{"hung_task_panic", "kernel.hung_task_panic" },
|
|
{"numa_zonelist_order", "vm.numa_zonelist_order" },
|
|
{"softlockup_all_cpu_backtrace", "kernel.softlockup_all_cpu_backtrace" },
|
|
- {"softlockup_panic", "kernel.softlockup_panic" },
|
|
{ }
|
|
};
|
|
|
|
@@ -1830,6 +1829,13 @@ static const char *sysctl_find_alias(char *param)
|
|
return NULL;
|
|
}
|
|
|
|
+bool sysctl_is_alias(char *param)
|
|
+{
|
|
+ const char *alias = sysctl_find_alias(param);
|
|
+
|
|
+ return alias != NULL;
|
|
+}
|
|
+
|
|
/* Set sysctl value passed on kernel command line. */
|
|
static int process_sysctl_arg(char *param, char *val,
|
|
const char *unused, void *arg)
|
|
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
|
|
index f26ddfcaa5e61..b0cf3869d3bf5 100644
|
|
--- a/fs/quota/dquot.c
|
|
+++ b/fs/quota/dquot.c
|
|
@@ -2403,6 +2403,20 @@ static int vfs_setup_quota_inode(struct inode *inode, int type)
|
|
if (sb_has_quota_loaded(sb, type))
|
|
return -EBUSY;
|
|
|
|
+ /*
|
|
+ * Quota files should never be encrypted. They should be thought of as
|
|
+ * filesystem metadata, not user data. New-style internal quota files
|
|
+ * cannot be encrypted by users anyway, but old-style external quota
|
|
+ * files could potentially be incorrectly created in an encrypted
|
|
+ * directory, hence this explicit check. Some reasons why encrypted
|
|
+ * quota files don't work include: (1) some filesystems that support
|
|
+ * encryption don't handle it in their quota_read and quota_write, and
|
|
+ * (2) cleaning up encrypted quota files at unmount would need special
|
|
+ * consideration, as quota files are cleaned up later than user files.
|
|
+ */
|
|
+ if (IS_ENCRYPTED(inode))
|
|
+ return -EINVAL;
|
|
+
|
|
dqopt->files[type] = igrab(inode);
|
|
if (!dqopt->files[type])
|
|
return -EIO;
|
|
diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
|
|
index e41154ad96afc..ed396b186c5a4 100644
|
|
--- a/fs/smb/client/cifs_debug.c
|
|
+++ b/fs/smb/client/cifs_debug.c
|
|
@@ -380,6 +380,11 @@ skip_rdma:
|
|
seq_printf(m, "\n\n\tSessions: ");
|
|
i = 0;
|
|
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
|
|
+ spin_lock(&ses->ses_lock);
|
|
+ if (ses->ses_status == SES_EXITING) {
|
|
+ spin_unlock(&ses->ses_lock);
|
|
+ continue;
|
|
+ }
|
|
i++;
|
|
if ((ses->serverDomain == NULL) ||
|
|
(ses->serverOS == NULL) ||
|
|
@@ -400,6 +405,7 @@ skip_rdma:
|
|
ses->ses_count, ses->serverOS, ses->serverNOS,
|
|
ses->capabilities, ses->ses_status);
|
|
}
|
|
+ spin_unlock(&ses->ses_lock);
|
|
|
|
seq_printf(m, "\n\tSecurity type: %s ",
|
|
get_security_type_str(server->ops->select_sectype(server, ses->sectype)));
|
|
diff --git a/fs/smb/client/cifs_spnego.c b/fs/smb/client/cifs_spnego.c
|
|
index 342717bf1dc28..1e6819daaaa7e 100644
|
|
--- a/fs/smb/client/cifs_spnego.c
|
|
+++ b/fs/smb/client/cifs_spnego.c
|
|
@@ -64,8 +64,8 @@ struct key_type cifs_spnego_key_type = {
|
|
* strlen(";sec=ntlmsspi") */
|
|
#define MAX_MECH_STR_LEN 13
|
|
|
|
-/* strlen of "host=" */
|
|
-#define HOST_KEY_LEN 5
|
|
+/* strlen of ";host=" */
|
|
+#define HOST_KEY_LEN 6
|
|
|
|
/* strlen of ";ip4=" or ";ip6=" */
|
|
#define IP_KEY_LEN 5
|
|
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
|
|
index 18d66497c42d1..33ea1440f4b06 100644
|
|
--- a/fs/smb/client/cifsfs.c
|
|
+++ b/fs/smb/client/cifsfs.c
|
|
@@ -1186,6 +1186,7 @@ const char *cifs_get_link(struct dentry *dentry, struct inode *inode,
|
|
|
|
const struct inode_operations cifs_symlink_inode_ops = {
|
|
.get_link = cifs_get_link,
|
|
+ .setattr = cifs_setattr,
|
|
.permission = cifs_permission,
|
|
.listxattr = cifs_listxattr,
|
|
};
|
|
diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h
|
|
index cc458b98441c7..c403816d0b6c1 100644
|
|
--- a/fs/smb/client/cifspdu.h
|
|
+++ b/fs/smb/client/cifspdu.h
|
|
@@ -2570,7 +2570,7 @@ typedef struct {
|
|
|
|
|
|
struct win_dev {
|
|
- unsigned char type[8]; /* IntxCHR or IntxBLK */
|
|
+ unsigned char type[8]; /* IntxCHR or IntxBLK or LnxFIFO*/
|
|
__le64 major;
|
|
__le64 minor;
|
|
} __attribute__((packed));
|
|
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
|
|
index a914b88ca51a1..f37e4da0fe405 100644
|
|
--- a/fs/smb/client/cifsproto.h
|
|
+++ b/fs/smb/client/cifsproto.h
|
|
@@ -79,7 +79,7 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata,
|
|
const char *fullpath, const struct dfs_info3_param *ref,
|
|
char **devname);
|
|
extern void delete_mid(struct mid_q_entry *mid);
|
|
-extern void release_mid(struct mid_q_entry *mid);
|
|
+void __release_mid(struct kref *refcount);
|
|
extern void cifs_wake_up_task(struct mid_q_entry *mid);
|
|
extern int cifs_handle_standard(struct TCP_Server_Info *server,
|
|
struct mid_q_entry *mid);
|
|
@@ -694,4 +694,9 @@ struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
|
|
void cifs_put_tcon_super(struct super_block *sb);
|
|
int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
|
|
|
|
+static inline void release_mid(struct mid_q_entry *mid)
|
|
+{
|
|
+ kref_put(&mid->refcount, __release_mid);
|
|
+}
|
|
+
|
|
#endif /* _CIFSPROTO_H */
|
|
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
|
|
index acb8951eb7576..6ca1e00b3f76a 100644
|
|
--- a/fs/smb/client/connect.c
|
|
+++ b/fs/smb/client/connect.c
|
|
@@ -205,13 +205,14 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
|
|
/* If server is a channel, select the primary channel */
|
|
pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
|
|
|
|
- spin_lock(&pserver->srv_lock);
|
|
+ /* if we need to signal just this channel */
|
|
if (!all_channels) {
|
|
- pserver->tcpStatus = CifsNeedReconnect;
|
|
- spin_unlock(&pserver->srv_lock);
|
|
+ spin_lock(&server->srv_lock);
|
|
+ if (server->tcpStatus != CifsExiting)
|
|
+ server->tcpStatus = CifsNeedReconnect;
|
|
+ spin_unlock(&server->srv_lock);
|
|
return;
|
|
}
|
|
- spin_unlock(&pserver->srv_lock);
|
|
|
|
spin_lock(&cifs_tcp_ses_lock);
|
|
list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
|
|
@@ -4204,8 +4205,12 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
|
is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
spin_unlock(&ses->chan_lock);
|
|
|
|
- if (!is_binding)
|
|
+ if (!is_binding) {
|
|
ses->ses_status = SES_IN_SETUP;
|
|
+
|
|
+ /* force iface_list refresh */
|
|
+ ses->iface_last_update = 0;
|
|
+ }
|
|
spin_unlock(&ses->ses_lock);
|
|
|
|
/* update ses ip_addr only for primary chan */
|
|
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
|
|
index 9531ea2430899..05516309ec3ab 100644
|
|
--- a/fs/smb/client/inode.c
|
|
+++ b/fs/smb/client/inode.c
|
|
@@ -567,6 +567,10 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
|
|
cifs_dbg(FYI, "Symlink\n");
|
|
fattr->cf_mode |= S_IFLNK;
|
|
fattr->cf_dtype = DT_LNK;
|
|
+ } else if (memcmp("LnxFIFO", pbuf, 8) == 0) {
|
|
+ cifs_dbg(FYI, "FIFO\n");
|
|
+ fattr->cf_mode |= S_IFIFO;
|
|
+ fattr->cf_dtype = DT_FIFO;
|
|
} else {
|
|
fattr->cf_mode |= S_IFREG; /* file? */
|
|
fattr->cf_dtype = DT_REG;
|
|
diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
|
|
index 1e3e22979604f..f0d164873500b 100644
|
|
--- a/fs/smb/client/sess.c
|
|
+++ b/fs/smb/client/sess.c
|
|
@@ -186,7 +186,6 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
|
|
}
|
|
|
|
if (!(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
|
|
- ses->chan_max = 1;
|
|
spin_unlock(&ses->chan_lock);
|
|
cifs_server_dbg(VFS, "no multichannel support\n");
|
|
return 0;
|
|
diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c
|
|
index 572293c18e16f..eaa5bd148810a 100644
|
|
--- a/fs/smb/client/smb2misc.c
|
|
+++ b/fs/smb/client/smb2misc.c
|
|
@@ -787,7 +787,7 @@ __smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid,
|
|
{
|
|
struct close_cancelled_open *cancelled;
|
|
|
|
- cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC);
|
|
+ cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
|
|
if (!cancelled)
|
|
return -ENOMEM;
|
|
|
|
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
|
|
index efff7137412b4..2c1898803279a 100644
|
|
--- a/fs/smb/client/smb2ops.c
|
|
+++ b/fs/smb/client/smb2ops.c
|
|
@@ -5215,7 +5215,7 @@ smb2_make_node(unsigned int xid, struct inode *inode,
|
|
* over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions
|
|
*/
|
|
|
|
- if (!S_ISCHR(mode) && !S_ISBLK(mode))
|
|
+ if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode))
|
|
return rc;
|
|
|
|
cifs_dbg(FYI, "sfu compat create special file\n");
|
|
@@ -5263,6 +5263,12 @@ smb2_make_node(unsigned int xid, struct inode *inode,
|
|
pdev->minor = cpu_to_le64(MINOR(dev));
|
|
rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
|
|
&bytes_written, iov, 1);
|
|
+ } else if (S_ISFIFO(mode)) {
|
|
+ memcpy(pdev->type, "LnxFIFO", 8);
|
|
+ pdev->major = 0;
|
|
+ pdev->minor = 0;
|
|
+ rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
|
|
+ &bytes_written, iov, 1);
|
|
}
|
|
tcon->ses->server->ops->close(xid, tcon, &fid);
|
|
d_drop(dentry);
|
|
diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
|
|
index 22954a9c7a6c7..69dbd08fd4419 100644
|
|
--- a/fs/smb/client/smb2transport.c
|
|
+++ b/fs/smb/client/smb2transport.c
|
|
@@ -451,6 +451,8 @@ generate_smb3signingkey(struct cifs_ses *ses,
|
|
ptriplet->encryption.context,
|
|
ses->smb3encryptionkey,
|
|
SMB3_ENC_DEC_KEY_SIZE);
|
|
+ if (rc)
|
|
+ return rc;
|
|
rc = generate_key(ses, ptriplet->decryption.label,
|
|
ptriplet->decryption.context,
|
|
ses->smb3decryptionkey,
|
|
@@ -459,9 +461,6 @@ generate_smb3signingkey(struct cifs_ses *ses,
|
|
return rc;
|
|
}
|
|
|
|
- if (rc)
|
|
- return rc;
|
|
-
|
|
#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
|
|
cifs_dbg(VFS, "%s: dumping generated AES session keys\n", __func__);
|
|
/*
|
|
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
|
|
index 87aea456ee903..8a1dd8407a3a7 100644
|
|
--- a/fs/smb/client/transport.c
|
|
+++ b/fs/smb/client/transport.c
|
|
@@ -76,7 +76,7 @@ alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
|
|
return temp;
|
|
}
|
|
|
|
-static void __release_mid(struct kref *refcount)
|
|
+void __release_mid(struct kref *refcount)
|
|
{
|
|
struct mid_q_entry *midEntry =
|
|
container_of(refcount, struct mid_q_entry, refcount);
|
|
@@ -156,15 +156,6 @@ static void __release_mid(struct kref *refcount)
|
|
mempool_free(midEntry, cifs_mid_poolp);
|
|
}
|
|
|
|
-void release_mid(struct mid_q_entry *mid)
|
|
-{
|
|
- struct TCP_Server_Info *server = mid->server;
|
|
-
|
|
- spin_lock(&server->mid_lock);
|
|
- kref_put(&mid->refcount, __release_mid);
|
|
- spin_unlock(&server->mid_lock);
|
|
-}
|
|
-
|
|
void
|
|
delete_mid(struct mid_q_entry *mid)
|
|
{
|
|
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c
|
|
index 998fa51f9b684..786b4f6e1263a 100644
|
|
--- a/fs/smb/client/xattr.c
|
|
+++ b/fs/smb/client/xattr.c
|
|
@@ -150,10 +150,13 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
|
goto out;
|
|
|
|
- if (pTcon->ses->server->ops->set_EA)
|
|
+ if (pTcon->ses->server->ops->set_EA) {
|
|
rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
|
|
full_path, name, value, (__u16)size,
|
|
cifs_sb->local_nls, cifs_sb);
|
|
+ if (rc == 0)
|
|
+ inode_set_ctime_current(inode);
|
|
+ }
|
|
break;
|
|
|
|
case XATTR_CIFS_ACL:
|
|
diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c
|
|
index a4421d9458d90..adc41b57b84c6 100644
|
|
--- a/fs/smb/server/smb_common.c
|
|
+++ b/fs/smb/server/smb_common.c
|
|
@@ -372,11 +372,22 @@ static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
|
|
return 0;
|
|
}
|
|
|
|
+/**
|
|
+ * set_smb1_rsp_status() - set error type in smb response header
|
|
+ * @work: smb work containing smb response header
|
|
+ * @err: error code to set in response
|
|
+ */
|
|
+static void set_smb1_rsp_status(struct ksmbd_work *work, __le32 err)
|
|
+{
|
|
+ work->send_no_response = 1;
|
|
+}
|
|
+
|
|
static struct smb_version_ops smb1_server_ops = {
|
|
.get_cmd_val = get_smb1_cmd_val,
|
|
.init_rsp_hdr = init_smb1_rsp_hdr,
|
|
.allocate_rsp_buf = smb1_allocate_rsp_buf,
|
|
.check_user_session = smb1_check_user_session,
|
|
+ .set_rsp_status = set_smb1_rsp_status,
|
|
};
|
|
|
|
static int smb1_negotiate(struct ksmbd_work *work)
|
|
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
|
|
index b05ff9b146b55..c24df86eb112b 100644
|
|
--- a/fs/smb/server/smbacl.c
|
|
+++ b/fs/smb/server/smbacl.c
|
|
@@ -1107,6 +1107,7 @@ pass:
|
|
struct smb_acl *pdacl;
|
|
struct smb_sid *powner_sid = NULL, *pgroup_sid = NULL;
|
|
int powner_sid_size = 0, pgroup_sid_size = 0, pntsd_size;
|
|
+ int pntsd_alloc_size;
|
|
|
|
if (parent_pntsd->osidoffset) {
|
|
powner_sid = (struct smb_sid *)((char *)parent_pntsd +
|
|
@@ -1119,9 +1120,10 @@ pass:
|
|
pgroup_sid_size = 1 + 1 + 6 + (pgroup_sid->num_subauth * 4);
|
|
}
|
|
|
|
- pntsd = kzalloc(sizeof(struct smb_ntsd) + powner_sid_size +
|
|
- pgroup_sid_size + sizeof(struct smb_acl) +
|
|
- nt_size, GFP_KERNEL);
|
|
+ pntsd_alloc_size = sizeof(struct smb_ntsd) + powner_sid_size +
|
|
+ pgroup_sid_size + sizeof(struct smb_acl) + nt_size;
|
|
+
|
|
+ pntsd = kzalloc(pntsd_alloc_size, GFP_KERNEL);
|
|
if (!pntsd) {
|
|
rc = -ENOMEM;
|
|
goto free_aces_base;
|
|
@@ -1136,6 +1138,27 @@ pass:
|
|
pntsd->gsidoffset = parent_pntsd->gsidoffset;
|
|
pntsd->dacloffset = parent_pntsd->dacloffset;
|
|
|
|
+ if ((u64)le32_to_cpu(pntsd->osidoffset) + powner_sid_size >
|
|
+ pntsd_alloc_size) {
|
|
+ rc = -EINVAL;
|
|
+ kfree(pntsd);
|
|
+ goto free_aces_base;
|
|
+ }
|
|
+
|
|
+ if ((u64)le32_to_cpu(pntsd->gsidoffset) + pgroup_sid_size >
|
|
+ pntsd_alloc_size) {
|
|
+ rc = -EINVAL;
|
|
+ kfree(pntsd);
|
|
+ goto free_aces_base;
|
|
+ }
|
|
+
|
|
+ if ((u64)le32_to_cpu(pntsd->dacloffset) + sizeof(struct smb_acl) + nt_size >
|
|
+ pntsd_alloc_size) {
|
|
+ rc = -EINVAL;
|
|
+ kfree(pntsd);
|
|
+ goto free_aces_base;
|
|
+ }
|
|
+
|
|
if (pntsd->osidoffset) {
|
|
struct smb_sid *owner_sid = (struct smb_sid *)((char *)pntsd +
|
|
le32_to_cpu(pntsd->osidoffset));
|
|
diff --git a/fs/xfs/xfs_inode_item_recover.c b/fs/xfs/xfs_inode_item_recover.c
|
|
index 0e5dba2343ea1..e6609067ef261 100644
|
|
--- a/fs/xfs/xfs_inode_item_recover.c
|
|
+++ b/fs/xfs/xfs_inode_item_recover.c
|
|
@@ -369,24 +369,26 @@ xlog_recover_inode_commit_pass2(
|
|
* superblock flag to determine whether we need to look at di_flushiter
|
|
* to skip replay when the on disk inode is newer than the log one
|
|
*/
|
|
- if (!xfs_has_v3inodes(mp) &&
|
|
- ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
|
|
- /*
|
|
- * Deal with the wrap case, DI_MAX_FLUSH is less
|
|
- * than smaller numbers
|
|
- */
|
|
- if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
|
|
- ldip->di_flushiter < (DI_MAX_FLUSH >> 1)) {
|
|
- /* do nothing */
|
|
- } else {
|
|
- trace_xfs_log_recover_inode_skip(log, in_f);
|
|
- error = 0;
|
|
- goto out_release;
|
|
+ if (!xfs_has_v3inodes(mp)) {
|
|
+ if (ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
|
|
+ /*
|
|
+ * Deal with the wrap case, DI_MAX_FLUSH is less
|
|
+ * than smaller numbers
|
|
+ */
|
|
+ if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
|
|
+ ldip->di_flushiter < (DI_MAX_FLUSH >> 1)) {
|
|
+ /* do nothing */
|
|
+ } else {
|
|
+ trace_xfs_log_recover_inode_skip(log, in_f);
|
|
+ error = 0;
|
|
+ goto out_release;
|
|
+ }
|
|
}
|
|
+
|
|
+ /* Take the opportunity to reset the flush iteration count */
|
|
+ ldip->di_flushiter = 0;
|
|
}
|
|
|
|
- /* Take the opportunity to reset the flush iteration count */
|
|
- ldip->di_flushiter = 0;
|
|
|
|
if (unlikely(S_ISREG(ldip->di_mode))) {
|
|
if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
|
|
diff --git a/include/linux/damon.h b/include/linux/damon.h
|
|
index 620ada094c3b2..b13be7ae2275e 100644
|
|
--- a/include/linux/damon.h
|
|
+++ b/include/linux/damon.h
|
|
@@ -559,6 +559,13 @@ static inline bool damon_target_has_pid(const struct damon_ctx *ctx)
|
|
return ctx->ops.id == DAMON_OPS_VADDR || ctx->ops.id == DAMON_OPS_FVADDR;
|
|
}
|
|
|
|
+static inline unsigned int damon_max_nr_accesses(const struct damon_attrs *attrs)
|
|
+{
|
|
+ /* {aggr,sample}_interval are unsigned long, hence could overflow */
|
|
+ return min(attrs->aggr_interval / attrs->sample_interval,
|
|
+ (unsigned long)UINT_MAX);
|
|
+}
|
|
+
|
|
|
|
int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive);
|
|
int damon_stop(struct damon_ctx **ctxs, int nr_ctxs);
|
|
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
|
|
index 99dc7bfbcd3c3..7dacc109eb251 100644
|
|
--- a/include/linux/ethtool.h
|
|
+++ b/include/linux/ethtool.h
|
|
@@ -836,10 +836,10 @@ int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index);
|
|
|
|
/**
|
|
* ethtool_sprintf - Write formatted string to ethtool string data
|
|
- * @data: Pointer to start of string to update
|
|
+ * @data: Pointer to a pointer to the start of string to update
|
|
* @fmt: Format of string to write
|
|
*
|
|
- * Write formatted string to data. Update data to point at start of
|
|
+ * Write formatted string to *data. Update *data to point at start of
|
|
* next string.
|
|
*/
|
|
extern __printf(2, 3) void ethtool_sprintf(u8 **data, const char *fmt, ...);
|
|
diff --git a/include/linux/fs.h b/include/linux/fs.h
|
|
index dc745317e1bdb..b6af6abc7a77f 100644
|
|
--- a/include/linux/fs.h
|
|
+++ b/include/linux/fs.h
|
|
@@ -1812,7 +1812,50 @@ static inline bool fsuidgid_has_mapping(struct super_block *sb,
|
|
kgid_has_mapping(fs_userns, kgid);
|
|
}
|
|
|
|
-extern struct timespec64 current_time(struct inode *inode);
|
|
+struct timespec64 current_time(struct inode *inode);
|
|
+struct timespec64 inode_set_ctime_current(struct inode *inode);
|
|
+
|
|
+/**
|
|
+ * inode_get_ctime - fetch the current ctime from the inode
|
|
+ * @inode: inode from which to fetch ctime
|
|
+ *
|
|
+ * Grab the current ctime from the inode and return it.
|
|
+ */
|
|
+static inline struct timespec64 inode_get_ctime(const struct inode *inode)
|
|
+{
|
|
+ return inode->i_ctime;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * inode_set_ctime_to_ts - set the ctime in the inode
|
|
+ * @inode: inode in which to set the ctime
|
|
+ * @ts: value to set in the ctime field
|
|
+ *
|
|
+ * Set the ctime in @inode to @ts
|
|
+ */
|
|
+static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode,
|
|
+ struct timespec64 ts)
|
|
+{
|
|
+ inode->i_ctime = ts;
|
|
+ return ts;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * inode_set_ctime - set the ctime in the inode
|
|
+ * @inode: inode in which to set the ctime
|
|
+ * @sec: tv_sec value to set
|
|
+ * @nsec: tv_nsec value to set
|
|
+ *
|
|
+ * Set the ctime in @inode to { @sec, @nsec }
|
|
+ */
|
|
+static inline struct timespec64 inode_set_ctime(struct inode *inode,
|
|
+ time64_t sec, long nsec)
|
|
+{
|
|
+ struct timespec64 ts = { .tv_sec = sec,
|
|
+ .tv_nsec = nsec };
|
|
+
|
|
+ return inode_set_ctime_to_ts(inode, ts);
|
|
+}
|
|
|
|
/*
|
|
* Snapshotting support.
|
|
diff --git a/include/linux/generic-radix-tree.h b/include/linux/generic-radix-tree.h
|
|
index 107613f7d7920..f6cd0f909d9fb 100644
|
|
--- a/include/linux/generic-radix-tree.h
|
|
+++ b/include/linux/generic-radix-tree.h
|
|
@@ -38,6 +38,7 @@
|
|
|
|
#include <asm/page.h>
|
|
#include <linux/bug.h>
|
|
+#include <linux/limits.h>
|
|
#include <linux/log2.h>
|
|
#include <linux/math.h>
|
|
#include <linux/types.h>
|
|
@@ -184,6 +185,12 @@ void *__genradix_iter_peek(struct genradix_iter *, struct __genradix *, size_t);
|
|
static inline void __genradix_iter_advance(struct genradix_iter *iter,
|
|
size_t obj_size)
|
|
{
|
|
+ if (iter->offset + obj_size < iter->offset) {
|
|
+ iter->offset = SIZE_MAX;
|
|
+ iter->pos = SIZE_MAX;
|
|
+ return;
|
|
+ }
|
|
+
|
|
iter->offset += obj_size;
|
|
|
|
if (!is_power_of_2(obj_size) &&
|
|
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
|
|
index 4a97a6db9bcec..02b19c508b78f 100644
|
|
--- a/include/linux/lsm_hook_defs.h
|
|
+++ b/include/linux/lsm_hook_defs.h
|
|
@@ -48,7 +48,7 @@ LSM_HOOK(int, 0, quota_on, struct dentry *dentry)
|
|
LSM_HOOK(int, 0, syslog, int type)
|
|
LSM_HOOK(int, 0, settime, const struct timespec64 *ts,
|
|
const struct timezone *tz)
|
|
-LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages)
|
|
+LSM_HOOK(int, 1, vm_enough_memory, struct mm_struct *mm, long pages)
|
|
LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm)
|
|
LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, struct file *file)
|
|
LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm)
|
|
@@ -266,7 +266,7 @@ LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen)
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode)
|
|
LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen)
|
|
LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen)
|
|
-LSM_HOOK(int, 0, inode_getsecctx, struct inode *inode, void **ctx,
|
|
+LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, void **ctx,
|
|
u32 *ctxlen)
|
|
|
|
#if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
|
|
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
|
|
index daa2f40d9ce65..7b12eebc5586d 100644
|
|
--- a/include/linux/mmc/card.h
|
|
+++ b/include/linux/mmc/card.h
|
|
@@ -295,7 +295,9 @@ struct mmc_card {
|
|
#define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */
|
|
#define MMC_QUIRK_BROKEN_SD_DISCARD (1<<14) /* Disable broken SD discard support */
|
|
#define MMC_QUIRK_BROKEN_SD_CACHE (1<<15) /* Disable broken SD cache support */
|
|
+#define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */
|
|
|
|
+ bool written_flag; /* Indicates eMMC has been written since power on */
|
|
bool reenable_cmdq; /* Re-enable Command Queue */
|
|
|
|
unsigned int erase_size; /* erase size in sectors */
|
|
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
|
|
index 0df425bf9bd75..8cfcc5d454512 100644
|
|
--- a/include/linux/preempt.h
|
|
+++ b/include/linux/preempt.h
|
|
@@ -98,14 +98,21 @@ static __always_inline unsigned char interrupt_context_level(void)
|
|
return level;
|
|
}
|
|
|
|
+/*
|
|
+ * These macro definitions avoid redundant invocations of preempt_count()
|
|
+ * because such invocations would result in redundant loads given that
|
|
+ * preempt_count() is commonly implemented with READ_ONCE().
|
|
+ */
|
|
+
|
|
#define nmi_count() (preempt_count() & NMI_MASK)
|
|
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
|
|
#ifdef CONFIG_PREEMPT_RT
|
|
# define softirq_count() (current->softirq_disable_cnt & SOFTIRQ_MASK)
|
|
+# define irq_count() ((preempt_count() & (NMI_MASK | HARDIRQ_MASK)) | softirq_count())
|
|
#else
|
|
# define softirq_count() (preempt_count() & SOFTIRQ_MASK)
|
|
+# define irq_count() (preempt_count() & (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_MASK))
|
|
#endif
|
|
-#define irq_count() (nmi_count() | hardirq_count() | softirq_count())
|
|
|
|
/*
|
|
* Macros to retrieve the current execution context:
|
|
@@ -118,7 +125,11 @@ static __always_inline unsigned char interrupt_context_level(void)
|
|
#define in_nmi() (nmi_count())
|
|
#define in_hardirq() (hardirq_count())
|
|
#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
|
|
-#define in_task() (!(in_nmi() | in_hardirq() | in_serving_softirq()))
|
|
+#ifdef CONFIG_PREEMPT_RT
|
|
+# define in_task() (!((preempt_count() & (NMI_MASK | HARDIRQ_MASK)) | in_serving_softirq()))
|
|
+#else
|
|
+# define in_task() (!(preempt_count() & (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
|
|
+#endif
|
|
|
|
/*
|
|
* The following macros are deprecated and should not be used in new code:
|
|
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
|
|
index 161e91167b9c0..5e88f1b591832 100644
|
|
--- a/include/linux/pwm.h
|
|
+++ b/include/linux/pwm.h
|
|
@@ -41,8 +41,8 @@ struct pwm_args {
|
|
};
|
|
|
|
enum {
|
|
- PWMF_REQUESTED = 1 << 0,
|
|
- PWMF_EXPORTED = 1 << 1,
|
|
+ PWMF_REQUESTED = 0,
|
|
+ PWMF_EXPORTED = 1,
|
|
};
|
|
|
|
/*
|
|
diff --git a/include/linux/socket.h b/include/linux/socket.h
|
|
index de3701a2a2129..1db29aab8f9c3 100644
|
|
--- a/include/linux/socket.h
|
|
+++ b/include/linux/socket.h
|
|
@@ -376,6 +376,7 @@ struct ucred {
|
|
#define SOL_MPTCP 284
|
|
#define SOL_MCTP 285
|
|
#define SOL_SMC 286
|
|
+#define SOL_VSOCK 287
|
|
|
|
/* IPX options */
|
|
#define IPX_TYPE 1
|
|
diff --git a/include/linux/string.h b/include/linux/string.h
|
|
index 26ab8928d8661..422606e98cc42 100644
|
|
--- a/include/linux/string.h
|
|
+++ b/include/linux/string.h
|
|
@@ -5,7 +5,9 @@
|
|
#include <linux/compiler.h> /* for inline */
|
|
#include <linux/types.h> /* for size_t */
|
|
#include <linux/stddef.h> /* for NULL */
|
|
+#include <linux/err.h> /* for ERR_PTR() */
|
|
#include <linux/errno.h> /* for E2BIG */
|
|
+#include <linux/overflow.h> /* for check_mul_overflow() */
|
|
#include <linux/stdarg.h>
|
|
#include <uapi/linux/string.h>
|
|
|
|
@@ -14,6 +16,44 @@ extern void *memdup_user(const void __user *, size_t);
|
|
extern void *vmemdup_user(const void __user *, size_t);
|
|
extern void *memdup_user_nul(const void __user *, size_t);
|
|
|
|
+/**
|
|
+ * memdup_array_user - duplicate array from user space
|
|
+ * @src: source address in user space
|
|
+ * @n: number of array members to copy
|
|
+ * @size: size of one array member
|
|
+ *
|
|
+ * Return: an ERR_PTR() on failure. Result is physically
|
|
+ * contiguous, to be freed by kfree().
|
|
+ */
|
|
+static inline void *memdup_array_user(const void __user *src, size_t n, size_t size)
|
|
+{
|
|
+ size_t nbytes;
|
|
+
|
|
+ if (check_mul_overflow(n, size, &nbytes))
|
|
+ return ERR_PTR(-EOVERFLOW);
|
|
+
|
|
+ return memdup_user(src, nbytes);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * vmemdup_array_user - duplicate array from user space
|
|
+ * @src: source address in user space
|
|
+ * @n: number of array members to copy
|
|
+ * @size: size of one array member
|
|
+ *
|
|
+ * Return: an ERR_PTR() on failure. Result may be not
|
|
+ * physically contiguous. Use kvfree() to free.
|
|
+ */
|
|
+static inline void *vmemdup_array_user(const void __user *src, size_t n, size_t size)
|
|
+{
|
|
+ size_t nbytes;
|
|
+
|
|
+ if (check_mul_overflow(n, size, &nbytes))
|
|
+ return ERR_PTR(-EOVERFLOW);
|
|
+
|
|
+ return vmemdup_user(src, nbytes);
|
|
+}
|
|
+
|
|
/*
|
|
* Include machine specific inline routines
|
|
*/
|
|
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
|
|
index 770ef2cb57752..c794b0ce4e782 100644
|
|
--- a/include/linux/sunrpc/clnt.h
|
|
+++ b/include/linux/sunrpc/clnt.h
|
|
@@ -84,6 +84,7 @@ struct rpc_clnt {
|
|
};
|
|
const struct cred *cl_cred;
|
|
unsigned int cl_max_connect; /* max number of transports not to the same IP */
|
|
+ struct super_block *pipefs_sb;
|
|
};
|
|
|
|
/*
|
|
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
|
|
index 780690dc08cda..a207c7ed41bd2 100644
|
|
--- a/include/linux/sysctl.h
|
|
+++ b/include/linux/sysctl.h
|
|
@@ -238,6 +238,7 @@ extern void __register_sysctl_init(const char *path, struct ctl_table *table,
|
|
extern struct ctl_table_header *register_sysctl_mount_point(const char *path);
|
|
|
|
void do_sysctl_args(void);
|
|
+bool sysctl_is_alias(char *param);
|
|
int do_proc_douintvec(struct ctl_table *table, int write,
|
|
void *buffer, size_t *lenp, loff_t *ppos,
|
|
int (*conv)(unsigned long *lvalp,
|
|
@@ -301,6 +302,11 @@ static inline void setup_sysctl_set(struct ctl_table_set *p,
|
|
static inline void do_sysctl_args(void)
|
|
{
|
|
}
|
|
+
|
|
+static inline bool sysctl_is_alias(char *param)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
#endif /* CONFIG_SYSCTL */
|
|
|
|
int sysctl_max_threads(struct ctl_table *table, int write, void *buffer,
|
|
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
|
|
index 422f4ca656cf9..c8b5e9781d01a 100644
|
|
--- a/include/linux/trace_events.h
|
|
+++ b/include/linux/trace_events.h
|
|
@@ -478,6 +478,7 @@ enum {
|
|
EVENT_FILE_FL_TRIGGER_COND_BIT,
|
|
EVENT_FILE_FL_PID_FILTER_BIT,
|
|
EVENT_FILE_FL_WAS_ENABLED_BIT,
|
|
+ EVENT_FILE_FL_FREED_BIT,
|
|
};
|
|
|
|
extern struct trace_event_file *trace_get_event_file(const char *instance,
|
|
@@ -616,6 +617,7 @@ extern int __kprobe_event_add_fields(struct dynevent_cmd *cmd, ...);
|
|
* TRIGGER_COND - When set, one or more triggers has an associated filter
|
|
* PID_FILTER - When set, the event is filtered based on pid
|
|
* WAS_ENABLED - Set when enabled to know to clear trace on module removal
|
|
+ * FREED - File descriptor is freed, all fields should be considered invalid
|
|
*/
|
|
enum {
|
|
EVENT_FILE_FL_ENABLED = (1 << EVENT_FILE_FL_ENABLED_BIT),
|
|
@@ -629,6 +631,7 @@ enum {
|
|
EVENT_FILE_FL_TRIGGER_COND = (1 << EVENT_FILE_FL_TRIGGER_COND_BIT),
|
|
EVENT_FILE_FL_PID_FILTER = (1 << EVENT_FILE_FL_PID_FILTER_BIT),
|
|
EVENT_FILE_FL_WAS_ENABLED = (1 << EVENT_FILE_FL_WAS_ENABLED_BIT),
|
|
+ EVENT_FILE_FL_FREED = (1 << EVENT_FILE_FL_FREED_BIT),
|
|
};
|
|
|
|
struct trace_event_file {
|
|
@@ -657,6 +660,7 @@ struct trace_event_file {
|
|
* caching and such. Which is mostly OK ;-)
|
|
*/
|
|
unsigned long flags;
|
|
+ atomic_t ref; /* ref count for opened files */
|
|
atomic_t sm_ref; /* soft-mode reference counter */
|
|
atomic_t tm_ref; /* trigger-mode reference counter */
|
|
};
|
|
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
|
|
index 3ca41b9da6473..5d052e193a85c 100644
|
|
--- a/include/linux/workqueue.h
|
|
+++ b/include/linux/workqueue.h
|
|
@@ -222,18 +222,16 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
|
|
* to generate better code.
|
|
*/
|
|
#ifdef CONFIG_LOCKDEP
|
|
-#define __INIT_WORK(_work, _func, _onstack) \
|
|
+#define __INIT_WORK_KEY(_work, _func, _onstack, _key) \
|
|
do { \
|
|
- static struct lock_class_key __key; \
|
|
- \
|
|
__init_work((_work), _onstack); \
|
|
(_work)->data = (atomic_long_t) WORK_DATA_INIT(); \
|
|
- lockdep_init_map(&(_work)->lockdep_map, "(work_completion)"#_work, &__key, 0); \
|
|
+ lockdep_init_map(&(_work)->lockdep_map, "(work_completion)"#_work, (_key), 0); \
|
|
INIT_LIST_HEAD(&(_work)->entry); \
|
|
(_work)->func = (_func); \
|
|
} while (0)
|
|
#else
|
|
-#define __INIT_WORK(_work, _func, _onstack) \
|
|
+#define __INIT_WORK_KEY(_work, _func, _onstack, _key) \
|
|
do { \
|
|
__init_work((_work), _onstack); \
|
|
(_work)->data = (atomic_long_t) WORK_DATA_INIT(); \
|
|
@@ -242,12 +240,22 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
|
|
} while (0)
|
|
#endif
|
|
|
|
+#define __INIT_WORK(_work, _func, _onstack) \
|
|
+ do { \
|
|
+ static __maybe_unused struct lock_class_key __key; \
|
|
+ \
|
|
+ __INIT_WORK_KEY(_work, _func, _onstack, &__key); \
|
|
+ } while (0)
|
|
+
|
|
#define INIT_WORK(_work, _func) \
|
|
__INIT_WORK((_work), (_func), 0)
|
|
|
|
#define INIT_WORK_ONSTACK(_work, _func) \
|
|
__INIT_WORK((_work), (_func), 1)
|
|
|
|
+#define INIT_WORK_ONSTACK_KEY(_work, _func, _key) \
|
|
+ __INIT_WORK_KEY((_work), (_func), 1, _key)
|
|
+
|
|
#define __INIT_DELAYED_WORK(_work, _func, _tflags) \
|
|
do { \
|
|
INIT_WORK(&(_work)->work, (_func)); \
|
|
@@ -681,8 +689,32 @@ static inline long work_on_cpu_safe(int cpu, long (*fn)(void *), void *arg)
|
|
return fn(arg);
|
|
}
|
|
#else
|
|
-long work_on_cpu(int cpu, long (*fn)(void *), void *arg);
|
|
-long work_on_cpu_safe(int cpu, long (*fn)(void *), void *arg);
|
|
+long work_on_cpu_key(int cpu, long (*fn)(void *),
|
|
+ void *arg, struct lock_class_key *key);
|
|
+/*
|
|
+ * A new key is defined for each caller to make sure the work
|
|
+ * associated with the function doesn't share its locking class.
|
|
+ */
|
|
+#define work_on_cpu(_cpu, _fn, _arg) \
|
|
+({ \
|
|
+ static struct lock_class_key __key; \
|
|
+ \
|
|
+ work_on_cpu_key(_cpu, _fn, _arg, &__key); \
|
|
+})
|
|
+
|
|
+long work_on_cpu_safe_key(int cpu, long (*fn)(void *),
|
|
+ void *arg, struct lock_class_key *key);
|
|
+
|
|
+/*
|
|
+ * A new key is defined for each caller to make sure the work
|
|
+ * associated with the function doesn't share its locking class.
|
|
+ */
|
|
+#define work_on_cpu_safe(_cpu, _fn, _arg) \
|
|
+({ \
|
|
+ static struct lock_class_key __key; \
|
|
+ \
|
|
+ work_on_cpu_safe_key(_cpu, _fn, _arg, &__key); \
|
|
+})
|
|
#endif /* CONFIG_SMP */
|
|
|
|
#ifdef CONFIG_FREEZER
|
|
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
|
|
index d1f81a6d7773b..c726da3b7d68a 100644
|
|
--- a/include/net/netfilter/nf_tables.h
|
|
+++ b/include/net/netfilter/nf_tables.h
|
|
@@ -177,9 +177,9 @@ static inline __be32 nft_reg_load_be32(const u32 *sreg)
|
|
return *(__force __be32 *)sreg;
|
|
}
|
|
|
|
-static inline void nft_reg_store64(u32 *dreg, u64 val)
|
|
+static inline void nft_reg_store64(u64 *dreg, u64 val)
|
|
{
|
|
- put_unaligned(val, (u64 *)dreg);
|
|
+ put_unaligned(val, dreg);
|
|
}
|
|
|
|
static inline u64 nft_reg_load64(const u32 *sreg)
|
|
diff --git a/include/net/sock.h b/include/net/sock.h
|
|
index a1fcbb2a8a2ce..b6027b01c2455 100644
|
|
--- a/include/net/sock.h
|
|
+++ b/include/net/sock.h
|
|
@@ -2032,21 +2032,33 @@ static inline void sk_tx_queue_set(struct sock *sk, int tx_queue)
|
|
/* sk_tx_queue_mapping accept only upto a 16-bit value */
|
|
if (WARN_ON_ONCE((unsigned short)tx_queue >= USHRT_MAX))
|
|
return;
|
|
- sk->sk_tx_queue_mapping = tx_queue;
|
|
+ /* Paired with READ_ONCE() in sk_tx_queue_get() and
|
|
+ * other WRITE_ONCE() because socket lock might be not held.
|
|
+ */
|
|
+ WRITE_ONCE(sk->sk_tx_queue_mapping, tx_queue);
|
|
}
|
|
|
|
#define NO_QUEUE_MAPPING USHRT_MAX
|
|
|
|
static inline void sk_tx_queue_clear(struct sock *sk)
|
|
{
|
|
- sk->sk_tx_queue_mapping = NO_QUEUE_MAPPING;
|
|
+ /* Paired with READ_ONCE() in sk_tx_queue_get() and
|
|
+ * other WRITE_ONCE() because socket lock might be not held.
|
|
+ */
|
|
+ WRITE_ONCE(sk->sk_tx_queue_mapping, NO_QUEUE_MAPPING);
|
|
}
|
|
|
|
static inline int sk_tx_queue_get(const struct sock *sk)
|
|
{
|
|
- if (sk && sk->sk_tx_queue_mapping != NO_QUEUE_MAPPING)
|
|
- return sk->sk_tx_queue_mapping;
|
|
+ if (sk) {
|
|
+ /* Paired with WRITE_ONCE() in sk_tx_queue_clear()
|
|
+ * and sk_tx_queue_set().
|
|
+ */
|
|
+ int val = READ_ONCE(sk->sk_tx_queue_mapping);
|
|
|
|
+ if (val != NO_QUEUE_MAPPING)
|
|
+ return val;
|
|
+ }
|
|
return -1;
|
|
}
|
|
|
|
@@ -2195,7 +2207,7 @@ static inline void __dst_negative_advice(struct sock *sk)
|
|
if (ndst != dst) {
|
|
rcu_assign_pointer(sk->sk_dst_cache, ndst);
|
|
sk_tx_queue_clear(sk);
|
|
- sk->sk_dst_pending_confirm = 0;
|
|
+ WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
|
|
}
|
|
}
|
|
}
|
|
@@ -2212,7 +2224,7 @@ __sk_dst_set(struct sock *sk, struct dst_entry *dst)
|
|
struct dst_entry *old_dst;
|
|
|
|
sk_tx_queue_clear(sk);
|
|
- sk->sk_dst_pending_confirm = 0;
|
|
+ WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
|
|
old_dst = rcu_dereference_protected(sk->sk_dst_cache,
|
|
lockdep_sock_is_held(sk));
|
|
rcu_assign_pointer(sk->sk_dst_cache, dst);
|
|
@@ -2225,7 +2237,7 @@ sk_dst_set(struct sock *sk, struct dst_entry *dst)
|
|
struct dst_entry *old_dst;
|
|
|
|
sk_tx_queue_clear(sk);
|
|
- sk->sk_dst_pending_confirm = 0;
|
|
+ WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
|
|
old_dst = xchg((__force struct dst_entry **)&sk->sk_dst_cache, dst);
|
|
dst_release(old_dst);
|
|
}
|
|
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
|
|
index 528279056b3ab..1a5f90b0a5463 100644
|
|
--- a/include/sound/soc-acpi.h
|
|
+++ b/include/sound/soc-acpi.h
|
|
@@ -67,6 +67,10 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
|
|
* @i2s_link_mask: I2S/TDM links enabled on the board
|
|
* @num_dai_drivers: number of elements in @dai_drivers
|
|
* @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode
|
|
+ * @subsystem_vendor: optional PCI SSID vendor value
|
|
+ * @subsystem_device: optional PCI SSID device value
|
|
+ * @subsystem_id_set: true if a value has been written to
|
|
+ * subsystem_vendor and subsystem_device.
|
|
*/
|
|
struct snd_soc_acpi_mach_params {
|
|
u32 acpi_ipc_irq_index;
|
|
@@ -79,6 +83,9 @@ struct snd_soc_acpi_mach_params {
|
|
u32 i2s_link_mask;
|
|
u32 num_dai_drivers;
|
|
struct snd_soc_dai_driver *dai_drivers;
|
|
+ unsigned short subsystem_vendor;
|
|
+ unsigned short subsystem_device;
|
|
+ bool subsystem_id_set;
|
|
};
|
|
|
|
/**
|
|
diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h
|
|
index 9d31a5c0db33c..40d3023cf0d16 100644
|
|
--- a/include/sound/soc-card.h
|
|
+++ b/include/sound/soc-card.h
|
|
@@ -44,6 +44,43 @@ int snd_soc_card_add_dai_link(struct snd_soc_card *card,
|
|
void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
|
|
struct snd_soc_dai_link *dai_link);
|
|
|
|
+#ifdef CONFIG_PCI
|
|
+static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card,
|
|
+ unsigned short vendor,
|
|
+ unsigned short device)
|
|
+{
|
|
+ card->pci_subsystem_vendor = vendor;
|
|
+ card->pci_subsystem_device = device;
|
|
+ card->pci_subsystem_set = true;
|
|
+}
|
|
+
|
|
+static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card,
|
|
+ unsigned short *vendor,
|
|
+ unsigned short *device)
|
|
+{
|
|
+ if (!card->pci_subsystem_set)
|
|
+ return -ENOENT;
|
|
+
|
|
+ *vendor = card->pci_subsystem_vendor;
|
|
+ *device = card->pci_subsystem_device;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#else /* !CONFIG_PCI */
|
|
+static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card,
|
|
+ unsigned short vendor,
|
|
+ unsigned short device)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card,
|
|
+ unsigned short *vendor,
|
|
+ unsigned short *device)
|
|
+{
|
|
+ return -ENOENT;
|
|
+}
|
|
+#endif /* CONFIG_PCI */
|
|
+
|
|
/* device driver data */
|
|
static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
|
|
void *data)
|
|
diff --git a/include/sound/soc.h b/include/sound/soc.h
|
|
index 37bbfc8b45cb2..108617cea9c67 100644
|
|
--- a/include/sound/soc.h
|
|
+++ b/include/sound/soc.h
|
|
@@ -911,6 +911,17 @@ struct snd_soc_card {
|
|
#ifdef CONFIG_DMI
|
|
char dmi_longname[80];
|
|
#endif /* CONFIG_DMI */
|
|
+
|
|
+#ifdef CONFIG_PCI
|
|
+ /*
|
|
+ * PCI does not define 0 as invalid, so pci_subsystem_set indicates
|
|
+ * whether a value has been written to these fields.
|
|
+ */
|
|
+ unsigned short pci_subsystem_vendor;
|
|
+ unsigned short pci_subsystem_device;
|
|
+ bool pci_subsystem_set;
|
|
+#endif /* CONFIG_PCI */
|
|
+
|
|
char topology_shortname[32];
|
|
|
|
struct device *dev;
|
|
diff --git a/include/sound/sof.h b/include/sound/sof.h
|
|
index 341fef19e6124..1caeb7bf109b4 100644
|
|
--- a/include/sound/sof.h
|
|
+++ b/include/sound/sof.h
|
|
@@ -63,6 +63,14 @@ struct snd_sof_pdata {
|
|
const char *name;
|
|
const char *platform;
|
|
|
|
+ /*
|
|
+ * PCI SSID. As PCI does not define 0 as invalid, the subsystem_id_set
|
|
+ * flag indicates that a value has been written to these members.
|
|
+ */
|
|
+ unsigned short subsystem_vendor;
|
|
+ unsigned short subsystem_device;
|
|
+ bool subsystem_id_set;
|
|
+
|
|
struct device *dev;
|
|
|
|
/* indicate how many first bytes shouldn't be loaded into DSP memory. */
|
|
diff --git a/include/uapi/linux/vm_sockets.h b/include/uapi/linux/vm_sockets.h
|
|
index c60ca33eac594..ed07181d4eff9 100644
|
|
--- a/include/uapi/linux/vm_sockets.h
|
|
+++ b/include/uapi/linux/vm_sockets.h
|
|
@@ -191,4 +191,21 @@ struct sockaddr_vm {
|
|
|
|
#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9)
|
|
|
|
+/* MSG_ZEROCOPY notifications are encoded in the standard error format,
|
|
+ * sock_extended_err. See Documentation/networking/msg_zerocopy.rst in
|
|
+ * kernel source tree for more details.
|
|
+ */
|
|
+
|
|
+/* 'cmsg_level' field value of 'struct cmsghdr' for notification parsing
|
|
+ * when MSG_ZEROCOPY flag is used on transmissions.
|
|
+ */
|
|
+
|
|
+#define SOL_VSOCK 287
|
|
+
|
|
+/* 'cmsg_type' field value of 'struct cmsghdr' for notification parsing
|
|
+ * when MSG_ZEROCOPY flag is used on transmissions.
|
|
+ */
|
|
+
|
|
+#define VSOCK_RECVERR 1
|
|
+
|
|
#endif /* _UAPI_VM_SOCKETS_H */
|
|
diff --git a/init/main.c b/init/main.c
|
|
index fe378351e8a95..87a52bdb41d67 100644
|
|
--- a/init/main.c
|
|
+++ b/init/main.c
|
|
@@ -533,6 +533,10 @@ static int __init unknown_bootoption(char *param, char *val,
|
|
{
|
|
size_t len = strlen(param);
|
|
|
|
+ /* Handle params aliased to sysctls */
|
|
+ if (sysctl_is_alias(param))
|
|
+ return 0;
|
|
+
|
|
repair_env_string(param, val);
|
|
|
|
/* Handle obsolete-style parameters */
|
|
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
|
|
index 65075f1e4ac8c..7a98cd176a127 100644
|
|
--- a/kernel/audit_watch.c
|
|
+++ b/kernel/audit_watch.c
|
|
@@ -527,11 +527,18 @@ int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark *mark)
|
|
unsigned long ino;
|
|
dev_t dev;
|
|
|
|
- exe_file = get_task_exe_file(tsk);
|
|
+ /* only do exe filtering if we are recording @current events/records */
|
|
+ if (tsk != current)
|
|
+ return 0;
|
|
+
|
|
+ if (!current->mm)
|
|
+ return 0;
|
|
+ exe_file = get_mm_exe_file(current->mm);
|
|
if (!exe_file)
|
|
return 0;
|
|
ino = file_inode(exe_file)->i_ino;
|
|
dev = file_inode(exe_file)->i_sb->s_dev;
|
|
fput(exe_file);
|
|
+
|
|
return audit_mark_compare(mark, ino, dev);
|
|
}
|
|
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
|
|
index 64706723624b9..7225cb67c0d3a 100644
|
|
--- a/kernel/bpf/core.c
|
|
+++ b/kernel/bpf/core.c
|
|
@@ -608,7 +608,11 @@ static __always_inline int bpf_tree_comp(void *key, struct latch_tree_node *n)
|
|
|
|
if (val < ksym->start)
|
|
return -1;
|
|
- if (val >= ksym->end)
|
|
+ /* Ensure that we detect return addresses as part of the program, when
|
|
+ * the final instruction is a call for a program part of the stack
|
|
+ * trace. Therefore, do val > ksym->end instead of val >= ksym->end.
|
|
+ */
|
|
+ if (val > ksym->end)
|
|
return 1;
|
|
|
|
return 0;
|
|
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
|
|
index eb3f52be115d6..12d360d80c149 100644
|
|
--- a/kernel/bpf/verifier.c
|
|
+++ b/kernel/bpf/verifier.c
|
|
@@ -978,7 +978,8 @@ static void print_verifier_state(struct bpf_verifier_env *env,
|
|
if (state->in_async_callback_fn)
|
|
verbose(env, " async_cb");
|
|
verbose(env, "\n");
|
|
- mark_verifier_state_clean(env);
|
|
+ if (!print_all)
|
|
+ mark_verifier_state_clean(env);
|
|
}
|
|
|
|
static inline u32 vlog_alignment(u32 pos)
|
|
@@ -2595,7 +2596,12 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx,
|
|
if (class == BPF_ALU || class == BPF_ALU64) {
|
|
if (!(*reg_mask & dreg))
|
|
return 0;
|
|
- if (opcode == BPF_MOV) {
|
|
+ if (opcode == BPF_END || opcode == BPF_NEG) {
|
|
+ /* sreg is reserved and unused
|
|
+ * dreg still need precision before this insn
|
|
+ */
|
|
+ return 0;
|
|
+ } else if (opcode == BPF_MOV) {
|
|
if (BPF_SRC(insn->code) == BPF_X) {
|
|
/* dreg = sreg
|
|
* dreg needs precision after this insn
|
|
@@ -3291,7 +3297,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
insn->imm != 0 && env->bpf_capable) {
|
|
struct bpf_reg_state fake_reg = {};
|
|
|
|
- __mark_reg_known(&fake_reg, (u32)insn->imm);
|
|
+ __mark_reg_known(&fake_reg, insn->imm);
|
|
fake_reg.type = SCALAR_VALUE;
|
|
save_register_state(state, spi, &fake_reg, size);
|
|
} else if (reg && is_spillable_regtype(reg->type)) {
|
|
@@ -10476,6 +10482,8 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
|
!sanitize_speculative_path(env, insn, *insn_idx + 1,
|
|
*insn_idx))
|
|
return -EFAULT;
|
|
+ if (env->log.level & BPF_LOG_LEVEL)
|
|
+ print_insn_state(env, this_branch->frame[this_branch->curframe]);
|
|
*insn_idx += insn->off;
|
|
return 0;
|
|
} else if (pred == 0) {
|
|
@@ -10488,6 +10496,8 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
|
*insn_idx + insn->off + 1,
|
|
*insn_idx))
|
|
return -EFAULT;
|
|
+ if (env->log.level & BPF_LOG_LEVEL)
|
|
+ print_insn_state(env, this_branch->frame[this_branch->curframe]);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/kernel/cpu.c b/kernel/cpu.c
|
|
index f8eb1825f704f..0e4d362e90825 100644
|
|
--- a/kernel/cpu.c
|
|
+++ b/kernel/cpu.c
|
|
@@ -1243,11 +1243,14 @@ static int cpu_down_maps_locked(unsigned int cpu, enum cpuhp_state target)
|
|
/*
|
|
* Ensure that the control task does not run on the to be offlined
|
|
* CPU to prevent a deadlock against cfs_b->period_timer.
|
|
+ * Also keep at least one housekeeping cpu onlined to avoid generating
|
|
+ * an empty sched_domain span.
|
|
*/
|
|
- cpu = cpumask_any_but(cpu_online_mask, cpu);
|
|
- if (cpu >= nr_cpu_ids)
|
|
- return -EBUSY;
|
|
- return work_on_cpu(cpu, __cpu_down_maps_locked, &work);
|
|
+ for_each_cpu_and(cpu, cpu_online_mask, housekeeping_cpumask(HK_TYPE_DOMAIN)) {
|
|
+ if (cpu != work.cpu)
|
|
+ return work_on_cpu(cpu, __cpu_down_maps_locked, &work);
|
|
+ }
|
|
+ return -EBUSY;
|
|
}
|
|
|
|
static int cpu_down(unsigned int cpu, enum cpuhp_state target)
|
|
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
|
|
index d5e9ccde3ab8e..3a904d8697c8f 100644
|
|
--- a/kernel/debug/debug_core.c
|
|
+++ b/kernel/debug/debug_core.c
|
|
@@ -1006,6 +1006,9 @@ void kgdb_panic(const char *msg)
|
|
if (panic_timeout)
|
|
return;
|
|
|
|
+ debug_locks_off();
|
|
+ console_flush_on_panic(CONSOLE_FLUSH_PENDING);
|
|
+
|
|
if (dbg_kdb_mode)
|
|
kdb_printf("PANIC: %s\n", msg);
|
|
|
|
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
|
|
index 273a0fe7910a5..45965f13757e4 100644
|
|
--- a/kernel/events/ring_buffer.c
|
|
+++ b/kernel/events/ring_buffer.c
|
|
@@ -699,6 +699,12 @@ int rb_alloc_aux(struct perf_buffer *rb, struct perf_event *event,
|
|
watermark = 0;
|
|
}
|
|
|
|
+ /*
|
|
+ * kcalloc_node() is unable to allocate buffer if the size is larger
|
|
+ * than: PAGE_SIZE << MAX_ORDER; directly bail out in this case.
|
|
+ */
|
|
+ if (get_order((unsigned long)nr_pages * sizeof(void *)) > MAX_ORDER)
|
|
+ return -ENOMEM;
|
|
rb->aux_pages = kcalloc_node(nr_pages, sizeof(void *), GFP_KERNEL,
|
|
node);
|
|
if (!rb->aux_pages)
|
|
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
|
|
index c653cd31548d0..5a452b94b6434 100644
|
|
--- a/kernel/irq/generic-chip.c
|
|
+++ b/kernel/irq/generic-chip.c
|
|
@@ -544,21 +544,34 @@ EXPORT_SYMBOL_GPL(irq_setup_alt_chip);
|
|
void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
|
|
unsigned int clr, unsigned int set)
|
|
{
|
|
- unsigned int i = gc->irq_base;
|
|
+ unsigned int i, virq;
|
|
|
|
raw_spin_lock(&gc_lock);
|
|
list_del(&gc->list);
|
|
raw_spin_unlock(&gc_lock);
|
|
|
|
- for (; msk; msk >>= 1, i++) {
|
|
+ for (i = 0; msk; msk >>= 1, i++) {
|
|
if (!(msk & 0x01))
|
|
continue;
|
|
|
|
+ /*
|
|
+ * Interrupt domain based chips store the base hardware
|
|
+ * interrupt number in gc::irq_base. Otherwise gc::irq_base
|
|
+ * contains the base Linux interrupt number.
|
|
+ */
|
|
+ if (gc->domain) {
|
|
+ virq = irq_find_mapping(gc->domain, gc->irq_base + i);
|
|
+ if (!virq)
|
|
+ continue;
|
|
+ } else {
|
|
+ virq = gc->irq_base + i;
|
|
+ }
|
|
+
|
|
/* Remove handler first. That will mask the irq line */
|
|
- irq_set_handler(i, NULL);
|
|
- irq_set_chip(i, &no_irq_chip);
|
|
- irq_set_chip_data(i, NULL);
|
|
- irq_modify_status(i, clr, set);
|
|
+ irq_set_handler(virq, NULL);
|
|
+ irq_set_chip(virq, &no_irq_chip);
|
|
+ irq_set_chip_data(virq, NULL);
|
|
+ irq_modify_status(virq, clr, set);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(irq_remove_generic_chip);
|
|
diff --git a/kernel/kexec.c b/kernel/kexec.c
|
|
index cb8e6e6f983c7..5ff1dcc4acb78 100644
|
|
--- a/kernel/kexec.c
|
|
+++ b/kernel/kexec.c
|
|
@@ -240,7 +240,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
|
|
((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT))
|
|
return -EINVAL;
|
|
|
|
- ksegments = memdup_user(segments, nr_segments * sizeof(ksegments[0]));
|
|
+ ksegments = memdup_array_user(segments, nr_segments, sizeof(ksegments[0]));
|
|
if (IS_ERR(ksegments))
|
|
return PTR_ERR(ksegments);
|
|
|
|
diff --git a/kernel/locking/test-ww_mutex.c b/kernel/locking/test-ww_mutex.c
|
|
index 43efb2a041602..b1e25695185a4 100644
|
|
--- a/kernel/locking/test-ww_mutex.c
|
|
+++ b/kernel/locking/test-ww_mutex.c
|
|
@@ -466,7 +466,6 @@ retry:
|
|
} while (!time_after(jiffies, stress->timeout));
|
|
|
|
kfree(order);
|
|
- kfree(stress);
|
|
}
|
|
|
|
struct reorder_lock {
|
|
@@ -531,7 +530,6 @@ out:
|
|
list_for_each_entry_safe(ll, ln, &locks, link)
|
|
kfree(ll);
|
|
kfree(order);
|
|
- kfree(stress);
|
|
}
|
|
|
|
static void stress_one_work(struct work_struct *work)
|
|
@@ -552,8 +550,6 @@ static void stress_one_work(struct work_struct *work)
|
|
break;
|
|
}
|
|
} while (!time_after(jiffies, stress->timeout));
|
|
-
|
|
- kfree(stress);
|
|
}
|
|
|
|
#define STRESS_INORDER BIT(0)
|
|
@@ -564,15 +560,24 @@ static void stress_one_work(struct work_struct *work)
|
|
static int stress(int nlocks, int nthreads, unsigned int flags)
|
|
{
|
|
struct ww_mutex *locks;
|
|
- int n;
|
|
+ struct stress *stress_array;
|
|
+ int n, count;
|
|
|
|
locks = kmalloc_array(nlocks, sizeof(*locks), GFP_KERNEL);
|
|
if (!locks)
|
|
return -ENOMEM;
|
|
|
|
+ stress_array = kmalloc_array(nthreads, sizeof(*stress_array),
|
|
+ GFP_KERNEL);
|
|
+ if (!stress_array) {
|
|
+ kfree(locks);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
for (n = 0; n < nlocks; n++)
|
|
ww_mutex_init(&locks[n], &ww_class);
|
|
|
|
+ count = 0;
|
|
for (n = 0; nthreads; n++) {
|
|
struct stress *stress;
|
|
void (*fn)(struct work_struct *work);
|
|
@@ -596,9 +601,7 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
|
|
if (!fn)
|
|
continue;
|
|
|
|
- stress = kmalloc(sizeof(*stress), GFP_KERNEL);
|
|
- if (!stress)
|
|
- break;
|
|
+ stress = &stress_array[count++];
|
|
|
|
INIT_WORK(&stress->work, fn);
|
|
stress->locks = locks;
|
|
@@ -613,6 +616,7 @@ static int stress(int nlocks, int nthreads, unsigned int flags)
|
|
|
|
for (n = 0; n < nlocks; n++)
|
|
ww_mutex_destroy(&locks[n]);
|
|
+ kfree(stress_array);
|
|
kfree(locks);
|
|
|
|
return 0;
|
|
diff --git a/kernel/padata.c b/kernel/padata.c
|
|
index 791d9cb07a501..7bef7dae3db54 100644
|
|
--- a/kernel/padata.c
|
|
+++ b/kernel/padata.c
|
|
@@ -194,7 +194,7 @@ int padata_do_parallel(struct padata_shell *ps,
|
|
*cb_cpu = cpu;
|
|
}
|
|
|
|
- err = -EBUSY;
|
|
+ err = -EBUSY;
|
|
if ((pinst->flags & PADATA_RESET))
|
|
goto out;
|
|
|
|
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
|
|
index c20ca5fb9adc8..03c4ca4048e3e 100644
|
|
--- a/kernel/power/snapshot.c
|
|
+++ b/kernel/power/snapshot.c
|
|
@@ -2418,8 +2418,9 @@ static void *get_highmem_page_buffer(struct page *page,
|
|
pbe->copy_page = tmp;
|
|
} else {
|
|
/* Copy of the page will be stored in normal memory */
|
|
- kaddr = safe_pages_list;
|
|
- safe_pages_list = safe_pages_list->next;
|
|
+ kaddr = __get_safe_page(ca->gfp_mask);
|
|
+ if (!kaddr)
|
|
+ return ERR_PTR(-ENOMEM);
|
|
pbe->copy_page = virt_to_page(kaddr);
|
|
}
|
|
pbe->next = highmem_pblist;
|
|
@@ -2599,8 +2600,9 @@ static void *get_buffer(struct memory_bitmap *bm, struct chain_allocator *ca)
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
pbe->orig_address = page_address(page);
|
|
- pbe->address = safe_pages_list;
|
|
- safe_pages_list = safe_pages_list->next;
|
|
+ pbe->address = __get_safe_page(ca->gfp_mask);
|
|
+ if (!pbe->address)
|
|
+ return ERR_PTR(-ENOMEM);
|
|
pbe->next = restore_pblist;
|
|
restore_pblist = pbe;
|
|
return pbe->address;
|
|
@@ -2631,8 +2633,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
|
|
if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages)
|
|
return 0;
|
|
|
|
- handle->sync_read = 1;
|
|
-
|
|
if (!handle->cur) {
|
|
if (!buffer)
|
|
/* This makes the buffer be freed by swsusp_free() */
|
|
@@ -2668,7 +2668,6 @@ int snapshot_write_next(struct snapshot_handle *handle)
|
|
memory_bm_position_reset(&orig_bm);
|
|
restore_pblist = NULL;
|
|
handle->buffer = get_buffer(&orig_bm, &ca);
|
|
- handle->sync_read = 0;
|
|
if (IS_ERR(handle->buffer))
|
|
return PTR_ERR(handle->buffer);
|
|
}
|
|
@@ -2678,9 +2677,8 @@ int snapshot_write_next(struct snapshot_handle *handle)
|
|
handle->buffer = get_buffer(&orig_bm, &ca);
|
|
if (IS_ERR(handle->buffer))
|
|
return PTR_ERR(handle->buffer);
|
|
- if (handle->buffer != buffer)
|
|
- handle->sync_read = 0;
|
|
}
|
|
+ handle->sync_read = (handle->buffer == buffer);
|
|
handle->cur++;
|
|
return PAGE_SIZE;
|
|
}
|
|
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
|
|
index 4db36d543be37..8fdf076720384 100644
|
|
--- a/kernel/rcu/srcutree.c
|
|
+++ b/kernel/rcu/srcutree.c
|
|
@@ -223,7 +223,7 @@ static bool init_srcu_struct_nodes(struct srcu_struct *ssp, gfp_t gfp_flags)
|
|
snp->grplo = cpu;
|
|
snp->grphi = cpu;
|
|
}
|
|
- sdp->grpmask = 1 << (cpu - sdp->mynode->grplo);
|
|
+ sdp->grpmask = 1UL << (cpu - sdp->mynode->grplo);
|
|
}
|
|
smp_store_release(&ssp->srcu_size_state, SRCU_SIZE_WAIT_BARRIER);
|
|
return true;
|
|
@@ -722,7 +722,7 @@ static void srcu_schedule_cbs_snp(struct srcu_struct *ssp, struct srcu_node *snp
|
|
int cpu;
|
|
|
|
for (cpu = snp->grplo; cpu <= snp->grphi; cpu++) {
|
|
- if (!(mask & (1 << (cpu - snp->grplo))))
|
|
+ if (!(mask & (1UL << (cpu - snp->grplo))))
|
|
continue;
|
|
srcu_schedule_cbs_sdp(per_cpu_ptr(ssp->sda, cpu), delay);
|
|
}
|
|
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
|
|
index 917a1e43f7839..15df37bc052a9 100644
|
|
--- a/kernel/rcu/tree.c
|
|
+++ b/kernel/rcu/tree.c
|
|
@@ -31,6 +31,7 @@
|
|
#include <linux/bitops.h>
|
|
#include <linux/export.h>
|
|
#include <linux/completion.h>
|
|
+#include <linux/kmemleak.h>
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/panic.h>
|
|
#include <linux/panic_notifier.h>
|
|
@@ -1604,10 +1605,22 @@ static bool rcu_gp_fqs_check_wake(int *gfp)
|
|
*/
|
|
static void rcu_gp_fqs(bool first_time)
|
|
{
|
|
+ int nr_fqs = READ_ONCE(rcu_state.nr_fqs_jiffies_stall);
|
|
struct rcu_node *rnp = rcu_get_root();
|
|
|
|
WRITE_ONCE(rcu_state.gp_activity, jiffies);
|
|
WRITE_ONCE(rcu_state.n_force_qs, rcu_state.n_force_qs + 1);
|
|
+
|
|
+ WARN_ON_ONCE(nr_fqs > 3);
|
|
+ /* Only countdown nr_fqs for stall purposes if jiffies moves. */
|
|
+ if (nr_fqs) {
|
|
+ if (nr_fqs == 1) {
|
|
+ WRITE_ONCE(rcu_state.jiffies_stall,
|
|
+ jiffies + rcu_jiffies_till_stall_check());
|
|
+ }
|
|
+ WRITE_ONCE(rcu_state.nr_fqs_jiffies_stall, --nr_fqs);
|
|
+ }
|
|
+
|
|
if (first_time) {
|
|
/* Collect dyntick-idle snapshots. */
|
|
force_qs_rnp(dyntick_save_progress_counter);
|
|
@@ -3369,6 +3382,14 @@ void kvfree_call_rcu(struct rcu_head *head, rcu_callback_t func)
|
|
|
|
WRITE_ONCE(krcp->count, krcp->count + 1);
|
|
|
|
+ /*
|
|
+ * The kvfree_rcu() caller considers the pointer freed at this point
|
|
+ * and likely removes any references to it. Since the actual slab
|
|
+ * freeing (and kmemleak_free()) is deferred, tell kmemleak to ignore
|
|
+ * this object (no scanning or false positives reporting).
|
|
+ */
|
|
+ kmemleak_ignore(ptr);
|
|
+
|
|
// Set timer to drain after KFREE_DRAIN_JIFFIES.
|
|
if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING)
|
|
schedule_delayed_monitor_work(krcp);
|
|
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
|
|
index d4a97e40ea9c3..7b702220d81cb 100644
|
|
--- a/kernel/rcu/tree.h
|
|
+++ b/kernel/rcu/tree.h
|
|
@@ -365,6 +365,10 @@ struct rcu_state {
|
|
/* in jiffies. */
|
|
unsigned long jiffies_stall; /* Time at which to check */
|
|
/* for CPU stalls. */
|
|
+ int nr_fqs_jiffies_stall; /* Number of fqs loops after
|
|
+ * which read jiffies and set
|
|
+ * jiffies_stall. Stall
|
|
+ * warnings disabled if !0. */
|
|
unsigned long jiffies_resched; /* Time at which to resched */
|
|
/* a reluctant CPU. */
|
|
unsigned long n_force_qs_gpstart; /* Snapshot of n_force_qs at */
|
|
diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
|
|
index 5653560573e22..7d15b5b5a235a 100644
|
|
--- a/kernel/rcu/tree_stall.h
|
|
+++ b/kernel/rcu/tree_stall.h
|
|
@@ -149,12 +149,17 @@ static void panic_on_rcu_stall(void)
|
|
/**
|
|
* rcu_cpu_stall_reset - restart stall-warning timeout for current grace period
|
|
*
|
|
+ * To perform the reset request from the caller, disable stall detection until
|
|
+ * 3 fqs loops have passed. This is required to ensure a fresh jiffies is
|
|
+ * loaded. It should be safe to do from the fqs loop as enough timer
|
|
+ * interrupts and context switches should have passed.
|
|
+ *
|
|
* The caller must disable hard irqs.
|
|
*/
|
|
void rcu_cpu_stall_reset(void)
|
|
{
|
|
- WRITE_ONCE(rcu_state.jiffies_stall,
|
|
- jiffies + rcu_jiffies_till_stall_check());
|
|
+ WRITE_ONCE(rcu_state.nr_fqs_jiffies_stall, 3);
|
|
+ WRITE_ONCE(rcu_state.jiffies_stall, ULONG_MAX);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
@@ -170,6 +175,7 @@ static void record_gp_stall_check_time(void)
|
|
WRITE_ONCE(rcu_state.gp_start, j);
|
|
j1 = rcu_jiffies_till_stall_check();
|
|
smp_mb(); // ->gp_start before ->jiffies_stall and caller's ->gp_seq.
|
|
+ WRITE_ONCE(rcu_state.nr_fqs_jiffies_stall, 0);
|
|
WRITE_ONCE(rcu_state.jiffies_stall, j + j1);
|
|
rcu_state.jiffies_resched = j + j1 / 2;
|
|
rcu_state.n_force_qs_gpstart = READ_ONCE(rcu_state.n_force_qs);
|
|
@@ -694,6 +700,16 @@ static void check_cpu_stall(struct rcu_data *rdp)
|
|
!rcu_gp_in_progress())
|
|
return;
|
|
rcu_stall_kick_kthreads();
|
|
+
|
|
+ /*
|
|
+ * Check if it was requested (via rcu_cpu_stall_reset()) that the FQS
|
|
+ * loop has to set jiffies to ensure a non-stale jiffies value. This
|
|
+ * is required to have good jiffies value after coming out of long
|
|
+ * breaks of jiffies updates. Not doing so can cause false positives.
|
|
+ */
|
|
+ if (READ_ONCE(rcu_state.nr_fqs_jiffies_stall) > 0)
|
|
+ return;
|
|
+
|
|
j = jiffies;
|
|
|
|
/*
|
|
diff --git a/kernel/reboot.c b/kernel/reboot.c
|
|
index 3bba88c7ffc6b..6ebef11c88760 100644
|
|
--- a/kernel/reboot.c
|
|
+++ b/kernel/reboot.c
|
|
@@ -74,6 +74,7 @@ void __weak (*pm_power_off)(void);
|
|
void emergency_restart(void)
|
|
{
|
|
kmsg_dump(KMSG_DUMP_EMERG);
|
|
+ system_state = SYSTEM_RESTART;
|
|
machine_emergency_restart();
|
|
}
|
|
EXPORT_SYMBOL_GPL(emergency_restart);
|
|
diff --git a/kernel/smp.c b/kernel/smp.c
|
|
index 06a413987a14a..63e466bb6b03a 100644
|
|
--- a/kernel/smp.c
|
|
+++ b/kernel/smp.c
|
|
@@ -185,6 +185,8 @@ static DEFINE_PER_CPU(struct cfd_seq_local, cfd_seq_local);
|
|
|
|
static ulong csd_lock_timeout = 5000; /* CSD lock timeout in milliseconds. */
|
|
module_param(csd_lock_timeout, ulong, 0444);
|
|
+static int panic_on_ipistall; /* CSD panic timeout in milliseconds, 300000 for five minutes. */
|
|
+module_param(panic_on_ipistall, int, 0444);
|
|
|
|
static atomic_t csd_bug_count = ATOMIC_INIT(0);
|
|
static u64 cfd_seq;
|
|
@@ -343,6 +345,7 @@ static bool csd_lock_wait_toolong(struct __call_single_data *csd, u64 ts0, u64 *
|
|
}
|
|
|
|
ts2 = sched_clock();
|
|
+ /* How long since we last checked for a stuck CSD lock.*/
|
|
ts_delta = ts2 - *ts1;
|
|
if (likely(ts_delta <= csd_lock_timeout_ns || csd_lock_timeout_ns == 0))
|
|
return false;
|
|
@@ -356,9 +359,17 @@ static bool csd_lock_wait_toolong(struct __call_single_data *csd, u64 ts0, u64 *
|
|
else
|
|
cpux = cpu;
|
|
cpu_cur_csd = smp_load_acquire(&per_cpu(cur_csd, cpux)); /* Before func and info. */
|
|
+ /* How long since this CSD lock was stuck. */
|
|
+ ts_delta = ts2 - ts0;
|
|
pr_alert("csd: %s non-responsive CSD lock (#%d) on CPU#%d, waiting %llu ns for CPU#%02d %pS(%ps).\n",
|
|
- firsttime ? "Detected" : "Continued", *bug_id, raw_smp_processor_id(), ts2 - ts0,
|
|
+ firsttime ? "Detected" : "Continued", *bug_id, raw_smp_processor_id(), ts_delta,
|
|
cpu, csd->func, csd->info);
|
|
+ /*
|
|
+ * If the CSD lock is still stuck after 5 minutes, it is unlikely
|
|
+ * to become unstuck. Use a signed comparison to avoid triggering
|
|
+ * on underflows when the TSC is out of sync between sockets.
|
|
+ */
|
|
+ BUG_ON(panic_on_ipistall > 0 && (s64)ts_delta > ((s64)panic_on_ipistall * NSEC_PER_MSEC));
|
|
if (cpu_cur_csd && csd != cpu_cur_csd) {
|
|
pr_alert("\tcsd: CSD lock (#%d) handling prior %pS(%ps) request.\n",
|
|
*bug_id, READ_ONCE(per_cpu(cur_csd_func, cpux)),
|
|
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
|
|
index 9db92a6e14636..ddcfc78e93e00 100644
|
|
--- a/kernel/trace/trace.c
|
|
+++ b/kernel/trace/trace.c
|
|
@@ -4912,6 +4912,20 @@ int tracing_open_file_tr(struct inode *inode, struct file *filp)
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ mutex_lock(&event_mutex);
|
|
+
|
|
+ /* Fail if the file is marked for removal */
|
|
+ if (file->flags & EVENT_FILE_FL_FREED) {
|
|
+ trace_array_put(file->tr);
|
|
+ ret = -ENODEV;
|
|
+ } else {
|
|
+ event_file_get(file);
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&event_mutex);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
filp->private_data = inode->i_private;
|
|
|
|
return 0;
|
|
@@ -4922,6 +4936,7 @@ int tracing_release_file_tr(struct inode *inode, struct file *filp)
|
|
struct trace_event_file *file = inode->i_private;
|
|
|
|
trace_array_put(file->tr);
|
|
+ event_file_put(file);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
|
|
index 7e6d5101bdb05..10aaafa2936dc 100644
|
|
--- a/kernel/trace/trace.h
|
|
+++ b/kernel/trace/trace.h
|
|
@@ -1631,6 +1631,9 @@ extern void event_trigger_unregister(struct event_command *cmd_ops,
|
|
char *glob,
|
|
struct event_trigger_data *trigger_data);
|
|
|
|
+extern void event_file_get(struct trace_event_file *file);
|
|
+extern void event_file_put(struct trace_event_file *file);
|
|
+
|
|
/**
|
|
* struct event_trigger_ops - callbacks for trace event triggers
|
|
*
|
|
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
|
|
index 2e3dce5e2575e..a6d2f99f847d3 100644
|
|
--- a/kernel/trace/trace_events.c
|
|
+++ b/kernel/trace/trace_events.c
|
|
@@ -988,26 +988,38 @@ static void remove_subsystem(struct trace_subsystem_dir *dir)
|
|
}
|
|
}
|
|
|
|
-static void remove_event_file_dir(struct trace_event_file *file)
|
|
+void event_file_get(struct trace_event_file *file)
|
|
{
|
|
- struct dentry *dir = file->dir;
|
|
- struct dentry *child;
|
|
+ atomic_inc(&file->ref);
|
|
+}
|
|
|
|
- if (dir) {
|
|
- spin_lock(&dir->d_lock); /* probably unneeded */
|
|
- list_for_each_entry(child, &dir->d_subdirs, d_child) {
|
|
- if (d_really_is_positive(child)) /* probably unneeded */
|
|
- d_inode(child)->i_private = NULL;
|
|
- }
|
|
- spin_unlock(&dir->d_lock);
|
|
+void event_file_put(struct trace_event_file *file)
|
|
+{
|
|
+ if (WARN_ON_ONCE(!atomic_read(&file->ref))) {
|
|
+ if (file->flags & EVENT_FILE_FL_FREED)
|
|
+ kmem_cache_free(file_cachep, file);
|
|
+ return;
|
|
+ }
|
|
|
|
- tracefs_remove(dir);
|
|
+ if (atomic_dec_and_test(&file->ref)) {
|
|
+ /* Count should only go to zero when it is freed */
|
|
+ if (WARN_ON_ONCE(!(file->flags & EVENT_FILE_FL_FREED)))
|
|
+ return;
|
|
+ kmem_cache_free(file_cachep, file);
|
|
}
|
|
+}
|
|
+
|
|
+static void remove_event_file_dir(struct trace_event_file *file)
|
|
+{
|
|
+ struct dentry *dir = file->dir;
|
|
+
|
|
+ tracefs_remove(dir);
|
|
|
|
list_del(&file->list);
|
|
remove_subsystem(file->system);
|
|
free_event_filter(file->filter);
|
|
- kmem_cache_free(file_cachep, file);
|
|
+ file->flags |= EVENT_FILE_FL_FREED;
|
|
+ event_file_put(file);
|
|
}
|
|
|
|
/*
|
|
@@ -1380,7 +1392,7 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
|
|
flags = file->flags;
|
|
mutex_unlock(&event_mutex);
|
|
|
|
- if (!file)
|
|
+ if (!file || flags & EVENT_FILE_FL_FREED)
|
|
return -ENODEV;
|
|
|
|
if (flags & EVENT_FILE_FL_ENABLED &&
|
|
@@ -1418,7 +1430,7 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
|
|
ret = -ENODEV;
|
|
mutex_lock(&event_mutex);
|
|
file = event_file_data(filp);
|
|
- if (likely(file))
|
|
+ if (likely(file && !(file->flags & EVENT_FILE_FL_FREED)))
|
|
ret = ftrace_event_enable_disable(file, val);
|
|
mutex_unlock(&event_mutex);
|
|
break;
|
|
@@ -1692,7 +1704,7 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
|
|
|
|
mutex_lock(&event_mutex);
|
|
file = event_file_data(filp);
|
|
- if (file)
|
|
+ if (file && !(file->flags & EVENT_FILE_FL_FREED))
|
|
print_event_filter(file, s);
|
|
mutex_unlock(&event_mutex);
|
|
|
|
@@ -2810,6 +2822,7 @@ trace_create_new_event(struct trace_event_call *call,
|
|
atomic_set(&file->tm_ref, 0);
|
|
INIT_LIST_HEAD(&file->triggers);
|
|
list_add(&file->list, &tr->events);
|
|
+ event_file_get(file);
|
|
|
|
return file;
|
|
}
|
|
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
|
|
index 96acc2b71ac74..86a0531efd43d 100644
|
|
--- a/kernel/trace/trace_events_filter.c
|
|
+++ b/kernel/trace/trace_events_filter.c
|
|
@@ -1997,6 +1997,9 @@ int apply_event_filter(struct trace_event_file *file, char *filter_string)
|
|
struct event_filter *filter = NULL;
|
|
int err;
|
|
|
|
+ if (file->flags & EVENT_FILE_FL_FREED)
|
|
+ return -ENODEV;
|
|
+
|
|
if (!strcmp(strstrip(filter_string), "0")) {
|
|
filter_disable(file);
|
|
filter = event_filter(file);
|
|
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
|
|
index b0d3876c96ab2..94a2e9d21f582 100644
|
|
--- a/kernel/trace/trace_events_synth.c
|
|
+++ b/kernel/trace/trace_events_synth.c
|
|
@@ -473,7 +473,7 @@ static unsigned int trace_string(struct synth_trace_event *entry,
|
|
|
|
#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
|
|
if ((unsigned long)str_val < TASK_SIZE)
|
|
- ret = strncpy_from_user_nofault(str_field, str_val, STR_VAR_LEN_MAX);
|
|
+ ret = strncpy_from_user_nofault(str_field, (const void __user *)str_val, STR_VAR_LEN_MAX);
|
|
else
|
|
#endif
|
|
ret = strncpy_from_kernel_nofault(str_field, str_val, STR_VAR_LEN_MAX);
|
|
diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c
|
|
index 28ed71d277bd7..442bb92212f2a 100644
|
|
--- a/kernel/watch_queue.c
|
|
+++ b/kernel/watch_queue.c
|
|
@@ -332,7 +332,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,
|
|
filter.__reserved != 0)
|
|
return -EINVAL;
|
|
|
|
- tf = memdup_user(_filter->filters, filter.nr_filters * sizeof(*tf));
|
|
+ tf = memdup_array_user(_filter->filters, filter.nr_filters, sizeof(*tf));
|
|
if (IS_ERR(tf))
|
|
return PTR_ERR(tf);
|
|
|
|
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
|
|
index 8e61f21e7e33e..45693fb3e08de 100644
|
|
--- a/kernel/watchdog.c
|
|
+++ b/kernel/watchdog.c
|
|
@@ -183,6 +183,13 @@ static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
|
|
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
|
|
static unsigned long soft_lockup_nmi_warn;
|
|
|
|
+static int __init softlockup_panic_setup(char *str)
|
|
+{
|
|
+ softlockup_panic = simple_strtoul(str, NULL, 0);
|
|
+ return 1;
|
|
+}
|
|
+__setup("softlockup_panic=", softlockup_panic_setup);
|
|
+
|
|
static int __init nowatchdog_setup(char *str)
|
|
{
|
|
watchdog_user_enabled = 0;
|
|
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
|
|
index bc1a97ee40b21..f3b6ac232e219 100644
|
|
--- a/kernel/workqueue.c
|
|
+++ b/kernel/workqueue.c
|
|
@@ -5185,50 +5185,54 @@ static void work_for_cpu_fn(struct work_struct *work)
|
|
}
|
|
|
|
/**
|
|
- * work_on_cpu - run a function in thread context on a particular cpu
|
|
+ * work_on_cpu_key - run a function in thread context on a particular cpu
|
|
* @cpu: the cpu to run on
|
|
* @fn: the function to run
|
|
* @arg: the function arg
|
|
+ * @key: The lock class key for lock debugging purposes
|
|
*
|
|
* It is up to the caller to ensure that the cpu doesn't go offline.
|
|
* The caller must not hold any locks which would prevent @fn from completing.
|
|
*
|
|
* Return: The value @fn returns.
|
|
*/
|
|
-long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
|
|
+long work_on_cpu_key(int cpu, long (*fn)(void *),
|
|
+ void *arg, struct lock_class_key *key)
|
|
{
|
|
struct work_for_cpu wfc = { .fn = fn, .arg = arg };
|
|
|
|
- INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
|
|
+ INIT_WORK_ONSTACK_KEY(&wfc.work, work_for_cpu_fn, key);
|
|
schedule_work_on(cpu, &wfc.work);
|
|
flush_work(&wfc.work);
|
|
destroy_work_on_stack(&wfc.work);
|
|
return wfc.ret;
|
|
}
|
|
-EXPORT_SYMBOL_GPL(work_on_cpu);
|
|
+EXPORT_SYMBOL_GPL(work_on_cpu_key);
|
|
|
|
/**
|
|
- * work_on_cpu_safe - run a function in thread context on a particular cpu
|
|
+ * work_on_cpu_safe_key - run a function in thread context on a particular cpu
|
|
* @cpu: the cpu to run on
|
|
* @fn: the function to run
|
|
* @arg: the function argument
|
|
+ * @key: The lock class key for lock debugging purposes
|
|
*
|
|
* Disables CPU hotplug and calls work_on_cpu(). The caller must not hold
|
|
* any locks which would prevent @fn from completing.
|
|
*
|
|
* Return: The value @fn returns.
|
|
*/
|
|
-long work_on_cpu_safe(int cpu, long (*fn)(void *), void *arg)
|
|
+long work_on_cpu_safe_key(int cpu, long (*fn)(void *),
|
|
+ void *arg, struct lock_class_key *key)
|
|
{
|
|
long ret = -ENODEV;
|
|
|
|
cpus_read_lock();
|
|
if (cpu_online(cpu))
|
|
- ret = work_on_cpu(cpu, fn, arg);
|
|
+ ret = work_on_cpu_key(cpu, fn, arg, key);
|
|
cpus_read_unlock();
|
|
return ret;
|
|
}
|
|
-EXPORT_SYMBOL_GPL(work_on_cpu_safe);
|
|
+EXPORT_SYMBOL_GPL(work_on_cpu_safe_key);
|
|
#endif /* CONFIG_SMP */
|
|
|
|
#ifdef CONFIG_FREEZER
|
|
diff --git a/lib/generic-radix-tree.c b/lib/generic-radix-tree.c
|
|
index f25eb111c0516..7dfa88282b006 100644
|
|
--- a/lib/generic-radix-tree.c
|
|
+++ b/lib/generic-radix-tree.c
|
|
@@ -166,6 +166,10 @@ void *__genradix_iter_peek(struct genradix_iter *iter,
|
|
struct genradix_root *r;
|
|
struct genradix_node *n;
|
|
unsigned level, i;
|
|
+
|
|
+ if (iter->offset == SIZE_MAX)
|
|
+ return NULL;
|
|
+
|
|
restart:
|
|
r = READ_ONCE(radix->root);
|
|
if (!r)
|
|
@@ -184,10 +188,17 @@ restart:
|
|
(GENRADIX_ARY - 1);
|
|
|
|
while (!n->children[i]) {
|
|
+ size_t objs_per_ptr = genradix_depth_size(level);
|
|
+
|
|
+ if (iter->offset + objs_per_ptr < iter->offset) {
|
|
+ iter->offset = SIZE_MAX;
|
|
+ iter->pos = SIZE_MAX;
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
i++;
|
|
- iter->offset = round_down(iter->offset +
|
|
- genradix_depth_size(level),
|
|
- genradix_depth_size(level));
|
|
+ iter->offset = round_down(iter->offset + objs_per_ptr,
|
|
+ objs_per_ptr);
|
|
iter->pos = (iter->offset >> PAGE_SHIFT) *
|
|
objs_per_page;
|
|
if (i == GENRADIX_ARY)
|
|
diff --git a/mm/cma.c b/mm/cma.c
|
|
index 4a978e09547a8..30b6ca30009bb 100644
|
|
--- a/mm/cma.c
|
|
+++ b/mm/cma.c
|
|
@@ -500,7 +500,7 @@ struct page *cma_alloc(struct cma *cma, unsigned long count,
|
|
*/
|
|
if (page) {
|
|
for (i = 0; i < count; i++)
|
|
- page_kasan_tag_reset(page + i);
|
|
+ page_kasan_tag_reset(nth_page(page, i));
|
|
}
|
|
|
|
if (ret && !no_warn) {
|
|
diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
|
|
index efbc2bda8b9cd..63bdad20dbaf8 100644
|
|
--- a/mm/damon/lru_sort.c
|
|
+++ b/mm/damon/lru_sort.c
|
|
@@ -195,9 +195,7 @@ static int damon_lru_sort_apply_parameters(void)
|
|
if (err)
|
|
return err;
|
|
|
|
- /* aggr_interval / sample_interval is the maximum nr_accesses */
|
|
- hot_thres = damon_lru_sort_mon_attrs.aggr_interval /
|
|
- damon_lru_sort_mon_attrs.sample_interval *
|
|
+ hot_thres = damon_max_nr_accesses(&damon_lru_sort_mon_attrs) *
|
|
hot_thres_access_freq / 1000;
|
|
scheme = damon_lru_sort_new_hot_scheme(hot_thres);
|
|
if (!scheme)
|
|
diff --git a/mm/damon/ops-common.c b/mm/damon/ops-common.c
|
|
index 13b99975cbc2c..0b75a8d5c7068 100644
|
|
--- a/mm/damon/ops-common.c
|
|
+++ b/mm/damon/ops-common.c
|
|
@@ -87,7 +87,6 @@ void damon_pmdp_mkold(pmd_t *pmd, struct vm_area_struct *vma, unsigned long addr
|
|
int damon_hot_score(struct damon_ctx *c, struct damon_region *r,
|
|
struct damos *s)
|
|
{
|
|
- unsigned int max_nr_accesses;
|
|
int freq_subscore;
|
|
unsigned int age_in_sec;
|
|
int age_in_log, age_subscore;
|
|
@@ -95,8 +94,8 @@ int damon_hot_score(struct damon_ctx *c, struct damon_region *r,
|
|
unsigned int age_weight = s->quota.weight_age;
|
|
int hotness;
|
|
|
|
- max_nr_accesses = c->attrs.aggr_interval / c->attrs.sample_interval;
|
|
- freq_subscore = r->nr_accesses * DAMON_MAX_SUBSCORE / max_nr_accesses;
|
|
+ freq_subscore = r->nr_accesses * DAMON_MAX_SUBSCORE /
|
|
+ damon_max_nr_accesses(&c->attrs);
|
|
|
|
age_in_sec = (unsigned long)r->age * c->attrs.aggr_interval / 1000000;
|
|
for (age_in_log = 0; age_in_log < DAMON_MAX_AGE_IN_LOG && age_in_sec;
|
|
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
|
|
index 07e5f1bdf025f..dbf5e4de97a0f 100644
|
|
--- a/mm/damon/sysfs.c
|
|
+++ b/mm/damon/sysfs.c
|
|
@@ -2188,58 +2188,75 @@ destroy_targets_out:
|
|
return err;
|
|
}
|
|
|
|
-/*
|
|
- * Search a target in a context that corresponds to the sysfs target input.
|
|
- *
|
|
- * Return: pointer to the target if found, NULL if not found, or negative
|
|
- * error code if the search failed.
|
|
- */
|
|
-static struct damon_target *damon_sysfs_existing_target(
|
|
- struct damon_sysfs_target *sys_target, struct damon_ctx *ctx)
|
|
+static int damon_sysfs_update_target_pid(struct damon_target *target, int pid)
|
|
{
|
|
- struct pid *pid;
|
|
- struct damon_target *t;
|
|
+ struct pid *pid_new;
|
|
|
|
- if (!damon_target_has_pid(ctx)) {
|
|
- /* Up to only one target for paddr could exist */
|
|
- damon_for_each_target(t, ctx)
|
|
- return t;
|
|
- return NULL;
|
|
+ pid_new = find_get_pid(pid);
|
|
+ if (!pid_new)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (pid_new == target->pid) {
|
|
+ put_pid(pid_new);
|
|
+ return 0;
|
|
}
|
|
|
|
- /* ops.id should be DAMON_OPS_VADDR or DAMON_OPS_FVADDR */
|
|
- pid = find_get_pid(sys_target->pid);
|
|
- if (!pid)
|
|
- return ERR_PTR(-EINVAL);
|
|
- damon_for_each_target(t, ctx) {
|
|
- if (t->pid == pid) {
|
|
- put_pid(pid);
|
|
- return t;
|
|
- }
|
|
+ put_pid(target->pid);
|
|
+ target->pid = pid_new;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int damon_sysfs_update_target(struct damon_target *target,
|
|
+ struct damon_ctx *ctx,
|
|
+ struct damon_sysfs_target *sys_target)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ if (damon_target_has_pid(ctx)) {
|
|
+ err = damon_sysfs_update_target_pid(target, sys_target->pid);
|
|
+ if (err)
|
|
+ return err;
|
|
}
|
|
- put_pid(pid);
|
|
- return NULL;
|
|
+
|
|
+ /*
|
|
+ * Do monitoring target region boundary update only if one or more
|
|
+ * regions are set by the user. This is for keeping current monitoring
|
|
+ * target results and range easier, especially for dynamic monitoring
|
|
+ * target regions update ops like 'vaddr'.
|
|
+ */
|
|
+ if (sys_target->regions->nr)
|
|
+ err = damon_sysfs_set_regions(target, sys_target->regions);
|
|
+ return err;
|
|
}
|
|
|
|
static int damon_sysfs_set_targets(struct damon_ctx *ctx,
|
|
struct damon_sysfs_targets *sysfs_targets)
|
|
{
|
|
- int i, err;
|
|
+ struct damon_target *t, *next;
|
|
+ int i = 0, err;
|
|
|
|
/* Multiple physical address space monitoring targets makes no sense */
|
|
if (ctx->ops.id == DAMON_OPS_PADDR && sysfs_targets->nr > 1)
|
|
return -EINVAL;
|
|
|
|
- for (i = 0; i < sysfs_targets->nr; i++) {
|
|
+ damon_for_each_target_safe(t, next, ctx) {
|
|
+ if (i < sysfs_targets->nr) {
|
|
+ err = damon_sysfs_update_target(t, ctx,
|
|
+ sysfs_targets->targets_arr[i]);
|
|
+ if (err)
|
|
+ return err;
|
|
+ } else {
|
|
+ if (damon_target_has_pid(ctx))
|
|
+ put_pid(t->pid);
|
|
+ damon_destroy_target(t);
|
|
+ }
|
|
+ i++;
|
|
+ }
|
|
+
|
|
+ for (; i < sysfs_targets->nr; i++) {
|
|
struct damon_sysfs_target *st = sysfs_targets->targets_arr[i];
|
|
- struct damon_target *t = damon_sysfs_existing_target(st, ctx);
|
|
|
|
- if (IS_ERR(t))
|
|
- return PTR_ERR(t);
|
|
- if (!t)
|
|
- err = damon_sysfs_add_target(st, ctx);
|
|
- else
|
|
- err = damon_sysfs_set_regions(t, st->regions);
|
|
+ err = damon_sysfs_add_target(st, ctx);
|
|
if (err)
|
|
return err;
|
|
}
|
|
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
|
|
index b20fef29e5bb5..2753fb54cdf38 100644
|
|
--- a/mm/huge_memory.c
|
|
+++ b/mm/huge_memory.c
|
|
@@ -2757,13 +2757,15 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
|
|
int nr = folio_nr_pages(folio);
|
|
|
|
xas_split(&xas, folio, folio_order(folio));
|
|
- if (folio_test_swapbacked(folio)) {
|
|
- __lruvec_stat_mod_folio(folio, NR_SHMEM_THPS,
|
|
- -nr);
|
|
- } else {
|
|
- __lruvec_stat_mod_folio(folio, NR_FILE_THPS,
|
|
- -nr);
|
|
- filemap_nr_thps_dec(mapping);
|
|
+ if (folio_test_pmd_mappable(folio)) {
|
|
+ if (folio_test_swapbacked(folio)) {
|
|
+ __lruvec_stat_mod_folio(folio,
|
|
+ NR_SHMEM_THPS, -nr);
|
|
+ } else {
|
|
+ __lruvec_stat_mod_folio(folio,
|
|
+ NR_FILE_THPS, -nr);
|
|
+ filemap_nr_thps_dec(mapping);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
|
|
index dacbaf4f7b2c4..9da98e3e71cfe 100644
|
|
--- a/mm/memcontrol.c
|
|
+++ b/mm/memcontrol.c
|
|
@@ -2854,7 +2854,8 @@ static void commit_charge(struct folio *folio, struct mem_cgroup *memcg)
|
|
* Moreover, it should not come from DMA buffer and is not readily
|
|
* reclaimable. So those GFP bits should be masked off.
|
|
*/
|
|
-#define OBJCGS_CLEAR_MASK (__GFP_DMA | __GFP_RECLAIMABLE | __GFP_ACCOUNT)
|
|
+#define OBJCGS_CLEAR_MASK (__GFP_DMA | __GFP_RECLAIMABLE | \
|
|
+ __GFP_ACCOUNT | __GFP_NOFAIL)
|
|
|
|
/*
|
|
* mod_objcg_mlstate() may be called with irq enabled, so
|
|
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
|
|
index fd40f7e9f1763..bd2570b4f9b7b 100644
|
|
--- a/mm/memory_hotplug.c
|
|
+++ b/mm/memory_hotplug.c
|
|
@@ -1611,7 +1611,7 @@ static int scan_movable_pages(unsigned long start, unsigned long end,
|
|
*/
|
|
if (HPageMigratable(head))
|
|
goto found;
|
|
- skip = compound_nr(head) - (page - head);
|
|
+ skip = compound_nr(head) - (pfn - page_to_pfn(head));
|
|
pfn += skip - 1;
|
|
}
|
|
return -ENOENT;
|
|
diff --git a/net/9p/client.c b/net/9p/client.c
|
|
index a96e127ca4883..84b93b04d0f06 100644
|
|
--- a/net/9p/client.c
|
|
+++ b/net/9p/client.c
|
|
@@ -1987,7 +1987,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
|
|
goto error;
|
|
}
|
|
p9_debug(P9_DEBUG_9P,
|
|
- ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n",
|
|
+ ">>> TXATTRWALK file_fid %d, attr_fid %d name '%s'\n",
|
|
file_fid->fid, attr_fid->fid, attr_name);
|
|
|
|
req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds",
|
|
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
|
|
index 5a1aecf7fe487..a69422366a235 100644
|
|
--- a/net/9p/trans_fd.c
|
|
+++ b/net/9p/trans_fd.c
|
|
@@ -833,14 +833,21 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
|
|
goto out_free_ts;
|
|
if (!(ts->rd->f_mode & FMODE_READ))
|
|
goto out_put_rd;
|
|
- /* prevent workers from hanging on IO when fd is a pipe */
|
|
- ts->rd->f_flags |= O_NONBLOCK;
|
|
+ /* Prevent workers from hanging on IO when fd is a pipe.
|
|
+ * It's technically possible for userspace or concurrent mounts to
|
|
+ * modify this flag concurrently, which will likely result in a
|
|
+ * broken filesystem. However, just having bad flags here should
|
|
+ * not crash the kernel or cause any other sort of bug, so mark this
|
|
+ * particular data race as intentional so that tooling (like KCSAN)
|
|
+ * can allow it and detect further problems.
|
|
+ */
|
|
+ data_race(ts->rd->f_flags |= O_NONBLOCK);
|
|
ts->wr = fget(wfd);
|
|
if (!ts->wr)
|
|
goto out_put_rd;
|
|
if (!(ts->wr->f_mode & FMODE_WRITE))
|
|
goto out_put_wr;
|
|
- ts->wr->f_flags |= O_NONBLOCK;
|
|
+ data_race(ts->wr->f_flags |= O_NONBLOCK);
|
|
|
|
client->trans = ts;
|
|
client->status = Connected;
|
|
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
|
|
index 728be9307f526..55e0ecd88543e 100644
|
|
--- a/net/bluetooth/hci_conn.c
|
|
+++ b/net/bluetooth/hci_conn.c
|
|
@@ -168,13 +168,11 @@ static void hci_conn_cleanup(struct hci_conn *conn)
|
|
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
|
|
}
|
|
|
|
- hci_conn_del_sysfs(conn);
|
|
-
|
|
debugfs_remove_recursive(conn->debugfs);
|
|
|
|
- hci_dev_put(hdev);
|
|
+ hci_conn_del_sysfs(conn);
|
|
|
|
- hci_conn_put(conn);
|
|
+ hci_dev_put(hdev);
|
|
}
|
|
|
|
static void le_scan_cleanup(struct work_struct *work)
|
|
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
|
|
index 08542dfc2dc53..633b82d542728 100644
|
|
--- a/net/bluetooth/hci_sysfs.c
|
|
+++ b/net/bluetooth/hci_sysfs.c
|
|
@@ -33,7 +33,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
|
|
{
|
|
struct hci_dev *hdev = conn->hdev;
|
|
|
|
- BT_DBG("conn %p", conn);
|
|
+ bt_dev_dbg(hdev, "conn %p", conn);
|
|
|
|
conn->dev.type = &bt_link;
|
|
conn->dev.class = bt_class;
|
|
@@ -46,27 +46,30 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
|
|
{
|
|
struct hci_dev *hdev = conn->hdev;
|
|
|
|
- BT_DBG("conn %p", conn);
|
|
+ bt_dev_dbg(hdev, "conn %p", conn);
|
|
|
|
if (device_is_registered(&conn->dev))
|
|
return;
|
|
|
|
dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
|
|
|
|
- if (device_add(&conn->dev) < 0) {
|
|
+ if (device_add(&conn->dev) < 0)
|
|
bt_dev_err(hdev, "failed to register connection device");
|
|
- return;
|
|
- }
|
|
-
|
|
- hci_dev_hold(hdev);
|
|
}
|
|
|
|
void hci_conn_del_sysfs(struct hci_conn *conn)
|
|
{
|
|
struct hci_dev *hdev = conn->hdev;
|
|
|
|
- if (!device_is_registered(&conn->dev))
|
|
+ bt_dev_dbg(hdev, "conn %p", conn);
|
|
+
|
|
+ if (!device_is_registered(&conn->dev)) {
|
|
+ /* If device_add() has *not* succeeded, use *only* put_device()
|
|
+ * to drop the reference count.
|
|
+ */
|
|
+ put_device(&conn->dev);
|
|
return;
|
|
+ }
|
|
|
|
while (1) {
|
|
struct device *dev;
|
|
@@ -78,9 +81,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
|
put_device(dev);
|
|
}
|
|
|
|
- device_del(&conn->dev);
|
|
-
|
|
- hci_dev_put(hdev);
|
|
+ device_unregister(&conn->dev);
|
|
}
|
|
|
|
static void bt_host_release(struct device *dev)
|
|
diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c
|
|
index 73242962be5d7..06d94b2c6b5de 100644
|
|
--- a/net/bridge/netfilter/nf_conntrack_bridge.c
|
|
+++ b/net/bridge/netfilter/nf_conntrack_bridge.c
|
|
@@ -37,7 +37,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
|
|
ktime_t tstamp = skb->tstamp;
|
|
struct ip_frag_state state;
|
|
struct iphdr *iph;
|
|
- int err;
|
|
+ int err = 0;
|
|
|
|
/* for offloaded checksums cleanup checksum before fragmentation */
|
|
if (skb->ip_summed == CHECKSUM_PARTIAL &&
|
|
diff --git a/net/core/sock.c b/net/core/sock.c
|
|
index 0ee2e33bbe5f8..4305e55dbfba4 100644
|
|
--- a/net/core/sock.c
|
|
+++ b/net/core/sock.c
|
|
@@ -596,7 +596,7 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
|
|
INDIRECT_CALL_INET(dst->ops->check, ip6_dst_check, ipv4_dst_check,
|
|
dst, cookie) == NULL) {
|
|
sk_tx_queue_clear(sk);
|
|
- sk->sk_dst_pending_confirm = 0;
|
|
+ WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
|
|
RCU_INIT_POINTER(sk->sk_dst_cache, NULL);
|
|
dst_release(dst);
|
|
return NULL;
|
|
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
|
|
index 62d9472ac8bca..f2ed2aed08ab3 100644
|
|
--- a/net/ipv4/inet_hashtables.c
|
|
+++ b/net/ipv4/inet_hashtables.c
|
|
@@ -731,12 +731,12 @@ int __inet_hash(struct sock *sk, struct sock *osk)
|
|
if (err)
|
|
goto unlock;
|
|
}
|
|
+ sock_set_flag(sk, SOCK_RCU_FREE);
|
|
if (IS_ENABLED(CONFIG_IPV6) && sk->sk_reuseport &&
|
|
sk->sk_family == AF_INET6)
|
|
__sk_nulls_add_node_tail_rcu(sk, &ilb2->nulls_head);
|
|
else
|
|
__sk_nulls_add_node_rcu(sk, &ilb2->nulls_head);
|
|
- sock_set_flag(sk, SOCK_RCU_FREE);
|
|
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
|
|
unlock:
|
|
spin_unlock(&ilb2->lock);
|
|
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
|
|
index cc7ed86fb0a57..5b93d1ed1ed19 100644
|
|
--- a/net/ipv4/tcp_output.c
|
|
+++ b/net/ipv4/tcp_output.c
|
|
@@ -1319,7 +1319,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
|
|
skb->destructor = skb_is_tcp_pure_ack(skb) ? __sock_wfree : tcp_wfree;
|
|
refcount_add(skb->truesize, &sk->sk_wmem_alloc);
|
|
|
|
- skb_set_dst_pending_confirm(skb, sk->sk_dst_pending_confirm);
|
|
+ skb_set_dst_pending_confirm(skb, READ_ONCE(sk->sk_dst_pending_confirm));
|
|
|
|
/* Build TCP header and checksum it. */
|
|
th = (struct tcphdr *)skb->data;
|
|
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
|
|
index ee9f455bb2d18..2ca442f485132 100644
|
|
--- a/net/mac80211/cfg.c
|
|
+++ b/net/mac80211/cfg.c
|
|
@@ -3006,6 +3006,10 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy,
|
|
else
|
|
*dbm = sdata->vif.bss_conf.txpower;
|
|
|
|
+ /* INT_MIN indicates no power level was set yet */
|
|
+ if (*dbm == INT_MIN)
|
|
+ return -EINVAL;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
|
|
index 5d845fcf3d09e..980050f6b456f 100644
|
|
--- a/net/mptcp/pm_netlink.c
|
|
+++ b/net/mptcp/pm_netlink.c
|
|
@@ -1557,8 +1557,9 @@ void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
list_for_each_entry(entry, rm_list, list) {
|
|
- remove_anno_list_by_saddr(msk, &entry->addr);
|
|
- if (alist.nr < MPTCP_RM_IDS_MAX)
|
|
+ if ((remove_anno_list_by_saddr(msk, &entry->addr) ||
|
|
+ lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) &&
|
|
+ alist.nr < MPTCP_RM_IDS_MAX)
|
|
alist.ids[alist.nr++] = entry->addr.id;
|
|
}
|
|
|
|
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
|
|
index 0eb20274459c8..76539d1004ebb 100644
|
|
--- a/net/mptcp/protocol.c
|
|
+++ b/net/mptcp/protocol.c
|
|
@@ -1275,6 +1275,8 @@ static void mptcp_update_infinite_map(struct mptcp_sock *msk,
|
|
mptcp_do_fallback(ssk);
|
|
}
|
|
|
|
+#define MPTCP_MAX_GSO_SIZE (GSO_LEGACY_MAX_SIZE - (MAX_TCP_HEADER + 1))
|
|
+
|
|
static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
|
|
struct mptcp_data_frag *dfrag,
|
|
struct mptcp_sendmsg_info *info)
|
|
@@ -1301,6 +1303,8 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
|
|
return -EAGAIN;
|
|
|
|
/* compute send limit */
|
|
+ if (unlikely(ssk->sk_gso_max_size > MPTCP_MAX_GSO_SIZE))
|
|
+ ssk->sk_gso_max_size = MPTCP_MAX_GSO_SIZE;
|
|
info->mss_now = tcp_send_mss(ssk, &info->size_goal, info->flags);
|
|
copy = info->size_goal;
|
|
|
|
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
|
|
index 937bd4c556151..30374fd44228f 100644
|
|
--- a/net/mptcp/sockopt.c
|
|
+++ b/net/mptcp/sockopt.c
|
|
@@ -735,8 +735,11 @@ static int mptcp_setsockopt_v4_set_tos(struct mptcp_sock *msk, int optname,
|
|
val = inet_sk(sk)->tos;
|
|
mptcp_for_each_subflow(msk, subflow) {
|
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
|
+ bool slow;
|
|
|
|
+ slow = lock_sock_fast(ssk);
|
|
__ip_sock_set_tos(ssk, val);
|
|
+ unlock_sock_fast(ssk, slow);
|
|
}
|
|
release_sock(sk);
|
|
|
|
diff --git a/net/ncsi/ncsi-aen.c b/net/ncsi/ncsi-aen.c
|
|
index f8854bff286cb..62fb1031763d1 100644
|
|
--- a/net/ncsi/ncsi-aen.c
|
|
+++ b/net/ncsi/ncsi-aen.c
|
|
@@ -89,11 +89,6 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
|
|
if ((had_link == has_link) || chained)
|
|
return 0;
|
|
|
|
- if (had_link)
|
|
- netif_carrier_off(ndp->ndev.dev);
|
|
- else
|
|
- netif_carrier_on(ndp->ndev.dev);
|
|
-
|
|
if (!ndp->multi_package && !nc->package->multi_channel) {
|
|
if (had_link) {
|
|
ndp->flags |= NCSI_DEV_RESHUFFLE;
|
|
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
|
|
index d6d59e36d17a7..421211eba838b 100644
|
|
--- a/net/netfilter/nf_tables_api.c
|
|
+++ b/net/netfilter/nf_tables_api.c
|
|
@@ -6194,6 +6194,12 @@ static int nft_setelem_deactivate(const struct net *net,
|
|
return ret;
|
|
}
|
|
|
|
+static void nft_setelem_catchall_destroy(struct nft_set_elem_catchall *catchall)
|
|
+{
|
|
+ list_del_rcu(&catchall->list);
|
|
+ kfree_rcu(catchall, rcu);
|
|
+}
|
|
+
|
|
static void nft_setelem_catchall_remove(const struct net *net,
|
|
const struct nft_set *set,
|
|
const struct nft_set_elem *elem)
|
|
@@ -6202,8 +6208,7 @@ static void nft_setelem_catchall_remove(const struct net *net,
|
|
|
|
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
|
|
if (catchall->elem == elem->priv) {
|
|
- list_del_rcu(&catchall->list);
|
|
- kfree_rcu(catchall, rcu);
|
|
+ nft_setelem_catchall_destroy(catchall);
|
|
break;
|
|
}
|
|
}
|
|
@@ -9266,9 +9271,8 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
|
|
call_rcu(&trans->rcu, nft_trans_gc_trans_free);
|
|
}
|
|
|
|
-static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
|
|
- unsigned int gc_seq,
|
|
- bool sync)
|
|
+struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
|
|
+ unsigned int gc_seq)
|
|
{
|
|
struct nft_set_elem_catchall *catchall;
|
|
const struct nft_set *set = gc->set;
|
|
@@ -9284,11 +9288,7 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
|
|
|
|
nft_set_elem_dead(ext);
|
|
dead_elem:
|
|
- if (sync)
|
|
- gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
|
|
- else
|
|
- gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
|
|
-
|
|
+ gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
|
|
if (!gc)
|
|
return NULL;
|
|
|
|
@@ -9298,15 +9298,34 @@ dead_elem:
|
|
return gc;
|
|
}
|
|
|
|
-struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
|
|
- unsigned int gc_seq)
|
|
-{
|
|
- return nft_trans_gc_catchall(gc, gc_seq, false);
|
|
-}
|
|
-
|
|
struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
|
|
{
|
|
- return nft_trans_gc_catchall(gc, 0, true);
|
|
+ struct nft_set_elem_catchall *catchall, *next;
|
|
+ const struct nft_set *set = gc->set;
|
|
+ struct nft_set_elem elem;
|
|
+ struct nft_set_ext *ext;
|
|
+
|
|
+ WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net));
|
|
+
|
|
+ list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
|
|
+ ext = nft_set_elem_ext(set, catchall->elem);
|
|
+
|
|
+ if (!nft_set_elem_expired(ext))
|
|
+ continue;
|
|
+
|
|
+ gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
|
|
+ if (!gc)
|
|
+ return NULL;
|
|
+
|
|
+ memset(&elem, 0, sizeof(elem));
|
|
+ elem.priv = catchall->elem;
|
|
+
|
|
+ nft_setelem_data_deactivate(gc->net, gc->set, &elem);
|
|
+ nft_setelem_catchall_destroy(catchall);
|
|
+ nft_trans_gc_elem_add(gc, elem.priv);
|
|
+ }
|
|
+
|
|
+ return gc;
|
|
}
|
|
|
|
static void nf_tables_module_autoload_cleanup(struct net *net)
|
|
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
|
|
index 2e2eb2cb17bc7..605178133d9eb 100644
|
|
--- a/net/netfilter/nft_byteorder.c
|
|
+++ b/net/netfilter/nft_byteorder.c
|
|
@@ -38,13 +38,14 @@ void nft_byteorder_eval(const struct nft_expr *expr,
|
|
|
|
switch (priv->size) {
|
|
case 8: {
|
|
+ u64 *dst64 = (void *)dst;
|
|
u64 src64;
|
|
|
|
switch (priv->op) {
|
|
case NFT_BYTEORDER_NTOH:
|
|
for (i = 0; i < priv->len / 8; i++) {
|
|
src64 = nft_reg_load64(&src[i]);
|
|
- nft_reg_store64(&dst[i],
|
|
+ nft_reg_store64(&dst64[i],
|
|
be64_to_cpu((__force __be64)src64));
|
|
}
|
|
break;
|
|
@@ -52,7 +53,7 @@ void nft_byteorder_eval(const struct nft_expr *expr,
|
|
for (i = 0; i < priv->len / 8; i++) {
|
|
src64 = (__force __u64)
|
|
cpu_to_be64(nft_reg_load64(&src[i]));
|
|
- nft_reg_store64(&dst[i], src64);
|
|
+ nft_reg_store64(&dst64[i], src64);
|
|
}
|
|
break;
|
|
}
|
|
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
|
|
index 55d2d49c34259..6e83321926229 100644
|
|
--- a/net/netfilter/nft_meta.c
|
|
+++ b/net/netfilter/nft_meta.c
|
|
@@ -63,7 +63,7 @@ nft_meta_get_eval_time(enum nft_meta_keys key,
|
|
{
|
|
switch (key) {
|
|
case NFT_META_TIME_NS:
|
|
- nft_reg_store64(dest, ktime_get_real_ns());
|
|
+ nft_reg_store64((u64 *)dest, ktime_get_real_ns());
|
|
break;
|
|
case NFT_META_TIME_DAY:
|
|
nft_reg_store8(dest, nft_meta_weekday());
|
|
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
|
|
index 2b803383c7b31..61e5c77462e94 100644
|
|
--- a/net/sunrpc/clnt.c
|
|
+++ b/net/sunrpc/clnt.c
|
|
@@ -111,7 +111,8 @@ static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
|
|
|
|
pipefs_sb = rpc_get_sb_net(net);
|
|
if (pipefs_sb) {
|
|
- __rpc_clnt_remove_pipedir(clnt);
|
|
+ if (pipefs_sb == clnt->pipefs_sb)
|
|
+ __rpc_clnt_remove_pipedir(clnt);
|
|
rpc_put_sb_net(net);
|
|
}
|
|
}
|
|
@@ -151,6 +152,8 @@ rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt)
|
|
{
|
|
struct dentry *dentry;
|
|
|
|
+ clnt->pipefs_sb = pipefs_sb;
|
|
+
|
|
if (clnt->cl_program->pipe_dir_name != NULL) {
|
|
dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt);
|
|
if (IS_ERR(dentry))
|
|
@@ -2157,6 +2160,7 @@ call_connect_status(struct rpc_task *task)
|
|
task->tk_status = 0;
|
|
switch (status) {
|
|
case -ECONNREFUSED:
|
|
+ case -ECONNRESET:
|
|
/* A positive refusal suggests a rebind is needed. */
|
|
if (RPC_IS_SOFTCONN(task))
|
|
break;
|
|
@@ -2165,7 +2169,6 @@ call_connect_status(struct rpc_task *task)
|
|
goto out_retry;
|
|
}
|
|
fallthrough;
|
|
- case -ECONNRESET:
|
|
case -ECONNABORTED:
|
|
case -ENETDOWN:
|
|
case -ENETUNREACH:
|
|
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
|
|
index 5a8e6d46809ae..82afb56695f8d 100644
|
|
--- a/net/sunrpc/rpcb_clnt.c
|
|
+++ b/net/sunrpc/rpcb_clnt.c
|
|
@@ -746,6 +746,10 @@ void rpcb_getport_async(struct rpc_task *task)
|
|
|
|
child = rpcb_call_async(rpcb_clnt, map, proc);
|
|
rpc_release_client(rpcb_clnt);
|
|
+ if (IS_ERR(child)) {
|
|
+ /* rpcb_map_release() has freed the arguments */
|
|
+ return;
|
|
+ }
|
|
|
|
xprt->stat.bind_count++;
|
|
rpc_put_task(child);
|
|
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
|
|
index 6da6608985ce9..b2dd01e5274e9 100644
|
|
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
|
|
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
|
|
@@ -857,7 +857,8 @@ out_readfail:
|
|
if (ret == -EINVAL)
|
|
svc_rdma_send_error(rdma_xprt, ctxt, ret);
|
|
svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
|
|
- return ret;
|
|
+ svc_xprt_deferred_close(xprt);
|
|
+ return -ENOTCONN;
|
|
|
|
out_backchannel:
|
|
svc_rdma_handle_bc_reply(rqstp, ctxt);
|
|
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
|
|
index dfea27a906f2f..9eb7cab6b2f60 100644
|
|
--- a/net/tipc/netlink_compat.c
|
|
+++ b/net/tipc/netlink_compat.c
|
|
@@ -101,6 +101,7 @@ static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
|
|
return -EMSGSIZE;
|
|
|
|
skb_put(skb, TLV_SPACE(len));
|
|
+ memset(tlv, 0, TLV_SPACE(len));
|
|
tlv->tlv_type = htons(type);
|
|
tlv->tlv_len = htons(TLV_LENGTH(len));
|
|
if (len && data)
|
|
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
|
|
index 310952f4c68f7..6dbeb80073338 100644
|
|
--- a/net/unix/af_unix.c
|
|
+++ b/net/unix/af_unix.c
|
|
@@ -2641,15 +2641,16 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
|
|
|
|
if (!(state->flags & MSG_PEEK))
|
|
WRITE_ONCE(u->oob_skb, NULL);
|
|
-
|
|
+ else
|
|
+ skb_get(oob_skb);
|
|
unix_state_unlock(sk);
|
|
|
|
chunk = state->recv_actor(oob_skb, 0, chunk, state);
|
|
|
|
- if (!(state->flags & MSG_PEEK)) {
|
|
+ if (!(state->flags & MSG_PEEK))
|
|
UNIXCB(oob_skb).consumed += 1;
|
|
- kfree_skb(oob_skb);
|
|
- }
|
|
+
|
|
+ consume_skb(oob_skb);
|
|
|
|
mutex_unlock(&u->iolock);
|
|
|
|
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
|
|
index 8360c790a8a01..84471745c0829 100644
|
|
--- a/net/vmw_vsock/af_vsock.c
|
|
+++ b/net/vmw_vsock/af_vsock.c
|
|
@@ -89,6 +89,7 @@
|
|
#include <linux/types.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/cred.h>
|
|
+#include <linux/errqueue.h>
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/kernel.h>
|
|
@@ -110,6 +111,7 @@
|
|
#include <linux/workqueue.h>
|
|
#include <net/sock.h>
|
|
#include <net/af_vsock.h>
|
|
+#include <uapi/linux/vm_sockets.h>
|
|
|
|
static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
|
|
static void vsock_sk_destruct(struct sock *sk);
|
|
@@ -2096,6 +2098,10 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
|
int err;
|
|
|
|
sk = sock->sk;
|
|
+
|
|
+ if (unlikely(flags & MSG_ERRQUEUE))
|
|
+ return sock_recv_errqueue(sk, msg, len, SOL_VSOCK, VSOCK_RECVERR);
|
|
+
|
|
vsk = vsock_sk(sk);
|
|
err = 0;
|
|
|
|
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
|
|
index 951b74ba1b242..366395cab490d 100644
|
|
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
|
|
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
|
|
@@ -191,12 +191,14 @@ static void partition_struct(tree *fields, unsigned long length, struct partitio
|
|
|
|
static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prng_state)
|
|
{
|
|
- unsigned long i, x;
|
|
+ unsigned long i, x, index;
|
|
struct partition_group size_group[length];
|
|
unsigned long num_groups = 0;
|
|
unsigned long randnum;
|
|
|
|
partition_struct(newtree, length, (struct partition_group *)&size_group, &num_groups);
|
|
+
|
|
+ /* FIXME: this group shuffle is currently a no-op. */
|
|
for (i = num_groups - 1; i > 0; i--) {
|
|
struct partition_group tmp;
|
|
randnum = ranval(prng_state) % (i + 1);
|
|
@@ -206,11 +208,14 @@ static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prn
|
|
}
|
|
|
|
for (x = 0; x < num_groups; x++) {
|
|
- for (i = size_group[x].start + size_group[x].length - 1; i > size_group[x].start; i--) {
|
|
+ for (index = size_group[x].length - 1; index > 0; index--) {
|
|
tree tmp;
|
|
+
|
|
+ i = size_group[x].start + index;
|
|
if (DECL_BIT_FIELD_TYPE(newtree[i]))
|
|
continue;
|
|
- randnum = ranval(prng_state) % (i + 1);
|
|
+ randnum = ranval(prng_state) % (index + 1);
|
|
+ randnum += size_group[x].start;
|
|
// we could handle this case differently if desired
|
|
if (DECL_BIT_FIELD_TYPE(newtree[randnum]))
|
|
continue;
|
|
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
|
|
index 65418e0906c13..cb251ab0e7076 100644
|
|
--- a/security/integrity/iint.c
|
|
+++ b/security/integrity/iint.c
|
|
@@ -66,9 +66,32 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
|
|
return iint;
|
|
}
|
|
|
|
-static void iint_free(struct integrity_iint_cache *iint)
|
|
+#define IMA_MAX_NESTING (FILESYSTEM_MAX_STACK_DEPTH+1)
|
|
+
|
|
+/*
|
|
+ * It is not clear that IMA should be nested at all, but as long is it measures
|
|
+ * files both on overlayfs and on underlying fs, we need to annotate the iint
|
|
+ * mutex to avoid lockdep false positives related to IMA + overlayfs.
|
|
+ * See ovl_lockdep_annotate_inode_mutex_key() for more details.
|
|
+ */
|
|
+static inline void iint_lockdep_annotate(struct integrity_iint_cache *iint,
|
|
+ struct inode *inode)
|
|
+{
|
|
+#ifdef CONFIG_LOCKDEP
|
|
+ static struct lock_class_key iint_mutex_key[IMA_MAX_NESTING];
|
|
+
|
|
+ int depth = inode->i_sb->s_stack_depth;
|
|
+
|
|
+ if (WARN_ON_ONCE(depth < 0 || depth >= IMA_MAX_NESTING))
|
|
+ depth = 0;
|
|
+
|
|
+ lockdep_set_class(&iint->mutex, &iint_mutex_key[depth]);
|
|
+#endif
|
|
+}
|
|
+
|
|
+static void iint_init_always(struct integrity_iint_cache *iint,
|
|
+ struct inode *inode)
|
|
{
|
|
- kfree(iint->ima_hash);
|
|
iint->ima_hash = NULL;
|
|
iint->version = 0;
|
|
iint->flags = 0UL;
|
|
@@ -80,6 +103,14 @@ static void iint_free(struct integrity_iint_cache *iint)
|
|
iint->ima_creds_status = INTEGRITY_UNKNOWN;
|
|
iint->evm_status = INTEGRITY_UNKNOWN;
|
|
iint->measured_pcrs = 0;
|
|
+ mutex_init(&iint->mutex);
|
|
+ iint_lockdep_annotate(iint, inode);
|
|
+}
|
|
+
|
|
+static void iint_free(struct integrity_iint_cache *iint)
|
|
+{
|
|
+ kfree(iint->ima_hash);
|
|
+ mutex_destroy(&iint->mutex);
|
|
kmem_cache_free(iint_cache, iint);
|
|
}
|
|
|
|
@@ -112,6 +143,8 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
|
|
if (!iint)
|
|
return NULL;
|
|
|
|
+ iint_init_always(iint, inode);
|
|
+
|
|
write_lock(&integrity_iint_lock);
|
|
|
|
p = &integrity_iint_tree.rb_node;
|
|
@@ -161,25 +194,18 @@ void integrity_inode_free(struct inode *inode)
|
|
iint_free(iint);
|
|
}
|
|
|
|
-static void init_once(void *foo)
|
|
+static void iint_init_once(void *foo)
|
|
{
|
|
struct integrity_iint_cache *iint = (struct integrity_iint_cache *) foo;
|
|
|
|
memset(iint, 0, sizeof(*iint));
|
|
- iint->ima_file_status = INTEGRITY_UNKNOWN;
|
|
- iint->ima_mmap_status = INTEGRITY_UNKNOWN;
|
|
- iint->ima_bprm_status = INTEGRITY_UNKNOWN;
|
|
- iint->ima_read_status = INTEGRITY_UNKNOWN;
|
|
- iint->ima_creds_status = INTEGRITY_UNKNOWN;
|
|
- iint->evm_status = INTEGRITY_UNKNOWN;
|
|
- mutex_init(&iint->mutex);
|
|
}
|
|
|
|
static int __init integrity_iintcache_init(void)
|
|
{
|
|
iint_cache =
|
|
kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
|
|
- 0, SLAB_PANIC, init_once);
|
|
+ 0, SLAB_PANIC, iint_init_once);
|
|
return 0;
|
|
}
|
|
DEFINE_LSM(integrity) = {
|
|
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
|
|
index 1e3a7a4f8833f..026c8c9db9920 100644
|
|
--- a/security/integrity/ima/ima_api.c
|
|
+++ b/security/integrity/ima/ima_api.c
|
|
@@ -243,6 +243,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
|
{
|
|
const char *audit_cause = "failed";
|
|
struct inode *inode = file_inode(file);
|
|
+ struct inode *real_inode = d_real_inode(file_dentry(file));
|
|
const char *filename = file->f_path.dentry->d_name.name;
|
|
struct ima_max_digest_data hash;
|
|
int result = 0;
|
|
@@ -305,6 +306,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
|
|
iint->ima_hash = tmpbuf;
|
|
memcpy(iint->ima_hash, &hash, length);
|
|
iint->version = i_version;
|
|
+ if (real_inode != inode) {
|
|
+ iint->real_ino = real_inode->i_ino;
|
|
+ iint->real_dev = real_inode->i_sb->s_dev;
|
|
+ }
|
|
|
|
/* Possibly temporary failure due to type of read (eg. O_DIRECT) */
|
|
if (!result)
|
|
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
|
|
index bc84a0ac25aaa..185666d90eebc 100644
|
|
--- a/security/integrity/ima/ima_main.c
|
|
+++ b/security/integrity/ima/ima_main.c
|
|
@@ -26,6 +26,7 @@
|
|
#include <linux/ima.h>
|
|
#include <linux/iversion.h>
|
|
#include <linux/fs.h>
|
|
+#include <linux/iversion.h>
|
|
|
|
#include "ima.h"
|
|
|
|
@@ -202,7 +203,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
|
u32 secid, char *buf, loff_t size, int mask,
|
|
enum ima_hooks func)
|
|
{
|
|
- struct inode *inode = file_inode(file);
|
|
+ struct inode *backing_inode, *inode = file_inode(file);
|
|
struct integrity_iint_cache *iint = NULL;
|
|
struct ima_template_desc *template_desc = NULL;
|
|
char *pathbuf = NULL;
|
|
@@ -278,6 +279,19 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
|
iint->measured_pcrs = 0;
|
|
}
|
|
|
|
+ /* Detect and re-evaluate changes made to the backing file. */
|
|
+ backing_inode = d_real_inode(file_dentry(file));
|
|
+ if (backing_inode != inode &&
|
|
+ (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
|
|
+ if (!IS_I_VERSION(backing_inode) ||
|
|
+ backing_inode->i_sb->s_dev != iint->real_dev ||
|
|
+ backing_inode->i_ino != iint->real_ino ||
|
|
+ !inode_eq_iversion(backing_inode, iint->version)) {
|
|
+ iint->flags &= ~IMA_DONE_MASK;
|
|
+ iint->measured_pcrs = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
/* Determine if already appraised/measured based on bitmask
|
|
* (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED,
|
|
* IMA_AUDIT, IMA_AUDITED)
|
|
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
|
|
index 7167a6e99bdc0..52c3c806bf69f 100644
|
|
--- a/security/integrity/integrity.h
|
|
+++ b/security/integrity/integrity.h
|
|
@@ -164,6 +164,8 @@ struct integrity_iint_cache {
|
|
unsigned long flags;
|
|
unsigned long measured_pcrs;
|
|
unsigned long atomic_flags;
|
|
+ unsigned long real_ino;
|
|
+ dev_t real_dev;
|
|
enum integrity_status ima_file_status:4;
|
|
enum integrity_status ima_mmap_status:4;
|
|
enum integrity_status ima_bprm_status:4;
|
|
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
|
|
index 85fb5c22529a7..fee1ab2c734d3 100644
|
|
--- a/security/keys/trusted-keys/trusted_core.c
|
|
+++ b/security/keys/trusted-keys/trusted_core.c
|
|
@@ -358,17 +358,17 @@ static int __init init_trusted(void)
|
|
if (!get_random)
|
|
get_random = kernel_get_random;
|
|
|
|
- static_call_update(trusted_key_seal,
|
|
- trusted_key_sources[i].ops->seal);
|
|
- static_call_update(trusted_key_unseal,
|
|
- trusted_key_sources[i].ops->unseal);
|
|
- static_call_update(trusted_key_get_random,
|
|
- get_random);
|
|
- trusted_key_exit = trusted_key_sources[i].ops->exit;
|
|
- migratable = trusted_key_sources[i].ops->migratable;
|
|
-
|
|
ret = trusted_key_sources[i].ops->init();
|
|
- if (!ret)
|
|
+ if (!ret) {
|
|
+ static_call_update(trusted_key_seal, trusted_key_sources[i].ops->seal);
|
|
+ static_call_update(trusted_key_unseal, trusted_key_sources[i].ops->unseal);
|
|
+ static_call_update(trusted_key_get_random, get_random);
|
|
+
|
|
+ trusted_key_exit = trusted_key_sources[i].ops->exit;
|
|
+ migratable = trusted_key_sources[i].ops->migratable;
|
|
+ }
|
|
+
|
|
+ if (!ret || ret != -ENODEV)
|
|
break;
|
|
}
|
|
|
|
diff --git a/security/keys/trusted-keys/trusted_tee.c b/security/keys/trusted-keys/trusted_tee.c
|
|
index c8626686ee1b7..24f67ca8d7131 100644
|
|
--- a/security/keys/trusted-keys/trusted_tee.c
|
|
+++ b/security/keys/trusted-keys/trusted_tee.c
|
|
@@ -65,24 +65,16 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
|
|
int ret;
|
|
struct tee_ioctl_invoke_arg inv_arg;
|
|
struct tee_param param[4];
|
|
- struct tee_shm *reg_shm_in = NULL, *reg_shm_out = NULL;
|
|
+ struct tee_shm *reg_shm = NULL;
|
|
|
|
memset(&inv_arg, 0, sizeof(inv_arg));
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
- reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
|
|
- p->key_len);
|
|
- if (IS_ERR(reg_shm_in)) {
|
|
- dev_err(pvt_data.dev, "key shm register failed\n");
|
|
- return PTR_ERR(reg_shm_in);
|
|
- }
|
|
-
|
|
- reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
|
|
- sizeof(p->blob));
|
|
- if (IS_ERR(reg_shm_out)) {
|
|
- dev_err(pvt_data.dev, "blob shm register failed\n");
|
|
- ret = PTR_ERR(reg_shm_out);
|
|
- goto out;
|
|
+ reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
|
|
+ sizeof(p->key) + sizeof(p->blob));
|
|
+ if (IS_ERR(reg_shm)) {
|
|
+ dev_err(pvt_data.dev, "shm register failed\n");
|
|
+ return PTR_ERR(reg_shm);
|
|
}
|
|
|
|
inv_arg.func = TA_CMD_SEAL;
|
|
@@ -90,13 +82,13 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
|
|
inv_arg.num_params = 4;
|
|
|
|
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
|
|
- param[0].u.memref.shm = reg_shm_in;
|
|
+ param[0].u.memref.shm = reg_shm;
|
|
param[0].u.memref.size = p->key_len;
|
|
param[0].u.memref.shm_offs = 0;
|
|
param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
|
|
- param[1].u.memref.shm = reg_shm_out;
|
|
+ param[1].u.memref.shm = reg_shm;
|
|
param[1].u.memref.size = sizeof(p->blob);
|
|
- param[1].u.memref.shm_offs = 0;
|
|
+ param[1].u.memref.shm_offs = sizeof(p->key);
|
|
|
|
ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
|
|
if ((ret < 0) || (inv_arg.ret != 0)) {
|
|
@@ -107,11 +99,7 @@ static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
|
|
p->blob_len = param[1].u.memref.size;
|
|
}
|
|
|
|
-out:
|
|
- if (reg_shm_out)
|
|
- tee_shm_free(reg_shm_out);
|
|
- if (reg_shm_in)
|
|
- tee_shm_free(reg_shm_in);
|
|
+ tee_shm_free(reg_shm);
|
|
|
|
return ret;
|
|
}
|
|
@@ -124,24 +112,16 @@ static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob)
|
|
int ret;
|
|
struct tee_ioctl_invoke_arg inv_arg;
|
|
struct tee_param param[4];
|
|
- struct tee_shm *reg_shm_in = NULL, *reg_shm_out = NULL;
|
|
+ struct tee_shm *reg_shm = NULL;
|
|
|
|
memset(&inv_arg, 0, sizeof(inv_arg));
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
- reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
|
|
- p->blob_len);
|
|
- if (IS_ERR(reg_shm_in)) {
|
|
- dev_err(pvt_data.dev, "blob shm register failed\n");
|
|
- return PTR_ERR(reg_shm_in);
|
|
- }
|
|
-
|
|
- reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
|
|
- sizeof(p->key));
|
|
- if (IS_ERR(reg_shm_out)) {
|
|
- dev_err(pvt_data.dev, "key shm register failed\n");
|
|
- ret = PTR_ERR(reg_shm_out);
|
|
- goto out;
|
|
+ reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
|
|
+ sizeof(p->key) + sizeof(p->blob));
|
|
+ if (IS_ERR(reg_shm)) {
|
|
+ dev_err(pvt_data.dev, "shm register failed\n");
|
|
+ return PTR_ERR(reg_shm);
|
|
}
|
|
|
|
inv_arg.func = TA_CMD_UNSEAL;
|
|
@@ -149,11 +129,11 @@ static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob)
|
|
inv_arg.num_params = 4;
|
|
|
|
param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
|
|
- param[0].u.memref.shm = reg_shm_in;
|
|
+ param[0].u.memref.shm = reg_shm;
|
|
param[0].u.memref.size = p->blob_len;
|
|
- param[0].u.memref.shm_offs = 0;
|
|
+ param[0].u.memref.shm_offs = sizeof(p->key);
|
|
param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
|
|
- param[1].u.memref.shm = reg_shm_out;
|
|
+ param[1].u.memref.shm = reg_shm;
|
|
param[1].u.memref.size = sizeof(p->key);
|
|
param[1].u.memref.shm_offs = 0;
|
|
|
|
@@ -166,11 +146,7 @@ static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob)
|
|
p->key_len = param[1].u.memref.size;
|
|
}
|
|
|
|
-out:
|
|
- if (reg_shm_out)
|
|
- tee_shm_free(reg_shm_out);
|
|
- if (reg_shm_in)
|
|
- tee_shm_free(reg_shm_in);
|
|
+ tee_shm_free(reg_shm);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/sound/core/info.c b/sound/core/info.c
|
|
index 0b2f04dcb5897..e2f302e55bbb2 100644
|
|
--- a/sound/core/info.c
|
|
+++ b/sound/core/info.c
|
|
@@ -56,7 +56,7 @@ struct snd_info_private_data {
|
|
};
|
|
|
|
static int snd_info_version_init(void);
|
|
-static void snd_info_disconnect(struct snd_info_entry *entry);
|
|
+static void snd_info_clear_entries(struct snd_info_entry *entry);
|
|
|
|
/*
|
|
|
|
@@ -569,11 +569,16 @@ void snd_info_card_disconnect(struct snd_card *card)
|
|
{
|
|
if (!card)
|
|
return;
|
|
- mutex_lock(&info_mutex);
|
|
+
|
|
proc_remove(card->proc_root_link);
|
|
- card->proc_root_link = NULL;
|
|
if (card->proc_root)
|
|
- snd_info_disconnect(card->proc_root);
|
|
+ proc_remove(card->proc_root->p);
|
|
+
|
|
+ mutex_lock(&info_mutex);
|
|
+ if (card->proc_root)
|
|
+ snd_info_clear_entries(card->proc_root);
|
|
+ card->proc_root_link = NULL;
|
|
+ card->proc_root = NULL;
|
|
mutex_unlock(&info_mutex);
|
|
}
|
|
|
|
@@ -745,15 +750,14 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
|
|
}
|
|
EXPORT_SYMBOL(snd_info_create_card_entry);
|
|
|
|
-static void snd_info_disconnect(struct snd_info_entry *entry)
|
|
+static void snd_info_clear_entries(struct snd_info_entry *entry)
|
|
{
|
|
struct snd_info_entry *p;
|
|
|
|
if (!entry->p)
|
|
return;
|
|
list_for_each_entry(p, &entry->children, list)
|
|
- snd_info_disconnect(p);
|
|
- proc_remove(entry->p);
|
|
+ snd_info_clear_entries(p);
|
|
entry->p = NULL;
|
|
}
|
|
|
|
@@ -770,8 +774,9 @@ void snd_info_free_entry(struct snd_info_entry * entry)
|
|
if (!entry)
|
|
return;
|
|
if (entry->p) {
|
|
+ proc_remove(entry->p);
|
|
mutex_lock(&info_mutex);
|
|
- snd_info_disconnect(entry);
|
|
+ snd_info_clear_entries(entry);
|
|
mutex_unlock(&info_mutex);
|
|
}
|
|
|
|
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
|
|
index 1b8be39c38a96..741a5d17ae4cb 100644
|
|
--- a/sound/hda/hdac_stream.c
|
|
+++ b/sound/hda/hdac_stream.c
|
|
@@ -338,8 +338,10 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
|
|
struct hdac_stream *res = NULL;
|
|
|
|
/* make a non-zero unique key for the substream */
|
|
- int key = (substream->pcm->device << 16) | (substream->number << 2) |
|
|
- (substream->stream + 1);
|
|
+ int key = (substream->number << 2) | (substream->stream + 1);
|
|
+
|
|
+ if (substream->pcm)
|
|
+ key |= (substream->pcm->device << 16);
|
|
|
|
spin_lock_irq(&bus->reg_lock);
|
|
list_for_each_entry(azx_dev, &bus->stream_list, list) {
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 0163d4c7fdda8..b63e12b661996 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -9624,6 +9624,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
|
|
SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x890e, "HP 255 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
|
SND_PCI_QUIRK(0x103c, 0x8919, "HP Pavilion Aero Laptop 13-be0xxx", ALC287_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x896d, "HP ZBook Firefly 16 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x896e, "HP EliteBook x360 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
@@ -9659,6 +9660,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x8b2f, "HP 255 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
|
|
SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8b43, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8b44, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
@@ -9692,12 +9694,16 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x103c, 0x8c70, "HP EliteBook 835 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8c71, "HP EliteBook 845 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8c72, "HP EliteBook 865 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
|
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
|
|
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
|
SND_PCI_QUIRK(0x1043, 0x10a1, "ASUS UX391UA", ALC294_FIXUP_ASUS_SPK),
|
|
SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
|
|
SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
|
+ SND_PCI_QUIRK(0x1043, 0x10d3, "ASUS K6500ZC", ALC294_FIXUP_ASUS_SPK),
|
|
SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
|
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
|
|
@@ -9749,6 +9755,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
|
|
SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
|
|
SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS UX3402VA", ALC245_FIXUP_CS35L41_SPI_2),
|
|
+ SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2),
|
|
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
|
|
SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
|
|
SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
|
|
@@ -10590,22 +10597,6 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
|
|
{0x12, 0x90a60130},
|
|
{0x17, 0x90170110},
|
|
{0x21, 0x03211020}),
|
|
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
|
|
- {0x14, 0x90170110},
|
|
- {0x21, 0x04211020}),
|
|
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
|
|
- {0x14, 0x90170110},
|
|
- {0x21, 0x04211030}),
|
|
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
- ALC295_STANDARD_PINS,
|
|
- {0x17, 0x21014020},
|
|
- {0x18, 0x21a19030}),
|
|
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
- ALC295_STANDARD_PINS,
|
|
- {0x17, 0x21014040},
|
|
- {0x18, 0x21a19050}),
|
|
- SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
- ALC295_STANDARD_PINS),
|
|
SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
ALC298_STANDARD_PINS,
|
|
{0x17, 0x90170110}),
|
|
@@ -10649,6 +10640,9 @@ static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = {
|
|
SND_HDA_PIN_QUIRK(0x10ec0289, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
|
|
{0x19, 0x40000000},
|
|
{0x1b, 0x40000000}),
|
|
+ SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE,
|
|
+ {0x19, 0x40000000},
|
|
+ {0x1b, 0x40000000}),
|
|
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
{0x19, 0x40000000},
|
|
{0x1a, 0x40000000}),
|
|
diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c
|
|
index 8ed48c86ccb33..2ccc68513f7c1 100644
|
|
--- a/sound/soc/codecs/lpass-wsa-macro.c
|
|
+++ b/sound/soc/codecs/lpass-wsa-macro.c
|
|
@@ -1682,6 +1682,9 @@ static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w,
|
|
boost_path_cfg1 = CDC_WSA_RX1_RX_PATH_CFG1;
|
|
reg = CDC_WSA_RX1_RX_PATH_CTL;
|
|
reg_mix = CDC_WSA_RX1_RX_PATH_MIX_CTL;
|
|
+ } else {
|
|
+ dev_warn(component->dev, "Incorrect widget name in the driver\n");
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
switch (event) {
|
|
diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
|
|
index cdcbf04b8832f..5e2ec60e2954b 100644
|
|
--- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
|
|
+++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
|
|
@@ -75,6 +75,39 @@ static struct snd_soc_acpi_mach *cht_ess8316_quirk(void *arg)
|
|
return arg;
|
|
}
|
|
|
|
+/*
|
|
+ * The Lenovo Yoga Tab 3 Pro YT3-X90, with Android factory OS has a buggy DSDT
|
|
+ * with the coded not being listed at all.
|
|
+ */
|
|
+static const struct dmi_system_id lenovo_yoga_tab3_x90[] = {
|
|
+ {
|
|
+ /* Lenovo Yoga Tab 3 Pro YT3-X90, codec missing from DSDT */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
|
|
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
|
|
+ },
|
|
+ },
|
|
+ { }
|
|
+};
|
|
+
|
|
+static struct snd_soc_acpi_mach cht_lenovo_yoga_tab3_x90_mach = {
|
|
+ .id = "10WM5102",
|
|
+ .drv_name = "bytcr_wm5102",
|
|
+ .fw_filename = "intel/fw_sst_22a8.bin",
|
|
+ .board = "bytcr_wm5102",
|
|
+ .sof_tplg_filename = "sof-cht-wm5102.tplg",
|
|
+};
|
|
+
|
|
+static struct snd_soc_acpi_mach *lenovo_yt3_x90_quirk(void *arg)
|
|
+{
|
|
+ if (dmi_check_system(lenovo_yoga_tab3_x90))
|
|
+ return &cht_lenovo_yoga_tab3_x90_mach;
|
|
+
|
|
+ /* Skip wildcard match snd_soc_acpi_intel_cherrytrail_machines[] entry */
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
static const struct snd_soc_acpi_codecs rt5640_comp_ids = {
|
|
.num_codecs = 2,
|
|
.codecs = { "10EC5640", "10EC3276" },
|
|
@@ -175,6 +208,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[] = {
|
|
.drv_name = "sof_pcm512x",
|
|
.sof_tplg_filename = "sof-cht-src-50khz-pcm512x.tplg",
|
|
},
|
|
+ /*
|
|
+ * Special case for the Lenovo Yoga Tab 3 Pro YT3-X90 where the DSDT
|
|
+ * misses the codec. Match on the SST id instead, lenovo_yt3_x90_quirk()
|
|
+ * will return a YT3 specific mach or NULL when called on other hw,
|
|
+ * skipping this entry.
|
|
+ */
|
|
+ {
|
|
+ .id = "808622A8",
|
|
+ .machine_quirk = lenovo_yt3_x90_quirk,
|
|
+ },
|
|
|
|
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
|
|
/*
|
|
diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c
|
|
index c08f3960ddd96..06e1872abfee7 100644
|
|
--- a/sound/soc/sof/ipc4.c
|
|
+++ b/sound/soc/sof/ipc4.c
|
|
@@ -601,6 +601,9 @@ static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev)
|
|
case SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS:
|
|
sof_ipc4_mtrace_update_pos(sdev, SOF_IPC4_LOG_CORE_GET(ipc4_msg->primary));
|
|
break;
|
|
+ case SOF_IPC4_NOTIFY_EXCEPTION_CAUGHT:
|
|
+ snd_sof_dsp_panic(sdev, 0, true);
|
|
+ break;
|
|
default:
|
|
dev_dbg(sdev->dev, "Unhandled DSP message: %#x|%#x\n",
|
|
ipc4_msg->primary, ipc4_msg->extension);
|
|
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
|
|
index cf2c0db57d899..061ab7289a6c3 100644
|
|
--- a/sound/soc/sof/sof-audio.c
|
|
+++ b/sound/soc/sof/sof-audio.c
|
|
@@ -832,6 +832,13 @@ int sof_machine_check(struct snd_sof_dev *sdev)
|
|
mach = snd_sof_machine_select(sdev);
|
|
if (mach) {
|
|
sof_pdata->machine = mach;
|
|
+
|
|
+ if (sof_pdata->subsystem_id_set) {
|
|
+ mach->mach_params.subsystem_vendor = sof_pdata->subsystem_vendor;
|
|
+ mach->mach_params.subsystem_device = sof_pdata->subsystem_device;
|
|
+ mach->mach_params.subsystem_id_set = true;
|
|
+ }
|
|
+
|
|
snd_sof_set_mach_params(mach, sdev);
|
|
return 0;
|
|
}
|
|
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
|
|
index 05fb4e20e8a40..99cc272e321d0 100644
|
|
--- a/sound/soc/sof/sof-pci-dev.c
|
|
+++ b/sound/soc/sof/sof-pci-dev.c
|
|
@@ -217,6 +217,14 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
|
|
return ret;
|
|
|
|
sof_pdata->name = pci_name(pci);
|
|
+
|
|
+ /* PCI defines a vendor ID of 0xFFFF as invalid. */
|
|
+ if (pci->subsystem_vendor != 0xFFFF) {
|
|
+ sof_pdata->subsystem_vendor = pci->subsystem_vendor;
|
|
+ sof_pdata->subsystem_device = pci->subsystem_device;
|
|
+ sof_pdata->subsystem_id_set = true;
|
|
+ }
|
|
+
|
|
sof_pdata->desc = desc;
|
|
sof_pdata->dev = dev;
|
|
|
|
diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c
|
|
index 7c539a41a6a34..4b8aac1a36fa2 100644
|
|
--- a/sound/soc/ti/omap-mcbsp.c
|
|
+++ b/sound/soc/ti/omap-mcbsp.c
|
|
@@ -74,14 +74,16 @@ static int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
|
|
return -EINVAL;
|
|
}
|
|
|
|
- pm_runtime_put_sync(mcbsp->dev);
|
|
+ if (mcbsp->active)
|
|
+ pm_runtime_put_sync(mcbsp->dev);
|
|
|
|
r = clk_set_parent(mcbsp->fclk, fck_src);
|
|
if (r)
|
|
dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n",
|
|
src);
|
|
|
|
- pm_runtime_get_sync(mcbsp->dev);
|
|
+ if (mcbsp->active)
|
|
+ pm_runtime_get_sync(mcbsp->dev);
|
|
|
|
clk_put(fck_src);
|
|
|
|
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
|
|
index d1338a4071268..6fb64c58b408b 100644
|
|
--- a/tools/perf/util/intel-pt.c
|
|
+++ b/tools/perf/util/intel-pt.c
|
|
@@ -1483,9 +1483,11 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
|
|
} else if (ptq->state->flags & INTEL_PT_ASYNC) {
|
|
if (!ptq->state->to_ip)
|
|
ptq->flags = PERF_IP_FLAG_BRANCH |
|
|
+ PERF_IP_FLAG_ASYNC |
|
|
PERF_IP_FLAG_TRACE_END;
|
|
else if (ptq->state->from_nr && !ptq->state->to_nr)
|
|
ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
|
|
+ PERF_IP_FLAG_ASYNC |
|
|
PERF_IP_FLAG_VMEXIT;
|
|
else
|
|
ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
|
|
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
|
|
index c61c6c704fbe6..b113900d94879 100644
|
|
--- a/tools/power/x86/turbostat/turbostat.c
|
|
+++ b/tools/power/x86/turbostat/turbostat.c
|
|
@@ -2180,7 +2180,7 @@ retry:
|
|
if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) {
|
|
if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
|
|
return -7;
|
|
- } else if (do_knl_cstates || soft_c1_residency_display(BIC_CPU_c6)) {
|
|
+ } else if (do_knl_cstates && soft_c1_residency_display(BIC_CPU_c6)) {
|
|
if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6))
|
|
return -7;
|
|
}
|
|
@@ -5790,6 +5790,7 @@ void process_cpuid()
|
|
rapl_probe(family, model);
|
|
perf_limit_reasons_probe(family, model);
|
|
automatic_cstate_conversion_probe(family, model);
|
|
+ prewake_cstate_probe(family, model);
|
|
|
|
check_tcc_offset(model_orig);
|
|
|
|
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
|
|
index 7edce12fd2ce5..339b31a3319bf 100644
|
|
--- a/tools/testing/cxl/test/cxl.c
|
|
+++ b/tools/testing/cxl/test/cxl.c
|
|
@@ -551,6 +551,142 @@ static int mock_decoder_reset(struct cxl_decoder *cxld)
|
|
return 0;
|
|
}
|
|
|
|
+static void default_mock_decoder(struct cxl_decoder *cxld)
|
|
+{
|
|
+ cxld->hpa_range = (struct range){
|
|
+ .start = 0,
|
|
+ .end = -1,
|
|
+ };
|
|
+
|
|
+ cxld->interleave_ways = 1;
|
|
+ cxld->interleave_granularity = 256;
|
|
+ cxld->target_type = CXL_DECODER_EXPANDER;
|
|
+ cxld->commit = mock_decoder_commit;
|
|
+ cxld->reset = mock_decoder_reset;
|
|
+}
|
|
+
|
|
+static int first_decoder(struct device *dev, void *data)
|
|
+{
|
|
+ struct cxl_decoder *cxld;
|
|
+
|
|
+ if (!is_switch_decoder(dev))
|
|
+ return 0;
|
|
+ cxld = to_cxl_decoder(dev);
|
|
+ if (cxld->id == 0)
|
|
+ return 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
|
|
+{
|
|
+ struct acpi_cedt_cfmws *window = mock_cfmws[0];
|
|
+ struct platform_device *pdev = NULL;
|
|
+ struct cxl_endpoint_decoder *cxled;
|
|
+ struct cxl_switch_decoder *cxlsd;
|
|
+ struct cxl_port *port, *iter;
|
|
+ const int size = SZ_512M;
|
|
+ struct cxl_memdev *cxlmd;
|
|
+ struct cxl_dport *dport;
|
|
+ struct device *dev;
|
|
+ bool hb0 = false;
|
|
+ u64 base;
|
|
+ int i;
|
|
+
|
|
+ if (is_endpoint_decoder(&cxld->dev)) {
|
|
+ cxled = to_cxl_endpoint_decoder(&cxld->dev);
|
|
+ cxlmd = cxled_to_memdev(cxled);
|
|
+ WARN_ON(!dev_is_platform(cxlmd->dev.parent));
|
|
+ pdev = to_platform_device(cxlmd->dev.parent);
|
|
+
|
|
+ /* check is endpoint is attach to host-bridge0 */
|
|
+ port = cxled_to_port(cxled);
|
|
+ do {
|
|
+ if (port->uport == &cxl_host_bridge[0]->dev) {
|
|
+ hb0 = true;
|
|
+ break;
|
|
+ }
|
|
+ if (is_cxl_port(port->dev.parent))
|
|
+ port = to_cxl_port(port->dev.parent);
|
|
+ else
|
|
+ port = NULL;
|
|
+ } while (port);
|
|
+ port = cxled_to_port(cxled);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * The first decoder on the first 2 devices on the first switch
|
|
+ * attached to host-bridge0 mock a fake / static RAM region. All
|
|
+ * other decoders are default disabled. Given the round robin
|
|
+ * assignment those devices are named cxl_mem.0, and cxl_mem.4.
|
|
+ *
|
|
+ * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
|
|
+ */
|
|
+ if (!hb0 || pdev->id % 4 || pdev->id > 4 || cxld->id > 0) {
|
|
+ default_mock_decoder(cxld);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ base = window->base_hpa;
|
|
+ cxld->hpa_range = (struct range) {
|
|
+ .start = base,
|
|
+ .end = base + size - 1,
|
|
+ };
|
|
+
|
|
+ cxld->interleave_ways = 2;
|
|
+ eig_to_granularity(window->granularity, &cxld->interleave_granularity);
|
|
+ cxld->target_type = CXL_DECODER_EXPANDER;
|
|
+ cxld->flags = CXL_DECODER_F_ENABLE;
|
|
+ cxled->state = CXL_DECODER_STATE_AUTO;
|
|
+ port->commit_end = cxld->id;
|
|
+ devm_cxl_dpa_reserve(cxled, 0, size / cxld->interleave_ways, 0);
|
|
+ cxld->commit = mock_decoder_commit;
|
|
+ cxld->reset = mock_decoder_reset;
|
|
+
|
|
+ /*
|
|
+ * Now that endpoint decoder is set up, walk up the hierarchy
|
|
+ * and setup the switch and root port decoders targeting @cxlmd.
|
|
+ */
|
|
+ iter = port;
|
|
+ for (i = 0; i < 2; i++) {
|
|
+ dport = iter->parent_dport;
|
|
+ iter = dport->port;
|
|
+ dev = device_find_child(&iter->dev, NULL, first_decoder);
|
|
+ /*
|
|
+ * Ancestor ports are guaranteed to be enumerated before
|
|
+ * @port, and all ports have at least one decoder.
|
|
+ */
|
|
+ if (WARN_ON(!dev))
|
|
+ continue;
|
|
+ cxlsd = to_cxl_switch_decoder(dev);
|
|
+ if (i == 0) {
|
|
+ /* put cxl_mem.4 second in the decode order */
|
|
+ if (pdev->id == 4)
|
|
+ cxlsd->target[1] = dport;
|
|
+ else
|
|
+ cxlsd->target[0] = dport;
|
|
+ } else
|
|
+ cxlsd->target[0] = dport;
|
|
+ cxld = &cxlsd->cxld;
|
|
+ cxld->target_type = CXL_DECODER_EXPANDER;
|
|
+ cxld->flags = CXL_DECODER_F_ENABLE;
|
|
+ iter->commit_end = 0;
|
|
+ /*
|
|
+ * Switch targets 2 endpoints, while host bridge targets
|
|
+ * one root port
|
|
+ */
|
|
+ if (i == 0)
|
|
+ cxld->interleave_ways = 2;
|
|
+ else
|
|
+ cxld->interleave_ways = 1;
|
|
+ cxld->interleave_granularity = 4096;
|
|
+ cxld->hpa_range = (struct range) {
|
|
+ .start = base,
|
|
+ .end = base + size - 1,
|
|
+ };
|
|
+ put_device(dev);
|
|
+ }
|
|
+}
|
|
+
|
|
static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
|
|
{
|
|
struct cxl_port *port = cxlhdm->port;
|
|
@@ -596,16 +732,7 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
|
|
cxld = &cxled->cxld;
|
|
}
|
|
|
|
- cxld->hpa_range = (struct range) {
|
|
- .start = 0,
|
|
- .end = -1,
|
|
- };
|
|
-
|
|
- cxld->interleave_ways = min_not_zero(target_count, 1);
|
|
- cxld->interleave_granularity = SZ_4K;
|
|
- cxld->target_type = CXL_DECODER_EXPANDER;
|
|
- cxld->commit = mock_decoder_commit;
|
|
- cxld->reset = mock_decoder_reset;
|
|
+ mock_init_hdm_decoder(cxld);
|
|
|
|
if (target_count) {
|
|
rc = device_for_each_child(port->uport, &ctx,
|
|
diff --git a/tools/testing/selftests/efivarfs/create-read.c b/tools/testing/selftests/efivarfs/create-read.c
|
|
index 9674a19396a32..7bc7af4eb2c17 100644
|
|
--- a/tools/testing/selftests/efivarfs/create-read.c
|
|
+++ b/tools/testing/selftests/efivarfs/create-read.c
|
|
@@ -32,8 +32,10 @@ int main(int argc, char **argv)
|
|
rc = read(fd, buf, sizeof(buf));
|
|
if (rc != 0) {
|
|
fprintf(stderr, "Reading a new var should return EOF\n");
|
|
+ close(fd);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
+ close(fd);
|
|
return EXIT_SUCCESS;
|
|
}
|
|
diff --git a/tools/testing/selftests/lkdtm/config b/tools/testing/selftests/lkdtm/config
|
|
index 5d52f64dfb430..7afe05e8c4d79 100644
|
|
--- a/tools/testing/selftests/lkdtm/config
|
|
+++ b/tools/testing/selftests/lkdtm/config
|
|
@@ -9,7 +9,6 @@ CONFIG_INIT_ON_FREE_DEFAULT_ON=y
|
|
CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
|
|
CONFIG_UBSAN=y
|
|
CONFIG_UBSAN_BOUNDS=y
|
|
-CONFIG_UBSAN_TRAP=y
|
|
CONFIG_STACKPROTECTOR_STRONG=y
|
|
CONFIG_SLUB_DEBUG=y
|
|
CONFIG_SLUB_DEBUG_ON=y
|
|
diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt
|
|
index 607b8d7e3ea34..2f3a1b96da6e3 100644
|
|
--- a/tools/testing/selftests/lkdtm/tests.txt
|
|
+++ b/tools/testing/selftests/lkdtm/tests.txt
|
|
@@ -7,7 +7,7 @@ EXCEPTION
|
|
#EXHAUST_STACK Corrupts memory on failure
|
|
#CORRUPT_STACK Crashes entire system on success
|
|
#CORRUPT_STACK_STRONG Crashes entire system on success
|
|
-ARRAY_BOUNDS
|
|
+ARRAY_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
|
|
CORRUPT_LIST_ADD list_add corruption
|
|
CORRUPT_LIST_DEL list_del corruption
|
|
STACK_GUARD_PAGE_LEADING
|
|
diff --git a/tools/testing/selftests/resctrl/Makefile b/tools/testing/selftests/resctrl/Makefile
|
|
index 5073dbc961258..2deac2031de9e 100644
|
|
--- a/tools/testing/selftests/resctrl/Makefile
|
|
+++ b/tools/testing/selftests/resctrl/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
-CFLAGS = -g -Wall -O2 -D_FORTIFY_SOURCE=2
|
|
+CFLAGS = -g -Wall -O2 -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE
|
|
CFLAGS += $(KHDR_INCLUDES)
|
|
|
|
TEST_GEN_PROGS := resctrl_tests
|
|
diff --git a/tools/testing/selftests/resctrl/cmt_test.c b/tools/testing/selftests/resctrl/cmt_test.c
|
|
index 3b0454e7fc826..dd9f9db70af46 100644
|
|
--- a/tools/testing/selftests/resctrl/cmt_test.c
|
|
+++ b/tools/testing/selftests/resctrl/cmt_test.c
|
|
@@ -91,9 +91,6 @@ int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- if (!validate_resctrl_feature_request(CMT_STR))
|
|
- return -1;
|
|
-
|
|
ret = get_cbm_mask("L3", cbm_mask);
|
|
if (ret)
|
|
return ret;
|
|
diff --git a/tools/testing/selftests/resctrl/mba_test.c b/tools/testing/selftests/resctrl/mba_test.c
|
|
index 97dc98c0c9497..ff8b588b63ed7 100644
|
|
--- a/tools/testing/selftests/resctrl/mba_test.c
|
|
+++ b/tools/testing/selftests/resctrl/mba_test.c
|
|
@@ -12,7 +12,7 @@
|
|
|
|
#define RESULT_FILE_NAME "result_mba"
|
|
#define NUM_OF_RUNS 5
|
|
-#define MAX_DIFF_PERCENT 5
|
|
+#define MAX_DIFF_PERCENT 8
|
|
#define ALLOCATION_MAX 100
|
|
#define ALLOCATION_MIN 10
|
|
#define ALLOCATION_STEP 10
|
|
diff --git a/tools/testing/selftests/resctrl/mbm_test.c b/tools/testing/selftests/resctrl/mbm_test.c
|
|
index 280187628054d..5dc1dce89733a 100644
|
|
--- a/tools/testing/selftests/resctrl/mbm_test.c
|
|
+++ b/tools/testing/selftests/resctrl/mbm_test.c
|
|
@@ -11,7 +11,7 @@
|
|
#include "resctrl.h"
|
|
|
|
#define RESULT_FILE_NAME "result_mbm"
|
|
-#define MAX_DIFF_PERCENT 5
|
|
+#define MAX_DIFF_PERCENT 8
|
|
#define NUM_OF_RUNS 5
|
|
|
|
static int
|
|
diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h
|
|
index dbe5cfb545585..4597bba66ad45 100644
|
|
--- a/tools/testing/selftests/resctrl/resctrl.h
|
|
+++ b/tools/testing/selftests/resctrl/resctrl.h
|
|
@@ -1,5 +1,4 @@
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
-#define _GNU_SOURCE
|
|
#ifndef RESCTRL_H
|
|
#define RESCTRL_H
|
|
#include <stdio.h>
|