From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, akpm@linux-foundation.org,
torvalds@linux-foundation.org, stable@vger.kernel.org
Cc: lwn@lwn.net, jslaby@suse.cz,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: Re: Linux 6.19.13
Date: Sat, 18 Apr 2026 10:51:33 +0200 [thread overview]
Message-ID: <2026041833-undefined-depravity-1236@gregkh> (raw)
In-Reply-To: <2026041833-snowbird-deviant-beb9@gregkh>
diff --git a/Makefile b/Makefile
index 05978903b747..7441da122752 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 19
-SUBLEVEL = 12
+SUBLEVEL = 13
EXTRAVERSION =
NAME = Baby Opossum Posse
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-r3.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-r3.dts
index 077c5cd2586f..4533a84fb0b9 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-r3.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-r3.dts
@@ -7,7 +7,7 @@
&a53_opp_table {
opp-1000000000 {
- opp-microvolt = <950000>;
+ opp-microvolt = <1000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
index 9e0e2d7271ef..e5f228517b6d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
@@ -844,9 +844,9 @@ buck1_reg: BUCK1 {
regulator-max-microvolt = <1300000>;
regulator-boot-on;
regulator-ramp-delay = <1250>;
- rohm,dvs-run-voltage = <880000>;
- rohm,dvs-idle-voltage = <820000>;
- rohm,dvs-suspend-voltage = <810000>;
+ rohm,dvs-run-voltage = <900000>;
+ rohm,dvs-idle-voltage = <850000>;
+ rohm,dvs-suspend-voltage = <850000>;
regulator-always-on;
};
@@ -856,8 +856,8 @@ buck2_reg: BUCK2 {
regulator-max-microvolt = <1300000>;
regulator-boot-on;
regulator-ramp-delay = <1250>;
- rohm,dvs-run-voltage = <950000>;
- rohm,dvs-idle-voltage = <850000>;
+ rohm,dvs-run-voltage = <1000000>;
+ rohm,dvs-idle-voltage = <900000>;
regulator-always-on;
};
@@ -866,14 +866,14 @@ buck3_reg: BUCK3 {
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
regulator-boot-on;
- rohm,dvs-run-voltage = <850000>;
+ rohm,dvs-run-voltage = <900000>;
};
buck4_reg: BUCK4 {
regulator-name = "buck4";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1300000>;
- rohm,dvs-run-voltage = <930000>;
+ rohm,dvs-run-voltage = <1000000>;
};
buck5_reg: BUCK5 {
@@ -1407,13 +1407,3 @@ &wdog1 {
fsl,ext-reset-output;
status = "okay";
};
-
-&a53_opp_table {
- opp-1000000000 {
- opp-microvolt = <850000>;
- };
-
- opp-1500000000 {
- opp-microvolt = <950000>;
- };
-};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts
index 7d370dac4c85..579d55daa7d0 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts
@@ -179,7 +179,7 @@ &ohci {
};
&pcie {
- reset-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio4 4 GPIO_ACTIVE_LOW>;
vpcie-supply = <®_pcie>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi b/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
index f6bc001c3832..2f4ad5da5e33 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
@@ -122,6 +122,7 @@ soc: soc@f0000000 {
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0xf0000000 0x10000000>;
+ dma-ranges = <0x0 0x0 0x0 0x40000000>;
crg: clock-reset-controller@8a22000 {
compatible = "hisilicon,hi3798cv200-crg", "syscon", "simple-mfd";
diff --git a/arch/arm64/boot/dts/renesas/r8a779g3-sparrow-hawk.dts b/arch/arm64/boot/dts/renesas/r8a779g3-sparrow-hawk.dts
index ff07d984cbf2..812b133cf29e 100644
--- a/arch/arm64/boot/dts/renesas/r8a779g3-sparrow-hawk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a779g3-sparrow-hawk.dts
@@ -118,6 +118,17 @@ memory@600000000 {
reg = <0x6 0x00000000 0x1 0x00000000>;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ tfa@40000000 {
+ reg = <0x0 0x40000000 0x0 0x8000000>;
+ no-map;
+ };
+ };
+
/* Page 27 / DSI to Display */
dp-con {
compatible = "dp-connector";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
index 753d51344954..ae937a3afa11 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
@@ -879,12 +879,6 @@ vcc5v0_host_en_pin: vcc5v0-host-en-pin {
};
};
- wifi {
- wifi_host_wake_l: wifi-host-wake-l {
- rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
wireless-bluetooth {
bt_wake_pin: bt-wake-pin {
rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
@@ -942,19 +936,7 @@ &sdio0 {
pinctrl-names = "default";
pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
sd-uhs-sdr104;
- #address-cells = <1>;
- #size-cells = <0>;
status = "okay";
-
- brcmf: wifi@1 {
- compatible = "brcm,bcm4329-fmac";
- reg = <1>;
- interrupt-parent = <&gpio0>;
- interrupts = <RK_PA3 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "host-wake";
- pinctrl-names = "default";
- pinctrl-0 = <&wifi_host_wake_l>;
- };
};
&sdhci {
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 404390bb87ea..3f11e5218e6c 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -484,7 +484,6 @@
# endif
# ifndef cpu_vmbits
# define cpu_vmbits cpu_data[0].vmbits
-# define __NEED_VMBITS_PROBE
# endif
#endif
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index fd60837ce50b..211b578af6aa 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -80,9 +80,7 @@ struct cpuinfo_mips {
int srsets; /* Shadow register sets */
int package;/* physical package number */
unsigned int globalnumber;
-#ifdef CONFIG_64BIT
int vmbits; /* Virtual memory size in bits */
-#endif
void *data; /* Additional data */
unsigned int watch_reg_count; /* Number that exist */
unsigned int watch_reg_use_cnt; /* Usable by ptrace */
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index f799c0d723da..12a095dbf9e2 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1871,6 +1871,8 @@ do { \
#define read_c0_entryhi() __read_ulong_c0_register($10, 0)
#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val)
+#define read_c0_entryhi_64() __read_64bit_c0_register($10, 0)
+#define write_c0_entryhi_64(val) __write_64bit_c0_register($10, 0, val)
#define read_c0_guestctl1() __read_32bit_c0_register($10, 4)
#define write_c0_guestctl1(val) __write_32bit_c0_register($10, 4, val)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 1e49e05ac8b1..489612ed9d49 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -210,11 +210,14 @@ static inline void set_elf_base_platform(const char *plat)
static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
{
-#ifdef __NEED_VMBITS_PROBE
- write_c0_entryhi(0x3fffffffffffe000ULL);
- back_to_back_c0_hazard();
- c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
-#endif
+ int vmbits = 31;
+
+ if (cpu_has_64bits) {
+ write_c0_entryhi_64(0x3fffffffffffe000ULL);
+ back_to_back_c0_hazard();
+ vmbits = fls64(read_c0_entryhi_64() & 0x3fffffffffffe000ULL);
+ }
+ c->vmbits = vmbits;
}
static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
diff --git a/arch/mips/kernel/cpu-r3k-probe.c b/arch/mips/kernel/cpu-r3k-probe.c
index 0c826f729f75..edcf04de0a6f 100644
--- a/arch/mips/kernel/cpu-r3k-probe.c
+++ b/arch/mips/kernel/cpu-r3k-probe.c
@@ -137,6 +137,8 @@ void cpu_probe(void)
else
cpu_set_nofpu_opts(c);
+ c->vmbits = 31;
+
reserve_exception_space(0, 0x400);
}
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 645f77e09d5b..24fe85fa169d 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/memblock.h>
+#include <linux/minmax.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/export.h>
@@ -24,6 +25,7 @@
#include <asm/hazards.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
+#include <asm/tlbdebug.h>
#include <asm/tlbex.h>
#include <asm/tlbmisc.h>
#include <asm/setup.h>
@@ -511,87 +513,259 @@ static int __init set_ntlb(char *str)
__setup("ntlb=", set_ntlb);
-/* Comparison function for EntryHi VPN fields. */
-static int r4k_vpn_cmp(const void *a, const void *b)
+/* The start bit position of VPN2 and Mask in EntryHi/PageMask registers. */
+#define VPN2_SHIFT 13
+
+/* Read full EntryHi even with CONFIG_32BIT. */
+static inline unsigned long long read_c0_entryhi_native(void)
+{
+ return cpu_has_64bits ? read_c0_entryhi_64() : read_c0_entryhi();
+}
+
+/* Write full EntryHi even with CONFIG_32BIT. */
+static inline void write_c0_entryhi_native(unsigned long long v)
{
- long v = *(unsigned long *)a - *(unsigned long *)b;
- int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0;
- return s ? (v != 0) | v >> s : v;
+ if (cpu_has_64bits)
+ write_c0_entryhi_64(v);
+ else
+ write_c0_entryhi(v);
}
+/* TLB entry state for uniquification. */
+struct tlbent {
+ unsigned long long wired:1;
+ unsigned long long global:1;
+ unsigned long long asid:10;
+ unsigned long long vpn:51;
+ unsigned long long pagesz:5;
+ unsigned long long index:14;
+};
+
/*
- * Initialise all TLB entries with unique values that do not clash with
- * what we have been handed over and what we'll be using ourselves.
+ * Comparison function for TLB entry sorting. Place wired entries first,
+ * then global entries, then order by the increasing VPN/ASID and the
+ * decreasing page size. This lets us avoid clashes with wired entries
+ * easily and get entries for larger pages out of the way first.
+ *
+ * We could group bits so as to reduce the number of comparisons, but this
+ * is seldom executed and not performance-critical, so prefer legibility.
*/
-static void __ref r4k_tlb_uniquify(void)
+static int r4k_entry_cmp(const void *a, const void *b)
{
- int tlbsize = current_cpu_data.tlbsize;
- bool use_slab = slab_is_available();
- int start = num_wired_entries();
- phys_addr_t tlb_vpn_size;
- unsigned long *tlb_vpns;
- unsigned long vpn_mask;
- int cnt, ent, idx, i;
-
- vpn_mask = GENMASK(cpu_vmbits - 1, 13);
- vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
+ struct tlbent ea = *(struct tlbent *)a, eb = *(struct tlbent *)b;
+
+ if (ea.wired > eb.wired)
+ return -1;
+ else if (ea.wired < eb.wired)
+ return 1;
+ else if (ea.global > eb.global)
+ return -1;
+ else if (ea.global < eb.global)
+ return 1;
+ else if (ea.vpn < eb.vpn)
+ return -1;
+ else if (ea.vpn > eb.vpn)
+ return 1;
+ else if (ea.asid < eb.asid)
+ return -1;
+ else if (ea.asid > eb.asid)
+ return 1;
+ else if (ea.pagesz > eb.pagesz)
+ return -1;
+ else if (ea.pagesz < eb.pagesz)
+ return 1;
+ else
+ return 0;
+}
- tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
- tlb_vpns = (use_slab ?
- kmalloc(tlb_vpn_size, GFP_ATOMIC) :
- memblock_alloc_raw(tlb_vpn_size, sizeof(*tlb_vpns)));
- if (WARN_ON(!tlb_vpns))
- return; /* Pray local_flush_tlb_all() is good enough. */
+/*
+ * Fetch all the TLB entries. Mask individual VPN values retrieved with
+ * the corresponding page mask and ignoring any 1KiB extension as we'll
+ * be using 4KiB pages for uniquification.
+ */
+static void __ref r4k_tlb_uniquify_read(struct tlbent *tlb_vpns, int tlbsize)
+{
+ int start = num_wired_entries();
+ unsigned long long vpn_mask;
+ bool global;
+ int i;
- htw_stop();
+ vpn_mask = GENMASK(current_cpu_data.vmbits - 1, VPN2_SHIFT);
+ vpn_mask |= cpu_has_64bits ? 3ULL << 62 : 1 << 31;
- for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
- unsigned long vpn;
+ for (i = 0; i < tlbsize; i++) {
+ unsigned long long entryhi, vpn, mask, asid;
+ unsigned int pagesz;
write_c0_index(i);
mtc0_tlbr_hazard();
tlb_read();
tlb_read_hazard();
- vpn = read_c0_entryhi();
- vpn &= vpn_mask & PAGE_MASK;
- tlb_vpns[cnt] = vpn;
- /* Prevent any large pages from overlapping regular ones. */
- write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK);
- mtc0_tlbw_hazard();
- tlb_write_indexed();
- tlbw_use_hazard();
+ global = !!(read_c0_entrylo0() & ENTRYLO_G);
+ entryhi = read_c0_entryhi_native();
+ mask = read_c0_pagemask();
+
+ asid = entryhi & cpu_asid_mask(¤t_cpu_data);
+ vpn = (entryhi & vpn_mask & ~mask) >> VPN2_SHIFT;
+ pagesz = ilog2((mask >> VPN2_SHIFT) + 1);
+
+ tlb_vpns[i].global = global;
+ tlb_vpns[i].asid = global ? 0 : asid;
+ tlb_vpns[i].vpn = vpn;
+ tlb_vpns[i].pagesz = pagesz;
+ tlb_vpns[i].wired = i < start;
+ tlb_vpns[i].index = i;
}
+}
- sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
+/*
+ * Write unique values to all but the wired TLB entries each, using
+ * the 4KiB page size. This size might not be supported with R6, but
+ * EHINV is mandatory for R6, so we won't ever be called in that case.
+ *
+ * A sorted table is supplied with any wired entries at the beginning,
+ * followed by any global entries, and then finally regular entries.
+ * We start at the VPN and ASID values of zero and only assign user
+ * addresses, therefore guaranteeing no clash with addresses produced
+ * by UNIQUE_ENTRYHI. We avoid any VPN values used by wired or global
+ * entries, by increasing the VPN value beyond the span of such entry.
+ *
+ * When a VPN/ASID clash is found with a regular entry we increment the
+ * ASID instead until no VPN/ASID clash has been found or the ASID space
+ * has been exhausted, in which case we increase the VPN value beyond
+ * the span of the largest clashing entry.
+ *
+ * We do not need to be concerned about FTLB or MMID configurations as
+ * those are required to implement the EHINV feature.
+ */
+static void __ref r4k_tlb_uniquify_write(struct tlbent *tlb_vpns, int tlbsize)
+{
+ unsigned long long asid, vpn, vpn_size, pagesz;
+ int widx, gidx, idx, sidx, lidx, i;
- write_c0_pagemask(PM_DEFAULT_MASK);
+ vpn_size = 1ULL << (current_cpu_data.vmbits - VPN2_SHIFT);
+ pagesz = ilog2((PM_4K >> VPN2_SHIFT) + 1);
+
+ write_c0_pagemask(PM_4K);
write_c0_entrylo0(0);
write_c0_entrylo1(0);
- idx = 0;
- ent = tlbsize;
- for (i = start; i < tlbsize; i++)
- while (1) {
- unsigned long entryhi, vpn;
+ asid = 0;
+ vpn = 0;
+ widx = 0;
+ gidx = 0;
+ for (sidx = 0; sidx < tlbsize && tlb_vpns[sidx].wired; sidx++)
+ ;
+ for (lidx = sidx; lidx < tlbsize && tlb_vpns[lidx].global; lidx++)
+ ;
+ idx = gidx = sidx + 1;
+ for (i = sidx; i < tlbsize; i++) {
+ unsigned long long entryhi, vpn_pagesz = 0;
- entryhi = UNIQUE_ENTRYHI(ent);
- vpn = entryhi & vpn_mask & PAGE_MASK;
+ while (1) {
+ if (WARN_ON(vpn >= vpn_size)) {
+ dump_tlb_all();
+ /* Pray local_flush_tlb_all() will cope. */
+ return;
+ }
- if (idx >= cnt || vpn < tlb_vpns[idx]) {
- write_c0_entryhi(entryhi);
- write_c0_index(i);
- mtc0_tlbw_hazard();
- tlb_write_indexed();
- ent++;
- break;
- } else if (vpn == tlb_vpns[idx]) {
- ent++;
- } else {
+ /* VPN must be below the next wired entry. */
+ if (widx < sidx && vpn >= tlb_vpns[widx].vpn) {
+ vpn = max(vpn,
+ (tlb_vpns[widx].vpn +
+ (1ULL << tlb_vpns[widx].pagesz)));
+ asid = 0;
+ widx++;
+ continue;
+ }
+ /* VPN must be below the next global entry. */
+ if (gidx < lidx && vpn >= tlb_vpns[gidx].vpn) {
+ vpn = max(vpn,
+ (tlb_vpns[gidx].vpn +
+ (1ULL << tlb_vpns[gidx].pagesz)));
+ asid = 0;
+ gidx++;
+ continue;
+ }
+ /* Try to find a free ASID so as to conserve VPNs. */
+ if (idx < tlbsize && vpn == tlb_vpns[idx].vpn &&
+ asid == tlb_vpns[idx].asid) {
+ unsigned long long idx_pagesz;
+
+ idx_pagesz = tlb_vpns[idx].pagesz;
+ vpn_pagesz = max(vpn_pagesz, idx_pagesz);
+ do
+ idx++;
+ while (idx < tlbsize &&
+ vpn == tlb_vpns[idx].vpn &&
+ asid == tlb_vpns[idx].asid);
+ asid++;
+ if (asid > cpu_asid_mask(¤t_cpu_data)) {
+ vpn += vpn_pagesz;
+ asid = 0;
+ vpn_pagesz = 0;
+ }
+ continue;
+ }
+ /* VPN mustn't be above the next regular entry. */
+ if (idx < tlbsize && vpn > tlb_vpns[idx].vpn) {
+ vpn = max(vpn,
+ (tlb_vpns[idx].vpn +
+ (1ULL << tlb_vpns[idx].pagesz)));
+ asid = 0;
idx++;
+ continue;
}
+ break;
}
+ entryhi = (vpn << VPN2_SHIFT) | asid;
+ write_c0_entryhi_native(entryhi);
+ write_c0_index(tlb_vpns[i].index);
+ mtc0_tlbw_hazard();
+ tlb_write_indexed();
+
+ tlb_vpns[i].asid = asid;
+ tlb_vpns[i].vpn = vpn;
+ tlb_vpns[i].pagesz = pagesz;
+
+ asid++;
+ if (asid > cpu_asid_mask(¤t_cpu_data)) {
+ vpn += 1ULL << pagesz;
+ asid = 0;
+ }
+ }
+}
+
+/*
+ * Initialise all TLB entries with unique values that do not clash with
+ * what we have been handed over and what we'll be using ourselves.
+ */
+static void __ref r4k_tlb_uniquify(void)
+{
+ int tlbsize = current_cpu_data.tlbsize;
+ bool use_slab = slab_is_available();
+ phys_addr_t tlb_vpn_size;
+ struct tlbent *tlb_vpns;
+
+ tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
+ tlb_vpns = (use_slab ?
+ kmalloc(tlb_vpn_size, GFP_ATOMIC) :
+ memblock_alloc_raw(tlb_vpn_size, sizeof(*tlb_vpns)));
+ if (WARN_ON(!tlb_vpns))
+ return; /* Pray local_flush_tlb_all() is good enough. */
+
+ htw_stop();
+
+ r4k_tlb_uniquify_read(tlb_vpns, tlbsize);
+
+ sort(tlb_vpns, tlbsize, sizeof(*tlb_vpns), r4k_entry_cmp, NULL);
+
+ r4k_tlb_uniquify_write(tlb_vpns, tlbsize);
+
+ write_c0_pagemask(PM_DEFAULT_MASK);
+
tlbw_use_hazard();
htw_start();
flush_micro_tlb();
@@ -640,7 +814,8 @@ static void r4k_tlb_configure(void)
temp_tlb_entry = current_cpu_data.tlbsize - 1;
/* From this point on the ARC firmware is dead. */
- r4k_tlb_uniquify();
+ if (!cpu_has_tlbinv)
+ r4k_tlb_uniquify();
local_flush_tlb_all();
/* Did I tell you that ARC SUCKS? */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index d1b11b4c40d2..75d2218cd032 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -669,6 +669,9 @@
#define MSR_AMD64_DC_CFG 0xc0011022
#define MSR_AMD64_TW_CFG 0xc0011023
+#define MSR_AMD64_FP_CFG 0xc0011028
+#define MSR_AMD64_FP_CFG_ZEN1_DENORM_FIX_BIT 9
+
#define MSR_AMD64_DE_CFG 0xc0011029
#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1
#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 86059f2c0fcd..b3499c84d89d 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -949,6 +949,9 @@ static void init_amd_zen1(struct cpuinfo_x86 *c)
msr_clear_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
clear_cpu_cap(c, X86_FEATURE_IRPERF);
}
+
+ pr_notice_once("AMD Zen1 FPDSS bug detected, enabling mitigation.\n");
+ msr_set_bit(MSR_AMD64_FP_CFG, MSR_AMD64_FP_CFG_ZEN1_DENORM_FIX_BIT);
}
static const struct x86_cpu_id amd_zenbleed_microcode[] = {
diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
index 7b9932f13bca..159f0becf8cc 100644
--- a/arch/x86/kernel/cpu/mce/amd.c
+++ b/arch/x86/kernel/cpu/mce/amd.c
@@ -604,6 +604,14 @@ bool amd_filter_mce(struct mce *m)
enum smca_bank_types bank_type = smca_get_bank_type(m->extcpu, m->bank);
struct cpuinfo_x86 *c = &boot_cpu_data;
+ /* Bogus hw errors on Cezanne A0. */
+ if (c->x86 == 0x19 &&
+ c->x86_model == 0x50 &&
+ c->x86_stepping == 0x0) {
+ if (!(m->status & MCI_STATUS_EN))
+ return true;
+ }
+
/* See Family 17h Models 10h-2Fh Erratum #1114. */
if (c->x86 == 0x17 &&
c->x86_model >= 0x10 && c->x86_model <= 0x2F &&
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index b37cae914987..aac2d55345a9 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -584,10 +584,10 @@ int x509_process_extension(void *context, size_t hdrlen,
* 0x04 is where keyCertSign lands in this bit string
* 0x80 is where digitalSignature lands in this bit string
*/
- if (v[0] != ASN1_BTS)
- return -EBADMSG;
if (vlen < 4)
return -EBADMSG;
+ if (v[0] != ASN1_BTS)
+ return -EBADMSG;
if (v[2] >= 8)
return -EBADMSG;
if (v[3] & 0x80)
@@ -620,10 +620,10 @@ int x509_process_extension(void *context, size_t hdrlen,
* (Expect 0xFF if the CA is TRUE)
* vlen should match the entire extension size
*/
- if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ))
- return -EBADMSG;
if (vlen < 2)
return -EBADMSG;
+ if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ))
+ return -EBADMSG;
if (v[1] != vlen - 2)
return -EBADMSG;
/* Empty SEQUENCE means CA:FALSE (default value omitted per DER) */
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 0959320fe51c..b510919e49c0 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -370,13 +370,13 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
if (!mci->layers)
goto error;
+ mci->dev.release = mci_release;
+ device_initialize(&mci->dev);
+
mci->pvt_info = kzalloc(sz_pvt, GFP_KERNEL);
if (!mci->pvt_info)
goto error;
- mci->dev.release = mci_release;
- device_initialize(&mci->dev);
-
/* setup index and various internal pointers */
mci->mc_idx = mc_num;
mci->tot_dimms = tot_dimms;
diff --git a/drivers/firmware/thead,th1520-aon.c b/drivers/firmware/thead,th1520-aon.c
index 38f812ac9920..b87d4e8235b1 100644
--- a/drivers/firmware/thead,th1520-aon.c
+++ b/drivers/firmware/thead,th1520-aon.c
@@ -170,10 +170,9 @@ int th1520_aon_power_update(struct th1520_aon_chan *aon_chan, u16 rsrc,
hdr->func = TH1520_AON_PM_FUNC_SET_RESOURCE_POWER_MODE;
hdr->size = TH1520_AON_RPC_MSG_NUM;
- RPC_SET_BE16(&msg.resource, 0, rsrc);
- RPC_SET_BE16(&msg.resource, 2,
- (power_on ? TH1520_AON_PM_PW_MODE_ON :
- TH1520_AON_PM_PW_MODE_OFF));
+ msg.resource = cpu_to_be16(rsrc);
+ msg.mode = cpu_to_be16(power_on ? TH1520_AON_PM_PW_MODE_ON :
+ TH1520_AON_PM_PW_MODE_OFF);
ret = th1520_aon_call_rpc(aon_chan, &msg);
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 5e90985a53d9..6dddeb4421ba 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2656,9 +2656,9 @@ static u32 psr2_pipe_srcsz_early_tpt_calc(struct intel_crtc_state *crtc_state,
static void clip_area_update(struct drm_rect *overlap_damage_area,
struct drm_rect *damage_area,
- struct drm_rect *pipe_src)
+ struct drm_rect *display_area)
{
- if (!drm_rect_intersect(damage_area, pipe_src))
+ if (!drm_rect_intersect(damage_area, display_area))
return;
if (overlap_damage_area->y1 == -1) {
@@ -2709,6 +2709,7 @@ static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_st
static void
intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state,
struct intel_crtc *crtc,
+ struct drm_rect *display_area,
bool *cursor_in_su_area)
{
struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
@@ -2736,7 +2737,7 @@ intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state,
continue;
clip_area_update(&crtc_state->psr2_su_area, &new_plane_state->uapi.dst,
- &crtc_state->pipe_src);
+ display_area);
*cursor_in_su_area = true;
}
}
@@ -2832,6 +2833,12 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
struct intel_plane_state *new_plane_state, *old_plane_state;
struct intel_plane *plane;
+ struct drm_rect display_area = {
+ .x1 = 0,
+ .y1 = 0,
+ .x2 = crtc_state->hw.adjusted_mode.crtc_hdisplay,
+ .y2 = crtc_state->hw.adjusted_mode.crtc_vdisplay,
+ };
bool full_update = false, su_area_changed;
int i, ret;
@@ -2845,7 +2852,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
crtc_state->psr2_su_area.x1 = 0;
crtc_state->psr2_su_area.y1 = -1;
- crtc_state->psr2_su_area.x2 = drm_rect_width(&crtc_state->pipe_src);
+ crtc_state->psr2_su_area.x2 = drm_rect_width(&display_area);
crtc_state->psr2_su_area.y2 = -1;
/*
@@ -2883,14 +2890,14 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
damaged_area.y1 = old_plane_state->uapi.dst.y1;
damaged_area.y2 = old_plane_state->uapi.dst.y2;
clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
- &crtc_state->pipe_src);
+ &display_area);
}
if (new_plane_state->uapi.visible) {
damaged_area.y1 = new_plane_state->uapi.dst.y1;
damaged_area.y2 = new_plane_state->uapi.dst.y2;
clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
- &crtc_state->pipe_src);
+ &display_area);
}
continue;
} else if (new_plane_state->uapi.alpha != old_plane_state->uapi.alpha) {
@@ -2898,7 +2905,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
damaged_area.y1 = new_plane_state->uapi.dst.y1;
damaged_area.y2 = new_plane_state->uapi.dst.y2;
clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
- &crtc_state->pipe_src);
+ &display_area);
continue;
}
@@ -2914,7 +2921,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
damaged_area.x1 += new_plane_state->uapi.dst.x1 - src.x1;
damaged_area.x2 += new_plane_state->uapi.dst.x1 - src.x1;
- clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &crtc_state->pipe_src);
+ clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &display_area);
}
/*
@@ -2949,7 +2956,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
* cursor is added into affected planes even when
* cursor is not updated by itself.
*/
- intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area);
+ intel_psr2_sel_fetch_et_alignment(state, crtc, &display_area,
+ &cursor_in_su_area);
su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state);
@@ -3025,8 +3033,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
skip_sel_fetch_set_loop:
if (full_update)
- clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src,
- &crtc_state->pipe_src);
+ clip_area_update(&crtc_state->psr2_su_area, &display_area,
+ &display_area);
psr2_man_trk_ctl_calc(crtc_state, full_update);
crtc_state->pipe_srcsz_early_tpt =
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
index b279878dca29..6424ecce8bcb 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
@@ -148,10 +148,12 @@ static void heartbeat(struct work_struct *wrk)
/* Just in case everything has gone horribly wrong, give it a kick */
intel_engine_flush_submission(engine);
- rq = engine->heartbeat.systole;
- if (rq && i915_request_completed(rq)) {
- i915_request_put(rq);
- engine->heartbeat.systole = NULL;
+ rq = xchg(&engine->heartbeat.systole, NULL);
+ if (rq) {
+ if (i915_request_completed(rq))
+ i915_request_put(rq);
+ else
+ engine->heartbeat.systole = rq;
}
if (!intel_engine_pm_get_if_awake(engine))
@@ -232,8 +234,11 @@ static void heartbeat(struct work_struct *wrk)
unlock:
mutex_unlock(&ce->timeline->mutex);
out:
- if (!engine->i915->params.enable_hangcheck || !next_heartbeat(engine))
- i915_request_put(fetch_and_zero(&engine->heartbeat.systole));
+ if (!engine->i915->params.enable_hangcheck || !next_heartbeat(engine)) {
+ rq = xchg(&engine->heartbeat.systole, NULL);
+ if (rq)
+ i915_request_put(rq);
+ }
intel_engine_pm_put(engine);
}
@@ -247,8 +252,13 @@ void intel_engine_unpark_heartbeat(struct intel_engine_cs *engine)
void intel_engine_park_heartbeat(struct intel_engine_cs *engine)
{
- if (cancel_delayed_work(&engine->heartbeat.work))
- i915_request_put(fetch_and_zero(&engine->heartbeat.systole));
+ if (cancel_delayed_work(&engine->heartbeat.work)) {
+ struct i915_request *rq;
+
+ rq = xchg(&engine->heartbeat.systole, NULL);
+ if (rq)
+ i915_request_put(rq);
+ }
}
void intel_gt_unpark_heartbeats(struct intel_gt *gt)
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 452d120a210b..a208fefd3c3b 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -401,7 +401,7 @@ static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx)
static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma_addr_t phy_addr)
{
struct imx_i2c_dma *dma;
- struct dma_slave_config dma_sconfig;
+ struct dma_slave_config dma_sconfig = {};
struct device *dev = i2c_imx->adapter.dev.parent;
int ret;
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 13336a2fd49c..0e9544a98e67 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -25,8 +25,10 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/lockdep.h>
#include <linux/miscdevice.h>
#include <linux/overflow.h>
+#include <linux/spinlock.h>
#include <linux/input/mt.h>
#include "../input-compat.h"
@@ -57,6 +59,7 @@ struct uinput_device {
struct input_dev *dev;
struct mutex mutex;
enum uinput_state state;
+ spinlock_t state_lock;
wait_queue_head_t waitq;
unsigned char ready;
unsigned char head;
@@ -75,6 +78,8 @@ static int uinput_dev_event(struct input_dev *dev,
struct uinput_device *udev = input_get_drvdata(dev);
struct timespec64 ts;
+ lockdep_assert_held(&dev->event_lock);
+
ktime_get_ts64(&ts);
udev->buff[udev->head] = (struct input_event) {
@@ -146,27 +151,26 @@ static void uinput_request_release_slot(struct uinput_device *udev,
static int uinput_request_send(struct uinput_device *udev,
struct uinput_request *request)
{
- int retval;
+ unsigned long flags;
+ int retval = 0;
- retval = mutex_lock_interruptible(&udev->mutex);
- if (retval)
- return retval;
+ spin_lock(&udev->state_lock);
if (udev->state != UIST_CREATED) {
retval = -ENODEV;
goto out;
}
- init_completion(&request->done);
-
/*
* Tell our userspace application about this new request
* by queueing an input event.
*/
+ spin_lock_irqsave(&udev->dev->event_lock, flags);
uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id);
+ spin_unlock_irqrestore(&udev->dev->event_lock, flags);
out:
- mutex_unlock(&udev->mutex);
+ spin_unlock(&udev->state_lock);
return retval;
}
@@ -175,6 +179,13 @@ static int uinput_request_submit(struct uinput_device *udev,
{
int retval;
+ /*
+ * Initialize completion before allocating the request slot.
+ * Once the slot is allocated, uinput_flush_requests() may
+ * complete it at any time, so it must be initialized first.
+ */
+ init_completion(&request->done);
+
retval = uinput_request_reserve_slot(udev, request);
if (retval)
return retval;
@@ -289,7 +300,14 @@ static void uinput_destroy_device(struct uinput_device *udev)
struct input_dev *dev = udev->dev;
enum uinput_state old_state = udev->state;
+ /*
+ * Update state under state_lock so that concurrent
+ * uinput_request_send() sees the state change before we
+ * flush pending requests and tear down the device.
+ */
+ spin_lock(&udev->state_lock);
udev->state = UIST_NEW_DEVICE;
+ spin_unlock(&udev->state_lock);
if (dev) {
name = dev->name;
@@ -366,7 +384,9 @@ static int uinput_create_device(struct uinput_device *udev)
if (error)
goto fail2;
+ spin_lock(&udev->state_lock);
udev->state = UIST_CREATED;
+ spin_unlock(&udev->state_lock);
return 0;
@@ -384,6 +404,7 @@ static int uinput_open(struct inode *inode, struct file *file)
return -ENOMEM;
mutex_init(&newdev->mutex);
+ spin_lock_init(&newdev->state_lock);
spin_lock_init(&newdev->requests_lock);
init_waitqueue_head(&newdev->requests_waitq);
init_waitqueue_head(&newdev->waitq);
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index ff49d0770506..3c9df27f9fa7 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -369,11 +369,14 @@ struct vub300_mmc_host {
static void vub300_delete(struct kref *kref)
{ /* kref callback - softirq */
struct vub300_mmc_host *vub300 = kref_to_vub300_mmc_host(kref);
+ struct mmc_host *mmc = vub300->mmc;
+
usb_free_urb(vub300->command_out_urb);
vub300->command_out_urb = NULL;
usb_free_urb(vub300->command_res_urb);
vub300->command_res_urb = NULL;
usb_put_dev(vub300->udev);
+ mmc_free_host(mmc);
/*
* and hence also frees vub300
* which is contained at the end of struct mmc
@@ -2112,7 +2115,7 @@ static int vub300_probe(struct usb_interface *interface,
goto error1;
}
/* this also allocates memory for our VUB300 mmc host device */
- mmc = devm_mmc_alloc_host(&udev->dev, sizeof(*vub300));
+ mmc = mmc_alloc_host(sizeof(*vub300), &udev->dev);
if (!mmc) {
retval = -ENOMEM;
dev_err(&udev->dev, "not enough memory for the mmc_host\n");
@@ -2269,7 +2272,7 @@ static int vub300_probe(struct usb_interface *interface,
dev_err(&vub300->udev->dev,
"Could not find two sets of bulk-in/out endpoint pairs\n");
retval = -EINVAL;
- goto error4;
+ goto err_free_host;
}
retval =
usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
@@ -2278,14 +2281,14 @@ static int vub300_probe(struct usb_interface *interface,
0x0000, 0x0000, &vub300->hc_info,
sizeof(vub300->hc_info), 1000);
if (retval < 0)
- goto error4;
+ goto err_free_host;
retval =
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
SET_ROM_WAIT_STATES,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
firmware_rom_wait_states, 0x0000, NULL, 0, 1000);
if (retval < 0)
- goto error4;
+ goto err_free_host;
dev_info(&vub300->udev->dev,
"operating_mode = %s %s %d MHz %s %d byte USB packets\n",
(mmc->caps & MMC_CAP_SDIO_IRQ) ? "IRQs" : "POLL",
@@ -2300,7 +2303,7 @@ static int vub300_probe(struct usb_interface *interface,
0x0000, 0x0000, &vub300->system_port_status,
sizeof(vub300->system_port_status), 1000);
if (retval < 0) {
- goto error4;
+ goto err_free_host;
} else if (sizeof(vub300->system_port_status) == retval) {
vub300->card_present =
(0x0001 & vub300->system_port_status.port_flags) ? 1 : 0;
@@ -2308,7 +2311,7 @@ static int vub300_probe(struct usb_interface *interface,
(0x0010 & vub300->system_port_status.port_flags) ? 1 : 0;
} else {
retval = -EINVAL;
- goto error4;
+ goto err_free_host;
}
usb_set_intfdata(interface, vub300);
INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread);
@@ -2338,6 +2341,8 @@ static int vub300_probe(struct usb_interface *interface,
return 0;
error6:
timer_delete_sync(&vub300->inactivity_timer);
+err_free_host:
+ mmc_free_host(mmc);
/*
* and hence also frees vub300
* which is contained at the end of struct mmc
@@ -2365,8 +2370,8 @@ static void vub300_disconnect(struct usb_interface *interface)
usb_set_intfdata(interface, NULL);
/* prevent more I/O from starting */
vub300->interface = NULL;
- kref_put(&vub300->kref, vub300_delete);
mmc_remove_host(mmc);
+ kref_put(&vub300->kref, vub300_delete);
pr_info("USB vub300 remote SDIO host controller[%d]"
" now disconnected", ifnum);
return;
diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c
index ca55c5fd11df..7011558e56fd 100644
--- a/drivers/net/ethernet/altera/altera_tse_main.c
+++ b/drivers/net/ethernet/altera/altera_tse_main.c
@@ -572,6 +572,7 @@ static netdev_tx_t tse_start_xmit(struct sk_buff *skb, struct net_device *dev)
DMA_TO_DEVICE);
if (dma_mapping_error(priv->device, dma_addr)) {
netdev_err(priv->dev, "%s: DMA mapping error\n", __func__);
+ dev_kfree_skb_any(skb);
ret = NETDEV_TX_OK;
goto out;
}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index cb702eac86c8..3c8ceff0e669 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -284,26 +284,21 @@ int idpf_send_mb_msg(struct idpf_adapter *adapter, u32 op,
return err;
}
-/* API for virtchnl "transaction" support ("xn" for short).
- *
- * We are reusing the completion lock to serialize the accesses to the
- * transaction state for simplicity, but it could be its own separate synchro
- * as well. For now, this API is only used from within a workqueue context;
- * raw_spin_lock() is enough.
- */
+/* API for virtchnl "transaction" support ("xn" for short). */
+
/**
* idpf_vc_xn_lock - Request exclusive access to vc transaction
* @xn: struct idpf_vc_xn* to access
*/
#define idpf_vc_xn_lock(xn) \
- raw_spin_lock(&(xn)->completed.wait.lock)
+ spin_lock(&(xn)->lock)
/**
* idpf_vc_xn_unlock - Release exclusive access to vc transaction
* @xn: struct idpf_vc_xn* to access
*/
#define idpf_vc_xn_unlock(xn) \
- raw_spin_unlock(&(xn)->completed.wait.lock)
+ spin_unlock(&(xn)->lock)
/**
* idpf_vc_xn_release_bufs - Release reference to reply buffer(s) and
@@ -335,6 +330,7 @@ static void idpf_vc_xn_init(struct idpf_vc_xn_manager *vcxn_mngr)
xn->state = IDPF_VC_XN_IDLE;
xn->idx = i;
idpf_vc_xn_release_bufs(xn);
+ spin_lock_init(&xn->lock);
init_completion(&xn->completed);
}
@@ -403,7 +399,9 @@ static void idpf_vc_xn_push_free(struct idpf_vc_xn_manager *vcxn_mngr,
struct idpf_vc_xn *xn)
{
idpf_vc_xn_release_bufs(xn);
+ spin_lock_bh(&vcxn_mngr->xn_bm_lock);
set_bit(xn->idx, vcxn_mngr->free_xn_bm);
+ spin_unlock_bh(&vcxn_mngr->xn_bm_lock);
}
/**
@@ -614,6 +612,10 @@ idpf_vc_xn_forward_reply(struct idpf_adapter *adapter,
err = -ENXIO;
goto out_unlock;
case IDPF_VC_XN_ASYNC:
+ /* Set reply_sz from the actual payload so that async_handler
+ * can evaluate the response.
+ */
+ xn->reply_sz = ctlq_msg->data_len;
err = idpf_vc_xn_forward_async(adapter, xn, ctlq_msg);
idpf_vc_xn_unlock(xn);
return err;
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
index eac3d15daa42..0a50a08eb9af 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
@@ -42,8 +42,8 @@ typedef int (*async_vc_cb) (struct idpf_adapter *, struct idpf_vc_xn *,
* struct idpf_vc_xn - Data structure representing virtchnl transactions
* @completed: virtchnl event loop uses that to signal when a reply is
* available, uses kernel completion API
- * @state: virtchnl event loop stores the data below, protected by the
- * completion's lock.
+ * @lock: protects the transaction state fields below
+ * @state: virtchnl event loop stores the data below, protected by @lock
* @reply_sz: Original size of reply, may be > reply_buf.iov_len; it will be
* truncated on its way to the receiver thread according to
* reply_buf.iov_len.
@@ -58,6 +58,7 @@ typedef int (*async_vc_cb) (struct idpf_adapter *, struct idpf_vc_xn *,
*/
struct idpf_vc_xn {
struct completion completed;
+ spinlock_t lock;
enum idpf_vc_xn_state state;
size_t reply_sz;
struct kvec reply;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index dbea37269d2c..33c6d61ef518 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2203,9 +2203,8 @@ void igb_down(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_q_vectors; i++) {
if (adapter->q_vector[i]) {
- napi_synchronize(&adapter->q_vector[i]->napi);
- igb_set_queue_napi(adapter, i, NULL);
napi_disable(&adapter->q_vector[i]->napi);
+ igb_set_queue_napi(adapter, i, NULL);
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 55b4e0cceae2..b62eddad64ab 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -2267,6 +2267,7 @@ static const struct pci_device_id mlx5_core_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x1023) }, /* ConnectX-8 */
{ PCI_VDEVICE(MELLANOX, 0x1025) }, /* ConnectX-9 */
{ PCI_VDEVICE(MELLANOX, 0x1027) }, /* ConnectX-10 */
+ { PCI_VDEVICE(MELLANOX, 0x2101) }, /* ConnectX-10 NVLink-C2C */
{ PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */
{ PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */
{ PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
index 502670718104..646f3d65274e 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
@@ -91,6 +91,8 @@ static int lan966x_fdma_rx_alloc_page_pool(struct lan966x_rx *rx)
pp_params.dma_dir = DMA_BIDIRECTIONAL;
rx->page_pool = page_pool_create(&pp_params);
+ if (unlikely(IS_ERR(rx->page_pool)))
+ return PTR_ERR(rx->page_pool);
for (int i = 0; i < lan966x->num_phys_ports; ++i) {
struct lan966x_port *port;
@@ -117,8 +119,10 @@ static int lan966x_fdma_rx_alloc(struct lan966x_rx *rx)
return PTR_ERR(rx->page_pool);
err = fdma_alloc_coherent(lan966x->dev, fdma);
- if (err)
+ if (err) {
+ page_pool_destroy(rx->page_pool);
return err;
+ }
fdma_dcbs_init(fdma, FDMA_DCB_INFO_DATAL(fdma->db_size),
FDMA_DCB_STATUS_INTR);
@@ -809,9 +813,15 @@ static int lan966x_qsys_sw_status(struct lan966x *lan966x)
static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu)
{
+ struct page *(*old_pages)[FDMA_RX_DCB_MAX_DBS];
struct page_pool *page_pool;
struct fdma fdma_rx_old;
- int err;
+ int err, i, j;
+
+ old_pages = kmemdup(lan966x->rx.page, sizeof(lan966x->rx.page),
+ GFP_KERNEL);
+ if (!old_pages)
+ return -ENOMEM;
/* Store these for later to free them */
memcpy(&fdma_rx_old, &lan966x->rx.fdma, sizeof(struct fdma));
@@ -822,7 +832,6 @@ static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu)
lan966x_fdma_stop_netdev(lan966x);
lan966x_fdma_rx_disable(&lan966x->rx);
- lan966x_fdma_rx_free_pages(&lan966x->rx);
lan966x->rx.page_order = round_up(new_mtu, PAGE_SIZE) / PAGE_SIZE - 1;
lan966x->rx.max_mtu = new_mtu;
err = lan966x_fdma_rx_alloc(&lan966x->rx);
@@ -830,6 +839,11 @@ static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu)
goto restore;
lan966x_fdma_rx_start(&lan966x->rx);
+ for (i = 0; i < fdma_rx_old.n_dcbs; ++i)
+ for (j = 0; j < fdma_rx_old.n_dbs; ++j)
+ page_pool_put_full_page(page_pool,
+ old_pages[i][j], false);
+
fdma_free_coherent(lan966x->dev, &fdma_rx_old);
page_pool_destroy(page_pool);
@@ -837,12 +851,17 @@ static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu)
lan966x_fdma_wakeup_netdev(lan966x);
napi_enable(&lan966x->napi);
- return err;
+ kfree(old_pages);
+ return 0;
restore:
lan966x->rx.page_pool = page_pool;
memcpy(&lan966x->rx.fdma, &fdma_rx_old, sizeof(struct fdma));
lan966x_fdma_rx_start(&lan966x->rx);
+ lan966x_fdma_wakeup_netdev(lan966x);
+ napi_enable(&lan966x->napi);
+
+ kfree(old_pages);
return err;
}
@@ -956,6 +975,7 @@ int lan966x_fdma_init(struct lan966x *lan966x)
err = lan966x_fdma_tx_alloc(&lan966x->tx);
if (err) {
fdma_free_coherent(lan966x->dev, &lan966x->rx.fdma);
+ page_pool_destroy(lan966x->rx.page_pool);
return err;
}
diff --git a/drivers/net/ethernet/qualcomm/qca_uart.c b/drivers/net/ethernet/qualcomm/qca_uart.c
index 37efb1ea9fcd..847a5f928e41 100644
--- a/drivers/net/ethernet/qualcomm/qca_uart.c
+++ b/drivers/net/ethernet/qualcomm/qca_uart.c
@@ -100,7 +100,7 @@ qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count)
if (!qca->rx_skb) {
netdev_dbg(netdev, "recv: out of RX resources\n");
n_stats->rx_errors++;
- return i;
+ return i + 1;
}
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
index 120a009c9992..37f9417c7c0e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
@@ -20,7 +20,7 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
unsigned int nopaged_len = skb_headlen(skb);
struct stmmac_priv *priv = tx_q->priv_data;
unsigned int entry = tx_q->cur_tx;
- unsigned int bmax, des2;
+ unsigned int bmax, buf_len, des2;
unsigned int i = 1, len;
struct dma_desc *desc;
@@ -31,17 +31,18 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
else
bmax = BUF_SIZE_2KiB;
- len = nopaged_len - bmax;
+ buf_len = min_t(unsigned int, nopaged_len, bmax);
+ len = nopaged_len - buf_len;
des2 = dma_map_single(priv->device, skb->data,
- bmax, DMA_TO_DEVICE);
+ buf_len, DMA_TO_DEVICE);
desc->des2 = cpu_to_le32(des2);
if (dma_mapping_error(priv->device, des2))
return -1;
tx_q->tx_skbuff_dma[entry].buf = des2;
- tx_q->tx_skbuff_dma[entry].len = bmax;
+ tx_q->tx_skbuff_dma[entry].len = buf_len;
/* do not close the descriptor and do not set own bit */
- stmmac_prepare_tx_desc(priv, desc, 1, bmax, csum, STMMAC_CHAIN_MODE,
+ stmmac_prepare_tx_desc(priv, desc, 1, buf_len, csum, STMMAC_CHAIN_MODE,
0, false, skb->len);
while (len != 0) {
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
index c739bf7463b3..13d0d6b68238 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
@@ -483,7 +483,7 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
& boundary)) {
*alignbits = dma_align_sizetobits(size);
- dma_free_coherent(di->dmadev, size, va, *descpa);
+ dma_free_coherent(di->dmadev, *alloced, va, *descpa);
va = dma_alloc_consistent(di, size, *alignbits,
alloced, descpa);
}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index a6d50149e0c3..1275bd8232d2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -828,7 +828,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
if (retval)
goto exit_free_device;
- rt2x00dev->anchor = devm_kmalloc(&usb_dev->dev,
+ rt2x00dev->anchor = devm_kmalloc(&usb_intf->dev,
sizeof(struct usb_anchor),
GFP_KERNEL);
if (!rt2x00dev->anchor) {
diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c
index 49c399a57175..3aacfc79fa72 100644
--- a/drivers/nfc/pn533/uart.c
+++ b/drivers/nfc/pn533/uart.c
@@ -211,6 +211,13 @@ static size_t pn532_receive_buf(struct serdev_device *serdev,
timer_delete(&dev->cmd_timeout);
for (i = 0; i < count; i++) {
+ if (!dev->recv_skb) {
+ dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN,
+ GFP_KERNEL);
+ if (!dev->recv_skb)
+ return i;
+ }
+
if (unlikely(!skb_tailroom(dev->recv_skb)))
skb_trim(dev->recv_skb, 0);
@@ -219,9 +226,7 @@ static size_t pn532_receive_buf(struct serdev_device *serdev,
continue;
pn533_recv_frame(dev->priv, dev->recv_skb, 0);
- dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN, GFP_KERNEL);
- if (!dev->recv_skb)
- return 0;
+ dev->recv_skb = NULL;
}
return i;
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
index 77ecf9f26480..c8de8688daed 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
@@ -1460,6 +1460,8 @@ static int isst_if_get_turbo_freq_info(void __user *argp)
SST_MUL_FACTOR_FREQ)
}
+ memset(turbo_freq.bucket_core_counts, 0, sizeof(turbo_freq.bucket_core_counts));
+
if (feature_rev >= 2) {
bool has_tf_info_8 = false;
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
index 1237d9570886..4c7e64db478c 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
@@ -537,6 +537,7 @@ static void set_cdie_id(int domain_id, struct tpmi_uncore_cluster_info *cluster_
#define UNCORE_VERSION_MASK GENMASK_ULL(7, 0)
#define UNCORE_LOCAL_FABRIC_CLUSTER_ID_MASK GENMASK_ULL(15, 8)
#define UNCORE_CLUSTER_OFF_MASK GENMASK_ULL(7, 0)
+#define UNCORE_AUTONOMOUS_UFS_DISABLED BIT(32)
#define UNCORE_MAX_CLUSTER_PER_DOMAIN 8
static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
@@ -598,6 +599,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
for (i = 0; i < num_resources; ++i) {
struct tpmi_uncore_power_domain_info *pd_info;
+ bool auto_ufs_enabled;
struct resource *res;
u64 cluster_offset;
u8 cluster_mask;
@@ -647,6 +649,8 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
continue;
}
+ auto_ufs_enabled = !(header & UNCORE_AUTONOMOUS_UFS_DISABLED);
+
/* Find out number of clusters in this resource */
pd_info->cluster_count = hweight8(cluster_mask);
@@ -689,7 +693,9 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
cluster_info->uncore_root = tpmi_uncore;
- if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) >= UNCORE_ELC_SUPPORTED_VERSION)
+ if ((TPMI_MINOR_VERSION(pd_info->ufs_header_ver) >=
+ UNCORE_ELC_SUPPORTED_VERSION) &&
+ auto_ufs_enabled)
cluster_info->elc_supported = true;
ret = uncore_freq_add_entry(&cluster_info->uncore_data, 0);
diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
index 8fc79f9723f0..3f5b9499d30a 100644
--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
@@ -352,9 +352,6 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
break;
- case IMX8MP_HDMIBLK_PD_HDCP:
- regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
- break;
case IMX8MP_HDMIBLK_PD_HRV:
regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
@@ -408,9 +405,6 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(7));
regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
break;
- case IMX8MP_HDMIBLK_PD_HDCP:
- regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
- break;
case IMX8MP_HDMIBLK_PD_HRV:
regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
@@ -439,7 +433,7 @@ static int imx8mp_hdmi_power_notifier(struct notifier_block *nb,
regmap_write(bc->regmap, HDMI_RTX_CLK_CTL0, 0x0);
regmap_write(bc->regmap, HDMI_RTX_CLK_CTL1, 0x0);
regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0,
- BIT(0) | BIT(1) | BIT(10));
+ BIT(0) | BIT(1) | BIT(10) | BIT(11));
regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(0));
/*
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index b77910152399..7df3a7b94a40 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -43,7 +43,8 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
return;
if (UCSI_CCI_CONNECTOR(cci)) {
- if (UCSI_CCI_CONNECTOR(cci) <= ucsi->cap.num_connectors)
+ if (!ucsi->cap.num_connectors ||
+ UCSI_CCI_CONNECTOR(cci) <= ucsi->cap.num_connectors)
ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
else
dev_err(ucsi->dev, "bogus connector number in CCI: %lu\n",
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index bc0db6593f32..f5ca544e3543 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -476,7 +476,7 @@ static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans,
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
if (key.objectid != bytenr ||
key.type != BTRFS_EXTENT_DATA_REF_KEY)
- goto fail;
+ return -ENOENT;
ref = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_extent_data_ref);
@@ -487,12 +487,11 @@ static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans,
btrfs_release_path(path);
goto again;
}
- ret = 0;
- break;
+ return 0;
}
path->slots[0]++;
}
-fail:
+
return ret;
}
@@ -2474,7 +2473,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
int i;
int action;
int level;
- int ret = 0;
+ int ret;
if (btrfs_is_testing(fs_info))
return 0;
@@ -2526,7 +2525,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
else
ret = btrfs_free_extent(trans, &ref);
if (ret)
- goto fail;
+ return ret;
} else {
/* We don't know the owning_root, leave as 0. */
ref.bytenr = btrfs_node_blockptr(buf, i);
@@ -2539,12 +2538,10 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
else
ret = btrfs_free_extent(trans, &ref);
if (ret)
- goto fail;
+ return ret;
}
}
return 0;
-fail:
- return ret;
}
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
@@ -3466,12 +3463,12 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
return 0;
if (btrfs_header_generation(buf) != trans->transid)
- goto out;
+ return 0;
if (root_id != BTRFS_TREE_LOG_OBJECTID) {
ret = check_ref_cleanup(trans, buf->start);
if (!ret)
- goto out;
+ return 0;
}
bg = btrfs_lookup_block_group(fs_info, buf->start);
@@ -3479,7 +3476,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
pin_down_extent(trans, bg, buf->start, buf->len, true);
btrfs_put_block_group(bg);
- goto out;
+ return 0;
}
/*
@@ -3503,7 +3500,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|| btrfs_is_zoned(fs_info)) {
pin_down_extent(trans, bg, buf->start, buf->len, true);
btrfs_put_block_group(bg);
- goto out;
+ return 0;
}
WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
@@ -3513,7 +3510,6 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
btrfs_put_block_group(bg);
trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len);
-out:
return 0;
}
diff --git a/include/linux/firmware/thead/thead,th1520-aon.h b/include/linux/firmware/thead/thead,th1520-aon.h
index dae132b66873..d81f5f6f5b90 100644
--- a/include/linux/firmware/thead/thead,th1520-aon.h
+++ b/include/linux/firmware/thead/thead,th1520-aon.h
@@ -97,80 +97,6 @@ struct th1520_aon_rpc_ack_common {
#define RPC_GET_SVC_FLAG_ACK_TYPE(MESG) (((MESG)->svc & 0x40) >> 6)
#define RPC_SET_SVC_FLAG_ACK_TYPE(MESG, ACK) ((MESG)->svc |= (ACK) << 6)
-#define RPC_SET_BE64(MESG, OFFSET, SET_DATA) \
- do { \
- u8 *data = (u8 *)(MESG); \
- u64 _offset = (OFFSET); \
- u64 _set_data = (SET_DATA); \
- data[_offset + 7] = _set_data & 0xFF; \
- data[_offset + 6] = (_set_data & 0xFF00) >> 8; \
- data[_offset + 5] = (_set_data & 0xFF0000) >> 16; \
- data[_offset + 4] = (_set_data & 0xFF000000) >> 24; \
- data[_offset + 3] = (_set_data & 0xFF00000000) >> 32; \
- data[_offset + 2] = (_set_data & 0xFF0000000000) >> 40; \
- data[_offset + 1] = (_set_data & 0xFF000000000000) >> 48; \
- data[_offset + 0] = (_set_data & 0xFF00000000000000) >> 56; \
- } while (0)
-
-#define RPC_SET_BE32(MESG, OFFSET, SET_DATA) \
- do { \
- u8 *data = (u8 *)(MESG); \
- u64 _offset = (OFFSET); \
- u64 _set_data = (SET_DATA); \
- data[_offset + 3] = (_set_data) & 0xFF; \
- data[_offset + 2] = (_set_data & 0xFF00) >> 8; \
- data[_offset + 1] = (_set_data & 0xFF0000) >> 16; \
- data[_offset + 0] = (_set_data & 0xFF000000) >> 24; \
- } while (0)
-
-#define RPC_SET_BE16(MESG, OFFSET, SET_DATA) \
- do { \
- u8 *data = (u8 *)(MESG); \
- u64 _offset = (OFFSET); \
- u64 _set_data = (SET_DATA); \
- data[_offset + 1] = (_set_data) & 0xFF; \
- data[_offset + 0] = (_set_data & 0xFF00) >> 8; \
- } while (0)
-
-#define RPC_SET_U8(MESG, OFFSET, SET_DATA) \
- do { \
- u8 *data = (u8 *)(MESG); \
- data[OFFSET] = (SET_DATA) & 0xFF; \
- } while (0)
-
-#define RPC_GET_BE64(MESG, OFFSET, PTR) \
- do { \
- u8 *data = (u8 *)(MESG); \
- u64 _offset = (OFFSET); \
- *(u32 *)(PTR) = \
- (data[_offset + 7] | data[_offset + 6] << 8 | \
- data[_offset + 5] << 16 | data[_offset + 4] << 24 | \
- data[_offset + 3] << 32 | data[_offset + 2] << 40 | \
- data[_offset + 1] << 48 | data[_offset + 0] << 56); \
- } while (0)
-
-#define RPC_GET_BE32(MESG, OFFSET, PTR) \
- do { \
- u8 *data = (u8 *)(MESG); \
- u64 _offset = (OFFSET); \
- *(u32 *)(PTR) = \
- (data[_offset + 3] | data[_offset + 2] << 8 | \
- data[_offset + 1] << 16 | data[_offset + 0] << 24); \
- } while (0)
-
-#define RPC_GET_BE16(MESG, OFFSET, PTR) \
- do { \
- u8 *data = (u8 *)(MESG); \
- u64 _offset = (OFFSET); \
- *(u16 *)(PTR) = (data[_offset + 1] | data[_offset + 0] << 8); \
- } while (0)
-
-#define RPC_GET_U8(MESG, OFFSET, PTR) \
- do { \
- u8 *data = (u8 *)(MESG); \
- *(u8 *)(PTR) = (data[OFFSET]); \
- } while (0)
-
/*
* Defines for SC PM Power Mode
*/
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
index 9fdaba911de6..3a66d4abb6d6 100644
--- a/include/net/netfilter/nf_conntrack_timeout.h
+++ b/include/net/netfilter/nf_conntrack_timeout.h
@@ -14,6 +14,7 @@
struct nf_ct_timeout {
__u16 l3num;
const struct nf_conntrack_l4proto *l4proto;
+ struct rcu_head rcu;
char data[];
};
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 869f97c9bf73..578b8038b211 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -185,6 +185,7 @@
EM(rxrpc_skb_put_input, "PUT input ") \
EM(rxrpc_skb_put_jumbo_subpacket, "PUT jumbo-sub") \
EM(rxrpc_skb_put_oob, "PUT oob ") \
+ EM(rxrpc_skb_put_old_response, "PUT old-resp ") \
EM(rxrpc_skb_put_purge, "PUT purge ") \
EM(rxrpc_skb_put_purge_oob, "PUT purge-oob") \
EM(rxrpc_skb_put_response, "PUT response ") \
@@ -347,7 +348,7 @@
EM(rxrpc_call_see_release, "SEE release ") \
EM(rxrpc_call_see_userid_exists, "SEE u-exists") \
EM(rxrpc_call_see_waiting_call, "SEE q-conn ") \
- E_(rxrpc_call_see_zap, "SEE zap ")
+ E_(rxrpc_call_see_still_live, "SEE !still-l")
#define rxrpc_txqueue_traces \
EM(rxrpc_txqueue_await_reply, "AWR") \
@@ -520,6 +521,7 @@
#define rxrpc_req_ack_traces \
EM(rxrpc_reqack_ack_lost, "ACK-LOST ") \
EM(rxrpc_reqack_app_stall, "APP-STALL ") \
+ EM(rxrpc_reqack_jumbo_win, "JUMBO-WIN ") \
EM(rxrpc_reqack_more_rtt, "MORE-RTT ") \
EM(rxrpc_reqack_no_srv_last, "NO-SRVLAST") \
EM(rxrpc_reqack_old_rtt, "OLD-RTT ") \
diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index dbdbc3bd7929..5c5c5f241c0d 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -558,8 +558,13 @@ int luo_session_deserialize(void)
}
scoped_guard(mutex, &session->mutex) {
- luo_file_deserialize(&session->file_set,
- &sh->ser[i].file_set_ser);
+ err = luo_file_deserialize(&session->file_set,
+ &sh->ser[i].file_set_ser);
+ }
+ if (err) {
+ pr_warn("Failed to deserialize files for session [%s] %pe\n",
+ session->name, ERR_PTR(err));
+ return err;
}
}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index a4574c1e276a..5dcf00fca5c3 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1849,8 +1849,20 @@ static void unplug_oldest_pwq(struct workqueue_struct *wq)
raw_spin_lock_irq(&pwq->pool->lock);
if (pwq->plugged) {
pwq->plugged = false;
- if (pwq_activate_first_inactive(pwq, true))
+ if (pwq_activate_first_inactive(pwq, true)) {
+ /*
+ * While plugged, queueing skips activation which
+ * includes bumping the nr_active count and adding the
+ * pwq to nna->pending_pwqs if the count can't be
+ * obtained. We need to restore both for the pwq being
+ * unplugged. The first call activates the first
+ * inactive work item and the second, if there are more
+ * inactive, puts the pwq on pending_pwqs.
+ */
+ pwq_activate_first_inactive(pwq, false);
+
kick_pool(pwq->pool);
+ }
}
raw_spin_unlock_irq(&pwq->pool->lock);
}
diff --git a/mm/damon/stat.c b/mm/damon/stat.c
index 217bde3c53b9..723bdd673c10 100644
--- a/mm/damon/stat.c
+++ b/mm/damon/stat.c
@@ -253,6 +253,12 @@ static int damon_stat_start(void)
{
int err;
+ if (damon_stat_context) {
+ if (damon_is_running(damon_stat_context))
+ return -EAGAIN;
+ damon_destroy_ctx(damon_stat_context);
+ }
+
damon_stat_context = damon_stat_build_ctx();
if (!damon_stat_context)
return -ENOMEM;
@@ -269,6 +275,7 @@ static void damon_stat_stop(void)
{
damon_stop(&damon_stat_context, 1);
damon_destroy_ctx(damon_stat_context);
+ damon_stat_context = NULL;
}
static int damon_stat_enabled_store(
diff --git a/mm/damon/sysfs.c b/mm/damon/sysfs.c
index 21d0196a3bac..fc50edf3c42c 100644
--- a/mm/damon/sysfs.c
+++ b/mm/damon/sysfs.c
@@ -1673,7 +1673,8 @@ static int damon_sysfs_turn_damon_on(struct damon_sysfs_kdamond *kdamond)
repeat_call_control->data = kdamond;
repeat_call_control->repeat = true;
repeat_call_control->dealloc_on_cancel = true;
- damon_call(ctx, repeat_call_control);
+ if (damon_call(ctx, repeat_call_control))
+ kfree(repeat_call_control);
return err;
}
diff --git a/mm/filemap.c b/mm/filemap.c
index d98e4883f13d..1192e1e6f104 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -3883,14 +3883,19 @@ vm_fault_t filemap_map_pages(struct vm_fault *vmf,
unsigned int nr_pages = 0, folio_type;
unsigned short mmap_miss = 0, mmap_miss_saved;
+ /*
+ * Recalculate end_pgoff based on file_end before calling
+ * next_uptodate_folio() to avoid races with concurrent
+ * truncation.
+ */
+ file_end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE) - 1;
+ end_pgoff = min(end_pgoff, file_end);
+
rcu_read_lock();
folio = next_uptodate_folio(&xas, mapping, end_pgoff);
if (!folio)
goto out;
- file_end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE) - 1;
- end_pgoff = min(end_pgoff, file_end);
-
/*
* Do not allow to map with PMD across i_size to preserve
* SIGBUS semantics.
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index a63ec679d861..08767e689c25 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1209,6 +1209,13 @@ int online_pages(unsigned long pfn, unsigned long nr_pages,
if (node_arg.nid >= 0)
node_set_state(nid, N_MEMORY);
+ /*
+ * Check whether we are adding normal memory to the node for the first
+ * time.
+ */
+ if (!node_state(nid, N_NORMAL_MEMORY) && zone_idx(zone) <= ZONE_NORMAL)
+ node_set_state(nid, N_NORMAL_MEMORY);
+
if (need_zonelists_rebuild)
build_all_zonelists(NULL);
@@ -1908,6 +1915,8 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages,
unsigned long flags;
char *reason;
int ret;
+ unsigned long normal_pages = 0;
+ enum zone_type zt;
/*
* {on,off}lining is constrained to full memory sections (or more
@@ -2055,6 +2064,17 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages,
/* reinitialise watermarks and update pcp limits */
init_per_zone_wmark_min();
+ /*
+ * Check whether this operation removes the last normal memory from
+ * the node. We do this before clearing N_MEMORY to avoid the possible
+ * transient "!N_MEMORY && N_NORMAL_MEMORY" state.
+ */
+ if (zone_idx(zone) <= ZONE_NORMAL) {
+ for (zt = 0; zt <= ZONE_NORMAL; zt++)
+ normal_pages += pgdat->node_zones[zt].present_pages;
+ if (!normal_pages)
+ node_clear_state(node, N_NORMAL_MEMORY);
+ }
/*
* Make sure to mark the node as memory-less before rebuilding the zone
* list. Otherwise this node would still appear in the fallback lists.
diff --git a/mm/vma.c b/mm/vma.c
index 7a908a964d18..690e68931868 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -2774,6 +2774,13 @@ static unsigned long __mmap_region(struct file *file, unsigned long addr,
if (map.charged)
vm_unacct_memory(map.charged);
abort_munmap:
+ /*
+ * This indicates that .mmap_prepare has set a new file, differing from
+ * desc->vm_file. But since we're aborting the operation, only the
+ * original file will be cleaned up. Ensure we clean up both.
+ */
+ if (map.file_doesnt_need_get)
+ fput(map.file);
vms_abort_munmap_vmas(&map.vms, &map.mas_detach);
return error;
}
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 3dc791c15bf7..648fa97ea913 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -2130,6 +2130,7 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid,
struct batadv_bla_claim *claim)
{
const u8 *primary_addr = primary_if->net_dev->dev_addr;
+ struct batadv_bla_backbone_gw *backbone_gw;
u16 backbone_crc;
bool is_own;
void *hdr;
@@ -2145,32 +2146,35 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid,
genl_dump_check_consistent(cb, hdr);
- is_own = batadv_compare_eth(claim->backbone_gw->orig,
- primary_addr);
+ backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
+
+ is_own = batadv_compare_eth(backbone_gw->orig, primary_addr);
- spin_lock_bh(&claim->backbone_gw->crc_lock);
- backbone_crc = claim->backbone_gw->crc;
- spin_unlock_bh(&claim->backbone_gw->crc_lock);
+ spin_lock_bh(&backbone_gw->crc_lock);
+ backbone_crc = backbone_gw->crc;
+ spin_unlock_bh(&backbone_gw->crc_lock);
if (is_own)
if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {
genlmsg_cancel(msg, hdr);
- goto out;
+ goto put_backbone_gw;
}
if (nla_put(msg, BATADV_ATTR_BLA_ADDRESS, ETH_ALEN, claim->addr) ||
nla_put_u16(msg, BATADV_ATTR_BLA_VID, claim->vid) ||
nla_put(msg, BATADV_ATTR_BLA_BACKBONE, ETH_ALEN,
- claim->backbone_gw->orig) ||
+ backbone_gw->orig) ||
nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
backbone_crc)) {
genlmsg_cancel(msg, hdr);
- goto out;
+ goto put_backbone_gw;
}
genlmsg_end(msg, hdr);
ret = 0;
+put_backbone_gw:
+ batadv_backbone_gw_put(backbone_gw);
out:
return ret;
}
@@ -2448,6 +2452,7 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
bool batadv_bla_check_claim(struct batadv_priv *bat_priv,
u8 *addr, unsigned short vid)
{
+ struct batadv_bla_backbone_gw *backbone_gw;
struct batadv_bla_claim search_claim;
struct batadv_bla_claim *claim = NULL;
struct batadv_hard_iface *primary_if = NULL;
@@ -2470,9 +2475,13 @@ bool batadv_bla_check_claim(struct batadv_priv *bat_priv,
* return false.
*/
if (claim) {
- if (!batadv_compare_eth(claim->backbone_gw->orig,
+ backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
+
+ if (!batadv_compare_eth(backbone_gw->orig,
primary_if->net_dev->dev_addr))
ret = false;
+
+ batadv_backbone_gw_put(backbone_gw);
batadv_claim_put(claim);
}
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 6e95e883c2bf..05cddcf994f6 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -798,8 +798,8 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
{
u16 num_vlan = 0;
u16 num_entries = 0;
- u16 change_offset;
- u16 tvlv_len;
+ u16 tvlv_len = 0;
+ unsigned int change_offset;
struct batadv_tvlv_tt_vlan_data *tt_vlan;
struct batadv_orig_node_vlan *vlan;
u8 *tt_change_ptr;
@@ -816,6 +816,11 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
if (*tt_len < 0)
*tt_len = batadv_tt_len(num_entries);
+ if (change_offset > U16_MAX || *tt_len > U16_MAX - change_offset) {
+ *tt_len = 0;
+ goto out;
+ }
+
tvlv_len = *tt_len;
tvlv_len += change_offset;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 79dc6d6900cd..a95dc0638836 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1062,10 +1062,7 @@ static int skb_pp_frag_ref(struct sk_buff *skb)
static void skb_kfree_head(void *head, unsigned int end_offset)
{
- if (end_offset == SKB_SMALL_HEAD_HEADROOM)
- kmem_cache_free(net_hotdata.skb_small_head_cache, head);
- else
- kfree(head);
+ kfree(head);
}
static void skb_free_head(struct sk_buff *skb)
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index f28cfd88eaf5..c2eac844bcdb 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -50,6 +50,7 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
{
struct xfrm_offload *xo = xfrm_offload(skb);
struct iphdr *iph = ip_hdr(skb);
+ struct net_device *dev = skb->dev;
iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
@@ -73,8 +74,10 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
}
NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
- dev_net(skb->dev), NULL, skb, skb->dev, NULL,
+ dev_net(dev), NULL, skb, dev, NULL,
xfrm4_rcv_encap_finish);
+ if (async)
+ dev_put(dev);
return 0;
}
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 3e1b9991131a..d6a0f7df9080 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -48,7 +48,8 @@ static size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo)
}
struct seg6_lwt {
- struct dst_cache cache;
+ struct dst_cache cache_input;
+ struct dst_cache cache_output;
struct seg6_iptunnel_encap tuninfo[];
};
@@ -488,7 +489,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
slwt = seg6_lwt_lwtunnel(lwtst);
local_bh_disable();
- dst = dst_cache_get(&slwt->cache);
+ dst = dst_cache_get(&slwt->cache_input);
local_bh_enable();
err = seg6_do_srh(skb, dst);
@@ -504,7 +505,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
/* cache only if we don't create a dst reference loop */
if (!dst->error && lwtst != dst->lwtstate) {
local_bh_disable();
- dst_cache_set_ip6(&slwt->cache, dst,
+ dst_cache_set_ip6(&slwt->cache_input, dst,
&ipv6_hdr(skb)->saddr);
local_bh_enable();
}
@@ -564,7 +565,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
local_bh_disable();
- dst = dst_cache_get(&slwt->cache);
+ dst = dst_cache_get(&slwt->cache_output);
local_bh_enable();
err = seg6_do_srh(skb, dst);
@@ -591,7 +592,7 @@ static int seg6_output_core(struct net *net, struct sock *sk,
/* cache only if we don't create a dst reference loop */
if (orig_dst->lwtstate != dst->lwtstate) {
local_bh_disable();
- dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
+ dst_cache_set_ip6(&slwt->cache_output, dst, &fl6.saddr);
local_bh_enable();
}
@@ -701,11 +702,13 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
slwt = seg6_lwt_lwtunnel(newts);
- err = dst_cache_init(&slwt->cache, GFP_ATOMIC);
- if (err) {
- kfree(newts);
- return err;
- }
+ err = dst_cache_init(&slwt->cache_input, GFP_ATOMIC);
+ if (err)
+ goto err_free_newts;
+
+ err = dst_cache_init(&slwt->cache_output, GFP_ATOMIC);
+ if (err)
+ goto err_destroy_input;
memcpy(&slwt->tuninfo, tuninfo, tuninfo_len);
@@ -720,11 +723,20 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
*ts = newts;
return 0;
+
+err_destroy_input:
+ dst_cache_destroy(&slwt->cache_input);
+err_free_newts:
+ kfree(newts);
+ return err;
}
static void seg6_destroy_state(struct lwtunnel_state *lwt)
{
- dst_cache_destroy(&seg6_lwt_lwtunnel(lwt)->cache);
+ struct seg6_lwt *slwt = seg6_lwt_lwtunnel(lwt);
+
+ dst_cache_destroy(&slwt->cache_input);
+ dst_cache_destroy(&slwt->cache_output);
}
static int seg6_fill_encap_info(struct sk_buff *skb,
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 9005fc156a20..699a001ac166 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -43,6 +43,7 @@ static int xfrm6_transport_finish2(struct net *net, struct sock *sk,
int xfrm6_transport_finish(struct sk_buff *skb, int async)
{
struct xfrm_offload *xo = xfrm_offload(skb);
+ struct net_device *dev = skb->dev;
int nhlen = -skb_network_offset(skb);
skb_network_header(skb)[IP6CB(skb)->nhoff] =
@@ -68,8 +69,10 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
}
NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
- dev_net(skb->dev), NULL, skb, skb->dev, NULL,
+ dev_net(dev), NULL, skb, dev, NULL,
xfrm6_transport_finish2);
+ if (async)
+ dev_put(dev);
return 0;
}
diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
index 17eb50276e77..38547fbadd35 100644
--- a/net/mptcp/pm_kernel.c
+++ b/net/mptcp/pm_kernel.c
@@ -720,7 +720,7 @@ static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
struct mptcp_pm_addr_entry *entry,
- bool needs_id, bool replace)
+ bool replace)
{
struct mptcp_pm_addr_entry *cur, *del_entry = NULL;
int ret = -EINVAL;
@@ -779,7 +779,7 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
}
}
- if (!entry->addr.id && needs_id) {
+ if (!entry->addr.id) {
find_next:
entry->addr.id = find_next_zero_bit(pernet->id_bitmap,
MPTCP_PM_MAX_ADDR_ID + 1,
@@ -790,7 +790,7 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
}
}
- if (!entry->addr.id && needs_id)
+ if (!entry->addr.id)
goto out;
__set_bit(entry->addr.id, pernet->id_bitmap);
@@ -923,7 +923,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk,
return -ENOMEM;
entry->addr.port = 0;
- ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, true, false);
+ ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, false);
if (ret < 0)
kfree(entry);
@@ -977,18 +977,6 @@ static int mptcp_nl_add_subflow_or_signal_addr(struct net *net,
return 0;
}
-static bool mptcp_pm_has_addr_attr_id(const struct nlattr *attr,
- struct genl_info *info)
-{
- struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1];
-
- if (!nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr,
- mptcp_pm_address_nl_policy, info->extack) &&
- tb[MPTCP_PM_ADDR_ATTR_ID])
- return true;
- return false;
-}
-
/* Add an MPTCP endpoint */
int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info)
{
@@ -1037,9 +1025,7 @@ int mptcp_pm_nl_add_addr_doit(struct sk_buff *skb, struct genl_info *info)
goto out_free;
}
}
- ret = mptcp_pm_nl_append_new_local_addr(pernet, entry,
- !mptcp_pm_has_addr_attr_id(attr, info),
- true);
+ ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, true);
if (ret < 0) {
GENL_SET_ERR_MSG_FMT(info, "too many addresses or duplicate one: %d", ret);
goto out_free;
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index f1fa35cb8c00..80cb723ba1f3 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -4456,6 +4456,8 @@ int __init mptcp_proto_v6_init(void)
{
int err;
+ mptcp_subflow_v6_init();
+
mptcp_v6_prot = mptcp_prot;
strscpy(mptcp_v6_prot.name, "MPTCPv6", sizeof(mptcp_v6_prot.name));
mptcp_v6_prot.slab = NULL;
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 39afd44e072f..b10453adf997 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -875,6 +875,7 @@ static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
void __init mptcp_proto_init(void);
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
int __init mptcp_proto_v6_init(void);
+void __init mptcp_subflow_v6_init(void);
#endif
struct sock *mptcp_sk_clone_init(const struct sock *sk,
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index b11d0bf006c1..10458e2e9b86 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -2167,7 +2167,15 @@ void __init mptcp_subflow_init(void)
tcp_prot_override.psock_update_sk_prot = NULL;
#endif
+ mptcp_diag_subflow_init(&subflow_ulp_ops);
+
+ if (tcp_register_ulp(&subflow_ulp_ops) != 0)
+ panic("MPTCP: failed to register subflows to ULP\n");
+}
+
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+void __init mptcp_subflow_v6_init(void)
+{
/* In struct mptcp_subflow_request_sock, we assume the TCP request sock
* structures for v4 and v6 have the same size. It should not changed in
* the future but better to make sure to be warned if it is no longer
@@ -2206,10 +2214,5 @@ void __init mptcp_subflow_init(void)
/* Disable sockmap processing for subflows */
tcpv6_prot_override.psock_update_sk_prot = NULL;
#endif
-#endif
-
- mptcp_diag_subflow_init(&subflow_ulp_ops);
-
- if (tcp_register_ulp(&subflow_ulp_ops) != 0)
- panic("MPTCP: failed to register subflows to ULP\n");
}
+#endif
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index db1bf69f8775..4f52ca4c48d5 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -1021,7 +1021,7 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx,
nf_queue_nf_hook_drop(ctx->net);
nf_ct_untimeout(ctx->net, timeout);
nf_ct_netns_put(ctx->net, ctx->family);
- kfree(priv->timeout);
+ kfree_rcu(priv->timeout, rcu);
}
static int nft_ct_timeout_obj_dump(struct sk_buff *skb,
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 7d3e82e4c2fc..868a8586dc17 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -73,11 +73,14 @@ struct rfkill_int_event {
struct rfkill_event_ext ev;
};
+/* Max rfkill events that can be "in-flight" for one data source */
+#define MAX_RFKILL_EVENT 1000
struct rfkill_data {
struct list_head list;
struct list_head events;
struct mutex mtx;
wait_queue_head_t read_wait;
+ u32 event_count;
bool input_handler;
u8 max_size;
};
@@ -255,10 +258,12 @@ static void rfkill_global_led_trigger_unregister(void)
}
#endif /* CONFIG_RFKILL_LEDS */
-static void rfkill_fill_event(struct rfkill_event_ext *ev,
- struct rfkill *rfkill,
- enum rfkill_operation op)
+static int rfkill_fill_event(struct rfkill_int_event *int_ev,
+ struct rfkill *rfkill,
+ struct rfkill_data *data,
+ enum rfkill_operation op)
{
+ struct rfkill_event_ext *ev = &int_ev->ev;
unsigned long flags;
ev->idx = rfkill->idx;
@@ -271,6 +276,15 @@ static void rfkill_fill_event(struct rfkill_event_ext *ev,
RFKILL_BLOCK_SW_PREV));
ev->hard_block_reasons = rfkill->hard_block_reasons;
spin_unlock_irqrestore(&rfkill->lock, flags);
+
+ scoped_guard(mutex, &data->mtx) {
+ if (data->event_count++ > MAX_RFKILL_EVENT) {
+ data->event_count--;
+ return -ENOSPC;
+ }
+ list_add_tail(&int_ev->list, &data->events);
+ }
+ return 0;
}
static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op)
@@ -282,10 +296,10 @@ static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op)
ev = kzalloc(sizeof(*ev), GFP_KERNEL);
if (!ev)
continue;
- rfkill_fill_event(&ev->ev, rfkill, op);
- mutex_lock(&data->mtx);
- list_add_tail(&ev->list, &data->events);
- mutex_unlock(&data->mtx);
+ if (rfkill_fill_event(ev, rfkill, data, op)) {
+ kfree(ev);
+ continue;
+ }
wake_up_interruptible(&data->read_wait);
}
}
@@ -1186,10 +1200,8 @@ static int rfkill_fop_open(struct inode *inode, struct file *file)
if (!ev)
goto free;
rfkill_sync(rfkill);
- rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD);
- mutex_lock(&data->mtx);
- list_add_tail(&ev->list, &data->events);
- mutex_unlock(&data->mtx);
+ if (rfkill_fill_event(ev, rfkill, data, RFKILL_OP_ADD))
+ kfree(ev);
}
list_add(&data->list, &rfkill_fds);
mutex_unlock(&rfkill_global_mutex);
@@ -1259,6 +1271,7 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
ret = -EFAULT;
list_del(&ev->list);
+ data->event_count--;
kfree(ev);
out:
mutex_unlock(&data->mtx);
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0f90272ac254..32ec91fa938f 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -654,9 +654,6 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
goto success;
case RXRPC_SECURITY_KEY:
- ret = -EINVAL;
- if (rx->key)
- goto error;
ret = -EISCONN;
if (rx->sk.sk_state != RXRPC_UNBOUND)
goto error;
@@ -664,9 +661,6 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
goto error;
case RXRPC_SECURITY_KEYRING:
- ret = -EINVAL;
- if (rx->key)
- goto error;
ret = -EISCONN;
if (rx->sk.sk_state != RXRPC_UNBOUND)
goto error;
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 36d6ca0d1089..96ecb83c9071 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -117,7 +117,7 @@ struct rxrpc_net {
atomic_t stat_tx_jumbo[10];
atomic_t stat_rx_jumbo[10];
- atomic_t stat_why_req_ack[8];
+ atomic_t stat_why_req_ack[9];
atomic_t stat_io_loop;
};
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 918f41d97a2f..f035f486c139 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -654,11 +654,9 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace why)
if (dead) {
ASSERTCMP(__rxrpc_call_state(call), ==, RXRPC_CALL_COMPLETE);
- if (!list_empty(&call->link)) {
- spin_lock(&rxnet->call_lock);
- list_del_init(&call->link);
- spin_unlock(&rxnet->call_lock);
- }
+ spin_lock(&rxnet->call_lock);
+ list_del_rcu(&call->link);
+ spin_unlock(&rxnet->call_lock);
rxrpc_cleanup_call(call);
}
@@ -694,6 +692,7 @@ static void rxrpc_destroy_call(struct work_struct *work)
rxrpc_put_bundle(call->bundle, rxrpc_bundle_put_call);
rxrpc_put_peer(call->peer, rxrpc_peer_put_call);
rxrpc_put_local(call->local, rxrpc_local_put_call);
+ key_put(call->key);
call_rcu(&call->rcu, rxrpc_rcu_free_call);
}
@@ -730,24 +729,20 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)
_enter("");
if (!list_empty(&rxnet->calls)) {
- spin_lock(&rxnet->call_lock);
+ int shown = 0;
- while (!list_empty(&rxnet->calls)) {
- call = list_entry(rxnet->calls.next,
- struct rxrpc_call, link);
- _debug("Zapping call %p", call);
+ spin_lock(&rxnet->call_lock);
- rxrpc_see_call(call, rxrpc_call_see_zap);
- list_del_init(&call->link);
+ list_for_each_entry(call, &rxnet->calls, link) {
+ rxrpc_see_call(call, rxrpc_call_see_still_live);
pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n",
call, refcount_read(&call->ref),
rxrpc_call_states[__rxrpc_call_state(call)],
call->flags, call->events);
- spin_unlock(&rxnet->call_lock);
- cond_resched();
- spin_lock(&rxnet->call_lock);
+ if (++shown >= 10)
+ break;
}
spin_unlock(&rxnet->call_lock);
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 98ad9b51ca2c..9a41ec708aeb 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -247,6 +247,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+ bool secured = false;
int ret;
if (conn->state == RXRPC_CONN_ABORTED)
@@ -262,6 +263,13 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
return ret;
case RXRPC_PACKET_TYPE_RESPONSE:
+ spin_lock_irq(&conn->state_lock);
+ if (conn->state != RXRPC_CONN_SERVICE_CHALLENGING) {
+ spin_unlock_irq(&conn->state_lock);
+ return 0;
+ }
+ spin_unlock_irq(&conn->state_lock);
+
ret = conn->security->verify_response(conn, skb);
if (ret < 0)
return ret;
@@ -272,11 +280,13 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
return ret;
spin_lock_irq(&conn->state_lock);
- if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING)
+ if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
conn->state = RXRPC_CONN_SERVICE;
+ secured = true;
+ }
spin_unlock_irq(&conn->state_lock);
- if (conn->state == RXRPC_CONN_SERVICE) {
+ if (secured) {
/* Offload call state flipping to the I/O thread. As
* we've already received the packet, put it on the
* front of the queue.
@@ -557,11 +567,11 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb)
spin_lock_irq(&local->lock);
old = conn->tx_response;
if (old) {
- struct rxrpc_skb_priv *osp = rxrpc_skb(skb);
+ struct rxrpc_skb_priv *osp = rxrpc_skb(old);
/* Always go with the response to the most recent challenge. */
if (after(sp->resp.challenge_serial, osp->resp.challenge_serial))
- conn->tx_response = old;
+ conn->tx_response = skb;
else
old = skb;
} else {
@@ -569,4 +579,5 @@ void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb)
}
spin_unlock_irq(&local->lock);
rxrpc_poke_conn(conn, rxrpc_conn_get_poke_response);
+ rxrpc_free_skb(old, rxrpc_skb_put_old_response);
}
diff --git a/net/rxrpc/input_rack.c b/net/rxrpc/input_rack.c
index 13c371261e0a..9eb109ffba56 100644
--- a/net/rxrpc/input_rack.c
+++ b/net/rxrpc/input_rack.c
@@ -413,6 +413,6 @@ void rxrpc_rack_timer_expired(struct rxrpc_call *call, ktime_t overran_by)
break;
//case RXRPC_CALL_RACKTIMER_ZEROWIN:
default:
- pr_warn("Unexpected rack timer %u", call->rack_timer_mode);
+ pr_warn("Unexpected rack timer %u", mode);
}
}
diff --git a/net/rxrpc/io_thread.c b/net/rxrpc/io_thread.c
index e939ecf417c4..697956931925 100644
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -419,7 +419,8 @@ static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
if (sp->hdr.callNumber > chan->call_id) {
if (rxrpc_to_client(sp)) {
- rxrpc_put_call(call, rxrpc_call_put_input);
+ if (call)
+ rxrpc_put_call(call, rxrpc_call_put_input);
return rxrpc_protocol_error(skb,
rxrpc_eproto_unexpected_implicit_end);
}
diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
index 9fdc1f031c9d..e0c29ebe6b6d 100644
--- a/net/rxrpc/key.c
+++ b/net/rxrpc/key.c
@@ -13,6 +13,7 @@
#include <crypto/skcipher.h>
#include <linux/module.h>
#include <linux/net.h>
+#include <linux/overflow.h>
#include <linux/skbuff.h>
#include <linux/key-type.h>
#include <linux/ctype.h>
@@ -72,7 +73,7 @@ static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
return -EKEYREJECTED;
plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
- prep->quotalen = datalen + plen;
+ prep->quotalen += datalen + plen;
plen -= sizeof(*token);
token = kzalloc(sizeof(*token), GFP_KERNEL);
@@ -171,7 +172,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
size_t plen;
const __be32 *ticket, *key;
s64 tmp;
- u32 tktlen, keylen;
+ size_t raw_keylen, raw_tktlen, keylen, tktlen;
_enter(",{%x,%x,%x,%x},%x",
ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
@@ -181,32 +182,36 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
goto reject;
key = xdr + (6 * 2 + 1);
- keylen = ntohl(key[-1]);
- _debug("keylen: %x", keylen);
- keylen = round_up(keylen, 4);
+ raw_keylen = ntohl(key[-1]);
+ _debug("keylen: %zx", raw_keylen);
+ if (raw_keylen > AFSTOKEN_GK_KEY_MAX)
+ goto reject;
+ keylen = round_up(raw_keylen, 4);
if ((6 * 2 + 2) * 4 + keylen > toklen)
goto reject;
ticket = xdr + (6 * 2 + 1 + (keylen / 4) + 1);
- tktlen = ntohl(ticket[-1]);
- _debug("tktlen: %x", tktlen);
- tktlen = round_up(tktlen, 4);
+ raw_tktlen = ntohl(ticket[-1]);
+ _debug("tktlen: %zx", raw_tktlen);
+ if (raw_tktlen > AFSTOKEN_GK_TOKEN_MAX)
+ goto reject;
+ tktlen = round_up(raw_tktlen, 4);
if ((6 * 2 + 2) * 4 + keylen + tktlen != toklen) {
- kleave(" = -EKEYREJECTED [%x!=%x, %x,%x]",
+ kleave(" = -EKEYREJECTED [%zx!=%x, %zx,%zx]",
(6 * 2 + 2) * 4 + keylen + tktlen, toklen,
keylen, tktlen);
goto reject;
}
plen = sizeof(*token) + sizeof(*token->rxgk) + tktlen + keylen;
- prep->quotalen = datalen + plen;
+ prep->quotalen += datalen + plen;
plen -= sizeof(*token);
token = kzalloc(sizeof(*token), GFP_KERNEL);
if (!token)
goto nomem;
- token->rxgk = kzalloc(sizeof(*token->rxgk) + keylen, GFP_KERNEL);
+ token->rxgk = kzalloc(struct_size_t(struct rxgk_key, _key, raw_keylen), GFP_KERNEL);
if (!token->rxgk)
goto nomem_token;
@@ -221,9 +226,9 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
token->rxgk->enctype = tmp = xdr_dec64(xdr + 5 * 2);
if (tmp < 0 || tmp > UINT_MAX)
goto reject_token;
- token->rxgk->key.len = ntohl(key[-1]);
+ token->rxgk->key.len = raw_keylen;
token->rxgk->key.data = token->rxgk->_key;
- token->rxgk->ticket.len = ntohl(ticket[-1]);
+ token->rxgk->ticket.len = raw_tktlen;
if (token->rxgk->endtime != 0) {
expiry = rxrpc_s64_to_time64(token->rxgk->endtime);
@@ -236,8 +241,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
memcpy(token->rxgk->key.data, key, token->rxgk->key.len);
/* Pad the ticket so that we can use it directly in XDR */
- token->rxgk->ticket.data = kzalloc(round_up(token->rxgk->ticket.len, 4),
- GFP_KERNEL);
+ token->rxgk->ticket.data = kzalloc(tktlen, GFP_KERNEL);
if (!token->rxgk->ticket.data)
goto nomem_yrxgk;
memcpy(token->rxgk->ticket.data, ticket, token->rxgk->ticket.len);
@@ -274,6 +278,7 @@ static int rxrpc_preparse_xdr_yfs_rxgk(struct key_preparsed_payload *prep,
nomem:
return -ENOMEM;
reject_token:
+ kfree(token->rxgk);
kfree(token);
reject:
return -EKEYREJECTED;
@@ -460,6 +465,7 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)
memcpy(&kver, prep->data, sizeof(kver));
prep->data += sizeof(kver);
prep->datalen -= sizeof(kver);
+ prep->quotalen = 0;
_debug("KEY I/F VERSION: %u", kver);
@@ -497,7 +503,7 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)
goto error;
plen = sizeof(*token->kad) + v1->ticket_length;
- prep->quotalen = plen + sizeof(*token);
+ prep->quotalen += plen + sizeof(*token);
ret = -ENOMEM;
token = kzalloc(sizeof(*token), GFP_KERNEL);
@@ -616,7 +622,7 @@ int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
_enter("");
- if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
+ if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->key)
return -EINVAL;
description = memdup_sockptr_nul(optval, optlen);
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index d70db367e358..870e59bf06af 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -479,6 +479,8 @@ static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call,
why = rxrpc_reqack_old_rtt;
else if (!last && !after(READ_ONCE(call->send_top), txb->seq))
why = rxrpc_reqack_app_stall;
+ else if (call->tx_winsize <= (2 * req->n) || call->cong_cwnd <= (2 * req->n))
+ why = rxrpc_reqack_jumbo_win;
else
goto dont_set_request_ack;
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 59292f7f9205..e9a27fa7b25d 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -10,6 +10,10 @@
#include <net/af_rxrpc.h>
#include "ar-internal.h"
+#define RXRPC_PROC_ADDRBUF_SIZE \
+ (sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") + \
+ sizeof(":12345"))
+
static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = {
[RXRPC_CONN_UNUSED] = "Unused ",
[RXRPC_CONN_CLIENT_UNSECURED] = "ClUnsec ",
@@ -53,7 +57,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
enum rxrpc_call_state state;
rxrpc_seq_t tx_bottom;
- char lbuff[50], rbuff[50];
+ char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE];
long timeout = 0;
if (v == &rxnet->calls) {
@@ -69,11 +73,11 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
local = call->local;
if (local)
- sprintf(lbuff, "%pISpc", &local->srx.transport);
+ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport);
else
strcpy(lbuff, "no_local");
- sprintf(rbuff, "%pISpc", &call->dest_srx.transport);
+ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &call->dest_srx.transport);
state = rxrpc_call_state(call);
if (state != RXRPC_CALL_SERVER_PREALLOC)
@@ -142,7 +146,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
struct rxrpc_connection *conn;
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
const char *state;
- char lbuff[50], rbuff[50];
+ char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE];
if (v == &rxnet->conn_proc_list) {
seq_puts(seq,
@@ -161,8 +165,8 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
goto print;
}
- sprintf(lbuff, "%pISpc", &conn->local->srx.transport);
- sprintf(rbuff, "%pISpc", &conn->peer->srx.transport);
+ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &conn->local->srx.transport);
+ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &conn->peer->srx.transport);
print:
state = rxrpc_is_conn_aborted(conn) ?
rxrpc_call_completions[conn->completion] :
@@ -228,7 +232,7 @@ static int rxrpc_bundle_seq_show(struct seq_file *seq, void *v)
{
struct rxrpc_bundle *bundle;
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
- char lbuff[50], rbuff[50];
+ char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE];
if (v == &rxnet->bundle_proc_list) {
seq_puts(seq,
@@ -242,8 +246,8 @@ static int rxrpc_bundle_seq_show(struct seq_file *seq, void *v)
bundle = list_entry(v, struct rxrpc_bundle, proc_link);
- sprintf(lbuff, "%pISpc", &bundle->local->srx.transport);
- sprintf(rbuff, "%pISpc", &bundle->peer->srx.transport);
+ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &bundle->local->srx.transport);
+ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &bundle->peer->srx.transport);
seq_printf(seq,
"UDP %-47.47s %-47.47s %4x %3u %3d"
" %c%c%c %08x | %08x %08x %08x %08x %08x\n",
@@ -279,7 +283,7 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
{
struct rxrpc_peer *peer;
time64_t now;
- char lbuff[50], rbuff[50];
+ char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE];
if (v == SEQ_START_TOKEN) {
seq_puts(seq,
@@ -290,9 +294,9 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
peer = list_entry(v, struct rxrpc_peer, hash_link);
- sprintf(lbuff, "%pISpc", &peer->local->srx.transport);
+ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &peer->local->srx.transport);
- sprintf(rbuff, "%pISpc", &peer->srx.transport);
+ scnprintf(rbuff, sizeof(rbuff), "%pISpc", &peer->srx.transport);
now = ktime_get_seconds();
seq_printf(seq,
@@ -401,7 +405,7 @@ const struct seq_operations rxrpc_peer_seq_ops = {
static int rxrpc_local_seq_show(struct seq_file *seq, void *v)
{
struct rxrpc_local *local;
- char lbuff[50];
+ char lbuff[RXRPC_PROC_ADDRBUF_SIZE];
if (v == SEQ_START_TOKEN) {
seq_puts(seq,
@@ -412,7 +416,7 @@ static int rxrpc_local_seq_show(struct seq_file *seq, void *v)
local = hlist_entry(v, struct rxrpc_local, link);
- sprintf(lbuff, "%pISpc", &local->srx.transport);
+ scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport);
seq_printf(seq,
"UDP %-47.47s %3u %3u %3u\n",
@@ -518,11 +522,12 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_IDLE]),
atomic_read(&rxnet->stat_rx_acks[0]));
seq_printf(seq,
- "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u\n",
+ "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u jwin=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_ack_lost]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_more_rtt]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt]),
- atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]));
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]),
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_jumbo_win]));
seq_printf(seq,
"Why-Req-A: nolast=%u retx=%u slows=%u smtxw=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_no_srv_last]),
diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
index 43cbf9efd89f..c39f5066d8e8 100644
--- a/net/rxrpc/rxgk.c
+++ b/net/rxrpc/rxgk.c
@@ -1085,6 +1085,9 @@ static int rxgk_do_verify_authenticator(struct rxrpc_connection *conn,
_enter("");
+ if ((end - p) * sizeof(__be32) < 24)
+ return rxrpc_abort_conn(conn, skb, RXGK_NOTAUTH, -EPROTO,
+ rxgk_abort_resp_short_auth);
if (memcmp(p, conn->rxgk.nonce, 20) != 0)
return rxrpc_abort_conn(conn, skb, RXGK_NOTAUTH, -EPROTO,
rxgk_abort_resp_bad_nonce);
@@ -1098,7 +1101,7 @@ static int rxgk_do_verify_authenticator(struct rxrpc_connection *conn,
p += xdr_round_up(app_len) / sizeof(__be32);
if (end - p < 4)
return rxrpc_abort_conn(conn, skb, RXGK_NOTAUTH, -EPROTO,
- rxgk_abort_resp_short_applen);
+ rxgk_abort_resp_short_auth);
level = ntohl(*p++);
epoch = ntohl(*p++);
@@ -1164,7 +1167,8 @@ static int rxgk_verify_authenticator(struct rxrpc_connection *conn,
}
p = auth;
- ret = rxgk_do_verify_authenticator(conn, krb5, skb, p, p + auth_len);
+ ret = rxgk_do_verify_authenticator(conn, krb5, skb, p,
+ p + auth_len / sizeof(*p));
error:
kfree(auth);
return ret;
@@ -1208,7 +1212,8 @@ static int rxgk_verify_response(struct rxrpc_connection *conn,
token_offset = offset;
token_len = ntohl(rhdr.token_len);
- if (xdr_round_up(token_len) + sizeof(__be32) > len)
+ if (token_len > len ||
+ xdr_round_up(token_len) + sizeof(__be32) > len)
goto short_packet;
trace_rxrpc_rx_response(conn, sp->hdr.serial, 0, sp->hdr.cksum, token_len);
@@ -1223,7 +1228,7 @@ static int rxgk_verify_response(struct rxrpc_connection *conn,
auth_offset = offset;
auth_len = ntohl(xauth_len);
- if (auth_len < len)
+ if (auth_len > len)
goto short_packet;
if (auth_len & 3)
goto inconsistent;
@@ -1268,16 +1273,18 @@ static int rxgk_verify_response(struct rxrpc_connection *conn,
if (ret < 0) {
rxrpc_abort_conn(conn, skb, RXGK_SEALEDINCON, ret,
rxgk_abort_resp_auth_dec);
- goto out;
+ goto out_gk;
}
ret = rxgk_verify_authenticator(conn, krb5, skb, auth_offset, auth_len);
if (ret < 0)
- goto out;
+ goto out_gk;
conn->key = key;
key = NULL;
ret = 0;
+out_gk:
+ rxgk_put(gk);
out:
key_put(key);
_leave(" = %d", ret);
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index a756855a0a62..4a3c63094149 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -197,6 +197,7 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn,
struct rxrpc_crypt iv;
__be32 *tmpbuf;
size_t tmpsize = 4 * sizeof(__be32);
+ int ret;
_enter("");
@@ -225,13 +226,13 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn,
skcipher_request_set_sync_tfm(req, ci);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, tmpsize, iv.x);
- crypto_skcipher_encrypt(req);
+ ret = crypto_skcipher_encrypt(req);
skcipher_request_free(req);
memcpy(&conn->rxkad.csum_iv, tmpbuf + 2, sizeof(conn->rxkad.csum_iv));
kfree(tmpbuf);
- _leave(" = 0");
- return 0;
+ _leave(" = %d", ret);
+ return ret;
}
/*
@@ -264,6 +265,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
struct scatterlist sg;
size_t pad;
u16 check;
+ int ret;
_enter("");
@@ -286,11 +288,11 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
- crypto_skcipher_encrypt(req);
+ ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
- _leave(" = 0");
- return 0;
+ _leave(" = %d", ret);
+ return ret;
}
/*
@@ -345,7 +347,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
union {
__be32 buf[2];
} crypto __aligned(8);
- u32 x, y;
+ u32 x, y = 0;
int ret;
_enter("{%d{%x}},{#%u},%u,",
@@ -376,8 +378,10 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
- crypto_skcipher_encrypt(req);
+ ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
+ if (ret < 0)
+ goto out;
y = ntohl(crypto.buf[1]);
y = (y >> 16) & 0xffff;
@@ -413,6 +417,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
memset(p + txb->pkt_len, 0, gap);
}
+out:
skcipher_request_free(req);
_leave(" = %d [set %x]", ret, y);
return ret;
@@ -453,8 +458,10 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, 8, iv.x);
- crypto_skcipher_decrypt(req);
+ ret = crypto_skcipher_decrypt(req);
skcipher_request_zero(req);
+ if (ret < 0)
+ return ret;
/* Extract the decrypted packet length */
if (skb_copy_bits(skb, sp->offset, &sechdr, sizeof(sechdr)) < 0)
@@ -531,10 +538,14 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, sp->len, iv.x);
- crypto_skcipher_decrypt(req);
+ ret = crypto_skcipher_decrypt(req);
skcipher_request_zero(req);
if (sg != _sg)
kfree(sg);
+ if (ret < 0) {
+ WARN_ON_ONCE(ret != -ENOMEM);
+ return ret;
+ }
/* Extract the decrypted packet length */
if (skb_copy_bits(skb, sp->offset, &sechdr, sizeof(sechdr)) < 0)
@@ -602,8 +613,10 @@ static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb)
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
- crypto_skcipher_encrypt(req);
+ ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
+ if (ret < 0)
+ goto out;
y = ntohl(crypto.buf[1]);
cksum = (y >> 16) & 0xffff;
@@ -958,6 +971,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
struct in_addr addr;
unsigned int life;
time64_t issue, now;
+ int ret;
bool little_endian;
u8 *p, *q, *name, *end;
@@ -977,8 +991,11 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
sg_init_one(&sg[0], ticket, ticket_len);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x);
- crypto_skcipher_decrypt(req);
+ ret = crypto_skcipher_decrypt(req);
skcipher_request_free(req);
+ if (ret < 0)
+ return rxrpc_abort_conn(conn, skb, RXKADBADTICKET, -EPROTO,
+ rxkad_abort_resp_tkt_short);
p = ticket;
end = p + ticket_len;
@@ -1073,21 +1090,23 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
/*
* decrypt the response packet
*/
-static void rxkad_decrypt_response(struct rxrpc_connection *conn,
- struct rxkad_response *resp,
- const struct rxrpc_crypt *session_key)
+static int rxkad_decrypt_response(struct rxrpc_connection *conn,
+ struct rxkad_response *resp,
+ const struct rxrpc_crypt *session_key)
{
struct skcipher_request *req = rxkad_ci_req;
struct scatterlist sg[1];
struct rxrpc_crypt iv;
+ int ret;
_enter(",,%08x%08x",
ntohl(session_key->n[0]), ntohl(session_key->n[1]));
mutex_lock(&rxkad_ci_mutex);
- if (crypto_sync_skcipher_setkey(rxkad_ci, session_key->x,
- sizeof(*session_key)) < 0)
- BUG();
+ ret = crypto_sync_skcipher_setkey(rxkad_ci, session_key->x,
+ sizeof(*session_key));
+ if (ret < 0)
+ goto unlock;
memcpy(&iv, session_key, sizeof(iv));
@@ -1096,12 +1115,14 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn,
skcipher_request_set_sync_tfm(req, rxkad_ci);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
- crypto_skcipher_decrypt(req);
+ ret = crypto_skcipher_decrypt(req);
skcipher_request_zero(req);
+unlock:
mutex_unlock(&rxkad_ci_mutex);
_leave("");
+ return ret;
}
/*
@@ -1194,7 +1215,9 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
/* use the session key from inside the ticket to decrypt the
* response */
- rxkad_decrypt_response(conn, response, &session_key);
+ ret = rxkad_decrypt_response(conn, response, &session_key);
+ if (ret < 0)
+ goto temporary_error_free_ticket;
if (ntohl(response->encrypted.epoch) != conn->proto.epoch ||
ntohl(response->encrypted.cid) != conn->proto.cid ||
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index ebbb78b842de..39a6b21d6b8f 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -637,7 +637,7 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
memset(&cp, 0, sizeof(cp));
cp.local = rx->local;
cp.peer = peer;
- cp.key = rx->key;
+ cp.key = key;
cp.security_level = rx->min_sec_level;
cp.exclusive = rx->exclusive | p->exclusive;
cp.upgrade = p->upgrade;
diff --git a/net/rxrpc/server_key.c b/net/rxrpc/server_key.c
index 36b05fd842a7..27491f1e1273 100644
--- a/net/rxrpc/server_key.c
+++ b/net/rxrpc/server_key.c
@@ -125,6 +125,9 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
_enter("");
+ if (rx->securities)
+ return -EINVAL;
+
if (optlen <= 0 || optlen > PAGE_SIZE - 1)
return -EINVAL;
diff --git a/net/tipc/group.c b/net/tipc/group.c
index 3e137d8c9d2f..215f2a7d8458 100644
--- a/net/tipc/group.c
+++ b/net/tipc/group.c
@@ -746,6 +746,7 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
u32 port = msg_origport(hdr);
struct tipc_member *m, *pm;
u16 remitted, in_flight;
+ u16 acked;
if (!grp)
return;
@@ -798,7 +799,10 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
case GRP_ACK_MSG:
if (!m)
return;
- m->bc_acked = msg_grp_bc_acked(hdr);
+ acked = msg_grp_bc_acked(hdr);
+ if (less_eq(acked, m->bc_acked))
+ return;
+ m->bc_acked = acked;
if (--grp->bc_ackers)
return;
list_del_init(&m->small_win);
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index c0aadc8dce14..7f10c18a6eea 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -584,6 +584,16 @@ static int tls_do_encryption(struct sock *sk,
if (rc == -EBUSY) {
rc = tls_encrypt_async_wait(ctx);
rc = rc ?: -EINPROGRESS;
+ /*
+ * The async callback tls_encrypt_done() has already
+ * decremented encrypt_pending and restored the sge on
+ * both success and error. Skip the synchronous cleanup
+ * below on error, just remove the record and return.
+ */
+ if (rc != -EINPROGRESS) {
+ list_del(&rec->list);
+ return rc;
+ }
}
if (!rc || rc != -EINPROGRESS) {
atomic_dec(&ctx->encrypt_pending);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 4ed346e682c7..5d49323695eb 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -503,7 +503,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
/* An encap_type of -1 indicates async resumption. */
if (encap_type == -1) {
async = 1;
- dev_put(skb->dev);
seq = XFRM_SKB_CB(skb)->seq.input.low;
spin_lock(&x->lock);
goto resume;
@@ -656,8 +655,11 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
dev_hold(skb->dev);
nexthdr = x->type->input(x, skb);
- if (nexthdr == -EINPROGRESS)
+ if (nexthdr == -EINPROGRESS) {
+ if (async)
+ dev_put(skb->dev);
return 0;
+ }
dev_put(skb->dev);
spin_lock(&x->lock);
@@ -692,9 +694,11 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
err = xfrm_inner_mode_input(x, skb);
- if (err == -EINPROGRESS)
+ if (err == -EINPROGRESS) {
+ if (async)
+ dev_put(skb->dev);
return 0;
- else if (err) {
+ } else if (err) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
goto drop;
}
@@ -731,6 +735,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
sp->olen = 0;
if (skb_valid_dst(skb))
skb_dst_drop(skb);
+ if (async)
+ dev_put(skb->dev);
gro_cells_receive(&gro_cells, skb);
return 0;
} else {
@@ -750,6 +756,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
sp->olen = 0;
if (skb_valid_dst(skb))
skb_dst_drop(skb);
+ if (async)
+ dev_put(skb->dev);
gro_cells_receive(&gro_cells, skb);
return err;
}
@@ -760,6 +768,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
drop_unlock:
spin_unlock(&x->lock);
drop:
+ if (async)
+ dev_put(skb->dev);
xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1);
kfree_skb(skb);
return 0;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 4dd8341225bc..306e4f65ce26 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -3951,6 +3951,8 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
return err;
}
upe->hard = !!hard;
+ /* clear the padding bytes */
+ memset_after(upe, 0, hard);
nlmsg_end(skb, nlh);
return 0;
@@ -4108,6 +4110,7 @@ static int build_report(struct sk_buff *skb, u8 proto,
return -EMSGSIZE;
ur = nlmsg_data(nlh);
+ memset(ur, 0, sizeof(*ur));
ur->proto = proto;
memcpy(&ur->sel, sel, sizeof(ur->sel));
diff --git a/scripts/Makefile.package b/scripts/Makefile.package
index 83bfcf7cb09f..1b56b1fa0d3f 100644
--- a/scripts/Makefile.package
+++ b/scripts/Makefile.package
@@ -195,7 +195,7 @@ tar%-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar.% FORCE
.tmp_modules_cpio: FORCE
$(Q)$(MAKE) -f $(srctree)/Makefile
$(Q)rm -rf $@
- $(Q)$(MAKE) -f $(srctree)/Makefile INSTALL_MOD_PATH=$@ modules_install
+ $(Q)$(MAKE) -f $(srctree)/Makefile INSTALL_MOD_PATH=$@/$(INSTALL_MOD_PATH) modules_install
quiet_cmd_cpio = CPIO $@
cmd_cpio = $(CONFIG_SHELL) $(srctree)/usr/gen_initramfs.sh -o $@ $<
@@ -265,6 +265,7 @@ help:
@echo ' tarxz-pkg - Build the kernel as a xz compressed tarball'
@echo ' tarzst-pkg - Build the kernel as a zstd compressed tarball'
@echo ' modules-cpio-pkg - Build the kernel modules as cpio archive'
+ @echo ' (uses INSTALL_MOD_PATH inside the archive)'
@echo ' perf-tar-src-pkg - Build the perf source tarball with no compression'
@echo ' perf-targz-src-pkg - Build the perf source tarball with gzip compression'
@echo ' perf-tarbz2-src-pkg - Build the perf source tarball with bz2 compression'
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 88ad227f87cd..e8680442968d 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -56,7 +56,7 @@ static bool allow_missing_ns_imports;
static bool error_occurred;
-static bool extra_warn;
+static bool extra_warn __attribute__((unused));
bool target_is_big_endian;
bool host_is_big_endian;
diff --git a/sound/hda/codecs/realtek/alc662.c b/sound/hda/codecs/realtek/alc662.c
index 3a943adf9087..5073165d1f3c 100644
--- a/sound/hda/codecs/realtek/alc662.c
+++ b/sound/hda/codecs/realtek/alc662.c
@@ -313,7 +313,6 @@ enum {
ALC897_FIXUP_HEADSET_MIC_PIN2,
ALC897_FIXUP_UNIS_H3C_X500S,
ALC897_FIXUP_HEADSET_MIC_PIN3,
- ALC897_FIXUP_H610M_HP_PIN,
};
static const struct hda_fixup alc662_fixups[] = {
@@ -767,13 +766,6 @@ static const struct hda_fixup alc662_fixups[] = {
{ }
},
},
- [ALC897_FIXUP_H610M_HP_PIN] = {
- .type = HDA_FIXUP_PINS,
- .v.pins = (const struct hda_pintbl[]) {
- { 0x19, 0x0321403f }, /* HP out */
- { }
- },
- },
};
static const struct hda_quirk alc662_fixup_tbl[] = {
@@ -823,7 +815,6 @@ static const struct hda_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
- SND_PCI_QUIRK(0x1458, 0xa194, "H610M H V2 DDR4", ALC897_FIXUP_H610M_HP_PIN),
SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c
index c01108f8cb7f..906be1660ac5 100644
--- a/sound/hda/controllers/intel.c
+++ b/sound/hda/controllers/intel.c
@@ -295,6 +295,9 @@ enum {
#define AZX_DCAPS_INTEL_LNL \
(AZX_DCAPS_INTEL_SKYLAKE | AZX_DCAPS_PIO_COMMANDS)
+#define AZX_DCAPS_INTEL_NVL \
+ (AZX_DCAPS_INTEL_LNL & ~AZX_DCAPS_NO_ALIGN_BUFSIZE)
+
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
(AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\
@@ -2552,8 +2555,8 @@ static const struct pci_device_id azx_ids[] = {
/* Wildcat Lake */
{ PCI_DEVICE_DATA(INTEL, HDA_WCL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
/* Nova Lake */
- { PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
- { PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
+ { PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) },
+ { PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) },
/* Apollolake (Broxton-P) */
{ PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) },
/* Gemini-Lake */
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index da6c1e7263cd..16a364072821 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -219,6 +219,7 @@ EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
{
+ const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_component *scomp = sdev->component;
@@ -268,8 +269,17 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
return -ENODEV;
}
- /* minimum as per HDA spec */
- snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
+ /*
+ * Set period size constraint to ensure BDLE buffer length and
+ * start address alignment requirements are met. Align to 128
+ * bytes for newer Intel platforms, with older ones using 4 byte alignment.
+ */
+ if (chip_info->hw_ip_version >= SOF_INTEL_ACE_4_0)
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+ else
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
/* avoid circular buffer wrap in middle of period */
snd_pcm_hw_constraint_integer(substream->runtime,
prev parent reply other threads:[~2026-04-18 8:52 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-18 8:51 Linux 6.19.13 Greg Kroah-Hartman
2026-04-18 8:51 ` Greg Kroah-Hartman [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2026041833-undefined-depravity-1236@gregkh \
--to=gregkh@linuxfoundation.org \
--cc=akpm@linux-foundation.org \
--cc=jslaby@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=lwn@lwn.net \
--cc=stable@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox