mirror of
https://github.com/armbian/build.git
synced 2025-08-15 15:46:58 +02:00
9068 lines
304 KiB
Diff
9068 lines
304 KiB
Diff
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index 315a817e338042..f95734ceb82b86 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -5978,8 +5978,6 @@
|
|
|
|
Selecting 'on' will also enable the mitigation
|
|
against user space to user space task attacks.
|
|
- Selecting specific mitigation does not force enable
|
|
- user mitigations.
|
|
|
|
Selecting 'off' will disable both the kernel and
|
|
the user space protections.
|
|
diff --git a/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml b/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml
|
|
index 424a4fc218b66b..2cb311ddd912a9 100644
|
|
--- a/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml
|
|
+++ b/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml
|
|
@@ -103,7 +103,10 @@ properties:
|
|
|
|
resets:
|
|
items:
|
|
- - description: module reset
|
|
+ - description:
|
|
+ Module reset. This property is optional for controllers in Tegra194,
|
|
+ Tegra234 etc where an internal software reset is available as an
|
|
+ alternative.
|
|
|
|
reset-names:
|
|
items:
|
|
@@ -119,6 +122,13 @@ properties:
|
|
- const: rx
|
|
- const: tx
|
|
|
|
+required:
|
|
+ - compatible
|
|
+ - reg
|
|
+ - interrupts
|
|
+ - clocks
|
|
+ - clock-names
|
|
+
|
|
allOf:
|
|
- $ref: /schemas/i2c/i2c-controller.yaml
|
|
- if:
|
|
@@ -172,6 +182,18 @@ allOf:
|
|
items:
|
|
- description: phandle to the VENC power domain
|
|
|
|
+ - if:
|
|
+ not:
|
|
+ properties:
|
|
+ compatible:
|
|
+ contains:
|
|
+ enum:
|
|
+ - nvidia,tegra194-i2c
|
|
+ then:
|
|
+ required:
|
|
+ - resets
|
|
+ - reset-names
|
|
+
|
|
unevaluatedProperties: false
|
|
|
|
examples:
|
|
diff --git a/Makefile b/Makefile
|
|
index 9625d9072c7781..679dff5e165c07 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 6
|
|
PATCHLEVEL = 6
|
|
-SUBLEVEL = 94
|
|
+SUBLEVEL = 95
|
|
EXTRAVERSION =
|
|
NAME = Pinguïn Aangedreven
|
|
|
|
diff --git a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi
|
|
index 96451c8a815ccd..27e73e745e25f2 100644
|
|
--- a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi
|
|
+++ b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi
|
|
@@ -385,7 +385,7 @@ ethphy0: ethernet-phy@0 {
|
|
/* Support GPIO reset on revision C3 boards */
|
|
reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
|
|
reset-assert-us = <300>;
|
|
- reset-deassert-us = <6500>;
|
|
+ reset-deassert-us = <50000>;
|
|
};
|
|
};
|
|
|
|
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
|
|
index c36fb27212615a..86a2f9e5d0ef9d 100644
|
|
--- a/arch/arm/mach-omap2/clockdomain.h
|
|
+++ b/arch/arm/mach-omap2/clockdomain.h
|
|
@@ -48,6 +48,7 @@
|
|
#define CLKDM_NO_AUTODEPS (1 << 4)
|
|
#define CLKDM_ACTIVE_WITH_MPU (1 << 5)
|
|
#define CLKDM_MISSING_IDLE_REPORTING (1 << 6)
|
|
+#define CLKDM_STANDBY_FORCE_WAKEUP BIT(7)
|
|
|
|
#define CLKDM_CAN_HWSUP (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
|
|
#define CLKDM_CAN_SWSUP (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
|
|
diff --git a/arch/arm/mach-omap2/clockdomains33xx_data.c b/arch/arm/mach-omap2/clockdomains33xx_data.c
|
|
index 87f4e927eb1830..c05a3c07d44863 100644
|
|
--- a/arch/arm/mach-omap2/clockdomains33xx_data.c
|
|
+++ b/arch/arm/mach-omap2/clockdomains33xx_data.c
|
|
@@ -19,7 +19,7 @@ static struct clockdomain l4ls_am33xx_clkdm = {
|
|
.pwrdm = { .name = "per_pwrdm" },
|
|
.cm_inst = AM33XX_CM_PER_MOD,
|
|
.clkdm_offs = AM33XX_CM_PER_L4LS_CLKSTCTRL_OFFSET,
|
|
- .flags = CLKDM_CAN_SWSUP,
|
|
+ .flags = CLKDM_CAN_SWSUP | CLKDM_STANDBY_FORCE_WAKEUP,
|
|
};
|
|
|
|
static struct clockdomain l3s_am33xx_clkdm = {
|
|
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
|
|
index c824d4e3db632c..aaee67d097915c 100644
|
|
--- a/arch/arm/mach-omap2/cm33xx.c
|
|
+++ b/arch/arm/mach-omap2/cm33xx.c
|
|
@@ -20,6 +20,9 @@
|
|
#include "cm-regbits-34xx.h"
|
|
#include "cm-regbits-33xx.h"
|
|
#include "prm33xx.h"
|
|
+#if IS_ENABLED(CONFIG_SUSPEND)
|
|
+#include <linux/suspend.h>
|
|
+#endif
|
|
|
|
/*
|
|
* CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
|
|
@@ -328,8 +331,17 @@ static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm)
|
|
{
|
|
bool hwsup = false;
|
|
|
|
+#if IS_ENABLED(CONFIG_SUSPEND)
|
|
+ /*
|
|
+ * In case of standby, Don't put the l4ls clk domain to sleep.
|
|
+ * Since CM3 PM FW doesn't wake-up/enable the l4ls clk domain
|
|
+ * upon wake-up, CM3 PM FW fails to wake-up th MPU.
|
|
+ */
|
|
+ if (pm_suspend_target_state == PM_SUSPEND_STANDBY &&
|
|
+ (clkdm->flags & CLKDM_STANDBY_FORCE_WAKEUP))
|
|
+ return 0;
|
|
+#endif
|
|
hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
|
|
-
|
|
if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
|
|
am33xx_clkdm_sleep(clkdm);
|
|
|
|
diff --git a/arch/arm/mach-omap2/pmic-cpcap.c b/arch/arm/mach-omap2/pmic-cpcap.c
|
|
index 668dc84fd31e04..527cf4b7e37874 100644
|
|
--- a/arch/arm/mach-omap2/pmic-cpcap.c
|
|
+++ b/arch/arm/mach-omap2/pmic-cpcap.c
|
|
@@ -264,7 +264,11 @@ int __init omap4_cpcap_init(void)
|
|
|
|
static int __init cpcap_late_init(void)
|
|
{
|
|
- omap4_vc_set_pmic_signaling(PWRDM_POWER_RET);
|
|
+ if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
|
|
+ return 0;
|
|
+
|
|
+ if (soc_is_omap443x() || soc_is_omap446x() || soc_is_omap447x())
|
|
+ omap4_vc_set_pmic_signaling(PWRDM_POWER_RET);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
|
|
index 1c5aeba9bc27f3..7801c5bb775d90 100644
|
|
--- a/arch/arm/mm/ioremap.c
|
|
+++ b/arch/arm/mm/ioremap.c
|
|
@@ -515,7 +515,5 @@ void __init early_ioremap_init(void)
|
|
bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
|
|
unsigned long flags)
|
|
{
|
|
- unsigned long pfn = PHYS_PFN(offset);
|
|
-
|
|
- return memblock_is_map_memory(pfn);
|
|
+ return memblock_is_map_memory(offset);
|
|
}
|
|
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
|
|
index d37db2f7a54cf0..6eeb56b6fac13e 100644
|
|
--- a/arch/arm64/include/asm/tlbflush.h
|
|
+++ b/arch/arm64/include/asm/tlbflush.h
|
|
@@ -311,13 +311,14 @@ static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *b
|
|
}
|
|
|
|
/*
|
|
- * If mprotect/munmap/etc occurs during TLB batched flushing, we need to
|
|
- * synchronise all the TLBI issued with a DSB to avoid the race mentioned in
|
|
- * flush_tlb_batched_pending().
|
|
+ * If mprotect/munmap/etc occurs during TLB batched flushing, we need to ensure
|
|
+ * all the previously issued TLBIs targeting mm have completed. But since we
|
|
+ * can be executing on a remote CPU, a DSB cannot guarantee this like it can
|
|
+ * for arch_tlbbatch_flush(). Our only option is to flush the entire mm.
|
|
*/
|
|
static inline void arch_flush_tlb_batched_pending(struct mm_struct *mm)
|
|
{
|
|
- dsb(ish);
|
|
+ flush_tlb_mm(mm);
|
|
}
|
|
|
|
/*
|
|
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
|
|
index a26293e0cc555d..c30f5a70bd18f4 100644
|
|
--- a/arch/arm64/kernel/ptrace.c
|
|
+++ b/arch/arm64/kernel/ptrace.c
|
|
@@ -139,7 +139,7 @@ unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
|
|
|
|
addr += n;
|
|
if (regs_within_kernel_stack(regs, (unsigned long)addr))
|
|
- return *addr;
|
|
+ return READ_ONCE_NOCHECK(*addr);
|
|
else
|
|
return 0;
|
|
}
|
|
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
|
|
index bc97916a035a64..c8e83fe1cd5a73 100644
|
|
--- a/arch/arm64/mm/mmu.c
|
|
+++ b/arch/arm64/mm/mmu.c
|
|
@@ -1253,7 +1253,8 @@ int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
|
|
next = addr;
|
|
end = addr + PUD_SIZE;
|
|
do {
|
|
- pmd_free_pte_page(pmdp, next);
|
|
+ if (pmd_present(pmdp_get(pmdp)))
|
|
+ pmd_free_pte_page(pmdp, next);
|
|
} while (pmdp++, next += PMD_SIZE, next != end);
|
|
|
|
pud_clear(pudp);
|
|
diff --git a/arch/loongarch/include/asm/irqflags.h b/arch/loongarch/include/asm/irqflags.h
|
|
index 319a8c616f1f5b..003172b8406be7 100644
|
|
--- a/arch/loongarch/include/asm/irqflags.h
|
|
+++ b/arch/loongarch/include/asm/irqflags.h
|
|
@@ -14,40 +14,48 @@
|
|
static inline void arch_local_irq_enable(void)
|
|
{
|
|
u32 flags = CSR_CRMD_IE;
|
|
+ register u32 mask asm("t0") = CSR_CRMD_IE;
|
|
+
|
|
__asm__ __volatile__(
|
|
"csrxchg %[val], %[mask], %[reg]\n\t"
|
|
: [val] "+r" (flags)
|
|
- : [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
+ : [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
: "memory");
|
|
}
|
|
|
|
static inline void arch_local_irq_disable(void)
|
|
{
|
|
u32 flags = 0;
|
|
+ register u32 mask asm("t0") = CSR_CRMD_IE;
|
|
+
|
|
__asm__ __volatile__(
|
|
"csrxchg %[val], %[mask], %[reg]\n\t"
|
|
: [val] "+r" (flags)
|
|
- : [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
+ : [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
: "memory");
|
|
}
|
|
|
|
static inline unsigned long arch_local_irq_save(void)
|
|
{
|
|
u32 flags = 0;
|
|
+ register u32 mask asm("t0") = CSR_CRMD_IE;
|
|
+
|
|
__asm__ __volatile__(
|
|
"csrxchg %[val], %[mask], %[reg]\n\t"
|
|
: [val] "+r" (flags)
|
|
- : [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
+ : [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
: "memory");
|
|
return flags;
|
|
}
|
|
|
|
static inline void arch_local_irq_restore(unsigned long flags)
|
|
{
|
|
+ register u32 mask asm("t0") = CSR_CRMD_IE;
|
|
+
|
|
__asm__ __volatile__(
|
|
"csrxchg %[val], %[mask], %[reg]\n\t"
|
|
: [val] "+r" (flags)
|
|
- : [mask] "r" (CSR_CRMD_IE), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
+ : [mask] "r" (mask), [reg] "i" (LOONGARCH_CSR_CRMD)
|
|
: "memory");
|
|
}
|
|
|
|
diff --git a/arch/loongarch/mm/hugetlbpage.c b/arch/loongarch/mm/hugetlbpage.c
|
|
index 41308429f44612..58277fd9fb2f0e 100644
|
|
--- a/arch/loongarch/mm/hugetlbpage.c
|
|
+++ b/arch/loongarch/mm/hugetlbpage.c
|
|
@@ -47,7 +47,8 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr,
|
|
pmd = pmd_offset(pud, addr);
|
|
}
|
|
}
|
|
- return pmd_none(pmdp_get(pmd)) ? NULL : (pte_t *) pmd;
|
|
+
|
|
+ return (!pmd || pmd_none(pmdp_get(pmd))) ? NULL : (pte_t *) pmd;
|
|
}
|
|
|
|
int pmd_huge(pmd_t pmd)
|
|
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
|
|
index eb56581f6d734f..0a3249647401d4 100644
|
|
--- a/arch/mips/vdso/Makefile
|
|
+++ b/arch/mips/vdso/Makefile
|
|
@@ -30,6 +30,7 @@ endif
|
|
# offsets.
|
|
cflags-vdso := $(ccflags-vdso) \
|
|
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
|
|
+ $(filter -std=%,$(KBUILD_CFLAGS)) \
|
|
-O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
|
|
-mrelax-pic-calls $(call cc-option, -mexplicit-relocs) \
|
|
-fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
|
|
diff --git a/arch/parisc/boot/compressed/Makefile b/arch/parisc/boot/compressed/Makefile
|
|
index a294a1b58ee7ed..9fba12b70d1b31 100644
|
|
--- a/arch/parisc/boot/compressed/Makefile
|
|
+++ b/arch/parisc/boot/compressed/Makefile
|
|
@@ -22,6 +22,7 @@ KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs -Os
|
|
ifndef CONFIG_64BIT
|
|
KBUILD_CFLAGS += -mfast-indirect-calls
|
|
endif
|
|
+KBUILD_CFLAGS += -std=gnu11
|
|
|
|
LDFLAGS_vmlinux := -X -e startup --as-needed -T
|
|
$(obj)/vmlinux: $(obj)/vmlinux.lds $(addprefix $(obj)/, $(OBJECTS)) $(LIBGCC) FORCE
|
|
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
|
|
index a8e75e5b884a70..e673c71e16d97a 100644
|
|
--- a/arch/parisc/kernel/unaligned.c
|
|
+++ b/arch/parisc/kernel/unaligned.c
|
|
@@ -24,7 +24,7 @@
|
|
#define DPRINTF(fmt, args...)
|
|
#endif
|
|
|
|
-#define RFMT "%#08lx"
|
|
+#define RFMT "0x%08lx"
|
|
|
|
/* 1111 1100 0000 0000 0001 0011 1100 0000 */
|
|
#define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6)
|
|
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
|
|
index e7792aa135105a..fa792653286659 100644
|
|
--- a/arch/powerpc/include/asm/ppc_asm.h
|
|
+++ b/arch/powerpc/include/asm/ppc_asm.h
|
|
@@ -183,7 +183,7 @@
|
|
/*
|
|
* Used to name C functions called from asm
|
|
*/
|
|
-#ifdef CONFIG_PPC_KERNEL_PCREL
|
|
+#if defined(__powerpc64__) && defined(CONFIG_PPC_KERNEL_PCREL)
|
|
#define CFUNC(name) name@notoc
|
|
#else
|
|
#define CFUNC(name) name
|
|
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
|
|
index ab316e155ea9f5..2e286bba2f6456 100644
|
|
--- a/arch/powerpc/kernel/eeh.c
|
|
+++ b/arch/powerpc/kernel/eeh.c
|
|
@@ -1516,6 +1516,8 @@ int eeh_pe_configure(struct eeh_pe *pe)
|
|
/* Invalid PE ? */
|
|
if (!pe)
|
|
return -ENODEV;
|
|
+ else
|
|
+ ret = eeh_ops->configure_bridge(pe);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
|
|
index d5defff8472da7..47a9533a4dc1d6 100644
|
|
--- a/arch/powerpc/kernel/vdso/Makefile
|
|
+++ b/arch/powerpc/kernel/vdso/Makefile
|
|
@@ -50,7 +50,7 @@ ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl,--orphan-handling=$(CONFIG_LD_ORPHAN_WAR
|
|
ldflags-y += $(filter-out $(CC_AUTO_VAR_INIT_ZERO_ENABLER) $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS))
|
|
|
|
CC32FLAGS := -m32
|
|
-CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
|
|
+CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc -mpcrel
|
|
ifdef CONFIG_CC_IS_CLANG
|
|
# This flag is supported by clang for 64-bit but not 32-bit so it will cause
|
|
# an unused command line flag warning for this file.
|
|
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
|
|
index 423ee1d5bd9440..fdcf10cd4d1270 100644
|
|
--- a/arch/powerpc/platforms/pseries/msi.c
|
|
+++ b/arch/powerpc/platforms/pseries/msi.c
|
|
@@ -519,7 +519,12 @@ static struct msi_domain_info pseries_msi_domain_info = {
|
|
|
|
static void pseries_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
|
|
{
|
|
- __pci_read_msi_msg(irq_data_get_msi_desc(data), msg);
|
|
+ struct pci_dev *dev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data));
|
|
+
|
|
+ if (dev->current_state == PCI_D0)
|
|
+ __pci_read_msi_msg(irq_data_get_msi_desc(data), msg);
|
|
+ else
|
|
+ get_cached_msi_msg(data->irq, msg);
|
|
}
|
|
|
|
static struct irq_chip pseries_msi_irq_chip = {
|
|
diff --git a/arch/riscv/kvm/vcpu_sbi_replace.c b/arch/riscv/kvm/vcpu_sbi_replace.c
|
|
index 87ec68ed52d762..36f5386c60db75 100644
|
|
--- a/arch/riscv/kvm/vcpu_sbi_replace.c
|
|
+++ b/arch/riscv/kvm/vcpu_sbi_replace.c
|
|
@@ -103,7 +103,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run
|
|
kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_SENT);
|
|
break;
|
|
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
|
|
- if (cp->a2 == 0 && cp->a3 == 0)
|
|
+ if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL)
|
|
kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask);
|
|
else
|
|
kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask,
|
|
@@ -111,7 +111,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run
|
|
kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_SENT);
|
|
break;
|
|
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
|
|
- if (cp->a2 == 0 && cp->a3 == 0)
|
|
+ if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL)
|
|
kvm_riscv_hfence_vvma_asid_all(vcpu->kvm,
|
|
hbase, hmask, cp->a4);
|
|
else
|
|
@@ -127,9 +127,9 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run
|
|
case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
|
|
/*
|
|
* Until nested virtualization is implemented, the
|
|
- * SBI HFENCE calls should be treated as NOPs
|
|
+ * SBI HFENCE calls should return not supported
|
|
+ * hence fallthrough.
|
|
*/
|
|
- break;
|
|
default:
|
|
retdata->err_val = SBI_ERR_NOT_SUPPORTED;
|
|
}
|
|
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
|
|
index 090dc38334336b..969a5e15691923 100644
|
|
--- a/arch/s390/kvm/gaccess.c
|
|
+++ b/arch/s390/kvm/gaccess.c
|
|
@@ -490,7 +490,7 @@ enum prot_type {
|
|
PROT_TYPE_DAT = 3,
|
|
PROT_TYPE_IEP = 4,
|
|
/* Dummy value for passing an initialized value when code != PGM_PROTECTION */
|
|
- PROT_NONE,
|
|
+ PROT_TYPE_DUMMY,
|
|
};
|
|
|
|
static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva, u8 ar,
|
|
@@ -506,7 +506,7 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva,
|
|
switch (code) {
|
|
case PGM_PROTECTION:
|
|
switch (prot) {
|
|
- case PROT_NONE:
|
|
+ case PROT_TYPE_DUMMY:
|
|
/* We should never get here, acts like termination */
|
|
WARN_ON_ONCE(1);
|
|
break;
|
|
@@ -976,7 +976,7 @@ static int guest_range_to_gpas(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
|
|
gpa = kvm_s390_real_to_abs(vcpu, ga);
|
|
if (kvm_is_error_gpa(vcpu->kvm, gpa)) {
|
|
rc = PGM_ADDRESSING;
|
|
- prot = PROT_NONE;
|
|
+ prot = PROT_TYPE_DUMMY;
|
|
}
|
|
}
|
|
if (rc)
|
|
@@ -1134,7 +1134,7 @@ int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
|
|
if (rc == PGM_PROTECTION)
|
|
prot = PROT_TYPE_KEYC;
|
|
else
|
|
- prot = PROT_NONE;
|
|
+ prot = PROT_TYPE_DUMMY;
|
|
rc = trans_exc_ending(vcpu, rc, ga, ar, mode, prot, terminate);
|
|
}
|
|
out_unlock:
|
|
diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c
|
|
index a90499c087f0c5..2ee7b5a5016c7d 100644
|
|
--- a/arch/s390/pci/pci_mmio.c
|
|
+++ b/arch/s390/pci/pci_mmio.c
|
|
@@ -223,7 +223,7 @@ static inline int __pcilg_mio_inuser(
|
|
[ioaddr_len] "+&d" (ioaddr_len.pair),
|
|
[cc] "+d" (cc), [val] "=d" (val),
|
|
[dst] "+a" (dst), [cnt] "+d" (cnt), [tmp] "=d" (tmp),
|
|
- [shift] "+d" (shift)
|
|
+ [shift] "+a" (shift)
|
|
:: "cc", "memory");
|
|
|
|
/* did we write everything to the user space buffer? */
|
|
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
|
|
index e9c4bcb38f4586..07b45bbf6348de 100644
|
|
--- a/arch/x86/kernel/cpu/bugs.c
|
|
+++ b/arch/x86/kernel/cpu/bugs.c
|
|
@@ -1442,13 +1442,9 @@ static __ro_after_init enum spectre_v2_mitigation_cmd spectre_v2_cmd;
|
|
static enum spectre_v2_user_cmd __init
|
|
spectre_v2_parse_user_cmdline(void)
|
|
{
|
|
- enum spectre_v2_user_cmd mode;
|
|
char arg[20];
|
|
int ret, i;
|
|
|
|
- mode = IS_ENABLED(CONFIG_MITIGATION_SPECTRE_V2) ?
|
|
- SPECTRE_V2_USER_CMD_AUTO : SPECTRE_V2_USER_CMD_NONE;
|
|
-
|
|
switch (spectre_v2_cmd) {
|
|
case SPECTRE_V2_CMD_NONE:
|
|
return SPECTRE_V2_USER_CMD_NONE;
|
|
@@ -1461,7 +1457,7 @@ spectre_v2_parse_user_cmdline(void)
|
|
ret = cmdline_find_option(boot_command_line, "spectre_v2_user",
|
|
arg, sizeof(arg));
|
|
if (ret < 0)
|
|
- return mode;
|
|
+ return SPECTRE_V2_USER_CMD_AUTO;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) {
|
|
if (match_option(arg, ret, v2_user_options[i].option)) {
|
|
@@ -1471,8 +1467,8 @@ spectre_v2_parse_user_cmdline(void)
|
|
}
|
|
}
|
|
|
|
- pr_err("Unknown user space protection option (%s). Switching to default\n", arg);
|
|
- return mode;
|
|
+ pr_err("Unknown user space protection option (%s). Switching to AUTO select\n", arg);
|
|
+ return SPECTRE_V2_USER_CMD_AUTO;
|
|
}
|
|
|
|
static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
|
|
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
|
|
index c7f8c3200e8d7f..0db6eeeeb67205 100644
|
|
--- a/arch/x86/kernel/cpu/sgx/main.c
|
|
+++ b/arch/x86/kernel/cpu/sgx/main.c
|
|
@@ -718,6 +718,8 @@ int arch_memory_failure(unsigned long pfn, int flags)
|
|
goto out;
|
|
}
|
|
|
|
+ sgx_unmark_page_reclaimable(page);
|
|
+
|
|
/*
|
|
* TBD: Add additional plumbing to enable pre-emptive
|
|
* action for asynchronous poison notification. Until
|
|
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
|
|
index c84a1451f194c4..86c50747e15837 100644
|
|
--- a/arch/x86/kvm/svm/svm.c
|
|
+++ b/arch/x86/kvm/svm/svm.c
|
|
@@ -1503,7 +1503,7 @@ static void svm_clear_current_vmcb(struct vmcb *vmcb)
|
|
{
|
|
int i;
|
|
|
|
- for_each_online_cpu(i)
|
|
+ for_each_possible_cpu(i)
|
|
cmpxchg(per_cpu_ptr(&svm_data.current_vmcb, i), vmcb, NULL);
|
|
}
|
|
|
|
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
|
|
index e5a2c230110ea4..e7f3b70f9114ae 100644
|
|
--- a/arch/x86/kvm/vmx/vmx.c
|
|
+++ b/arch/x86/kvm/vmx/vmx.c
|
|
@@ -787,8 +787,11 @@ static void vmx_emergency_disable(void)
|
|
return;
|
|
|
|
list_for_each_entry(v, &per_cpu(loaded_vmcss_on_cpu, cpu),
|
|
- loaded_vmcss_on_cpu_link)
|
|
+ loaded_vmcss_on_cpu_link) {
|
|
vmcs_clear(v->vmcs);
|
|
+ if (v->shadow_vmcs)
|
|
+ vmcs_clear(v->shadow_vmcs);
|
|
+ }
|
|
|
|
kvm_cpu_vmxoff();
|
|
}
|
|
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
|
|
index fb9ed5e1da89dc..2bdae8a25e084d 100644
|
|
--- a/drivers/acpi/acpica/dsutils.c
|
|
+++ b/drivers/acpi/acpica/dsutils.c
|
|
@@ -668,6 +668,8 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
|
|
union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
|
|
u32 arg_count = 0;
|
|
u32 index = walk_state->num_operands;
|
|
+ u32 prev_num_operands = walk_state->num_operands;
|
|
+ u32 new_num_operands;
|
|
u32 i;
|
|
|
|
ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
|
|
@@ -696,6 +698,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
|
|
|
|
/* Create the interpreter arguments, in reverse order */
|
|
|
|
+ new_num_operands = index;
|
|
index--;
|
|
for (i = 0; i < arg_count; i++) {
|
|
arg = arguments[index];
|
|
@@ -720,7 +723,11 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
|
|
* pop everything off of the operand stack and delete those
|
|
* objects
|
|
*/
|
|
- acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
|
|
+ walk_state->num_operands = i;
|
|
+ acpi_ds_obj_stack_pop_and_delete(new_num_operands, walk_state);
|
|
+
|
|
+ /* Restore operand count */
|
|
+ walk_state->num_operands = prev_num_operands;
|
|
|
|
ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
|
|
return_ACPI_STATUS(status);
|
|
diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c
|
|
index 54471083ba545e..0bce1baaa62b32 100644
|
|
--- a/drivers/acpi/acpica/psobject.c
|
|
+++ b/drivers/acpi/acpica/psobject.c
|
|
@@ -636,7 +636,8 @@ acpi_status
|
|
acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
|
union acpi_parse_object *op, acpi_status status)
|
|
{
|
|
- acpi_status status2;
|
|
+ acpi_status return_status = status;
|
|
+ u8 ascending = TRUE;
|
|
|
|
ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state);
|
|
|
|
@@ -650,7 +651,7 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
|
op));
|
|
do {
|
|
if (op) {
|
|
- if (walk_state->ascending_callback != NULL) {
|
|
+ if (ascending && walk_state->ascending_callback != NULL) {
|
|
walk_state->op = op;
|
|
walk_state->op_info =
|
|
acpi_ps_get_opcode_info(op->common.
|
|
@@ -672,49 +673,26 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
|
}
|
|
|
|
if (status == AE_CTRL_TERMINATE) {
|
|
- status = AE_OK;
|
|
-
|
|
- /* Clean up */
|
|
- do {
|
|
- if (op) {
|
|
- status2 =
|
|
- acpi_ps_complete_this_op
|
|
- (walk_state, op);
|
|
- if (ACPI_FAILURE
|
|
- (status2)) {
|
|
- return_ACPI_STATUS
|
|
- (status2);
|
|
- }
|
|
- }
|
|
-
|
|
- acpi_ps_pop_scope(&
|
|
- (walk_state->
|
|
- parser_state),
|
|
- &op,
|
|
- &walk_state->
|
|
- arg_types,
|
|
- &walk_state->
|
|
- arg_count);
|
|
-
|
|
- } while (op);
|
|
-
|
|
- return_ACPI_STATUS(status);
|
|
+ ascending = FALSE;
|
|
+ return_status = AE_CTRL_TERMINATE;
|
|
}
|
|
|
|
else if (ACPI_FAILURE(status)) {
|
|
|
|
/* First error is most important */
|
|
|
|
- (void)
|
|
- acpi_ps_complete_this_op(walk_state,
|
|
- op);
|
|
- return_ACPI_STATUS(status);
|
|
+ ascending = FALSE;
|
|
+ return_status = status;
|
|
}
|
|
}
|
|
|
|
- status2 = acpi_ps_complete_this_op(walk_state, op);
|
|
- if (ACPI_FAILURE(status2)) {
|
|
- return_ACPI_STATUS(status2);
|
|
+ status = acpi_ps_complete_this_op(walk_state, op);
|
|
+ if (ACPI_FAILURE(status)) {
|
|
+ ascending = FALSE;
|
|
+ if (ACPI_SUCCESS(return_status) ||
|
|
+ return_status == AE_CTRL_TERMINATE) {
|
|
+ return_status = status;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -724,5 +702,5 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
|
|
|
} while (op);
|
|
|
|
- return_ACPI_STATUS(status);
|
|
+ return_ACPI_STATUS(return_status);
|
|
}
|
|
diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c
|
|
index 42b30b9f93128e..7fad03c5252c35 100644
|
|
--- a/drivers/acpi/acpica/utprint.c
|
|
+++ b/drivers/acpi/acpica/utprint.c
|
|
@@ -333,11 +333,8 @@ int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
|
|
|
|
pos = string;
|
|
|
|
- if (size != ACPI_UINT32_MAX) {
|
|
- end = string + size;
|
|
- } else {
|
|
- end = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
|
|
- }
|
|
+ size = ACPI_MIN(size, ACPI_PTR_DIFF(ACPI_MAX_PTR, string));
|
|
+ end = string + size;
|
|
|
|
for (; *format; ++format) {
|
|
if (*format != '%') {
|
|
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
|
|
index e3cbaf3c3bbc15..cd3cbb7a36f855 100644
|
|
--- a/drivers/acpi/battery.c
|
|
+++ b/drivers/acpi/battery.c
|
|
@@ -243,10 +243,23 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
|
break;
|
|
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
|
case POWER_SUPPLY_PROP_POWER_NOW:
|
|
- if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
|
|
+ if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) {
|
|
ret = -ENODEV;
|
|
- else
|
|
- val->intval = battery->rate_now * 1000;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ val->intval = battery->rate_now * 1000;
|
|
+ /*
|
|
+ * When discharging, the current should be reported as a
|
|
+ * negative number as per the power supply class interface
|
|
+ * definition.
|
|
+ */
|
|
+ if (psp == POWER_SUPPLY_PROP_CURRENT_NOW &&
|
|
+ (battery->state & ACPI_BATTERY_STATE_DISCHARGING) &&
|
|
+ acpi_battery_handle_discharging(battery)
|
|
+ == POWER_SUPPLY_STATUS_DISCHARGING)
|
|
+ val->intval = -val->intval;
|
|
+
|
|
break;
|
|
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
|
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
|
|
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
|
|
index a4aa53b7e2bb30..645464f02363f3 100644
|
|
--- a/drivers/acpi/bus.c
|
|
+++ b/drivers/acpi/bus.c
|
|
@@ -1396,8 +1396,10 @@ static int __init acpi_init(void)
|
|
}
|
|
|
|
acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
|
|
- if (!acpi_kobj)
|
|
- pr_debug("%s: kset create error\n", __func__);
|
|
+ if (!acpi_kobj) {
|
|
+ pr_err("Failed to register kobject\n");
|
|
+ return -ENOMEM;
|
|
+ }
|
|
|
|
init_prmt();
|
|
acpi_init_pcc();
|
|
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
|
|
index 696b99720dcbda..d82728a01832b5 100644
|
|
--- a/drivers/ata/pata_via.c
|
|
+++ b/drivers/ata/pata_via.c
|
|
@@ -368,7 +368,8 @@ static unsigned int via_mode_filter(struct ata_device *dev, unsigned int mask)
|
|
}
|
|
|
|
if (dev->class == ATA_DEV_ATAPI &&
|
|
- dmi_check_system(no_atapi_dma_dmi_table)) {
|
|
+ (dmi_check_system(no_atapi_dma_dmi_table) ||
|
|
+ config->id == PCI_DEVICE_ID_VIA_6415)) {
|
|
ata_dev_warn(dev, "controller locks up on ATAPI DMA, forcing PIO\n");
|
|
mask &= ATA_MASK_PIO;
|
|
}
|
|
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
|
|
index 96bea1ab1eccf4..ff558908897f3e 100644
|
|
--- a/drivers/atm/atmtcp.c
|
|
+++ b/drivers/atm/atmtcp.c
|
|
@@ -288,7 +288,9 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
|
|
struct sk_buff *new_skb;
|
|
int result = 0;
|
|
|
|
- if (!skb->len) return 0;
|
|
+ if (skb->len < sizeof(struct atmtcp_hdr))
|
|
+ goto done;
|
|
+
|
|
dev = vcc->dev_data;
|
|
hdr = (struct atmtcp_hdr *) skb->data;
|
|
if (hdr->length == ATMTCP_HDR_MAGIC) {
|
|
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
|
|
index 0af26cf8c0059f..0d43bf5b6cecbf 100644
|
|
--- a/drivers/base/power/runtime.c
|
|
+++ b/drivers/base/power/runtime.c
|
|
@@ -1001,7 +1001,7 @@ static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer)
|
|
* If 'expires' is after the current time, we've been called
|
|
* too early.
|
|
*/
|
|
- if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
|
|
+ if (expires > 0 && expires <= ktime_get_mono_fast_ns()) {
|
|
dev->power.timer_expires = 0;
|
|
rpm_suspend(dev, dev->power.timer_autosuspends ?
|
|
(RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
|
|
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
|
|
index 079bd14bdedc7c..a7a3e3b66bb5ed 100644
|
|
--- a/drivers/base/swnode.c
|
|
+++ b/drivers/base/swnode.c
|
|
@@ -518,7 +518,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
|
|
if (prop->is_inline)
|
|
return -EINVAL;
|
|
|
|
- if (index * sizeof(*ref) >= prop->length)
|
|
+ if ((index + 1) * sizeof(*ref) > prop->length)
|
|
return -ENOENT;
|
|
|
|
ref_array = prop->pointer;
|
|
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
|
|
index 3523dd82d7a002..280679bde3a506 100644
|
|
--- a/drivers/block/aoe/aoedev.c
|
|
+++ b/drivers/block/aoe/aoedev.c
|
|
@@ -198,6 +198,7 @@ aoedev_downdev(struct aoedev *d)
|
|
{
|
|
struct aoetgt *t, **tt, **te;
|
|
struct list_head *head, *pos, *nx;
|
|
+ struct request *rq, *rqnext;
|
|
int i;
|
|
|
|
d->flags &= ~DEVFL_UP;
|
|
@@ -223,6 +224,13 @@ aoedev_downdev(struct aoedev *d)
|
|
/* clean out the in-process request (if any) */
|
|
aoe_failip(d);
|
|
|
|
+ /* clean out any queued block requests */
|
|
+ list_for_each_entry_safe(rq, rqnext, &d->rq_list, queuelist) {
|
|
+ list_del_init(&rq->queuelist);
|
|
+ blk_mq_start_request(rq);
|
|
+ blk_mq_end_request(rq, BLK_STS_IOERR);
|
|
+ }
|
|
+
|
|
/* fast fail all pending I/O */
|
|
if (d->blkq) {
|
|
/* UP is cleared, freeze+quiesce to insure all are errored */
|
|
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
|
|
index 95095500f93afb..df3e5aab4b5ac9 100644
|
|
--- a/drivers/block/ublk_drv.c
|
|
+++ b/drivers/block/ublk_drv.c
|
|
@@ -2323,6 +2323,9 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
|
|
if (copy_from_user(&info, argp, sizeof(info)))
|
|
return -EFAULT;
|
|
|
|
+ if (info.queue_depth > UBLK_MAX_QUEUE_DEPTH || info.nr_hw_queues > UBLK_MAX_NR_QUEUES)
|
|
+ return -EINVAL;
|
|
+
|
|
if (capable(CAP_SYS_ADMIN))
|
|
info.flags &= ~UBLK_F_UNPRIVILEGED_DEV;
|
|
else if (!(info.flags & UBLK_F_UNPRIVILEGED_DEV))
|
|
diff --git a/drivers/bus/fsl-mc/fsl-mc-uapi.c b/drivers/bus/fsl-mc/fsl-mc-uapi.c
|
|
index 9c4c1395fcdbf2..a376ec66165348 100644
|
|
--- a/drivers/bus/fsl-mc/fsl-mc-uapi.c
|
|
+++ b/drivers/bus/fsl-mc/fsl-mc-uapi.c
|
|
@@ -275,13 +275,13 @@ static struct fsl_mc_cmd_desc fsl_mc_accepted_cmds[] = {
|
|
.size = 8,
|
|
},
|
|
[DPSW_GET_TAILDROP] = {
|
|
- .cmdid_value = 0x0A80,
|
|
+ .cmdid_value = 0x0A90,
|
|
.cmdid_mask = 0xFFF0,
|
|
.token = true,
|
|
.size = 14,
|
|
},
|
|
[DPSW_SET_TAILDROP] = {
|
|
- .cmdid_value = 0x0A90,
|
|
+ .cmdid_value = 0x0A80,
|
|
.cmdid_mask = 0xFFF0,
|
|
.token = true,
|
|
.size = 24,
|
|
diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c
|
|
index 95b10a6cf3073f..8b7a34f4db94bb 100644
|
|
--- a/drivers/bus/fsl-mc/mc-io.c
|
|
+++ b/drivers/bus/fsl-mc/mc-io.c
|
|
@@ -214,12 +214,19 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
|
|
if (error < 0)
|
|
goto error_cleanup_resource;
|
|
|
|
- dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
|
|
- &dpmcp_dev->dev,
|
|
- DL_FLAG_AUTOREMOVE_CONSUMER);
|
|
- if (!dpmcp_dev->consumer_link) {
|
|
- error = -EINVAL;
|
|
- goto error_cleanup_mc_io;
|
|
+ /* If the DPRC device itself tries to allocate a portal (usually for
|
|
+ * UAPI interaction), don't add a device link between them since the
|
|
+ * DPMCP device is an actual child device of the DPRC and a reverse
|
|
+ * dependency is not allowed.
|
|
+ */
|
|
+ if (mc_dev != mc_bus_dev) {
|
|
+ dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
|
|
+ &dpmcp_dev->dev,
|
|
+ DL_FLAG_AUTOREMOVE_CONSUMER);
|
|
+ if (!dpmcp_dev->consumer_link) {
|
|
+ error = -EINVAL;
|
|
+ goto error_cleanup_mc_io;
|
|
+ }
|
|
}
|
|
|
|
*new_mc_io = mc_io;
|
|
diff --git a/drivers/bus/fsl-mc/mc-sys.c b/drivers/bus/fsl-mc/mc-sys.c
|
|
index f2052cd0a05178..b22c59d57c8f0a 100644
|
|
--- a/drivers/bus/fsl-mc/mc-sys.c
|
|
+++ b/drivers/bus/fsl-mc/mc-sys.c
|
|
@@ -19,7 +19,7 @@
|
|
/*
|
|
* Timeout in milliseconds to wait for the completion of an MC command
|
|
*/
|
|
-#define MC_CMD_COMPLETION_TIMEOUT_MS 500
|
|
+#define MC_CMD_COMPLETION_TIMEOUT_MS 15000
|
|
|
|
/*
|
|
* usleep_range() min and max values used to throttle down polling
|
|
diff --git a/drivers/bus/mhi/ep/ring.c b/drivers/bus/mhi/ep/ring.c
|
|
index ba9f696d1aa80e..fedf26392e8d29 100644
|
|
--- a/drivers/bus/mhi/ep/ring.c
|
|
+++ b/drivers/bus/mhi/ep/ring.c
|
|
@@ -131,19 +131,23 @@ int mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *e
|
|
}
|
|
|
|
old_offset = ring->rd_offset;
|
|
- mhi_ep_ring_inc_index(ring);
|
|
|
|
dev_dbg(dev, "Adding an element to ring at offset (%zu)\n", ring->rd_offset);
|
|
+ buf_info.host_addr = ring->rbase + (old_offset * sizeof(*el));
|
|
+ buf_info.dev_addr = el;
|
|
+ buf_info.size = sizeof(*el);
|
|
+
|
|
+ ret = mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ mhi_ep_ring_inc_index(ring);
|
|
|
|
/* Update rp in ring context */
|
|
rp = cpu_to_le64(ring->rd_offset * sizeof(*el) + ring->rbase);
|
|
memcpy_toio((void __iomem *) &ring->ring_ctx->generic.rp, &rp, sizeof(u64));
|
|
|
|
- buf_info.host_addr = ring->rbase + (old_offset * sizeof(*el));
|
|
- buf_info.dev_addr = el;
|
|
- buf_info.size = sizeof(*el);
|
|
-
|
|
- return mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
|
|
+ return ret;
|
|
}
|
|
|
|
void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id)
|
|
diff --git a/drivers/bus/mhi/host/pm.c b/drivers/bus/mhi/host/pm.c
|
|
index 27f8a40f288cfd..e48bf44c785c9b 100644
|
|
--- a/drivers/bus/mhi/host/pm.c
|
|
+++ b/drivers/bus/mhi/host/pm.c
|
|
@@ -586,6 +586,7 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
|
|
struct mhi_cmd *mhi_cmd;
|
|
struct mhi_event_ctxt *er_ctxt;
|
|
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
|
+ bool reset_device = false;
|
|
int ret, i;
|
|
|
|
dev_dbg(dev, "Transitioning from PM state: %s to: %s\n",
|
|
@@ -614,8 +615,23 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
|
|
/* Wake up threads waiting for state transition */
|
|
wake_up_all(&mhi_cntrl->state_event);
|
|
|
|
- /* Trigger MHI RESET so that the device will not access host memory */
|
|
if (MHI_REG_ACCESS_VALID(prev_state)) {
|
|
+ /*
|
|
+ * If the device is in PBL or SBL, it will only respond to
|
|
+ * RESET if the device is in SYSERR state. SYSERR might
|
|
+ * already be cleared at this point.
|
|
+ */
|
|
+ enum mhi_state cur_state = mhi_get_mhi_state(mhi_cntrl);
|
|
+ enum mhi_ee_type cur_ee = mhi_get_exec_env(mhi_cntrl);
|
|
+
|
|
+ if (cur_state == MHI_STATE_SYS_ERR)
|
|
+ reset_device = true;
|
|
+ else if (cur_ee != MHI_EE_PBL && cur_ee != MHI_EE_SBL)
|
|
+ reset_device = true;
|
|
+ }
|
|
+
|
|
+ /* Trigger MHI RESET so that the device will not access host memory */
|
|
+ if (reset_device) {
|
|
u32 in_reset = -1;
|
|
unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms);
|
|
|
|
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
|
|
index 65163312dab8ac..46d7410f6f0fce 100644
|
|
--- a/drivers/bus/ti-sysc.c
|
|
+++ b/drivers/bus/ti-sysc.c
|
|
@@ -667,51 +667,6 @@ static int sysc_parse_and_check_child_range(struct sysc *ddata)
|
|
return 0;
|
|
}
|
|
|
|
-/* Interconnect instances to probe before l4_per instances */
|
|
-static struct resource early_bus_ranges[] = {
|
|
- /* am3/4 l4_wkup */
|
|
- { .start = 0x44c00000, .end = 0x44c00000 + 0x300000, },
|
|
- /* omap4/5 and dra7 l4_cfg */
|
|
- { .start = 0x4a000000, .end = 0x4a000000 + 0x300000, },
|
|
- /* omap4 l4_wkup */
|
|
- { .start = 0x4a300000, .end = 0x4a300000 + 0x30000, },
|
|
- /* omap5 and dra7 l4_wkup without dra7 dcan segment */
|
|
- { .start = 0x4ae00000, .end = 0x4ae00000 + 0x30000, },
|
|
-};
|
|
-
|
|
-static atomic_t sysc_defer = ATOMIC_INIT(10);
|
|
-
|
|
-/**
|
|
- * sysc_defer_non_critical - defer non_critical interconnect probing
|
|
- * @ddata: device driver data
|
|
- *
|
|
- * We want to probe l4_cfg and l4_wkup interconnect instances before any
|
|
- * l4_per instances as l4_per instances depend on resources on l4_cfg and
|
|
- * l4_wkup interconnects.
|
|
- */
|
|
-static int sysc_defer_non_critical(struct sysc *ddata)
|
|
-{
|
|
- struct resource *res;
|
|
- int i;
|
|
-
|
|
- if (!atomic_read(&sysc_defer))
|
|
- return 0;
|
|
-
|
|
- for (i = 0; i < ARRAY_SIZE(early_bus_ranges); i++) {
|
|
- res = &early_bus_ranges[i];
|
|
- if (ddata->module_pa >= res->start &&
|
|
- ddata->module_pa <= res->end) {
|
|
- atomic_set(&sysc_defer, 0);
|
|
-
|
|
- return 0;
|
|
- }
|
|
- }
|
|
-
|
|
- atomic_dec_if_positive(&sysc_defer);
|
|
-
|
|
- return -EPROBE_DEFER;
|
|
-}
|
|
-
|
|
static struct device_node *stdout_path;
|
|
|
|
static void sysc_init_stdout_path(struct sysc *ddata)
|
|
@@ -937,10 +892,6 @@ static int sysc_map_and_check_registers(struct sysc *ddata)
|
|
if (error)
|
|
return error;
|
|
|
|
- error = sysc_defer_non_critical(ddata);
|
|
- if (error)
|
|
- return error;
|
|
-
|
|
sysc_check_children(ddata);
|
|
|
|
if (!of_property_present(np, "reg"))
|
|
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
|
|
index 233ce4a4c1c2f1..69018efbf7f47b 100644
|
|
--- a/drivers/clk/meson/g12a.c
|
|
+++ b/drivers/clk/meson/g12a.c
|
|
@@ -3971,6 +3971,7 @@ static const struct clk_parent_data spicc_sclk_parent_data[] = {
|
|
{ .hw = &g12a_clk81.hw },
|
|
{ .hw = &g12a_fclk_div4.hw },
|
|
{ .hw = &g12a_fclk_div3.hw },
|
|
+ { .hw = &g12a_fclk_div2.hw },
|
|
{ .hw = &g12a_fclk_div5.hw },
|
|
{ .hw = &g12a_fclk_div7.hw },
|
|
};
|
|
diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c
|
|
index d644bc155ec6e5..f5f27535087a30 100644
|
|
--- a/drivers/clk/rockchip/clk-rk3036.c
|
|
+++ b/drivers/clk/rockchip/clk-rk3036.c
|
|
@@ -431,6 +431,7 @@ static const char *const rk3036_critical_clocks[] __initconst = {
|
|
"hclk_peri",
|
|
"pclk_peri",
|
|
"pclk_ddrupctl",
|
|
+ "ddrphy",
|
|
};
|
|
|
|
static void __init rk3036_clk_init(struct device_node *np)
|
|
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
|
|
index e4989764efe2a8..6ff77003a96eac 100644
|
|
--- a/drivers/cpufreq/scmi-cpufreq.c
|
|
+++ b/drivers/cpufreq/scmi-cpufreq.c
|
|
@@ -299,6 +299,40 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
|
|
.register_em = scmi_cpufreq_register_em,
|
|
};
|
|
|
|
+static bool scmi_dev_used_by_cpus(struct device *scmi_dev)
|
|
+{
|
|
+ struct device_node *scmi_np = dev_of_node(scmi_dev);
|
|
+ struct device_node *cpu_np, *np;
|
|
+ struct device *cpu_dev;
|
|
+ int cpu, idx;
|
|
+
|
|
+ if (!scmi_np)
|
|
+ return false;
|
|
+
|
|
+ for_each_possible_cpu(cpu) {
|
|
+ cpu_dev = get_cpu_device(cpu);
|
|
+ if (!cpu_dev)
|
|
+ continue;
|
|
+
|
|
+ cpu_np = dev_of_node(cpu_dev);
|
|
+
|
|
+ np = of_parse_phandle(cpu_np, "clocks", 0);
|
|
+ of_node_put(np);
|
|
+
|
|
+ if (np == scmi_np)
|
|
+ return true;
|
|
+
|
|
+ idx = of_property_match_string(cpu_np, "power-domain-names", "perf");
|
|
+ np = of_parse_phandle(cpu_np, "power-domains", idx);
|
|
+ of_node_put(np);
|
|
+
|
|
+ if (np == scmi_np)
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
static int scmi_cpufreq_probe(struct scmi_device *sdev)
|
|
{
|
|
int ret;
|
|
@@ -307,7 +341,7 @@ static int scmi_cpufreq_probe(struct scmi_device *sdev)
|
|
|
|
handle = sdev->handle;
|
|
|
|
- if (!handle)
|
|
+ if (!handle || !scmi_dev_used_by_cpus(dev))
|
|
return -ENODEV;
|
|
|
|
perf_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PERF, &ph);
|
|
diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c
|
|
index 4e5b6f9a56d1b2..7b8fcfa55038bc 100644
|
|
--- a/drivers/cpufreq/tegra186-cpufreq.c
|
|
+++ b/drivers/cpufreq/tegra186-cpufreq.c
|
|
@@ -73,18 +73,11 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
|
|
{
|
|
struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
|
|
unsigned int cluster = data->cpus[policy->cpu].bpmp_cluster_id;
|
|
- u32 cpu;
|
|
|
|
policy->freq_table = data->clusters[cluster].table;
|
|
policy->cpuinfo.transition_latency = 300 * 1000;
|
|
policy->driver_data = NULL;
|
|
|
|
- /* set same policy for all cpus in a cluster */
|
|
- for (cpu = 0; cpu < ARRAY_SIZE(tegra186_cpus); cpu++) {
|
|
- if (data->cpus[cpu].bpmp_cluster_id == cluster)
|
|
- cpumask_set_cpu(cpu, policy->cpus);
|
|
- }
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/crypto/marvell/cesa/cesa.c b/drivers/crypto/marvell/cesa/cesa.c
|
|
index b61e35b932e590..76f34b81258dc3 100644
|
|
--- a/drivers/crypto/marvell/cesa/cesa.c
|
|
+++ b/drivers/crypto/marvell/cesa/cesa.c
|
|
@@ -94,7 +94,7 @@ static int mv_cesa_std_process(struct mv_cesa_engine *engine, u32 status)
|
|
|
|
static int mv_cesa_int_process(struct mv_cesa_engine *engine, u32 status)
|
|
{
|
|
- if (engine->chain.first && engine->chain.last)
|
|
+ if (engine->chain_hw.first && engine->chain_hw.last)
|
|
return mv_cesa_tdma_process(engine, status);
|
|
|
|
return mv_cesa_std_process(engine, status);
|
|
diff --git a/drivers/crypto/marvell/cesa/cesa.h b/drivers/crypto/marvell/cesa/cesa.h
|
|
index d215a6bed6bc7b..50ca1039fdaa7a 100644
|
|
--- a/drivers/crypto/marvell/cesa/cesa.h
|
|
+++ b/drivers/crypto/marvell/cesa/cesa.h
|
|
@@ -440,8 +440,10 @@ struct mv_cesa_dev {
|
|
* SRAM
|
|
* @queue: fifo of the pending crypto requests
|
|
* @load: engine load counter, useful for load balancing
|
|
- * @chain: list of the current tdma descriptors being processed
|
|
- * by this engine.
|
|
+ * @chain_hw: list of the current tdma descriptors being processed
|
|
+ * by the hardware.
|
|
+ * @chain_sw: list of the current tdma descriptors that will be
|
|
+ * submitted to the hardware.
|
|
* @complete_queue: fifo of the processed requests by the engine
|
|
*
|
|
* Structure storing CESA engine information.
|
|
@@ -463,7 +465,8 @@ struct mv_cesa_engine {
|
|
struct gen_pool *pool;
|
|
struct crypto_queue queue;
|
|
atomic_t load;
|
|
- struct mv_cesa_tdma_chain chain;
|
|
+ struct mv_cesa_tdma_chain chain_hw;
|
|
+ struct mv_cesa_tdma_chain chain_sw;
|
|
struct list_head complete_queue;
|
|
int irq;
|
|
};
|
|
diff --git a/drivers/crypto/marvell/cesa/tdma.c b/drivers/crypto/marvell/cesa/tdma.c
|
|
index 388a06e180d64a..243305354420c1 100644
|
|
--- a/drivers/crypto/marvell/cesa/tdma.c
|
|
+++ b/drivers/crypto/marvell/cesa/tdma.c
|
|
@@ -38,6 +38,15 @@ void mv_cesa_dma_step(struct mv_cesa_req *dreq)
|
|
{
|
|
struct mv_cesa_engine *engine = dreq->engine;
|
|
|
|
+ spin_lock_bh(&engine->lock);
|
|
+ if (engine->chain_sw.first == dreq->chain.first) {
|
|
+ engine->chain_sw.first = NULL;
|
|
+ engine->chain_sw.last = NULL;
|
|
+ }
|
|
+ engine->chain_hw.first = dreq->chain.first;
|
|
+ engine->chain_hw.last = dreq->chain.last;
|
|
+ spin_unlock_bh(&engine->lock);
|
|
+
|
|
writel_relaxed(0, engine->regs + CESA_SA_CFG);
|
|
|
|
mv_cesa_set_int_mask(engine, CESA_SA_INT_ACC0_IDMA_DONE);
|
|
@@ -96,25 +105,27 @@ void mv_cesa_dma_prepare(struct mv_cesa_req *dreq,
|
|
void mv_cesa_tdma_chain(struct mv_cesa_engine *engine,
|
|
struct mv_cesa_req *dreq)
|
|
{
|
|
- if (engine->chain.first == NULL && engine->chain.last == NULL) {
|
|
- engine->chain.first = dreq->chain.first;
|
|
- engine->chain.last = dreq->chain.last;
|
|
- } else {
|
|
- struct mv_cesa_tdma_desc *last;
|
|
+ struct mv_cesa_tdma_desc *last = engine->chain_sw.last;
|
|
|
|
- last = engine->chain.last;
|
|
+ /*
|
|
+ * Break the DMA chain if the request being queued needs the IV
|
|
+ * regs to be set before lauching the request.
|
|
+ */
|
|
+ if (!last || dreq->chain.first->flags & CESA_TDMA_SET_STATE)
|
|
+ engine->chain_sw.first = dreq->chain.first;
|
|
+ else {
|
|
last->next = dreq->chain.first;
|
|
- engine->chain.last = dreq->chain.last;
|
|
-
|
|
- /*
|
|
- * Break the DMA chain if the CESA_TDMA_BREAK_CHAIN is set on
|
|
- * the last element of the current chain, or if the request
|
|
- * being queued needs the IV regs to be set before lauching
|
|
- * the request.
|
|
- */
|
|
- if (!(last->flags & CESA_TDMA_BREAK_CHAIN) &&
|
|
- !(dreq->chain.first->flags & CESA_TDMA_SET_STATE))
|
|
- last->next_dma = cpu_to_le32(dreq->chain.first->cur_dma);
|
|
+ last->next_dma = cpu_to_le32(dreq->chain.first->cur_dma);
|
|
+ }
|
|
+ last = dreq->chain.last;
|
|
+ engine->chain_sw.last = last;
|
|
+ /*
|
|
+ * Break the DMA chain if the CESA_TDMA_BREAK_CHAIN is set on
|
|
+ * the last element of the current chain.
|
|
+ */
|
|
+ if (last->flags & CESA_TDMA_BREAK_CHAIN) {
|
|
+ engine->chain_sw.first = NULL;
|
|
+ engine->chain_sw.last = NULL;
|
|
}
|
|
}
|
|
|
|
@@ -127,7 +138,7 @@ int mv_cesa_tdma_process(struct mv_cesa_engine *engine, u32 status)
|
|
|
|
tdma_cur = readl(engine->regs + CESA_TDMA_CUR);
|
|
|
|
- for (tdma = engine->chain.first; tdma; tdma = next) {
|
|
+ for (tdma = engine->chain_hw.first; tdma; tdma = next) {
|
|
spin_lock_bh(&engine->lock);
|
|
next = tdma->next;
|
|
spin_unlock_bh(&engine->lock);
|
|
@@ -149,12 +160,12 @@ int mv_cesa_tdma_process(struct mv_cesa_engine *engine, u32 status)
|
|
&backlog);
|
|
|
|
/* Re-chaining to the next request */
|
|
- engine->chain.first = tdma->next;
|
|
+ engine->chain_hw.first = tdma->next;
|
|
tdma->next = NULL;
|
|
|
|
/* If this is the last request, clear the chain */
|
|
- if (engine->chain.first == NULL)
|
|
- engine->chain.last = NULL;
|
|
+ if (engine->chain_hw.first == NULL)
|
|
+ engine->chain_hw.last = NULL;
|
|
spin_unlock_bh(&engine->lock);
|
|
|
|
ctx = crypto_tfm_ctx(req->tfm);
|
|
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
|
|
index 373282beeb6068..980975ffc55d3c 100644
|
|
--- a/drivers/dma-buf/udmabuf.c
|
|
+++ b/drivers/dma-buf/udmabuf.c
|
|
@@ -161,8 +161,7 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
|
|
ubuf->sg = NULL;
|
|
}
|
|
} else {
|
|
- dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents,
|
|
- direction);
|
|
+ dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
|
|
}
|
|
|
|
return ret;
|
|
@@ -177,7 +176,7 @@ static int end_cpu_udmabuf(struct dma_buf *buf,
|
|
if (!ubuf->sg)
|
|
return -EINVAL;
|
|
|
|
- dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction);
|
|
+ dma_sync_sgtable_for_device(dev, ubuf->sg, direction);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
|
|
index e04fd1a7e9aaea..54ec894150939a 100644
|
|
--- a/drivers/edac/altera_edac.c
|
|
+++ b/drivers/edac/altera_edac.c
|
|
@@ -1756,9 +1756,9 @@ altr_edac_a10_device_trig(struct file *file, const char __user *user_buf,
|
|
|
|
local_irq_save(flags);
|
|
if (trig_type == ALTR_UE_TRIGGER_CHAR)
|
|
- writel(priv->ue_set_mask, set_addr);
|
|
+ writew(priv->ue_set_mask, set_addr);
|
|
else
|
|
- writel(priv->ce_set_mask, set_addr);
|
|
+ writew(priv->ce_set_mask, set_addr);
|
|
|
|
/* Ensure the interrupt test bits are set */
|
|
wmb();
|
|
@@ -1788,7 +1788,7 @@ altr_edac_a10_device_trig2(struct file *file, const char __user *user_buf,
|
|
|
|
local_irq_save(flags);
|
|
if (trig_type == ALTR_UE_TRIGGER_CHAR) {
|
|
- writel(priv->ue_set_mask, set_addr);
|
|
+ writew(priv->ue_set_mask, set_addr);
|
|
} else {
|
|
/* Setup read/write of 4 bytes */
|
|
writel(ECC_WORD_WRITE, drvdata->base + ECC_BLK_DBYTECTRL_OFST);
|
|
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
|
|
index 9cd86390a16747..10119cf27ffde5 100644
|
|
--- a/drivers/edac/amd64_edac.c
|
|
+++ b/drivers/edac/amd64_edac.c
|
|
@@ -4130,6 +4130,7 @@ static int per_family_init(struct amd64_pvt *pvt)
|
|
break;
|
|
case 0x70 ... 0x7f:
|
|
pvt->ctl_name = "F19h_M70h";
|
|
+ pvt->max_mcs = 4;
|
|
pvt->flags.zn_regs_v2 = 1;
|
|
break;
|
|
case 0xa0 ... 0xaf:
|
|
diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c
|
|
index 10ea71273c8915..9875e34bde72a4 100644
|
|
--- a/drivers/gpio/gpio-mlxbf3.c
|
|
+++ b/drivers/gpio/gpio-mlxbf3.c
|
|
@@ -190,7 +190,9 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev)
|
|
struct mlxbf3_gpio_context *gs;
|
|
struct gpio_irq_chip *girq;
|
|
struct gpio_chip *gc;
|
|
+ char *colon_ptr;
|
|
int ret, irq;
|
|
+ long num;
|
|
|
|
gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL);
|
|
if (!gs)
|
|
@@ -227,25 +229,39 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev)
|
|
gc->owner = THIS_MODULE;
|
|
gc->add_pin_ranges = mlxbf3_gpio_add_pin_ranges;
|
|
|
|
- irq = platform_get_irq(pdev, 0);
|
|
- if (irq >= 0) {
|
|
- girq = &gs->gc.irq;
|
|
- gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip);
|
|
- girq->default_type = IRQ_TYPE_NONE;
|
|
- /* This will let us handle the parent IRQ in the driver */
|
|
- girq->num_parents = 0;
|
|
- girq->parents = NULL;
|
|
- girq->parent_handler = NULL;
|
|
- girq->handler = handle_bad_irq;
|
|
-
|
|
- /*
|
|
- * Directly request the irq here instead of passing
|
|
- * a flow-handler because the irq is shared.
|
|
- */
|
|
- ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler,
|
|
- IRQF_SHARED, dev_name(dev), gs);
|
|
- if (ret)
|
|
- return dev_err_probe(dev, ret, "failed to request IRQ");
|
|
+ colon_ptr = strchr(dev_name(dev), ':');
|
|
+ if (!colon_ptr) {
|
|
+ dev_err(dev, "invalid device name format\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ ret = kstrtol(++colon_ptr, 16, &num);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "invalid device instance\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (!num) {
|
|
+ irq = platform_get_irq(pdev, 0);
|
|
+ if (irq >= 0) {
|
|
+ girq = &gs->gc.irq;
|
|
+ gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip);
|
|
+ girq->default_type = IRQ_TYPE_NONE;
|
|
+ /* This will let us handle the parent IRQ in the driver */
|
|
+ girq->num_parents = 0;
|
|
+ girq->parents = NULL;
|
|
+ girq->parent_handler = NULL;
|
|
+ girq->handler = handle_bad_irq;
|
|
+
|
|
+ /*
|
|
+ * Directly request the irq here instead of passing
|
|
+ * a flow-handler because the irq is shared.
|
|
+ */
|
|
+ ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler,
|
|
+ IRQF_SHARED, dev_name(dev), gs);
|
|
+ if (ret)
|
|
+ return dev_err_probe(dev, ret, "failed to request IRQ");
|
|
+ }
|
|
}
|
|
|
|
platform_set_drvdata(pdev, gs);
|
|
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
|
|
index a0a2a0f75bba46..c1e83b2926ae4d 100644
|
|
--- a/drivers/gpio/gpiolib-of.c
|
|
+++ b/drivers/gpio/gpiolib-of.c
|
|
@@ -203,6 +203,15 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
|
|
*/
|
|
{ "lantiq,pci-xway", "gpio-reset", false },
|
|
#endif
|
|
+#if IS_ENABLED(CONFIG_REGULATOR_S5M8767)
|
|
+ /*
|
|
+ * According to S5M8767, the DVS and DS pin are
|
|
+ * active-high signals. However, exynos5250-spring.dts use
|
|
+ * active-low setting.
|
|
+ */
|
|
+ { "samsung,s5m8767-pmic", "s5m8767,pmic-buck-dvs-gpios", true },
|
|
+ { "samsung,s5m8767-pmic", "s5m8767,pmic-buck-ds-gpios", true },
|
|
+#endif
|
|
#if IS_ENABLED(CONFIG_TOUCHSCREEN_TSC2005)
|
|
/*
|
|
* DTS for Nokia N900 incorrectly specified "active high"
|
|
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
|
|
index 7b1076b5e748c5..33ab82c334a881 100644
|
|
--- a/drivers/gpu/drm/i915/i915_pmu.c
|
|
+++ b/drivers/gpu/drm/i915/i915_pmu.c
|
|
@@ -105,7 +105,7 @@ static u32 config_mask(const u64 config)
|
|
{
|
|
unsigned int bit = config_bit(config);
|
|
|
|
- if (__builtin_constant_p(config))
|
|
+ if (__builtin_constant_p(bit))
|
|
BUILD_BUG_ON(bit >
|
|
BITS_PER_TYPE(typeof_member(struct i915_pmu,
|
|
enable)) - 1);
|
|
@@ -114,7 +114,7 @@ static u32 config_mask(const u64 config)
|
|
BITS_PER_TYPE(typeof_member(struct i915_pmu,
|
|
enable)) - 1);
|
|
|
|
- return BIT(config_bit(config));
|
|
+ return BIT(bit);
|
|
}
|
|
|
|
static bool is_engine_event(struct perf_event *event)
|
|
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
|
|
index 20c8b9af7a2199..2cda9bbf68f965 100644
|
|
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
|
|
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
|
|
@@ -93,17 +93,21 @@ static void drm_mode_to_intf_timing_params(
|
|
timing->vsync_polarity = 0;
|
|
}
|
|
|
|
- /* for DP/EDP, Shift timings to align it to bottom right */
|
|
- if (phys_enc->hw_intf->cap->type == INTF_DP) {
|
|
+ timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
|
|
+ timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent);
|
|
+
|
|
+ /*
|
|
+ * For DP/EDP, Shift timings to align it to bottom right.
|
|
+ * wide_bus_en is set for everything excluding SDM845 &
|
|
+ * porch changes cause DisplayPort failure and HDMI tearing.
|
|
+ */
|
|
+ if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) {
|
|
timing->h_back_porch += timing->h_front_porch;
|
|
timing->h_front_porch = 0;
|
|
timing->v_back_porch += timing->v_front_porch;
|
|
timing->v_front_porch = 0;
|
|
}
|
|
|
|
- timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
|
|
- timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent);
|
|
-
|
|
/*
|
|
* for DP, divide the horizonal parameters by 2 when
|
|
* widebus is enabled
|
|
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
|
|
index 27b592c776a300..1c111969342a77 100644
|
|
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
|
|
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
|
|
@@ -716,6 +716,13 @@ static int dsi_pll_10nm_init(struct msm_dsi_phy *phy)
|
|
/* TODO: Remove this when we have proper display handover support */
|
|
msm_dsi_phy_pll_save_state(phy);
|
|
|
|
+ /*
|
|
+ * Store also proper vco_current_rate, because its value will be used in
|
|
+ * dsi_10nm_pll_restore_state().
|
|
+ */
|
|
+ if (!dsi_pll_10nm_vco_recalc_rate(&pll_10nm->clk_hw, VCO_REF_CLK_RATE))
|
|
+ pll_10nm->vco_current_rate = pll_10nm->phy->cfg->min_pll_rate;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
|
|
index 91b5ecc5753808..4e6f305c9e504d 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
|
|
@@ -42,7 +42,7 @@
|
|
#include "nouveau_acpi.h"
|
|
|
|
static struct ida bl_ida;
|
|
-#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
|
|
+#define BL_NAME_SIZE 24 // 12 for name + 11 for digits + 1 for '\0'
|
|
|
|
static bool
|
|
nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
|
|
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
|
|
index f001ae880e1dbe..27306c17b0c4e4 100644
|
|
--- a/drivers/hv/connection.c
|
|
+++ b/drivers/hv/connection.c
|
|
@@ -206,11 +206,20 @@ int vmbus_connect(void)
|
|
INIT_LIST_HEAD(&vmbus_connection.chn_list);
|
|
mutex_init(&vmbus_connection.channel_mutex);
|
|
|
|
+ /*
|
|
+ * The following Hyper-V interrupt and monitor pages can be used by
|
|
+ * UIO for mapping to user-space, so they should always be allocated on
|
|
+ * system page boundaries. The system page size must be >= the Hyper-V
|
|
+ * page size.
|
|
+ */
|
|
+ BUILD_BUG_ON(PAGE_SIZE < HV_HYP_PAGE_SIZE);
|
|
+
|
|
/*
|
|
* Setup the vmbus event connection for channel interrupt
|
|
* abstraction stuff
|
|
*/
|
|
- vmbus_connection.int_page = hv_alloc_hyperv_zeroed_page();
|
|
+ vmbus_connection.int_page =
|
|
+ (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
|
|
if (vmbus_connection.int_page == NULL) {
|
|
ret = -ENOMEM;
|
|
goto cleanup;
|
|
@@ -225,8 +234,8 @@ int vmbus_connect(void)
|
|
* Setup the monitor notification facility. The 1st page for
|
|
* parent->child and the 2nd page for child->parent
|
|
*/
|
|
- vmbus_connection.monitor_pages[0] = hv_alloc_hyperv_page();
|
|
- vmbus_connection.monitor_pages[1] = hv_alloc_hyperv_page();
|
|
+ vmbus_connection.monitor_pages[0] = (void *)__get_free_page(GFP_KERNEL);
|
|
+ vmbus_connection.monitor_pages[1] = (void *)__get_free_page(GFP_KERNEL);
|
|
if ((vmbus_connection.monitor_pages[0] == NULL) ||
|
|
(vmbus_connection.monitor_pages[1] == NULL)) {
|
|
ret = -ENOMEM;
|
|
@@ -342,21 +351,23 @@ void vmbus_disconnect(void)
|
|
destroy_workqueue(vmbus_connection.work_queue);
|
|
|
|
if (vmbus_connection.int_page) {
|
|
- hv_free_hyperv_page(vmbus_connection.int_page);
|
|
+ free_page((unsigned long)vmbus_connection.int_page);
|
|
vmbus_connection.int_page = NULL;
|
|
}
|
|
|
|
if (vmbus_connection.monitor_pages[0]) {
|
|
if (!set_memory_encrypted(
|
|
(unsigned long)vmbus_connection.monitor_pages[0], 1))
|
|
- hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
|
|
+ free_page((unsigned long)
|
|
+ vmbus_connection.monitor_pages[0]);
|
|
vmbus_connection.monitor_pages[0] = NULL;
|
|
}
|
|
|
|
if (vmbus_connection.monitor_pages[1]) {
|
|
if (!set_memory_encrypted(
|
|
(unsigned long)vmbus_connection.monitor_pages[1], 1))
|
|
- hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
|
|
+ free_page((unsigned long)
|
|
+ vmbus_connection.monitor_pages[1]);
|
|
vmbus_connection.monitor_pages[1] = NULL;
|
|
}
|
|
}
|
|
diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c
|
|
index b74a2665e73321..27e5dd94b04f2c 100644
|
|
--- a/drivers/hwmon/ftsteutates.c
|
|
+++ b/drivers/hwmon/ftsteutates.c
|
|
@@ -423,13 +423,16 @@ static int fts_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|
break;
|
|
case hwmon_pwm:
|
|
switch (attr) {
|
|
- case hwmon_pwm_auto_channels_temp:
|
|
- if (data->fan_source[channel] == FTS_FAN_SOURCE_INVALID)
|
|
+ case hwmon_pwm_auto_channels_temp: {
|
|
+ u8 fan_source = data->fan_source[channel];
|
|
+
|
|
+ if (fan_source == FTS_FAN_SOURCE_INVALID || fan_source >= BITS_PER_LONG)
|
|
*val = 0;
|
|
else
|
|
- *val = BIT(data->fan_source[channel]);
|
|
+ *val = BIT(fan_source);
|
|
|
|
return 0;
|
|
+ }
|
|
default:
|
|
break;
|
|
}
|
|
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
|
|
index dd690f700d4990..483f79b394298f 100644
|
|
--- a/drivers/hwmon/occ/common.c
|
|
+++ b/drivers/hwmon/occ/common.c
|
|
@@ -459,12 +459,10 @@ static ssize_t occ_show_power_1(struct device *dev,
|
|
return sysfs_emit(buf, "%llu\n", val);
|
|
}
|
|
|
|
-static u64 occ_get_powr_avg(u64 *accum, u32 *samples)
|
|
+static u64 occ_get_powr_avg(u64 accum, u32 samples)
|
|
{
|
|
- u64 divisor = get_unaligned_be32(samples);
|
|
-
|
|
- return (divisor == 0) ? 0 :
|
|
- div64_u64(get_unaligned_be64(accum) * 1000000ULL, divisor);
|
|
+ return (samples == 0) ? 0 :
|
|
+ mul_u64_u32_div(accum, 1000000UL, samples);
|
|
}
|
|
|
|
static ssize_t occ_show_power_2(struct device *dev,
|
|
@@ -489,8 +487,8 @@ static ssize_t occ_show_power_2(struct device *dev,
|
|
get_unaligned_be32(&power->sensor_id),
|
|
power->function_id, power->apss_channel);
|
|
case 1:
|
|
- val = occ_get_powr_avg(&power->accumulator,
|
|
- &power->update_tag);
|
|
+ val = occ_get_powr_avg(get_unaligned_be64(&power->accumulator),
|
|
+ get_unaligned_be32(&power->update_tag));
|
|
break;
|
|
case 2:
|
|
val = (u64)get_unaligned_be32(&power->update_tag) *
|
|
@@ -527,8 +525,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
|
|
return sysfs_emit(buf, "%u_system\n",
|
|
get_unaligned_be32(&power->sensor_id));
|
|
case 1:
|
|
- val = occ_get_powr_avg(&power->system.accumulator,
|
|
- &power->system.update_tag);
|
|
+ val = occ_get_powr_avg(get_unaligned_be64(&power->system.accumulator),
|
|
+ get_unaligned_be32(&power->system.update_tag));
|
|
break;
|
|
case 2:
|
|
val = (u64)get_unaligned_be32(&power->system.update_tag) *
|
|
@@ -541,8 +539,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
|
|
return sysfs_emit(buf, "%u_proc\n",
|
|
get_unaligned_be32(&power->sensor_id));
|
|
case 5:
|
|
- val = occ_get_powr_avg(&power->proc.accumulator,
|
|
- &power->proc.update_tag);
|
|
+ val = occ_get_powr_avg(get_unaligned_be64(&power->proc.accumulator),
|
|
+ get_unaligned_be32(&power->proc.update_tag));
|
|
break;
|
|
case 6:
|
|
val = (u64)get_unaligned_be32(&power->proc.update_tag) *
|
|
@@ -555,8 +553,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
|
|
return sysfs_emit(buf, "%u_vdd\n",
|
|
get_unaligned_be32(&power->sensor_id));
|
|
case 9:
|
|
- val = occ_get_powr_avg(&power->vdd.accumulator,
|
|
- &power->vdd.update_tag);
|
|
+ val = occ_get_powr_avg(get_unaligned_be64(&power->vdd.accumulator),
|
|
+ get_unaligned_be32(&power->vdd.update_tag));
|
|
break;
|
|
case 10:
|
|
val = (u64)get_unaligned_be32(&power->vdd.update_tag) *
|
|
@@ -569,8 +567,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
|
|
return sysfs_emit(buf, "%u_vdn\n",
|
|
get_unaligned_be32(&power->sensor_id));
|
|
case 13:
|
|
- val = occ_get_powr_avg(&power->vdn.accumulator,
|
|
- &power->vdn.update_tag);
|
|
+ val = occ_get_powr_avg(get_unaligned_be64(&power->vdn.accumulator),
|
|
+ get_unaligned_be32(&power->vdn.update_tag));
|
|
break;
|
|
case 14:
|
|
val = (u64)get_unaligned_be32(&power->vdn.update_tag) *
|
|
@@ -747,29 +745,30 @@ static ssize_t occ_show_extended(struct device *dev,
|
|
}
|
|
|
|
/*
|
|
- * Some helper macros to make it easier to define an occ_attribute. Since these
|
|
- * are dynamically allocated, we shouldn't use the existing kernel macros which
|
|
+ * A helper to make it easier to define an occ_attribute. Since these
|
|
+ * are dynamically allocated, we cannot use the existing kernel macros which
|
|
* stringify the name argument.
|
|
*/
|
|
-#define ATTR_OCC(_name, _mode, _show, _store) { \
|
|
- .attr = { \
|
|
- .name = _name, \
|
|
- .mode = VERIFY_OCTAL_PERMISSIONS(_mode), \
|
|
- }, \
|
|
- .show = _show, \
|
|
- .store = _store, \
|
|
-}
|
|
-
|
|
-#define SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index) { \
|
|
- .dev_attr = ATTR_OCC(_name, _mode, _show, _store), \
|
|
- .index = _index, \
|
|
- .nr = _nr, \
|
|
+static void occ_init_attribute(struct occ_attribute *attr, int mode,
|
|
+ ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf),
|
|
+ ssize_t (*store)(struct device *dev, struct device_attribute *attr,
|
|
+ const char *buf, size_t count),
|
|
+ int nr, int index, const char *fmt, ...)
|
|
+{
|
|
+ va_list args;
|
|
+
|
|
+ va_start(args, fmt);
|
|
+ vsnprintf(attr->name, sizeof(attr->name), fmt, args);
|
|
+ va_end(args);
|
|
+
|
|
+ attr->sensor.dev_attr.attr.name = attr->name;
|
|
+ attr->sensor.dev_attr.attr.mode = mode;
|
|
+ attr->sensor.dev_attr.show = show;
|
|
+ attr->sensor.dev_attr.store = store;
|
|
+ attr->sensor.index = index;
|
|
+ attr->sensor.nr = nr;
|
|
}
|
|
|
|
-#define OCC_INIT_ATTR(_name, _mode, _show, _store, _nr, _index) \
|
|
- ((struct sensor_device_attribute_2) \
|
|
- SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index))
|
|
-
|
|
/*
|
|
* Allocate and instatiate sensor_device_attribute_2s. It's most efficient to
|
|
* use our own instead of the built-in hwmon attribute types.
|
|
@@ -855,14 +854,15 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
|
sensors->extended.num_sensors = 0;
|
|
}
|
|
|
|
- occ->attrs = devm_kzalloc(dev, sizeof(*occ->attrs) * num_attrs,
|
|
+ occ->attrs = devm_kcalloc(dev, num_attrs, sizeof(*occ->attrs),
|
|
GFP_KERNEL);
|
|
if (!occ->attrs)
|
|
return -ENOMEM;
|
|
|
|
/* null-terminated list */
|
|
- occ->group.attrs = devm_kzalloc(dev, sizeof(*occ->group.attrs) *
|
|
- num_attrs + 1, GFP_KERNEL);
|
|
+ occ->group.attrs = devm_kcalloc(dev, num_attrs + 1,
|
|
+ sizeof(*occ->group.attrs),
|
|
+ GFP_KERNEL);
|
|
if (!occ->group.attrs)
|
|
return -ENOMEM;
|
|
|
|
@@ -872,43 +872,33 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
|
s = i + 1;
|
|
temp = ((struct temp_sensor_2 *)sensors->temp.data) + i;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "temp%d_label", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL,
|
|
- 0, i);
|
|
+ occ_init_attribute(attr, 0444, show_temp, NULL,
|
|
+ 0, i, "temp%d_label", s);
|
|
attr++;
|
|
|
|
if (sensors->temp.version == 2 &&
|
|
temp->fru_type == OCC_FRU_TYPE_VRM) {
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "temp%d_alarm", s);
|
|
+ occ_init_attribute(attr, 0444, show_temp, NULL,
|
|
+ 1, i, "temp%d_alarm", s);
|
|
} else {
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "temp%d_input", s);
|
|
+ occ_init_attribute(attr, 0444, show_temp, NULL,
|
|
+ 1, i, "temp%d_input", s);
|
|
}
|
|
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL,
|
|
- 1, i);
|
|
attr++;
|
|
|
|
if (sensors->temp.version > 1) {
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "temp%d_fru_type", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_temp, NULL, 2, i);
|
|
+ occ_init_attribute(attr, 0444, show_temp, NULL,
|
|
+ 2, i, "temp%d_fru_type", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "temp%d_fault", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_temp, NULL, 3, i);
|
|
+ occ_init_attribute(attr, 0444, show_temp, NULL,
|
|
+ 3, i, "temp%d_fault", s);
|
|
attr++;
|
|
|
|
if (sensors->temp.version == 0x10) {
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "temp%d_max", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_temp, NULL,
|
|
- 4, i);
|
|
+ occ_init_attribute(attr, 0444, show_temp, NULL,
|
|
+ 4, i, "temp%d_max", s);
|
|
attr++;
|
|
}
|
|
}
|
|
@@ -917,14 +907,12 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
|
for (i = 0; i < sensors->freq.num_sensors; ++i) {
|
|
s = i + 1;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "freq%d_label", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL,
|
|
- 0, i);
|
|
+ occ_init_attribute(attr, 0444, show_freq, NULL,
|
|
+ 0, i, "freq%d_label", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "freq%d_input", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL,
|
|
- 1, i);
|
|
+ occ_init_attribute(attr, 0444, show_freq, NULL,
|
|
+ 1, i, "freq%d_input", s);
|
|
attr++;
|
|
}
|
|
|
|
@@ -940,32 +928,24 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
|
s = (i * 4) + 1;
|
|
|
|
for (j = 0; j < 4; ++j) {
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_label", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL,
|
|
- nr++, i);
|
|
+ occ_init_attribute(attr, 0444, show_power,
|
|
+ NULL, nr++, i,
|
|
+ "power%d_label", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_average", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL,
|
|
- nr++, i);
|
|
+ occ_init_attribute(attr, 0444, show_power,
|
|
+ NULL, nr++, i,
|
|
+ "power%d_average", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_average_interval", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL,
|
|
- nr++, i);
|
|
+ occ_init_attribute(attr, 0444, show_power,
|
|
+ NULL, nr++, i,
|
|
+ "power%d_average_interval", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_input", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL,
|
|
- nr++, i);
|
|
+ occ_init_attribute(attr, 0444, show_power,
|
|
+ NULL, nr++, i,
|
|
+ "power%d_input", s);
|
|
attr++;
|
|
|
|
s++;
|
|
@@ -977,28 +957,20 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
|
for (i = 0; i < sensors->power.num_sensors; ++i) {
|
|
s = i + 1;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_label", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL, 0, i);
|
|
+ occ_init_attribute(attr, 0444, show_power, NULL,
|
|
+ 0, i, "power%d_label", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_average", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL, 1, i);
|
|
+ occ_init_attribute(attr, 0444, show_power, NULL,
|
|
+ 1, i, "power%d_average", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_average_interval", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL, 2, i);
|
|
+ occ_init_attribute(attr, 0444, show_power, NULL,
|
|
+ 2, i, "power%d_average_interval", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_input", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_power, NULL, 3, i);
|
|
+ occ_init_attribute(attr, 0444, show_power, NULL,
|
|
+ 3, i, "power%d_input", s);
|
|
attr++;
|
|
}
|
|
|
|
@@ -1006,56 +978,43 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
|
}
|
|
|
|
if (sensors->caps.num_sensors >= 1) {
|
|
- snprintf(attr->name, sizeof(attr->name), "power%d_label", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
|
|
- 0, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 0, 0, "power%d_label", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "power%d_cap", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
|
|
- 1, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 1, 0, "power%d_cap", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "power%d_input", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
|
|
- 2, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 2, 0, "power%d_input", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_cap_not_redundant", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
|
|
- 3, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 3, 0, "power%d_cap_not_redundant", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "power%d_cap_max", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
|
|
- 4, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 4, 0, "power%d_cap_max", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "power%d_cap_min", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
|
|
- 5, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 5, 0, "power%d_cap_min", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "power%d_cap_user",
|
|
- s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0644, show_caps,
|
|
- occ_store_caps_user, 6, 0);
|
|
+ occ_init_attribute(attr, 0644, show_caps, occ_store_caps_user,
|
|
+ 6, 0, "power%d_cap_user", s);
|
|
attr++;
|
|
|
|
if (sensors->caps.version > 1) {
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_cap_user_source", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_caps, NULL, 7, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 7, 0, "power%d_cap_user_source", s);
|
|
attr++;
|
|
|
|
if (sensors->caps.version > 2) {
|
|
- snprintf(attr->name, sizeof(attr->name),
|
|
- "power%d_cap_min_soft", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- show_caps, NULL,
|
|
- 8, 0);
|
|
+ occ_init_attribute(attr, 0444, show_caps, NULL,
|
|
+ 8, 0,
|
|
+ "power%d_cap_min_soft", s);
|
|
attr++;
|
|
}
|
|
}
|
|
@@ -1064,19 +1023,16 @@ static int occ_setup_sensor_attrs(struct occ *occ)
|
|
for (i = 0; i < sensors->extended.num_sensors; ++i) {
|
|
s = i + 1;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "extn%d_label", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- occ_show_extended, NULL, 0, i);
|
|
+ occ_init_attribute(attr, 0444, occ_show_extended, NULL,
|
|
+ 0, i, "extn%d_label", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "extn%d_flags", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- occ_show_extended, NULL, 1, i);
|
|
+ occ_init_attribute(attr, 0444, occ_show_extended, NULL,
|
|
+ 1, i, "extn%d_flags", s);
|
|
attr++;
|
|
|
|
- snprintf(attr->name, sizeof(attr->name), "extn%d_input", s);
|
|
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
|
|
- occ_show_extended, NULL, 2, i);
|
|
+ occ_init_attribute(attr, 0444, occ_show_extended, NULL,
|
|
+ 2, i, "extn%d_input", s);
|
|
attr++;
|
|
}
|
|
|
|
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
|
|
index 345b532a2b455d..ea4c4955fe2646 100644
|
|
--- a/drivers/i2c/busses/i2c-designware-slave.c
|
|
+++ b/drivers/i2c/busses/i2c-designware-slave.c
|
|
@@ -91,7 +91,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
|
|
i2c_dw_disable(dev);
|
|
synchronize_irq(dev->irq);
|
|
dev->slave = NULL;
|
|
- pm_runtime_put(dev->dev);
|
|
+ pm_runtime_put_sync_suspend(dev->dev);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
|
|
index 91f508d50e7ab4..5b3987460976e3 100644
|
|
--- a/drivers/i2c/busses/i2c-npcm7xx.c
|
|
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
|
|
@@ -1971,10 +1971,14 @@ static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
|
|
|
|
/* Check HW is OK: SDA and SCL should be high at this point. */
|
|
if ((npcm_i2c_get_SDA(&bus->adap) == 0) || (npcm_i2c_get_SCL(&bus->adap) == 0)) {
|
|
- dev_err(bus->dev, "I2C%d init fail: lines are low\n", bus->num);
|
|
- dev_err(bus->dev, "SDA=%d SCL=%d\n", npcm_i2c_get_SDA(&bus->adap),
|
|
- npcm_i2c_get_SCL(&bus->adap));
|
|
- return -ENXIO;
|
|
+ dev_warn(bus->dev, " I2C%d SDA=%d SCL=%d, attempting to recover\n", bus->num,
|
|
+ npcm_i2c_get_SDA(&bus->adap), npcm_i2c_get_SCL(&bus->adap));
|
|
+ if (npcm_i2c_recovery_tgclk(&bus->adap)) {
|
|
+ dev_err(bus->dev, "I2C%d init fail: SDA=%d SCL=%d\n",
|
|
+ bus->num, npcm_i2c_get_SDA(&bus->adap),
|
|
+ npcm_i2c_get_SCL(&bus->adap));
|
|
+ return -ENXIO;
|
|
+ }
|
|
}
|
|
|
|
npcm_i2c_int_enable(bus, true);
|
|
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
|
|
index 91be04b534fe61..08a81daedc115e 100644
|
|
--- a/drivers/i2c/busses/i2c-tegra.c
|
|
+++ b/drivers/i2c/busses/i2c-tegra.c
|
|
@@ -1397,6 +1397,11 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
|
|
ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], MSG_END_CONTINUE);
|
|
if (ret)
|
|
break;
|
|
+
|
|
+ /* Validate message length before proceeding */
|
|
+ if (msgs[i].buf[0] == 0 || msgs[i].buf[0] > I2C_SMBUS_BLOCK_MAX)
|
|
+ break;
|
|
+
|
|
/* Set the msg length from first byte */
|
|
msgs[i].len += msgs[i].buf[0];
|
|
dev_dbg(i2c_dev->dev, "reading %d bytes\n", msgs[i].len);
|
|
diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c
|
|
index be8a15cb945fdf..17820b2c3a1dec 100644
|
|
--- a/drivers/iio/accel/fxls8962af-core.c
|
|
+++ b/drivers/iio/accel/fxls8962af-core.c
|
|
@@ -20,6 +20,7 @@
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/regmap.h>
|
|
+#include <linux/units.h>
|
|
|
|
#include <linux/iio/buffer.h>
|
|
#include <linux/iio/events.h>
|
|
@@ -434,8 +435,16 @@ static int fxls8962af_read_raw(struct iio_dev *indio_dev,
|
|
*val = FXLS8962AF_TEMP_CENTER_VAL;
|
|
return IIO_VAL_INT;
|
|
case IIO_CHAN_INFO_SCALE:
|
|
- *val = 0;
|
|
- return fxls8962af_read_full_scale(data, val2);
|
|
+ switch (chan->type) {
|
|
+ case IIO_TEMP:
|
|
+ *val = MILLIDEGREE_PER_DEGREE;
|
|
+ return IIO_VAL_INT;
|
|
+ case IIO_ACCEL:
|
|
+ *val = 0;
|
|
+ return fxls8962af_read_full_scale(data, val2);
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
|
return fxls8962af_read_samp_freq(data, val, val2);
|
|
default:
|
|
@@ -734,9 +743,11 @@ static const struct iio_event_spec fxls8962af_event[] = {
|
|
.type = IIO_TEMP, \
|
|
.address = FXLS8962AF_TEMP_OUT, \
|
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
|
+ BIT(IIO_CHAN_INFO_SCALE) | \
|
|
BIT(IIO_CHAN_INFO_OFFSET),\
|
|
.scan_index = -1, \
|
|
.scan_type = { \
|
|
+ .sign = 's', \
|
|
.realbits = 8, \
|
|
.storagebits = 8, \
|
|
}, \
|
|
diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
|
|
index 67c96572cecc40..df48464a115d03 100644
|
|
--- a/drivers/iio/adc/ad7606_spi.c
|
|
+++ b/drivers/iio/adc/ad7606_spi.c
|
|
@@ -151,7 +151,7 @@ static int ad7606_spi_reg_write(struct ad7606_state *st,
|
|
struct spi_device *spi = to_spi_device(st->dev);
|
|
|
|
st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) |
|
|
- (val & 0x1FF));
|
|
+ (val & 0xFF));
|
|
|
|
return spi_write(spi, &st->d16[0], sizeof(st->d16[0]));
|
|
}
|
|
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
|
|
index 213cce1c31110e..91f0f381082bda 100644
|
|
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
|
|
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
|
|
@@ -67,16 +67,18 @@ int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev,
|
|
return IIO_VAL_INT;
|
|
/*
|
|
* T°C = (temp / 132.48) + 25
|
|
- * Tm°C = 1000 * ((temp * 100 / 13248) + 25)
|
|
+ * Tm°C = 1000 * ((temp / 132.48) + 25)
|
|
+ * Tm°C = 7.548309 * temp + 25000
|
|
+ * Tm°C = (temp + 3312) * 7.548309
|
|
* scale: 100000 / 13248 ~= 7.548309
|
|
- * offset: 25000
|
|
+ * offset: 3312
|
|
*/
|
|
case IIO_CHAN_INFO_SCALE:
|
|
*val = 7;
|
|
*val2 = 548309;
|
|
return IIO_VAL_INT_PLUS_MICRO;
|
|
case IIO_CHAN_INFO_OFFSET:
|
|
- *val = 25000;
|
|
+ *val = 3312;
|
|
return IIO_VAL_INT;
|
|
default:
|
|
return -EINVAL;
|
|
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
|
|
index 3e4941754b48d0..ce41f235af253c 100644
|
|
--- a/drivers/infiniband/core/iwcm.c
|
|
+++ b/drivers/infiniband/core/iwcm.c
|
|
@@ -367,12 +367,9 @@ EXPORT_SYMBOL(iw_cm_disconnect);
|
|
/*
|
|
* CM_ID <-- DESTROYING
|
|
*
|
|
- * Clean up all resources associated with the connection and release
|
|
- * the initial reference taken by iw_create_cm_id.
|
|
- *
|
|
- * Returns true if and only if the last cm_id_priv reference has been dropped.
|
|
+ * Clean up all resources associated with the connection.
|
|
*/
|
|
-static bool destroy_cm_id(struct iw_cm_id *cm_id)
|
|
+static void destroy_cm_id(struct iw_cm_id *cm_id)
|
|
{
|
|
struct iwcm_id_private *cm_id_priv;
|
|
struct ib_qp *qp;
|
|
@@ -441,20 +438,22 @@ static bool destroy_cm_id(struct iw_cm_id *cm_id)
|
|
iwpm_remove_mapinfo(&cm_id->local_addr, &cm_id->m_local_addr);
|
|
iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
|
|
}
|
|
-
|
|
- return iwcm_deref_id(cm_id_priv);
|
|
}
|
|
|
|
/*
|
|
- * This function is only called by the application thread and cannot
|
|
- * be called by the event thread. The function will wait for all
|
|
- * references to be released on the cm_id and then kfree the cm_id
|
|
- * object.
|
|
+ * Destroy cm_id. If the cm_id still has other references, wait for all
|
|
+ * references to be released on the cm_id and then release the initial
|
|
+ * reference taken by iw_create_cm_id.
|
|
*/
|
|
void iw_destroy_cm_id(struct iw_cm_id *cm_id)
|
|
{
|
|
- if (!destroy_cm_id(cm_id))
|
|
+ struct iwcm_id_private *cm_id_priv;
|
|
+
|
|
+ cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
|
|
+ destroy_cm_id(cm_id);
|
|
+ if (refcount_read(&cm_id_priv->refcount) > 1)
|
|
flush_workqueue(iwcm_wq);
|
|
+ iwcm_deref_id(cm_id_priv);
|
|
}
|
|
EXPORT_SYMBOL(iw_destroy_cm_id);
|
|
|
|
@@ -1037,8 +1036,10 @@ static void cm_work_handler(struct work_struct *_work)
|
|
|
|
if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
|
|
ret = process_event(cm_id_priv, &levent);
|
|
- if (ret)
|
|
- WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
|
|
+ if (ret) {
|
|
+ destroy_cm_id(&cm_id_priv->id);
|
|
+ WARN_ON_ONCE(iwcm_deref_id(cm_id_priv));
|
|
+ }
|
|
} else
|
|
pr_debug("dropping event %d\n", levent.event);
|
|
if (iwcm_deref_id(cm_id_priv))
|
|
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
|
|
index 2e7c2c046e675f..c5f4207fddce92 100644
|
|
--- a/drivers/input/keyboard/gpio_keys.c
|
|
+++ b/drivers/input/keyboard/gpio_keys.c
|
|
@@ -455,6 +455,8 @@ static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t)
|
|
release_timer);
|
|
struct input_dev *input = bdata->input;
|
|
|
|
+ guard(spinlock_irqsave)(&bdata->lock);
|
|
+
|
|
if (bdata->key_pressed) {
|
|
input_report_key(input, *bdata->code, 0);
|
|
input_sync(input);
|
|
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
|
|
index 180d90e46061e7..5cfe9b56978da0 100644
|
|
--- a/drivers/input/misc/ims-pcu.c
|
|
+++ b/drivers/input/misc/ims-pcu.c
|
|
@@ -845,6 +845,12 @@ static int ims_pcu_flash_firmware(struct ims_pcu *pcu,
|
|
addr = be32_to_cpu(rec->addr) / 2;
|
|
len = be16_to_cpu(rec->len);
|
|
|
|
+ if (len > sizeof(pcu->cmd_buf) - 1 - sizeof(*fragment)) {
|
|
+ dev_err(pcu->dev,
|
|
+ "Invalid record length in firmware: %d\n", len);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
fragment = (void *)&pcu->cmd_buf[1];
|
|
put_unaligned_le32(addr, &fragment->addr);
|
|
fragment->len = len;
|
|
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
|
|
index e5dd84725c6e74..d715fd736426d1 100644
|
|
--- a/drivers/input/misc/sparcspkr.c
|
|
+++ b/drivers/input/misc/sparcspkr.c
|
|
@@ -75,9 +75,14 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
|
|
return -1;
|
|
|
|
switch (code) {
|
|
- case SND_BELL: if (value) value = 1000;
|
|
- case SND_TONE: break;
|
|
- default: return -1;
|
|
+ case SND_BELL:
|
|
+ if (value)
|
|
+ value = 1000;
|
|
+ break;
|
|
+ case SND_TONE:
|
|
+ break;
|
|
+ default:
|
|
+ return -1;
|
|
}
|
|
|
|
if (value > 20 && value < 32767)
|
|
@@ -113,9 +118,14 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned
|
|
return -1;
|
|
|
|
switch (code) {
|
|
- case SND_BELL: if (value) value = 1000;
|
|
- case SND_TONE: break;
|
|
- default: return -1;
|
|
+ case SND_BELL:
|
|
+ if (value)
|
|
+ value = 1000;
|
|
+ break;
|
|
+ case SND_TONE:
|
|
+ break;
|
|
+ default:
|
|
+ return -1;
|
|
}
|
|
|
|
if (value > 20 && value < 32767)
|
|
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
|
|
index 83c5d786686d07..a5d6d786dba523 100644
|
|
--- a/drivers/iommu/amd/iommu.c
|
|
+++ b/drivers/iommu/amd/iommu.c
|
|
@@ -780,6 +780,14 @@ int amd_iommu_register_ga_log_notifier(int (*notifier)(u32))
|
|
{
|
|
iommu_ga_log_notifier = notifier;
|
|
|
|
+ /*
|
|
+ * Ensure all in-flight IRQ handlers run to completion before returning
|
|
+ * to the caller, e.g. to ensure module code isn't unloaded while it's
|
|
+ * being executed in the IRQ handler.
|
|
+ */
|
|
+ if (!notifier)
|
|
+ synchronize_rcu();
|
|
+
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(amd_iommu_register_ga_log_notifier);
|
|
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
|
|
index 9511dae5b556a9..94b6c43dfa5cbd 100644
|
|
--- a/drivers/md/dm-raid1.c
|
|
+++ b/drivers/md/dm-raid1.c
|
|
@@ -133,10 +133,9 @@ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw)
|
|
spin_lock_irqsave(&ms->lock, flags);
|
|
should_wake = !(bl->head);
|
|
bio_list_add(bl, bio);
|
|
- spin_unlock_irqrestore(&ms->lock, flags);
|
|
-
|
|
if (should_wake)
|
|
wakeup_mirrord(ms);
|
|
+ spin_unlock_irqrestore(&ms->lock, flags);
|
|
}
|
|
|
|
static void dispatch_bios(void *context, struct bio_list *bio_list)
|
|
@@ -646,9 +645,9 @@ static void write_callback(unsigned long error, void *context)
|
|
if (!ms->failures.head)
|
|
should_wake = 1;
|
|
bio_list_add(&ms->failures, bio);
|
|
- spin_unlock_irqrestore(&ms->lock, flags);
|
|
if (should_wake)
|
|
wakeup_mirrord(ms);
|
|
+ spin_unlock_irqrestore(&ms->lock, flags);
|
|
}
|
|
|
|
static void do_write(struct mirror_set *ms, struct bio *bio)
|
|
diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c
|
|
index 6a7a17c489c998..8007e2e2197295 100644
|
|
--- a/drivers/md/dm-verity-fec.c
|
|
+++ b/drivers/md/dm-verity-fec.c
|
|
@@ -624,6 +624,10 @@ int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
|
|
(*argc)--;
|
|
|
|
if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_DEV)) {
|
|
+ if (v->fec->dev) {
|
|
+ ti->error = "FEC device already specified";
|
|
+ return -EINVAL;
|
|
+ }
|
|
r = dm_get_device(ti, arg_value, BLK_OPEN_READ, &v->fec->dev);
|
|
if (r) {
|
|
ti->error = "FEC device lookup failed";
|
|
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
|
|
index 6ae97da741bba3..60e74c0e02f1ab 100644
|
|
--- a/drivers/md/dm-verity-target.c
|
|
+++ b/drivers/md/dm-verity-target.c
|
|
@@ -1043,6 +1043,9 @@ static int verity_alloc_most_once(struct dm_verity *v)
|
|
{
|
|
struct dm_target *ti = v->ti;
|
|
|
|
+ if (v->validated_blocks)
|
|
+ return 0;
|
|
+
|
|
/* the bitset can only handle INT_MAX blocks */
|
|
if (v->data_blocks > INT_MAX) {
|
|
ti->error = "device too large to use check_at_most_once";
|
|
@@ -1066,6 +1069,9 @@ static int verity_alloc_zero_digest(struct dm_verity *v)
|
|
struct ahash_request *req;
|
|
u8 *zero_data;
|
|
|
|
+ if (v->zero_digest)
|
|
+ return 0;
|
|
+
|
|
v->zero_digest = kmalloc(v->digest_size, GFP_KERNEL);
|
|
|
|
if (!v->zero_digest)
|
|
@@ -1405,7 +1411,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|
goto bad;
|
|
}
|
|
|
|
- /* Root hash signature is a optional parameter*/
|
|
+ /* Root hash signature is an optional parameter */
|
|
r = verity_verify_root_hash(root_hash_digest_to_validate,
|
|
strlen(root_hash_digest_to_validate),
|
|
verify_args.sig,
|
|
diff --git a/drivers/md/dm-verity-verify-sig.c b/drivers/md/dm-verity-verify-sig.c
|
|
index 4836508ea50c07..1ced2ef255f325 100644
|
|
--- a/drivers/md/dm-verity-verify-sig.c
|
|
+++ b/drivers/md/dm-verity-verify-sig.c
|
|
@@ -71,9 +71,14 @@ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as,
|
|
const char *arg_name)
|
|
{
|
|
struct dm_target *ti = v->ti;
|
|
- int ret = 0;
|
|
+ int ret;
|
|
const char *sig_key = NULL;
|
|
|
|
+ if (v->signature_key_desc) {
|
|
+ ti->error = DM_VERITY_VERIFY_ERR("root_hash_sig_key_desc already specified");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
if (!*argc) {
|
|
ti->error = DM_VERITY_VERIFY_ERR("Signature key not specified");
|
|
return -EINVAL;
|
|
@@ -83,14 +88,18 @@ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as,
|
|
(*argc)--;
|
|
|
|
ret = verity_verify_get_sig_from_key(sig_key, sig_opts);
|
|
- if (ret < 0)
|
|
+ if (ret < 0) {
|
|
ti->error = DM_VERITY_VERIFY_ERR("Invalid key specified");
|
|
+ return ret;
|
|
+ }
|
|
|
|
v->signature_key_desc = kstrdup(sig_key, GFP_KERNEL);
|
|
- if (!v->signature_key_desc)
|
|
+ if (!v->signature_key_desc) {
|
|
+ ti->error = DM_VERITY_VERIFY_ERR("Could not allocate memory for signature key");
|
|
return -ENOMEM;
|
|
+ }
|
|
|
|
- return ret;
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
|
|
index 6975a71d740f6d..a5aa6a2a028cb2 100644
|
|
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
|
|
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
|
|
@@ -469,7 +469,7 @@ vb2_dma_sg_dmabuf_ops_begin_cpu_access(struct dma_buf *dbuf,
|
|
struct vb2_dma_sg_buf *buf = dbuf->priv;
|
|
struct sg_table *sgt = buf->dma_sgt;
|
|
|
|
- dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
|
|
+ dma_sync_sgtable_for_cpu(buf->dev, sgt, buf->dma_dir);
|
|
return 0;
|
|
}
|
|
|
|
@@ -480,7 +480,7 @@ vb2_dma_sg_dmabuf_ops_end_cpu_access(struct dma_buf *dbuf,
|
|
struct vb2_dma_sg_buf *buf = dbuf->priv;
|
|
struct sg_table *sgt = buf->dma_sgt;
|
|
|
|
- dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
|
|
+ dma_sync_sgtable_for_device(buf->dev, sgt, buf->dma_dir);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c
|
|
index cf8858cb13d4ce..611c9823be8578 100644
|
|
--- a/drivers/media/i2c/ccs-pll.c
|
|
+++ b/drivers/media/i2c/ccs-pll.c
|
|
@@ -312,6 +312,11 @@ __ccs_pll_calculate_vt_tree(struct device *dev,
|
|
dev_dbg(dev, "more_mul2: %u\n", more_mul);
|
|
|
|
pll_fr->pll_multiplier = mul * more_mul;
|
|
+ if (pll_fr->pll_multiplier > lim_fr->max_pll_multiplier) {
|
|
+ dev_dbg(dev, "pll multiplier %u too high\n",
|
|
+ pll_fr->pll_multiplier);
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
if (pll_fr->pll_multiplier * pll_fr->pll_ip_clk_freq_hz >
|
|
lim_fr->max_pll_op_clk_freq_hz)
|
|
@@ -397,6 +402,8 @@ static int ccs_pll_calculate_vt_tree(struct device *dev,
|
|
min_pre_pll_clk_div = max_t(u16, min_pre_pll_clk_div,
|
|
pll->ext_clk_freq_hz /
|
|
lim_fr->max_pll_ip_clk_freq_hz);
|
|
+ if (!(pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER))
|
|
+ min_pre_pll_clk_div = clk_div_even(min_pre_pll_clk_div);
|
|
|
|
dev_dbg(dev, "vt min/max_pre_pll_clk_div: %u,%u\n",
|
|
min_pre_pll_clk_div, max_pre_pll_clk_div);
|
|
@@ -792,7 +799,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
|
|
op_lim_fr->min_pre_pll_clk_div, op_lim_fr->max_pre_pll_clk_div);
|
|
max_op_pre_pll_clk_div =
|
|
min_t(u16, op_lim_fr->max_pre_pll_clk_div,
|
|
- clk_div_even(pll->ext_clk_freq_hz /
|
|
+ DIV_ROUND_UP(pll->ext_clk_freq_hz,
|
|
op_lim_fr->min_pll_ip_clk_freq_hz));
|
|
min_op_pre_pll_clk_div =
|
|
max_t(u16, op_lim_fr->min_pre_pll_clk_div,
|
|
@@ -815,6 +822,8 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
|
|
one_or_more(
|
|
DIV_ROUND_UP(op_lim_fr->max_pll_op_clk_freq_hz,
|
|
pll->ext_clk_freq_hz))));
|
|
+ if (!(pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER))
|
|
+ min_op_pre_pll_clk_div = clk_div_even(min_op_pre_pll_clk_div);
|
|
dev_dbg(dev, "pll_op check: min / max op_pre_pll_clk_div: %u / %u\n",
|
|
min_op_pre_pll_clk_div, max_op_pre_pll_clk_div);
|
|
|
|
diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
|
|
index ae33d1ecf835df..6ec960d7914e9a 100644
|
|
--- a/drivers/media/i2c/ds90ub913.c
|
|
+++ b/drivers/media/i2c/ds90ub913.c
|
|
@@ -453,10 +453,10 @@ static int ub913_set_fmt(struct v4l2_subdev *sd,
|
|
if (!fmt)
|
|
return -EINVAL;
|
|
|
|
- format->format.code = finfo->outcode;
|
|
-
|
|
*fmt = format->format;
|
|
|
|
+ fmt->code = finfo->outcode;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c
|
|
index c499e7e93c54b9..92c3e7951ee727 100644
|
|
--- a/drivers/media/i2c/ov5675.c
|
|
+++ b/drivers/media/i2c/ov5675.c
|
|
@@ -1339,11 +1339,8 @@ static int ov5675_probe(struct i2c_client *client)
|
|
return -ENOMEM;
|
|
|
|
ret = ov5675_get_hwcfg(ov5675, &client->dev);
|
|
- if (ret) {
|
|
- dev_err(&client->dev, "failed to get HW configuration: %d",
|
|
- ret);
|
|
+ if (ret)
|
|
return ret;
|
|
- }
|
|
|
|
v4l2_i2c_subdev_init(&ov5675->sd, client, &ov5675_subdev_ops);
|
|
|
|
diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c
|
|
index f053c3a7676a09..8c93fe6285f809 100644
|
|
--- a/drivers/media/i2c/ov8856.c
|
|
+++ b/drivers/media/i2c/ov8856.c
|
|
@@ -2323,8 +2323,8 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev)
|
|
if (!is_acpi_node(fwnode)) {
|
|
ov8856->xvclk = devm_clk_get(dev, "xvclk");
|
|
if (IS_ERR(ov8856->xvclk)) {
|
|
- dev_err(dev, "could not get xvclk clock (%pe)\n",
|
|
- ov8856->xvclk);
|
|
+ dev_err_probe(dev, PTR_ERR(ov8856->xvclk),
|
|
+ "could not get xvclk clock\n");
|
|
return PTR_ERR(ov8856->xvclk);
|
|
}
|
|
|
|
@@ -2429,11 +2429,8 @@ static int ov8856_probe(struct i2c_client *client)
|
|
return -ENOMEM;
|
|
|
|
ret = ov8856_get_hwcfg(ov8856, &client->dev);
|
|
- if (ret) {
|
|
- dev_err(&client->dev, "failed to get HW configuration: %d",
|
|
- ret);
|
|
+ if (ret)
|
|
return ret;
|
|
- }
|
|
|
|
v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops);
|
|
|
|
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
|
|
index 21836dd6ef85a3..bbf56016f70a22 100644
|
|
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
|
|
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
|
|
@@ -821,7 +821,7 @@ static int vdec_hevc_slice_setup_core_buffer(struct vdec_hevc_slice_inst *inst,
|
|
inst->vsi_core->fb.y.dma_addr = y_fb_dma;
|
|
inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0];
|
|
inst->vsi_core->fb.c.dma_addr = c_fb_dma;
|
|
- inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1];
|
|
+ inst->vsi_core->fb.c.size = ctx->picinfo.fb_sz[1];
|
|
|
|
inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb;
|
|
|
|
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
|
|
index 092d83b7e79549..dc3e0d2928104c 100644
|
|
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
|
|
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
|
|
@@ -752,6 +752,32 @@ static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data)
|
|
return -1;
|
|
}
|
|
|
|
+static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
|
|
+{
|
|
+ /* free descriptor for decoding/encoding phase */
|
|
+ dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
|
|
+ jpeg->slot_data.desc,
|
|
+ jpeg->slot_data.desc_handle);
|
|
+ jpeg->slot_data.desc = NULL;
|
|
+ jpeg->slot_data.desc_handle = 0;
|
|
+
|
|
+ /* free descriptor for encoder configuration phase / decoder DHT */
|
|
+ dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
|
|
+ jpeg->slot_data.cfg_desc,
|
|
+ jpeg->slot_data.cfg_desc_handle);
|
|
+ jpeg->slot_data.cfg_desc_handle = 0;
|
|
+ jpeg->slot_data.cfg_desc = NULL;
|
|
+
|
|
+ /* free configuration stream */
|
|
+ dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
|
|
+ jpeg->slot_data.cfg_stream_vaddr,
|
|
+ jpeg->slot_data.cfg_stream_handle);
|
|
+ jpeg->slot_data.cfg_stream_vaddr = NULL;
|
|
+ jpeg->slot_data.cfg_stream_handle = 0;
|
|
+
|
|
+ jpeg->slot_data.used = false;
|
|
+}
|
|
+
|
|
static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
|
|
{
|
|
struct mxc_jpeg_desc *desc;
|
|
@@ -794,30 +820,11 @@ static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
|
|
return true;
|
|
err:
|
|
dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", jpeg->slot_data.slot);
|
|
+ mxc_jpeg_free_slot_data(jpeg);
|
|
|
|
return false;
|
|
}
|
|
|
|
-static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
|
|
-{
|
|
- /* free descriptor for decoding/encoding phase */
|
|
- dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
|
|
- jpeg->slot_data.desc,
|
|
- jpeg->slot_data.desc_handle);
|
|
-
|
|
- /* free descriptor for encoder configuration phase / decoder DHT */
|
|
- dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
|
|
- jpeg->slot_data.cfg_desc,
|
|
- jpeg->slot_data.cfg_desc_handle);
|
|
-
|
|
- /* free configuration stream */
|
|
- dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
|
|
- jpeg->slot_data.cfg_stream_vaddr,
|
|
- jpeg->slot_data.cfg_stream_handle);
|
|
-
|
|
- jpeg->slot_data.used = false;
|
|
-}
|
|
-
|
|
static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx,
|
|
struct vb2_v4l2_buffer *src_buf,
|
|
struct vb2_v4l2_buffer *dst_buf)
|
|
@@ -1913,9 +1920,19 @@ static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)
|
|
jpeg_src_buf = vb2_to_mxc_buf(vb);
|
|
jpeg_src_buf->jpeg_parse_error = false;
|
|
ret = mxc_jpeg_parse(ctx, vb);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
jpeg_src_buf->jpeg_parse_error = true;
|
|
|
|
+ /*
|
|
+ * if the capture queue is not setup, the device_run() won't be scheduled,
|
|
+ * need to drop the error buffer, so that the decoding can continue
|
|
+ */
|
|
+ if (!vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx))) {
|
|
+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
end:
|
|
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
|
|
}
|
|
diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
|
|
index 9745d6219a1667..cd6c52e9d158a7 100644
|
|
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
|
|
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
|
|
@@ -43,6 +43,7 @@ struct mxc_isi_m2m_ctx_queue_data {
|
|
struct v4l2_pix_format_mplane format;
|
|
const struct mxc_isi_format_info *info;
|
|
u32 sequence;
|
|
+ bool streaming;
|
|
};
|
|
|
|
struct mxc_isi_m2m_ctx {
|
|
@@ -486,15 +487,18 @@ static int mxc_isi_m2m_streamon(struct file *file, void *fh,
|
|
enum v4l2_buf_type type)
|
|
{
|
|
struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh);
|
|
+ struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type);
|
|
const struct v4l2_pix_format_mplane *out_pix = &ctx->queues.out.format;
|
|
const struct v4l2_pix_format_mplane *cap_pix = &ctx->queues.cap.format;
|
|
const struct mxc_isi_format_info *cap_info = ctx->queues.cap.info;
|
|
const struct mxc_isi_format_info *out_info = ctx->queues.out.info;
|
|
struct mxc_isi_m2m *m2m = ctx->m2m;
|
|
bool bypass;
|
|
-
|
|
int ret;
|
|
|
|
+ if (q->streaming)
|
|
+ return 0;
|
|
+
|
|
mutex_lock(&m2m->lock);
|
|
|
|
if (m2m->usage_count == INT_MAX) {
|
|
@@ -547,6 +551,8 @@ static int mxc_isi_m2m_streamon(struct file *file, void *fh,
|
|
goto unchain;
|
|
}
|
|
|
|
+ q->streaming = true;
|
|
+
|
|
return 0;
|
|
|
|
unchain:
|
|
@@ -569,10 +575,14 @@ static int mxc_isi_m2m_streamoff(struct file *file, void *fh,
|
|
enum v4l2_buf_type type)
|
|
{
|
|
struct mxc_isi_m2m_ctx *ctx = to_isi_m2m_ctx(fh);
|
|
+ struct mxc_isi_m2m_ctx_queue_data *q = mxc_isi_m2m_ctx_qdata(ctx, type);
|
|
struct mxc_isi_m2m *m2m = ctx->m2m;
|
|
|
|
v4l2_m2m_ioctl_streamoff(file, fh, type);
|
|
|
|
+ if (!q->streaming)
|
|
+ return 0;
|
|
+
|
|
mutex_lock(&m2m->lock);
|
|
|
|
/*
|
|
@@ -598,6 +608,8 @@ static int mxc_isi_m2m_streamoff(struct file *file, void *fh,
|
|
|
|
mutex_unlock(&m2m->lock);
|
|
|
|
+ q->streaming = false;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
|
|
index b570eb8c37568f..47ce3365451d37 100644
|
|
--- a/drivers/media/platform/qcom/venus/core.c
|
|
+++ b/drivers/media/platform/qcom/venus/core.c
|
|
@@ -348,7 +348,7 @@ static int venus_probe(struct platform_device *pdev)
|
|
|
|
ret = v4l2_device_register(dev, &core->v4l2_dev);
|
|
if (ret)
|
|
- goto err_core_deinit;
|
|
+ goto err_hfi_destroy;
|
|
|
|
platform_set_drvdata(pdev, core);
|
|
|
|
@@ -380,24 +380,24 @@ static int venus_probe(struct platform_device *pdev)
|
|
|
|
ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC);
|
|
if (ret)
|
|
- goto err_venus_shutdown;
|
|
+ goto err_core_deinit;
|
|
|
|
ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_ENC);
|
|
if (ret)
|
|
- goto err_venus_shutdown;
|
|
+ goto err_core_deinit;
|
|
|
|
ret = pm_runtime_put_sync(dev);
|
|
if (ret) {
|
|
pm_runtime_get_noresume(dev);
|
|
- goto err_dev_unregister;
|
|
+ goto err_core_deinit;
|
|
}
|
|
|
|
venus_dbgfs_init(core);
|
|
|
|
return 0;
|
|
|
|
-err_dev_unregister:
|
|
- v4l2_device_unregister(&core->v4l2_dev);
|
|
+err_core_deinit:
|
|
+ hfi_core_deinit(core, false);
|
|
err_venus_shutdown:
|
|
venus_shutdown(core);
|
|
err_firmware_deinit:
|
|
@@ -408,9 +408,9 @@ static int venus_probe(struct platform_device *pdev)
|
|
pm_runtime_put_noidle(dev);
|
|
pm_runtime_disable(dev);
|
|
pm_runtime_set_suspended(dev);
|
|
+ v4l2_device_unregister(&core->v4l2_dev);
|
|
+err_hfi_destroy:
|
|
hfi_destroy(core);
|
|
-err_core_deinit:
|
|
- hfi_core_deinit(core, false);
|
|
err_core_put:
|
|
if (core->pm_ops->core_put)
|
|
core->pm_ops->core_put(core);
|
|
diff --git a/drivers/media/platform/ti/davinci/vpif.c b/drivers/media/platform/ti/davinci/vpif.c
|
|
index 63cdfed37bc9bc..fa9679abf7a483 100644
|
|
--- a/drivers/media/platform/ti/davinci/vpif.c
|
|
+++ b/drivers/media/platform/ti/davinci/vpif.c
|
|
@@ -505,7 +505,7 @@ static int vpif_probe(struct platform_device *pdev)
|
|
pdev_display = kzalloc(sizeof(*pdev_display), GFP_KERNEL);
|
|
if (!pdev_display) {
|
|
ret = -ENOMEM;
|
|
- goto err_put_pdev_capture;
|
|
+ goto err_del_pdev_capture;
|
|
}
|
|
|
|
pdev_display->name = "vpif_display";
|
|
@@ -528,6 +528,8 @@ static int vpif_probe(struct platform_device *pdev)
|
|
|
|
err_put_pdev_display:
|
|
platform_device_put(pdev_display);
|
|
+err_del_pdev_capture:
|
|
+ platform_device_del(pdev_capture);
|
|
err_put_pdev_capture:
|
|
platform_device_put(pdev_capture);
|
|
err_put_rpm:
|
|
diff --git a/drivers/media/platform/ti/omap3isp/ispccdc.c b/drivers/media/platform/ti/omap3isp/ispccdc.c
|
|
index 2fe42aa9180049..6eb387ea1dae10 100644
|
|
--- a/drivers/media/platform/ti/omap3isp/ispccdc.c
|
|
+++ b/drivers/media/platform/ti/omap3isp/ispccdc.c
|
|
@@ -446,8 +446,8 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
|
|
if (ret < 0)
|
|
goto done;
|
|
|
|
- dma_sync_sg_for_cpu(isp->dev, req->table.sgt.sgl,
|
|
- req->table.sgt.nents, DMA_TO_DEVICE);
|
|
+ dma_sync_sgtable_for_cpu(isp->dev, &req->table.sgt,
|
|
+ DMA_TO_DEVICE);
|
|
|
|
if (copy_from_user(req->table.addr, config->lsc,
|
|
req->config.size)) {
|
|
@@ -455,8 +455,8 @@ static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
|
|
goto done;
|
|
}
|
|
|
|
- dma_sync_sg_for_device(isp->dev, req->table.sgt.sgl,
|
|
- req->table.sgt.nents, DMA_TO_DEVICE);
|
|
+ dma_sync_sgtable_for_device(isp->dev, &req->table.sgt,
|
|
+ DMA_TO_DEVICE);
|
|
}
|
|
|
|
spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
|
|
diff --git a/drivers/media/platform/ti/omap3isp/ispstat.c b/drivers/media/platform/ti/omap3isp/ispstat.c
|
|
index 68cf68dbcace28..dc496ca9748a6c 100644
|
|
--- a/drivers/media/platform/ti/omap3isp/ispstat.c
|
|
+++ b/drivers/media/platform/ti/omap3isp/ispstat.c
|
|
@@ -161,8 +161,7 @@ static void isp_stat_buf_sync_for_device(struct ispstat *stat,
|
|
if (ISP_STAT_USES_DMAENGINE(stat))
|
|
return;
|
|
|
|
- dma_sync_sg_for_device(stat->isp->dev, buf->sgt.sgl,
|
|
- buf->sgt.nents, DMA_FROM_DEVICE);
|
|
+ dma_sync_sgtable_for_device(stat->isp->dev, &buf->sgt, DMA_FROM_DEVICE);
|
|
}
|
|
|
|
static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
|
|
@@ -171,8 +170,7 @@ static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
|
|
if (ISP_STAT_USES_DMAENGINE(stat))
|
|
return;
|
|
|
|
- dma_sync_sg_for_cpu(stat->isp->dev, buf->sgt.sgl,
|
|
- buf->sgt.nents, DMA_FROM_DEVICE);
|
|
+ dma_sync_sgtable_for_cpu(stat->isp->dev, &buf->sgt, DMA_FROM_DEVICE);
|
|
}
|
|
|
|
static void isp_stat_buf_clear(struct ispstat *stat)
|
|
diff --git a/drivers/media/test-drivers/vidtv/vidtv_channel.c b/drivers/media/test-drivers/vidtv/vidtv_channel.c
|
|
index 7838e62727128f..f3023e91b3ebc8 100644
|
|
--- a/drivers/media/test-drivers/vidtv/vidtv_channel.c
|
|
+++ b/drivers/media/test-drivers/vidtv/vidtv_channel.c
|
|
@@ -497,7 +497,7 @@ int vidtv_channel_si_init(struct vidtv_mux *m)
|
|
vidtv_psi_sdt_table_destroy(m->si.sdt);
|
|
free_pat:
|
|
vidtv_psi_pat_table_destroy(m->si.pat);
|
|
- return 0;
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
void vidtv_channel_si_destroy(struct vidtv_mux *m)
|
|
diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
|
|
index 9443dbb04699a3..0ab47fb8696bd0 100644
|
|
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c
|
|
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
|
|
@@ -954,8 +954,8 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection
|
|
if (dev->has_compose_cap) {
|
|
v4l2_rect_set_min_size(compose, &min_rect);
|
|
v4l2_rect_set_max_size(compose, &max_rect);
|
|
- v4l2_rect_map_inside(compose, &fmt);
|
|
}
|
|
+ v4l2_rect_map_inside(compose, &fmt);
|
|
dev->fmt_cap_rect = fmt;
|
|
tpg_s_buf_height(&dev->tpg, fmt.height);
|
|
} else if (dev->has_compose_cap) {
|
|
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
|
|
index 1d98d3465e28d4..ce52c936cb9310 100644
|
|
--- a/drivers/media/usb/dvb-usb/cxusb.c
|
|
+++ b/drivers/media/usb/dvb-usb/cxusb.c
|
|
@@ -119,9 +119,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
|
|
|
|
o[0] = GPIO_TUNER;
|
|
o[1] = onoff;
|
|
- cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
|
|
|
|
- if (i != 0x01)
|
|
+ if (!cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1) && i != 0x01)
|
|
dev_info(&d->udev->dev, "gpio_write failed.\n");
|
|
|
|
st->gpio_write_state[GPIO_TUNER] = onoff;
|
|
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
|
|
index 5a47dcbf1c8e55..303b055fefea98 100644
|
|
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
|
|
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
|
|
@@ -520,12 +520,13 @@ static int hdcs_init(struct sd *sd)
|
|
static int hdcs_dump(struct sd *sd)
|
|
{
|
|
u16 reg, val;
|
|
+ int err = 0;
|
|
|
|
pr_info("Dumping sensor registers:\n");
|
|
|
|
- for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
|
|
- stv06xx_read_sensor(sd, reg, &val);
|
|
+ for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH && !err; reg++) {
|
|
+ err = stv06xx_read_sensor(sd, reg, &val);
|
|
pr_info("reg 0x%02x = 0x%02x\n", reg, val);
|
|
}
|
|
- return 0;
|
|
+ return (err < 0) ? err : 0;
|
|
}
|
|
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
|
|
index 5926a9dfb0b1f8..59e21746f55073 100644
|
|
--- a/drivers/media/usb/uvc/uvc_ctrl.c
|
|
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
|
|
@@ -1642,7 +1642,9 @@ static bool uvc_ctrl_xctrls_has_control(const struct v4l2_ext_control *xctrls,
|
|
}
|
|
|
|
static void uvc_ctrl_send_events(struct uvc_fh *handle,
|
|
- const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
|
|
+ struct uvc_entity *entity,
|
|
+ const struct v4l2_ext_control *xctrls,
|
|
+ unsigned int xctrls_count)
|
|
{
|
|
struct uvc_control_mapping *mapping;
|
|
struct uvc_control *ctrl;
|
|
@@ -1653,6 +1655,9 @@ static void uvc_ctrl_send_events(struct uvc_fh *handle,
|
|
u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
|
|
|
|
ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
|
|
+ if (ctrl->entity != entity)
|
|
+ continue;
|
|
+
|
|
if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
|
|
/* Notification will be sent from an Interrupt event. */
|
|
continue;
|
|
@@ -1783,12 +1788,17 @@ int uvc_ctrl_begin(struct uvc_video_chain *chain)
|
|
return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Returns the number of uvc controls that have been correctly set, or a
|
|
+ * negative number if there has been an error.
|
|
+ */
|
|
static int uvc_ctrl_commit_entity(struct uvc_device *dev,
|
|
struct uvc_fh *handle,
|
|
struct uvc_entity *entity,
|
|
int rollback,
|
|
struct uvc_control **err_ctrl)
|
|
{
|
|
+ unsigned int processed_ctrls = 0;
|
|
struct uvc_control *ctrl;
|
|
unsigned int i;
|
|
int ret;
|
|
@@ -1823,6 +1833,9 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
|
|
else
|
|
ret = 0;
|
|
|
|
+ if (!ret)
|
|
+ processed_ctrls++;
|
|
+
|
|
if (rollback || ret < 0)
|
|
memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
|
|
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
|
|
@@ -1841,7 +1854,7 @@ static int uvc_ctrl_commit_entity(struct uvc_device *dev,
|
|
uvc_ctrl_set_handle(handle, ctrl, handle);
|
|
}
|
|
|
|
- return 0;
|
|
+ return processed_ctrls;
|
|
}
|
|
|
|
static int uvc_ctrl_find_ctrl_idx(struct uvc_entity *entity,
|
|
@@ -1883,11 +1896,13 @@ int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
|
|
uvc_ctrl_find_ctrl_idx(entity, ctrls,
|
|
err_ctrl);
|
|
goto done;
|
|
+ } else if (ret > 0 && !rollback) {
|
|
+ uvc_ctrl_send_events(handle, entity,
|
|
+ ctrls->controls, ctrls->count);
|
|
}
|
|
}
|
|
|
|
- if (!rollback)
|
|
- uvc_ctrl_send_events(handle, ctrls->controls, ctrls->count);
|
|
+ ret = 0;
|
|
done:
|
|
mutex_unlock(&chain->ctrl_mutex);
|
|
return ret;
|
|
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
|
|
index 02cfa12b9cb902..76f18557f37bd4 100644
|
|
--- a/drivers/media/usb/uvc/uvc_driver.c
|
|
+++ b/drivers/media/usb/uvc/uvc_driver.c
|
|
@@ -2217,13 +2217,16 @@ static int uvc_probe(struct usb_interface *intf,
|
|
#endif
|
|
|
|
/* Parse the Video Class control descriptor. */
|
|
- if (uvc_parse_control(dev) < 0) {
|
|
+ ret = uvc_parse_control(dev);
|
|
+ if (ret < 0) {
|
|
+ ret = -ENODEV;
|
|
uvc_dbg(dev, PROBE, "Unable to parse UVC descriptors\n");
|
|
goto error;
|
|
}
|
|
|
|
/* Parse the associated GPIOs. */
|
|
- if (uvc_gpio_parse(dev) < 0) {
|
|
+ ret = uvc_gpio_parse(dev);
|
|
+ if (ret < 0) {
|
|
uvc_dbg(dev, PROBE, "Unable to parse UVC GPIOs\n");
|
|
goto error;
|
|
}
|
|
@@ -2249,24 +2252,32 @@ static int uvc_probe(struct usb_interface *intf,
|
|
}
|
|
|
|
/* Register the V4L2 device. */
|
|
- if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
|
|
+ ret = v4l2_device_register(&intf->dev, &dev->vdev);
|
|
+ if (ret < 0)
|
|
goto error;
|
|
|
|
/* Scan the device for video chains. */
|
|
- if (uvc_scan_device(dev) < 0)
|
|
+ if (uvc_scan_device(dev) < 0) {
|
|
+ ret = -ENODEV;
|
|
goto error;
|
|
+ }
|
|
|
|
/* Initialize controls. */
|
|
- if (uvc_ctrl_init_device(dev) < 0)
|
|
+ if (uvc_ctrl_init_device(dev) < 0) {
|
|
+ ret = -ENODEV;
|
|
goto error;
|
|
+ }
|
|
|
|
/* Register video device nodes. */
|
|
- if (uvc_register_chains(dev) < 0)
|
|
+ if (uvc_register_chains(dev) < 0) {
|
|
+ ret = -ENODEV;
|
|
goto error;
|
|
+ }
|
|
|
|
#ifdef CONFIG_MEDIA_CONTROLLER
|
|
/* Register the media device node */
|
|
- if (media_device_register(&dev->mdev) < 0)
|
|
+ ret = media_device_register(&dev->mdev);
|
|
+ if (ret < 0)
|
|
goto error;
|
|
#endif
|
|
/* Save our data pointer in the interface data. */
|
|
@@ -2300,7 +2311,7 @@ static int uvc_probe(struct usb_interface *intf,
|
|
error:
|
|
uvc_unregister_video(dev);
|
|
kref_put(&dev->ref, uvc_delete);
|
|
- return -ENODEV;
|
|
+ return ret;
|
|
}
|
|
|
|
static void uvc_disconnect(struct usb_interface *intf)
|
|
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
|
|
index 77bbf276ae89df..c4d3d110c5007e 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-dev.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-dev.c
|
|
@@ -1033,25 +1033,25 @@ int __video_register_device(struct video_device *vdev,
|
|
vdev->dev.class = &video_class;
|
|
vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
|
|
vdev->dev.parent = vdev->dev_parent;
|
|
+ vdev->dev.release = v4l2_device_release;
|
|
dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
|
|
+
|
|
+ /* Increase v4l2_device refcount */
|
|
+ v4l2_device_get(vdev->v4l2_dev);
|
|
+
|
|
mutex_lock(&videodev_lock);
|
|
ret = device_register(&vdev->dev);
|
|
if (ret < 0) {
|
|
mutex_unlock(&videodev_lock);
|
|
pr_err("%s: device_register failed\n", __func__);
|
|
- goto cleanup;
|
|
+ put_device(&vdev->dev);
|
|
+ return ret;
|
|
}
|
|
- /* Register the release callback that will be called when the last
|
|
- reference to the device goes away. */
|
|
- vdev->dev.release = v4l2_device_release;
|
|
|
|
if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
|
|
pr_warn("%s: requested %s%d, got %s\n", __func__,
|
|
name_base, nr, video_device_node_name(vdev));
|
|
|
|
- /* Increase v4l2_device refcount */
|
|
- v4l2_device_get(vdev->v4l2_dev);
|
|
-
|
|
/* Part 5: Register the entity. */
|
|
ret = video_register_media_controller(vdev);
|
|
|
|
diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
|
|
index 8476754b1b170c..fe0b2fa3bb89dc 100644
|
|
--- a/drivers/mmc/core/card.h
|
|
+++ b/drivers/mmc/core/card.h
|
|
@@ -86,6 +86,7 @@ struct mmc_fixup {
|
|
#define CID_MANFID_MICRON 0x13
|
|
#define CID_MANFID_SAMSUNG 0x15
|
|
#define CID_MANFID_APACER 0x27
|
|
+#define CID_MANFID_SWISSBIT 0x5D
|
|
#define CID_MANFID_KINGSTON 0x70
|
|
#define CID_MANFID_HYNIX 0x90
|
|
#define CID_MANFID_KINGSTON_SD 0x9F
|
|
@@ -291,4 +292,9 @@ static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c)
|
|
return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY;
|
|
}
|
|
|
|
+static inline int mmc_card_no_uhs_ddr50_tuning(const struct mmc_card *c)
|
|
+{
|
|
+ return c->quirks & MMC_QUIRK_NO_UHS_DDR50_TUNING;
|
|
+}
|
|
+
|
|
#endif
|
|
diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
|
|
index 89b512905be140..7f893bafaa607d 100644
|
|
--- a/drivers/mmc/core/quirks.h
|
|
+++ b/drivers/mmc/core/quirks.h
|
|
@@ -34,6 +34,16 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = {
|
|
MMC_QUIRK_BROKEN_SD_CACHE | MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY,
|
|
EXT_CSD_REV_ANY),
|
|
|
|
+ /*
|
|
+ * Swissbit series S46-u cards throw I/O errors during tuning requests
|
|
+ * after the initial tuning request expectedly times out. This has
|
|
+ * only been observed on cards manufactured on 01/2019 that are using
|
|
+ * Bay Trail host controllers.
|
|
+ */
|
|
+ _FIXUP_EXT("0016G", CID_MANFID_SWISSBIT, 0x5342, 2019, 1,
|
|
+ 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
|
|
+ MMC_QUIRK_NO_UHS_DDR50_TUNING, EXT_CSD_REV_ANY),
|
|
+
|
|
END_FIXUP
|
|
};
|
|
|
|
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
|
|
index f02c3e5eb5c851..a06f3011e2b58c 100644
|
|
--- a/drivers/mmc/core/sd.c
|
|
+++ b/drivers/mmc/core/sd.c
|
|
@@ -618,6 +618,29 @@ static int sd_set_current_limit(struct mmc_card *card, u8 *status)
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Determine if the card should tune or not.
|
|
+ */
|
|
+static bool mmc_sd_use_tuning(struct mmc_card *card)
|
|
+{
|
|
+ /*
|
|
+ * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and
|
|
+ * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
|
|
+ */
|
|
+ if (mmc_host_is_spi(card->host))
|
|
+ return false;
|
|
+
|
|
+ switch (card->host->ios.timing) {
|
|
+ case MMC_TIMING_UHS_SDR50:
|
|
+ case MMC_TIMING_UHS_SDR104:
|
|
+ return true;
|
|
+ case MMC_TIMING_UHS_DDR50:
|
|
+ return !mmc_card_no_uhs_ddr50_tuning(card);
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
/*
|
|
* UHS-I specific initialization procedure
|
|
*/
|
|
@@ -661,14 +684,7 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
|
|
if (err)
|
|
goto out;
|
|
|
|
- /*
|
|
- * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and
|
|
- * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104.
|
|
- */
|
|
- if (!mmc_host_is_spi(card->host) &&
|
|
- (card->host->ios.timing == MMC_TIMING_UHS_SDR50 ||
|
|
- card->host->ios.timing == MMC_TIMING_UHS_DDR50 ||
|
|
- card->host->ios.timing == MMC_TIMING_UHS_SDR104)) {
|
|
+ if (mmc_sd_use_tuning(card)) {
|
|
err = mmc_execute_tuning(card);
|
|
|
|
/*
|
|
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
|
|
index b8cff9240b286c..beafca6ba0df4d 100644
|
|
--- a/drivers/mtd/nand/raw/qcom_nandc.c
|
|
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
|
|
@@ -2917,7 +2917,7 @@ static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_
|
|
write_reg_dma(nandc, NAND_DEV_CMD1, 1, NAND_BAM_NEXT_SGL);
|
|
}
|
|
|
|
- nandc->buf_count = len;
|
|
+ nandc->buf_count = 512;
|
|
memset(nandc->data_buffer, 0xff, nandc->buf_count);
|
|
|
|
config_nand_single_cw_page_read(chip, false, 0);
|
|
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
|
|
index 9abf38049d35f3..4469618ee60331 100644
|
|
--- a/drivers/mtd/nand/raw/sunxi_nand.c
|
|
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
|
|
@@ -817,6 +817,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ sunxi_nfc_randomizer_config(nand, page, false);
|
|
sunxi_nfc_randomizer_enable(nand);
|
|
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
|
|
nfc->regs + NFC_REG_CMD);
|
|
@@ -1049,6 +1050,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ sunxi_nfc_randomizer_config(nand, page, false);
|
|
sunxi_nfc_randomizer_enable(nand);
|
|
sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page);
|
|
|
|
diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
|
|
index ae8c42f5debd4d..4d440ecfc211c1 100644
|
|
--- a/drivers/net/can/m_can/tcan4x5x-core.c
|
|
+++ b/drivers/net/can/m_can/tcan4x5x-core.c
|
|
@@ -385,10 +385,11 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
|
|
priv = cdev_to_priv(mcan_class);
|
|
|
|
priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
|
|
- if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
|
|
- ret = -EPROBE_DEFER;
|
|
- goto out_m_can_class_free_dev;
|
|
- } else {
|
|
+ if (IS_ERR(priv->power)) {
|
|
+ if (PTR_ERR(priv->power) == -EPROBE_DEFER) {
|
|
+ ret = -EPROBE_DEFER;
|
|
+ goto out_m_can_class_free_dev;
|
|
+ }
|
|
priv->power = NULL;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
|
|
index 0b2a52199914b7..75d436c9069689 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c
|
|
@@ -123,7 +123,6 @@ static netdev_tx_t aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *nd
|
|
}
|
|
#endif
|
|
|
|
- skb_tx_timestamp(skb);
|
|
return aq_nic_xmit(aq_nic, skb);
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
index c9b0d57696a487..07392174f6437e 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
@@ -898,6 +898,8 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
|
|
|
|
frags = aq_nic_map_skb(self, skb, ring);
|
|
|
|
+ skb_tx_timestamp(skb);
|
|
+
|
|
if (likely(frags)) {
|
|
err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw,
|
|
ring, frags);
|
|
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
|
|
index 6f45f4d9fba71f..534e7f7bca4c2f 100644
|
|
--- a/drivers/net/ethernet/cadence/macb_main.c
|
|
+++ b/drivers/net/ethernet/cadence/macb_main.c
|
|
@@ -5070,7 +5070,11 @@ static int macb_probe(struct platform_device *pdev)
|
|
|
|
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
|
if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
|
|
- dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
|
|
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
|
|
+ if (err) {
|
|
+ dev_err(&pdev->dev, "failed to set DMA mask\n");
|
|
+ goto err_out_free_netdev;
|
|
+ }
|
|
bp->hw_dma_cap |= HW_DMA_CAP_64B;
|
|
}
|
|
#endif
|
|
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
|
|
index 5af98fba74803e..fce2ff1e1d8348 100644
|
|
--- a/drivers/net/ethernet/cortina/gemini.c
|
|
+++ b/drivers/net/ethernet/cortina/gemini.c
|
|
@@ -1148,6 +1148,7 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb,
|
|
struct gmac_txdesc *txd;
|
|
skb_frag_t *skb_frag;
|
|
dma_addr_t mapping;
|
|
+ bool tcp = false;
|
|
void *buffer;
|
|
u16 mss;
|
|
int ret;
|
|
@@ -1155,6 +1156,13 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb,
|
|
word1 = skb->len;
|
|
word3 = SOF_BIT;
|
|
|
|
+ /* Determine if we are doing TCP */
|
|
+ if (skb->protocol == htons(ETH_P_IP))
|
|
+ tcp = (ip_hdr(skb)->protocol == IPPROTO_TCP);
|
|
+ else
|
|
+ /* IPv6 */
|
|
+ tcp = (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP);
|
|
+
|
|
mss = skb_shinfo(skb)->gso_size;
|
|
if (mss) {
|
|
/* This means we are dealing with TCP and skb->len is the
|
|
@@ -1167,8 +1175,26 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb,
|
|
mss, skb->len);
|
|
word1 |= TSS_MTU_ENABLE_BIT;
|
|
word3 |= mss;
|
|
+ } else if (tcp) {
|
|
+ /* Even if we are not using TSO, use the hardware offloader
|
|
+ * for transferring the TCP frame: this hardware has partial
|
|
+ * TCP awareness (called TOE - TCP Offload Engine) and will
|
|
+ * according to the datasheet put packets belonging to the
|
|
+ * same TCP connection in the same queue for the TOE/TSO
|
|
+ * engine to process. The engine will deal with chopping
|
|
+ * up frames that exceed ETH_DATA_LEN which the
|
|
+ * checksumming engine cannot handle (see below) into
|
|
+ * manageable chunks. It flawlessly deals with quite big
|
|
+ * frames and frames containing custom DSA EtherTypes.
|
|
+ */
|
|
+ mss = netdev->mtu + skb_tcp_all_headers(skb);
|
|
+ mss = min(mss, skb->len);
|
|
+ netdev_dbg(netdev, "TOE/TSO len %04x mtu %04x mss %04x\n",
|
|
+ skb->len, netdev->mtu, mss);
|
|
+ word1 |= TSS_MTU_ENABLE_BIT;
|
|
+ word3 |= mss;
|
|
} else if (skb->len >= ETH_FRAME_LEN) {
|
|
- /* Hardware offloaded checksumming isn't working on frames
|
|
+ /* Hardware offloaded checksumming isn't working on non-TCP 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
|
|
@@ -1185,21 +1211,16 @@ static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb,
|
|
}
|
|
|
|
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)) {
|
|
+ if (skb->protocol == htons(ETH_P_IP))
|
|
word1 |= TSS_IP_CHKSUM_BIT;
|
|
- tcp = ip_hdr(skb)->protocol == IPPROTO_TCP;
|
|
- } else { /* IPv6 */
|
|
+ else
|
|
word1 |= TSS_IPV6_ENABLE_BIT;
|
|
- tcp = ipv6_hdr(skb)->nexthdr == IPPROTO_TCP;
|
|
- }
|
|
|
|
word1 |= tcp ? TSS_TCP_CHKSUM_BIT : TSS_UDP_CHKSUM_BIT;
|
|
}
|
|
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
|
|
index ce46f3ac3b5a18..fad5a72d3b1671 100644
|
|
--- a/drivers/net/ethernet/dlink/dl2k.c
|
|
+++ b/drivers/net/ethernet/dlink/dl2k.c
|
|
@@ -146,6 +146,8 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
np->ioaddr = ioaddr;
|
|
np->chip_id = chip_idx;
|
|
np->pdev = pdev;
|
|
+
|
|
+ spin_lock_init(&np->stats_lock);
|
|
spin_lock_init (&np->tx_lock);
|
|
spin_lock_init (&np->rx_lock);
|
|
|
|
@@ -866,7 +868,6 @@ tx_error (struct net_device *dev, int tx_status)
|
|
frame_id = (tx_status & 0xffff0000);
|
|
printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n",
|
|
dev->name, tx_status, frame_id);
|
|
- dev->stats.tx_errors++;
|
|
/* Ttransmit Underrun */
|
|
if (tx_status & 0x10) {
|
|
dev->stats.tx_fifo_errors++;
|
|
@@ -903,9 +904,15 @@ tx_error (struct net_device *dev, int tx_status)
|
|
rio_set_led_mode(dev);
|
|
/* Let TxStartThresh stay default value */
|
|
}
|
|
+
|
|
+ spin_lock(&np->stats_lock);
|
|
/* Maximum Collisions */
|
|
if (tx_status & 0x08)
|
|
dev->stats.collisions++;
|
|
+
|
|
+ dev->stats.tx_errors++;
|
|
+ spin_unlock(&np->stats_lock);
|
|
+
|
|
/* Restart the Tx */
|
|
dw32(MACCtrl, dr16(MACCtrl) | TxEnable);
|
|
}
|
|
@@ -1074,7 +1081,9 @@ get_stats (struct net_device *dev)
|
|
int i;
|
|
#endif
|
|
unsigned int stat_reg;
|
|
+ unsigned long flags;
|
|
|
|
+ spin_lock_irqsave(&np->stats_lock, flags);
|
|
/* All statistics registers need to be acknowledged,
|
|
else statistic overflow could cause problems */
|
|
|
|
@@ -1124,6 +1133,9 @@ get_stats (struct net_device *dev)
|
|
dr16(TCPCheckSumErrors);
|
|
dr16(UDPCheckSumErrors);
|
|
dr16(IPCheckSumErrors);
|
|
+
|
|
+ spin_unlock_irqrestore(&np->stats_lock, flags);
|
|
+
|
|
return &dev->stats;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h
|
|
index 0e33e2eaae9606..56aff2f0bdbfa0 100644
|
|
--- a/drivers/net/ethernet/dlink/dl2k.h
|
|
+++ b/drivers/net/ethernet/dlink/dl2k.h
|
|
@@ -372,6 +372,8 @@ struct netdev_private {
|
|
struct pci_dev *pdev;
|
|
void __iomem *ioaddr;
|
|
void __iomem *eeprom_addr;
|
|
+ // To ensure synchronization when stats are updated.
|
|
+ spinlock_t stats_lock;
|
|
spinlock_t tx_lock;
|
|
spinlock_t rx_lock;
|
|
unsigned int rx_buf_sz; /* Based on MTU+slack. */
|
|
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
|
index 51b8377edd1d04..a89aa4ac0a064a 100644
|
|
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
|
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
|
@@ -1609,7 +1609,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
|
|
/* version 1 of the cmd is not supported only by BE2 */
|
|
if (BE2_chip(adapter))
|
|
hdr->version = 0;
|
|
- if (BE3_chip(adapter) || lancer_chip(adapter))
|
|
+ else if (BE3_chip(adapter) || lancer_chip(adapter))
|
|
hdr->version = 1;
|
|
else
|
|
hdr->version = 2;
|
|
diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig
|
|
index c699bd6bcbb938..474073c7f94d74 100644
|
|
--- a/drivers/net/ethernet/faraday/Kconfig
|
|
+++ b/drivers/net/ethernet/faraday/Kconfig
|
|
@@ -31,6 +31,7 @@ config FTGMAC100
|
|
depends on ARM || COMPILE_TEST
|
|
depends on !64BIT || BROKEN
|
|
select PHYLIB
|
|
+ select FIXED_PHY
|
|
select MDIO_ASPEED if MACH_ASPEED_G6
|
|
select CRC32
|
|
help
|
|
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
index 721c098f2bb1b2..7e4fea0e186b6e 100644
|
|
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
@@ -3540,9 +3540,6 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
|
|
case e1000_pch_cnp:
|
|
case e1000_pch_tgp:
|
|
case e1000_pch_adp:
|
|
- case e1000_pch_mtp:
|
|
- case e1000_pch_lnp:
|
|
- case e1000_pch_ptp:
|
|
case e1000_pch_nvp:
|
|
if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) {
|
|
/* Stable 24MHz frequency */
|
|
@@ -3558,6 +3555,17 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
|
|
adapter->cc.shift = shift;
|
|
}
|
|
break;
|
|
+ case e1000_pch_mtp:
|
|
+ case e1000_pch_lnp:
|
|
+ case e1000_pch_ptp:
|
|
+ /* System firmware can misreport this value, so set it to a
|
|
+ * stable 38400KHz frequency.
|
|
+ */
|
|
+ incperiod = INCPERIOD_38400KHZ;
|
|
+ incvalue = INCVALUE_38400KHZ;
|
|
+ shift = INCVALUE_SHIFT_38400KHZ;
|
|
+ adapter->cc.shift = shift;
|
|
+ break;
|
|
case e1000_82574:
|
|
case e1000_82583:
|
|
/* Stable 25MHz frequency */
|
|
diff --git a/drivers/net/ethernet/intel/e1000e/ptp.c b/drivers/net/ethernet/intel/e1000e/ptp.c
|
|
index bbcfd529399b0f..d039dea48ca324 100644
|
|
--- a/drivers/net/ethernet/intel/e1000e/ptp.c
|
|
+++ b/drivers/net/ethernet/intel/e1000e/ptp.c
|
|
@@ -294,15 +294,17 @@ void e1000e_ptp_init(struct e1000_adapter *adapter)
|
|
case e1000_pch_cnp:
|
|
case e1000_pch_tgp:
|
|
case e1000_pch_adp:
|
|
- case e1000_pch_mtp:
|
|
- case e1000_pch_lnp:
|
|
- case e1000_pch_ptp:
|
|
case e1000_pch_nvp:
|
|
if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)
|
|
adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ;
|
|
else
|
|
adapter->ptp_clock_info.max_adj = MAX_PPB_38400KHZ;
|
|
break;
|
|
+ case e1000_pch_mtp:
|
|
+ case e1000_pch_lnp:
|
|
+ case e1000_pch_ptp:
|
|
+ adapter->ptp_clock_info.max_adj = MAX_PPB_38400KHZ;
|
|
+ break;
|
|
case e1000_82574:
|
|
case e1000_82583:
|
|
adapter->ptp_clock_info.max_adj = MAX_PPB_25MHZ;
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
|
|
index 4d7caa11997199..5d46a8e5376dac 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
|
|
@@ -1067,10 +1067,11 @@ int i40e_pf_reset(struct i40e_hw *hw)
|
|
void i40e_clear_hw(struct i40e_hw *hw)
|
|
{
|
|
u32 num_queues, base_queue;
|
|
- u32 num_pf_int;
|
|
- u32 num_vf_int;
|
|
+ s32 num_pf_int;
|
|
+ s32 num_vf_int;
|
|
u32 num_vfs;
|
|
- u32 i, j;
|
|
+ s32 i;
|
|
+ u32 j;
|
|
u32 val;
|
|
u32 eol = 0x7ff;
|
|
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
|
|
index d7e0116f67737b..7036070bc0208b 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_arfs.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
|
|
@@ -376,6 +376,50 @@ ice_arfs_is_perfect_flow_set(struct ice_hw *hw, __be16 l3_proto, u8 l4_proto)
|
|
return false;
|
|
}
|
|
|
|
+/**
|
|
+ * ice_arfs_cmp - Check if aRFS filter matches this flow.
|
|
+ * @fltr_info: filter info of the saved ARFS entry.
|
|
+ * @fk: flow dissector keys.
|
|
+ * @n_proto: One of htons(ETH_P_IP) or htons(ETH_P_IPV6).
|
|
+ * @ip_proto: One of IPPROTO_TCP or IPPROTO_UDP.
|
|
+ *
|
|
+ * Since this function assumes limited values for n_proto and ip_proto, it
|
|
+ * is meant to be called only from ice_rx_flow_steer().
|
|
+ *
|
|
+ * Return:
|
|
+ * * true - fltr_info refers to the same flow as fk.
|
|
+ * * false - fltr_info and fk refer to different flows.
|
|
+ */
|
|
+static bool
|
|
+ice_arfs_cmp(const struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk,
|
|
+ __be16 n_proto, u8 ip_proto)
|
|
+{
|
|
+ /* Determine if the filter is for IPv4 or IPv6 based on flow_type,
|
|
+ * which is one of ICE_FLTR_PTYPE_NONF_IPV{4,6}_{TCP,UDP}.
|
|
+ */
|
|
+ bool is_v4 = fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
|
|
+ fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP;
|
|
+
|
|
+ /* Following checks are arranged in the quickest and most discriminative
|
|
+ * fields first for early failure.
|
|
+ */
|
|
+ if (is_v4)
|
|
+ return n_proto == htons(ETH_P_IP) &&
|
|
+ fltr_info->ip.v4.src_port == fk->ports.src &&
|
|
+ fltr_info->ip.v4.dst_port == fk->ports.dst &&
|
|
+ fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src &&
|
|
+ fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst &&
|
|
+ fltr_info->ip.v4.proto == ip_proto;
|
|
+
|
|
+ return fltr_info->ip.v6.src_port == fk->ports.src &&
|
|
+ fltr_info->ip.v6.dst_port == fk->ports.dst &&
|
|
+ fltr_info->ip.v6.proto == ip_proto &&
|
|
+ !memcmp(&fltr_info->ip.v6.src_ip, &fk->addrs.v6addrs.src,
|
|
+ sizeof(struct in6_addr)) &&
|
|
+ !memcmp(&fltr_info->ip.v6.dst_ip, &fk->addrs.v6addrs.dst,
|
|
+ sizeof(struct in6_addr));
|
|
+}
|
|
+
|
|
/**
|
|
* ice_rx_flow_steer - steer the Rx flow to where application is being run
|
|
* @netdev: ptr to the netdev being adjusted
|
|
@@ -447,6 +491,10 @@ ice_rx_flow_steer(struct net_device *netdev, const struct sk_buff *skb,
|
|
continue;
|
|
|
|
fltr_info = &arfs_entry->fltr_info;
|
|
+
|
|
+ if (!ice_arfs_cmp(fltr_info, &fk, n_proto, ip_proto))
|
|
+ continue;
|
|
+
|
|
ret = fltr_info->fltr_id;
|
|
|
|
if (fltr_info->q_index == rxq_idx ||
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
|
|
index 19f730a68fa21c..ac004ef1d724d3 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
|
|
@@ -3024,7 +3024,7 @@ ice_add_update_vsi_list(struct ice_hw *hw,
|
|
u16 vsi_handle_arr[2];
|
|
|
|
/* A rule already exists with the new VSI being added */
|
|
- if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
|
|
+ if (cur_fltr->vsi_handle == new_fltr->vsi_handle)
|
|
return -EEXIST;
|
|
|
|
vsi_handle_arr[0] = cur_fltr->vsi_handle;
|
|
@@ -5991,7 +5991,7 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw,
|
|
|
|
/* A rule already exists with the new VSI being added */
|
|
if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
|
|
- return 0;
|
|
+ return -EEXIST;
|
|
|
|
/* Update the previously created VSI list set with
|
|
* the new VSI ID passed in
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
|
|
index 7417087b6db597..a2807a1e4f4a62 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
|
|
@@ -352,9 +352,12 @@ int cn10k_free_matchall_ipolicer(struct otx2_nic *pfvf)
|
|
mutex_lock(&pfvf->mbox.lock);
|
|
|
|
/* Remove RQ's policer mapping */
|
|
- for (qidx = 0; qidx < hw->rx_queues; qidx++)
|
|
- cn10k_map_unmap_rq_policer(pfvf, qidx,
|
|
- hw->matchall_ipolicer, false);
|
|
+ for (qidx = 0; qidx < hw->rx_queues; qidx++) {
|
|
+ rc = cn10k_map_unmap_rq_policer(pfvf, qidx, hw->matchall_ipolicer, false);
|
|
+ if (rc)
|
|
+ dev_warn(pfvf->dev, "Failed to unmap RQ %d's policer (error %d).",
|
|
+ qidx, rc);
|
|
+ }
|
|
|
|
rc = cn10k_free_leaf_profile(pfvf, hw->matchall_ipolicer);
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
|
|
index 164a13272faa2f..07dced3c2b1c00 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
|
|
@@ -1916,6 +1916,7 @@ static int mlx4_en_get_ts_info(struct net_device *dev,
|
|
if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
|
|
info->so_timestamping |=
|
|
SOF_TIMESTAMPING_TX_HARDWARE |
|
|
+ SOF_TIMESTAMPING_TX_SOFTWARE |
|
|
SOF_TIMESTAMPING_RX_HARDWARE |
|
|
SOF_TIMESTAMPING_RAW_HARDWARE;
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
|
|
index 21753f32786850..06b5265b6e6db2 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c
|
|
@@ -444,19 +444,22 @@ int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
|
|
{
|
|
u32 *out;
|
|
int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
|
|
+ int err;
|
|
|
|
out = kvzalloc(outlen, GFP_KERNEL);
|
|
if (!out)
|
|
return -ENOMEM;
|
|
|
|
- mlx5_query_nic_vport_context(mdev, 0, out);
|
|
+ err = mlx5_query_nic_vport_context(mdev, 0, out);
|
|
+ if (err)
|
|
+ goto out;
|
|
|
|
*node_guid = MLX5_GET64(query_nic_vport_context_out, out,
|
|
nic_vport_context.node_guid);
|
|
-
|
|
+out:
|
|
kvfree(out);
|
|
|
|
- return 0;
|
|
+ return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
|
|
|
|
@@ -498,19 +501,22 @@ int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
|
|
{
|
|
u32 *out;
|
|
int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out);
|
|
+ int err;
|
|
|
|
out = kvzalloc(outlen, GFP_KERNEL);
|
|
if (!out)
|
|
return -ENOMEM;
|
|
|
|
- mlx5_query_nic_vport_context(mdev, 0, out);
|
|
+ err = mlx5_query_nic_vport_context(mdev, 0, out);
|
|
+ if (err)
|
|
+ goto out;
|
|
|
|
*qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out,
|
|
nic_vport_context.qkey_violation_counter);
|
|
-
|
|
+out:
|
|
kvfree(out);
|
|
|
|
- return 0;
|
|
+ return err;
|
|
}
|
|
EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr);
|
|
|
|
diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c
|
|
index 72b3092d35f712..39a58c3578a028 100644
|
|
--- a/drivers/net/ethernet/microchip/lan743x_ethtool.c
|
|
+++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c
|
|
@@ -18,6 +18,8 @@
|
|
#define EEPROM_MAC_OFFSET (0x01)
|
|
#define MAX_EEPROM_SIZE (512)
|
|
#define MAX_OTP_SIZE (1024)
|
|
+#define MAX_HS_OTP_SIZE (8 * 1024)
|
|
+#define MAX_HS_EEPROM_SIZE (64 * 1024)
|
|
#define OTP_INDICATOR_1 (0xF3)
|
|
#define OTP_INDICATOR_2 (0xF7)
|
|
|
|
@@ -272,6 +274,9 @@ static int lan743x_hs_otp_read(struct lan743x_adapter *adapter, u32 offset,
|
|
int ret;
|
|
int i;
|
|
|
|
+ if (offset + length > MAX_HS_OTP_SIZE)
|
|
+ return -EINVAL;
|
|
+
|
|
ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
|
|
if (ret < 0)
|
|
return ret;
|
|
@@ -320,6 +325,9 @@ static int lan743x_hs_otp_write(struct lan743x_adapter *adapter, u32 offset,
|
|
int ret;
|
|
int i;
|
|
|
|
+ if (offset + length > MAX_HS_OTP_SIZE)
|
|
+ return -EINVAL;
|
|
+
|
|
ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
|
|
if (ret < 0)
|
|
return ret;
|
|
@@ -497,6 +505,9 @@ static int lan743x_hs_eeprom_read(struct lan743x_adapter *adapter,
|
|
u32 val;
|
|
int i;
|
|
|
|
+ if (offset + length > MAX_HS_EEPROM_SIZE)
|
|
+ return -EINVAL;
|
|
+
|
|
retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
|
|
if (retval < 0)
|
|
return retval;
|
|
@@ -539,6 +550,9 @@ static int lan743x_hs_eeprom_write(struct lan743x_adapter *adapter,
|
|
u32 val;
|
|
int i;
|
|
|
|
+ if (offset + length > MAX_HS_EEPROM_SIZE)
|
|
+ return -EINVAL;
|
|
+
|
|
retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
|
|
if (retval < 0)
|
|
return retval;
|
|
@@ -604,9 +618,9 @@ static int lan743x_ethtool_get_eeprom_len(struct net_device *netdev)
|
|
struct lan743x_adapter *adapter = netdev_priv(netdev);
|
|
|
|
if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP)
|
|
- return MAX_OTP_SIZE;
|
|
+ return adapter->is_pci11x1x ? MAX_HS_OTP_SIZE : MAX_OTP_SIZE;
|
|
|
|
- return MAX_EEPROM_SIZE;
|
|
+ return adapter->is_pci11x1x ? MAX_HS_EEPROM_SIZE : MAX_EEPROM_SIZE;
|
|
}
|
|
|
|
static int lan743x_ethtool_get_eeprom(struct net_device *netdev,
|
|
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c
|
|
index 39e1066ecd5ff0..47f2531198f62a 100644
|
|
--- a/drivers/net/ethernet/microchip/lan743x_ptp.c
|
|
+++ b/drivers/net/ethernet/microchip/lan743x_ptp.c
|
|
@@ -58,7 +58,7 @@ int lan743x_gpio_init(struct lan743x_adapter *adapter)
|
|
static void lan743x_ptp_wait_till_cmd_done(struct lan743x_adapter *adapter,
|
|
u32 bit_mask)
|
|
{
|
|
- int timeout = 1000;
|
|
+ int timeout = PTP_CMD_CTL_TIMEOUT_CNT;
|
|
u32 data = 0;
|
|
|
|
while (timeout &&
|
|
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.h b/drivers/net/ethernet/microchip/lan743x_ptp.h
|
|
index e26d4eff713361..225e8232474d73 100644
|
|
--- a/drivers/net/ethernet/microchip/lan743x_ptp.h
|
|
+++ b/drivers/net/ethernet/microchip/lan743x_ptp.h
|
|
@@ -18,9 +18,10 @@
|
|
*/
|
|
#define LAN743X_PTP_N_EVENT_CHAN 2
|
|
#define LAN743X_PTP_N_PEROUT LAN743X_PTP_N_EVENT_CHAN
|
|
-#define LAN743X_PTP_N_EXTTS 4
|
|
-#define LAN743X_PTP_N_PPS 0
|
|
#define PCI11X1X_PTP_IO_MAX_CHANNELS 8
|
|
+#define LAN743X_PTP_N_EXTTS PCI11X1X_PTP_IO_MAX_CHANNELS
|
|
+#define LAN743X_PTP_N_PPS 0
|
|
+#define PTP_CMD_CTL_TIMEOUT_CNT 50
|
|
|
|
struct lan743x_adapter;
|
|
|
|
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c
|
|
index 3ca6893d1bf26a..2869922cffe2e1 100644
|
|
--- a/drivers/net/ethernet/pensando/ionic/ionic_main.c
|
|
+++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c
|
|
@@ -464,9 +464,9 @@ static int __ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds,
|
|
unsigned long start_time;
|
|
unsigned long max_wait;
|
|
unsigned long duration;
|
|
- int done = 0;
|
|
bool fw_up;
|
|
int opcode;
|
|
+ bool done;
|
|
int err;
|
|
|
|
/* Wait for dev cmd to complete, retrying if we get EAGAIN,
|
|
@@ -474,6 +474,7 @@ static int __ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds,
|
|
*/
|
|
max_wait = jiffies + (max_seconds * HZ);
|
|
try_again:
|
|
+ done = false;
|
|
opcode = idev->opcode;
|
|
start_time = jiffies;
|
|
for (fw_up = ionic_is_fw_running(idev);
|
|
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
|
|
index c379a958380ce0..28cc23736a69bb 100644
|
|
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
|
|
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
|
|
@@ -2089,7 +2089,9 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
|
|
goto of_node_put;
|
|
|
|
ret = of_get_mac_address(port_np, port->slave.mac_addr);
|
|
- if (ret) {
|
|
+ if (ret == -EPROBE_DEFER) {
|
|
+ goto of_node_put;
|
|
+ } else if (ret) {
|
|
am65_cpsw_am654_get_efuse_macid(port_np,
|
|
port->port_id,
|
|
port->slave.mac_addr);
|
|
@@ -2949,6 +2951,16 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
|
|
return ret;
|
|
}
|
|
|
|
+ am65_cpsw_nuss_get_ver(common);
|
|
+
|
|
+ ret = am65_cpsw_nuss_init_host_p(common);
|
|
+ if (ret)
|
|
+ goto err_pm_clear;
|
|
+
|
|
+ ret = am65_cpsw_nuss_init_slave_ports(common);
|
|
+ if (ret)
|
|
+ goto err_pm_clear;
|
|
+
|
|
node = of_get_child_by_name(dev->of_node, "mdio");
|
|
if (!node) {
|
|
dev_warn(dev, "MDIO node not found\n");
|
|
@@ -2965,16 +2977,6 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
|
|
}
|
|
of_node_put(node);
|
|
|
|
- am65_cpsw_nuss_get_ver(common);
|
|
-
|
|
- ret = am65_cpsw_nuss_init_host_p(common);
|
|
- if (ret)
|
|
- goto err_of_clear;
|
|
-
|
|
- ret = am65_cpsw_nuss_init_slave_ports(common);
|
|
- if (ret)
|
|
- goto err_of_clear;
|
|
-
|
|
/* init common data */
|
|
ale_params.dev = dev;
|
|
ale_params.ale_ageout = AM65_CPSW_ALE_AGEOUT_DEFAULT;
|
|
diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c
|
|
index 060a566bc6aae1..c902f8761d5d4d 100644
|
|
--- a/drivers/net/ethernet/vertexcom/mse102x.c
|
|
+++ b/drivers/net/ethernet/vertexcom/mse102x.c
|
|
@@ -306,7 +306,7 @@ static void mse102x_dump_packet(const char *msg, int len, const char *data)
|
|
data, len, true);
|
|
}
|
|
|
|
-static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|
+static irqreturn_t mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|
{
|
|
struct sk_buff *skb;
|
|
unsigned int rxalign;
|
|
@@ -327,7 +327,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|
mse102x_tx_cmd_spi(mse, CMD_CTR);
|
|
ret = mse102x_rx_cmd_spi(mse, (u8 *)&rx);
|
|
if (ret)
|
|
- return;
|
|
+ return IRQ_NONE;
|
|
|
|
cmd_resp = be16_to_cpu(rx);
|
|
if ((cmd_resp & CMD_MASK) != CMD_RTS) {
|
|
@@ -360,7 +360,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|
rxalign = ALIGN(rxlen + DET_SOF_LEN + DET_DFT_LEN, 4);
|
|
skb = netdev_alloc_skb_ip_align(mse->ndev, rxalign);
|
|
if (!skb)
|
|
- return;
|
|
+ return IRQ_NONE;
|
|
|
|
/* 2 bytes Start of frame (before ethernet header)
|
|
* 2 bytes Data frame tail (after ethernet frame)
|
|
@@ -370,7 +370,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|
if (mse102x_rx_frame_spi(mse, rxpkt, rxlen, drop)) {
|
|
mse->ndev->stats.rx_errors++;
|
|
dev_kfree_skb(skb);
|
|
- return;
|
|
+ return IRQ_HANDLED;
|
|
}
|
|
|
|
if (netif_msg_pktdata(mse))
|
|
@@ -381,6 +381,8 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|
|
|
mse->ndev->stats.rx_packets++;
|
|
mse->ndev->stats.rx_bytes += rxlen;
|
|
+
|
|
+ return IRQ_HANDLED;
|
|
}
|
|
|
|
static int mse102x_tx_pkt_spi(struct mse102x_net *mse, struct sk_buff *txb,
|
|
@@ -512,12 +514,13 @@ static irqreturn_t mse102x_irq(int irq, void *_mse)
|
|
{
|
|
struct mse102x_net *mse = _mse;
|
|
struct mse102x_net_spi *mses = to_mse102x_spi(mse);
|
|
+ irqreturn_t ret;
|
|
|
|
mutex_lock(&mses->lock);
|
|
- mse102x_rx_pkt_spi(mse);
|
|
+ ret = mse102x_rx_pkt_spi(mse);
|
|
mutex_unlock(&mses->lock);
|
|
|
|
- return IRQ_HANDLED;
|
|
+ return ret;
|
|
}
|
|
|
|
static int mse102x_net_open(struct net_device *ndev)
|
|
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
|
|
index 74162190bccc10..8531b804021aa4 100644
|
|
--- a/drivers/net/usb/asix.h
|
|
+++ b/drivers/net/usb/asix.h
|
|
@@ -224,7 +224,6 @@ int asix_write_rx_ctl(struct usbnet *dev, u16 mode, int in_pm);
|
|
|
|
u16 asix_read_medium_status(struct usbnet *dev, int in_pm);
|
|
int asix_write_medium_mode(struct usbnet *dev, u16 mode, int in_pm);
|
|
-void asix_adjust_link(struct net_device *netdev);
|
|
|
|
int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm);
|
|
|
|
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
|
|
index 72ffc89b477ad8..7fd763917ae2cf 100644
|
|
--- a/drivers/net/usb/asix_common.c
|
|
+++ b/drivers/net/usb/asix_common.c
|
|
@@ -414,28 +414,6 @@ int asix_write_medium_mode(struct usbnet *dev, u16 mode, int in_pm)
|
|
return ret;
|
|
}
|
|
|
|
-/* set MAC link settings according to information from phylib */
|
|
-void asix_adjust_link(struct net_device *netdev)
|
|
-{
|
|
- struct phy_device *phydev = netdev->phydev;
|
|
- struct usbnet *dev = netdev_priv(netdev);
|
|
- u16 mode = 0;
|
|
-
|
|
- if (phydev->link) {
|
|
- mode = AX88772_MEDIUM_DEFAULT;
|
|
-
|
|
- if (phydev->duplex == DUPLEX_HALF)
|
|
- mode &= ~AX_MEDIUM_FD;
|
|
-
|
|
- if (phydev->speed != SPEED_100)
|
|
- mode &= ~AX_MEDIUM_PS;
|
|
- }
|
|
-
|
|
- asix_write_medium_mode(dev, mode, 0);
|
|
- phy_print_status(phydev);
|
|
- usbnet_link_change(dev, phydev->link, 0);
|
|
-}
|
|
-
|
|
int asix_write_gpio(struct usbnet *dev, u16 value, int sleep, int in_pm)
|
|
{
|
|
int ret;
|
|
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
|
|
index ec4dcf89cbedd2..119295f5f3b351 100644
|
|
--- a/drivers/net/usb/asix_devices.c
|
|
+++ b/drivers/net/usb/asix_devices.c
|
|
@@ -752,7 +752,6 @@ static void ax88772_mac_link_down(struct phylink_config *config,
|
|
struct usbnet *dev = netdev_priv(to_net_dev(config->dev));
|
|
|
|
asix_write_medium_mode(dev, 0, 0);
|
|
- usbnet_link_change(dev, false, false);
|
|
}
|
|
|
|
static void ax88772_mac_link_up(struct phylink_config *config,
|
|
@@ -783,7 +782,6 @@ static void ax88772_mac_link_up(struct phylink_config *config,
|
|
m |= AX_MEDIUM_RFC;
|
|
|
|
asix_write_medium_mode(dev, m, 0);
|
|
- usbnet_link_change(dev, true, false);
|
|
}
|
|
|
|
static const struct phylink_mac_ops ax88772_phylink_mac_ops = {
|
|
@@ -1350,10 +1348,9 @@ static const struct driver_info ax88772_info = {
|
|
.description = "ASIX AX88772 USB 2.0 Ethernet",
|
|
.bind = ax88772_bind,
|
|
.unbind = ax88772_unbind,
|
|
- .status = asix_status,
|
|
.reset = ax88772_reset,
|
|
.stop = ax88772_stop,
|
|
- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET,
|
|
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_MULTI_PACKET,
|
|
.rx_fixup = asix_rx_fixup_common,
|
|
.tx_fixup = asix_tx_fixup,
|
|
};
|
|
@@ -1362,11 +1359,9 @@ static const struct driver_info ax88772b_info = {
|
|
.description = "ASIX AX88772B USB 2.0 Ethernet",
|
|
.bind = ax88772_bind,
|
|
.unbind = ax88772_unbind,
|
|
- .status = asix_status,
|
|
.reset = ax88772_reset,
|
|
.stop = ax88772_stop,
|
|
- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
|
|
- FLAG_MULTI_PACKET,
|
|
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_MULTI_PACKET,
|
|
.rx_fixup = asix_rx_fixup_common,
|
|
.tx_fixup = asix_tx_fixup,
|
|
.data = FLAG_EEPROM_MAC,
|
|
@@ -1376,11 +1371,9 @@ static const struct driver_info lxausb_t1l_info = {
|
|
.description = "Linux Automation GmbH USB 10Base-T1L",
|
|
.bind = ax88772_bind,
|
|
.unbind = ax88772_unbind,
|
|
- .status = asix_status,
|
|
.reset = ax88772_reset,
|
|
.stop = ax88772_stop,
|
|
- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
|
|
- FLAG_MULTI_PACKET,
|
|
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_MULTI_PACKET,
|
|
.rx_fixup = asix_rx_fixup_common,
|
|
.tx_fixup = asix_tx_fixup,
|
|
.data = FLAG_EEPROM_MAC,
|
|
@@ -1412,10 +1405,8 @@ static const struct driver_info hg20f9_info = {
|
|
.description = "HG20F9 USB 2.0 Ethernet",
|
|
.bind = ax88772_bind,
|
|
.unbind = ax88772_unbind,
|
|
- .status = asix_status,
|
|
.reset = ax88772_reset,
|
|
- .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR |
|
|
- FLAG_MULTI_PACKET,
|
|
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_MULTI_PACKET,
|
|
.rx_fixup = asix_rx_fixup_common,
|
|
.tx_fixup = asix_tx_fixup,
|
|
.data = FLAG_EEPROM_MAC,
|
|
diff --git a/drivers/net/usb/ch9200.c b/drivers/net/usb/ch9200.c
|
|
index f69d9b902da04a..a206ffa76f1b93 100644
|
|
--- a/drivers/net/usb/ch9200.c
|
|
+++ b/drivers/net/usb/ch9200.c
|
|
@@ -178,6 +178,7 @@ static int ch9200_mdio_read(struct net_device *netdev, int phy_id, int loc)
|
|
{
|
|
struct usbnet *dev = netdev_priv(netdev);
|
|
unsigned char buff[2];
|
|
+ int ret;
|
|
|
|
netdev_dbg(netdev, "%s phy_id:%02x loc:%02x\n",
|
|
__func__, phy_id, loc);
|
|
@@ -185,8 +186,10 @@ static int ch9200_mdio_read(struct net_device *netdev, int phy_id, int loc)
|
|
if (phy_id != 0)
|
|
return -ENODEV;
|
|
|
|
- control_read(dev, REQUEST_READ, 0, loc * 2, buff, 0x02,
|
|
- CONTROL_TIMEOUT_MS);
|
|
+ ret = control_read(dev, REQUEST_READ, 0, loc * 2, buff, 0x02,
|
|
+ CONTROL_TIMEOUT_MS);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
return (buff[0] | buff[1] << 8);
|
|
}
|
|
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
|
|
index 2ed879a0abc6ce..1b6b6acd34894b 100644
|
|
--- a/drivers/net/vxlan/vxlan_core.c
|
|
+++ b/drivers/net/vxlan/vxlan_core.c
|
|
@@ -606,10 +606,10 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
|
|
if (rd == NULL)
|
|
return -ENOMEM;
|
|
|
|
- if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) {
|
|
- kfree(rd);
|
|
- return -ENOMEM;
|
|
- }
|
|
+ /* The driver can work correctly without a dst cache, so do not treat
|
|
+ * dst cache initialization errors as fatal.
|
|
+ */
|
|
+ dst_cache_init(&rd->dst_cache, GFP_ATOMIC | __GFP_NOWARN);
|
|
|
|
rd->remote_ip = *ip;
|
|
rd->remote_port = port;
|
|
diff --git a/drivers/net/wireless/ath/ath11k/ce.c b/drivers/net/wireless/ath/ath11k/ce.c
|
|
index e66e86bdec20ff..9d8efec46508a1 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/ce.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/ce.c
|
|
@@ -393,11 +393,10 @@ static int ath11k_ce_completed_recv_next(struct ath11k_ce_pipe *pipe,
|
|
goto err;
|
|
}
|
|
|
|
+ /* Make sure descriptor is read after the head pointer. */
|
|
+ dma_rmb();
|
|
+
|
|
*nbytes = ath11k_hal_ce_dst_status_get_length(desc);
|
|
- if (*nbytes == 0) {
|
|
- ret = -EIO;
|
|
- goto err;
|
|
- }
|
|
|
|
*skb = pipe->dest_ring->skb[sw_index];
|
|
pipe->dest_ring->skb[sw_index] = NULL;
|
|
@@ -430,8 +429,8 @@ static void ath11k_ce_recv_process_cb(struct ath11k_ce_pipe *pipe)
|
|
dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
|
|
max_nbytes, DMA_FROM_DEVICE);
|
|
|
|
- if (unlikely(max_nbytes < nbytes)) {
|
|
- ath11k_warn(ab, "rxed more than expected (nbytes %d, max %d)",
|
|
+ if (unlikely(max_nbytes < nbytes || nbytes == 0)) {
|
|
+ ath11k_warn(ab, "unexpected rx length (nbytes %d, max %d)",
|
|
nbytes, max_nbytes);
|
|
dev_kfree_skb_any(skb);
|
|
continue;
|
|
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
|
|
index 609d8387c41f3e..0e8ff839cae234 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
|
@@ -704,6 +704,52 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
|
},
|
|
};
|
|
|
|
+static const struct dmi_system_id ath11k_pm_quirk_table[] = {
|
|
+ {
|
|
+ .driver_data = (void *)ATH11K_PM_WOW,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21J4"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .driver_data = (void *)ATH11K_PM_WOW,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21K4"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .driver_data = (void *)ATH11K_PM_WOW,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21K6"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .driver_data = (void *)ATH11K_PM_WOW,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21K8"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .driver_data = (void *)ATH11K_PM_WOW,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21KA"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .driver_data = (void *)ATH11K_PM_WOW,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21F9"),
|
|
+ },
|
|
+ },
|
|
+ {}
|
|
+};
|
|
+
|
|
static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
|
|
{
|
|
WARN_ON(!ab->hw_params.single_pdev_only);
|
|
@@ -2018,8 +2064,17 @@ EXPORT_SYMBOL(ath11k_core_pre_init);
|
|
|
|
int ath11k_core_init(struct ath11k_base *ab)
|
|
{
|
|
+ const struct dmi_system_id *dmi_id;
|
|
int ret;
|
|
|
|
+ dmi_id = dmi_first_match(ath11k_pm_quirk_table);
|
|
+ if (dmi_id)
|
|
+ ab->pm_policy = (kernel_ulong_t)dmi_id->driver_data;
|
|
+ else
|
|
+ ab->pm_policy = ATH11K_PM_DEFAULT;
|
|
+
|
|
+ ath11k_dbg(ab, ATH11K_DBG_BOOT, "pm policy %u\n", ab->pm_policy);
|
|
+
|
|
ret = ath11k_core_soc_create(ab);
|
|
if (ret) {
|
|
ath11k_err(ab, "failed to create soc core: %d\n", ret);
|
|
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
|
|
index 555deafd8399ac..812a174f74c0b3 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -842,6 +842,11 @@ struct ath11k_msi_config {
|
|
u16 hw_rev;
|
|
};
|
|
|
|
+enum ath11k_pm_policy {
|
|
+ ATH11K_PM_DEFAULT,
|
|
+ ATH11K_PM_WOW,
|
|
+};
|
|
+
|
|
/* Master structure to hold the hw data which may be used in core module */
|
|
struct ath11k_base {
|
|
enum ath11k_hw_rev hw_rev;
|
|
@@ -994,6 +999,8 @@ struct ath11k_base {
|
|
} testmode;
|
|
#endif
|
|
|
|
+ enum ath11k_pm_policy pm_policy;
|
|
+
|
|
/* must be last */
|
|
u8 drv_priv[] __aligned(sizeof(void *));
|
|
};
|
|
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
index 4c70366ac56eb0..2b7bee66647286 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
|
|
@@ -2649,7 +2649,7 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
|
|
struct ath11k *ar;
|
|
struct hal_reo_dest_ring *desc;
|
|
enum hal_reo_dest_ring_push_reason push_reason;
|
|
- u32 cookie;
|
|
+ u32 cookie, info0, rx_msdu_info0, rx_mpdu_info0;
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_RADIOS; i++)
|
|
@@ -2662,11 +2662,14 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
|
|
try_again:
|
|
ath11k_hal_srng_access_begin(ab, srng);
|
|
|
|
+ /* Make sure descriptor is read after the head pointer. */
|
|
+ dma_rmb();
|
|
+
|
|
while (likely(desc =
|
|
(struct hal_reo_dest_ring *)ath11k_hal_srng_dst_get_next_entry(ab,
|
|
srng))) {
|
|
cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
|
|
- desc->buf_addr_info.info1);
|
|
+ READ_ONCE(desc->buf_addr_info.info1));
|
|
buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID,
|
|
cookie);
|
|
mac_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_PDEV_ID, cookie);
|
|
@@ -2695,8 +2698,9 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
|
|
|
|
num_buffs_reaped[mac_id]++;
|
|
|
|
+ info0 = READ_ONCE(desc->info0);
|
|
push_reason = FIELD_GET(HAL_REO_DEST_RING_INFO0_PUSH_REASON,
|
|
- desc->info0);
|
|
+ info0);
|
|
if (unlikely(push_reason !=
|
|
HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION)) {
|
|
dev_kfree_skb_any(msdu);
|
|
@@ -2704,18 +2708,21 @@ int ath11k_dp_process_rx(struct ath11k_base *ab, int ring_id,
|
|
continue;
|
|
}
|
|
|
|
- rxcb->is_first_msdu = !!(desc->rx_msdu_info.info0 &
|
|
+ rx_msdu_info0 = READ_ONCE(desc->rx_msdu_info.info0);
|
|
+ rx_mpdu_info0 = READ_ONCE(desc->rx_mpdu_info.info0);
|
|
+
|
|
+ rxcb->is_first_msdu = !!(rx_msdu_info0 &
|
|
RX_MSDU_DESC_INFO0_FIRST_MSDU_IN_MPDU);
|
|
- rxcb->is_last_msdu = !!(desc->rx_msdu_info.info0 &
|
|
+ rxcb->is_last_msdu = !!(rx_msdu_info0 &
|
|
RX_MSDU_DESC_INFO0_LAST_MSDU_IN_MPDU);
|
|
- rxcb->is_continuation = !!(desc->rx_msdu_info.info0 &
|
|
+ rxcb->is_continuation = !!(rx_msdu_info0 &
|
|
RX_MSDU_DESC_INFO0_MSDU_CONTINUATION);
|
|
rxcb->peer_id = FIELD_GET(RX_MPDU_DESC_META_DATA_PEER_ID,
|
|
- desc->rx_mpdu_info.meta_data);
|
|
+ READ_ONCE(desc->rx_mpdu_info.meta_data));
|
|
rxcb->seq_no = FIELD_GET(RX_MPDU_DESC_INFO0_SEQ_NUM,
|
|
- desc->rx_mpdu_info.info0);
|
|
+ rx_mpdu_info0);
|
|
rxcb->tid = FIELD_GET(HAL_REO_DEST_RING_INFO0_RX_QUEUE_NUM,
|
|
- desc->info0);
|
|
+ info0);
|
|
|
|
rxcb->mac_id = mac_id;
|
|
__skb_queue_tail(&msdu_list[mac_id], msdu);
|
|
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
|
|
index ae5f7e401e21b7..f32fa104ded9de 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/hal.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/hal.c
|
|
@@ -601,7 +601,7 @@ u32 ath11k_hal_ce_dst_status_get_length(void *buf)
|
|
(struct hal_ce_srng_dst_status_desc *)buf;
|
|
u32 len;
|
|
|
|
- len = FIELD_GET(HAL_CE_DST_STATUS_DESC_FLAGS_LEN, desc->flags);
|
|
+ len = FIELD_GET(HAL_CE_DST_STATUS_DESC_FLAGS_LEN, READ_ONCE(desc->flags));
|
|
desc->flags &= ~HAL_CE_DST_STATUS_DESC_FLAGS_LEN;
|
|
|
|
return len;
|
|
@@ -802,7 +802,7 @@ void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng)
|
|
srng->u.src_ring.cached_tp =
|
|
*(volatile u32 *)srng->u.src_ring.tp_addr;
|
|
} else {
|
|
- srng->u.dst_ring.cached_hp = *srng->u.dst_ring.hp_addr;
|
|
+ srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
|
|
|
|
/* Try to prefetch the next descriptor in the ring */
|
|
if (srng->flags & HAL_SRNG_FLAGS_CACHED)
|
|
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
|
|
index fa46e645009cf6..91e31f30d2c80f 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
|
@@ -1989,6 +1989,15 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
|
chunk->prev_size == chunk->size)
|
|
continue;
|
|
|
|
+ if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
|
|
+ ath11k_dbg(ab, ATH11K_DBG_QMI,
|
|
+ "size/type mismatch (current %d %u) (prev %d %u), try later with small size\n",
|
|
+ chunk->size, chunk->type,
|
|
+ chunk->prev_size, chunk->prev_type);
|
|
+ ab->qmi.target_mem_delayed = true;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
/* cannot reuse the existing chunk */
|
|
dma_free_coherent(ab->dev, chunk->prev_size,
|
|
chunk->vaddr, chunk->paddr);
|
|
diff --git a/drivers/net/wireless/ath/ath12k/ce.c b/drivers/net/wireless/ath/ath12k/ce.c
|
|
index be0d669d31fcce..740586fe49d1f9 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/ce.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/ce.c
|
|
@@ -343,11 +343,10 @@ static int ath12k_ce_completed_recv_next(struct ath12k_ce_pipe *pipe,
|
|
goto err;
|
|
}
|
|
|
|
+ /* Make sure descriptor is read after the head pointer. */
|
|
+ dma_rmb();
|
|
+
|
|
*nbytes = ath12k_hal_ce_dst_status_get_length(desc);
|
|
- if (*nbytes == 0) {
|
|
- ret = -EIO;
|
|
- goto err;
|
|
- }
|
|
|
|
*skb = pipe->dest_ring->skb[sw_index];
|
|
pipe->dest_ring->skb[sw_index] = NULL;
|
|
@@ -380,8 +379,8 @@ static void ath12k_ce_recv_process_cb(struct ath12k_ce_pipe *pipe)
|
|
dma_unmap_single(ab->dev, ATH12K_SKB_RXCB(skb)->paddr,
|
|
max_nbytes, DMA_FROM_DEVICE);
|
|
|
|
- if (unlikely(max_nbytes < nbytes)) {
|
|
- ath12k_warn(ab, "rxed more than expected (nbytes %d, max %d)",
|
|
+ if (unlikely(max_nbytes < nbytes || nbytes == 0)) {
|
|
+ ath12k_warn(ab, "unexpected rx length (nbytes %d, max %d)",
|
|
nbytes, max_nbytes);
|
|
dev_kfree_skb_any(skb);
|
|
continue;
|
|
diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h
|
|
index 857bc5f9e946a9..f9547a3945e44b 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/ce.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/ce.h
|
|
@@ -1,7 +1,7 @@
|
|
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
|
/*
|
|
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
|
- * Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ * Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef ATH12K_CE_H
|
|
@@ -39,8 +39,8 @@
|
|
#define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */
|
|
|
|
/* CE address/mask */
|
|
-#define CE_HOST_IE_ADDRESS 0x00A1803C
|
|
-#define CE_HOST_IE_2_ADDRESS 0x00A18040
|
|
+#define CE_HOST_IE_ADDRESS 0x75804C
|
|
+#define CE_HOST_IE_2_ADDRESS 0x758050
|
|
#define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS
|
|
|
|
#define CE_HOST_IE_3_SHIFT 0xC
|
|
diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c
|
|
index 35f22a4a16cf20..69bf75ebd7518a 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/dp_mon.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/dp_mon.c
|
|
@@ -1077,6 +1077,8 @@ static void ath12k_dp_mon_rx_deliver_msdu(struct ath12k *ar, struct napi_struct
|
|
bool is_mcbc = rxcb->is_mcbc;
|
|
bool is_eapol_tkip = rxcb->is_eapol;
|
|
|
|
+ status->link_valid = 0;
|
|
+
|
|
if ((status->encoding == RX_ENC_HE) && !(status->flag & RX_FLAG_RADIOTAP_HE) &&
|
|
!(status->flag & RX_FLAG_SKIP_MONITOR)) {
|
|
he = skb_push(msdu, sizeof(known));
|
|
diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
|
|
index 0b5a91ab0df49c..169e16c6ed650f 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/hal.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/hal.c
|
|
@@ -1565,7 +1565,7 @@ u32 ath12k_hal_ce_dst_status_get_length(struct hal_ce_srng_dst_status_desc *desc
|
|
{
|
|
u32 len;
|
|
|
|
- len = le32_get_bits(desc->flags, HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
|
|
+ len = le32_get_bits(READ_ONCE(desc->flags), HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
|
|
desc->flags &= ~cpu_to_le32(HAL_CE_DST_STATUS_DESC_FLAGS_LEN);
|
|
|
|
return len;
|
|
@@ -1734,7 +1734,7 @@ void ath12k_hal_srng_access_begin(struct ath12k_base *ab, struct hal_srng *srng)
|
|
srng->u.src_ring.cached_tp =
|
|
*(volatile u32 *)srng->u.src_ring.tp_addr;
|
|
else
|
|
- srng->u.dst_ring.cached_hp = *srng->u.dst_ring.hp_addr;
|
|
+ srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr);
|
|
}
|
|
|
|
/* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin()
|
|
diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h
|
|
index 1bb840c2bef577..5fd9232ad101ee 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/hal_desc.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/hal_desc.h
|
|
@@ -683,7 +683,7 @@ enum hal_rx_msdu_desc_reo_dest_ind {
|
|
#define RX_MSDU_DESC_INFO0_DECAP_FORMAT GENMASK(30, 29)
|
|
|
|
#define HAL_RX_MSDU_PKT_LENGTH_GET(val) \
|
|
- (u32_get_bits((val), RX_MSDU_DESC_INFO0_MSDU_LENGTH))
|
|
+ (le32_get_bits((val), RX_MSDU_DESC_INFO0_MSDU_LENGTH))
|
|
|
|
struct rx_msdu_desc {
|
|
__le32 info0;
|
|
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
|
|
index 5fd80f90ecafed..7dfbabf0637d23 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/pci.c
|
|
@@ -1153,6 +1153,9 @@ void ath12k_pci_power_down(struct ath12k_base *ab)
|
|
{
|
|
struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
|
|
|
|
+ if (!test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags))
|
|
+ return;
|
|
+
|
|
/* restore aspm in case firmware bootup fails */
|
|
ath12k_pci_aspm_restore(ab_pci);
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
|
|
index a0ac2f350934f9..958ac4ed5c3491 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
|
|
@@ -951,14 +951,24 @@ int ath12k_wmi_vdev_down(struct ath12k *ar, u8 vdev_id)
|
|
static void ath12k_wmi_put_wmi_channel(struct ath12k_wmi_channel_params *chan,
|
|
struct wmi_vdev_start_req_arg *arg)
|
|
{
|
|
+ u32 center_freq1 = arg->band_center_freq1;
|
|
+
|
|
memset(chan, 0, sizeof(*chan));
|
|
|
|
chan->mhz = cpu_to_le32(arg->freq);
|
|
- chan->band_center_freq1 = cpu_to_le32(arg->band_center_freq1);
|
|
- if (arg->mode == MODE_11AC_VHT80_80)
|
|
+ chan->band_center_freq1 = cpu_to_le32(center_freq1);
|
|
+ if (arg->mode == MODE_11BE_EHT160) {
|
|
+ if (arg->freq > center_freq1)
|
|
+ chan->band_center_freq1 = cpu_to_le32(center_freq1 + 40);
|
|
+ else
|
|
+ chan->band_center_freq1 = cpu_to_le32(center_freq1 - 40);
|
|
+
|
|
+ chan->band_center_freq2 = cpu_to_le32(center_freq1);
|
|
+ } else if (arg->mode == MODE_11BE_EHT80_80) {
|
|
chan->band_center_freq2 = cpu_to_le32(arg->band_center_freq2);
|
|
- else
|
|
+ } else {
|
|
chan->band_center_freq2 = 0;
|
|
+ }
|
|
|
|
chan->info |= le32_encode_bits(arg->mode, WMI_CHAN_INFO_MODE);
|
|
if (arg->passive)
|
|
@@ -5503,7 +5513,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
|
|
goto fallback;
|
|
}
|
|
|
|
- spin_lock(&ab->base_lock);
|
|
+ spin_lock_bh(&ab->base_lock);
|
|
if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {
|
|
/* Once mac is registered, ar is valid and all CC events from
|
|
* fw is considered to be received due to user requests
|
|
@@ -5527,7 +5537,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
|
|
ab->default_regd[pdev_idx] = regd;
|
|
}
|
|
ab->dfs_region = reg_info->dfs_region;
|
|
- spin_unlock(&ab->base_lock);
|
|
+ spin_unlock_bh(&ab->base_lock);
|
|
|
|
goto mem_free;
|
|
|
|
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
|
|
index a5265997b5767c..debac4699687e1 100644
|
|
--- a/drivers/net/wireless/ath/carl9170/usb.c
|
|
+++ b/drivers/net/wireless/ath/carl9170/usb.c
|
|
@@ -438,14 +438,21 @@ static void carl9170_usb_rx_complete(struct urb *urb)
|
|
|
|
if (atomic_read(&ar->rx_anch_urbs) == 0) {
|
|
/*
|
|
- * The system is too slow to cope with
|
|
- * the enormous workload. We have simply
|
|
- * run out of active rx urbs and this
|
|
- * unfortunately leads to an unpredictable
|
|
- * device.
|
|
+ * At this point, either the system is too slow to
|
|
+ * cope with the enormous workload (so we have simply
|
|
+ * run out of active rx urbs and this unfortunately
|
|
+ * leads to an unpredictable device), or the device
|
|
+ * is not fully functional after an unsuccessful
|
|
+ * firmware loading attempts (so it doesn't pass
|
|
+ * ieee80211_register_hw() and there is no internal
|
|
+ * workqueue at all).
|
|
*/
|
|
|
|
- ieee80211_queue_work(ar->hw, &ar->ping_work);
|
|
+ if (ar->registered)
|
|
+ ieee80211_queue_work(ar->hw, &ar->ping_work);
|
|
+ else
|
|
+ pr_warn_once("device %s is not registered\n",
|
|
+ dev_name(&ar->udev->dev));
|
|
}
|
|
} else {
|
|
/*
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
|
|
index d594694206b33a..906f2790f56197 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
|
|
@@ -44,6 +44,8 @@
|
|
IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode"
|
|
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
|
IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
|
+#define IWL_QU_C_JF_B_MODULE_FIRMWARE(api) \
|
|
+ IWL_QU_C_JF_B_FW_PRE "-" __stringify(api) ".ucode"
|
|
#define IWL_CC_A_MODULE_FIRMWARE(api) \
|
|
IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode"
|
|
|
|
@@ -423,6 +425,7 @@ const struct iwl_cfg iwl_cfg_quz_a0_hr_b0 = {
|
|
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
+MODULE_FIRMWARE(IWL_QU_C_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
|
|
index e9807fcca6ad10..5c2e8d28839765 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
|
|
@@ -2701,6 +2701,8 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
|
|
for (i = 0; i < trans->num_rx_queues && pos < bufsz; i++) {
|
|
struct iwl_rxq *rxq = &trans_pcie->rxq[i];
|
|
|
|
+ spin_lock_bh(&rxq->lock);
|
|
+
|
|
pos += scnprintf(buf + pos, bufsz - pos, "queue#: %2d\n",
|
|
i);
|
|
pos += scnprintf(buf + pos, bufsz - pos, "\tread: %u\n",
|
|
@@ -2721,6 +2723,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
|
|
pos += scnprintf(buf + pos, bufsz - pos,
|
|
"\tclosed_rb_num: Not Allocated\n");
|
|
}
|
|
+ spin_unlock_bh(&rxq->lock);
|
|
}
|
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
|
kfree(buf);
|
|
@@ -3385,8 +3388,11 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans,
|
|
/* Dump RBs is supported only for pre-9000 devices (1 queue) */
|
|
struct iwl_rxq *rxq = &trans_pcie->rxq[0];
|
|
/* RBs */
|
|
+ spin_lock_bh(&rxq->lock);
|
|
num_rbs = iwl_get_closed_rb_stts(trans, rxq);
|
|
num_rbs = (num_rbs - rxq->read) & RX_QUEUE_MASK;
|
|
+ spin_unlock_bh(&rxq->lock);
|
|
+
|
|
len += num_rbs * (sizeof(*data) +
|
|
sizeof(struct iwl_fw_error_dump_rb) +
|
|
(PAGE_SIZE << trans_pcie->rx_page_order));
|
|
diff --git a/drivers/net/wireless/intersil/p54/fwio.c b/drivers/net/wireless/intersil/p54/fwio.c
|
|
index b52cce38115d0a..06e5df90b43ece 100644
|
|
--- a/drivers/net/wireless/intersil/p54/fwio.c
|
|
+++ b/drivers/net/wireless/intersil/p54/fwio.c
|
|
@@ -231,6 +231,7 @@ int p54_download_eeprom(struct p54_common *priv, void *buf,
|
|
|
|
mutex_lock(&priv->eeprom_mutex);
|
|
priv->eeprom = buf;
|
|
+ priv->eeprom_slice_size = len;
|
|
eeprom_hdr = skb_put(skb, eeprom_hdr_size + len);
|
|
|
|
if (priv->fw_var < 0x509) {
|
|
@@ -253,6 +254,7 @@ int p54_download_eeprom(struct p54_common *priv, void *buf,
|
|
ret = -EBUSY;
|
|
}
|
|
priv->eeprom = NULL;
|
|
+ priv->eeprom_slice_size = 0;
|
|
mutex_unlock(&priv->eeprom_mutex);
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/net/wireless/intersil/p54/p54.h b/drivers/net/wireless/intersil/p54/p54.h
|
|
index 3356ea708d8163..97fc863fef810f 100644
|
|
--- a/drivers/net/wireless/intersil/p54/p54.h
|
|
+++ b/drivers/net/wireless/intersil/p54/p54.h
|
|
@@ -258,6 +258,7 @@ struct p54_common {
|
|
|
|
/* eeprom handling */
|
|
void *eeprom;
|
|
+ size_t eeprom_slice_size;
|
|
struct completion eeprom_comp;
|
|
struct mutex eeprom_mutex;
|
|
};
|
|
diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c
|
|
index 8414aa208655f6..2deb1bb54f24bd 100644
|
|
--- a/drivers/net/wireless/intersil/p54/txrx.c
|
|
+++ b/drivers/net/wireless/intersil/p54/txrx.c
|
|
@@ -496,14 +496,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv,
|
|
return ;
|
|
|
|
if (priv->fw_var >= 0x509) {
|
|
- memcpy(priv->eeprom, eeprom->v2.data,
|
|
- le16_to_cpu(eeprom->v2.len));
|
|
+ if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size)
|
|
+ return;
|
|
+
|
|
+ memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size);
|
|
} else {
|
|
- memcpy(priv->eeprom, eeprom->v1.data,
|
|
- le16_to_cpu(eeprom->v1.len));
|
|
+ if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size)
|
|
+ return;
|
|
+
|
|
+ memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size);
|
|
}
|
|
|
|
priv->eeprom = NULL;
|
|
+ priv->eeprom_slice_size = 0;
|
|
tmp = p54_find_and_unlink_skb(priv, hdr->req_id);
|
|
dev_kfree_skb_any(tmp);
|
|
complete(&priv->eeprom_comp);
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
|
|
index 70d3895762b4cd..00248e2b21ea70 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
|
|
@@ -17,6 +17,8 @@ static const struct usb_device_id mt76x2u_device_table[] = {
|
|
{ USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
|
|
{ USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
|
|
{ USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */
|
|
+ { USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */
|
|
+ { USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */
|
|
{ USB_DEVICE(0x2c4e, 0x0103) }, /* Mercury UD13 */
|
|
{ USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */
|
|
{ USB_DEVICE(0x045e, 0x02e6) }, /* XBox One Wireless Adapter */
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
|
|
index 33a14365ec9b98..3b556281151158 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
|
|
@@ -191,6 +191,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
|
|
{
|
|
struct ieee80211_hw *hw = mt76_hw(dev);
|
|
struct mt76_usb *usb = &dev->mt76.usb;
|
|
+ bool vht;
|
|
int err;
|
|
|
|
INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate);
|
|
@@ -217,7 +218,17 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
|
|
|
|
/* check hw sg support in order to enable AMSDU */
|
|
hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1;
|
|
- err = mt76_register_device(&dev->mt76, true, mt76x02_rates,
|
|
+ switch (dev->mt76.rev) {
|
|
+ case 0x76320044:
|
|
+ /* these ASIC revisions do not support VHT */
|
|
+ vht = false;
|
|
+ break;
|
|
+ default:
|
|
+ vht = true;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ err = mt76_register_device(&dev->mt76, vht, mt76x02_rates,
|
|
ARRAY_SIZE(mt76x02_rates));
|
|
if (err)
|
|
goto fail;
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
|
|
index 31ef58e2a3d2a3..8e2ec395633171 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
|
|
@@ -83,6 +83,11 @@ mt7921_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band,
|
|
he_cap_elem->phy_cap_info[9] |=
|
|
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
|
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
|
|
+
|
|
+ if (is_mt7922(phy->mt76->dev)) {
|
|
+ he_cap_elem->phy_cap_info[0] |=
|
|
+ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
|
+ }
|
|
break;
|
|
case NL80211_IFTYPE_STATION:
|
|
he_cap_elem->mac_cap_info[1] |=
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
|
|
index 35d9673ec0d8fc..8fa16f95e6a7b3 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
|
|
@@ -650,6 +650,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
|
|
status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
|
|
}
|
|
|
|
+ /* IEEE 802.11 fragmentation can only be applied to unicast frames.
|
|
+ * Hence, drop fragments with multicast/broadcast RA.
|
|
+ * This check fixes vulnerabilities, like CVE-2020-26145.
|
|
+ */
|
|
+ if ((ieee80211_has_morefrags(fc) || seq_ctrl & IEEE80211_SCTL_FRAG) &&
|
|
+ FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) != MT_RXD3_NORMAL_U2M)
|
|
+ return -EINVAL;
|
|
+
|
|
hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;
|
|
if (hdr_trans && ieee80211_has_morefrags(fc)) {
|
|
if (mt7996_reverse_frag0_hdr_trans(skb, hdr_gap))
|
|
diff --git a/drivers/net/wireless/purelifi/plfxlc/usb.c b/drivers/net/wireless/purelifi/plfxlc/usb.c
|
|
index 311676c1ece0ac..8151bc5e00ccc8 100644
|
|
--- a/drivers/net/wireless/purelifi/plfxlc/usb.c
|
|
+++ b/drivers/net/wireless/purelifi/plfxlc/usb.c
|
|
@@ -503,8 +503,10 @@ int plfxlc_usb_wreq_async(struct plfxlc_usb *usb, const u8 *buffer,
|
|
(void *)buffer, buffer_len, complete_fn, context);
|
|
|
|
r = usb_submit_urb(urb, GFP_ATOMIC);
|
|
- if (r)
|
|
+ if (r) {
|
|
+ usb_free_urb(urb);
|
|
dev_err(&udev->dev, "Async write submit failed (%d)\n", r);
|
|
+ }
|
|
|
|
return r;
|
|
}
|
|
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
|
|
index 3abd0c4c954bc1..3645f212021f92 100644
|
|
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
|
|
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
|
|
@@ -155,6 +155,16 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
|
|
if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE &&
|
|
init_aspm == 0x43)
|
|
ppsc->support_aspm = false;
|
|
+
|
|
+ /* RTL8723BE found on some ASUSTek laptops, such as F441U and
|
|
+ * X555UQ with subsystem ID 11ad:1723 are known to output large
|
|
+ * amounts of PCIe AER errors during and after boot up, causing
|
|
+ * heavy lags, poor network throughput, and occasional lock-ups.
|
|
+ */
|
|
+ if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8723BE &&
|
|
+ (rtlpci->pdev->subsystem_vendor == 0x11ad &&
|
|
+ rtlpci->pdev->subsystem_device == 0x1723))
|
|
+ ppsc->support_aspm = false;
|
|
}
|
|
|
|
static bool _rtl_pci_platform_switch_device_pci_aspm(
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
index 8f1d653282b7ec..eba3a2ee747f9c 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/usb.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
@@ -133,7 +133,7 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
|
|
|
|
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
|
RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
|
|
- addr, 0, data, len, 30000);
|
|
+ addr, 0, data, len, 500);
|
|
if (ret < 0 && ret != -ENODEV && count++ < 4)
|
|
rtw_err(rtwdev, "write register 0x%x failed with %d\n",
|
|
addr, ret);
|
|
diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c
|
|
index f5301c2bbf133d..9a0ffaddb83606 100644
|
|
--- a/drivers/net/wireless/realtek/rtw89/cam.c
|
|
+++ b/drivers/net/wireless/realtek/rtw89/cam.c
|
|
@@ -6,6 +6,7 @@
|
|
#include "debug.h"
|
|
#include "fw.h"
|
|
#include "mac.h"
|
|
+#include "ps.h"
|
|
|
|
static struct sk_buff *
|
|
rtw89_cam_get_sec_key_cmd(struct rtw89_dev *rtwdev,
|
|
@@ -333,9 +334,11 @@ int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev,
|
|
|
|
switch (key->cipher) {
|
|
case WLAN_CIPHER_SUITE_WEP40:
|
|
+ rtw89_leave_ips_by_hwflags(rtwdev);
|
|
hw_key_type = RTW89_SEC_KEY_TYPE_WEP40;
|
|
break;
|
|
case WLAN_CIPHER_SUITE_WEP104:
|
|
+ rtw89_leave_ips_by_hwflags(rtwdev);
|
|
hw_key_type = RTW89_SEC_KEY_TYPE_WEP104;
|
|
break;
|
|
case WLAN_CIPHER_SUITE_CCMP:
|
|
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
|
|
index 30cc6e03c355e8..33b2543ee4d230 100644
|
|
--- a/drivers/net/wireless/realtek/rtw89/pci.c
|
|
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
|
|
@@ -1822,22 +1822,87 @@ static int rtw89_write16_mdio_clr(struct rtw89_dev *rtwdev, u8 addr, u16 mask, u
|
|
return 0;
|
|
}
|
|
|
|
+static int rtw89_dbi_write8(struct rtw89_dev *rtwdev, u16 addr, u8 data)
|
|
+{
|
|
+ u16 addr_2lsb = addr & B_AX_DBI_2LSB;
|
|
+ u16 write_addr;
|
|
+ u8 flag;
|
|
+ int ret;
|
|
+
|
|
+ write_addr = addr & B_AX_DBI_ADDR_MSK;
|
|
+ write_addr |= u16_encode_bits(BIT(addr_2lsb), B_AX_DBI_WREN_MSK);
|
|
+ rtw89_write8(rtwdev, R_AX_DBI_WDATA + addr_2lsb, data);
|
|
+ rtw89_write16(rtwdev, R_AX_DBI_FLAG, write_addr);
|
|
+ rtw89_write8(rtwdev, R_AX_DBI_FLAG + 2, B_AX_DBI_WFLAG >> 16);
|
|
+
|
|
+ ret = read_poll_timeout_atomic(rtw89_read8, flag, !flag, 10,
|
|
+ 10 * RTW89_PCI_WR_RETRY_CNT, false,
|
|
+ rtwdev, R_AX_DBI_FLAG + 2);
|
|
+ if (ret)
|
|
+ rtw89_err(rtwdev, "failed to write DBI register, addr=0x%X\n",
|
|
+ addr);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int rtw89_dbi_read8(struct rtw89_dev *rtwdev, u16 addr, u8 *value)
|
|
+{
|
|
+ u16 read_addr = addr & B_AX_DBI_ADDR_MSK;
|
|
+ u8 flag;
|
|
+ int ret;
|
|
+
|
|
+ rtw89_write16(rtwdev, R_AX_DBI_FLAG, read_addr);
|
|
+ rtw89_write8(rtwdev, R_AX_DBI_FLAG + 2, B_AX_DBI_RFLAG >> 16);
|
|
+
|
|
+ ret = read_poll_timeout_atomic(rtw89_read8, flag, !flag, 10,
|
|
+ 10 * RTW89_PCI_WR_RETRY_CNT, false,
|
|
+ rtwdev, R_AX_DBI_FLAG + 2);
|
|
+ if (ret) {
|
|
+ rtw89_err(rtwdev, "failed to read DBI register, addr=0x%X\n",
|
|
+ addr);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ read_addr = R_AX_DBI_RDATA + (addr & 3);
|
|
+ *value = rtw89_read8(rtwdev, read_addr);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int rtw89_pci_write_config_byte(struct rtw89_dev *rtwdev, u16 addr,
|
|
u8 data)
|
|
{
|
|
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
|
|
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
|
struct pci_dev *pdev = rtwpci->pdev;
|
|
+ int ret;
|
|
+
|
|
+ ret = pci_write_config_byte(pdev, addr, data);
|
|
+ if (!ret)
|
|
+ return 0;
|
|
|
|
- return pci_write_config_byte(pdev, addr, data);
|
|
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B)
|
|
+ ret = rtw89_dbi_write8(rtwdev, addr, data);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int rtw89_pci_read_config_byte(struct rtw89_dev *rtwdev, u16 addr,
|
|
u8 *value)
|
|
{
|
|
struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
|
|
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
|
|
struct pci_dev *pdev = rtwpci->pdev;
|
|
+ int ret;
|
|
|
|
- return pci_read_config_byte(pdev, addr, value);
|
|
+ ret = pci_read_config_byte(pdev, addr, value);
|
|
+ if (!ret)
|
|
+ return 0;
|
|
+
|
|
+ if (chip_id == RTL8852A || chip_id == RTL8852B || chip_id == RTL8851B)
|
|
+ ret = rtw89_dbi_read8(rtwdev, addr, value);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int rtw89_pci_config_byte_set(struct rtw89_dev *rtwdev, u16 addr,
|
|
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
|
|
index 4259b79b138fb4..119c0608b91a8a 100644
|
|
--- a/drivers/net/wireless/realtek/rtw89/pci.h
|
|
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
|
|
@@ -42,6 +42,7 @@
|
|
#define B_AX_DBI_WFLAG BIT(16)
|
|
#define B_AX_DBI_WREN_MSK GENMASK(15, 12)
|
|
#define B_AX_DBI_ADDR_MSK GENMASK(11, 2)
|
|
+#define B_AX_DBI_2LSB GENMASK(1, 0)
|
|
#define R_AX_DBI_WDATA 0x1094
|
|
#define R_AX_DBI_RDATA 0x1098
|
|
|
|
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
index d86a1bd7aab089..f5f48f7e6d26e3 100644
|
|
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
@@ -1201,6 +1201,11 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
|
|
/* MLD not supported here */
|
|
u32 bcn_int = data->link_data[0].beacon_int;
|
|
u64 delta = abs(tsf - now);
|
|
+ struct ieee80211_bss_conf *conf;
|
|
+
|
|
+ conf = link_conf_dereference_protected(vif, data->link_data[0].link_id);
|
|
+ if (conf && !conf->enable_beacon)
|
|
+ return;
|
|
|
|
/* adjust after beaconing with new timestamp at old TBTT */
|
|
if (tsf > now) {
|
|
diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
|
|
index a87dab9abba26f..08fb16918043f4 100644
|
|
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
|
|
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
|
|
@@ -294,13 +294,14 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
|
|
struct cdns_pcie *pcie = &ep->pcie;
|
|
u32 cap = CDNS_PCIE_EP_FUNC_MSIX_CAP_OFFSET;
|
|
u32 val, reg;
|
|
+ u16 actual_interrupts = interrupts + 1;
|
|
|
|
fn = cdns_pcie_get_fn_from_vfn(pcie, fn, vfn);
|
|
|
|
reg = cap + PCI_MSIX_FLAGS;
|
|
val = cdns_pcie_ep_fn_readw(pcie, fn, reg);
|
|
val &= ~PCI_MSIX_FLAGS_QSIZE;
|
|
- val |= interrupts;
|
|
+ val |= interrupts; /* 0's based value */
|
|
cdns_pcie_ep_fn_writew(pcie, fn, reg, val);
|
|
|
|
/* Set MSIX BAR and offset */
|
|
@@ -310,7 +311,7 @@ static int cdns_pcie_ep_set_msix(struct pci_epc *epc, u8 fn, u8 vfn,
|
|
|
|
/* Set PBA BAR and offset. BAR must match MSIX BAR */
|
|
reg = cap + PCI_MSIX_PBA;
|
|
- val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
|
|
+ val = (offset + (actual_interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;
|
|
cdns_pcie_ep_fn_writel(pcie, fn, reg, val);
|
|
|
|
return 0;
|
|
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
|
|
index 9b1256da096cb6..8af7a837a0612c 100644
|
|
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
|
|
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
|
|
@@ -275,8 +275,8 @@ static int rockchip_pcie_phy_init(struct rockchip_pcie *rockchip)
|
|
|
|
static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)
|
|
{
|
|
- phy_exit(rockchip->phy);
|
|
phy_power_off(rockchip->phy);
|
|
+ phy_exit(rockchip->phy);
|
|
}
|
|
|
|
static const struct dw_pcie_ops dw_pcie_ops = {
|
|
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
|
|
index 503304aba9eac1..4541dfbf0e1b63 100644
|
|
--- a/drivers/pci/pci.c
|
|
+++ b/drivers/pci/pci.c
|
|
@@ -5823,7 +5823,8 @@ static void pci_slot_unlock(struct pci_slot *slot)
|
|
continue;
|
|
if (dev->subordinate)
|
|
pci_bus_unlock(dev->subordinate);
|
|
- pci_dev_unlock(dev);
|
|
+ else
|
|
+ pci_dev_unlock(dev);
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index 70f484b811dea7..d67ea16e69e6ac 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -4988,6 +4988,18 @@ static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
|
|
PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
|
|
}
|
|
|
|
+static int pci_quirk_loongson_acs(struct pci_dev *dev, u16 acs_flags)
|
|
+{
|
|
+ /*
|
|
+ * Loongson PCIe Root Ports don't advertise an ACS capability, but
|
|
+ * they do not allow peer-to-peer transactions between Root Ports.
|
|
+ * Allow each Root Port to be in a separate IOMMU group by masking
|
|
+ * SV/RR/CR/UF bits.
|
|
+ */
|
|
+ return pci_acs_ctrl_enabled(acs_flags,
|
|
+ PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
|
|
+}
|
|
+
|
|
/*
|
|
* Wangxun 40G/25G/10G/1G NICs have no ACS capability, but on
|
|
* multi-function devices, the hardware isolates the functions by
|
|
@@ -5121,6 +5133,17 @@ static const struct pci_dev_acs_enabled {
|
|
{ PCI_VENDOR_ID_BROADCOM, 0x1762, pci_quirk_mf_endpoint_acs },
|
|
{ PCI_VENDOR_ID_BROADCOM, 0x1763, pci_quirk_mf_endpoint_acs },
|
|
{ PCI_VENDOR_ID_BROADCOM, 0xD714, pci_quirk_brcm_acs },
|
|
+ /* Loongson PCIe Root Ports */
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x3C09, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x3C19, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x3C29, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x7A09, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x7A19, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x7A29, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x7A39, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x7A49, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x7A59, pci_quirk_loongson_acs },
|
|
+ { PCI_VENDOR_ID_LOONGSON, 0x7A69, pci_quirk_loongson_acs },
|
|
/* Amazon Annapurna Labs */
|
|
{ PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031, pci_quirk_al_acs },
|
|
/* Zhaoxin multi-function devices */
|
|
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
|
|
index adc6394626ce83..f914f016b3d2ce 100644
|
|
--- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
|
|
+++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
|
|
@@ -95,12 +95,12 @@ static u32 phy_tx_preemp_amp_tune_from_property(u32 microamp)
|
|
static u32 phy_tx_vboost_level_from_property(u32 microvolt)
|
|
{
|
|
switch (microvolt) {
|
|
- case 0 ... 960:
|
|
- return 0;
|
|
- case 961 ... 1160:
|
|
- return 2;
|
|
- default:
|
|
+ case 1156:
|
|
+ return 5;
|
|
+ case 844:
|
|
return 3;
|
|
+ default:
|
|
+ return 4;
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
|
|
index 1a39fd97a9005a..ef87a6045e073a 100644
|
|
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
|
|
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
|
|
@@ -358,9 +358,7 @@ static int armada_37xx_pmx_set_by_name(struct pinctrl_dev *pctldev,
|
|
|
|
val = grp->val[func];
|
|
|
|
- regmap_update_bits(info->regmap, reg, mask, val);
|
|
-
|
|
- return 0;
|
|
+ return regmap_update_bits(info->regmap, reg, mask, val);
|
|
}
|
|
|
|
static int armada_37xx_pmx_set(struct pinctrl_dev *pctldev,
|
|
@@ -402,10 +400,13 @@ static int armada_37xx_gpio_get_direction(struct gpio_chip *chip,
|
|
struct armada_37xx_pinctrl *info = gpiochip_get_data(chip);
|
|
unsigned int reg = OUTPUT_EN;
|
|
unsigned int val, mask;
|
|
+ int ret;
|
|
|
|
armada_37xx_update_reg(®, &offset);
|
|
mask = BIT(offset);
|
|
- regmap_read(info->regmap, reg, &val);
|
|
+ ret = regmap_read(info->regmap, reg, &val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
if (val & mask)
|
|
return GPIO_LINE_DIRECTION_OUT;
|
|
@@ -442,11 +443,14 @@ static int armada_37xx_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
|
struct armada_37xx_pinctrl *info = gpiochip_get_data(chip);
|
|
unsigned int reg = INPUT_VAL;
|
|
unsigned int val, mask;
|
|
+ int ret;
|
|
|
|
armada_37xx_update_reg(®, &offset);
|
|
mask = BIT(offset);
|
|
|
|
- regmap_read(info->regmap, reg, &val);
|
|
+ ret = regmap_read(info->regmap, reg, &val);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
return (val & mask) != 0;
|
|
}
|
|
@@ -471,16 +475,17 @@ static int armada_37xx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
|
|
{
|
|
struct armada_37xx_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
|
|
struct gpio_chip *chip = range->gc;
|
|
+ int ret;
|
|
|
|
dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n",
|
|
offset, range->name, offset, input ? "input" : "output");
|
|
|
|
if (input)
|
|
- armada_37xx_gpio_direction_input(chip, offset);
|
|
+ ret = armada_37xx_gpio_direction_input(chip, offset);
|
|
else
|
|
- armada_37xx_gpio_direction_output(chip, offset, 0);
|
|
+ ret = armada_37xx_gpio_direction_output(chip, offset, 0);
|
|
|
|
- return 0;
|
|
+ return ret;
|
|
}
|
|
|
|
static int armada_37xx_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
|
|
index fd97b6ee2a8d11..ca45c1f36a89bd 100644
|
|
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
|
|
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
|
|
@@ -612,6 +612,14 @@ int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
|
|
|
|
mcp->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
|
|
|
+ /*
|
|
+ * Reset the chip - we don't really know what state it's in, so reset
|
|
+ * all pins to input first to prevent surprises.
|
|
+ */
|
|
+ ret = mcp_write(mcp, MCP_IODIR, mcp->chip.ngpio == 16 ? 0xFFFF : 0xFF);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
|
|
* and MCP_IOCON.HAEN = 1, so we work with all chips.
|
|
*/
|
|
diff --git a/drivers/platform/loongarch/loongson-laptop.c b/drivers/platform/loongarch/loongson-laptop.c
|
|
index 99203584949daa..5fcfa3a7970b75 100644
|
|
--- a/drivers/platform/loongarch/loongson-laptop.c
|
|
+++ b/drivers/platform/loongarch/loongson-laptop.c
|
|
@@ -56,8 +56,7 @@ static struct input_dev *generic_inputdev;
|
|
static acpi_handle hotkey_handle;
|
|
static struct key_entry hotkey_keycode_map[GENERIC_HOTKEY_MAP_MAX];
|
|
|
|
-int loongson_laptop_turn_on_backlight(void);
|
|
-int loongson_laptop_turn_off_backlight(void);
|
|
+static bool bl_powered;
|
|
static int loongson_laptop_backlight_update(struct backlight_device *bd);
|
|
|
|
/* 2. ACPI Helpers and device model */
|
|
@@ -354,16 +353,42 @@ static int ec_backlight_level(u8 level)
|
|
return level;
|
|
}
|
|
|
|
+static int ec_backlight_set_power(bool state)
|
|
+{
|
|
+ int status;
|
|
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
|
|
+ struct acpi_object_list args = { 1, &arg0 };
|
|
+
|
|
+ arg0.integer.value = state;
|
|
+ status = acpi_evaluate_object(NULL, "\\BLSW", &args, NULL);
|
|
+ if (ACPI_FAILURE(status)) {
|
|
+ pr_info("Loongson lvds error: 0x%x\n", status);
|
|
+ return -EIO;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int loongson_laptop_backlight_update(struct backlight_device *bd)
|
|
{
|
|
- int lvl = ec_backlight_level(bd->props.brightness);
|
|
+ bool target_powered = !backlight_is_blank(bd);
|
|
+ int ret = 0, lvl = ec_backlight_level(bd->props.brightness);
|
|
|
|
if (lvl < 0)
|
|
return -EIO;
|
|
+
|
|
if (ec_set_brightness(lvl))
|
|
return -EIO;
|
|
|
|
- return 0;
|
|
+ if (target_powered != bl_powered) {
|
|
+ ret = ec_backlight_set_power(target_powered);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ bl_powered = target_powered;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int loongson_laptop_get_brightness(struct backlight_device *bd)
|
|
@@ -384,7 +409,7 @@ static const struct backlight_ops backlight_laptop_ops = {
|
|
|
|
static int laptop_backlight_register(void)
|
|
{
|
|
- int status = 0;
|
|
+ int status = 0, ret;
|
|
struct backlight_properties props;
|
|
|
|
memset(&props, 0, sizeof(props));
|
|
@@ -392,44 +417,20 @@ static int laptop_backlight_register(void)
|
|
if (!acpi_evalf(hotkey_handle, &status, "ECLL", "d"))
|
|
return -EIO;
|
|
|
|
- props.brightness = 1;
|
|
+ ret = ec_backlight_set_power(true);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ bl_powered = true;
|
|
+
|
|
props.max_brightness = status;
|
|
+ props.brightness = ec_get_brightness();
|
|
+ props.power = FB_BLANK_UNBLANK;
|
|
props.type = BACKLIGHT_PLATFORM;
|
|
|
|
backlight_device_register("loongson_laptop",
|
|
NULL, NULL, &backlight_laptop_ops, &props);
|
|
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int loongson_laptop_turn_on_backlight(void)
|
|
-{
|
|
- int status;
|
|
- union acpi_object arg0 = { ACPI_TYPE_INTEGER };
|
|
- struct acpi_object_list args = { 1, &arg0 };
|
|
-
|
|
- arg0.integer.value = 1;
|
|
- status = acpi_evaluate_object(NULL, "\\BLSW", &args, NULL);
|
|
- if (ACPI_FAILURE(status)) {
|
|
- pr_info("Loongson lvds error: 0x%x\n", status);
|
|
- return -ENODEV;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-int loongson_laptop_turn_off_backlight(void)
|
|
-{
|
|
- int status;
|
|
- union acpi_object arg0 = { ACPI_TYPE_INTEGER };
|
|
- struct acpi_object_list args = { 1, &arg0 };
|
|
-
|
|
- arg0.integer.value = 0;
|
|
- status = acpi_evaluate_object(NULL, "\\BLSW", &args, NULL);
|
|
- if (ACPI_FAILURE(status)) {
|
|
- pr_info("Loongson lvds error: 0x%x\n", status);
|
|
- return -ENODEV;
|
|
- }
|
|
|
|
return 0;
|
|
}
|
|
@@ -611,11 +612,17 @@ static int __init generic_acpi_laptop_init(void)
|
|
|
|
static void __exit generic_acpi_laptop_exit(void)
|
|
{
|
|
+ int i;
|
|
+
|
|
if (generic_inputdev) {
|
|
- if (input_device_registered)
|
|
- input_unregister_device(generic_inputdev);
|
|
- else
|
|
+ if (!input_device_registered) {
|
|
input_free_device(generic_inputdev);
|
|
+ } else {
|
|
+ input_unregister_device(generic_inputdev);
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(generic_sub_drivers); i++)
|
|
+ generic_subdriver_exit(&generic_sub_drivers[i]);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/platform/x86/amd/pmc/pmc.c b/drivers/platform/x86/amd/pmc/pmc.c
|
|
index 946a546cd9dd01..af5cc8aa7988c1 100644
|
|
--- a/drivers/platform/x86/amd/pmc/pmc.c
|
|
+++ b/drivers/platform/x86/amd/pmc/pmc.c
|
|
@@ -332,6 +332,8 @@ static int amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
+ memset_io(dev->smu_virt_addr, 0, sizeof(struct smu_metrics));
|
|
+
|
|
/* Start the logging */
|
|
amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, false);
|
|
amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, false);
|
|
diff --git a/drivers/platform/x86/dell/dell_rbu.c b/drivers/platform/x86/dell/dell_rbu.c
|
|
index 9f51e0fcab04e1..fee20866b41e41 100644
|
|
--- a/drivers/platform/x86/dell/dell_rbu.c
|
|
+++ b/drivers/platform/x86/dell/dell_rbu.c
|
|
@@ -292,7 +292,7 @@ static int packet_read_list(char *data, size_t * pread_length)
|
|
remaining_bytes = *pread_length;
|
|
bytes_read = rbu_data.packet_read_count;
|
|
|
|
- list_for_each_entry(newpacket, (&packet_data_head.list)->next, list) {
|
|
+ list_for_each_entry(newpacket, &packet_data_head.list, list) {
|
|
bytes_copied = do_packet_read(pdest, newpacket,
|
|
remaining_bytes, bytes_read, &temp_count);
|
|
remaining_bytes -= bytes_copied;
|
|
@@ -315,14 +315,14 @@ static void packet_empty_list(void)
|
|
{
|
|
struct packet_data *newpacket, *tmp;
|
|
|
|
- list_for_each_entry_safe(newpacket, tmp, (&packet_data_head.list)->next, list) {
|
|
+ list_for_each_entry_safe(newpacket, tmp, &packet_data_head.list, list) {
|
|
list_del(&newpacket->list);
|
|
|
|
/*
|
|
* zero out the RBU packet memory before freeing
|
|
* to make sure there are no stale RBU packets left in memory
|
|
*/
|
|
- memset(newpacket->data, 0, rbu_data.packetsize);
|
|
+ memset(newpacket->data, 0, newpacket->length);
|
|
set_memory_wb((unsigned long)newpacket->data,
|
|
1 << newpacket->ordernum);
|
|
free_pages((unsigned long) newpacket->data,
|
|
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
|
|
index 88eefccb6ed276..50013af0537c36 100644
|
|
--- a/drivers/platform/x86/ideapad-laptop.c
|
|
+++ b/drivers/platform/x86/ideapad-laptop.c
|
|
@@ -1101,6 +1101,9 @@ static const struct key_entry ideapad_keymap[] = {
|
|
{ KE_KEY, 0x27 | IDEAPAD_WMI_KEY, { KEY_HELP } },
|
|
/* Refresh Rate Toggle */
|
|
{ KE_KEY, 0x0a | IDEAPAD_WMI_KEY, { KEY_DISPLAYTOGGLE } },
|
|
+ /* Specific to some newer models */
|
|
+ { KE_KEY, 0x3e | IDEAPAD_WMI_KEY, { KEY_MICMUTE } },
|
|
+ { KE_KEY, 0x3f | IDEAPAD_WMI_KEY, { KEY_RFKILL } },
|
|
|
|
{ KE_END },
|
|
};
|
|
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
|
|
index 10502216454824..5be3b26876151c 100644
|
|
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
|
|
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
|
|
@@ -269,10 +269,13 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
|
|
|
|
/* Get the package ID from the TPMI core */
|
|
plat_info = tpmi_get_platform_data(auxdev);
|
|
- if (plat_info)
|
|
- pkg = plat_info->package_id;
|
|
- else
|
|
+ if (unlikely(!plat_info)) {
|
|
dev_info(&auxdev->dev, "Platform information is NULL\n");
|
|
+ ret = -ENODEV;
|
|
+ goto err_rem_common;
|
|
+ }
|
|
+
|
|
+ pkg = plat_info->package_id;
|
|
|
|
for (i = 0; i < num_resources; ++i) {
|
|
struct tpmi_uncore_power_domain_info *pd_info;
|
|
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
|
|
index 23c87365675742..e51fa2c694bc6d 100644
|
|
--- a/drivers/power/supply/bq27xxx_battery.c
|
|
+++ b/drivers/power/supply/bq27xxx_battery.c
|
|
@@ -2044,7 +2044,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
|
|
mutex_unlock(&di->lock);
|
|
|
|
if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
|
|
- return -ENODEV;
|
|
+ return di->cache.flags;
|
|
|
|
switch (psp) {
|
|
case POWER_SUPPLY_PROP_STATUS:
|
|
diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c
|
|
index 886e0a8e2abd1e..8877fa333cd02e 100644
|
|
--- a/drivers/power/supply/bq27xxx_battery_i2c.c
|
|
+++ b/drivers/power/supply/bq27xxx_battery_i2c.c
|
|
@@ -6,6 +6,7 @@
|
|
* Andrew F. Davis <afd@ti.com>
|
|
*/
|
|
|
|
+#include <linux/delay.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/module.h>
|
|
@@ -32,6 +33,7 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
|
|
struct i2c_msg msg[2];
|
|
u8 data[2];
|
|
int ret;
|
|
+ int retry = 0;
|
|
|
|
if (!client->adapter)
|
|
return -ENODEV;
|
|
@@ -48,7 +50,16 @@ static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
|
|
else
|
|
msg[1].len = 2;
|
|
|
|
- ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
|
|
+ do {
|
|
+ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
|
|
+ if (ret == -EBUSY && ++retry < 3) {
|
|
+ /* sleep 10 milliseconds when busy */
|
|
+ usleep_range(10000, 11000);
|
|
+ continue;
|
|
+ }
|
|
+ break;
|
|
+ } while (1);
|
|
+
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
diff --git a/drivers/power/supply/collie_battery.c b/drivers/power/supply/collie_battery.c
|
|
index 68390bd1004f04..3daf7befc0bf64 100644
|
|
--- a/drivers/power/supply/collie_battery.c
|
|
+++ b/drivers/power/supply/collie_battery.c
|
|
@@ -440,6 +440,7 @@ static int collie_bat_probe(struct ucb1x00_dev *dev)
|
|
|
|
static void collie_bat_remove(struct ucb1x00_dev *dev)
|
|
{
|
|
+ device_init_wakeup(&ucb->dev, 0);
|
|
free_irq(gpiod_to_irq(collie_bat_main.gpio_full), &collie_bat_main);
|
|
power_supply_unregister(collie_bat_bu.psy);
|
|
power_supply_unregister(collie_bat_main.psy);
|
|
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
|
|
index 6b7e8b7ebcef5e..b7fc260ed43bc4 100644
|
|
--- a/drivers/ptp/ptp_clock.c
|
|
+++ b/drivers/ptp/ptp_clock.c
|
|
@@ -104,7 +104,8 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
|
|
struct ptp_clock_info *ops;
|
|
int err = -EOPNOTSUPP;
|
|
|
|
- if (ptp_clock_freerun(ptp)) {
|
|
+ if (tx->modes & (ADJ_SETOFFSET | ADJ_FREQUENCY | ADJ_OFFSET) &&
|
|
+ ptp_clock_freerun(ptp)) {
|
|
pr_err("ptp: physical clock is free running\n");
|
|
return -EBUSY;
|
|
}
|
|
diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
|
|
index d0eb4555720eba..a54124269c2f49 100644
|
|
--- a/drivers/ptp/ptp_private.h
|
|
+++ b/drivers/ptp/ptp_private.h
|
|
@@ -89,7 +89,27 @@ static inline int queue_cnt(const struct timestamp_event_queue *q)
|
|
/* Check if ptp virtual clock is in use */
|
|
static inline bool ptp_vclock_in_use(struct ptp_clock *ptp)
|
|
{
|
|
- return !ptp->is_virtual_clock;
|
|
+ bool in_use = false;
|
|
+
|
|
+ /* Virtual clocks can't be stacked on top of virtual clocks.
|
|
+ * Avoid acquiring the n_vclocks_mux on virtual clocks, to allow this
|
|
+ * function to be called from code paths where the n_vclocks_mux of the
|
|
+ * parent physical clock is already held. Functionally that's not an
|
|
+ * issue, but lockdep would complain, because they have the same lock
|
|
+ * class.
|
|
+ */
|
|
+ if (ptp->is_virtual_clock)
|
|
+ return false;
|
|
+
|
|
+ if (mutex_lock_interruptible(&ptp->n_vclocks_mux))
|
|
+ return true;
|
|
+
|
|
+ if (ptp->n_vclocks)
|
|
+ in_use = true;
|
|
+
|
|
+ mutex_unlock(&ptp->n_vclocks_mux);
|
|
+
|
|
+ return in_use;
|
|
}
|
|
|
|
/* Check if ptp clock shall be free running */
|
|
diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c
|
|
index 49f8d111e54623..897642e62068a3 100644
|
|
--- a/drivers/rapidio/rio_cm.c
|
|
+++ b/drivers/rapidio/rio_cm.c
|
|
@@ -787,6 +787,9 @@ static int riocm_ch_send(u16 ch_id, void *buf, int len)
|
|
if (buf == NULL || ch_id == 0 || len == 0 || len > RIO_MAX_MSG_SIZE)
|
|
return -EINVAL;
|
|
|
|
+ if (len < sizeof(struct rio_ch_chan_hdr))
|
|
+ return -EINVAL; /* insufficient data from user */
|
|
+
|
|
ch = riocm_get_channel(ch_id);
|
|
if (!ch) {
|
|
riocm_error("%s(%d) ch_%d not found", current->comm,
|
|
diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c
|
|
index 5e7171b9065ae7..41fd15adfd1fdd 100644
|
|
--- a/drivers/regulator/max14577-regulator.c
|
|
+++ b/drivers/regulator/max14577-regulator.c
|
|
@@ -40,11 +40,14 @@ static int max14577_reg_get_current_limit(struct regulator_dev *rdev)
|
|
struct max14577 *max14577 = rdev_get_drvdata(rdev);
|
|
const struct maxim_charger_current *limits =
|
|
&maxim_charger_currents[max14577->dev_type];
|
|
+ int ret;
|
|
|
|
if (rdev_get_id(rdev) != MAX14577_CHARGER)
|
|
return -EINVAL;
|
|
|
|
- max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL4, ®_data);
|
|
+ ret = max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL4, ®_data);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
if ((reg_data & CHGCTRL4_MBCICHWRCL_MASK) == 0)
|
|
return limits->min;
|
|
diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c
|
|
index 1cf04d1efb3313..8fcca52026bf15 100644
|
|
--- a/drivers/regulator/max20086-regulator.c
|
|
+++ b/drivers/regulator/max20086-regulator.c
|
|
@@ -29,7 +29,7 @@
|
|
#define MAX20086_REG_ADC4 0x09
|
|
|
|
/* DEVICE IDs */
|
|
-#define MAX20086_DEVICE_ID_MAX20086 0x40
|
|
+#define MAX20086_DEVICE_ID_MAX20086 0x30
|
|
#define MAX20086_DEVICE_ID_MAX20087 0x20
|
|
#define MAX20086_DEVICE_ID_MAX20088 0x10
|
|
#define MAX20086_DEVICE_ID_MAX20089 0x00
|
|
@@ -264,7 +264,7 @@ static int max20086_i2c_probe(struct i2c_client *i2c)
|
|
* shutdown.
|
|
*/
|
|
flags = boot_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
|
|
- chip->ena_gpiod = devm_gpiod_get(chip->dev, "enable", flags);
|
|
+ chip->ena_gpiod = devm_gpiod_get_optional(chip->dev, "enable", flags);
|
|
if (IS_ERR(chip->ena_gpiod)) {
|
|
ret = PTR_ERR(chip->ena_gpiod);
|
|
dev_err(chip->dev, "Failed to get enable GPIO: %d\n", ret);
|
|
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
|
|
index 0c363ca566ffdb..2d4ae3b5af86f6 100644
|
|
--- a/drivers/remoteproc/remoteproc_core.c
|
|
+++ b/drivers/remoteproc/remoteproc_core.c
|
|
@@ -1616,7 +1616,7 @@ static int rproc_attach(struct rproc *rproc)
|
|
ret = rproc_set_rsc_table(rproc);
|
|
if (ret) {
|
|
dev_err(dev, "can't load resource table: %d\n", ret);
|
|
- goto unprepare_device;
|
|
+ goto clean_up_resources;
|
|
}
|
|
|
|
/* reset max_notifyid */
|
|
@@ -1633,7 +1633,7 @@ static int rproc_attach(struct rproc *rproc)
|
|
ret = rproc_handle_resources(rproc, rproc_loading_handlers);
|
|
if (ret) {
|
|
dev_err(dev, "Failed to process resources: %d\n", ret);
|
|
- goto unprepare_device;
|
|
+ goto clean_up_resources;
|
|
}
|
|
|
|
/* Allocate carveout resources associated to rproc */
|
|
@@ -1652,9 +1652,9 @@ static int rproc_attach(struct rproc *rproc)
|
|
|
|
clean_up_resources:
|
|
rproc_resource_cleanup(rproc);
|
|
-unprepare_device:
|
|
/* release HW resources if needed */
|
|
rproc_unprepare_device(rproc);
|
|
+ kfree(rproc->clean_table);
|
|
disable_iommu:
|
|
rproc_disable_iommu(rproc);
|
|
return ret;
|
|
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
|
|
index cb67fa80fb12c8..a95da6768f6656 100644
|
|
--- a/drivers/s390/scsi/zfcp_sysfs.c
|
|
+++ b/drivers/s390/scsi/zfcp_sysfs.c
|
|
@@ -450,6 +450,8 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
|
|
if (kstrtoull(buf, 0, (unsigned long long *) &fcp_lun))
|
|
return -EINVAL;
|
|
|
|
+ flush_work(&port->rport_work);
|
|
+
|
|
retval = zfcp_unit_add(port, fcp_lun);
|
|
if (retval)
|
|
return retval;
|
|
diff --git a/drivers/scsi/elx/efct/efct_hw.c b/drivers/scsi/elx/efct/efct_hw.c
|
|
index 5a5525054d71c8..5b079b8b7a082b 100644
|
|
--- a/drivers/scsi/elx/efct/efct_hw.c
|
|
+++ b/drivers/scsi/elx/efct/efct_hw.c
|
|
@@ -1120,7 +1120,7 @@ int
|
|
efct_hw_parse_filter(struct efct_hw *hw, void *value)
|
|
{
|
|
int rc = 0;
|
|
- char *p = NULL;
|
|
+ char *p = NULL, *pp = NULL;
|
|
char *token;
|
|
u32 idx = 0;
|
|
|
|
@@ -1132,6 +1132,7 @@ efct_hw_parse_filter(struct efct_hw *hw, void *value)
|
|
efc_log_err(hw->os, "p is NULL\n");
|
|
return -ENOMEM;
|
|
}
|
|
+ pp = p;
|
|
|
|
idx = 0;
|
|
while ((token = strsep(&p, ",")) && *token) {
|
|
@@ -1144,7 +1145,7 @@ efct_hw_parse_filter(struct efct_hw *hw, void *value)
|
|
if (idx == ARRAY_SIZE(hw->config.filter_def))
|
|
break;
|
|
}
|
|
- kfree(p);
|
|
+ kfree(pp);
|
|
|
|
return rc;
|
|
}
|
|
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
index 5c9bc8af3c2df8..ff442833387713 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
@@ -5101,7 +5101,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba,
|
|
case CMD_GEN_REQUEST64_CR:
|
|
if (iocb->ndlp == ndlp)
|
|
return 1;
|
|
- fallthrough;
|
|
+ break;
|
|
case CMD_ELS_REQUEST64_CR:
|
|
if (remote_id == ndlp->nlp_DID)
|
|
return 1;
|
|
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
|
|
index 4a9fa00eeb798e..4cf935b7223af2 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_sli.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_sli.c
|
|
@@ -6014,9 +6014,9 @@ lpfc_sli4_get_ctl_attr(struct lpfc_hba *phba)
|
|
phba->sli4_hba.flash_id = bf_get(lpfc_cntl_attr_flash_id, cntl_attr);
|
|
phba->sli4_hba.asic_rev = bf_get(lpfc_cntl_attr_asic_rev, cntl_attr);
|
|
|
|
- memset(phba->BIOSVersion, 0, sizeof(phba->BIOSVersion));
|
|
- strlcat(phba->BIOSVersion, (char *)cntl_attr->bios_ver_str,
|
|
+ memcpy(phba->BIOSVersion, cntl_attr->bios_ver_str,
|
|
sizeof(phba->BIOSVersion));
|
|
+ phba->BIOSVersion[sizeof(phba->BIOSVersion) - 1] = '\0';
|
|
|
|
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
|
"3086 lnk_type:%d, lnk_numb:%d, bios_ver:%s, "
|
|
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
|
|
index 48b0ca92b44fb3..954a1cc50ba746 100644
|
|
--- a/drivers/scsi/storvsc_drv.c
|
|
+++ b/drivers/scsi/storvsc_drv.c
|
|
@@ -362,7 +362,7 @@ MODULE_PARM_DESC(ring_avail_percent_lowater,
|
|
/*
|
|
* Timeout in seconds for all devices managed by this driver.
|
|
*/
|
|
-static int storvsc_timeout = 180;
|
|
+static const int storvsc_timeout = 180;
|
|
|
|
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
|
|
static struct scsi_transport_template *fc_transport_template;
|
|
@@ -768,7 +768,7 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns)
|
|
return;
|
|
}
|
|
|
|
- t = wait_for_completion_timeout(&request->wait_event, 10*HZ);
|
|
+ t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ);
|
|
if (t == 0) {
|
|
dev_err(dev, "Failed to create sub-channel: timed out\n");
|
|
return;
|
|
@@ -833,7 +833,7 @@ static int storvsc_execute_vstor_op(struct hv_device *device,
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
- t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
|
|
+ t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ);
|
|
if (t == 0)
|
|
return -ETIMEDOUT;
|
|
|
|
@@ -1351,6 +1351,8 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size,
|
|
return ret;
|
|
|
|
ret = storvsc_channel_init(device, is_fc);
|
|
+ if (ret)
|
|
+ vmbus_close(device->channel);
|
|
|
|
return ret;
|
|
}
|
|
@@ -1668,7 +1670,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
|
if (ret != 0)
|
|
return FAILED;
|
|
|
|
- t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
|
|
+ t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ);
|
|
if (t == 0)
|
|
return TIMEOUT_ERROR;
|
|
|
|
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
|
|
index 2d0883a6408277..31d82a042dad20 100644
|
|
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
|
|
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
|
|
@@ -412,7 +412,7 @@ static ssize_t ad5933_store(struct device *dev,
|
|
ret = ad5933_cmd(st, 0);
|
|
break;
|
|
case AD5933_OUT_SETTLING_CYCLES:
|
|
- val = clamp(val, (u16)0, (u16)0x7FF);
|
|
+ val = clamp(val, (u16)0, (u16)0x7FC);
|
|
st->settling_cycles = val;
|
|
|
|
/* 2x, 4x handling, see datasheet */
|
|
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
|
|
index 0eb342de0b0018..d7ad16f262b2eb 100644
|
|
--- a/drivers/tee/tee_core.c
|
|
+++ b/drivers/tee/tee_core.c
|
|
@@ -10,6 +10,7 @@
|
|
#include <linux/fs.h>
|
|
#include <linux/idr.h>
|
|
#include <linux/module.h>
|
|
+#include <linux/overflow.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/tee_drv.h>
|
|
#include <linux/uaccess.h>
|
|
@@ -19,7 +20,7 @@
|
|
|
|
#define TEE_NUM_DEVICES 32
|
|
|
|
-#define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x))
|
|
+#define TEE_IOCTL_PARAM_SIZE(x) (size_mul(sizeof(struct tee_param), (x)))
|
|
|
|
#define TEE_UUID_NS_NAME_SIZE 128
|
|
|
|
@@ -487,7 +488,7 @@ static int tee_ioctl_open_session(struct tee_context *ctx,
|
|
if (copy_from_user(&arg, uarg, sizeof(arg)))
|
|
return -EFAULT;
|
|
|
|
- if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
|
|
+ if (size_add(sizeof(arg), TEE_IOCTL_PARAM_SIZE(arg.num_params)) != buf.buf_len)
|
|
return -EINVAL;
|
|
|
|
if (arg.num_params) {
|
|
@@ -565,7 +566,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx,
|
|
if (copy_from_user(&arg, uarg, sizeof(arg)))
|
|
return -EFAULT;
|
|
|
|
- if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
|
|
+ if (size_add(sizeof(arg), TEE_IOCTL_PARAM_SIZE(arg.num_params)) != buf.buf_len)
|
|
return -EINVAL;
|
|
|
|
if (arg.num_params) {
|
|
@@ -699,7 +700,7 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx,
|
|
if (get_user(num_params, &uarg->num_params))
|
|
return -EFAULT;
|
|
|
|
- if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) != buf.buf_len)
|
|
+ if (size_add(sizeof(*uarg), TEE_IOCTL_PARAM_SIZE(num_params)) != buf.buf_len)
|
|
return -EINVAL;
|
|
|
|
params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL);
|
|
@@ -798,7 +799,7 @@ static int tee_ioctl_supp_send(struct tee_context *ctx,
|
|
get_user(num_params, &uarg->num_params))
|
|
return -EFAULT;
|
|
|
|
- if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) > buf.buf_len)
|
|
+ if (size_add(sizeof(*uarg), TEE_IOCTL_PARAM_SIZE(num_params)) > buf.buf_len)
|
|
return -EINVAL;
|
|
|
|
params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL);
|
|
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
|
|
index be7e57e1d1e36a..dab5658d9d54a6 100644
|
|
--- a/drivers/tty/serial/sh-sci.c
|
|
+++ b/drivers/tty/serial/sh-sci.c
|
|
@@ -3424,6 +3424,22 @@ static int sci_probe_single(struct platform_device *dev,
|
|
}
|
|
|
|
if (sci_uart_earlycon && sci_ports[0].port.mapbase == sci_res->start) {
|
|
+ /*
|
|
+ * In case:
|
|
+ * - this is the earlycon port (mapped on index 0 in sci_ports[]) and
|
|
+ * - it now maps to an alias other than zero and
|
|
+ * - the earlycon is still alive (e.g., "earlycon keep_bootcon" is
|
|
+ * available in bootargs)
|
|
+ *
|
|
+ * we need to avoid disabling clocks and PM domains through the runtime
|
|
+ * PM APIs called in __device_attach(). For this, increment the runtime
|
|
+ * PM reference counter (the clocks and PM domains were already enabled
|
|
+ * by the bootloader). Otherwise the earlycon may access the HW when it
|
|
+ * has no clocks enabled leading to failures (infinite loop in
|
|
+ * sci_poll_put_char()).
|
|
+ */
|
|
+ pm_runtime_get_noresume(&dev->dev);
|
|
+
|
|
/*
|
|
* Skip cleanup the sci_port[0] in early_console_exit(), this
|
|
* port is the same as the earlycon one.
|
|
diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
|
|
index a2c7abf8c289ef..2804a4f749750a 100644
|
|
--- a/drivers/uio/uio_hv_generic.c
|
|
+++ b/drivers/uio/uio_hv_generic.c
|
|
@@ -288,13 +288,13 @@ hv_uio_probe(struct hv_device *dev,
|
|
pdata->info.mem[INT_PAGE_MAP].name = "int_page";
|
|
pdata->info.mem[INT_PAGE_MAP].addr
|
|
= (uintptr_t)vmbus_connection.int_page;
|
|
- pdata->info.mem[INT_PAGE_MAP].size = PAGE_SIZE;
|
|
+ pdata->info.mem[INT_PAGE_MAP].size = HV_HYP_PAGE_SIZE;
|
|
pdata->info.mem[INT_PAGE_MAP].memtype = UIO_MEM_LOGICAL;
|
|
|
|
pdata->info.mem[MON_PAGE_MAP].name = "monitor_page";
|
|
pdata->info.mem[MON_PAGE_MAP].addr
|
|
= (uintptr_t)vmbus_connection.monitor_pages[1];
|
|
- pdata->info.mem[MON_PAGE_MAP].size = PAGE_SIZE;
|
|
+ pdata->info.mem[MON_PAGE_MAP].size = HV_HYP_PAGE_SIZE;
|
|
pdata->info.mem[MON_PAGE_MAP].memtype = UIO_MEM_LOGICAL;
|
|
|
|
pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE);
|
|
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
|
|
index 7ad047bcae1711..c9ec89649b0552 100644
|
|
--- a/drivers/video/console/vgacon.c
|
|
+++ b/drivers/video/console/vgacon.c
|
|
@@ -1139,7 +1139,7 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
|
|
c->vc_screenbuf_size - delta);
|
|
c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
|
|
vga_rolled_over = 0;
|
|
- } else
|
|
+ } else if (oldo - delta >= (unsigned long)c->vc_screenbuf)
|
|
c->vc_origin -= delta;
|
|
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
|
|
scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
|
|
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
|
index 7a6f9a3cb3ba34..75996ef9992e41 100644
|
|
--- a/drivers/video/fbdev/core/fbcon.c
|
|
+++ b/drivers/video/fbdev/core/fbcon.c
|
|
@@ -115,9 +115,14 @@ static signed char con2fb_map_boot[MAX_NR_CONSOLES];
|
|
|
|
static struct fb_info *fbcon_info_from_console(int console)
|
|
{
|
|
+ signed char fb;
|
|
WARN_CONSOLE_UNLOCKED();
|
|
|
|
- return fbcon_registered_fb[con2fb_map[console]];
|
|
+ fb = con2fb_map[console];
|
|
+ if (fb < 0 || fb >= ARRAY_SIZE(fbcon_registered_fb))
|
|
+ return NULL;
|
|
+
|
|
+ return fbcon_registered_fb[fb];
|
|
}
|
|
|
|
static int logo_lines;
|
|
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
|
|
index ee44a46a66be1c..52bd3af5436908 100644
|
|
--- a/drivers/video/fbdev/core/fbmem.c
|
|
+++ b/drivers/video/fbdev/core/fbmem.c
|
|
@@ -868,8 +868,10 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
|
|
!list_empty(&info->modelist))
|
|
ret = fb_add_videomode(&mode, &info->modelist);
|
|
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ info->var = old_var;
|
|
return ret;
|
|
+ }
|
|
|
|
event.info = info;
|
|
event.data = &mode;
|
|
@@ -928,7 +930,7 @@ static int fb_check_foreignness(struct fb_info *fi)
|
|
|
|
static int do_register_framebuffer(struct fb_info *fb_info)
|
|
{
|
|
- int i;
|
|
+ int i, err = 0;
|
|
struct fb_videomode mode;
|
|
|
|
if (fb_check_foreignness(fb_info))
|
|
@@ -937,10 +939,18 @@ static int do_register_framebuffer(struct fb_info *fb_info)
|
|
if (num_registered_fb == FB_MAX)
|
|
return -ENXIO;
|
|
|
|
- num_registered_fb++;
|
|
for (i = 0 ; i < FB_MAX; i++)
|
|
if (!registered_fb[i])
|
|
break;
|
|
+
|
|
+ if (!fb_info->modelist.prev || !fb_info->modelist.next)
|
|
+ INIT_LIST_HEAD(&fb_info->modelist);
|
|
+
|
|
+ fb_var_to_videomode(&mode, &fb_info->var);
|
|
+ err = fb_add_videomode(&mode, &fb_info->modelist);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+
|
|
fb_info->node = i;
|
|
refcount_set(&fb_info->count, 1);
|
|
mutex_init(&fb_info->lock);
|
|
@@ -966,16 +976,12 @@ static int do_register_framebuffer(struct fb_info *fb_info)
|
|
if (!fb_info->pixmap.blit_y)
|
|
fb_info->pixmap.blit_y = ~(u32)0;
|
|
|
|
- if (!fb_info->modelist.prev || !fb_info->modelist.next)
|
|
- INIT_LIST_HEAD(&fb_info->modelist);
|
|
-
|
|
if (fb_info->skip_vt_switch)
|
|
pm_vt_switch_required(fb_info->device, false);
|
|
else
|
|
pm_vt_switch_required(fb_info->device, true);
|
|
|
|
- fb_var_to_videomode(&mode, &fb_info->var);
|
|
- fb_add_videomode(&mode, &fb_info->modelist);
|
|
+ num_registered_fb++;
|
|
registered_fb[i] = fb_info;
|
|
|
|
#ifdef CONFIG_GUMSTIX_AM200EPD
|
|
diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
|
|
index 6c583351714100..66bfc1d0a6dc82 100644
|
|
--- a/drivers/video/screen_info_pci.c
|
|
+++ b/drivers/video/screen_info_pci.c
|
|
@@ -7,8 +7,8 @@
|
|
|
|
static struct pci_dev *screen_info_lfb_pdev;
|
|
static size_t screen_info_lfb_bar;
|
|
-static resource_size_t screen_info_lfb_offset;
|
|
-static struct resource screen_info_lfb_res = DEFINE_RES_MEM(0, 0);
|
|
+static resource_size_t screen_info_lfb_res_start; // original start of resource
|
|
+static resource_size_t screen_info_lfb_offset; // framebuffer offset within resource
|
|
|
|
static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr)
|
|
{
|
|
@@ -31,7 +31,7 @@ void screen_info_apply_fixups(void)
|
|
if (screen_info_lfb_pdev) {
|
|
struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar];
|
|
|
|
- if (pr->start != screen_info_lfb_res.start) {
|
|
+ if (pr->start != screen_info_lfb_res_start) {
|
|
if (__screen_info_relocation_is_valid(si, pr)) {
|
|
/*
|
|
* Only update base if we have an actual
|
|
@@ -47,46 +47,67 @@ void screen_info_apply_fixups(void)
|
|
}
|
|
}
|
|
|
|
+static int __screen_info_lfb_pci_bus_region(const struct screen_info *si, unsigned int type,
|
|
+ struct pci_bus_region *r)
|
|
+{
|
|
+ u64 base, size;
|
|
+
|
|
+ base = __screen_info_lfb_base(si);
|
|
+ if (!base)
|
|
+ return -EINVAL;
|
|
+
|
|
+ size = __screen_info_lfb_size(si, type);
|
|
+ if (!size)
|
|
+ return -EINVAL;
|
|
+
|
|
+ r->start = base;
|
|
+ r->end = base + size - 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void screen_info_fixup_lfb(struct pci_dev *pdev)
|
|
{
|
|
unsigned int type;
|
|
- struct resource res[SCREEN_INFO_MAX_RESOURCES];
|
|
- size_t i, numres;
|
|
+ struct pci_bus_region bus_region;
|
|
int ret;
|
|
+ struct resource r = {
|
|
+ .flags = IORESOURCE_MEM,
|
|
+ };
|
|
+ const struct resource *pr;
|
|
const struct screen_info *si = &screen_info;
|
|
|
|
if (screen_info_lfb_pdev)
|
|
return; // already found
|
|
|
|
type = screen_info_video_type(si);
|
|
- if (type != VIDEO_TYPE_EFI)
|
|
- return; // only applies to EFI
|
|
+ if (!__screen_info_has_lfb(type))
|
|
+ return; // only applies to EFI; maybe VESA
|
|
|
|
- ret = screen_info_resources(si, res, ARRAY_SIZE(res));
|
|
+ ret = __screen_info_lfb_pci_bus_region(si, type, &bus_region);
|
|
if (ret < 0)
|
|
return;
|
|
- numres = ret;
|
|
|
|
- for (i = 0; i < numres; ++i) {
|
|
- struct resource *r = &res[i];
|
|
- const struct resource *pr;
|
|
-
|
|
- if (!(r->flags & IORESOURCE_MEM))
|
|
- continue;
|
|
- pr = pci_find_resource(pdev, r);
|
|
- if (!pr)
|
|
- continue;
|
|
-
|
|
- /*
|
|
- * We've found a PCI device with the framebuffer
|
|
- * resource. Store away the parameters to track
|
|
- * relocation of the framebuffer aperture.
|
|
- */
|
|
- screen_info_lfb_pdev = pdev;
|
|
- screen_info_lfb_bar = pr - pdev->resource;
|
|
- screen_info_lfb_offset = r->start - pr->start;
|
|
- memcpy(&screen_info_lfb_res, r, sizeof(screen_info_lfb_res));
|
|
- }
|
|
+ /*
|
|
+ * Translate the PCI bus address to resource. Account
|
|
+ * for an offset if the framebuffer is behind a PCI host
|
|
+ * bridge.
|
|
+ */
|
|
+ pcibios_bus_to_resource(pdev->bus, &r, &bus_region);
|
|
+
|
|
+ pr = pci_find_resource(pdev, &r);
|
|
+ if (!pr)
|
|
+ return;
|
|
+
|
|
+ /*
|
|
+ * We've found a PCI device with the framebuffer
|
|
+ * resource. Store away the parameters to track
|
|
+ * relocation of the framebuffer aperture.
|
|
+ */
|
|
+ screen_info_lfb_pdev = pdev;
|
|
+ screen_info_lfb_bar = pr - pdev->resource;
|
|
+ screen_info_lfb_offset = r.start - pr->start;
|
|
+ screen_info_lfb_res_start = bus_region.start;
|
|
}
|
|
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY, 16,
|
|
screen_info_fixup_lfb);
|
|
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
|
|
index d708c091bf1b1e..180526220d8c42 100644
|
|
--- a/drivers/watchdog/da9052_wdt.c
|
|
+++ b/drivers/watchdog/da9052_wdt.c
|
|
@@ -164,6 +164,7 @@ static int da9052_wdt_probe(struct platform_device *pdev)
|
|
da9052_wdt = &driver_data->wdt;
|
|
|
|
da9052_wdt->timeout = DA9052_DEF_TIMEOUT;
|
|
+ da9052_wdt->min_hw_heartbeat_ms = DA9052_TWDMIN;
|
|
da9052_wdt->info = &da9052_wdt_info;
|
|
da9052_wdt->ops = &da9052_wdt_ops;
|
|
da9052_wdt->parent = dev;
|
|
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
|
|
index 29026ba4f02290..84e855e8929b03 100644
|
|
--- a/fs/ceph/super.c
|
|
+++ b/fs/ceph/super.c
|
|
@@ -1220,6 +1220,7 @@ static int ceph_set_super(struct super_block *s, struct fs_context *fc)
|
|
s->s_time_min = 0;
|
|
s->s_time_max = U32_MAX;
|
|
s->s_flags |= SB_NODIRATIME | SB_NOATIME;
|
|
+ s->s_magic = CEPH_SUPER_MAGIC;
|
|
|
|
ceph_fscrypt_set_ops(s);
|
|
|
|
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
|
|
index 18677cd4e62f54..2df99cd1034d4e 100644
|
|
--- a/fs/configfs/dir.c
|
|
+++ b/fs/configfs/dir.c
|
|
@@ -593,7 +593,7 @@ static int populate_attrs(struct config_item *item)
|
|
break;
|
|
}
|
|
}
|
|
- if (t->ct_bin_attrs) {
|
|
+ if (!error && t->ct_bin_attrs) {
|
|
for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) {
|
|
error = configfs_create_bin_file(item, bin_attr);
|
|
if (error)
|
|
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
|
|
index 81fe87fcbfa068..b55d5e2abeb3cb 100644
|
|
--- a/fs/ext4/ext4.h
|
|
+++ b/fs/ext4/ext4.h
|
|
@@ -3351,6 +3351,13 @@ static inline unsigned int ext4_flex_bg_size(struct ext4_sb_info *sbi)
|
|
return 1 << sbi->s_log_groups_per_flex;
|
|
}
|
|
|
|
+static inline loff_t ext4_get_maxbytes(struct inode *inode)
|
|
+{
|
|
+ if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
|
|
+ return inode->i_sb->s_maxbytes;
|
|
+ return EXT4_SB(inode->i_sb)->s_bitmap_maxbytes;
|
|
+}
|
|
+
|
|
#define ext4_std_error(sb, errno) \
|
|
do { \
|
|
if ((errno)) \
|
|
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
|
|
index 39e3661a80c433..a3d3c9fc64262f 100644
|
|
--- a/fs/ext4/extents.c
|
|
+++ b/fs/ext4/extents.c
|
|
@@ -2374,18 +2374,19 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks,
|
|
int ext4_ext_index_trans_blocks(struct inode *inode, int extents)
|
|
{
|
|
int index;
|
|
- int depth;
|
|
|
|
/* If we are converting the inline data, only one is needed here. */
|
|
if (ext4_has_inline_data(inode))
|
|
return 1;
|
|
|
|
- depth = ext_depth(inode);
|
|
-
|
|
+ /*
|
|
+ * Extent tree can change between the time we estimate credits and
|
|
+ * the time we actually modify the tree. Assume the worst case.
|
|
+ */
|
|
if (extents <= 1)
|
|
- index = depth * 2;
|
|
+ index = EXT4_MAX_EXTENT_DEPTH * 2;
|
|
else
|
|
- index = depth * 3;
|
|
+ index = EXT4_MAX_EXTENT_DEPTH * 3;
|
|
|
|
return index;
|
|
}
|
|
@@ -4969,12 +4970,7 @@ static const struct iomap_ops ext4_iomap_xattr_ops = {
|
|
|
|
static int ext4_fiemap_check_ranges(struct inode *inode, u64 start, u64 *len)
|
|
{
|
|
- u64 maxbytes;
|
|
-
|
|
- if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
|
|
- maxbytes = inode->i_sb->s_maxbytes;
|
|
- else
|
|
- maxbytes = EXT4_SB(inode->i_sb)->s_bitmap_maxbytes;
|
|
+ u64 maxbytes = ext4_get_maxbytes(inode);
|
|
|
|
if (*len == 0)
|
|
return -EINVAL;
|
|
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
|
|
index c71af675e310af..b37e0e4a71bfbe 100644
|
|
--- a/fs/ext4/file.c
|
|
+++ b/fs/ext4/file.c
|
|
@@ -898,12 +898,7 @@ static int ext4_file_open(struct inode *inode, struct file *filp)
|
|
loff_t ext4_llseek(struct file *file, loff_t offset, int whence)
|
|
{
|
|
struct inode *inode = file->f_mapping->host;
|
|
- loff_t maxbytes;
|
|
-
|
|
- if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
|
|
- maxbytes = EXT4_SB(inode->i_sb)->s_bitmap_maxbytes;
|
|
- else
|
|
- maxbytes = inode->i_sb->s_maxbytes;
|
|
+ loff_t maxbytes = ext4_get_maxbytes(inode);
|
|
|
|
switch (whence) {
|
|
default:
|
|
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
|
|
index 3f363276ddd360..c85647a0ba09fb 100644
|
|
--- a/fs/ext4/inline.c
|
|
+++ b/fs/ext4/inline.c
|
|
@@ -392,7 +392,7 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
|
|
}
|
|
|
|
static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
|
|
- unsigned int len)
|
|
+ loff_t len)
|
|
{
|
|
int ret, size, no_expand;
|
|
struct ext4_inode_info *ei = EXT4_I(inode);
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index 86245e27be18db..9694ef6b996e47 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -1011,7 +1011,12 @@ int ext4_walk_page_buffers(handle_t *handle, struct inode *inode,
|
|
*/
|
|
static int ext4_dirty_journalled_data(handle_t *handle, struct buffer_head *bh)
|
|
{
|
|
- folio_mark_dirty(bh->b_folio);
|
|
+ struct folio *folio = bh->b_folio;
|
|
+ struct inode *inode = folio->mapping->host;
|
|
+
|
|
+ /* only regular files have a_ops */
|
|
+ if (S_ISREG(inode->i_mode))
|
|
+ folio_mark_dirty(folio);
|
|
return ext4_handle_dirty_metadata(handle, NULL, bh);
|
|
}
|
|
|
|
@@ -4939,7 +4944,8 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
|
|
ei->i_file_acl |=
|
|
((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
|
|
inode->i_size = ext4_isize(sb, raw_inode);
|
|
- if ((size = i_size_read(inode)) < 0) {
|
|
+ size = i_size_read(inode);
|
|
+ if (size < 0 || size > ext4_get_maxbytes(inode)) {
|
|
ext4_error_inode(inode, function, line, 0,
|
|
"iget: bad i_size value: %lld", size);
|
|
ret = -EFSCORRUPTED;
|
|
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
|
|
index f7ef69f44f3d84..e962de4ecaa2f6 100644
|
|
--- a/fs/f2fs/compress.c
|
|
+++ b/fs/f2fs/compress.c
|
|
@@ -176,8 +176,7 @@ void f2fs_compress_ctx_add_page(struct compress_ctx *cc, struct page *page)
|
|
#ifdef CONFIG_F2FS_FS_LZO
|
|
static int lzo_init_compress_ctx(struct compress_ctx *cc)
|
|
{
|
|
- cc->private = f2fs_kvmalloc(F2FS_I_SB(cc->inode),
|
|
- LZO1X_MEM_COMPRESS, GFP_NOFS);
|
|
+ cc->private = f2fs_vmalloc(LZO1X_MEM_COMPRESS);
|
|
if (!cc->private)
|
|
return -ENOMEM;
|
|
|
|
@@ -187,7 +186,7 @@ static int lzo_init_compress_ctx(struct compress_ctx *cc)
|
|
|
|
static void lzo_destroy_compress_ctx(struct compress_ctx *cc)
|
|
{
|
|
- kvfree(cc->private);
|
|
+ vfree(cc->private);
|
|
cc->private = NULL;
|
|
}
|
|
|
|
@@ -244,7 +243,7 @@ static int lz4_init_compress_ctx(struct compress_ctx *cc)
|
|
size = LZ4HC_MEM_COMPRESS;
|
|
#endif
|
|
|
|
- cc->private = f2fs_kvmalloc(F2FS_I_SB(cc->inode), size, GFP_NOFS);
|
|
+ cc->private = f2fs_vmalloc(size);
|
|
if (!cc->private)
|
|
return -ENOMEM;
|
|
|
|
@@ -259,7 +258,7 @@ static int lz4_init_compress_ctx(struct compress_ctx *cc)
|
|
|
|
static void lz4_destroy_compress_ctx(struct compress_ctx *cc)
|
|
{
|
|
- kvfree(cc->private);
|
|
+ vfree(cc->private);
|
|
cc->private = NULL;
|
|
}
|
|
|
|
@@ -340,8 +339,7 @@ static int zstd_init_compress_ctx(struct compress_ctx *cc)
|
|
params = zstd_get_params(level, cc->rlen);
|
|
workspace_size = zstd_cstream_workspace_bound(¶ms.cParams);
|
|
|
|
- workspace = f2fs_kvmalloc(F2FS_I_SB(cc->inode),
|
|
- workspace_size, GFP_NOFS);
|
|
+ workspace = f2fs_vmalloc(workspace_size);
|
|
if (!workspace)
|
|
return -ENOMEM;
|
|
|
|
@@ -349,7 +347,7 @@ static int zstd_init_compress_ctx(struct compress_ctx *cc)
|
|
if (!stream) {
|
|
f2fs_err_ratelimited(F2FS_I_SB(cc->inode),
|
|
"%s zstd_init_cstream failed", __func__);
|
|
- kvfree(workspace);
|
|
+ vfree(workspace);
|
|
return -EIO;
|
|
}
|
|
|
|
@@ -362,7 +360,7 @@ static int zstd_init_compress_ctx(struct compress_ctx *cc)
|
|
|
|
static void zstd_destroy_compress_ctx(struct compress_ctx *cc)
|
|
{
|
|
- kvfree(cc->private);
|
|
+ vfree(cc->private);
|
|
cc->private = NULL;
|
|
cc->private2 = NULL;
|
|
}
|
|
@@ -421,8 +419,7 @@ static int zstd_init_decompress_ctx(struct decompress_io_ctx *dic)
|
|
|
|
workspace_size = zstd_dstream_workspace_bound(max_window_size);
|
|
|
|
- workspace = f2fs_kvmalloc(F2FS_I_SB(dic->inode),
|
|
- workspace_size, GFP_NOFS);
|
|
+ workspace = f2fs_vmalloc(workspace_size);
|
|
if (!workspace)
|
|
return -ENOMEM;
|
|
|
|
@@ -430,7 +427,7 @@ static int zstd_init_decompress_ctx(struct decompress_io_ctx *dic)
|
|
if (!stream) {
|
|
f2fs_err_ratelimited(F2FS_I_SB(dic->inode),
|
|
"%s zstd_init_dstream failed", __func__);
|
|
- kvfree(workspace);
|
|
+ vfree(workspace);
|
|
return -EIO;
|
|
}
|
|
|
|
@@ -442,7 +439,7 @@ static int zstd_init_decompress_ctx(struct decompress_io_ctx *dic)
|
|
|
|
static void zstd_destroy_decompress_ctx(struct decompress_io_ctx *dic)
|
|
{
|
|
- kvfree(dic->private);
|
|
+ vfree(dic->private);
|
|
dic->private = NULL;
|
|
dic->private2 = NULL;
|
|
}
|
|
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
|
|
index 911c4c64d729d3..2d9a86129bd8de 100644
|
|
--- a/fs/f2fs/f2fs.h
|
|
+++ b/fs/f2fs/f2fs.h
|
|
@@ -3449,6 +3449,11 @@ static inline void *f2fs_kvzalloc(struct f2fs_sb_info *sbi,
|
|
return f2fs_kvmalloc(sbi, size, flags | __GFP_ZERO);
|
|
}
|
|
|
|
+static inline void *f2fs_vmalloc(size_t size)
|
|
+{
|
|
+ return vmalloc(size);
|
|
+}
|
|
+
|
|
static inline int get_extra_isize(struct inode *inode)
|
|
{
|
|
return F2FS_I(inode)->i_extra_isize / sizeof(__le32);
|
|
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
|
|
index 06941705e8939f..66721c2093c023 100644
|
|
--- a/fs/f2fs/inode.c
|
|
+++ b/fs/f2fs/inode.c
|
|
@@ -35,7 +35,9 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
|
|
if (f2fs_inode_dirtied(inode, sync))
|
|
return;
|
|
|
|
- if (f2fs_is_atomic_file(inode))
|
|
+ /* only atomic file w/ FI_ATOMIC_COMMITTED can be set vfs dirty */
|
|
+ if (f2fs_is_atomic_file(inode) &&
|
|
+ !is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
|
|
return;
|
|
|
|
mark_inode_dirty_sync(inode);
|
|
@@ -285,6 +287,12 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
|
|
return false;
|
|
}
|
|
|
|
+ if (ino_of_node(node_page) == fi->i_xattr_nid) {
|
|
+ f2fs_warn(sbi, "%s: corrupted inode i_ino=%lx, xnid=%x, run fsck to fix.",
|
|
+ __func__, inode->i_ino, fi->i_xattr_nid);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
if (f2fs_has_extra_attr(inode)) {
|
|
if (!f2fs_sb_has_extra_attr(sbi)) {
|
|
f2fs_warn(sbi, "%s: inode (ino=%lx) is with extra_attr, but extra_attr feature is off",
|
|
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
|
|
index 4d6f0a6365fe19..523009bc273209 100644
|
|
--- a/fs/f2fs/namei.c
|
|
+++ b/fs/f2fs/namei.c
|
|
@@ -560,6 +560,15 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
|
|
goto fail;
|
|
}
|
|
|
|
+ if (unlikely(inode->i_nlink == 0)) {
|
|
+ f2fs_warn(F2FS_I_SB(inode), "%s: inode (ino=%lx) has zero i_nlink",
|
|
+ __func__, inode->i_ino);
|
|
+ err = -EFSCORRUPTED;
|
|
+ set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
|
|
+ f2fs_put_page(page, 0);
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
f2fs_balance_fs(sbi, true);
|
|
|
|
f2fs_lock_op(sbi);
|
|
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
|
|
index 156d92b945258a..c7714e954cb540 100644
|
|
--- a/fs/f2fs/segment.c
|
|
+++ b/fs/f2fs/segment.c
|
|
@@ -372,7 +372,13 @@ static int __f2fs_commit_atomic_write(struct inode *inode)
|
|
} else {
|
|
sbi->committed_atomic_block += fi->atomic_write_cnt;
|
|
set_inode_flag(inode, FI_ATOMIC_COMMITTED);
|
|
+
|
|
+ /*
|
|
+ * inode may has no FI_ATOMIC_DIRTIED flag due to no write
|
|
+ * before commit.
|
|
+ */
|
|
if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
|
|
+ /* clear atomic dirty status and set vfs dirty status */
|
|
clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
|
|
f2fs_mark_inode_dirty_sync(inode, true);
|
|
}
|
|
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
|
|
index 6b3cafbe98672e..702137eafaa675 100644
|
|
--- a/fs/f2fs/super.c
|
|
+++ b/fs/f2fs/super.c
|
|
@@ -1500,7 +1500,9 @@ int f2fs_inode_dirtied(struct inode *inode, bool sync)
|
|
}
|
|
spin_unlock(&sbi->inode_lock[DIRTY_META]);
|
|
|
|
- if (!ret && f2fs_is_atomic_file(inode))
|
|
+ /* if atomic write is not committed, set inode w/ atomic dirty */
|
|
+ if (!ret && f2fs_is_atomic_file(inode) &&
|
|
+ !is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
|
|
set_inode_flag(inode, FI_ATOMIC_DIRTIED);
|
|
|
|
return ret;
|
|
@@ -3608,6 +3610,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
|
block_t user_block_count, valid_user_blocks;
|
|
block_t avail_node_count, valid_node_count;
|
|
unsigned int nat_blocks, nat_bits_bytes, nat_bits_blocks;
|
|
+ unsigned int sit_blk_cnt;
|
|
int i, j;
|
|
|
|
total = le32_to_cpu(raw_super->segment_count);
|
|
@@ -3719,6 +3722,13 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
|
|
return 1;
|
|
}
|
|
|
|
+ sit_blk_cnt = DIV_ROUND_UP(main_segs, SIT_ENTRY_PER_BLOCK);
|
|
+ if (sit_bitmap_size * 8 < sit_blk_cnt) {
|
|
+ f2fs_err(sbi, "Wrong bitmap size: sit: %u, sit_blk_cnt:%u",
|
|
+ sit_bitmap_size, sit_blk_cnt);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
cp_pack_start_sum = __start_sum_addr(sbi);
|
|
cp_payload = __cp_payload(sbi);
|
|
if (cp_pack_start_sum < cp_payload + 1 ||
|
|
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
|
|
index e028e55e67d95f..07aac73377d8fe 100644
|
|
--- a/fs/gfs2/lock_dlm.c
|
|
+++ b/fs/gfs2/lock_dlm.c
|
|
@@ -959,14 +959,15 @@ static int control_mount(struct gfs2_sbd *sdp)
|
|
if (sdp->sd_args.ar_spectator) {
|
|
fs_info(sdp, "Recovery is required. Waiting for a "
|
|
"non-spectator to mount.\n");
|
|
+ spin_unlock(&ls->ls_recover_spin);
|
|
msleep_interruptible(1000);
|
|
} else {
|
|
fs_info(sdp, "control_mount wait1 block %u start %u "
|
|
"mount %u lvb %u flags %lx\n", block_gen,
|
|
start_gen, mount_gen, lvb_gen,
|
|
ls->ls_recover_flags);
|
|
+ spin_unlock(&ls->ls_recover_spin);
|
|
}
|
|
- spin_unlock(&ls->ls_recover_spin);
|
|
goto restart;
|
|
}
|
|
|
|
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
|
|
index 76adab83cac368..c2b8ad0b24c443 100644
|
|
--- a/fs/jbd2/transaction.c
|
|
+++ b/fs/jbd2/transaction.c
|
|
@@ -1499,7 +1499,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
|
|
jh->b_next_transaction == transaction);
|
|
spin_unlock(&jh->b_state_lock);
|
|
}
|
|
- if (jh->b_modified == 1) {
|
|
+ if (data_race(jh->b_modified == 1)) {
|
|
/* If it's in our transaction it must be in BJ_Metadata list. */
|
|
if (data_race(jh->b_transaction == transaction &&
|
|
jh->b_jlist != BJ_Metadata)) {
|
|
@@ -1518,7 +1518,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
|
|
goto out;
|
|
}
|
|
|
|
- journal = transaction->t_journal;
|
|
spin_lock(&jh->b_state_lock);
|
|
|
|
if (is_handle_aborted(handle)) {
|
|
@@ -1533,6 +1532,8 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
|
|
goto out_unlock_bh;
|
|
}
|
|
|
|
+ journal = transaction->t_journal;
|
|
+
|
|
if (jh->b_modified == 0) {
|
|
/*
|
|
* This buffer's got modified and becoming part
|
|
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
|
|
index ef3a1e1b6cb065..fda9f4d6093f94 100644
|
|
--- a/fs/jffs2/erase.c
|
|
+++ b/fs/jffs2/erase.c
|
|
@@ -425,7 +425,9 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
|
|
.totlen = cpu_to_je32(c->cleanmarker_size)
|
|
};
|
|
|
|
- jffs2_prealloc_raw_node_refs(c, jeb, 1);
|
|
+ ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
|
|
+ if (ret)
|
|
+ goto filebad;
|
|
|
|
marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
|
|
|
|
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
|
|
index 29671e33a1714c..62879c218d4b11 100644
|
|
--- a/fs/jffs2/scan.c
|
|
+++ b/fs/jffs2/scan.c
|
|
@@ -256,7 +256,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
|
|
|
|
jffs2_dbg(1, "%s(): Skipping %d bytes in nextblock to ensure page alignment\n",
|
|
__func__, skip);
|
|
- jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
|
|
+ ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
|
|
+ if (ret)
|
|
+ goto out;
|
|
jffs2_scan_dirty_space(c, c->nextblock, skip);
|
|
}
|
|
#endif
|
|
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
|
|
index 4fe64519870f1a..d83372d3e1a07b 100644
|
|
--- a/fs/jffs2/summary.c
|
|
+++ b/fs/jffs2/summary.c
|
|
@@ -858,7 +858,10 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
|
|
spin_unlock(&c->erase_completion_lock);
|
|
|
|
jeb = c->nextblock;
|
|
- jffs2_prealloc_raw_node_refs(c, jeb, 1);
|
|
+ ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
|
|
+
|
|
+ if (ret)
|
|
+ goto out;
|
|
|
|
if (!c->summary->sum_num || !c->summary->sum_list_head) {
|
|
JFFS2_WARNING("Empty summary info!!!\n");
|
|
@@ -872,6 +875,8 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
|
|
datasize += padsize;
|
|
|
|
ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
|
|
+
|
|
+out:
|
|
spin_lock(&c->erase_completion_lock);
|
|
return ret;
|
|
}
|
|
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
|
|
index a142287d86f68e..688a24e9bc8bb8 100644
|
|
--- a/fs/nfs/read.c
|
|
+++ b/fs/nfs/read.c
|
|
@@ -56,7 +56,8 @@ static int nfs_return_empty_folio(struct folio *folio)
|
|
{
|
|
folio_zero_segment(folio, 0, folio_size(folio));
|
|
folio_mark_uptodate(folio);
|
|
- folio_unlock(folio);
|
|
+ if (nfs_netfs_folio_unlock(folio))
|
|
+ folio_unlock(folio);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
|
|
index b3eca08f15b13e..b2bbf3d6d177e8 100644
|
|
--- a/fs/nfsd/nfs4proc.c
|
|
+++ b/fs/nfsd/nfs4proc.c
|
|
@@ -3580,7 +3580,8 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
|
|
struct nfs4_op_map *allow = &cstate->clp->cl_spo_must_allow;
|
|
u32 opiter;
|
|
|
|
- if (!cstate->minorversion)
|
|
+ if (rqstp->rq_procinfo != &nfsd_version4.vs_proc[NFSPROC4_COMPOUND] ||
|
|
+ cstate->minorversion == 0)
|
|
return false;
|
|
|
|
if (cstate->spo_must_allowed)
|
|
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
|
|
index 710a54c7dffc54..623f522b156599 100644
|
|
--- a/fs/nfsd/nfssvc.c
|
|
+++ b/fs/nfsd/nfssvc.c
|
|
@@ -432,13 +432,13 @@ static int nfsd_startup_net(struct net *net, const struct cred *cred)
|
|
if (ret)
|
|
goto out_filecache;
|
|
|
|
+#ifdef CONFIG_NFSD_V4_2_INTER_SSC
|
|
+ nfsd4_ssc_init_umount_work(nn);
|
|
+#endif
|
|
ret = nfs4_state_start_net(net);
|
|
if (ret)
|
|
goto out_reply_cache;
|
|
|
|
-#ifdef CONFIG_NFSD_V4_2_INTER_SSC
|
|
- nfsd4_ssc_init_umount_work(nn);
|
|
-#endif
|
|
nn->nfsd_net_up = true;
|
|
return 0;
|
|
|
|
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
|
|
index 74979466729535..d64742ba371aa5 100644
|
|
--- a/fs/smb/client/cached_dir.c
|
|
+++ b/fs/smb/client/cached_dir.c
|
|
@@ -484,8 +484,17 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
|
|
spin_lock(&cfids->cfid_list_lock);
|
|
list_for_each_entry(cfid, &cfids->entries, entry) {
|
|
tmp_list = kmalloc(sizeof(*tmp_list), GFP_ATOMIC);
|
|
- if (tmp_list == NULL)
|
|
- break;
|
|
+ if (tmp_list == NULL) {
|
|
+ /*
|
|
+ * If the malloc() fails, we won't drop all
|
|
+ * dentries, and unmounting is likely to trigger
|
|
+ * a 'Dentry still in use' error.
|
|
+ */
|
|
+ cifs_tcon_dbg(VFS, "Out of memory while dropping dentries\n");
|
|
+ spin_unlock(&cfids->cfid_list_lock);
|
|
+ spin_unlock(&cifs_sb->tlink_tree_lock);
|
|
+ goto done;
|
|
+ }
|
|
spin_lock(&cfid->fid_lock);
|
|
tmp_list->dentry = cfid->dentry;
|
|
cfid->dentry = NULL;
|
|
@@ -497,6 +506,7 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
|
|
}
|
|
spin_unlock(&cifs_sb->tlink_tree_lock);
|
|
|
|
+done:
|
|
list_for_each_entry_safe(tmp_list, q, &entry, entry) {
|
|
list_del(&tmp_list->entry);
|
|
dput(tmp_list->dentry);
|
|
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
|
|
index 1dfe79d947a62f..bc8a812ff95f8b 100644
|
|
--- a/fs/smb/client/cached_dir.h
|
|
+++ b/fs/smb/client/cached_dir.h
|
|
@@ -21,10 +21,10 @@ struct cached_dirent {
|
|
struct cached_dirents {
|
|
bool is_valid:1;
|
|
bool is_failed:1;
|
|
- struct dir_context *ctx; /*
|
|
- * Only used to make sure we only take entries
|
|
- * from a single context. Never dereferenced.
|
|
- */
|
|
+ struct file *file; /*
|
|
+ * Used to associate the cache with a single
|
|
+ * open file instance.
|
|
+ */
|
|
struct mutex de_mutex;
|
|
int pos; /* Expected ctx->pos */
|
|
struct list_head entries;
|
|
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
|
|
index 39117343b703fa..6a4ed99e162c5d 100644
|
|
--- a/fs/smb/client/cifsglob.h
|
|
+++ b/fs/smb/client/cifsglob.h
|
|
@@ -1053,6 +1053,7 @@ struct cifs_chan {
|
|
};
|
|
|
|
#define CIFS_SES_FLAG_SCALE_CHANNELS (0x1)
|
|
+#define CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES (0x2)
|
|
|
|
/*
|
|
* Session structure. One of these for each uid session with a particular host
|
|
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
|
|
index 3faaee33ad4558..8fa5fe0a8c5c59 100644
|
|
--- a/fs/smb/client/connect.c
|
|
+++ b/fs/smb/client/connect.c
|
|
@@ -132,13 +132,9 @@ static void smb2_query_server_interfaces(struct work_struct *work)
|
|
rc = server->ops->query_server_interfaces(xid, tcon, false);
|
|
free_xid(xid);
|
|
|
|
- if (rc) {
|
|
- if (rc == -EOPNOTSUPP)
|
|
- return;
|
|
-
|
|
+ if (rc)
|
|
cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
|
|
__func__, rc);
|
|
- }
|
|
|
|
queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
|
|
(SMB_INTERFACE_POLL_INTERVAL * HZ));
|
|
@@ -393,6 +389,13 @@ static int __cifs_reconnect(struct TCP_Server_Info *server,
|
|
if (!cifs_tcp_ses_needs_reconnect(server, 1))
|
|
return 0;
|
|
|
|
+ /*
|
|
+ * if smb session has been marked for reconnect, also reconnect all
|
|
+ * connections. This way, the other connections do not end up bad.
|
|
+ */
|
|
+ if (mark_smb_session)
|
|
+ cifs_signal_cifsd_for_reconnect(server, mark_smb_session);
|
|
+
|
|
cifs_mark_tcp_ses_conns_for_reconnect(server, mark_smb_session);
|
|
|
|
cifs_abort_connection(server);
|
|
@@ -401,7 +404,8 @@ static int __cifs_reconnect(struct TCP_Server_Info *server,
|
|
try_to_freeze();
|
|
cifs_server_lock(server);
|
|
|
|
- if (!cifs_swn_set_server_dstaddr(server)) {
|
|
+ if (!cifs_swn_set_server_dstaddr(server) &&
|
|
+ !SERVER_IS_CHAN(server)) {
|
|
/* resolve the hostname again to make sure that IP address is up-to-date */
|
|
rc = reconn_set_ipaddr_from_hostname(server);
|
|
cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc);
|
|
@@ -3978,6 +3982,7 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
|
|
return 0;
|
|
}
|
|
|
|
+ server->lstrp = jiffies;
|
|
server->tcpStatus = CifsInNegotiate;
|
|
spin_unlock(&server->srv_lock);
|
|
|
|
diff --git a/fs/smb/client/namespace.c b/fs/smb/client/namespace.c
|
|
index 830f2a292bb00d..ec58c0e507244b 100644
|
|
--- a/fs/smb/client/namespace.c
|
|
+++ b/fs/smb/client/namespace.c
|
|
@@ -146,6 +146,9 @@ static char *automount_fullpath(struct dentry *dentry, void *page)
|
|
}
|
|
spin_unlock(&tcon->tc_lock);
|
|
|
|
+ if (unlikely(!page))
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+
|
|
s = dentry_path_raw(dentry, page, PATH_MAX);
|
|
if (IS_ERR(s))
|
|
return s;
|
|
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
|
|
index e616be8196deda..222348ae625866 100644
|
|
--- a/fs/smb/client/readdir.c
|
|
+++ b/fs/smb/client/readdir.c
|
|
@@ -850,9 +850,9 @@ static bool emit_cached_dirents(struct cached_dirents *cde,
|
|
}
|
|
|
|
static void update_cached_dirents_count(struct cached_dirents *cde,
|
|
- struct dir_context *ctx)
|
|
+ struct file *file)
|
|
{
|
|
- if (cde->ctx != ctx)
|
|
+ if (cde->file != file)
|
|
return;
|
|
if (cde->is_valid || cde->is_failed)
|
|
return;
|
|
@@ -861,9 +861,9 @@ static void update_cached_dirents_count(struct cached_dirents *cde,
|
|
}
|
|
|
|
static void finished_cached_dirents_count(struct cached_dirents *cde,
|
|
- struct dir_context *ctx)
|
|
+ struct dir_context *ctx, struct file *file)
|
|
{
|
|
- if (cde->ctx != ctx)
|
|
+ if (cde->file != file)
|
|
return;
|
|
if (cde->is_valid || cde->is_failed)
|
|
return;
|
|
@@ -876,11 +876,12 @@ static void finished_cached_dirents_count(struct cached_dirents *cde,
|
|
static void add_cached_dirent(struct cached_dirents *cde,
|
|
struct dir_context *ctx,
|
|
const char *name, int namelen,
|
|
- struct cifs_fattr *fattr)
|
|
+ struct cifs_fattr *fattr,
|
|
+ struct file *file)
|
|
{
|
|
struct cached_dirent *de;
|
|
|
|
- if (cde->ctx != ctx)
|
|
+ if (cde->file != file)
|
|
return;
|
|
if (cde->is_valid || cde->is_failed)
|
|
return;
|
|
@@ -910,7 +911,8 @@ static void add_cached_dirent(struct cached_dirents *cde,
|
|
static bool cifs_dir_emit(struct dir_context *ctx,
|
|
const char *name, int namelen,
|
|
struct cifs_fattr *fattr,
|
|
- struct cached_fid *cfid)
|
|
+ struct cached_fid *cfid,
|
|
+ struct file *file)
|
|
{
|
|
bool rc;
|
|
ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
|
|
@@ -922,7 +924,7 @@ static bool cifs_dir_emit(struct dir_context *ctx,
|
|
if (cfid) {
|
|
mutex_lock(&cfid->dirents.de_mutex);
|
|
add_cached_dirent(&cfid->dirents, ctx, name, namelen,
|
|
- fattr);
|
|
+ fattr, file);
|
|
mutex_unlock(&cfid->dirents.de_mutex);
|
|
}
|
|
|
|
@@ -1022,7 +1024,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
|
|
cifs_prime_dcache(file_dentry(file), &name, &fattr);
|
|
|
|
return !cifs_dir_emit(ctx, name.name, name.len,
|
|
- &fattr, cfid);
|
|
+ &fattr, cfid, file);
|
|
}
|
|
|
|
|
|
@@ -1073,8 +1075,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
|
|
* we need to initialize scanning and storing the
|
|
* directory content.
|
|
*/
|
|
- if (ctx->pos == 0 && cfid->dirents.ctx == NULL) {
|
|
- cfid->dirents.ctx = ctx;
|
|
+ if (ctx->pos == 0 && cfid->dirents.file == NULL) {
|
|
+ cfid->dirents.file = file;
|
|
cfid->dirents.pos = 2;
|
|
}
|
|
/*
|
|
@@ -1142,7 +1144,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
|
|
} else {
|
|
if (cfid) {
|
|
mutex_lock(&cfid->dirents.de_mutex);
|
|
- finished_cached_dirents_count(&cfid->dirents, ctx);
|
|
+ finished_cached_dirents_count(&cfid->dirents, ctx, file);
|
|
mutex_unlock(&cfid->dirents.de_mutex);
|
|
}
|
|
cifs_dbg(FYI, "Could not find entry\n");
|
|
@@ -1183,7 +1185,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
|
|
ctx->pos++;
|
|
if (cfid) {
|
|
mutex_lock(&cfid->dirents.de_mutex);
|
|
- update_cached_dirents_count(&cfid->dirents, ctx);
|
|
+ update_cached_dirents_count(&cfid->dirents, file);
|
|
mutex_unlock(&cfid->dirents.de_mutex);
|
|
}
|
|
|
|
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
|
|
index b6556fe3dfa11a..4d45c31336df17 100644
|
|
--- a/fs/smb/client/reparse.c
|
|
+++ b/fs/smb/client/reparse.c
|
|
@@ -738,7 +738,6 @@ static bool wsl_to_fattr(struct cifs_open_info_data *data,
|
|
if (!have_xattr_dev && (tag == IO_REPARSE_TAG_LX_CHR || tag == IO_REPARSE_TAG_LX_BLK))
|
|
return false;
|
|
|
|
- fattr->cf_dtype = S_DT(fattr->cf_mode);
|
|
return true;
|
|
}
|
|
|
|
diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
|
|
index f04922eb45d4c9..8959206a0353eb 100644
|
|
--- a/fs/smb/client/sess.c
|
|
+++ b/fs/smb/client/sess.c
|
|
@@ -485,6 +485,10 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
|
|
|
|
ses->chans[chan_index].iface = iface;
|
|
spin_unlock(&ses->chan_lock);
|
|
+
|
|
+ spin_lock(&server->srv_lock);
|
|
+ memcpy(&server->dstaddr, &iface->sockaddr, sizeof(server->dstaddr));
|
|
+ spin_unlock(&server->srv_lock);
|
|
}
|
|
|
|
/*
|
|
@@ -554,8 +558,7 @@ cifs_ses_add_channel(struct cifs_ses *ses,
|
|
ctx->domainauto = ses->domainAuto;
|
|
ctx->domainname = ses->domainName;
|
|
|
|
- /* no hostname for extra channels */
|
|
- ctx->server_hostname = "";
|
|
+ ctx->server_hostname = ses->server->hostname;
|
|
|
|
ctx->username = ses->user_name;
|
|
ctx->password = ses->password;
|
|
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
|
|
index 3e88e8b3c16ec2..e0f58600933059 100644
|
|
--- a/fs/smb/client/smb2pdu.c
|
|
+++ b/fs/smb/client/smb2pdu.c
|
|
@@ -425,14 +425,23 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
if (!rc &&
|
|
(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) &&
|
|
server->ops->query_server_interfaces) {
|
|
- mutex_unlock(&ses->session_mutex);
|
|
-
|
|
/*
|
|
- * query server network interfaces, in case they change
|
|
+ * query server network interfaces, in case they change.
|
|
+ * Also mark the session as pending this update while the query
|
|
+ * is in progress. This will be used to avoid calling
|
|
+ * smb2_reconnect recursively.
|
|
*/
|
|
+ ses->flags |= CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES;
|
|
xid = get_xid();
|
|
rc = server->ops->query_server_interfaces(xid, tcon, false);
|
|
free_xid(xid);
|
|
+ ses->flags &= ~CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES;
|
|
+
|
|
+ /* regardless of rc value, setup polling */
|
|
+ queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
|
|
+ (SMB_INTERFACE_POLL_INTERVAL * HZ));
|
|
+
|
|
+ mutex_unlock(&ses->session_mutex);
|
|
|
|
if (rc == -EOPNOTSUPP && ses->chan_count > 1) {
|
|
/*
|
|
@@ -452,11 +461,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
if (ses->chan_max > ses->chan_count &&
|
|
ses->iface_count &&
|
|
!SERVER_IS_CHAN(server)) {
|
|
- if (ses->chan_count == 1) {
|
|
+ if (ses->chan_count == 1)
|
|
cifs_server_dbg(VFS, "supports multichannel now\n");
|
|
- queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
|
|
- (SMB_INTERFACE_POLL_INTERVAL * HZ));
|
|
- }
|
|
|
|
cifs_try_adding_channels(ses);
|
|
}
|
|
@@ -574,11 +580,18 @@ static int smb2_ioctl_req_init(u32 opcode, struct cifs_tcon *tcon,
|
|
struct TCP_Server_Info *server,
|
|
void **request_buf, unsigned int *total_len)
|
|
{
|
|
- /* Skip reconnect only for FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs */
|
|
- if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) {
|
|
+ /*
|
|
+ * Skip reconnect in one of the following cases:
|
|
+ * 1. For FSCTL_VALIDATE_NEGOTIATE_INFO IOCTLs
|
|
+ * 2. For FSCTL_QUERY_NETWORK_INTERFACE_INFO IOCTL when called from
|
|
+ * smb2_reconnect (indicated by CIFS_SES_FLAG_SCALE_CHANNELS ses flag)
|
|
+ */
|
|
+ if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO ||
|
|
+ (opcode == FSCTL_QUERY_NETWORK_INTERFACE_INFO &&
|
|
+ (tcon->ses->flags & CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES)))
|
|
return __smb2_plain_req_init(SMB2_IOCTL, tcon, server,
|
|
request_buf, total_len);
|
|
- }
|
|
+
|
|
return smb2_plain_req_init(SMB2_IOCTL, tcon, server,
|
|
request_buf, total_len);
|
|
}
|
|
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
|
|
index 2269963e500819..7b2560612bd6aa 100644
|
|
--- a/fs/smb/client/transport.c
|
|
+++ b/fs/smb/client/transport.c
|
|
@@ -1025,14 +1025,16 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
|
|
uint index = 0;
|
|
unsigned int min_in_flight = UINT_MAX, max_in_flight = 0;
|
|
struct TCP_Server_Info *server = NULL;
|
|
- int i;
|
|
+ int i, start, cur;
|
|
|
|
if (!ses)
|
|
return NULL;
|
|
|
|
spin_lock(&ses->chan_lock);
|
|
+ start = atomic_inc_return(&ses->chan_seq);
|
|
for (i = 0; i < ses->chan_count; i++) {
|
|
- server = ses->chans[i].server;
|
|
+ cur = (start + i) % ses->chan_count;
|
|
+ server = ses->chans[cur].server;
|
|
if (!server || server->terminate)
|
|
continue;
|
|
|
|
@@ -1049,17 +1051,15 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
|
|
*/
|
|
if (server->in_flight < min_in_flight) {
|
|
min_in_flight = server->in_flight;
|
|
- index = i;
|
|
+ index = cur;
|
|
}
|
|
if (server->in_flight > max_in_flight)
|
|
max_in_flight = server->in_flight;
|
|
}
|
|
|
|
/* if all channels are equally loaded, fall back to round-robin */
|
|
- if (min_in_flight == max_in_flight) {
|
|
- index = (uint)atomic_inc_return(&ses->chan_seq);
|
|
- index %= ses->chan_count;
|
|
- }
|
|
+ if (min_in_flight == max_in_flight)
|
|
+ index = (uint)start % ses->chan_count;
|
|
|
|
server = ses->chans[index].server;
|
|
spin_unlock(&ses->chan_lock);
|
|
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
|
|
index 9bd817427a345a..d8325504a1624b 100644
|
|
--- a/fs/smb/server/smb2pdu.c
|
|
+++ b/fs/smb/server/smb2pdu.c
|
|
@@ -1599,17 +1599,18 @@ static int krb5_authenticate(struct ksmbd_work *work,
|
|
out_len = work->response_sz -
|
|
(le16_to_cpu(rsp->SecurityBufferOffset) + 4);
|
|
|
|
- /* Check previous session */
|
|
- prev_sess_id = le64_to_cpu(req->PreviousSessionId);
|
|
- if (prev_sess_id && prev_sess_id != sess->id)
|
|
- destroy_previous_session(conn, sess->user, prev_sess_id);
|
|
-
|
|
retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
|
|
out_blob, &out_len);
|
|
if (retval) {
|
|
ksmbd_debug(SMB, "krb5 authentication failed\n");
|
|
return -EINVAL;
|
|
}
|
|
+
|
|
+ /* Check previous session */
|
|
+ prev_sess_id = le64_to_cpu(req->PreviousSessionId);
|
|
+ if (prev_sess_id && prev_sess_id != sess->id)
|
|
+ destroy_previous_session(conn, sess->user, prev_sess_id);
|
|
+
|
|
rsp->SecurityBufferLength = cpu_to_le16(out_len);
|
|
|
|
if ((conn->sign || server_conf.enforced_signing) ||
|
|
diff --git a/fs/xattr.c b/fs/xattr.c
|
|
index 5fed22c22a2be8..7574d24b982ef6 100644
|
|
--- a/fs/xattr.c
|
|
+++ b/fs/xattr.c
|
|
@@ -1342,6 +1342,7 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
|
buffer += err;
|
|
}
|
|
remaining_size -= err;
|
|
+ err = 0;
|
|
|
|
read_lock(&xattrs->lock);
|
|
for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) {
|
|
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
|
|
index 85c2dcf2b70484..0a242008524151 100644
|
|
--- a/include/acpi/actypes.h
|
|
+++ b/include/acpi/actypes.h
|
|
@@ -527,7 +527,7 @@ typedef u64 acpi_integer;
|
|
|
|
/* Support for the special RSDP signature (8 characters) */
|
|
|
|
-#define ACPI_VALIDATE_RSDP_SIG(a) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8))
|
|
+#define ACPI_VALIDATE_RSDP_SIG(a) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, (sizeof(a) < 8) ? ACPI_NAMESEG_SIZE : 8))
|
|
#define ACPI_MAKE_RSDP_SIG(dest) (memcpy (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8))
|
|
|
|
/* Support for OEMx signature (x can be any character) */
|
|
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
|
|
index 1b76d2f83eac6a..7c6f4006389daa 100644
|
|
--- a/include/linux/acpi.h
|
|
+++ b/include/linux/acpi.h
|
|
@@ -1098,13 +1098,13 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
|
|
|
|
acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
|
|
u32 val_a, u32 val_b);
|
|
-#if defined(CONFIG_SUSPEND) && defined(CONFIG_X86)
|
|
struct acpi_s2idle_dev_ops {
|
|
struct list_head list_node;
|
|
void (*prepare)(void);
|
|
void (*check)(void);
|
|
void (*restore)(void);
|
|
};
|
|
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_X86)
|
|
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
|
|
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);
|
|
int acpi_get_lps0_constraint(struct acpi_device *adev);
|
|
@@ -1113,6 +1113,13 @@ static inline int acpi_get_lps0_constraint(struct device *dev)
|
|
{
|
|
return ACPI_STATE_UNKNOWN;
|
|
}
|
|
+static inline int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
|
|
+{
|
|
+ return -ENODEV;
|
|
+}
|
|
+static inline void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg)
|
|
+{
|
|
+}
|
|
#endif /* CONFIG_SUSPEND && CONFIG_X86 */
|
|
#ifndef CONFIG_IA64
|
|
void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
|
|
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
|
|
index 9b02961d65ee66..45f2f278b50a8a 100644
|
|
--- a/include/linux/atmdev.h
|
|
+++ b/include/linux/atmdev.h
|
|
@@ -249,6 +249,12 @@ static inline void atm_account_tx(struct atm_vcc *vcc, struct sk_buff *skb)
|
|
ATM_SKB(skb)->atm_options = vcc->atm_options;
|
|
}
|
|
|
|
+static inline void atm_return_tx(struct atm_vcc *vcc, struct sk_buff *skb)
|
|
+{
|
|
+ WARN_ON_ONCE(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize,
|
|
+ &sk_atm(vcc)->sk_wmem_alloc));
|
|
+}
|
|
+
|
|
static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
|
|
{
|
|
atomic_add(truesize, &sk_atm(vcc)->sk_rmem_alloc);
|
|
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
|
|
index fc2023d07f6931..8b051b8c40345d 100644
|
|
--- a/include/linux/hugetlb.h
|
|
+++ b/include/linux/hugetlb.h
|
|
@@ -281,6 +281,7 @@ long hugetlb_change_protection(struct vm_area_struct *vma,
|
|
|
|
bool is_hugetlb_entry_migration(pte_t pte);
|
|
void hugetlb_unshare_all_pmds(struct vm_area_struct *vma);
|
|
+void hugetlb_split(struct vm_area_struct *vma, unsigned long addr);
|
|
|
|
#else /* !CONFIG_HUGETLB_PAGE */
|
|
|
|
@@ -491,6 +492,8 @@ static inline vm_fault_t hugetlb_fault(struct mm_struct *mm,
|
|
|
|
static inline void hugetlb_unshare_all_pmds(struct vm_area_struct *vma) { }
|
|
|
|
+static inline void hugetlb_split(struct vm_area_struct *vma, unsigned long addr) {}
|
|
+
|
|
#endif /* !CONFIG_HUGETLB_PAGE */
|
|
/*
|
|
* hugepages at page global directory. If arch support
|
|
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
|
|
index afa575e362a473..7c6da19fff9f06 100644
|
|
--- a/include/linux/mmc/card.h
|
|
+++ b/include/linux/mmc/card.h
|
|
@@ -297,6 +297,7 @@ struct mmc_card {
|
|
#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 */
|
|
#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */
|
|
+#define MMC_QUIRK_NO_UHS_DDR50_TUNING (1<<18) /* Disable DDR50 tuning */
|
|
|
|
bool written_flag; /* Indicates eMMC has been written since power on */
|
|
bool reenable_cmdq; /* Re-enable Command Queue */
|
|
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
|
|
index 0b0a172337dbac..030d9de2ba2d23 100644
|
|
--- a/include/linux/netdevice.h
|
|
+++ b/include/linux/netdevice.h
|
|
@@ -3036,7 +3036,8 @@ extern rwlock_t dev_base_lock; /* Device list lock */
|
|
#define net_device_entry(lh) list_entry(lh, struct net_device, dev_list)
|
|
|
|
#define for_each_netdev_dump(net, d, ifindex) \
|
|
- xa_for_each_start(&(net)->dev_by_index, (ifindex), (d), (ifindex))
|
|
+ for (; (d = xa_find(&(net)->dev_by_index, &ifindex, \
|
|
+ ULONG_MAX, XA_PRESENT)); ifindex++)
|
|
|
|
static inline struct net_device *next_net_device(struct net_device *dev)
|
|
{
|
|
diff --git a/include/net/checksum.h b/include/net/checksum.h
|
|
index 1338cb92c8e72a..28b101f26636e8 100644
|
|
--- a/include/net/checksum.h
|
|
+++ b/include/net/checksum.h
|
|
@@ -158,7 +158,7 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
|
const __be32 *from, const __be32 *to,
|
|
bool pseudohdr);
|
|
void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
|
|
- __wsum diff, bool pseudohdr);
|
|
+ __wsum diff, bool pseudohdr, bool ipv6);
|
|
|
|
static __always_inline
|
|
void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
|
|
diff --git a/include/trace/events/erofs.h b/include/trace/events/erofs.h
|
|
index e18684b02c3dfa..0179af103d0f42 100644
|
|
--- a/include/trace/events/erofs.h
|
|
+++ b/include/trace/events/erofs.h
|
|
@@ -237,24 +237,6 @@ DEFINE_EVENT(erofs__map_blocks_exit, z_erofs_map_blocks_iter_exit,
|
|
TP_ARGS(inode, map, flags, ret)
|
|
);
|
|
|
|
-TRACE_EVENT(erofs_destroy_inode,
|
|
- TP_PROTO(struct inode *inode),
|
|
-
|
|
- TP_ARGS(inode),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field( dev_t, dev )
|
|
- __field( erofs_nid_t, nid )
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->dev = inode->i_sb->s_dev;
|
|
- __entry->nid = EROFS_I(inode)->nid;
|
|
- ),
|
|
-
|
|
- TP_printk("dev = (%d,%d), nid = %llu", show_dev_nid(__entry))
|
|
-);
|
|
-
|
|
#endif /* _TRACE_EROFS_H */
|
|
|
|
/* This part must be outside protection */
|
|
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
|
|
index c7f904a72af217..08a0494736e6e3 100644
|
|
--- a/include/uapi/linux/bpf.h
|
|
+++ b/include/uapi/linux/bpf.h
|
|
@@ -1913,6 +1913,7 @@ union bpf_attr {
|
|
* for updates resulting in a null checksum the value is set to
|
|
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
|
* the checksum is to be computed against a pseudo-header.
|
|
+ * Flag **BPF_F_IPV6** should be set for IPv6 packets.
|
|
*
|
|
* This helper works in combination with **bpf_csum_diff**\ (),
|
|
* which does not update the checksum in-place, but offers more
|
|
@@ -5920,6 +5921,7 @@ enum {
|
|
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
|
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
|
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
|
+ BPF_F_IPV6 = (1ULL << 7),
|
|
};
|
|
|
|
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
|
|
diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
|
|
index 93f3e4d1df853e..1c4ef4e4eb52b2 100644
|
|
--- a/io_uring/io-wq.c
|
|
+++ b/io_uring/io-wq.c
|
|
@@ -1206,8 +1206,10 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
|
|
atomic_set(&wq->worker_refs, 1);
|
|
init_completion(&wq->worker_done);
|
|
ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ put_task_struct(wq->task);
|
|
goto err;
|
|
+ }
|
|
|
|
return wq;
|
|
err:
|
|
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
|
|
index ff1a93d405e99e..897f07014c0193 100644
|
|
--- a/io_uring/io_uring.c
|
|
+++ b/io_uring/io_uring.c
|
|
@@ -1808,7 +1808,7 @@ static __cold void io_drain_req(struct io_kiocb *req)
|
|
spin_unlock(&ctx->completion_lock);
|
|
|
|
io_prep_async_link(req);
|
|
- de = kmalloc(sizeof(*de), GFP_KERNEL);
|
|
+ de = kmalloc(sizeof(*de), GFP_KERNEL_ACCOUNT);
|
|
if (!de) {
|
|
ret = -ENOMEM;
|
|
io_req_defer_failed(req, ret);
|
|
diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
|
|
index addd7c97365727..b2c381634393d2 100644
|
|
--- a/io_uring/kbuf.c
|
|
+++ b/io_uring/kbuf.c
|
|
@@ -560,7 +560,7 @@ int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
|
|
io_destroy_bl(ctx, bl);
|
|
}
|
|
|
|
- free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL);
|
|
+ free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL_ACCOUNT);
|
|
if (!bl)
|
|
return -ENOMEM;
|
|
|
|
diff --git a/ipc/shm.c b/ipc/shm.c
|
|
index 576a543b7cfff9..c4845689b7f68b 100644
|
|
--- a/ipc/shm.c
|
|
+++ b/ipc/shm.c
|
|
@@ -430,8 +430,11 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data)
|
|
void shm_destroy_orphaned(struct ipc_namespace *ns)
|
|
{
|
|
down_write(&shm_ids(ns).rwsem);
|
|
- if (shm_ids(ns).in_use)
|
|
+ if (shm_ids(ns).in_use) {
|
|
+ rcu_read_lock();
|
|
idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns);
|
|
+ rcu_read_unlock();
|
|
+ }
|
|
up_write(&shm_ids(ns).rwsem);
|
|
}
|
|
|
|
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
|
|
index 41d62405c85214..8f0b62b04deebe 100644
|
|
--- a/kernel/bpf/helpers.c
|
|
+++ b/kernel/bpf/helpers.c
|
|
@@ -128,7 +128,8 @@ const struct bpf_func_proto bpf_map_peek_elem_proto = {
|
|
|
|
BPF_CALL_3(bpf_map_lookup_percpu_elem, struct bpf_map *, map, void *, key, u32, cpu)
|
|
{
|
|
- WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
|
|
+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
|
|
+ !rcu_read_lock_bh_held());
|
|
return (unsigned long) map->ops->map_lookup_percpu_elem(map, key, cpu);
|
|
}
|
|
|
|
diff --git a/kernel/cgroup/legacy_freezer.c b/kernel/cgroup/legacy_freezer.c
|
|
index 66d1708042a72b..a3e13e6d5ee40d 100644
|
|
--- a/kernel/cgroup/legacy_freezer.c
|
|
+++ b/kernel/cgroup/legacy_freezer.c
|
|
@@ -189,13 +189,12 @@ static void freezer_attach(struct cgroup_taskset *tset)
|
|
if (!(freezer->state & CGROUP_FREEZING)) {
|
|
__thaw_task(task);
|
|
} else {
|
|
- freeze_task(task);
|
|
-
|
|
/* clear FROZEN and propagate upwards */
|
|
while (freezer && (freezer->state & CGROUP_FROZEN)) {
|
|
freezer->state &= ~CGROUP_FROZEN;
|
|
freezer = parent_freezer(freezer);
|
|
}
|
|
+ freeze_task(task);
|
|
}
|
|
}
|
|
|
|
diff --git a/kernel/events/core.c b/kernel/events/core.c
|
|
index 563f39518f7fe6..873b17545717cb 100644
|
|
--- a/kernel/events/core.c
|
|
+++ b/kernel/events/core.c
|
|
@@ -171,6 +171,19 @@ static void perf_ctx_unlock(struct perf_cpu_context *cpuctx,
|
|
raw_spin_unlock(&cpuctx->ctx.lock);
|
|
}
|
|
|
|
+typedef struct {
|
|
+ struct perf_cpu_context *cpuctx;
|
|
+ struct perf_event_context *ctx;
|
|
+} class_perf_ctx_lock_t;
|
|
+
|
|
+static inline void class_perf_ctx_lock_destructor(class_perf_ctx_lock_t *_T)
|
|
+{ perf_ctx_unlock(_T->cpuctx, _T->ctx); }
|
|
+
|
|
+static inline class_perf_ctx_lock_t
|
|
+class_perf_ctx_lock_constructor(struct perf_cpu_context *cpuctx,
|
|
+ struct perf_event_context *ctx)
|
|
+{ perf_ctx_lock(cpuctx, ctx); return (class_perf_ctx_lock_t){ cpuctx, ctx }; }
|
|
+
|
|
#define TASK_TOMBSTONE ((void *)-1L)
|
|
|
|
static bool is_kernel_event(struct perf_event *event)
|
|
@@ -866,7 +879,13 @@ static void perf_cgroup_switch(struct task_struct *task)
|
|
if (READ_ONCE(cpuctx->cgrp) == cgrp)
|
|
return;
|
|
|
|
- perf_ctx_lock(cpuctx, cpuctx->task_ctx);
|
|
+ guard(perf_ctx_lock)(cpuctx, cpuctx->task_ctx);
|
|
+ /*
|
|
+ * Re-check, could've raced vs perf_remove_from_context().
|
|
+ */
|
|
+ if (READ_ONCE(cpuctx->cgrp) == NULL)
|
|
+ return;
|
|
+
|
|
perf_ctx_disable(&cpuctx->ctx, true);
|
|
|
|
ctx_sched_out(&cpuctx->ctx, EVENT_ALL|EVENT_CGROUP);
|
|
@@ -884,7 +903,6 @@ static void perf_cgroup_switch(struct task_struct *task)
|
|
ctx_sched_in(&cpuctx->ctx, EVENT_ALL|EVENT_CGROUP);
|
|
|
|
perf_ctx_enable(&cpuctx->ctx, true);
|
|
- perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
|
|
}
|
|
|
|
static int perf_cgroup_ensure_storage(struct perf_event *event,
|
|
@@ -2067,8 +2085,9 @@ perf_aux_output_match(struct perf_event *event, struct perf_event *aux_event)
|
|
}
|
|
|
|
static void put_event(struct perf_event *event);
|
|
-static void event_sched_out(struct perf_event *event,
|
|
- struct perf_event_context *ctx);
|
|
+static void __event_disable(struct perf_event *event,
|
|
+ struct perf_event_context *ctx,
|
|
+ enum perf_event_state state);
|
|
|
|
static void perf_put_aux_event(struct perf_event *event)
|
|
{
|
|
@@ -2101,8 +2120,7 @@ static void perf_put_aux_event(struct perf_event *event)
|
|
* state so that we don't try to schedule it again. Note
|
|
* that perf_event_enable() will clear the ERROR status.
|
|
*/
|
|
- event_sched_out(iter, ctx);
|
|
- perf_event_set_state(event, PERF_EVENT_STATE_ERROR);
|
|
+ __event_disable(iter, ctx, PERF_EVENT_STATE_ERROR);
|
|
}
|
|
}
|
|
|
|
@@ -2156,18 +2174,6 @@ static inline struct list_head *get_event_list(struct perf_event *event)
|
|
&event->pmu_ctx->flexible_active;
|
|
}
|
|
|
|
-/*
|
|
- * Events that have PERF_EV_CAP_SIBLING require being part of a group and
|
|
- * cannot exist on their own, schedule them out and move them into the ERROR
|
|
- * state. Also see _perf_event_enable(), it will not be able to recover
|
|
- * this ERROR state.
|
|
- */
|
|
-static inline void perf_remove_sibling_event(struct perf_event *event)
|
|
-{
|
|
- event_sched_out(event, event->ctx);
|
|
- perf_event_set_state(event, PERF_EVENT_STATE_ERROR);
|
|
-}
|
|
-
|
|
static void perf_group_detach(struct perf_event *event)
|
|
{
|
|
struct perf_event *leader = event->group_leader;
|
|
@@ -2203,8 +2209,15 @@ static void perf_group_detach(struct perf_event *event)
|
|
*/
|
|
list_for_each_entry_safe(sibling, tmp, &event->sibling_list, sibling_list) {
|
|
|
|
+ /*
|
|
+ * Events that have PERF_EV_CAP_SIBLING require being part of
|
|
+ * a group and cannot exist on their own, schedule them out
|
|
+ * and move them into the ERROR state. Also see
|
|
+ * _perf_event_enable(), it will not be able to recover this
|
|
+ * ERROR state.
|
|
+ */
|
|
if (sibling->event_caps & PERF_EV_CAP_SIBLING)
|
|
- perf_remove_sibling_event(sibling);
|
|
+ __event_disable(sibling, ctx, PERF_EVENT_STATE_ERROR);
|
|
|
|
sibling->group_leader = sibling;
|
|
list_del_init(&sibling->sibling_list);
|
|
@@ -2437,6 +2450,15 @@ static void perf_remove_from_context(struct perf_event *event, unsigned long fla
|
|
event_function_call(event, __perf_remove_from_context, (void *)flags);
|
|
}
|
|
|
|
+static void __event_disable(struct perf_event *event,
|
|
+ struct perf_event_context *ctx,
|
|
+ enum perf_event_state state)
|
|
+{
|
|
+ event_sched_out(event, ctx);
|
|
+ perf_cgroup_event_disable(event, ctx);
|
|
+ perf_event_set_state(event, state);
|
|
+}
|
|
+
|
|
/*
|
|
* Cross CPU call to disable a performance event
|
|
*/
|
|
@@ -2455,13 +2477,18 @@ static void __perf_event_disable(struct perf_event *event,
|
|
|
|
perf_pmu_disable(event->pmu_ctx->pmu);
|
|
|
|
+ /*
|
|
+ * When disabling a group leader, the whole group becomes ineligible
|
|
+ * to run, so schedule out the full group.
|
|
+ */
|
|
if (event == event->group_leader)
|
|
group_sched_out(event, ctx);
|
|
- else
|
|
- event_sched_out(event, ctx);
|
|
|
|
- perf_event_set_state(event, PERF_EVENT_STATE_OFF);
|
|
- perf_cgroup_event_disable(event, ctx);
|
|
+ /*
|
|
+ * But only mark the leader OFF; the siblings will remain
|
|
+ * INACTIVE.
|
|
+ */
|
|
+ __event_disable(event, ctx, PERF_EVENT_STATE_OFF);
|
|
|
|
perf_pmu_enable(event->pmu_ctx->pmu);
|
|
}
|
|
@@ -6987,6 +7014,10 @@ perf_sample_ustack_size(u16 stack_size, u16 header_size,
|
|
if (!regs)
|
|
return 0;
|
|
|
|
+ /* No mm, no stack, no dump. */
|
|
+ if (!current->mm)
|
|
+ return 0;
|
|
+
|
|
/*
|
|
* Check if we fit in with the requested stack size into the:
|
|
* - TASK_SIZE
|
|
@@ -7685,6 +7716,9 @@ perf_callchain(struct perf_event *event, struct pt_regs *regs)
|
|
const u32 max_stack = event->attr.sample_max_stack;
|
|
struct perf_callchain_entry *callchain;
|
|
|
|
+ if (!current->mm)
|
|
+ user = false;
|
|
+
|
|
if (!kernel && !user)
|
|
return &__empty_callchain;
|
|
|
|
diff --git a/kernel/exit.c b/kernel/exit.c
|
|
index 3540b2c9b1b6a0..03a1dd32e6ff3c 100644
|
|
--- a/kernel/exit.c
|
|
+++ b/kernel/exit.c
|
|
@@ -858,6 +858,15 @@ void __noreturn do_exit(long code)
|
|
tsk->exit_code = code;
|
|
taskstats_exit(tsk, group_dead);
|
|
|
|
+ /*
|
|
+ * Since sampling can touch ->mm, make sure to stop everything before we
|
|
+ * tear it down.
|
|
+ *
|
|
+ * Also flushes inherited counters to the parent - before the parent
|
|
+ * gets woken up by child-exit notifications.
|
|
+ */
|
|
+ perf_event_exit_task(tsk);
|
|
+
|
|
exit_mm();
|
|
|
|
if (group_dead)
|
|
@@ -874,14 +883,6 @@ void __noreturn do_exit(long code)
|
|
exit_task_work(tsk);
|
|
exit_thread(tsk);
|
|
|
|
- /*
|
|
- * Flush inherited counters to the parent - before the parent
|
|
- * gets woken up by child-exit notifications.
|
|
- *
|
|
- * because of cgroup mode, must be called before cgroup_exit()
|
|
- */
|
|
- perf_event_exit_task(tsk);
|
|
-
|
|
sched_autogroup_exit_task(tsk);
|
|
cgroup_exit(tsk);
|
|
|
|
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
|
|
index 3130f24daf5979..353829883e66de 100644
|
|
--- a/kernel/time/clocksource.c
|
|
+++ b/kernel/time/clocksource.c
|
|
@@ -288,7 +288,7 @@ static void clocksource_verify_choose_cpus(void)
|
|
{
|
|
int cpu, i, n = verify_n_cpus;
|
|
|
|
- if (n < 0) {
|
|
+ if (n < 0 || n >= num_online_cpus()) {
|
|
/* Check all of the CPUs. */
|
|
cpumask_copy(&cpus_chosen, cpu_online_mask);
|
|
cpumask_clear_cpu(smp_processor_id(), &cpus_chosen);
|
|
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
|
|
index 650493ed76cd40..4351b9069a919d 100644
|
|
--- a/kernel/trace/ftrace.c
|
|
+++ b/kernel/trace/ftrace.c
|
|
@@ -6772,9 +6772,10 @@ void ftrace_release_mod(struct module *mod)
|
|
|
|
mutex_lock(&ftrace_lock);
|
|
|
|
- if (ftrace_disabled)
|
|
- goto out_unlock;
|
|
-
|
|
+ /*
|
|
+ * To avoid the UAF problem after the module is unloaded, the
|
|
+ * 'mod_map' resource needs to be released unconditionally.
|
|
+ */
|
|
list_for_each_entry_safe(mod_map, n, &ftrace_mod_maps, list) {
|
|
if (mod_map->mod == mod) {
|
|
list_del_rcu(&mod_map->list);
|
|
@@ -6783,6 +6784,9 @@ void ftrace_release_mod(struct module *mod)
|
|
}
|
|
}
|
|
|
|
+ if (ftrace_disabled)
|
|
+ goto out_unlock;
|
|
+
|
|
/*
|
|
* Each module has its own ftrace_pages, remove
|
|
* them from the list.
|
|
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
|
|
index 5cd6d4e2691579..7abd69a776b20a 100644
|
|
--- a/kernel/watchdog.c
|
|
+++ b/kernel/watchdog.c
|
|
@@ -40,6 +40,7 @@ int __read_mostly watchdog_user_enabled = 1;
|
|
static int __read_mostly watchdog_hardlockup_user_enabled = WATCHDOG_HARDLOCKUP_DEFAULT;
|
|
static int __read_mostly watchdog_softlockup_user_enabled = 1;
|
|
int __read_mostly watchdog_thresh = 10;
|
|
+static int __read_mostly watchdog_thresh_next;
|
|
static int __read_mostly watchdog_hardlockup_available;
|
|
|
|
struct cpumask watchdog_cpumask __read_mostly;
|
|
@@ -627,12 +628,20 @@ int lockup_detector_offline_cpu(unsigned int cpu)
|
|
return 0;
|
|
}
|
|
|
|
-static void __lockup_detector_reconfigure(void)
|
|
+static void __lockup_detector_reconfigure(bool thresh_changed)
|
|
{
|
|
cpus_read_lock();
|
|
watchdog_hardlockup_stop();
|
|
|
|
softlockup_stop_all();
|
|
+ /*
|
|
+ * To prevent watchdog_timer_fn from using the old interval and
|
|
+ * the new watchdog_thresh at the same time, which could lead to
|
|
+ * false softlockup reports, it is necessary to update the
|
|
+ * watchdog_thresh after the softlockup is completed.
|
|
+ */
|
|
+ if (thresh_changed)
|
|
+ watchdog_thresh = READ_ONCE(watchdog_thresh_next);
|
|
set_sample_period();
|
|
lockup_detector_update_enable();
|
|
if (watchdog_enabled && watchdog_thresh)
|
|
@@ -650,7 +659,7 @@ static void __lockup_detector_reconfigure(void)
|
|
void lockup_detector_reconfigure(void)
|
|
{
|
|
mutex_lock(&watchdog_mutex);
|
|
- __lockup_detector_reconfigure();
|
|
+ __lockup_detector_reconfigure(false);
|
|
mutex_unlock(&watchdog_mutex);
|
|
}
|
|
|
|
@@ -670,27 +679,29 @@ static __init void lockup_detector_setup(void)
|
|
return;
|
|
|
|
mutex_lock(&watchdog_mutex);
|
|
- __lockup_detector_reconfigure();
|
|
+ __lockup_detector_reconfigure(false);
|
|
softlockup_initialized = true;
|
|
mutex_unlock(&watchdog_mutex);
|
|
}
|
|
|
|
#else /* CONFIG_SOFTLOCKUP_DETECTOR */
|
|
-static void __lockup_detector_reconfigure(void)
|
|
+static void __lockup_detector_reconfigure(bool thresh_changed)
|
|
{
|
|
cpus_read_lock();
|
|
watchdog_hardlockup_stop();
|
|
+ if (thresh_changed)
|
|
+ watchdog_thresh = READ_ONCE(watchdog_thresh_next);
|
|
lockup_detector_update_enable();
|
|
watchdog_hardlockup_start();
|
|
cpus_read_unlock();
|
|
}
|
|
void lockup_detector_reconfigure(void)
|
|
{
|
|
- __lockup_detector_reconfigure();
|
|
+ __lockup_detector_reconfigure(false);
|
|
}
|
|
static inline void lockup_detector_setup(void)
|
|
{
|
|
- __lockup_detector_reconfigure();
|
|
+ __lockup_detector_reconfigure(false);
|
|
}
|
|
#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */
|
|
|
|
@@ -726,11 +737,11 @@ void lockup_detector_soft_poweroff(void)
|
|
#ifdef CONFIG_SYSCTL
|
|
|
|
/* Propagate any changes to the watchdog infrastructure */
|
|
-static void proc_watchdog_update(void)
|
|
+static void proc_watchdog_update(bool thresh_changed)
|
|
{
|
|
/* Remove impossible cpus to keep sysctl output clean. */
|
|
cpumask_and(&watchdog_cpumask, &watchdog_cpumask, cpu_possible_mask);
|
|
- __lockup_detector_reconfigure();
|
|
+ __lockup_detector_reconfigure(thresh_changed);
|
|
}
|
|
|
|
/*
|
|
@@ -763,7 +774,7 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,
|
|
old = READ_ONCE(*param);
|
|
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
if (!err && old != READ_ONCE(*param))
|
|
- proc_watchdog_update();
|
|
+ proc_watchdog_update(false);
|
|
}
|
|
mutex_unlock(&watchdog_mutex);
|
|
return err;
|
|
@@ -812,11 +823,13 @@ int proc_watchdog_thresh(struct ctl_table *table, int write,
|
|
|
|
mutex_lock(&watchdog_mutex);
|
|
|
|
- old = READ_ONCE(watchdog_thresh);
|
|
+ watchdog_thresh_next = READ_ONCE(watchdog_thresh);
|
|
+
|
|
+ old = watchdog_thresh_next;
|
|
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
|
|
- if (!err && write && old != READ_ONCE(watchdog_thresh))
|
|
- proc_watchdog_update();
|
|
+ if (!err && write && old != READ_ONCE(watchdog_thresh_next))
|
|
+ proc_watchdog_update(true);
|
|
|
|
mutex_unlock(&watchdog_mutex);
|
|
return err;
|
|
@@ -837,7 +850,7 @@ int proc_watchdog_cpumask(struct ctl_table *table, int write,
|
|
|
|
err = proc_do_large_bitmap(table, write, buffer, lenp, ppos);
|
|
if (!err && write)
|
|
- proc_watchdog_update();
|
|
+ proc_watchdog_update(false);
|
|
|
|
mutex_unlock(&watchdog_mutex);
|
|
return err;
|
|
@@ -857,7 +870,7 @@ static struct ctl_table watchdog_sysctls[] = {
|
|
},
|
|
{
|
|
.procname = "watchdog_thresh",
|
|
- .data = &watchdog_thresh,
|
|
+ .data = &watchdog_thresh_next,
|
|
.maxlen = sizeof(int),
|
|
.mode = 0644,
|
|
.proc_handler = proc_watchdog_thresh,
|
|
diff --git a/lib/Kconfig b/lib/Kconfig
|
|
index ee365b7402f193..43d69669465aff 100644
|
|
--- a/lib/Kconfig
|
|
+++ b/lib/Kconfig
|
|
@@ -751,6 +751,7 @@ config GENERIC_LIB_DEVMEM_IS_ALLOWED
|
|
|
|
config PLDMFW
|
|
bool
|
|
+ select CRC32
|
|
default n
|
|
|
|
config ASN1_ENCODER
|
|
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
|
|
index 635f0f0f6860e8..78f5df12b8eb37 100644
|
|
--- a/mm/huge_memory.c
|
|
+++ b/mm/huge_memory.c
|
|
@@ -2260,12 +2260,14 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|
{
|
|
spinlock_t *ptl;
|
|
struct mmu_notifier_range range;
|
|
+ bool pmd_migration;
|
|
|
|
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma->vm_mm,
|
|
address & HPAGE_PMD_MASK,
|
|
(address & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE);
|
|
mmu_notifier_invalidate_range_start(&range);
|
|
ptl = pmd_lock(vma->vm_mm, pmd);
|
|
+ pmd_migration = is_pmd_migration_entry(*pmd);
|
|
|
|
/*
|
|
* If caller asks to setup a migration entry, we need a folio to check
|
|
@@ -2274,13 +2276,12 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|
VM_BUG_ON(freeze && !folio);
|
|
VM_WARN_ON_ONCE(folio && !folio_test_locked(folio));
|
|
|
|
- if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd) ||
|
|
- is_pmd_migration_entry(*pmd)) {
|
|
+ if (pmd_trans_huge(*pmd) || pmd_devmap(*pmd) || pmd_migration) {
|
|
/*
|
|
- * It's safe to call pmd_page when folio is set because it's
|
|
- * guaranteed that pmd is present.
|
|
+ * Do not apply pmd_folio() to a migration entry; and folio lock
|
|
+ * guarantees that it must be of the wrong folio anyway.
|
|
*/
|
|
- if (folio && folio != page_folio(pmd_page(*pmd)))
|
|
+ if (folio && (pmd_migration || folio != page_folio(pmd_page(*pmd))))
|
|
goto out;
|
|
__split_huge_pmd_locked(vma, pmd, range.start, freeze);
|
|
}
|
|
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
|
|
index 7c196b754071bd..d57d8f1c2dfea4 100644
|
|
--- a/mm/hugetlb.c
|
|
+++ b/mm/hugetlb.c
|
|
@@ -96,7 +96,7 @@ static void hugetlb_vma_lock_free(struct vm_area_struct *vma);
|
|
static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma);
|
|
static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma);
|
|
static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
|
|
- unsigned long start, unsigned long end);
|
|
+ unsigned long start, unsigned long end, bool take_locks);
|
|
static struct resv_map *vma_resv_map(struct vm_area_struct *vma);
|
|
|
|
static inline bool subpool_is_free(struct hugepage_subpool *spool)
|
|
@@ -4903,26 +4903,40 @@ static int hugetlb_vm_op_split(struct vm_area_struct *vma, unsigned long addr)
|
|
{
|
|
if (addr & ~(huge_page_mask(hstate_vma(vma))))
|
|
return -EINVAL;
|
|
+ return 0;
|
|
+}
|
|
|
|
+void hugetlb_split(struct vm_area_struct *vma, unsigned long addr)
|
|
+{
|
|
/*
|
|
* PMD sharing is only possible for PUD_SIZE-aligned address ranges
|
|
* in HugeTLB VMAs. If we will lose PUD_SIZE alignment due to this
|
|
* split, unshare PMDs in the PUD_SIZE interval surrounding addr now.
|
|
+ * This function is called in the middle of a VMA split operation, with
|
|
+ * MM, VMA and rmap all write-locked to prevent concurrent page table
|
|
+ * walks (except hardware and gup_fast()).
|
|
*/
|
|
+ vma_assert_write_locked(vma);
|
|
+ i_mmap_assert_write_locked(vma->vm_file->f_mapping);
|
|
+
|
|
if (addr & ~PUD_MASK) {
|
|
- /*
|
|
- * hugetlb_vm_op_split is called right before we attempt to
|
|
- * split the VMA. We will need to unshare PMDs in the old and
|
|
- * new VMAs, so let's unshare before we split.
|
|
- */
|
|
unsigned long floor = addr & PUD_MASK;
|
|
unsigned long ceil = floor + PUD_SIZE;
|
|
|
|
- if (floor >= vma->vm_start && ceil <= vma->vm_end)
|
|
- hugetlb_unshare_pmds(vma, floor, ceil);
|
|
+ if (floor >= vma->vm_start && ceil <= vma->vm_end) {
|
|
+ /*
|
|
+ * Locking:
|
|
+ * Use take_locks=false here.
|
|
+ * The file rmap lock is already held.
|
|
+ * The hugetlb VMA lock can't be taken when we already
|
|
+ * hold the file rmap lock, and we don't need it because
|
|
+ * its purpose is to synchronize against concurrent page
|
|
+ * table walks, which are not possible thanks to the
|
|
+ * locks held by our caller.
|
|
+ */
|
|
+ hugetlb_unshare_pmds(vma, floor, ceil, /* take_locks = */ false);
|
|
+ }
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
static unsigned long hugetlb_vm_op_pagesize(struct vm_area_struct *vma)
|
|
@@ -7062,6 +7076,13 @@ int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
return 0;
|
|
|
|
pud_clear(pud);
|
|
+ /*
|
|
+ * Once our caller drops the rmap lock, some other process might be
|
|
+ * using this page table as a normal, non-hugetlb page table.
|
|
+ * Wait for pending gup_fast() in other threads to finish before letting
|
|
+ * that happen.
|
|
+ */
|
|
+ tlb_remove_table_sync_one();
|
|
ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep));
|
|
mm_dec_nr_pmds(mm);
|
|
return 1;
|
|
@@ -7298,9 +7319,16 @@ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int re
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+ * If @take_locks is false, the caller must ensure that no concurrent page table
|
|
+ * access can happen (except for gup_fast() and hardware page walks).
|
|
+ * If @take_locks is true, we take the hugetlb VMA lock (to lock out things like
|
|
+ * concurrent page fault handling) and the file rmap lock.
|
|
+ */
|
|
static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
|
|
unsigned long start,
|
|
- unsigned long end)
|
|
+ unsigned long end,
|
|
+ bool take_locks)
|
|
{
|
|
struct hstate *h = hstate_vma(vma);
|
|
unsigned long sz = huge_page_size(h);
|
|
@@ -7324,8 +7352,12 @@ static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
|
|
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm,
|
|
start, end);
|
|
mmu_notifier_invalidate_range_start(&range);
|
|
- hugetlb_vma_lock_write(vma);
|
|
- i_mmap_lock_write(vma->vm_file->f_mapping);
|
|
+ if (take_locks) {
|
|
+ hugetlb_vma_lock_write(vma);
|
|
+ i_mmap_lock_write(vma->vm_file->f_mapping);
|
|
+ } else {
|
|
+ i_mmap_assert_write_locked(vma->vm_file->f_mapping);
|
|
+ }
|
|
for (address = start; address < end; address += PUD_SIZE) {
|
|
ptep = hugetlb_walk(vma, address, sz);
|
|
if (!ptep)
|
|
@@ -7335,8 +7367,10 @@ static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
|
|
spin_unlock(ptl);
|
|
}
|
|
flush_hugetlb_tlb_range(vma, start, end);
|
|
- i_mmap_unlock_write(vma->vm_file->f_mapping);
|
|
- hugetlb_vma_unlock_write(vma);
|
|
+ if (take_locks) {
|
|
+ i_mmap_unlock_write(vma->vm_file->f_mapping);
|
|
+ hugetlb_vma_unlock_write(vma);
|
|
+ }
|
|
/*
|
|
* No need to call mmu_notifier_arch_invalidate_secondary_tlbs(), see
|
|
* Documentation/mm/mmu_notifier.rst.
|
|
@@ -7351,7 +7385,8 @@ static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
|
|
void hugetlb_unshare_all_pmds(struct vm_area_struct *vma)
|
|
{
|
|
hugetlb_unshare_pmds(vma, ALIGN(vma->vm_start, PUD_SIZE),
|
|
- ALIGN_DOWN(vma->vm_end, PUD_SIZE));
|
|
+ ALIGN_DOWN(vma->vm_end, PUD_SIZE),
|
|
+ /* take_locks = */ true);
|
|
}
|
|
|
|
#ifdef CONFIG_CMA
|
|
diff --git a/mm/mmap.c b/mm/mmap.c
|
|
index 03a24cb3951d47..a9c70001e45601 100644
|
|
--- a/mm/mmap.c
|
|
+++ b/mm/mmap.c
|
|
@@ -2402,7 +2402,13 @@ int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
|
init_vma_prep(&vp, vma);
|
|
vp.insert = new;
|
|
vma_prepare(&vp);
|
|
+ /*
|
|
+ * Get rid of huge pages and shared page tables straddling the split
|
|
+ * boundary.
|
|
+ */
|
|
vma_adjust_trans_huge(vma, vma->vm_start, addr, 0);
|
|
+ if (is_vm_hugetlb_page(vma))
|
|
+ hugetlb_split(vma, addr);
|
|
|
|
if (new_below) {
|
|
vma->vm_start = addr;
|
|
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
|
|
index e632ec9b642109..9ceb841af819e4 100644
|
|
--- a/mm/page-writeback.c
|
|
+++ b/mm/page-writeback.c
|
|
@@ -541,8 +541,8 @@ static int dirty_ratio_handler(struct ctl_table *table, int write, void *buffer,
|
|
|
|
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
if (ret == 0 && write && vm_dirty_ratio != old_ratio) {
|
|
- writeback_set_ratelimit();
|
|
vm_dirty_bytes = 0;
|
|
+ writeback_set_ratelimit();
|
|
}
|
|
return ret;
|
|
}
|
|
diff --git a/net/atm/common.c b/net/atm/common.c
|
|
index f7019df41c3e59..9cc82acbc73588 100644
|
|
--- a/net/atm/common.c
|
|
+++ b/net/atm/common.c
|
|
@@ -635,6 +635,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
|
|
|
|
skb->dev = NULL; /* for paths shared with net_device interfaces */
|
|
if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) {
|
|
+ atm_return_tx(vcc, skb);
|
|
kfree_skb(skb);
|
|
error = -EFAULT;
|
|
goto out;
|
|
diff --git a/net/atm/lec.c b/net/atm/lec.c
|
|
index ac3cfc1ae51024..b7fa48a9b72059 100644
|
|
--- a/net/atm/lec.c
|
|
+++ b/net/atm/lec.c
|
|
@@ -124,6 +124,7 @@ static unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
|
|
/* Device structures */
|
|
static struct net_device *dev_lec[MAX_LEC_ITF];
|
|
+static DEFINE_MUTEX(lec_mutex);
|
|
|
|
#if IS_ENABLED(CONFIG_BRIDGE)
|
|
static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
|
|
@@ -685,6 +686,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
|
|
int bytes_left;
|
|
struct atmlec_ioc ioc_data;
|
|
|
|
+ lockdep_assert_held(&lec_mutex);
|
|
/* Lecd must be up in this case */
|
|
bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
|
|
if (bytes_left != 0)
|
|
@@ -710,6 +712,7 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
|
|
|
|
static int lec_mcast_attach(struct atm_vcc *vcc, int arg)
|
|
{
|
|
+ lockdep_assert_held(&lec_mutex);
|
|
if (arg < 0 || arg >= MAX_LEC_ITF)
|
|
return -EINVAL;
|
|
arg = array_index_nospec(arg, MAX_LEC_ITF);
|
|
@@ -725,6 +728,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
|
|
int i;
|
|
struct lec_priv *priv;
|
|
|
|
+ lockdep_assert_held(&lec_mutex);
|
|
if (arg < 0)
|
|
arg = 0;
|
|
if (arg >= MAX_LEC_ITF)
|
|
@@ -742,6 +746,7 @@ static int lecd_attach(struct atm_vcc *vcc, int arg)
|
|
snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i);
|
|
if (register_netdev(dev_lec[i])) {
|
|
free_netdev(dev_lec[i]);
|
|
+ dev_lec[i] = NULL;
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -904,7 +909,6 @@ static void *lec_itf_walk(struct lec_state *state, loff_t *l)
|
|
v = (dev && netdev_priv(dev)) ?
|
|
lec_priv_walk(state, l, netdev_priv(dev)) : NULL;
|
|
if (!v && dev) {
|
|
- dev_put(dev);
|
|
/* Partial state reset for the next time we get called */
|
|
dev = NULL;
|
|
}
|
|
@@ -928,6 +932,7 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
|
|
{
|
|
struct lec_state *state = seq->private;
|
|
|
|
+ mutex_lock(&lec_mutex);
|
|
state->itf = 0;
|
|
state->dev = NULL;
|
|
state->locked = NULL;
|
|
@@ -945,8 +950,9 @@ static void lec_seq_stop(struct seq_file *seq, void *v)
|
|
if (state->dev) {
|
|
spin_unlock_irqrestore(&state->locked->lec_arp_lock,
|
|
state->flags);
|
|
- dev_put(state->dev);
|
|
+ state->dev = NULL;
|
|
}
|
|
+ mutex_unlock(&lec_mutex);
|
|
}
|
|
|
|
static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
|
@@ -1003,6 +1009,7 @@ static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|
return -ENOIOCTLCMD;
|
|
}
|
|
|
|
+ mutex_lock(&lec_mutex);
|
|
switch (cmd) {
|
|
case ATMLEC_CTRL:
|
|
err = lecd_attach(vcc, (int)arg);
|
|
@@ -1017,6 +1024,7 @@ static int lane_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|
break;
|
|
}
|
|
|
|
+ mutex_unlock(&lec_mutex);
|
|
return err;
|
|
}
|
|
|
|
diff --git a/net/atm/raw.c b/net/atm/raw.c
|
|
index 2b5f78a7ec3e4a..1e6511ec842cbc 100644
|
|
--- a/net/atm/raw.c
|
|
+++ b/net/atm/raw.c
|
|
@@ -36,7 +36,7 @@ static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb)
|
|
|
|
pr_debug("(%d) %d -= %d\n",
|
|
vcc->vci, sk_wmem_alloc_get(sk), ATM_SKB(skb)->acct_truesize);
|
|
- WARN_ON(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, &sk->sk_wmem_alloc));
|
|
+ atm_return_tx(vcc, skb);
|
|
dev_kfree_skb_any(skb);
|
|
sk->sk_write_space(sk);
|
|
}
|
|
diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c
|
|
index 1820f09ff59ceb..3f24b4ee49c274 100644
|
|
--- a/net/bridge/br_mst.c
|
|
+++ b/net/bridge/br_mst.c
|
|
@@ -80,10 +80,10 @@ static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg,
|
|
if (br_vlan_get_state(v) == state)
|
|
return;
|
|
|
|
- br_vlan_set_state(v, state);
|
|
-
|
|
if (v->vid == vg->pvid)
|
|
br_vlan_set_pvid_state(vg, state);
|
|
+
|
|
+ br_vlan_set_state(v, state);
|
|
}
|
|
|
|
int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
|
|
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
|
|
index c38244d60ff86e..fa16ee88ec396a 100644
|
|
--- a/net/bridge/br_multicast.c
|
|
+++ b/net/bridge/br_multicast.c
|
|
@@ -2104,12 +2104,17 @@ static void __br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
|
|
}
|
|
}
|
|
|
|
-void br_multicast_enable_port(struct net_bridge_port *port)
|
|
+static void br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
|
|
{
|
|
- struct net_bridge *br = port->br;
|
|
+ struct net_bridge *br = pmctx->port->br;
|
|
|
|
spin_lock_bh(&br->multicast_lock);
|
|
- __br_multicast_enable_port_ctx(&port->multicast_ctx);
|
|
+ if (br_multicast_port_ctx_is_vlan(pmctx) &&
|
|
+ !(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED)) {
|
|
+ spin_unlock_bh(&br->multicast_lock);
|
|
+ return;
|
|
+ }
|
|
+ __br_multicast_enable_port_ctx(pmctx);
|
|
spin_unlock_bh(&br->multicast_lock);
|
|
}
|
|
|
|
@@ -2136,11 +2141,67 @@ static void __br_multicast_disable_port_ctx(struct net_bridge_mcast_port *pmctx)
|
|
br_multicast_rport_del_notify(pmctx, del);
|
|
}
|
|
|
|
+static void br_multicast_disable_port_ctx(struct net_bridge_mcast_port *pmctx)
|
|
+{
|
|
+ struct net_bridge *br = pmctx->port->br;
|
|
+
|
|
+ spin_lock_bh(&br->multicast_lock);
|
|
+ if (br_multicast_port_ctx_is_vlan(pmctx) &&
|
|
+ !(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED)) {
|
|
+ spin_unlock_bh(&br->multicast_lock);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ __br_multicast_disable_port_ctx(pmctx);
|
|
+ spin_unlock_bh(&br->multicast_lock);
|
|
+}
|
|
+
|
|
+static void br_multicast_toggle_port(struct net_bridge_port *port, bool on)
|
|
+{
|
|
+#if IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
|
|
+ if (br_opt_get(port->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {
|
|
+ struct net_bridge_vlan_group *vg;
|
|
+ struct net_bridge_vlan *vlan;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ vg = nbp_vlan_group_rcu(port);
|
|
+ if (!vg) {
|
|
+ rcu_read_unlock();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* iterate each vlan, toggle vlan multicast context */
|
|
+ list_for_each_entry_rcu(vlan, &vg->vlan_list, vlist) {
|
|
+ struct net_bridge_mcast_port *pmctx =
|
|
+ &vlan->port_mcast_ctx;
|
|
+ u8 state = br_vlan_get_state(vlan);
|
|
+ /* enable vlan multicast context when state is
|
|
+ * LEARNING or FORWARDING
|
|
+ */
|
|
+ if (on && br_vlan_state_allowed(state, true))
|
|
+ br_multicast_enable_port_ctx(pmctx);
|
|
+ else
|
|
+ br_multicast_disable_port_ctx(pmctx);
|
|
+ }
|
|
+ rcu_read_unlock();
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
+ /* toggle port multicast context when vlan snooping is disabled */
|
|
+ if (on)
|
|
+ br_multicast_enable_port_ctx(&port->multicast_ctx);
|
|
+ else
|
|
+ br_multicast_disable_port_ctx(&port->multicast_ctx);
|
|
+}
|
|
+
|
|
+void br_multicast_enable_port(struct net_bridge_port *port)
|
|
+{
|
|
+ br_multicast_toggle_port(port, true);
|
|
+}
|
|
+
|
|
void br_multicast_disable_port(struct net_bridge_port *port)
|
|
{
|
|
- spin_lock_bh(&port->br->multicast_lock);
|
|
- __br_multicast_disable_port_ctx(&port->multicast_ctx);
|
|
- spin_unlock_bh(&port->br->multicast_lock);
|
|
+ br_multicast_toggle_port(port, false);
|
|
}
|
|
|
|
static int __grp_src_delete_marked(struct net_bridge_port_group *pg)
|
|
@@ -4210,6 +4271,32 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx)
|
|
#endif
|
|
}
|
|
|
|
+void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state)
|
|
+{
|
|
+#if IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
|
|
+ struct net_bridge *br;
|
|
+
|
|
+ if (!br_vlan_should_use(v))
|
|
+ return;
|
|
+
|
|
+ if (br_vlan_is_master(v))
|
|
+ return;
|
|
+
|
|
+ br = v->port->br;
|
|
+
|
|
+ if (!br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED))
|
|
+ return;
|
|
+
|
|
+ if (br_vlan_state_allowed(state, true))
|
|
+ br_multicast_enable_port_ctx(&v->port_mcast_ctx);
|
|
+
|
|
+ /* Multicast is not disabled for the vlan when it goes in
|
|
+ * blocking state because the timers will expire and stop by
|
|
+ * themselves without sending more queries.
|
|
+ */
|
|
+#endif
|
|
+}
|
|
+
|
|
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
|
|
{
|
|
struct net_bridge *br;
|
|
@@ -4303,9 +4390,9 @@ int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
|
|
__br_multicast_open(&br->multicast_ctx);
|
|
list_for_each_entry(p, &br->port_list, list) {
|
|
if (on)
|
|
- br_multicast_disable_port(p);
|
|
+ br_multicast_disable_port_ctx(&p->multicast_ctx);
|
|
else
|
|
- br_multicast_enable_port(p);
|
|
+ br_multicast_enable_port_ctx(&p->multicast_ctx);
|
|
}
|
|
|
|
list_for_each_entry(vlan, &vg->vlan_list, vlist)
|
|
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
|
|
index 9197b511e45972..067d47b8eb8ffb 100644
|
|
--- a/net/bridge/br_private.h
|
|
+++ b/net/bridge/br_private.h
|
|
@@ -1043,6 +1043,7 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,
|
|
struct net_bridge_vlan *vlan,
|
|
struct net_bridge_mcast_port *pmctx);
|
|
void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx);
|
|
+void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state);
|
|
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on);
|
|
int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
|
|
struct netlink_ext_ack *extack);
|
|
@@ -1479,6 +1480,11 @@ static inline void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pm
|
|
{
|
|
}
|
|
|
|
+static inline void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v,
|
|
+ u8 state)
|
|
+{
|
|
+}
|
|
+
|
|
static inline void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan,
|
|
bool on)
|
|
{
|
|
@@ -1830,7 +1836,9 @@ bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,
|
|
bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
|
|
const struct net_bridge_vlan *v_opts);
|
|
|
|
-/* vlan state manipulation helpers using *_ONCE to annotate lock-free access */
|
|
+/* vlan state manipulation helpers using *_ONCE to annotate lock-free access,
|
|
+ * while br_vlan_set_state() may access data protected by multicast_lock.
|
|
+ */
|
|
static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
|
|
{
|
|
return READ_ONCE(v->state);
|
|
@@ -1839,6 +1847,7 @@ static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
|
|
static inline void br_vlan_set_state(struct net_bridge_vlan *v, u8 state)
|
|
{
|
|
WRITE_ONCE(v->state, state);
|
|
+ br_multicast_update_vlan_mcast_ctx(v, state);
|
|
}
|
|
|
|
static inline u8 br_vlan_get_pvid_state(const struct net_bridge_vlan_group *vg)
|
|
diff --git a/net/core/filter.c b/net/core/filter.c
|
|
index 5143c8a9e52cab..3e10b4c8338f92 100644
|
|
--- a/net/core/filter.c
|
|
+++ b/net/core/filter.c
|
|
@@ -1968,10 +1968,11 @@ BPF_CALL_5(bpf_l4_csum_replace, struct sk_buff *, skb, u32, offset,
|
|
bool is_pseudo = flags & BPF_F_PSEUDO_HDR;
|
|
bool is_mmzero = flags & BPF_F_MARK_MANGLED_0;
|
|
bool do_mforce = flags & BPF_F_MARK_ENFORCE;
|
|
+ bool is_ipv6 = flags & BPF_F_IPV6;
|
|
__sum16 *ptr;
|
|
|
|
if (unlikely(flags & ~(BPF_F_MARK_MANGLED_0 | BPF_F_MARK_ENFORCE |
|
|
- BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK)))
|
|
+ BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK | BPF_F_IPV6)))
|
|
return -EINVAL;
|
|
if (unlikely(offset > 0xffff || offset & 1))
|
|
return -EFAULT;
|
|
@@ -1987,7 +1988,7 @@ BPF_CALL_5(bpf_l4_csum_replace, struct sk_buff *, skb, u32, offset,
|
|
if (unlikely(from != 0))
|
|
return -EINVAL;
|
|
|
|
- inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo);
|
|
+ inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo, is_ipv6);
|
|
break;
|
|
case 2:
|
|
inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo);
|
|
@@ -3229,6 +3230,13 @@ static const struct bpf_func_proto bpf_skb_vlan_pop_proto = {
|
|
.arg1_type = ARG_PTR_TO_CTX,
|
|
};
|
|
|
|
+static void bpf_skb_change_protocol(struct sk_buff *skb, u16 proto)
|
|
+{
|
|
+ skb->protocol = htons(proto);
|
|
+ if (skb_valid_dst(skb))
|
|
+ skb_dst_drop(skb);
|
|
+}
|
|
+
|
|
static int bpf_skb_generic_push(struct sk_buff *skb, u32 off, u32 len)
|
|
{
|
|
/* Caller already did skb_cow() with len as headroom,
|
|
@@ -3325,7 +3333,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
|
|
}
|
|
}
|
|
|
|
- skb->protocol = htons(ETH_P_IPV6);
|
|
+ bpf_skb_change_protocol(skb, ETH_P_IPV6);
|
|
skb_clear_hash(skb);
|
|
|
|
return 0;
|
|
@@ -3355,7 +3363,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
|
|
}
|
|
}
|
|
|
|
- skb->protocol = htons(ETH_P_IP);
|
|
+ bpf_skb_change_protocol(skb, ETH_P_IP);
|
|
skb_clear_hash(skb);
|
|
|
|
return 0;
|
|
@@ -3546,10 +3554,10 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
|
|
/* Match skb->protocol to new outer l3 protocol */
|
|
if (skb->protocol == htons(ETH_P_IP) &&
|
|
flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6)
|
|
- skb->protocol = htons(ETH_P_IPV6);
|
|
+ bpf_skb_change_protocol(skb, ETH_P_IPV6);
|
|
else if (skb->protocol == htons(ETH_P_IPV6) &&
|
|
flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4)
|
|
- skb->protocol = htons(ETH_P_IP);
|
|
+ bpf_skb_change_protocol(skb, ETH_P_IP);
|
|
}
|
|
|
|
if (skb_is_gso(skb)) {
|
|
@@ -3602,10 +3610,10 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
|
|
/* Match skb->protocol to new outer l3 protocol */
|
|
if (skb->protocol == htons(ETH_P_IP) &&
|
|
flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV6)
|
|
- skb->protocol = htons(ETH_P_IPV6);
|
|
+ bpf_skb_change_protocol(skb, ETH_P_IPV6);
|
|
else if (skb->protocol == htons(ETH_P_IPV6) &&
|
|
flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4)
|
|
- skb->protocol = htons(ETH_P_IP);
|
|
+ bpf_skb_change_protocol(skb, ETH_P_IP);
|
|
|
|
if (skb_is_gso(skb)) {
|
|
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
|
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
|
|
index 2076db464e9360..c3169e1e635248 100644
|
|
--- a/net/core/skmsg.c
|
|
+++ b/net/core/skmsg.c
|
|
@@ -689,7 +689,8 @@ static void sk_psock_backlog(struct work_struct *work)
|
|
if (ret <= 0) {
|
|
if (ret == -EAGAIN) {
|
|
sk_psock_skb_state(psock, state, len, off);
|
|
-
|
|
+ /* Restore redir info we cleared before */
|
|
+ skb_bpf_set_redir(skb, psock->sk, ingress);
|
|
/* Delay slightly to prioritize any
|
|
* other work that might be here.
|
|
*/
|
|
diff --git a/net/core/sock.c b/net/core/sock.c
|
|
index 84ba3f67bca97b..ec48690b5174eb 100644
|
|
--- a/net/core/sock.c
|
|
+++ b/net/core/sock.c
|
|
@@ -3817,7 +3817,7 @@ static int assign_proto_idx(struct proto *prot)
|
|
{
|
|
prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
|
|
|
|
- if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
|
|
+ if (unlikely(prot->inuse_idx == PROTO_INUSE_NR)) {
|
|
pr_err("PROTO_INUSE_NR exhausted\n");
|
|
return -ENOSPC;
|
|
}
|
|
@@ -3828,7 +3828,7 @@ static int assign_proto_idx(struct proto *prot)
|
|
|
|
static void release_proto_idx(struct proto *prot)
|
|
{
|
|
- if (prot->inuse_idx != PROTO_INUSE_NR - 1)
|
|
+ if (prot->inuse_idx != PROTO_INUSE_NR)
|
|
clear_bit(prot->inuse_idx, proto_inuse_idx);
|
|
}
|
|
#else
|
|
diff --git a/net/core/utils.c b/net/core/utils.c
|
|
index c994e95172acf5..5895d034bf279d 100644
|
|
--- a/net/core/utils.c
|
|
+++ b/net/core/utils.c
|
|
@@ -473,11 +473,11 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
|
EXPORT_SYMBOL(inet_proto_csum_replace16);
|
|
|
|
void inet_proto_csum_replace_by_diff(__sum16 *sum, struct sk_buff *skb,
|
|
- __wsum diff, bool pseudohdr)
|
|
+ __wsum diff, bool pseudohdr, bool ipv6)
|
|
{
|
|
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
|
csum_replace_by_diff(sum, diff);
|
|
- if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
|
|
+ if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr && !ipv6)
|
|
skb->csum = ~csum_sub(diff, skb->csum);
|
|
} else if (pseudohdr) {
|
|
*sum = ~csum_fold(csum_add(diff, csum_unfold(*sum)));
|
|
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
|
|
index 97dc30a03dbf26..8ee1ad2d8c13f6 100644
|
|
--- a/net/ipv4/route.c
|
|
+++ b/net/ipv4/route.c
|
|
@@ -192,7 +192,11 @@ const __u8 ip_tos2prio[16] = {
|
|
EXPORT_SYMBOL(ip_tos2prio);
|
|
|
|
static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
|
|
+#ifndef CONFIG_PREEMPT_RT
|
|
#define RT_CACHE_STAT_INC(field) raw_cpu_inc(rt_cache_stat.field)
|
|
+#else
|
|
+#define RT_CACHE_STAT_INC(field) this_cpu_inc(rt_cache_stat.field)
|
|
+#endif
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
|
|
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
|
|
index 32b28fc21b63c0..408985eb74eefa 100644
|
|
--- a/net/ipv4/tcp_fastopen.c
|
|
+++ b/net/ipv4/tcp_fastopen.c
|
|
@@ -3,6 +3,7 @@
|
|
#include <linux/tcp.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <net/tcp.h>
|
|
+#include <net/busy_poll.h>
|
|
|
|
void tcp_fastopen_init_key_once(struct net *net)
|
|
{
|
|
@@ -279,6 +280,8 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
|
|
|
|
refcount_set(&req->rsk_refcnt, 2);
|
|
|
|
+ sk_mark_napi_id_set(child, skb);
|
|
+
|
|
/* Now finish processing the fastopen child socket. */
|
|
tcp_init_transfer(child, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, skb);
|
|
|
|
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
|
|
index a172248b667837..f7b95bc8ad60bb 100644
|
|
--- a/net/ipv4/tcp_input.c
|
|
+++ b/net/ipv4/tcp_input.c
|
|
@@ -671,10 +671,12 @@ EXPORT_SYMBOL(tcp_initialize_rcv_mss);
|
|
*/
|
|
static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep)
|
|
{
|
|
- u32 new_sample = tp->rcv_rtt_est.rtt_us;
|
|
- long m = sample;
|
|
+ u32 new_sample, old_sample = tp->rcv_rtt_est.rtt_us;
|
|
+ long m = sample << 3;
|
|
|
|
- if (new_sample != 0) {
|
|
+ if (old_sample == 0 || m < old_sample) {
|
|
+ new_sample = m;
|
|
+ } else {
|
|
/* If we sample in larger samples in the non-timestamp
|
|
* case, we could grossly overestimate the RTT especially
|
|
* with chatty applications or bulk transfer apps which
|
|
@@ -685,17 +687,9 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep)
|
|
* else with timestamps disabled convergence takes too
|
|
* long.
|
|
*/
|
|
- if (!win_dep) {
|
|
- m -= (new_sample >> 3);
|
|
- new_sample += m;
|
|
- } else {
|
|
- m <<= 3;
|
|
- if (m < new_sample)
|
|
- new_sample = m;
|
|
- }
|
|
- } else {
|
|
- /* No previous measure. */
|
|
- new_sample = m << 3;
|
|
+ if (win_dep)
|
|
+ return;
|
|
+ new_sample = old_sample - (old_sample >> 3) + sample;
|
|
}
|
|
|
|
tp->rcv_rtt_est.rtt_us = new_sample;
|
|
@@ -2469,20 +2463,33 @@ static inline bool tcp_packet_delayed(const struct tcp_sock *tp)
|
|
{
|
|
const struct sock *sk = (const struct sock *)tp;
|
|
|
|
- if (tp->retrans_stamp &&
|
|
- tcp_tsopt_ecr_before(tp, tp->retrans_stamp))
|
|
- return true; /* got echoed TS before first retransmission */
|
|
+ /* Received an echoed timestamp before the first retransmission? */
|
|
+ if (tp->retrans_stamp)
|
|
+ return tcp_tsopt_ecr_before(tp, tp->retrans_stamp);
|
|
+
|
|
+ /* We set tp->retrans_stamp upon the first retransmission of a loss
|
|
+ * recovery episode, so normally if tp->retrans_stamp is 0 then no
|
|
+ * retransmission has happened yet (likely due to TSQ, which can cause
|
|
+ * fast retransmits to be delayed). So if snd_una advanced while
|
|
+ * (tp->retrans_stamp is 0 then apparently a packet was merely delayed,
|
|
+ * not lost. But there are exceptions where we retransmit but then
|
|
+ * clear tp->retrans_stamp, so we check for those exceptions.
|
|
+ */
|
|
|
|
- /* Check if nothing was retransmitted (retrans_stamp==0), which may
|
|
- * happen in fast recovery due to TSQ. But we ignore zero retrans_stamp
|
|
- * in TCP_SYN_SENT, since when we set FLAG_SYN_ACKED we also clear
|
|
- * retrans_stamp even if we had retransmitted the SYN.
|
|
+ /* (1) For non-SACK connections, tcp_is_non_sack_preventing_reopen()
|
|
+ * clears tp->retrans_stamp when snd_una == high_seq.
|
|
*/
|
|
- if (!tp->retrans_stamp && /* no record of a retransmit/SYN? */
|
|
- sk->sk_state != TCP_SYN_SENT) /* not the FLAG_SYN_ACKED case? */
|
|
- return true; /* nothing was retransmitted */
|
|
+ if (!tcp_is_sack(tp) && !before(tp->snd_una, tp->high_seq))
|
|
+ return false;
|
|
|
|
- return false;
|
|
+ /* (2) In TCP_SYN_SENT tcp_clean_rtx_queue() clears tp->retrans_stamp
|
|
+ * when setting FLAG_SYN_ACKED is set, even if the SYN was
|
|
+ * retransmitted.
|
|
+ */
|
|
+ if (sk->sk_state == TCP_SYN_SENT)
|
|
+ return false;
|
|
+
|
|
+ return true; /* tp->retrans_stamp is zero; no retransmit yet */
|
|
}
|
|
|
|
/* Undo procedures. */
|
|
@@ -6705,6 +6712,9 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
|
if (!tp->srtt_us)
|
|
tcp_synack_rtt_meas(sk, req);
|
|
|
|
+ if (tp->rx_opt.tstamp_ok)
|
|
+ tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
|
|
+
|
|
if (req) {
|
|
tcp_rcv_synrecv_state_fastopen(sk);
|
|
} else {
|
|
@@ -6729,9 +6739,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
|
tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale;
|
|
tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
|
|
|
|
- if (tp->rx_opt.tstamp_ok)
|
|
- tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
|
|
-
|
|
if (!inet_csk(sk)->icsk_ca_ops->cong_control)
|
|
tcp_update_pacing_rate(sk);
|
|
|
|
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
|
|
index c07e3da08d2a8b..24666291c54a87 100644
|
|
--- a/net/ipv6/calipso.c
|
|
+++ b/net/ipv6/calipso.c
|
|
@@ -1210,6 +1210,10 @@ static int calipso_req_setattr(struct request_sock *req,
|
|
struct ipv6_opt_hdr *old, *new;
|
|
struct sock *sk = sk_to_full_sk(req_to_sk(req));
|
|
|
|
+ /* sk is NULL for SYN+ACK w/ SYN Cookie */
|
|
+ if (!sk)
|
|
+ return -ENOMEM;
|
|
+
|
|
if (req_inet->ipv6_opt && req_inet->ipv6_opt->hopopt)
|
|
old = req_inet->ipv6_opt->hopopt;
|
|
else
|
|
@@ -1250,6 +1254,10 @@ static void calipso_req_delattr(struct request_sock *req)
|
|
struct ipv6_txoptions *txopts;
|
|
struct sock *sk = sk_to_full_sk(req_to_sk(req));
|
|
|
|
+ /* sk is NULL for SYN+ACK w/ SYN Cookie */
|
|
+ if (!sk)
|
|
+ return;
|
|
+
|
|
if (!req_inet->ipv6_opt || !req_inet->ipv6_opt->hopopt)
|
|
return;
|
|
|
|
diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c
|
|
index 95e9146918cc6f..b8d43ed4689db9 100644
|
|
--- a/net/ipv6/ila/ila_common.c
|
|
+++ b/net/ipv6/ila/ila_common.c
|
|
@@ -86,7 +86,7 @@ static void ila_csum_adjust_transport(struct sk_buff *skb,
|
|
|
|
diff = get_csum_diff(ip6h, p);
|
|
inet_proto_csum_replace_by_diff(&th->check, skb,
|
|
- diff, true);
|
|
+ diff, true, true);
|
|
}
|
|
break;
|
|
case NEXTHDR_UDP:
|
|
@@ -97,7 +97,7 @@ static void ila_csum_adjust_transport(struct sk_buff *skb,
|
|
if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
diff = get_csum_diff(ip6h, p);
|
|
inet_proto_csum_replace_by_diff(&uh->check, skb,
|
|
- diff, true);
|
|
+ diff, true, true);
|
|
if (!uh->check)
|
|
uh->check = CSUM_MANGLED_0;
|
|
}
|
|
@@ -111,7 +111,7 @@ static void ila_csum_adjust_transport(struct sk_buff *skb,
|
|
|
|
diff = get_csum_diff(ip6h, p);
|
|
inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb,
|
|
- diff, true);
|
|
+ diff, true, true);
|
|
}
|
|
break;
|
|
}
|
|
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
|
|
index c6395551f5df08..54930b06c3a4a5 100644
|
|
--- a/net/mac80211/mesh_hwmp.c
|
|
+++ b/net/mac80211/mesh_hwmp.c
|
|
@@ -634,7 +634,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
|
|
mesh_path_add_gate(mpath);
|
|
}
|
|
rcu_read_unlock();
|
|
- } else {
|
|
+ } else if (ifmsh->mshcfg.dot11MeshForwarding) {
|
|
rcu_read_lock();
|
|
mpath = mesh_path_lookup(sdata, target_addr);
|
|
if (mpath) {
|
|
@@ -652,6 +652,8 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
|
|
}
|
|
}
|
|
rcu_read_unlock();
|
|
+ } else {
|
|
+ forward = false;
|
|
}
|
|
|
|
if (reply) {
|
|
@@ -669,7 +671,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
|
|
}
|
|
}
|
|
|
|
- if (forward && ifmsh->mshcfg.dot11MeshForwarding) {
|
|
+ if (forward) {
|
|
u32 preq_id;
|
|
u8 hopcount;
|
|
|
|
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
|
index 45a093d3f1fa7f..ec5469add68a27 100644
|
|
--- a/net/mac80211/tx.c
|
|
+++ b/net/mac80211/tx.c
|
|
@@ -4507,8 +4507,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
|
|
IEEE80211_TX_CTRL_MLO_LINK_UNSPEC,
|
|
NULL);
|
|
} else if (ieee80211_vif_is_mld(&sdata->vif) &&
|
|
- sdata->vif.type == NL80211_IFTYPE_AP &&
|
|
- !ieee80211_hw_check(&sdata->local->hw, MLO_MCAST_MULTI_LINK_TX)) {
|
|
+ ((sdata->vif.type == NL80211_IFTYPE_AP &&
|
|
+ !ieee80211_hw_check(&sdata->local->hw, MLO_MCAST_MULTI_LINK_TX)) ||
|
|
+ (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
|
|
+ !sdata->wdev.use_4addr))) {
|
|
ieee80211_mlo_multicast_tx(dev, skb);
|
|
} else {
|
|
normal:
|
|
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
|
|
index 43e8343df0db71..5a4b175b78c8c9 100644
|
|
--- a/net/mpls/af_mpls.c
|
|
+++ b/net/mpls/af_mpls.c
|
|
@@ -81,8 +81,8 @@ static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
|
|
|
|
if (index < net->mpls.platform_labels) {
|
|
struct mpls_route __rcu **platform_label =
|
|
- rcu_dereference(net->mpls.platform_label);
|
|
- rt = rcu_dereference(platform_label[index]);
|
|
+ rcu_dereference_rtnl(net->mpls.platform_label);
|
|
+ rt = rcu_dereference_rtnl(platform_label[index]);
|
|
}
|
|
return rt;
|
|
}
|
|
diff --git a/net/nfc/nci/uart.c b/net/nfc/nci/uart.c
|
|
index ed1508a9e093ed..aab107727f186e 100644
|
|
--- a/net/nfc/nci/uart.c
|
|
+++ b/net/nfc/nci/uart.c
|
|
@@ -119,22 +119,22 @@ static int nci_uart_set_driver(struct tty_struct *tty, unsigned int driver)
|
|
|
|
memcpy(nu, nci_uart_drivers[driver], sizeof(struct nci_uart));
|
|
nu->tty = tty;
|
|
- tty->disc_data = nu;
|
|
skb_queue_head_init(&nu->tx_q);
|
|
INIT_WORK(&nu->write_work, nci_uart_write_work);
|
|
spin_lock_init(&nu->rx_lock);
|
|
|
|
ret = nu->ops.open(nu);
|
|
if (ret) {
|
|
- tty->disc_data = NULL;
|
|
kfree(nu);
|
|
+ return ret;
|
|
} else if (!try_module_get(nu->owner)) {
|
|
nu->ops.close(nu);
|
|
- tty->disc_data = NULL;
|
|
kfree(nu);
|
|
return -ENOENT;
|
|
}
|
|
- return ret;
|
|
+ tty->disc_data = nu;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
/* ------ LDISC part ------ */
|
|
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
|
|
index d564675a8be4d7..e871cb53946a3e 100644
|
|
--- a/net/sched/sch_sfq.c
|
|
+++ b/net/sched/sch_sfq.c
|
|
@@ -656,6 +656,14 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
|
|
NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
|
|
return -EINVAL;
|
|
}
|
|
+
|
|
+ if (ctl->perturb_period < 0 ||
|
|
+ ctl->perturb_period > INT_MAX / HZ) {
|
|
+ NL_SET_ERR_MSG_MOD(extack, "invalid perturb period");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ perturb_period = ctl->perturb_period * HZ;
|
|
+
|
|
if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max,
|
|
ctl_v1->Wlog, ctl_v1->Scell_log, NULL))
|
|
return -EINVAL;
|
|
@@ -672,14 +680,12 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
|
|
headdrop = q->headdrop;
|
|
maxdepth = q->maxdepth;
|
|
maxflows = q->maxflows;
|
|
- perturb_period = q->perturb_period;
|
|
quantum = q->quantum;
|
|
flags = q->flags;
|
|
|
|
/* update and validate configuration */
|
|
if (ctl->quantum)
|
|
quantum = ctl->quantum;
|
|
- perturb_period = ctl->perturb_period * HZ;
|
|
if (ctl->flows)
|
|
maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS);
|
|
if (ctl->divisor) {
|
|
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
|
|
index 951a87909c2974..d162e2dd860255 100644
|
|
--- a/net/sched/sch_taprio.c
|
|
+++ b/net/sched/sch_taprio.c
|
|
@@ -1338,13 +1338,15 @@ static int taprio_dev_notifier(struct notifier_block *nb, unsigned long event,
|
|
|
|
stab = rtnl_dereference(q->root->stab);
|
|
|
|
- oper = rtnl_dereference(q->oper_sched);
|
|
+ rcu_read_lock();
|
|
+ oper = rcu_dereference(q->oper_sched);
|
|
if (oper)
|
|
taprio_update_queue_max_sdu(q, oper, stab);
|
|
|
|
- admin = rtnl_dereference(q->admin_sched);
|
|
+ admin = rcu_dereference(q->admin_sched);
|
|
if (admin)
|
|
taprio_update_queue_max_sdu(q, admin, stab);
|
|
+ rcu_read_unlock();
|
|
|
|
break;
|
|
}
|
|
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
|
|
index b84c5e0a76f52d..adc04e88f349f0 100644
|
|
--- a/net/sctp/socket.c
|
|
+++ b/net/sctp/socket.c
|
|
@@ -9094,7 +9094,8 @@ static void __sctp_write_space(struct sctp_association *asoc)
|
|
wq = rcu_dereference(sk->sk_wq);
|
|
if (wq) {
|
|
if (waitqueue_active(&wq->wait))
|
|
- wake_up_interruptible(&wq->wait);
|
|
+ wake_up_interruptible_poll(&wq->wait, EPOLLOUT |
|
|
+ EPOLLWRNORM | EPOLLWRBAND);
|
|
|
|
/* Note that we try to include the Async I/O support
|
|
* here by modeling from the current TCP/UDP code.
|
|
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
|
|
index b43dc8409b1fb0..4d8d460747164e 100644
|
|
--- a/net/sunrpc/svc.c
|
|
+++ b/net/sunrpc/svc.c
|
|
@@ -1344,7 +1344,8 @@ svc_process_common(struct svc_rqst *rqstp)
|
|
case SVC_OK:
|
|
break;
|
|
case SVC_GARBAGE:
|
|
- goto err_garbage_args;
|
|
+ rqstp->rq_auth_stat = rpc_autherr_badcred;
|
|
+ goto err_bad_auth;
|
|
case SVC_SYSERR:
|
|
goto err_system_err;
|
|
case SVC_DENIED:
|
|
@@ -1485,14 +1486,6 @@ svc_process_common(struct svc_rqst *rqstp)
|
|
*rqstp->rq_accept_statp = rpc_proc_unavail;
|
|
goto sendit;
|
|
|
|
-err_garbage_args:
|
|
- svc_printk(rqstp, "failed to decode RPC header\n");
|
|
-
|
|
- if (serv->sv_stats)
|
|
- serv->sv_stats->rpcbadfmt++;
|
|
- *rqstp->rq_accept_statp = rpc_garbage_args;
|
|
- goto sendit;
|
|
-
|
|
err_system_err:
|
|
if (serv->sv_stats)
|
|
serv->sv_stats->rpcbadfmt++;
|
|
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
|
|
index 29df05879c8e95..f90d84492bbedc 100644
|
|
--- a/net/sunrpc/xprtsock.c
|
|
+++ b/net/sunrpc/xprtsock.c
|
|
@@ -2724,6 +2724,11 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
|
|
}
|
|
rpc_shutdown_client(lower_clnt);
|
|
|
|
+ /* Check for ingress data that arrived before the socket's
|
|
+ * ->data_ready callback was set up.
|
|
+ */
|
|
+ xs_poll_check_readable(upper_transport);
|
|
+
|
|
out_unlock:
|
|
current_restore_flags(pflags, PF_MEMALLOC);
|
|
upper_transport->clnt = NULL;
|
|
diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c
|
|
index 79f91b6ca8c847..ea5bb131ebd060 100644
|
|
--- a/net/tipc/crypto.c
|
|
+++ b/net/tipc/crypto.c
|
|
@@ -425,7 +425,7 @@ static void tipc_aead_free(struct rcu_head *rp)
|
|
}
|
|
free_percpu(aead->tfm_entry);
|
|
kfree_sensitive(aead->key);
|
|
- kfree(aead);
|
|
+ kfree_sensitive(aead);
|
|
}
|
|
|
|
static int tipc_aead_users(struct tipc_aead __rcu *aead)
|
|
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
|
|
index b16ca400ff559c..e993bd6ed7c26f 100644
|
|
--- a/net/tipc/udp_media.c
|
|
+++ b/net/tipc/udp_media.c
|
|
@@ -489,7 +489,7 @@ int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
|
rtnl_lock();
|
|
b = tipc_bearer_find(net, bname);
|
|
- if (!b) {
|
|
+ if (!b || b->bcast_addr.media_id != TIPC_MEDIA_TYPE_UDP) {
|
|
rtnl_unlock();
|
|
return -EINVAL;
|
|
}
|
|
@@ -500,7 +500,7 @@ int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
|
rtnl_lock();
|
|
b = rtnl_dereference(tn->bearer_list[bid]);
|
|
- if (!b) {
|
|
+ if (!b || b->bcast_addr.media_id != TIPC_MEDIA_TYPE_UDP) {
|
|
rtnl_unlock();
|
|
return -EINVAL;
|
|
}
|
|
diff --git a/net/wireless/core.c b/net/wireless/core.c
|
|
index a2b15349324b6e..f6693983b5e986 100644
|
|
--- a/net/wireless/core.c
|
|
+++ b/net/wireless/core.c
|
|
@@ -550,6 +550,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
|
|
INIT_WORK(&rdev->mgmt_registrations_update_wk,
|
|
cfg80211_mgmt_registrations_update_wk);
|
|
spin_lock_init(&rdev->mgmt_registrations_lock);
|
|
+ INIT_WORK(&rdev->wiphy_work, cfg80211_wiphy_work);
|
|
+ INIT_LIST_HEAD(&rdev->wiphy_work_list);
|
|
+ spin_lock_init(&rdev->wiphy_work_lock);
|
|
|
|
#ifdef CONFIG_CFG80211_DEFAULT_PS
|
|
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
|
@@ -567,9 +570,6 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
|
|
return NULL;
|
|
}
|
|
|
|
- INIT_WORK(&rdev->wiphy_work, cfg80211_wiphy_work);
|
|
- INIT_LIST_HEAD(&rdev->wiphy_work_list);
|
|
- spin_lock_init(&rdev->wiphy_work_lock);
|
|
INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work);
|
|
INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
|
|
INIT_WORK(&rdev->event_work, cfg80211_event_work);
|
|
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
|
|
index 95fcd2d3433e4b..0fbbc62ed3edec 100644
|
|
--- a/security/selinux/xfrm.c
|
|
+++ b/security/selinux/xfrm.c
|
|
@@ -95,7 +95,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
|
|
|
|
ctx->ctx_doi = XFRM_SC_DOI_LSM;
|
|
ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
|
|
- ctx->ctx_len = str_len;
|
|
+ ctx->ctx_len = str_len + 1;
|
|
memcpy(ctx->ctx_str, &uctx[1], str_len);
|
|
ctx->ctx_str[str_len] = '\0';
|
|
rc = security_context_to_sid(ctx->ctx_str, str_len,
|
|
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
|
|
index 3a0df631d25d91..3cd5b7da8e1528 100644
|
|
--- a/sound/pci/hda/hda_intel.c
|
|
+++ b/sound/pci/hda/hda_intel.c
|
|
@@ -2266,6 +2266,8 @@ static const struct snd_pci_quirk power_save_denylist[] = {
|
|
SND_PCI_QUIRK(0x1734, 0x1232, "KONTRON SinglePC", 0),
|
|
/* Dell ALC3271 */
|
|
SND_PCI_QUIRK(0x1028, 0x0962, "Dell ALC3271", 0),
|
|
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=220210 */
|
|
+ SND_PCI_QUIRK(0x17aa, 0x5079, "Lenovo Thinkpad E15", 0),
|
|
{}
|
|
};
|
|
#endif /* CONFIG_PM */
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 440b934cdc284a..82210b1e3b9782 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -9952,6 +9952,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
|
|
SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
|
|
SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
|
|
+ SND_PCI_QUIRK(0x1028, 0x0879, "Dell Latitude 5420 Rugged", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
|
|
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
|
|
index 622df58a969421..9fdee74c28df27 100644
|
|
--- a/sound/soc/amd/yc/acp6x-mach.c
|
|
+++ b/sound/soc/amd/yc/acp6x-mach.c
|
|
@@ -311,6 +311,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "83AS"),
|
|
}
|
|
},
|
|
+ {
|
|
+ .driver_data = &acp6x_card,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "83HN"),
|
|
+ }
|
|
+ },
|
|
{
|
|
.driver_data = &acp6x_card,
|
|
.matches = {
|
|
@@ -360,7 +367,7 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"),
|
|
}
|
|
},
|
|
- {
|
|
+ {
|
|
.driver_data = &acp6x_card,
|
|
.matches = {
|
|
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
|
|
index 5c6b825c757b33..181b16530e5bc9 100644
|
|
--- a/sound/soc/codecs/tas2770.c
|
|
+++ b/sound/soc/codecs/tas2770.c
|
|
@@ -158,11 +158,37 @@ static const struct snd_kcontrol_new isense_switch =
|
|
static const struct snd_kcontrol_new vsense_switch =
|
|
SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 2, 1, 1);
|
|
|
|
+static int sense_event(struct snd_soc_dapm_widget *w,
|
|
+ struct snd_kcontrol *kcontrol, int event)
|
|
+{
|
|
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
|
+ struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
|
|
+
|
|
+ /*
|
|
+ * Powering up ISENSE/VSENSE requires a trip through the shutdown state.
|
|
+ * Do that here to ensure that our changes are applied properly, otherwise
|
|
+ * we might end up with non-functional IVSENSE if playback started earlier,
|
|
+ * which would break software speaker protection.
|
|
+ */
|
|
+ switch (event) {
|
|
+ case SND_SOC_DAPM_PRE_REG:
|
|
+ return snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
|
|
+ TAS2770_PWR_CTRL_MASK,
|
|
+ TAS2770_PWR_CTRL_SHUTDOWN);
|
|
+ case SND_SOC_DAPM_POST_REG:
|
|
+ return tas2770_update_pwr_ctrl(tas2770);
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
|
|
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
|
|
SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2770_asi1_mux),
|
|
- SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch),
|
|
- SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch),
|
|
+ SND_SOC_DAPM_SWITCH_E("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch,
|
|
+ sense_event, SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG),
|
|
+ SND_SOC_DAPM_SWITCH_E("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch,
|
|
+ sense_event, SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG),
|
|
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
|
|
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
|
|
SND_SOC_DAPM_OUTPUT("OUT"),
|
|
diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c
|
|
index f7fd9c013e19f7..1adaf0041a4804 100644
|
|
--- a/sound/soc/meson/meson-card-utils.c
|
|
+++ b/sound/soc/meson/meson-card-utils.c
|
|
@@ -231,7 +231,7 @@ static int meson_card_parse_of_optional(struct snd_soc_card *card,
|
|
const char *p))
|
|
{
|
|
/* If property is not provided, don't fail ... */
|
|
- if (!of_property_read_bool(card->dev->of_node, propname))
|
|
+ if (!of_property_present(card->dev->of_node, propname))
|
|
return 0;
|
|
|
|
/* ... but do fail if it is provided and the parsing fails */
|
|
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
|
|
index 3eb29645a6377c..39d22304ce43ff 100644
|
|
--- a/sound/soc/qcom/sdm845.c
|
|
+++ b/sound/soc/qcom/sdm845.c
|
|
@@ -90,6 +90,10 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
|
|
else
|
|
ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt,
|
|
tx_ch, 0, NULL);
|
|
+ if (ret != 0 && ret != -ENOTSUPP) {
|
|
+ dev_err(rtd->dev, "failed to set cpu chan map, err:%d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c
|
|
index ab3c6b2544d205..140cb27f73287e 100644
|
|
--- a/sound/soc/tegra/tegra210_ahub.c
|
|
+++ b/sound/soc/tegra/tegra210_ahub.c
|
|
@@ -1359,6 +1359,8 @@ static int tegra_ahub_probe(struct platform_device *pdev)
|
|
return -ENOMEM;
|
|
|
|
ahub->soc_data = of_device_get_match_data(&pdev->dev);
|
|
+ if (!ahub->soc_data)
|
|
+ return -ENODEV;
|
|
|
|
platform_set_drvdata(pdev, ahub);
|
|
|
|
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
|
|
index 0e9b5431a47f20..faac7df1fbcf02 100644
|
|
--- a/sound/usb/mixer_maps.c
|
|
+++ b/sound/usb/mixer_maps.c
|
|
@@ -383,6 +383,13 @@ static const struct usbmix_name_map ms_usb_link_map[] = {
|
|
{ 0 } /* terminator */
|
|
};
|
|
|
|
+/* KTMicro USB */
|
|
+static struct usbmix_name_map s31b2_0022_map[] = {
|
|
+ { 23, "Speaker Playback" },
|
|
+ { 18, "Headphone Playback" },
|
|
+ { 0 }
|
|
+};
|
|
+
|
|
/* ASUS ROG Zenith II with Realtek ALC1220-VB */
|
|
static const struct usbmix_name_map asus_zenith_ii_map[] = {
|
|
{ 19, NULL, 12 }, /* FU, Input Gain Pad - broken response, disabled */
|
|
@@ -692,6 +699,11 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
|
|
.id = USB_ID(0x045e, 0x083c),
|
|
.map = ms_usb_link_map,
|
|
},
|
|
+ {
|
|
+ /* KTMicro USB */
|
|
+ .id = USB_ID(0X31b2, 0x0022),
|
|
+ .map = s31b2_0022_map,
|
|
+ },
|
|
{ 0 } /* terminator */
|
|
};
|
|
|
|
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
|
|
index 2a90f04a4160db..2e064a1032a050 100644
|
|
--- a/tools/include/uapi/linux/bpf.h
|
|
+++ b/tools/include/uapi/linux/bpf.h
|
|
@@ -1913,6 +1913,7 @@ union bpf_attr {
|
|
* for updates resulting in a null checksum the value is set to
|
|
* **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
|
|
* the checksum is to be computed against a pseudo-header.
|
|
+ * Flag **BPF_F_IPV6** should be set for IPv6 packets.
|
|
*
|
|
* This helper works in combination with **bpf_csum_diff**\ (),
|
|
* which does not update the checksum in-place, but offers more
|
|
@@ -5920,6 +5921,7 @@ enum {
|
|
BPF_F_PSEUDO_HDR = (1ULL << 4),
|
|
BPF_F_MARK_MANGLED_0 = (1ULL << 5),
|
|
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
|
+ BPF_F_IPV6 = (1ULL << 7),
|
|
};
|
|
|
|
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
|
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
|
|
index 8484b563b53d0a..2e9f28cece3ffe 100644
|
|
--- a/tools/lib/bpf/btf.c
|
|
+++ b/tools/lib/bpf/btf.c
|
|
@@ -3922,6 +3922,19 @@ static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32 id1, __u32 id
|
|
return true;
|
|
}
|
|
|
|
+static bool btf_dedup_identical_ptrs(struct btf_dedup *d, __u32 id1, __u32 id2)
|
|
+{
|
|
+ struct btf_type *t1, *t2;
|
|
+
|
|
+ t1 = btf_type_by_id(d->btf, id1);
|
|
+ t2 = btf_type_by_id(d->btf, id2);
|
|
+
|
|
+ if (!btf_is_ptr(t1) || !btf_is_ptr(t2))
|
|
+ return false;
|
|
+
|
|
+ return t1->type == t2->type;
|
|
+}
|
|
+
|
|
/*
|
|
* Check equivalence of BTF type graph formed by candidate struct/union (we'll
|
|
* call it "candidate graph" in this description for brevity) to a type graph
|
|
@@ -4054,6 +4067,9 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
|
|
*/
|
|
if (btf_dedup_identical_structs(d, hypot_type_id, cand_id))
|
|
return 1;
|
|
+ /* A similar case is again observed for PTRs. */
|
|
+ if (btf_dedup_identical_ptrs(d, hypot_type_id, cand_id))
|
|
+ return 1;
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
|
|
index 9bee082194d5ea..fb11a967c450dc 100644
|
|
--- a/tools/perf/util/print-events.c
|
|
+++ b/tools/perf/util/print-events.c
|
|
@@ -271,6 +271,7 @@ bool is_event_supported(u8 type, u64 config)
|
|
ret = evsel__open(evsel, NULL, tmap) >= 0;
|
|
}
|
|
|
|
+ evsel__close(evsel);
|
|
evsel__delete(evsel);
|
|
}
|
|
|
|
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
|
|
index 7e8c937627dd94..13ce9a53d5dec5 100644
|
|
--- a/tools/testing/selftests/x86/Makefile
|
|
+++ b/tools/testing/selftests/x86/Makefile
|
|
@@ -12,7 +12,7 @@ CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh "$(CC)" trivial_program.c -no-pie)
|
|
|
|
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \
|
|
check_initial_reg_state sigreturn iopl ioperm \
|
|
- test_vsyscall mov_ss_trap \
|
|
+ test_vsyscall mov_ss_trap sigtrap_loop \
|
|
syscall_arg_fault fsgsbase_restore sigaltstack
|
|
TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \
|
|
test_FCMOV test_FCOMI test_FISTTP \
|
|
diff --git a/tools/testing/selftests/x86/sigtrap_loop.c b/tools/testing/selftests/x86/sigtrap_loop.c
|
|
new file mode 100644
|
|
index 00000000000000..9d065479e89f94
|
|
--- /dev/null
|
|
+++ b/tools/testing/selftests/x86/sigtrap_loop.c
|
|
@@ -0,0 +1,101 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-only
|
|
+/*
|
|
+ * Copyright (C) 2025 Intel Corporation
|
|
+ */
|
|
+#define _GNU_SOURCE
|
|
+
|
|
+#include <err.h>
|
|
+#include <signal.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <sys/ucontext.h>
|
|
+
|
|
+#ifdef __x86_64__
|
|
+# define REG_IP REG_RIP
|
|
+#else
|
|
+# define REG_IP REG_EIP
|
|
+#endif
|
|
+
|
|
+static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), int flags)
|
|
+{
|
|
+ struct sigaction sa;
|
|
+
|
|
+ memset(&sa, 0, sizeof(sa));
|
|
+ sa.sa_sigaction = handler;
|
|
+ sa.sa_flags = SA_SIGINFO | flags;
|
|
+ sigemptyset(&sa.sa_mask);
|
|
+
|
|
+ if (sigaction(sig, &sa, 0))
|
|
+ err(1, "sigaction");
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
|
|
+{
|
|
+ ucontext_t *ctx = (ucontext_t *)ctx_void;
|
|
+ static unsigned int loop_count_on_same_ip;
|
|
+ static unsigned long last_trap_ip;
|
|
+
|
|
+ if (last_trap_ip == ctx->uc_mcontext.gregs[REG_IP]) {
|
|
+ printf("\tTrapped at %016lx\n", last_trap_ip);
|
|
+
|
|
+ /*
|
|
+ * If the same IP is hit more than 10 times in a row, it is
|
|
+ * _considered_ an infinite loop.
|
|
+ */
|
|
+ if (++loop_count_on_same_ip > 10) {
|
|
+ printf("[FAIL]\tDetected SIGTRAP infinite loop\n");
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ loop_count_on_same_ip = 0;
|
|
+ last_trap_ip = ctx->uc_mcontext.gregs[REG_IP];
|
|
+ printf("\tTrapped at %016lx\n", last_trap_ip);
|
|
+}
|
|
+
|
|
+int main(int argc, char *argv[])
|
|
+{
|
|
+ sethandler(SIGTRAP, sigtrap, 0);
|
|
+
|
|
+ /*
|
|
+ * Set the Trap Flag (TF) to single-step the test code, therefore to
|
|
+ * trigger a SIGTRAP signal after each instruction until the TF is
|
|
+ * cleared.
|
|
+ *
|
|
+ * Because the arithmetic flags are not significant here, the TF is
|
|
+ * set by pushing 0x302 onto the stack and then popping it into the
|
|
+ * flags register.
|
|
+ *
|
|
+ * Four instructions in the following asm code are executed with the
|
|
+ * TF set, thus the SIGTRAP handler is expected to run four times.
|
|
+ */
|
|
+ printf("[RUN]\tSIGTRAP infinite loop detection\n");
|
|
+ asm volatile(
|
|
+#ifdef __x86_64__
|
|
+ /*
|
|
+ * Avoid clobbering the redzone
|
|
+ *
|
|
+ * Equivalent to "sub $128, %rsp", however -128 can be encoded
|
|
+ * in a single byte immediate while 128 uses 4 bytes.
|
|
+ */
|
|
+ "add $-128, %rsp\n\t"
|
|
+#endif
|
|
+ "push $0x302\n\t"
|
|
+ "popf\n\t"
|
|
+ "nop\n\t"
|
|
+ "nop\n\t"
|
|
+ "push $0x202\n\t"
|
|
+ "popf\n\t"
|
|
+#ifdef __x86_64__
|
|
+ "sub $-128, %rsp\n\t"
|
|
+#endif
|
|
+ );
|
|
+
|
|
+ printf("[OK]\tNo SIGTRAP infinite loop detected\n");
|
|
+ return 0;
|
|
+}
|