summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2026-06-01 13:35:51 +0200
committerPaolo Abeni <pabeni@redhat.com>2026-06-01 13:42:12 +0200
commitc2c0486c56800ce276e79c40a6e576ffd672f2a9 (patch)
tree772e6e01d5c2b8ed08f705533e35eed3efcd2676
parent8415598365503ced2e3d019491b0a2756c85c494 (diff)
parentf3be0c984ecbcb82b0bec408022c4ef738cb3843 (diff)
downloadlinux-c2c0486c56800ce276e79c40a6e576ffd672f2a9.tar.gz
linux-c2c0486c56800ce276e79c40a6e576ffd672f2a9.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Conflicts: drivers/net/ethernet/microsoft/mana/mana_en.c: 17bfe0a8c014e ("net: mana: Add NULL guards in teardown path to prevent panic on attach failure") d07efe5a6e641 ("net: mana: Use per-queue allocation for tx_qp to reduce allocation size") Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--MAINTAINERS5
-rw-r--r--arch/arm64/include/asm/kvm_host.h2
-rw-r--r--arch/arm64/kvm/hyp/include/hyp/switch.h16
-rw-r--r--arch/arm64/kvm/hyp/nvhe/host.S2
-rw-r--r--arch/arm64/kvm/hyp_trace.c9
-rw-r--r--arch/arm64/kvm/nested.c5
-rw-r--r--arch/arm64/kvm/pmu-emul.c4
-rw-r--r--arch/arm64/kvm/sys_regs.c11
-rw-r--r--arch/riscv/include/asm/syscall_wrapper.h4
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/svm/avic.c35
-rw-r--r--arch/x86/kvm/svm/sev.c91
-rw-r--r--arch/x86/kvm/x86.c13
-rw-r--r--arch/x86/virt/hw.c15
-rw-r--r--block/blk-mq.c2
-rw-r--r--drivers/acpi/acpica/evxfgpe.c50
-rw-r--r--drivers/acpi/button.c25
-rw-r--r--drivers/bluetooth/btusb.c8
-rw-r--r--drivers/bluetooth/hci_qca.c4
-rw-r--r--drivers/cpufreq/amd-pstate-ut.c16
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-lenovo-go-s.c11
-rw-r--r--drivers/hid/hid-lenovo-go.c6
-rw-r--r--drivers/hid/hid-lenovo.c5
-rw-r--r--drivers/hid/hid-quirks.c1
-rw-r--r--drivers/hid/hid-u2fzero.c22
-rw-r--r--drivers/hid/wacom_sys.c13
-rw-r--r--drivers/hid/wacom_wac.h1
-rw-r--r--drivers/iommu/intel/cache.c51
-rw-r--r--drivers/iommu/io-pgtable-arm-v7s.c18
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c76
-rw-r--r--drivers/net/pcs/pcs-mtk-lynxi.c3
-rw-r--r--drivers/net/wireguard/send.c20
-rw-r--r--include/acpi/acpixf.h5
-rw-r--r--include/linux/compat.h4
-rw-r--r--include/linux/compiler-clang.h6
-rw-r--r--include/linux/compiler_attributes.h11
-rw-r--r--include/linux/compiler_types.h4
-rw-r--r--include/linux/hid.h2
-rw-r--r--include/linux/syscalls.h4
-rw-r--r--include/net/xfrm.h3
-rw-r--r--io_uring/tctx.c12
-rw-r--r--lib/debugobjects.c2
-rw-r--r--net/bluetooth/6lowpan.c2
-rw-r--r--net/bluetooth/hci_conn.c4
-rw-r--r--net/bluetooth/hci_core.c43
-rw-r--r--net/bluetooth/hci_sync.c16
-rw-r--r--net/bluetooth/hidp/core.c23
-rw-r--r--net/bluetooth/iso.c12
-rw-r--r--net/bluetooth/l2cap_core.c41
-rw-r--r--net/bluetooth/l2cap_sock.c16
-rw-r--r--net/core/filter.c2
-rw-r--r--net/core/skbuff.c10
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/esp4.c4
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/esp6.c4
-rw-r--r--net/ipv6/route.c5
-rw-r--r--net/key/af_key.c6
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/vmw_vsock/virtio_transport_common.c12
-rw-r--r--net/xfrm/xfrm_input.c16
-rw-r--r--net/xfrm/xfrm_ipcomp.c12
-rw-r--r--net/xfrm/xfrm_iptfs.c28
-rw-r--r--net/xfrm/xfrm_policy.c17
-rw-r--r--net/xfrm/xfrm_state.c23
-rw-r--r--net/xfrm/xfrm_user.c5
-rw-r--r--sound/core/oss/pcm_oss.c18
-rw-r--r--sound/firewire/motu/motu-register-dsp-message-parser.c11
-rw-r--r--sound/hda/codecs/cirrus/cs420x.c1
-rw-r--r--sound/hda/codecs/realtek/alc269.c6
-rw-r--r--sound/hda/codecs/side-codecs/cs35l56_hda.c17
-rw-r--r--sound/soc/codecs/simple-mux.c2
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c29
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c48
-rw-r--r--sound/usb/mixer_scarlett2.c33
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--tools/testing/cxl/test/cxl.c105
-rw-r--r--tools/testing/selftests/kvm/access_tracking_perf_test.c2
-rw-r--r--tools/testing/selftests/kvm/guest_memfd_test.c2
-rw-r--r--tools/testing/selftests/kvm/include/kvm_syscalls.h10
-rw-r--r--tools/testing/selftests/kvm/include/test_util.h2
-rw-r--r--tools/testing/selftests/kvm/lib/assert.c8
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util.c2
-rw-r--r--tools/testing/selftests/kvm/memslot_perf_test.c2
-rw-r--r--tools/testing/selftests/kvm/s390/shared_zeropage_test.c3
-rw-r--r--tools/testing/selftests/kvm/s390/tprot.c2
-rw-r--r--tools/testing/selftests/kvm/set_memory_region_test.c2
-rwxr-xr-xtools/testing/selftests/net/ioam6.sh2
90 files changed, 799 insertions, 418 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 9ce5542ab2f3..142a91386338 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1158,8 +1158,9 @@ F: Documentation/arch/x86/amd-hfi.rst
F: drivers/platform/x86/amd/hfi/
AMD IOMMU (AMD-VI)
-M: Joerg Roedel <joro@8bytes.org>
+M: Joerg Roedel (AMD) <joro@8bytes.org>
R: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+R: Vasant Hegde <vasant.hegde@amd.com>
L: iommu@lists.linux.dev
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux.git
@@ -13491,7 +13492,7 @@ F: include/linux/iommu-dma.h
F: include/linux/iova.h
IOMMU SUBSYSTEM
-M: Joerg Roedel <joro@8bytes.org>
+M: Joerg Roedel (AMD) <joro@8bytes.org>
M: Will Deacon <will@kernel.org>
R: Robin Murphy <robin.murphy@arm.com>
L: iommu@lists.linux.dev
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 65eead8362e0..a49042bfa801 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -511,7 +511,6 @@ enum vcpu_sysreg {
ACTLR_EL2, /* Auxiliary Control Register (EL2) */
CPTR_EL2, /* Architectural Feature Trap Register (EL2) */
HACR_EL2, /* Hypervisor Auxiliary Control Register */
- ZCR_EL2, /* SVE Control Register (EL2) */
TTBR0_EL2, /* Translation Table Base Register 0 (EL2) */
TTBR1_EL2, /* Translation Table Base Register 1 (EL2) */
TCR_EL2, /* Translation Control Register (EL2) */
@@ -543,6 +542,7 @@ enum vcpu_sysreg {
SCTLR2_EL2, /* System Control Register 2 (EL2) */
MDCR_EL2, /* Monitor Debug Configuration Register (EL2) */
CNTHCTL_EL2, /* Counter-timer Hypervisor Control register */
+ ZCR_EL2, /* SVE Control Register (EL2) */
/* Any VNCR-capable reg goes after this point */
MARKER(__VNCR_START__),
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index bf0eb5e43427..320cd45d49c5 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -462,11 +462,13 @@ static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu)
{
+ u64 zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
/*
* The vCPU's saved SVE state layout always matches the max VL of the
* vCPU. Start off with the max VL so we can load the SVE state.
*/
- sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL2);
+ sve_cond_update_zcr_vq(zcr_el2, SYS_ZCR_EL2);
__sve_restore_state(vcpu_sve_pffr(vcpu),
&vcpu->arch.ctxt.fp_regs.fpsr,
true);
@@ -476,8 +478,10 @@ static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu)
* nested guest, as the guest hypervisor could select a smaller VL. Slap
* that into hardware before wrapping up.
*/
- if (is_nested_ctxt(vcpu))
- sve_cond_update_zcr_vq(__vcpu_sys_reg(vcpu, ZCR_EL2), SYS_ZCR_EL2);
+ if (is_nested_ctxt(vcpu)) {
+ zcr_el2 = min(zcr_el2, __vcpu_sys_reg(vcpu, ZCR_EL2));
+ sve_cond_update_zcr_vq(zcr_el2, SYS_ZCR_EL2);
+ }
write_sysreg_el1(__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)), SYS_ZCR);
}
@@ -501,11 +505,11 @@ static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
return;
if (vcpu_has_sve(vcpu)) {
+ zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+
/* A guest hypervisor may restrict the effective max VL. */
if (is_nested_ctxt(vcpu))
- zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
- else
- zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
+ zcr_el2 = min(zcr_el2, __vcpu_sys_reg(vcpu, ZCR_EL2));
write_sysreg_el2(zcr_el2, SYS_ZCR);
diff --git a/arch/arm64/kvm/hyp/nvhe/host.S b/arch/arm64/kvm/hyp/nvhe/host.S
index f337770ec459..9393fe3ea6a1 100644
--- a/arch/arm64/kvm/hyp/nvhe/host.S
+++ b/arch/arm64/kvm/hyp/nvhe/host.S
@@ -120,7 +120,7 @@ SYM_FUNC_START(__hyp_do_panic)
mov x29, x0
-#ifdef PKVM_DISABLE_STAGE2_ON_PANIC
+#ifdef CONFIG_PKVM_DISABLE_STAGE2_ON_PANIC
/* Ensure host stage-2 is disabled */
mrs x0, hcr_el2
bic x0, x0, #HCR_VM
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 8b7f2bf2fba8..c4b3ee552131 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -189,7 +189,7 @@ static void hyp_trace_buffer_unshare_hyp(struct hyp_trace_buffer *trace_buffer,
if (cpu > last_cpu)
break;
- __share_page(rb_desc->meta_va);
+ __unshare_page(rb_desc->meta_va);
for (p = 0; p < rb_desc->nr_page_va; p++)
__unshare_page(rb_desc->page_va[p]);
}
@@ -212,14 +212,15 @@ static int hyp_trace_buffer_share_hyp(struct hyp_trace_buffer *trace_buffer)
}
if (ret) {
- for (p--; p >= 0; p--)
+ while (--p >= 0)
__unshare_page(rb_desc->page_va[p]);
+ __unshare_page(rb_desc->meta_va);
break;
}
}
if (ret)
- hyp_trace_buffer_unshare_hyp(trace_buffer, cpu--);
+ hyp_trace_buffer_unshare_hyp(trace_buffer, --cpu);
return ret;
}
@@ -248,6 +249,7 @@ static struct trace_buffer_desc *hyp_trace_load(unsigned long size, void *priv)
goto err_free_desc;
trace_buffer->desc = desc;
+ trace_buffer->desc_size = desc_size;
ret = hyp_trace_buffer_alloc_bpages_backing(trace_buffer, size);
if (ret)
@@ -297,6 +299,7 @@ static void hyp_trace_unload(struct trace_buffer_desc *desc, void *priv)
hyp_trace_buffer_free_bpages_backing(trace_buffer);
free_pages_exact(trace_buffer->desc, trace_buffer->desc_size);
trace_buffer->desc = NULL;
+ trace_buffer->desc_size = 0;
}
static int hyp_trace_enable_tracing(bool enable, void *priv)
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index 883b6c1008fb..38f672e94087 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -1834,6 +1834,11 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
resx.res1 = VNCR_EL2_RES1;
set_sysreg_masks(kvm, VNCR_EL2, resx);
+ /* ZCR_EL2 - bits 8:4 are RAZ/WI so treat them as RES0 */
+ resx.res0 = ZCR_ELx_RES0 | GENMASK_ULL(8, 4);
+ resx.res1 = ZCR_ELx_RES1;
+ set_sysreg_masks(kvm, ZCR_EL2, resx);
+
out:
for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr < NR_SYS_REGS; sr++)
__vcpu_rmw_sys_reg(vcpu, sr, |=, 0);
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index e1860acae641..c816db5d6761 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -174,8 +174,8 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force)
* action is to use PMCR.P, which will reset them to
* 0 (the only use of the 'force' parameter).
*/
- val = __vcpu_sys_reg(vcpu, reg) & GENMASK(63, 32);
- val |= lower_32_bits(val);
+ val = (__vcpu_sys_reg(vcpu, reg) & GENMASK(63, 32)) |
+ lower_32_bits(val);
}
__vcpu_assign_sys_reg(vcpu, reg, val);
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 148fc3400ea8..fa5c93c7a135 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -2862,21 +2862,16 @@ static bool access_zcr_el2(struct kvm_vcpu *vcpu,
struct sys_reg_params *p,
const struct sys_reg_desc *r)
{
- unsigned int vq;
-
if (guest_hyp_sve_traps_enabled(vcpu)) {
kvm_inject_nested_sve_trap(vcpu);
return false;
}
- if (!p->is_write) {
+ if (!p->is_write)
p->regval = __vcpu_sys_reg(vcpu, ZCR_EL2);
- return true;
- }
+ else
+ __vcpu_assign_sys_reg(vcpu, ZCR_EL2, p->regval);
- vq = SYS_FIELD_GET(ZCR_ELx, LEN, p->regval) + 1;
- vq = min(vq, vcpu_sve_max_vq(vcpu));
- __vcpu_assign_sys_reg(vcpu, ZCR_EL2, vq - 1);
return true;
}
diff --git a/arch/riscv/include/asm/syscall_wrapper.h b/arch/riscv/include/asm/syscall_wrapper.h
index ac80216549ff..226289c3b5c8 100644
--- a/arch/riscv/include/asm/syscall_wrapper.h
+++ b/arch/riscv/include/asm/syscall_wrapper.h
@@ -32,6 +32,10 @@ asmlinkage long __riscv_sys_ni_syscall(const struct pt_regs *);
__diag_push(); \
__diag_ignore(GCC, 8, "-Wattribute-alias", \
"Type aliasing is used to sanitize syscall arguments"); \
+ __diag_ignore(clang, 23, "-Wunknown-warning-option", \
+ "Avoid breaking versions without -Wattribute-alias"); \
+ __diag_ignore(clang, 23, "-Wattribute-alias", \
+ "Type aliasing is used to sanitize syscall arguments"); \
static long __se_##prefix##name(ulong, ulong, ulong, ulong, ulong, ulong, \
ulong) \
__attribute__((alias(__stringify(___se_##prefix##name)))); \
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index c470e40a00aa..f14009f25a3b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1504,6 +1504,7 @@ struct kvm_arch {
bool use_master_clock;
u64 master_kernel_ns;
u64 master_cycle_now;
+ struct ratelimit_state kvmclock_update_rs;
#ifdef CONFIG_KVM_HYPERV
struct kvm_hv hyperv;
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 993b551180fe..cdd5a6dc646f 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -207,6 +207,35 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
svm_clr_intercept(svm, INTERCEPT_CR8_WRITE);
/*
+ * Flush the TLB when enabling (x2)AVIC and when transitioning between
+ * xAVIC and x2AVIC, as the CPU may have inserted a TLB entry for the
+ * "wrong" mapping.
+ *
+ * KVM uses a per-VM "scratch" page to back the APIC memslot, because
+ * KVM also uses per-VM page tables *and* maintains the page table (NPT
+ * or shadow page) mappings for said memslot even if one or more vCPUs
+ * have their local APIC hardware-disabled or are in x2APIC mode, i.e.
+ * even if one or more vCPUs' APIC MMIO BAR is effectively disabled.
+ *
+ * If xAVIC is fully enabled, hardware ignores the physical address in
+ * KVM's page tables, i.e. in the leaf SPTE for the APIC memslot, and
+ * instead redirects the access to the AVIC backing page, i.e. to the
+ * vCPU's virtual APIC page. If xAVIC is not enabled (APIC is either
+ * hardware-disabled or in x2APIC mode), then guest accesses will use
+ * the page table mapping verbatim, i.e. will access the per-VM scratch
+ * page, as normal memory.
+ *
+ * In both cases, the CPU is allowed to cache TLB entries for the APIC
+ * base GPA. So, KVM needs to flush the TLB when enabling xAVIC, as
+ * accesses need to be redirected to the virtual APIC page, but the TLB
+ * may contain entries pointing at the scratch page. KVM also needs to
+ * flush the TLB when enabling x2AVIC, as accesses need to go to the
+ * scratch page, but the TLB may contain entries tagged as xAVIC, i.e.
+ * entries pointing to the vCPU's virtual APIC page.
+ */
+ kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, &svm->vcpu);
+
+ /*
* Note: KVM supports hybrid-AVIC mode, where KVM emulates x2APIC MSR
* accesses, while interrupt injection to a running vCPU can be
* achieved using AVIC doorbell. KVM disables the APIC access page
@@ -219,12 +248,6 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
/* Disabling MSR intercept for x2APIC registers */
avic_set_x2apic_msr_interception(svm, false);
} else {
- /*
- * Flush the TLB, the guest may have inserted a non-APIC
- * mapping into the TLB while AVIC was disabled.
- */
- kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, &svm->vcpu);
-
/* Enabling MSR intercept for x2APIC registers */
avic_set_x2apic_msr_interception(svm, true);
}
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index c2126b3c3072..62b5befe0eed 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3662,23 +3662,26 @@ int pre_sev_run(struct vcpu_svm *svm, int cpu)
}
#define GHCB_SCRATCH_AREA_LIMIT (16ULL * PAGE_SIZE)
-static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
+static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 min_len)
{
struct vmcb_control_area *control = &svm->vmcb->control;
u64 ghcb_scratch_beg, ghcb_scratch_end;
u64 scratch_gpa_beg, scratch_gpa_end;
void *scratch_va;
+ if (WARN_ON_ONCE(!min_len))
+ goto e_scratch;
+
scratch_gpa_beg = svm->sev_es.sw_scratch;
if (!scratch_gpa_beg) {
pr_err("vmgexit: scratch gpa not provided\n");
goto e_scratch;
}
- scratch_gpa_end = scratch_gpa_beg + len;
+ scratch_gpa_end = scratch_gpa_beg + min_len;
if (scratch_gpa_end < scratch_gpa_beg) {
pr_err("vmgexit: scratch length (%#llx) not valid for scratch address (%#llx)\n",
- len, scratch_gpa_beg);
+ min_len, scratch_gpa_beg);
goto e_scratch;
}
@@ -3702,21 +3705,27 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
scratch_va = (void *)svm->sev_es.ghcb;
scratch_va += (scratch_gpa_beg - control->ghcb_gpa);
+
+ svm->sev_es.ghcb_sa_len = ghcb_scratch_end - scratch_gpa_beg;
} else {
+ /* GHCB v2 requires the scratch area to be within the GHCB. */
+ if (to_kvm_sev_info(svm->vcpu.kvm)->ghcb_version >= 2)
+ goto e_scratch;
+
/*
* The guest memory must be read into a kernel buffer, so
* limit the size
*/
- if (len > GHCB_SCRATCH_AREA_LIMIT) {
+ if (min_len > GHCB_SCRATCH_AREA_LIMIT) {
pr_err("vmgexit: scratch area exceeds KVM limits (%#llx requested, %#llx limit)\n",
- len, GHCB_SCRATCH_AREA_LIMIT);
+ min_len, GHCB_SCRATCH_AREA_LIMIT);
goto e_scratch;
}
- scratch_va = kvzalloc(len, GFP_KERNEL_ACCOUNT);
+ scratch_va = kvzalloc(min_len, GFP_KERNEL_ACCOUNT);
if (!scratch_va)
return -ENOMEM;
- if (kvm_read_guest(svm->vcpu.kvm, scratch_gpa_beg, scratch_va, len)) {
+ if (kvm_read_guest(svm->vcpu.kvm, scratch_gpa_beg, scratch_va, min_len)) {
/* Unable to copy scratch area from guest */
pr_err("vmgexit: kvm_read_guest for scratch area failed\n");
@@ -3732,11 +3741,10 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
*/
svm->sev_es.ghcb_sa_sync = sync;
svm->sev_es.ghcb_sa_free = true;
+ svm->sev_es.ghcb_sa_len = min_len;
}
svm->sev_es.ghcb_sa = scratch_va;
- svm->sev_es.ghcb_sa_len = len;
-
return 0;
e_scratch:
@@ -3833,7 +3841,7 @@ struct psc_buffer {
struct psc_entry entries[];
} __packed;
-static int snp_begin_psc(struct vcpu_svm *svm, struct psc_buffer *psc);
+static int snp_begin_psc(struct vcpu_svm *svm);
static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret)
{
@@ -3864,9 +3872,9 @@ static void __snp_complete_one_psc(struct vcpu_svm *svm)
*/
for (idx = svm->sev_es.psc_idx; svm->sev_es.psc_inflight;
svm->sev_es.psc_inflight--, idx++) {
- struct psc_entry *entry = &entries[idx];
+ struct psc_entry entry = READ_ONCE(entries[idx]);
- entry->cur_page = entry->pagesize ? 512 : 1;
+ entries[idx].cur_page = entry.pagesize ? 512 : 1;
}
hdr->cur_entry = idx;
@@ -3875,7 +3883,6 @@ static void __snp_complete_one_psc(struct vcpu_svm *svm)
static int snp_complete_one_psc(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct psc_buffer *psc = svm->sev_es.ghcb_sa;
if (vcpu->run->hypercall.ret) {
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
@@ -3885,16 +3892,18 @@ static int snp_complete_one_psc(struct kvm_vcpu *vcpu)
__snp_complete_one_psc(svm);
/* Handle the next range (if any). */
- return snp_begin_psc(svm, psc);
+ return snp_begin_psc(svm);
}
-static int snp_begin_psc(struct vcpu_svm *svm, struct psc_buffer *psc)
+static int snp_begin_psc(struct vcpu_svm *svm)
{
+ struct vcpu_sev_es_state *sev_es = &svm->sev_es;
+ struct psc_buffer *psc = sev_es->ghcb_sa;
struct psc_entry *entries = psc->entries;
struct kvm_vcpu *vcpu = &svm->vcpu;
struct psc_hdr *hdr = &psc->hdr;
struct psc_entry entry_start;
- u16 idx, idx_start, idx_end;
+ u16 idx, idx_start, idx_end, max_nr_entries;
int npages;
bool huge;
u64 gfn;
@@ -3904,6 +3913,19 @@ static int snp_begin_psc(struct vcpu_svm *svm, struct psc_buffer *psc)
return 1;
}
+ /*
+ * GHCB v2 requires the scratch area to reside within the GHCB itself,
+ * and PSC requests are only supported for GHCB v2+. Thus it should be
+ * impossible to exceed the max PSC entry count (which is derived from
+ * the size of the shared GHCB buffer).
+ */
+ max_nr_entries = (sev_es->ghcb_sa_len - sizeof(struct psc_hdr)) /
+ sizeof(struct psc_entry);
+ if (WARN_ON_ONCE(max_nr_entries > VMGEXIT_PSC_MAX_COUNT)) {
+ snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
+ return 1;
+ }
+
next_range:
/* There should be no other PSCs in-flight at this point. */
if (WARN_ON_ONCE(svm->sev_es.psc_inflight)) {
@@ -3916,17 +3938,17 @@ next_range:
* validation, so take care to only use validated copies of values used
* for things like array indexing.
*/
- idx_start = hdr->cur_entry;
- idx_end = hdr->end_entry;
+ idx_start = READ_ONCE(hdr->cur_entry);
+ idx_end = READ_ONCE(hdr->end_entry);
- if (idx_end >= VMGEXIT_PSC_MAX_COUNT) {
+ if (idx_end >= max_nr_entries) {
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_INVALID_HDR);
return 1;
}
/* Find the start of the next range which needs processing. */
for (idx = idx_start; idx <= idx_end; idx++, hdr->cur_entry++) {
- entry_start = entries[idx];
+ entry_start = READ_ONCE(entries[idx]);
gfn = entry_start.gfn;
huge = entry_start.pagesize;
@@ -3970,7 +3992,7 @@ next_range:
* KVM_HC_MAP_GPA_RANGE exit.
*/
while (++idx <= idx_end) {
- struct psc_entry entry = entries[idx];
+ struct psc_entry entry = READ_ONCE(entries[idx]);
if (entry.operation != entry_start.operation ||
entry.gfn != entry_start.gfn + npages ||
@@ -4493,13 +4515,22 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
case SVM_VMGEXIT_MMIO_READ:
case SVM_VMGEXIT_MMIO_WRITE: {
bool is_write = control->exit_code == SVM_VMGEXIT_MMIO_WRITE;
+ u64 len = control->exit_info_2;
- ret = setup_vmgexit_scratch(svm, !is_write, control->exit_info_2);
+ if (!len)
+ return 1;
+
+ if (to_kvm_sev_info(vcpu->kvm)->ghcb_version >= 2 && len > 8) {
+ svm_vmgexit_bad_input(svm, GHCB_ERR_INVALID_INPUT);
+ return 1;
+ }
+
+ ret = setup_vmgexit_scratch(svm, !is_write, len);
if (ret)
break;
- ret = kvm_sev_es_mmio(vcpu, is_write, control->exit_info_1,
- control->exit_info_2, svm->sev_es.ghcb_sa);
+ ret = kvm_sev_es_mmio(vcpu, is_write, control->exit_info_1, len,
+ svm->sev_es.ghcb_sa);
break;
}
case SVM_VMGEXIT_NMI_COMPLETE:
@@ -4546,11 +4577,11 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
vcpu->run->system_event.data[0] = control->ghcb_gpa;
break;
case SVM_VMGEXIT_PSC:
- ret = setup_vmgexit_scratch(svm, true, control->exit_info_2);
+ ret = setup_vmgexit_scratch(svm, true, sizeof(struct psc_hdr));
if (ret)
break;
- ret = snp_begin_psc(svm, svm->sev_es.ghcb_sa);
+ ret = snp_begin_psc(svm);
break;
case SVM_VMGEXIT_AP_CREATION:
ret = sev_snp_ap_creation(svm);
@@ -4572,6 +4603,11 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
control->exit_info_1, control->exit_info_2);
ret = -EINVAL;
break;
+ case SVM_EXIT_IOIO:
+ if (!((control->exit_info_1 & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT))
+ return 1;
+
+ fallthrough;
default:
ret = svm_invoke_exit_handler(vcpu, control->exit_code);
}
@@ -4592,6 +4628,9 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
if (unlikely(check_mul_overflow(count, size, &bytes)))
return -EINVAL;
+ if (!bytes)
+ return 1;
+
r = setup_vmgexit_scratch(svm, in, bytes);
if (r)
return r;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c1a72d749084..0550359ed798 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5227,8 +5227,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
* On a host with synchronized TSC, there is no need to update
* kvmclock on vcpu->cpu migration
*/
- if (!vcpu->kvm->arch.use_master_clock || vcpu->cpu == -1)
- kvm_make_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu);
+ if (!vcpu->kvm->arch.use_master_clock || vcpu->cpu == -1) {
+ if (__ratelimit(&vcpu->kvm->arch.kvmclock_update_rs))
+ kvm_make_request(KVM_REQ_GLOBAL_CLOCK_UPDATE, vcpu);
+ else
+ kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
+ }
+
if (vcpu->cpu != cpu)
kvm_make_request(KVM_REQ_MIGRATE_TIMER, vcpu);
vcpu->cpu = cpu;
@@ -13366,6 +13371,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
raw_spin_lock_init(&kvm->arch.tsc_write_lock);
mutex_init(&kvm->arch.apic_map_lock);
seqcount_raw_spinlock_init(&kvm->arch.pvclock_sc, &kvm->arch.tsc_write_lock);
+ ratelimit_state_init(&kvm->arch.kvmclock_update_rs, HZ, 10);
+ ratelimit_set_flags(&kvm->arch.kvmclock_update_rs, RATELIMIT_MSG_ON_RELEASE);
kvm->arch.kvmclock_offset = -get_kvmclock_base_ns();
raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
@@ -14323,7 +14330,7 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva)
* the RAP (Return Address Predicator).
*/
if (guest_cpu_cap_has(vcpu, X86_FEATURE_ERAPS))
- kvm_register_is_dirty(vcpu, VCPU_EXREG_ERAPS);
+ kvm_register_mark_dirty(vcpu, VCPU_EXREG_ERAPS);
kvm_invalidate_pcid(vcpu, operand.pcid);
return kvm_skip_emulated_instruction(vcpu);
diff --git a/arch/x86/virt/hw.c b/arch/x86/virt/hw.c
index f647557d38ac..7e9091c640be 100644
--- a/arch/x86/virt/hw.c
+++ b/arch/x86/virt/hw.c
@@ -49,7 +49,20 @@ static void x86_virt_invoke_kvm_emergency_callback(void)
{
cpu_emergency_virt_cb *kvm_callback;
- kvm_callback = rcu_dereference(kvm_emergency_callback);
+ /*
+ * RCU may not be watching the crashing CPU here, so rcu_dereference()
+ * triggers a suspicious-RCU-usage splat. In principle, a concurrent
+ * KVM module unload could race with this read; see commit 2baa33a8ddd6
+ * ("KVM: x86: Leave user-return notifier registered on reboot/shutdown")
+ * which notes that nothing prevents module unload during panic/reboot.
+ *
+ * However, taking a lock here would be riskier than the current race:
+ * the system is going down via NMI shootdown, and any lock could be
+ * held by an already-stopped CPU. Use rcu_dereference_raw() to silence
+ * the lockdep splat and accept the comically small remaining race;
+ * panic context inherently cannot guarantee complete correctness.
+ */
+ kvm_callback = rcu_dereference_raw(kvm_emergency_callback);
if (kvm_callback)
kvm_callback();
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 28c2d931e75e..a24175441380 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3246,7 +3246,7 @@ queue_exit:
if (!rq)
blk_queue_exit(q);
else
- blk_mq_free_request(rq);
+ rq_list_add_head(&plug->cached_rqs, rq);
}
#ifdef CONFIG_BLK_MQ_STACKING
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 60dacec1b121..4074b5908db3 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -78,18 +78,22 @@ ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
/*******************************************************************************
*
- * FUNCTION: acpi_enable_gpe
+ * FUNCTION: acpi_enable_gpe_cond
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
+ * dispatch_type - GPE dispatch type to match
*
* RETURN: Status
*
- * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
- * hardware-enabled.
+ * DESCRIPTION: Add a reference to a GPE so long as its dispatch type matches
+ * the supplied one, or it is different from ACPI_GPE_DISPATCH_NONE
+ * if the supplied one is ACPI_GPE_DISPATCH_MASK. On the first
+ * reference, the GPE is hardware-enabled.
*
******************************************************************************/
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
+acpi_status acpi_enable_gpe_cond(acpi_handle gpe_device, u32 gpe_number,
+ u8 dispatch_type)
{
acpi_status status = AE_BAD_PARAMETER;
struct acpi_gpe_event_info *gpe_event_info;
@@ -100,14 +104,18 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/*
- * Ensure that we have a valid GPE number and that there is some way
- * of handling the GPE (handler or a GPE method). In other words, we
- * won't allow a valid GPE to be enabled if there is no way to handle it.
+ * Ensure that we have a valid GPE number and that the dispatch type of
+ * the GPE matches the supplied one (or it is not ACPI_GPE_DISPATCH_NONE
+ * if the supplied one is ACPI_GPE_DISPATCH_MASK).
*/
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (gpe_event_info) {
- if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
- ACPI_GPE_DISPATCH_NONE) {
+ if (dispatch_type == ACPI_GPE_DISPATCH_MASK)
+ dispatch_type = ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags);
+ else if (dispatch_type != ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags))
+ dispatch_type = ACPI_GPE_DISPATCH_NONE;
+
+ if (dispatch_type != ACPI_GPE_DISPATCH_NONE) {
status = acpi_ev_add_gpe_reference(gpe_event_info, TRUE);
if (ACPI_SUCCESS(status) &&
ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
@@ -128,6 +136,30 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
+ACPI_EXPORT_SYMBOL(acpi_enable_gpe_cond)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_enable_gpe
+ *
+ * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
+ * gpe_number - GPE level within the GPE block
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
+ * hardware-enabled.
+ *
+ ******************************************************************************/
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
+{
+ /*
+ * Ensure that there is some way of handling the GPE (handler or a GPE
+ * method). In other words, we won't allow a valid GPE to be enabled if
+ * there is no way to handle it.
+ */
+ return acpi_enable_gpe_cond(gpe_device, gpe_number, ACPI_GPE_DISPATCH_MASK);
+}
ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
/*******************************************************************************
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index b47301ee4c8a..d80276368b81 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -179,6 +179,7 @@ struct acpi_button {
ktime_t last_time;
bool suspended;
bool lid_state_initialized;
+ bool gpe_enabled;
};
static struct acpi_device *lid_device;
@@ -646,6 +647,21 @@ static int acpi_button_probe(struct platform_device *pdev)
status = acpi_install_notify_handler(device->handle,
ACPI_ALL_NOTIFY, handler,
button);
+ if (ACPI_SUCCESS(status) && device->wakeup.flags.valid) {
+ acpi_status st;
+
+ /*
+ * If the wakeup GPE has a handler method, enable it in
+ * case it is also used for signaling runtime events.
+ */
+ st = acpi_enable_gpe_cond(device->wakeup.gpe_device,
+ device->wakeup.gpe_number,
+ ACPI_GPE_DISPATCH_METHOD);
+ button->gpe_enabled = ACPI_SUCCESS(st);
+ if (button->gpe_enabled)
+ dev_dbg(button->dev, "Enabled ACPI GPE%02llx\n",
+ device->wakeup.gpe_number);
+ }
break;
}
if (ACPI_FAILURE(status)) {
@@ -671,6 +687,7 @@ err_remove_fs:
acpi_button_remove_fs(button);
err_free_button:
kfree(button);
+ memset(acpi_device_class(device), 0, sizeof(acpi_device_class));
return error;
}
@@ -689,7 +706,13 @@ static void acpi_button_remove(struct platform_device *pdev)
acpi_button_event);
break;
default:
- acpi_remove_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
+ if (button->gpe_enabled) {
+ dev_dbg(button->dev, "Disabling ACPI GPE%02llx\n",
+ adev->wakeup.gpe_number);
+ acpi_disable_gpe(adev->wakeup.gpe_device,
+ adev->wakeup.gpe_number);
+ }
+ acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
button->type == ACPI_BUTTON_TYPE_LID ?
acpi_lid_notify :
acpi_button_notify);
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 7f5fce93d984..830fefb342c6 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -3540,7 +3540,13 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
"firmware rome 0x%x build 0x%x",
rver_rom, rver_patch, ver_rom, ver_patch);
- if (rver_rom != ver_rom || rver_patch <= ver_patch) {
+ /* Allow rampatch when the patch version equals the firmware version.
+ * A firmware download may be aborted by a transient USB error (e.g.
+ * disconnect) after the controller updates version info but before
+ * completion.
+ * Allowing equal versions enables re-flashing during recovery.
+ */
+ if (rver_rom != ver_rom || rver_patch < ver_patch) {
bt_dev_err(hdev, "rampatch file version did not match with firmware");
err = -EINVAL;
goto done;
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index ed280399bf47..34500137df2c 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1680,8 +1680,8 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
mod_timer(&qca->tx_idle_timer, jiffies +
msecs_to_jiffies(qca->tx_idle_delay));
- /* Controller reset completion time is 50ms */
- msleep(50);
+ /* Wait for the controller to load the rampatch and NVM. */
+ msleep(100);
clear_bit(QCA_SSR_TRIGGERED, &qca->flags);
clear_bit(QCA_IBS_DISABLED, &qca->flags);
diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c
index 13a23dac477d..735b29f76438 100644
--- a/drivers/cpufreq/amd-pstate-ut.c
+++ b/drivers/cpufreq/amd-pstate-ut.c
@@ -302,12 +302,6 @@ static int amd_pstate_ut_epp(u32 index)
cpufreq_cpu_put(policy);
policy = NULL;
- /* disable dynamic EPP before running test */
- if (cpudata->dynamic_epp) {
- pr_debug("Dynamic EPP is enabled, disabling it\n");
- amd_pstate_clear_dynamic_epp(policy);
- }
-
buf = (char *)__get_free_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -327,6 +321,16 @@ static int amd_pstate_ut_epp(u32 index)
orig_policy = cpudata->policy;
cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
+ /*
+ * Disable dynamic EPP before running test. If "orig_dynamic_epp" is
+ * true, the driver will do a redundant switch at the end and there
+ * is no need for enabling it again at the end of the test.
+ */
+ if (cpudata->dynamic_epp) {
+ pr_debug("Dynamic EPP is enabled, disabling it\n");
+ amd_pstate_clear_dynamic_epp(policy);
+ }
+
for (epp = 0; epp <= U8_MAX; epp++) {
u8 val;
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 4657d96fb083..426ff78c1c03 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1284,6 +1284,7 @@
#define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f
#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002
+#define USB_DEVICE_ID_SIGMA_MICRO_USB_MOUSE 0x0034
#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD2 0x0059
#define USB_VENDOR_ID_SIGMATEL 0x066F
diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
index ff1782a75191..a72f7f748cb5 100644
--- a/drivers/hid/hid-lenovo-go-s.c
+++ b/drivers/hid/hid-lenovo-go-s.c
@@ -382,11 +382,9 @@ static int get_endpoint_address(struct hid_device *hdev)
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct usb_host_endpoint *ep;
- if (intf) {
- ep = intf->cur_altsetting->endpoint;
- if (ep)
- return ep->desc.bEndpointAddress;
- }
+ ep = intf->cur_altsetting->endpoint;
+ if (ep)
+ return ep->desc.bEndpointAddress;
return -ENODEV;
}
@@ -1461,6 +1459,9 @@ static int hid_gos_probe(struct hid_device *hdev,
{
int ret, ep;
+ if (!hid_is_usb(hdev))
+ return -EINVAL;
+
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "Parse failed\n");
diff --git a/drivers/hid/hid-lenovo-go.c b/drivers/hid/hid-lenovo-go.c
index d4d26c783356..e0c9d5ec9451 100644
--- a/drivers/hid/hid-lenovo-go.c
+++ b/drivers/hid/hid-lenovo-go.c
@@ -641,9 +641,6 @@ static int get_endpoint_address(struct hid_device *hdev)
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct usb_host_endpoint *ep;
- if (!intf)
- return -ENODEV;
-
ep = intf->cur_altsetting->endpoint;
if (!ep)
return -ENODEV;
@@ -2419,6 +2416,9 @@ static int hid_go_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret, ep;
+ if (!hid_is_usb(hdev))
+ return -EINVAL;
+
hdev->quirks |= HID_QUIRK_INPUT_PER_APP | HID_QUIRK_MULTI_INPUT;
ret = hid_parse(hdev);
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index a6b73e03c16b..c11957ae8b77 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -30,6 +30,7 @@
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/leds.h>
+#include <linux/unaligned.h>
#include <linux/workqueue.h>
#include "hid-ids.h"
@@ -793,8 +794,8 @@ static int lenovo_raw_event(struct hid_device *hdev,
*/
if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB
|| hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2)
- && size >= 3 && report->id == 0x03))
- return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(__le32 *)data));
+ && size >= 4 && report->id == 0x03))
+ return lenovo_raw_event_TP_X12_tab(hdev, get_unaligned_le32(data));
return 0;
}
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 512049963978..57d8efdd9b89 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -187,6 +187,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD), HID_QUIRK_NO_INIT_REPORTS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_USB_MOUSE), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH), HID_QUIRK_NOGET },
diff --git a/drivers/hid/hid-u2fzero.c b/drivers/hid/hid-u2fzero.c
index 744a91e6e78c..82404b6e2d25 100644
--- a/drivers/hid/hid-u2fzero.c
+++ b/drivers/hid/hid-u2fzero.c
@@ -341,29 +341,33 @@ static int u2fzero_probe(struct hid_device *hdev,
if (ret)
return ret;
- u2fzero_fill_in_urb(dev);
+ ret = u2fzero_fill_in_urb(dev);
+ if (ret)
+ goto err_hid_hw_stop;
dev->present = true;
minor = ((struct hidraw *) hdev->hidraw)->minor;
ret = u2fzero_init_led(dev, minor);
- if (ret) {
- hid_hw_stop(hdev);
- return ret;
- }
+ if (ret)
+ goto err_free_urb;
hid_info(hdev, "%s LED initialised\n", hw_configs[dev->hw_revision].name);
ret = u2fzero_init_hwrng(dev, minor);
- if (ret) {
- hid_hw_stop(hdev);
- return ret;
- }
+ if (ret)
+ goto err_free_urb;
hid_info(hdev, "%s RNG initialised\n", hw_configs[dev->hw_revision].name);
return 0;
+
+err_free_urb:
+ usb_free_urb(dev->urb);
+err_hid_hw_stop:
+ hid_hw_stop(hdev);
+ return ret;
}
static void u2fzero_remove(struct hid_device *hdev)
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index a32320b351e3..2220168bf116 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -356,6 +356,7 @@ static void wacom_feature_mapping(struct hid_device *hdev,
hid_data->inputmode = field->report->id;
hid_data->inputmode_index = usage->usage_index;
+ hid_data->inputmode_field_index = field->index;
break;
case HID_UP_DIGITIZER:
@@ -571,9 +572,14 @@ static int wacom_hid_set_device_mode(struct hid_device *hdev)
re = &(hdev->report_enum[HID_FEATURE_REPORT]);
r = re->report_id_hash[hid_data->inputmode];
- if (r) {
- r->field[0]->value[hid_data->inputmode_index] = 2;
- hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
+ if (r && hid_data->inputmode_field_index >= 0 &&
+ hid_data->inputmode_field_index < r->maxfield) {
+ struct hid_field *field = r->field[hid_data->inputmode_field_index];
+
+ if (field && hid_data->inputmode_index < field->report_count) {
+ field->value[hid_data->inputmode_index] = 2;
+ hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
+ }
}
return 0;
}
@@ -2846,6 +2852,7 @@ static int wacom_probe(struct hid_device *hdev,
return -ENODEV;
wacom_wac->hid_data.inputmode = -1;
+ wacom_wac->hid_data.inputmode_field_index = -1;
wacom_wac->mode_report = -1;
if (hid_is_usb(hdev)) {
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index d4f7d8ca1e7e..126bec6e5c0c 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -295,6 +295,7 @@ struct wacom_shared {
struct hid_data {
__s16 inputmode; /* InputMode HID feature, -1 if non-existent */
__s16 inputmode_index; /* InputMode HID feature index in the report */
+ __s16 inputmode_field_index; /* InputMode HID feature field index in the report */
bool sense_state;
bool inrange_state;
bool eraser;
diff --git a/drivers/iommu/intel/cache.c b/drivers/iommu/intel/cache.c
index be8410f0e841..fdc88817709f 100644
--- a/drivers/iommu/intel/cache.c
+++ b/drivers/iommu/intel/cache.c
@@ -254,37 +254,29 @@ void cache_tag_unassign_domain(struct dmar_domain *domain,
}
static unsigned long calculate_psi_aligned_address(unsigned long start,
- unsigned long end,
- unsigned long *_mask)
+ unsigned long last,
+ unsigned long *size_order)
{
- unsigned long pages = aligned_nrpages(start, end - start + 1);
- unsigned long aligned_pages = __roundup_pow_of_two(pages);
- unsigned long bitmask = aligned_pages - 1;
- unsigned long mask = ilog2(aligned_pages);
- unsigned long pfn = IOVA_PFN(start);
-
- /*
- * PSI masks the low order bits of the base address. If the
- * address isn't aligned to the mask, then compute a mask value
- * needed to ensure the target range is flushed.
- */
- if (unlikely(bitmask & pfn)) {
- unsigned long end_pfn = pfn + pages - 1, shared_bits;
-
+ unsigned int sz_lg2;
+
+ /* Compute a sz_lg2 that spans start and last */
+ start &= GENMASK(BITS_PER_LONG - 1, VTD_PAGE_SHIFT);
+ sz_lg2 = fls_long(start ^ last);
+ if (sz_lg2 <= 12) {
+ *size_order = 0;
+ return start;
+ }
+ if (unlikely(sz_lg2 >= BITS_PER_LONG)) {
/*
- * Since end_pfn <= pfn + bitmask, the only way bits
- * higher than bitmask can differ in pfn and end_pfn is
- * by carrying. This means after masking out bitmask,
- * high bits starting with the first set bit in
- * shared_bits are all equal in both pfn and end_pfn.
+ * MAX_AGAW_PFN_WIDTH triggers full invalidation in all
+ * downstream users.
*/
- shared_bits = ~(pfn ^ end_pfn) & ~bitmask;
- mask = shared_bits ? __ffs(shared_bits) : MAX_AGAW_PFN_WIDTH;
+ *size_order = MAX_AGAW_PFN_WIDTH;
+ return 0;
}
- *_mask = mask;
-
- return ALIGN_DOWN(start, VTD_PAGE_SIZE << mask);
+ *size_order = sz_lg2 - VTD_PAGE_SHIFT;
+ return start & GENMASK(BITS_PER_LONG - 1, sz_lg2);
}
static void qi_batch_flush_descs(struct intel_iommu *iommu, struct qi_batch *batch)
@@ -441,12 +433,7 @@ void cache_tag_flush_range(struct dmar_domain *domain, unsigned long start,
struct cache_tag *tag;
unsigned long flags;
- if (start == 0 && end == ULONG_MAX) {
- addr = 0;
- mask = MAX_AGAW_PFN_WIDTH;
- } else {
- addr = calculate_psi_aligned_address(start, end, &mask);
- }
+ addr = calculate_psi_aligned_address(start, end, &mask);
spin_lock_irqsave(&domain->cache_lock, flags);
list_for_each_entry(tag, &domain->cache_tags, node) {
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
index 40e33257d3c2..1dbef8c55007 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -777,21 +777,27 @@ struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns = {
static struct io_pgtable_cfg *cfg_cookie __initdata;
-static void __init dummy_tlb_flush_all(void *cookie)
+/*
+ * __noipa prevents gcc from turning indirect iommu_flush_ops calls
+ * into direct calls from a specialized __arm_v7s_unmap() that triggers
+ * a build time section mismatch assertion.
+ */
+static __noipa void __init dummy_tlb_flush_all(void *cookie)
{
WARN_ON(cookie != cfg_cookie);
}
-static void __init dummy_tlb_flush(unsigned long iova, size_t size,
- size_t granule, void *cookie)
+static __noipa void __init dummy_tlb_flush(unsigned long iova, size_t size,
+ size_t granule, void *cookie)
{
WARN_ON(cookie != cfg_cookie);
WARN_ON(!(size & cfg_cookie->pgsize_bitmap));
}
-static void __init dummy_tlb_add_page(struct iommu_iotlb_gather *gather,
- unsigned long iova, size_t granule,
- void *cookie)
+static __noipa void __init dummy_tlb_add_page(struct iommu_iotlb_gather *gather,
+ unsigned long iova,
+ size_t granule,
+ void *cookie)
{
dummy_tlb_flush(iova, granule, granule, cookie);
}
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 82f1461a48e9..db14357d3732 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1741,6 +1741,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
struct mana_rxq *rxq;
int err;
+ if (!apc->rxqs)
+ return;
+
for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
rxq = apc->rxqs[rxq_idx];
err = mana_fence_rq(apc, rxq);
@@ -2883,13 +2886,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
struct mana_rxq *rxq;
u32 rxq_idx;
- for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
- rxq = apc->rxqs[rxq_idx];
- if (!rxq)
- continue;
+ if (apc->rxqs) {
+
+ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+ rxq = apc->rxqs[rxq_idx];
+ if (!rxq)
+ continue;
- mana_destroy_rxq(apc, rxq, true);
- apc->rxqs[rxq_idx] = NULL;
+ mana_destroy_rxq(apc, rxq, true);
+ apc->rxqs[rxq_idx] = NULL;
+ }
}
mana_destroy_txq(apc);
@@ -3311,7 +3317,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
if (apc->port_is_up)
return -EINVAL;
- mana_chn_setxdp(apc, NULL);
+ if (apc->rxqs)
+ mana_chn_setxdp(apc, NULL);
if (gd->gdma_context->is_pf && !apc->ac->bm_hostmode)
mana_pf_deregister_filter(apc);
@@ -3329,33 +3336,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
* number of queues.
*/
- for (i = 0; i < apc->num_queues; i++) {
- txq = &apc->tx_qp[i]->txq;
- tsleep = 1000;
- while (atomic_read(&txq->pending_sends) > 0 &&
- time_before(jiffies, timeout)) {
- usleep_range(tsleep, tsleep + 1000);
- tsleep <<= 1;
- }
- if (atomic_read(&txq->pending_sends)) {
- err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
- if (err) {
- netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
- err, atomic_read(&txq->pending_sends),
- txq->gdma_txq_id);
+ if (apc->tx_qp) {
+ for (i = 0; i < apc->num_queues; i++) {
+ txq = &apc->tx_qp[i]->txq;
+ tsleep = 1000;
+ while (atomic_read(&txq->pending_sends) > 0 &&
+ time_before(jiffies, timeout)) {
+ usleep_range(tsleep, tsleep + 1000);
+ tsleep <<= 1;
+ }
+ if (atomic_read(&txq->pending_sends)) {
+ err =
+ pcie_flr(to_pci_dev(gd->gdma_context->dev));
+ if (err) {
+ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+ err,
+ atomic_read(&txq->pending_sends),
+ txq->gdma_txq_id);
+ }
+ break;
}
- break;
}
- }
- for (i = 0; i < apc->num_queues; i++) {
- txq = &apc->tx_qp[i]->txq;
- while ((skb = skb_dequeue(&txq->pending_skbs))) {
- mana_unmap_skb(skb, apc);
- dev_kfree_skb_any(skb);
+ for (i = 0; i < apc->num_queues; i++) {
+ txq = &apc->tx_qp[i]->txq;
+ while ((skb = skb_dequeue(&txq->pending_skbs))) {
+ mana_unmap_skb(skb, apc);
+ dev_kfree_skb_any(skb);
+ }
+ atomic_set(&txq->pending_sends, 0);
}
- atomic_set(&txq->pending_sends, 0);
}
+
/* We're 100% sure the queues can no longer be woken up, because
* we're sure now mana_poll_tx_cq() can't be running.
*/
@@ -3380,6 +3392,12 @@ int mana_detach(struct net_device *ndev, bool from_close)
ASSERT_RTNL();
+ /* If already detached (indicates detach succeeded but attach failed
+ * previously). Now skip mana detach and just retry mana_attach.
+ */
+ if (!from_close && !netif_device_present(ndev))
+ return 0;
+
apc->port_st_save = apc->port_is_up;
apc->port_is_up = false;
diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c
index c12f8087af9b..a753bd88cbc2 100644
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -129,6 +129,9 @@ static int mtk_pcs_config_polarity(struct mtk_pcs_lynxi *mpcs,
unsigned int val = 0;
int ret;
+ if (!fwnode)
+ return 0;
+
if (fwnode_property_read_bool(fwnode, "mediatek,pnswap"))
default_pol = PHY_POL_INVERT;
diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c
index 26e09c30d596..67d01478eb76 100644
--- a/drivers/net/wireguard/send.c
+++ b/drivers/net/wireguard/send.c
@@ -177,16 +177,6 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
trailer_len = padding_len + noise_encrypted_len(0);
plaintext_len = skb->len + padding_len;
- /* Expand data section to have room for padding and auth tag. */
- num_frags = skb_cow_data(skb, trailer_len, &trailer);
- if (unlikely(num_frags < 0 || num_frags > ARRAY_SIZE(sg)))
- return false;
-
- /* Set the padding to zeros, and make sure it and the auth tag are part
- * of the skb.
- */
- memset(skb_tail_pointer(trailer), 0, padding_len);
-
/* Expand head section to have room for our header and the network
* stack's headers.
*/
@@ -198,6 +188,16 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
skb_checksum_help(skb)))
return false;
+ /* Expand data section to have room for padding and auth tag. */
+ num_frags = skb_cow_data(skb, trailer_len, &trailer);
+ if (unlikely(num_frags < 0 || num_frags > ARRAY_SIZE(sg)))
+ return false;
+
+ /* Set the padding to zeros, and make sure it and the auth tag are part
+ * of the skb.
+ */
+ memset(skb_tail_pointer(trailer), 0, padding_len);
+
/* Only after checksumming can we safely add on the padding at the end
* and the header.
*/
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 49d1749f30bb..a4b562700151 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -726,6 +726,11 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_update_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+ acpi_enable_gpe_cond(acpi_handle gpe_device,
+ u32 gpe_number,
+ u8 dispatch_type))
+
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_enable_gpe(acpi_handle gpe_device,
u32 gpe_number))
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 56cebaff0c91..8da0a15c95f4 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -72,6 +72,10 @@
__diag_push(); \
__diag_ignore(GCC, 8, "-Wattribute-alias", \
"Type aliasing is used to sanitize syscall arguments");\
+ __diag_ignore(clang, 23, "-Wunknown-warning-option", \
+ "Avoid breaking versions without -Wattribute-alias"); \
+ __diag_ignore(clang, 23, "-Wattribute-alias", \
+ "Type aliasing is used to sanitize syscall arguments"); \
asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
__attribute__((alias(__stringify(__se_compat_sys##name)))); \
ALLOW_ERROR_INJECTION(compat_sys##name, ERRNO); \
diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
index e1123dd28486..527e4e136020 100644
--- a/include/linux/compiler-clang.h
+++ b/include/linux/compiler-clang.h
@@ -131,6 +131,12 @@
#define __diag_str(s) __diag_str1(s)
#define __diag(s) _Pragma(__diag_str(clang diagnostic s))
+#if CONFIG_CLANG_VERSION >= 230000
+#define __diag_clang_23(s) __diag(s)
+#else
+#define __diag_clang_23(s)
+#endif
+
#define __diag_clang_13(s) __diag(s)
#define __diag_ignore_all(option, comment) \
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index c16d4199bf92..836a50f5917a 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -397,6 +397,17 @@
#endif
/*
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html#index-noipa
+ */
+#if __has_attribute(noipa)
+# define __noipa __attribute__((noipa))
+#else
+# define __noipa
+#endif
+
+/*
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-weak-function-attribute
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-weak-variable-attribute
*/
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index e8fd77593b68..369966598a2c 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -711,6 +711,10 @@ struct ftrace_likely_data {
#define __diag_GCC(version, severity, string)
#endif
+#ifndef __diag_clang
+#define __diag_clang(version, severity, string)
+#endif
+
#define __diag_push() __diag(push)
#define __diag_pop() __diag(pop)
diff --git a/include/linux/hid.h b/include/linux/hid.h
index bfb9859f391e..47dc0bc89fa4 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1316,8 +1316,6 @@ void hid_quirks_exit(__u16 bus);
dev_notice(&(hid)->dev, fmt, ##__VA_ARGS__)
#define hid_warn(hid, fmt, ...) \
dev_warn(&(hid)->dev, fmt, ##__VA_ARGS__)
-#define hid_warn_ratelimited(hid, fmt, ...) \
- dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
#define hid_info(hid, fmt, ...) \
dev_info(&(hid)->dev, fmt, ##__VA_ARGS__)
#define hid_dbg(hid, fmt, ...) \
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index f5639d5ac331..4fb7291f54b6 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -247,6 +247,10 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)
__diag_push(); \
__diag_ignore(GCC, 8, "-Wattribute-alias", \
"Type aliasing is used to sanitize syscall arguments");\
+ __diag_ignore(clang, 23, "-Wunknown-warning-option", \
+ "Avoid breaking versions without -Wattribute-alias");\
+ __diag_ignore(clang, 23, "-Wattribute-alias", \
+ "Type aliasing is used to sanitize syscall arguments");\
asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
__attribute__((alias(__stringify(__se_sys##name)))); \
ALLOW_ERROR_INJECTION(sys##name, ERRNO); \
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 10d3edde6b2f..874409127e29 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -715,6 +715,7 @@ struct xfrm_mgr {
const struct xfrm_migrate *m,
int num_bundles,
const struct xfrm_kmaddress *k,
+ struct net *net,
const struct xfrm_encap_tmpl *encap);
bool (*is_alive)(const struct km_event *c);
};
@@ -1891,7 +1892,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
#ifdef CONFIG_XFRM_MIGRATE
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
- const struct xfrm_kmaddress *k,
+ const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap);
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net,
u32 if_id);
diff --git a/io_uring/tctx.c b/io_uring/tctx.c
index 6af62ca9baba..42b219b34aa8 100644
--- a/io_uring/tctx.c
+++ b/io_uring/tctx.c
@@ -139,12 +139,14 @@ static int io_tctx_install_node(struct io_ring_ctx *ctx,
int __io_uring_add_tctx_node(struct io_ring_ctx *ctx)
{
struct io_uring_task *tctx = current->io_uring;
+ bool new_tctx = false;
int ret;
if (unlikely(!tctx)) {
tctx = io_uring_alloc_task_context(current, ctx);
if (IS_ERR(tctx))
return PTR_ERR(tctx);
+ new_tctx = true;
if (data_race(ctx->int_flags) & IO_RING_F_IOWQ_LIMITS_SET) {
unsigned int limits[2];
@@ -168,13 +170,15 @@ int __io_uring_add_tctx_node(struct io_ring_ctx *ctx)
if (tctx->io_wq)
io_wq_set_exit_on_idle(tctx->io_wq, false);
- ret = io_tctx_install_node(ctx, tctx);
- if (!ret) {
+ if (new_tctx)
current->io_uring = tctx;
+
+ ret = io_tctx_install_node(ctx, tctx);
+ if (!ret)
return 0;
- }
- if (!current->io_uring) {
err_free:
+ if (new_tctx) {
+ current->io_uring = NULL;
if (tctx->io_wq) {
io_wq_exit_start(tctx->io_wq);
io_wq_put_and_exit(tctx->io_wq);
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 772ddabcbe7d..b18a682fe3da 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -1222,7 +1222,7 @@ struct self_test {
static __initconst const struct debug_obj_descr descr_type_test;
-static bool __init is_static_object(void *addr)
+static __noipa bool __init is_static_object(void *addr)
{
struct self_test *obj = addr;
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 2f03b780b40d..960a19b3e26d 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -486,6 +486,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
int ret;
local_skb = skb_clone(skb, GFP_ATOMIC);
+ if (!local_skb)
+ continue;
BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
netdev->name,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 17b46ad6a349..54eabaa46960 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -870,8 +870,10 @@ static int hci_le_big_terminate(struct hci_dev *hdev, struct hci_conn *conn)
d->big_sync_term = true;
}
- if (!d->pa_sync_term && !d->big_sync_term)
+ if (!d->pa_sync_term && !d->big_sync_term) {
+ kfree(d);
return 0;
+ }
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
terminate_big_destroy);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index c46c1236ebfa..28d7929dc593 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -539,46 +539,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)
hci_req_sync_lock(hdev);
- /* Drop queues */
- skb_queue_purge(&hdev->rx_q);
- skb_queue_purge(&hdev->cmd_q);
-
- /* Cancel these to avoid queueing non-chained pending work */
- hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
- /* Wait for
- *
- * if (!hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
- * queue_delayed_work(&hdev->{cmd,ncmd}_timer)
- *
- * inside RCU section to see the flag or complete scheduling.
- */
- synchronize_rcu();
- /* Explicitly cancel works in case scheduled after setting the flag. */
- cancel_delayed_work(&hdev->cmd_timer);
- cancel_delayed_work(&hdev->ncmd_timer);
-
- /* Avoid potential lockdep warnings from the *_flush() calls by
- * ensuring the workqueue is empty up front.
- */
- drain_workqueue(hdev->workqueue);
-
- hci_dev_lock(hdev);
- hci_inquiry_cache_flush(hdev);
- hci_conn_hash_flush(hdev);
- hci_dev_unlock(hdev);
-
- if (hdev->flush)
- hdev->flush(hdev);
-
- hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
-
- atomic_set(&hdev->cmd_cnt, 1);
- hdev->acl_cnt = 0;
- hdev->sco_cnt = 0;
- hdev->le_cnt = 0;
- hdev->iso_cnt = 0;
-
- ret = hci_reset_sync(hdev);
+ ret = hci_dev_close_sync(hdev);
+ if (!ret)
+ ret = hci_dev_open_sync(hdev);
hci_req_sync_unlock(hdev);
return ret;
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index aff8562a8690..aeccd8084cba 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -5301,6 +5301,12 @@ int hci_dev_close_sync(struct hci_dev *hdev)
bt_dev_dbg(hdev, "");
+ /* Set HCI_DRAIN_WORKQUEUE flag to prevent queuing work during
+ * reset/close. See hci_cmd_work() and handle_cmd_cnt_and_timer().
+ */
+ hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
+ synchronize_rcu();
+
if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
disable_delayed_work(&hdev->power_off);
disable_delayed_work(&hdev->ncmd_timer);
@@ -5324,6 +5330,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
cancel_delayed_work_sync(&hdev->cmd_timer);
+ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
return err;
}
@@ -5386,6 +5393,10 @@ int hci_dev_close_sync(struct hci_dev *hdev)
/* Reset device */
skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1);
+ hdev->acl_cnt = 0;
+ hdev->sco_cnt = 0;
+ hdev->le_cnt = 0;
+ hdev->iso_cnt = 0;
if (hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE) &&
!auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
set_bit(HCI_INIT, &hdev->flags);
@@ -5423,6 +5434,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
/* Clear flags */
hdev->flags &= BIT(HCI_RAW);
hci_dev_clear_volatile_flags(hdev);
+ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
memset(hdev->eir, 0, sizeof(hdev->eir));
memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
@@ -6699,6 +6711,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
DEFINE_FLEX(struct hci_cp_le_create_cis, cmd, cis, num_cis, 0x1f);
size_t aux_num_cis = 0;
struct hci_conn *conn;
+ u16 timeout = 0;
u8 cig = BT_ISO_QOS_CIG_UNSET;
/* The spec allows only one pending LE Create CIS command at a time. If
@@ -6769,6 +6782,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
set_bit(HCI_CONN_CREATE_CIS, &conn->flags);
cis->acl_handle = cpu_to_le16(conn->parent->handle);
cis->cis_handle = cpu_to_le16(conn->handle);
+ timeout = conn->conn_timeout;
aux_num_cis++;
if (aux_num_cis >= cmd->num_cis)
@@ -6788,7 +6802,7 @@ done:
return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_CREATE_CIS,
struct_size(cmd, cis, cmd->num_cis),
cmd, HCI_EVT_LE_CIS_ESTABLISHED,
- conn->conn_timeout, NULL);
+ timeout, NULL);
}
int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 976f91eeb745..70344bd3248a 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -179,12 +179,21 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
{
struct input_dev *dev = session->input;
unsigned char *keys = session->keys;
- unsigned char *udata = skb->data + 1;
- signed char *sdata = skb->data + 1;
- int i, size = skb->len - 1;
+ unsigned char *udata;
+ signed char *sdata;
+ u8 *hdr;
+ int i;
+
+ hdr = skb_pull_data(skb, 1);
+ if (!hdr)
+ return;
- switch (skb->data[0]) {
+ switch (*hdr) {
case 0x01: /* Keyboard report */
+ udata = skb_pull_data(skb, 8);
+ if (!udata)
+ break;
+
for (i = 0; i < 8; i++)
input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
@@ -213,6 +222,10 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
break;
case 0x02: /* Mouse report */
+ sdata = skb_pull_data(skb, 3);
+ if (!sdata)
+ break;
+
input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
@@ -222,7 +235,7 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_report_rel(dev, REL_X, sdata[1]);
input_report_rel(dev, REL_Y, sdata[2]);
- if (size > 3)
+ if (skb->len > 0)
input_report_rel(dev, REL_WHEEL, sdata[3]);
break;
}
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index d7af617cda45..876649556d3c 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -564,7 +564,7 @@ static void iso_recv_frame(struct iso_conn *conn, struct sk_buff *skb)
struct sock *sk;
iso_conn_lock(conn);
- sk = conn->sk;
+ sk = iso_sock_hold(conn);
iso_conn_unlock(conn);
if (!sk)
@@ -573,11 +573,15 @@ static void iso_recv_frame(struct iso_conn *conn, struct sk_buff *skb)
BT_DBG("sk %p len %d", sk, skb->len);
if (sk->sk_state != BT_CONNECTED)
- goto drop;
+ goto drop_put;
- if (!sock_queue_rcv_skb(sk, skb))
+ if (!sock_queue_rcv_skb(sk, skb)) {
+ sock_put(sk);
return;
+ }
+drop_put:
+ sock_put(sk);
drop:
kfree_skb(skb);
}
@@ -860,8 +864,8 @@ static void __iso_sock_close(struct sock *sk)
/* Must be called on unlocked socket. */
static void iso_sock_close(struct sock *sk)
{
- iso_sock_clear_timer(sk);
lock_sock(sk);
+ iso_sock_clear_timer(sk);
__iso_sock_close(sk);
release_sock(sk);
iso_sock_kill(sk);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index fdccd62ccca8..45b175399e8d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -411,8 +411,10 @@ static void l2cap_chan_timeout(struct work_struct *work)
BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
- if (!conn)
+ if (!conn) {
+ l2cap_chan_put(chan);
return;
+ }
mutex_lock(&conn->lock);
/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
@@ -5260,6 +5262,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
cmd_len -= sizeof(*rsp);
list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ struct l2cap_chan *orig;
u16 dcid;
if (chan->ident != cmd->ident ||
@@ -5281,8 +5284,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+ orig = __l2cap_get_chan_by_dcid(conn, dcid);
+
/* Check if dcid is already in use */
- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
+ if (dcid && orig) {
/* If a device receives a
* L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
* already-assigned Destination CID, then both the
@@ -5291,10 +5296,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
*/
l2cap_chan_del(chan, ECONNREFUSED);
l2cap_chan_unlock(chan);
- chan = __l2cap_get_chan_by_dcid(conn, dcid);
- l2cap_chan_lock(chan);
- l2cap_chan_del(chan, ECONNRESET);
- l2cap_chan_unlock(chan);
+
+ /* Check that the dcid channel mode is
+ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
+ * valid for that mode and shouldn't disconnect a dcid
+ * in other modes.
+ */
+ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
+ l2cap_chan_lock(orig);
+ /* Disconnect the original channel as it may be
+ * considered connected since dcid has already
+ * been assigned; don't call l2cap_chan_close
+ * directly since that could lead to
+ * l2cap_chan_del and then removing the channel
+ * from the list while we're iterating over it.
+ */
+ __set_chan_timer(orig, 0);
+ l2cap_chan_unlock(orig);
+ }
continue;
}
@@ -5458,14 +5477,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
BT_DBG("result 0x%4.4x", result);
- if (!result)
+ if (!result) {
+ list_for_each_entry(chan, &conn->chan_l, list) {
+ if (chan->ident == cmd->ident)
+ chan->ident = 0;
+ }
return 0;
+ }
list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
if (chan->ident != cmd->ident)
continue;
- l2cap_chan_hold(chan);
+ if (!l2cap_chan_hold_unless_zero(chan))
+ continue;
l2cap_chan_lock(chan);
l2cap_chan_del(chan, ECONNRESET);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b34e7da8d906..c138aa4ae266 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1499,6 +1499,10 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
* pin it (hold_unless_zero() additionally skips a chan already past
* its last reference). We then drop the sk lock before taking
* chan->lock, so sk and chan locks are never held together.
+ *
+ * Since we cannot call l2cap_chan_close() without conn->lock,
+ * schedule l2cap_chan_timeout to close the channel; it already
+ * acquires conn->lock -> chan->lock in the correct order.
*/
while ((sk = bt_accept_dequeue(parent, NULL))) {
struct l2cap_chan *chan;
@@ -1516,14 +1520,12 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
state_to_string(chan->state));
l2cap_chan_lock(chan);
- __clear_chan_timer(chan);
- l2cap_chan_close(chan, ECONNRESET);
- /* l2cap_conn_del() may already have killed this socket
- * (it sets SOCK_DEAD); skip the duplicate to avoid a
- * double sock_put()/l2cap_chan_put().
+ /* Since we cannot call l2cap_chan_close() without
+ * conn->lock, schedule its timer to trigger the close
+ * and cleanup of this channel.
*/
- if (!sock_flag(sk, SOCK_DEAD))
- l2cap_sock_kill(sk);
+ if (chan->conn)
+ __set_chan_timer(chan, 0);
l2cap_chan_unlock(chan);
l2cap_chan_put(chan);
diff --git a/net/core/filter.c b/net/core/filter.c
index 9590877b0714..80439767e0ee 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2869,7 +2869,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
psge->length = start - offset;
rsge.length -= psge->length;
- rsge.offset += start;
+ rsge.offset += start - offset;
sk_msg_iter_var_next(i);
sg_unmark_end(psge);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 78e75b1b2696..c64693fcb2d1 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -6824,6 +6824,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
skb->len -= off;
+ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
+ * while refcounting frags below.
+ */
+ skb_zcopy_downgrade_managed(skb);
+
memcpy((struct skb_shared_info *)(data + size),
skb_shinfo(skb),
offsetof(struct skb_shared_info,
@@ -6937,6 +6942,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
return -ENOMEM;
size = SKB_WITH_OVERHEAD(size);
+ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
+ * while refcounting frags below.
+ */
+ skb_zcopy_downgrade_managed(skb);
+
memcpy((struct skb_shared_info *)(data + size),
skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
if (skb_orphan_frags(skb, gfp_mask)) {
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 4366cbac3f06..6fd642d2278d 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -143,7 +143,7 @@ static void ah_output_done(void *data, int err)
}
kfree(AH_SKB_CB(skb)->tmp);
- xfrm_output_resume(skb->sk, skb, err);
+ xfrm_output_resume(skb_to_full_sk(skb), skb, err);
}
static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 6a5febbdbee4..513c8215c947 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -419,8 +419,8 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
return err;
}
- if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
- ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
+ if (ALIGN(skb->data_len + tailen, L1_CACHE_BYTES) >
+ PAGE_SIZE)
goto cow;
if (!skb_cloned(skb)) {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d7b03196725f..f5a93155e7eb 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1013,7 +1013,7 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
list_for_each(p, &idev->addr_list) {
struct inet6_ifaddr *ifa
= list_entry(p, struct inet6_ifaddr, if_list);
- if (ifp_scope > ipv6_addr_src_scope(&ifa->addr))
+ if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
break;
}
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index de1e68199a01..76f7a2de9108 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -337,7 +337,7 @@ static void ah6_output_done(void *data, int err)
ah6_restore_hdrs(top_iph, iph_ext, extlen);
kfree(AH_SKB_CB(skb)->tmp);
- xfrm_output_resume(skb->sk, skb, err);
+ xfrm_output_resume(skb_to_full_sk(skb), skb, err);
}
static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 9c06c5a1419d..57481e423e59 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -448,8 +448,8 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
return err;
}
- if (ALIGN(tailen, L1_CACHE_BYTES) > PAGE_SIZE ||
- ALIGN(skb->data_len, L1_CACHE_BYTES) > PAGE_SIZE)
+ if (ALIGN(skb->data_len + tailen, L1_CACHE_BYTES) >
+ PAGE_SIZE)
goto cow;
if (!skb_cloned(skb)) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b106e5fef9cb..636f0120d7e3 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -481,6 +481,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
const struct fib6_nh *nh = sibling->fib6_nh;
int nh_upper_bound;
+ if (!READ_ONCE(first->fib6_nsiblings))
+ break;
+
nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
if (hash > nh_upper_bound)
continue;
@@ -5902,6 +5905,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
goto nla_put_failure;
}
+ if (!READ_ONCE(rt->fib6_nsiblings))
+ break;
}
rcu_read_unlock();
diff --git a/net/key/af_key.c b/net/key/af_key.c
index a166a88d8788..9cffeef18cd9 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3564,7 +3564,7 @@ static int set_ipsecrequest(struct sk_buff *skb,
#ifdef CONFIG_NET_KEY_MIGRATE
static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
- const struct xfrm_kmaddress *k,
+ const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
int i;
@@ -3669,7 +3669,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
}
/* broadcast migrate message to sockets */
- pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
+ pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, net);
return 0;
@@ -3680,7 +3680,7 @@ err:
#else
static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
- const struct xfrm_kmaddress *k,
+ const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
return -ENOPROTOOPT;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1d2568bb6bc2..66e12fb0c646 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -9403,6 +9403,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
release_sock(sk);
current_timeo = schedule_timeout(current_timeo);
lock_sock(sk);
+ if (sk != asoc->base.sk)
+ goto do_error;
*timeo_p = current_timeo;
}
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index d4d26fba9e37..3b294164b741 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -205,6 +205,7 @@ static u16 virtio_transport_get_type(struct sock *sk)
static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
size_t payload_len,
bool zcopy,
+ struct ubuf_info *uarg,
u32 src_cid,
u32 src_port,
u32 dst_cid,
@@ -245,6 +246,12 @@ static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *
if (info->msg && payload_len > 0) {
int err;
+ /* Bind the zerocopy lifetime before filling frags so error
+ * rollback frees managed fixed-buffer pages through
+ * the uarg-aware path.
+ */
+ skb_zcopy_set(skb, uarg, NULL);
+
err = virtio_transport_fill_skb(skb, info, payload_len, zcopy);
if (err)
goto out;
@@ -364,6 +371,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
skb_len = min(max_skb_len, rest_len);
skb = virtio_transport_alloc_skb(info, skb_len, can_zcopy,
+ uarg,
src_cid, src_port,
dst_cid, dst_port);
if (!skb) {
@@ -371,8 +379,6 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
break;
}
- skb_zcopy_set(skb, uarg, NULL);
-
virtio_transport_inc_tx_pkt(vvs, skb);
ret = t_ops->send_pkt(skb, info->net);
@@ -1183,7 +1189,7 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
if (!t)
return -ENOTCONN;
- reply = virtio_transport_alloc_skb(&info, 0, false,
+ reply = virtio_transport_alloc_skb(&info, 0, false, NULL,
le64_to_cpu(hdr->dst_cid),
le32_to_cpu(hdr->dst_port),
le64_to_cpu(hdr->src_cid),
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index f65291eba1f6..e4c2cd24936d 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -797,9 +797,12 @@ static void xfrm_trans_reinject(struct work_struct *work)
spin_unlock_bh(&trans->queue_lock);
local_bh_disable();
- while ((skb = __skb_dequeue(&queue)))
- XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net,
- NULL, skb);
+ while ((skb = __skb_dequeue(&queue))) {
+ struct net *net = XFRM_TRANS_SKB_CB(skb)->net;
+
+ XFRM_TRANS_SKB_CB(skb)->finish(net, NULL, skb);
+ put_net(net);
+ }
local_bh_enable();
}
@@ -808,6 +811,7 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
struct sk_buff *))
{
struct xfrm_trans_tasklet *trans;
+ struct net *hold_net;
trans = this_cpu_ptr(&xfrm_trans_tasklet);
@@ -816,8 +820,12 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb));
+ hold_net = maybe_get_net(net);
+ if (!hold_net)
+ return -ENODEV;
+
XFRM_TRANS_SKB_CB(skb)->finish = finish;
- XFRM_TRANS_SKB_CB(skb)->net = net;
+ XFRM_TRANS_SKB_CB(skb)->net = hold_net;
spin_lock_bh(&trans->queue_lock);
__skb_queue_tail(&trans->queue, skb);
spin_unlock_bh(&trans->queue_lock);
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index 5f38dff16177..671d48f8c937 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -51,11 +51,15 @@ static int ipcomp_post_acomp(struct sk_buff *skb, int err, int hlen)
struct scatterlist *dsg;
int len, dlen;
- if (unlikely(err))
- goto out_free_req;
+ if (unlikely(!req))
+ return err;
extra = acomp_request_extra(req);
dsg = extra->sg;
+
+ if (unlikely(err))
+ goto out_free_req;
+
dlen = req->dlen;
pskb_trim_unique(skb, 0);
@@ -84,10 +88,10 @@ static int ipcomp_post_acomp(struct sk_buff *skb, int err, int hlen)
skb_shinfo(skb)->nr_frags++;
} while ((dlen -= len));
- for (; dsg; dsg = sg_next(dsg))
+out_free_req:
+ for (; dsg && sg_page(dsg); dsg = sg_next(dsg))
__free_page(sg_page(dsg));
-out_free_req:
acomp_request_free(req);
return err;
}
diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c
index 97bc979e55ba..6c6bbc040517 100644
--- a/net/xfrm/xfrm_iptfs.c
+++ b/net/xfrm/xfrm_iptfs.c
@@ -2650,7 +2650,8 @@ static void __iptfs_init_state(struct xfrm_state *x,
x->props.enc_hdr_len = sizeof(struct ip_iptfs_hdr);
/* Always keep a module reference when x->mode_data is set */
- __module_get(x->mode_cbs->owner);
+ if (x->mode_data != xtfs)
+ __module_get(x->mode_cbs->owner);
x->mode_data = xtfs;
xtfs->x = x;
@@ -2658,22 +2659,39 @@ static void __iptfs_init_state(struct xfrm_state *x,
static int iptfs_clone_state(struct xfrm_state *x, struct xfrm_state *orig)
{
+ struct skb_wseq *w_saved = NULL;
struct xfrm_iptfs_data *xtfs;
xtfs = kmemdup(orig->mode_data, sizeof(*xtfs), GFP_KERNEL);
if (!xtfs)
return -ENOMEM;
- xtfs->ra_newskb = NULL;
if (xtfs->cfg.reorder_win_size) {
- xtfs->w_saved = kzalloc_objs(*xtfs->w_saved,
- xtfs->cfg.reorder_win_size);
- if (!xtfs->w_saved) {
+ w_saved = kzalloc_objs(*w_saved, xtfs->cfg.reorder_win_size);
+ if (!w_saved) {
kfree_sensitive(xtfs);
return -ENOMEM;
}
}
+ xtfs->w_saved = w_saved;
+
+ __skb_queue_head_init(&xtfs->queue);
+ xtfs->queue_size = 0;
+ hrtimer_setup(&xtfs->iptfs_timer, iptfs_delay_timer, CLOCK_MONOTONIC,
+ IPTFS_HRTIMER_MODE);
+
+ spin_lock_init(&xtfs->drop_lock);
+ hrtimer_setup(&xtfs->drop_timer, iptfs_drop_timer, CLOCK_MONOTONIC,
+ IPTFS_HRTIMER_MODE);
+ xtfs->w_seq_set = false;
+ xtfs->w_wantseq = 0;
+ xtfs->w_savedlen = 0;
+ xtfs->ra_newskb = NULL;
+ xtfs->ra_wantseq = 0;
+ xtfs->ra_runtlen = 0;
+
+ __module_get(x->mode_cbs->owner);
x->mode_data = xtfs;
xtfs->x = x;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index c944327ce66c..dd09d2063da2 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -4276,21 +4276,21 @@ out_byidx:
return -ENOMEM;
}
-static void xfrm_policy_fini(struct net *net)
+static void __net_exit xfrm_net_pre_exit(struct net *net)
{
- struct xfrm_pol_inexact_bin *b, *t;
- unsigned int sz;
- int dir;
-
disable_work_sync(&net->xfrm.policy_hthresh.work);
-
flush_work(&net->xfrm.policy_hash_work);
#ifdef CONFIG_XFRM_SUB_POLICY
xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, false);
#endif
xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, false);
+}
- synchronize_rcu();
+static void xfrm_policy_fini(struct net *net)
+{
+ struct xfrm_pol_inexact_bin *b, *t;
+ unsigned int sz;
+ int dir;
WARN_ON(!list_empty(&net->xfrm.policy_all));
@@ -4368,6 +4368,7 @@ static void __net_exit xfrm_net_exit(struct net *net)
static struct pernet_operations __net_initdata xfrm_net_ops = {
.init = xfrm_net_init,
+ .pre_exit = xfrm_net_pre_exit,
.exit = xfrm_net_exit,
};
@@ -4703,7 +4704,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
}
/* Stage 5 - announce */
- km_migrate(sel, dir, type, m, num_migrate, k, encap);
+ km_migrate(sel, dir, type, m, num_migrate, k, net, encap);
xfrm_pol_put(pol);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 686014d39429..589c3b6e4679 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2837,7 +2837,7 @@ EXPORT_SYMBOL(km_policy_expired);
#ifdef CONFIG_XFRM_MIGRATE
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
- const struct xfrm_kmaddress *k,
+ const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
int err = -EINVAL;
@@ -2848,7 +2848,7 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
list_for_each_entry_rcu(km, &xfrm_km_list, list) {
if (km->migrate) {
ret = km->migrate(sel, dir, type, m, num_migrate, k,
- encap);
+ net, encap);
if (!ret)
err = ret;
}
@@ -3114,10 +3114,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
const struct xfrm_type *type = READ_ONCE(x->type);
struct crypto_aead *aead;
u32 blksize, net_adj = 0;
+ u32 overhead, payload_mtu;
if (x->km.state != XFRM_STATE_VALID ||
- !type || type->proto != IPPROTO_ESP)
+ !type || type->proto != IPPROTO_ESP) {
+ if (mtu <= x->props.header_len)
+ return 1;
return mtu - x->props.header_len;
+ }
aead = x->data;
blksize = ALIGN(crypto_aead_blocksize(aead), 4);
@@ -3140,8 +3144,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
break;
}
- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
- net_adj) & ~(blksize - 1)) + net_adj - 2;
+ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
+ if (mtu <= overhead)
+ return 1;
+
+ payload_mtu = mtu - overhead;
+ payload_mtu &= ~(blksize - 1);
+ if (payload_mtu <= 2)
+ return 1;
+
+ return payload_mtu + net_adj - 2;
+
}
EXPORT_SYMBOL_GPL(xfrm_state_mtu);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 38a90e5ee3d9..71a4b7278eba 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -3271,10 +3271,9 @@ out_cancel:
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
- const struct xfrm_kmaddress *k,
+ const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
- struct net *net = &init_net;
struct sk_buff *skb;
int err;
@@ -3292,7 +3291,7 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
#else
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
- const struct xfrm_kmaddress *k,
+ const struct xfrm_kmaddress *k, struct net *net,
const struct xfrm_encap_tmpl *encap)
{
return -ENOPROTOOPT;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 33fd34f0d615..746eaf93e1a5 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2974,8 +2974,10 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_str *pstr = entry->private_data;
- struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
+ struct snd_pcm_oss_setup *setup;
+
guard(mutex)(&pstr->oss.setup_mutex);
+ setup = pstr->oss.setup_list;
while (setup) {
snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
setup->task_name,
@@ -3060,6 +3062,13 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
buffer->error = -ENOMEM;
return;
}
+ template.task_name = kstrdup(task_name, GFP_KERNEL);
+ if (!template.task_name) {
+ kfree(setup);
+ buffer->error = -ENOMEM;
+ return;
+ }
+ *setup = template;
if (pstr->oss.setup_list == NULL)
pstr->oss.setup_list = setup;
else {
@@ -3067,12 +3076,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
setup1->next; setup1 = setup1->next);
setup1->next = setup;
}
- template.task_name = kstrdup(task_name, GFP_KERNEL);
- if (! template.task_name) {
- kfree(setup);
- buffer->error = -ENOMEM;
- return;
- }
+ continue;
}
*setup = template;
}
diff --git a/sound/firewire/motu/motu-register-dsp-message-parser.c b/sound/firewire/motu/motu-register-dsp-message-parser.c
index a8053e3ef065..4ec23e6880d9 100644
--- a/sound/firewire/motu/motu-register-dsp-message-parser.c
+++ b/sound/firewire/motu/motu-register-dsp-message-parser.c
@@ -386,6 +386,8 @@ unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *m
{
struct msg_parser *parser = motu->message_parser;
+ guard(spinlock_irqsave)(&parser->lock);
+
if (parser->pull_pos > parser->push_pos)
return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
else
@@ -395,13 +397,14 @@ unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *m
bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
{
struct msg_parser *parser = motu->message_parser;
- unsigned int pos = parser->pull_pos;
-
- if (pos == parser->push_pos)
- return false;
+ unsigned int pos;
guard(spinlock_irqsave)(&parser->lock);
+ if (parser->pull_pos == parser->push_pos)
+ return false;
+
+ pos = parser->pull_pos;
*event = parser->event_queue[pos];
++pos;
diff --git a/sound/hda/codecs/cirrus/cs420x.c b/sound/hda/codecs/cirrus/cs420x.c
index 42559edbba05..85c2ecf46d38 100644
--- a/sound/hda/codecs/cirrus/cs420x.c
+++ b/sound/hda/codecs/cirrus/cs420x.c
@@ -582,6 +582,7 @@ static const struct hda_quirk cs4208_mac_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
SND_PCI_QUIRK(0x106b, 0x7800, "MacPro 6,1", CS4208_MACMINI),
SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
+ SND_PCI_QUIRK(0x106b, 0x7f00, "iMac 16,1", CS4208_MBP11),
{} /* terminator */
};
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index f180d6a72021..dcbc669842e0 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -5458,7 +5458,7 @@ static const struct hda_fixup alc269_fixups[] = {
[ALC299_FIXUP_PREDATOR_SPK] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
- { 0x21, 0x90170150 }, /* use as headset mic, without its own jack detect */
+ { 0x21, 0x90170150 }, /* use as internal speaker */
{ }
}
},
@@ -7070,6 +7070,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x89da, "HP Spectre x360 14t-ea100", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8a06, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8a1f, "HP Laptop 14s-dr5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
@@ -7324,6 +7325,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
HDA_CODEC_QUIRK(0x1043, 0x1204, "ASUS Strix G16 G615JMR", ALC287_FIXUP_TXNW2781_I2C_ASUS),
SND_PCI_QUIRK(0x1043, 0x1204, "ASUS Strix G615JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
+ HDA_CODEC_QUIRK(0x1043, 0x1214, "ASUS ROG Strix G615LP", ALC287_FIXUP_TXNW2781_I2C_ASUS),
SND_PCI_QUIRK(0x1043, 0x1214, "ASUS Strix G615LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
@@ -7778,6 +7780,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3929, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x392b, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+ HDA_CODEC_QUIRK(0x17aa, 0x394c, "Lenovo Yoga Slim 7 14AGP11", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
@@ -7845,6 +7848,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK),
SND_PCI_QUIRK(0x1e50, 0x7007, "Positivo DN50E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+ SND_PCI_QUIRK(0x1e50, 0x7038, "Positivo DN140", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1ee7, 0x2081, "HONOR MRB-XXX M1020", ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO),
SND_PCI_QUIRK(0x1f4c, 0xe001, "Minisforum V3 (SE)", ALC245_FIXUP_BASS_HP_DAC),
diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda.c b/sound/hda/codecs/side-codecs/cs35l56_hda.c
index cdbc576569ef..a0ea08eb96a9 100644
--- a/sound/hda/codecs/side-codecs/cs35l56_hda.c
+++ b/sound/hda/codecs/side-codecs/cs35l56_hda.c
@@ -1025,7 +1025,7 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
u32 values[HDA_MAX_COMPONENTS];
char hid_string[8];
struct acpi_device *adev;
- const char *property, *sub;
+ const char *property;
int i, ret;
/*
@@ -1047,7 +1047,8 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
/* Initialize things that could be overwritten by a fixup */
cs35l56->index = -1;
- sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
+ const char *sub __free(kfree) = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
+
ret = cs35l56_hda_apply_platform_fixups(cs35l56, sub, &id);
if (ret)
return ret;
@@ -1095,15 +1096,16 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index,
cs35l56->num_amps, -1);
if (ret == -ENOENT) {
- cs35l56->system_name = sub;
+ cs35l56->system_name = devm_kstrdup(cs35l56->base.dev, sub, GFP_KERNEL);
} else if (ret >= 0) {
- cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
- kfree(sub);
- if (!cs35l56->system_name)
- return -ENOMEM;
+ cs35l56->system_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL,
+ "%s-spkid%d", sub, ret);
} else {
return ret;
}
+
+ if (!cs35l56->system_name)
+ return -ENOMEM;
}
cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
@@ -1254,7 +1256,6 @@ void cs35l56_hda_remove(struct device *dev)
cs_dsp_remove(&cs35l56->cs_dsp);
- kfree(cs35l56->system_name);
pm_runtime_put_noidle(cs35l56->base.dev);
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
index 069555f35f73..c2f906a3f074 100644
--- a/sound/soc/codecs/simple-mux.c
+++ b/sound/soc/codecs/simple-mux.c
@@ -51,7 +51,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
struct simple_mux *priv = snd_soc_component_get_drvdata(c);
- if (ucontrol->value.enumerated.item[0] > e->items)
+ if (ucontrol->value.enumerated.item[0] >= e->items)
return -EINVAL;
if (priv->mux == ucontrol->value.enumerated.item[0])
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index 192e2a394ff3..ea387dc74273 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -40,6 +40,7 @@ struct byt_cht_es8316_private {
struct gpio_desc *speaker_en_gpio;
struct device *codec_dev;
bool speaker_en;
+ bool mclk_enabled;
};
enum {
@@ -170,6 +171,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
},
};
+static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
+{
+ if (!priv->mclk_enabled)
+ return;
+
+ clk_disable_unprepare(priv->mclk);
+ priv->mclk_enabled = false;
+}
+
static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
{
struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
@@ -227,12 +237,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
ret = clk_prepare_enable(priv->mclk);
if (ret)
dev_err(card->dev, "unable to enable MCLK\n");
+ else
+ priv->mclk_enabled = true;
ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000,
SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(card->dev, "can't set codec clock %d\n", ret);
- return ret;
+ goto err_disable_mclk;
}
ret = snd_soc_card_jack_new_pins(card, "Headset",
@@ -241,13 +253,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
ARRAY_SIZE(byt_cht_es8316_jack_pins));
if (ret) {
dev_err(card->dev, "jack creation failed %d\n", ret);
- return ret;
+ goto err_disable_mclk;
}
snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_soc_component_set_jack(codec, &priv->jack, NULL);
return 0;
+
+err_disable_mclk:
+ byt_cht_es8316_disable_mclk(priv);
+ return ret;
+}
+
+static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
+{
+ struct snd_soc_card *card = runtime->card;
+ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+
+ byt_cht_es8316_disable_mclk(priv);
}
static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -353,6 +377,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = byt_cht_es8316_codec_fixup,
.init = byt_cht_es8316_init,
+ .exit = byt_cht_es8316_exit,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
};
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 4f8f7db6c3d3..4f09fdd40905 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -186,12 +186,10 @@ static void event_handler(uint32_t opcode, uint32_t token,
case ASM_CLIENT_EVENT_CMD_RUN_DONE:
break;
case ASM_CLIENT_EVENT_CMD_EOS_DONE:
- prtd->state = Q6ASM_STREAM_STOPPED;
break;
- case ASM_CLIENT_EVENT_DATA_WRITE_DONE: {
+ case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
snd_pcm_period_elapsed(substream);
break;
- }
case ASM_CLIENT_EVENT_DATA_READ_DONE:
snd_pcm_period_elapsed(substream);
if (prtd->state == Q6ASM_STREAM_RUNNING)
@@ -227,9 +225,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
/* rate and channels are sent to audio driver */
if (prtd->state == Q6ASM_STREAM_RUNNING) {
/* clear the previous setup if any */
- q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
- q6asm_unmap_memory_regions(substream->stream,
- prtd->audio_client);
+ ret = q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
+ if (ret < 0) {
+ dev_err(dev, "Failed to close q6asm stream %d\n", prtd->stream_id);
+ return ret;
+ }
+
+ ret = q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
+ if (ret < 0) {
+ dev_err(dev, "Failed to unmap memory regions for q6asm stream %d\n",
+ prtd->stream_id);
+ return ret;
+ }
+
q6routing_stream_close(soc_prtd->dai_link->id,
substream->stream);
prtd->state = Q6ASM_STREAM_STOPPED;
@@ -297,8 +305,6 @@ routing_err:
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
open_err:
q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
- q6asm_audio_client_free(prtd->audio_client);
- prtd->audio_client = NULL;
return ret;
}
@@ -341,7 +347,6 @@ static int q6asm_dai_trigger(struct snd_soc_component *component,
0, 0, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
- prtd->state = Q6ASM_STREAM_STOPPED;
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_EOS);
break;
@@ -378,7 +383,7 @@ static int q6asm_dai_open(struct snd_soc_component *component,
return -EINVAL;
}
- prtd = kzalloc_obj(struct q6asm_dai_rtd);
+ prtd = kzalloc_obj(*prtd);
if (prtd == NULL)
return -ENOMEM;
@@ -457,12 +462,12 @@ static int q6asm_dai_close(struct snd_soc_component *component,
struct q6asm_dai_rtd *prtd = runtime->private_data;
if (prtd->audio_client) {
- if (prtd->state)
+ if (prtd->state == Q6ASM_STREAM_RUNNING) {
q6asm_cmd(prtd->audio_client, prtd->stream_id,
CMD_CLOSE);
-
- q6asm_unmap_memory_regions(substream->stream,
+ q6asm_unmap_memory_regions(substream->stream,
prtd->audio_client);
+ }
q6asm_audio_client_free(prtd->audio_client);
prtd->audio_client = NULL;
}
@@ -555,8 +560,6 @@ static void compress_event_handler(uint32_t opcode, uint32_t token,
snd_compr_drain_notify(prtd->cstream);
prtd->notify_on_drain = false;
- } else {
- prtd->state = Q6ASM_STREAM_STOPPED;
}
break;
@@ -674,7 +677,7 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd = stream->private_data;
if (prtd->audio_client) {
- if (prtd->state) {
+ if (prtd->state == Q6ASM_STREAM_RUNNING) {
q6asm_cmd(prtd->audio_client, prtd->stream_id,
CMD_CLOSE);
if (prtd->next_track_stream_id) {
@@ -682,11 +685,11 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component,
prtd->next_track_stream_id,
CMD_CLOSE);
}
- }
- snd_dma_free_pages(&prtd->dma_buffer);
- q6asm_unmap_memory_regions(stream->direction,
+ q6asm_unmap_memory_regions(stream->direction,
prtd->audio_client);
+ }
+ snd_dma_free_pages(&prtd->dma_buffer);
q6asm_audio_client_free(prtd->audio_client);
prtd->audio_client = NULL;
}
@@ -916,7 +919,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
prtd->session_id, dir);
if (ret) {
dev_err(dev, "Stream reg failed ret:%d\n", ret);
- goto q6_err;
+ goto routing_err;
}
ret = __q6asm_dai_compr_set_codec_params(component, stream,
@@ -942,11 +945,11 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
return 0;
q6_err:
+ q6routing_stream_close(rtd->dai_link->id, dir);
+routing_err:
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
open_err:
- q6asm_audio_client_free(prtd->audio_client);
- prtd->audio_client = NULL;
return ret;
}
@@ -1014,7 +1017,6 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
0, 0, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
- prtd->state = Q6ASM_STREAM_STOPPED;
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_EOS);
break;
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 8e80a7165faf..a4fac4652201 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -2504,6 +2504,27 @@ static int scarlett2_has_config_item(
return !!private->config_set->items[config_item_num].offset;
}
+/* Return the configuration item's offset, applying any per-firmware
+ * overrides.
+ *
+ * Firmware 2417 for the 2i2 Gen 4 moved DIRECT_MONITOR_GAIN by 4
+ * bytes. Apply that shift here so that the rest of the driver can
+ * keep using the single config set. This override can be removed
+ * once the multi-config-set framework lands.
+ */
+static int scarlett2_config_item_offset(
+ struct scarlett2_data *private, int config_item_num)
+{
+ int offset = private->config_set->items[config_item_num].offset;
+
+ if (config_item_num == SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN &&
+ private->info == &s2i2_gen4_info &&
+ private->firmware_version >= 2417)
+ offset = 0x2a4;
+
+ return offset;
+}
+
/* Send a USB message to get configuration parameters; result placed in *buf */
static int scarlett2_usb_get_config(
struct usb_mixer_interface *mixer,
@@ -2513,6 +2534,7 @@ static int scarlett2_usb_get_config(
const struct scarlett2_config *config_item =
&private->config_set->items[config_item_num];
int size, err, i;
+ int item_offset;
u8 *buf_8;
u8 value;
@@ -2522,13 +2544,15 @@ static int scarlett2_usb_get_config(
if (!config_item->offset)
return -EFAULT;
+ item_offset = scarlett2_config_item_offset(private, config_item_num);
+
/* Writes to the parameter buffer are always 1 byte */
size = config_item->size ? config_item->size : 8;
/* For byte-sized parameters, retrieve directly into buf */
if (size >= 8) {
size = size / 8 * count;
- err = scarlett2_usb_get(mixer, config_item->offset, buf, size);
+ err = scarlett2_usb_get(mixer, item_offset, buf, size);
if (err < 0)
return err;
if (config_item->size == 16) {
@@ -2546,7 +2570,7 @@ static int scarlett2_usb_get_config(
}
/* For bit-sized parameters, retrieve into value */
- err = scarlett2_usb_get(mixer, config_item->offset, &value, 1);
+ err = scarlett2_usb_get(mixer, item_offset, &value, 1);
if (err < 0)
return err;
@@ -2696,7 +2720,8 @@ static int scarlett2_usb_set_config(
*/
if (config_item->size >= 8) {
size = config_item->size / 8;
- offset = config_item->offset + index * size;
+ offset = scarlett2_config_item_offset(private, config_item_num) +
+ index * size;
/* If updating a bit, retrieve the old value, set/clear the
* bit as needed, and update value
@@ -2705,7 +2730,7 @@ static int scarlett2_usb_set_config(
u8 tmp;
size = 1;
- offset = config_item->offset;
+ offset = scarlett2_config_item_offset(private, config_item_num);
err = scarlett2_usb_get(mixer, offset, &tmp, 1);
if (err < 0)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 31cbe383ae65..3d1b3523b020 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2449,6 +2449,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
QUIRK_FLAG_SET_IFACE_FIRST),
+ DEVICE_FLG(0x25aa, 0x600b, /* TAE1159 */
+ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x262a, 0x9302, /* ddHiFi TC44C */
QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index 418669927fb0..296516eecfd6 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -1523,6 +1523,23 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
#define SZ_64G (SZ_32G * 2)
#endif
+static int cxl_mock_platform_device_add(struct platform_device *pdev,
+ struct platform_device **ppdev)
+{
+ int rc;
+
+ if (ppdev)
+ *ppdev = pdev;
+ rc = platform_device_add(pdev);
+ if (rc) {
+ platform_device_put(pdev);
+ if (ppdev)
+ *ppdev = NULL;
+ }
+
+ return rc;
+}
+
static __init int cxl_rch_topo_init(void)
{
int rc, i;
@@ -1537,13 +1554,10 @@ static __init int cxl_rch_topo_init(void)
goto err_bridge;
mock_companion(adev, &pdev->dev);
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_rch[i]);
+ if (rc)
goto err_bridge;
- }
- cxl_rch[i] = pdev;
mock_pci_bus[idx].bridge = &pdev->dev;
rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
"firmware_node");
@@ -1595,13 +1609,10 @@ static __init int cxl_single_topo_init(void)
goto err_bridge;
mock_companion(adev, &pdev->dev);
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_hb_single[i]);
+ if (rc)
goto err_bridge;
- }
- cxl_hb_single[i] = pdev;
mock_pci_bus[i + NR_CXL_HOST_BRIDGES].bridge = &pdev->dev;
rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
"physical_node");
@@ -1620,12 +1631,9 @@ static __init int cxl_single_topo_init(void)
goto err_port;
pdev->dev.parent = &bridge->dev;
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_root_single[i]);
+ if (rc)
goto err_port;
- }
- cxl_root_single[i] = pdev;
}
for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) {
@@ -1638,12 +1646,9 @@ static __init int cxl_single_topo_init(void)
goto err_uport;
pdev->dev.parent = &root_port->dev;
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_swu_single[i]);
+ if (rc)
goto err_uport;
- }
- cxl_swu_single[i] = pdev;
}
for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) {
@@ -1657,12 +1662,9 @@ static __init int cxl_single_topo_init(void)
goto err_dport;
pdev->dev.parent = &uport->dev;
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_swd_single[i]);
+ if (rc)
goto err_dport;
- }
- cxl_swd_single[i] = pdev;
}
return 0;
@@ -1735,12 +1737,9 @@ static int cxl_mem_init(void)
pdev->dev.parent = &dport->dev;
set_dev_node(&pdev->dev, i % 2);
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]);
+ if (rc)
goto err_mem;
- }
- cxl_mem[i] = pdev;
}
for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
@@ -1753,12 +1752,9 @@ static int cxl_mem_init(void)
pdev->dev.parent = &dport->dev;
set_dev_node(&pdev->dev, i % 2);
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_mem_single[i]);
+ if (rc)
goto err_single;
- }
- cxl_mem_single[i] = pdev;
}
for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
@@ -1772,12 +1768,9 @@ static int cxl_mem_init(void)
pdev->dev.parent = &rch->dev;
set_dev_node(&pdev->dev, i % 2);
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_rcd[i]);
+ if (rc)
goto err_rcd;
- }
- cxl_rcd[i] = pdev;
}
return 0;
@@ -1869,13 +1862,10 @@ static __init int cxl_test_init(void)
goto err_bridge;
mock_companion(adev, &pdev->dev);
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_host_bridge[i]);
+ if (rc)
goto err_bridge;
- }
- cxl_host_bridge[i] = pdev;
mock_pci_bus[i].bridge = &pdev->dev;
rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
"physical_node");
@@ -1893,12 +1883,9 @@ static __init int cxl_test_init(void)
goto err_port;
pdev->dev.parent = &bridge->dev;
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_root_port[i]);
+ if (rc)
goto err_port;
- }
- cxl_root_port[i] = pdev;
}
BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
@@ -1911,12 +1898,9 @@ static __init int cxl_test_init(void)
goto err_uport;
pdev->dev.parent = &root_port->dev;
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_uport[i]);
+ if (rc)
goto err_uport;
- }
- cxl_switch_uport[i] = pdev;
}
for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
@@ -1929,12 +1913,9 @@ static __init int cxl_test_init(void)
goto err_dport;
pdev->dev.parent = &uport->dev;
- rc = platform_device_add(pdev);
- if (rc) {
- platform_device_put(pdev);
+ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_dport[i]);
+ if (rc)
goto err_dport;
- }
- cxl_switch_dport[i] = pdev;
}
rc = cxl_single_topo_init();
@@ -1953,9 +1934,9 @@ static __init int cxl_test_init(void)
acpi0017_mock.dev.bus = &platform_bus_type;
cxl_acpi->dev.groups = cxl_acpi_groups;
- rc = platform_device_add(cxl_acpi);
+ rc = cxl_mock_platform_device_add(cxl_acpi, NULL);
if (rc)
- goto err_root;
+ goto err_rch;
rc = cxl_mem_init();
if (rc)
diff --git a/tools/testing/selftests/kvm/access_tracking_perf_test.c b/tools/testing/selftests/kvm/access_tracking_perf_test.c
index e5bbdb5bbdc3..4415c94b2866 100644
--- a/tools/testing/selftests/kvm/access_tracking_perf_test.c
+++ b/tools/testing/selftests/kvm/access_tracking_perf_test.c
@@ -41,10 +41,10 @@
#include <inttypes.h>
#include <limits.h>
#include <pthread.h>
-#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include "kvm_syscalls.h"
#include "kvm_util.h"
#include "test_util.h"
#include "memstress.h"
diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
index 253e748c1d4a..832ef4dfb99f 100644
--- a/tools/testing/selftests/kvm/guest_memfd_test.c
+++ b/tools/testing/selftests/kvm/guest_memfd_test.c
@@ -14,10 +14,10 @@
#include <linux/bitmap.h>
#include <linux/falloc.h>
#include <linux/sizes.h>
-#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include "kvm_syscalls.h"
#include "kvm_util.h"
#include "numaif.h"
#include "test_util.h"
diff --git a/tools/testing/selftests/kvm/include/kvm_syscalls.h b/tools/testing/selftests/kvm/include/kvm_syscalls.h
index 843c9904c46f..067a4c9cf452 100644
--- a/tools/testing/selftests/kvm/include/kvm_syscalls.h
+++ b/tools/testing/selftests/kvm/include/kvm_syscalls.h
@@ -2,8 +2,18 @@
#ifndef SELFTEST_KVM_SYSCALLS_H
#define SELFTEST_KVM_SYSCALLS_H
+/*
+ * Include both the kernel and libc versions of mman.h. The kernel provides
+ * the most up-to-date flags and definitions, while libc provides the syscall
+ * wrappers tests expect.
+ */
+#include <linux/mman.h>
+
+#include <sys/mman.h>
#include <sys/syscall.h>
+#include <test_util.h>
+
#define MAP_ARGS0(m,...)
#define MAP_ARGS1(m,t,a,...) m(t,a)
#define MAP_ARGS2(m,t,a,...) m(t,a), MAP_ARGS1(m,__VA_ARGS__)
diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testing/selftests/kvm/include/test_util.h
index d9b433b834f1..a56271c237ae 100644
--- a/tools/testing/selftests/kvm/include/test_util.h
+++ b/tools/testing/selftests/kvm/include/test_util.h
@@ -19,9 +19,9 @@
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
-#include <sys/mman.h>
#include "kselftest.h"
+#include <linux/mman.h>
#include <linux/types.h>
#define msecs_to_usecs(msec) ((msec) * 1000ULL)
diff --git a/tools/testing/selftests/kvm/lib/assert.c b/tools/testing/selftests/kvm/lib/assert.c
index b49690658c60..8be0d09ecf0f 100644
--- a/tools/testing/selftests/kvm/lib/assert.c
+++ b/tools/testing/selftests/kvm/lib/assert.c
@@ -6,11 +6,14 @@
*/
#include "test_util.h"
-#include <execinfo.h>
+
#include <sys/syscall.h>
#include "kselftest.h"
+#ifdef __GLIBC__
+#include <execinfo.h>
+
/* Dumps the current stack trace to stderr. */
static void __attribute__((noinline)) test_dump_stack(void);
static void test_dump_stack(void)
@@ -57,6 +60,9 @@ static void test_dump_stack(void)
system(cmd);
#pragma GCC diagnostic pop
}
+#else
+static void test_dump_stack(void) {}
+#endif
static pid_t _gettid(void)
{
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 2a76eca7029d..e08967ef7b7b 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -5,13 +5,13 @@
* Copyright (C) 2018, Google LLC.
*/
#include "test_util.h"
+#include "kvm_syscalls.h"
#include "kvm_util.h"
#include "processor.h"
#include "ucall_common.h"
#include <assert.h>
#include <sched.h>
-#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/tools/testing/selftests/kvm/memslot_perf_test.c b/tools/testing/selftests/kvm/memslot_perf_test.c
index 3d02db371422..e977e979470f 100644
--- a/tools/testing/selftests/kvm/memslot_perf_test.c
+++ b/tools/testing/selftests/kvm/memslot_perf_test.c
@@ -15,7 +15,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
@@ -23,6 +22,7 @@
#include <linux/sizes.h>
#include <test_util.h>
+#include <kvm_syscalls.h>
#include <kvm_util.h>
#include <processor.h>
#include <ucall_common.h>
diff --git a/tools/testing/selftests/kvm/s390/shared_zeropage_test.c b/tools/testing/selftests/kvm/s390/shared_zeropage_test.c
index a9e5a01200b8..478381e6f84e 100644
--- a/tools/testing/selftests/kvm/s390/shared_zeropage_test.c
+++ b/tools/testing/selftests/kvm/s390/shared_zeropage_test.c
@@ -4,11 +4,10 @@
*
* Copyright (C) 2024, Red Hat, Inc.
*/
-#include <sys/mman.h>
-
#include <linux/fs.h>
#include "test_util.h"
+#include "kvm_syscalls.h"
#include "kvm_util.h"
#include "kselftest.h"
#include "ucall_common.h"
diff --git a/tools/testing/selftests/kvm/s390/tprot.c b/tools/testing/selftests/kvm/s390/tprot.c
index 8054d2b178f0..d86179827a18 100644
--- a/tools/testing/selftests/kvm/s390/tprot.c
+++ b/tools/testing/selftests/kvm/s390/tprot.c
@@ -4,8 +4,8 @@
*
* Copyright IBM Corp. 2021
*/
-#include <sys/mman.h>
#include "test_util.h"
+#include "kvm_syscalls.h"
#include "kvm_util.h"
#include "kselftest.h"
#include "ucall_common.h"
diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c
index 9b919a231c93..e639a9db51ee 100644
--- a/tools/testing/selftests/kvm/set_memory_region_test.c
+++ b/tools/testing/selftests/kvm/set_memory_region_test.c
@@ -8,11 +8,11 @@
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
-#include <sys/mman.h>
#include <linux/compiler.h>
#include <test_util.h>
+#include <kvm_syscalls.h>
#include <kvm_util.h>
#include <processor.h>
diff --git a/tools/testing/selftests/net/ioam6.sh b/tools/testing/selftests/net/ioam6.sh
index b2b99889942f..845c26dd01a9 100755
--- a/tools/testing/selftests/net/ioam6.sh
+++ b/tools/testing/selftests/net/ioam6.sh
@@ -273,8 +273,8 @@ setup()
ip -netns $ioam_node_beta link set ioam-veth-betaR name veth1 &>/dev/null
ip -netns $ioam_node_gamma link set ioam-veth-gamma name veth0 &>/dev/null
- ip -netns $ioam_node_alpha addr add 2001:db8:1::2/64 dev veth0 &>/dev/null
ip -netns $ioam_node_alpha addr add 2001:db8:1::50/64 dev veth0 &>/dev/null
+ ip -netns $ioam_node_alpha addr add 2001:db8:1::2/64 dev veth0 &>/dev/null
ip -netns $ioam_node_alpha link set veth0 up &>/dev/null
ip -netns $ioam_node_alpha link set lo up &>/dev/null
ip -netns $ioam_node_alpha route add 2001:db8:2::/64 \