commit: 037e70c2dcbcf61e699d1b3cf8a40ecf42a1dd8f Author: Arisu Tachibana <alicef <AT> gentoo <DOT> org> AuthorDate: Mon Nov 3 01:32:33 2025 +0000 Commit: Arisu Tachibana <alicef <AT> gentoo <DOT> org> CommitDate: Mon Nov 3 01:32:33 2025 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=037e70c2
Linux patch 6.6.116 Signed-off-by: Arisu Tachibana <alicef <AT> gentoo.org> 0000_README | 4 + 1115_linux-6.6.116.patch | 1467 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1471 insertions(+) diff --git a/0000_README b/0000_README index 2202adb6..6e8268f5 100644 --- a/0000_README +++ b/0000_README @@ -503,6 +503,10 @@ Patch: 1114_linux-6.6.115.patch From: https://www.kernel.org Desc: Linux 6.6.115 +Patch: 1115_linux-6.6.116.patch +From: https://www.kernel.org +Desc: Linux 6.6.116 + Patch: 1510_fs-enable-link-security-restrictions-by-default.patch From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch Desc: Enable link security restrictions by default. diff --git a/1115_linux-6.6.116.patch b/1115_linux-6.6.116.patch new file mode 100644 index 00000000..ae809f20 --- /dev/null +++ b/1115_linux-6.6.116.patch @@ -0,0 +1,1467 @@ +diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd +index 5a775b8f654351..fc82aa4e54b005 100644 +--- a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd ++++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd +@@ -75,3 +75,13 @@ Description: + The default value is 1 (GNU Remote Debug command). + Other permissible value is 0 which is for vendor defined debug + target. ++ ++What: /sys/bus/pci/drivers/xhci_hcd/.../dbc_poll_interval_ms ++Date: February 2024 ++Contact: Mathias Nyman <[email protected]> ++Description: ++ This attribute adjust the polling interval used to check for ++ DbC events. Unit is milliseconds. Accepted values range from 0 ++ up to 5000. The default value is 64 ms. ++ This polling interval is used while DbC is enabled but has no ++ active data transfers. +diff --git a/Makefile b/Makefile +index 85d8fa82569578..f28f1f9f5f4e6d 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 6 +-SUBLEVEL = 115 ++SUBLEVEL = 116 + EXTRAVERSION = + NAME = Pinguïn Aangedreven + +diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c +index 11c35cf45b4610..cb205f22096d78 100644 +--- a/arch/alpha/kernel/asm-offsets.c ++++ b/arch/alpha/kernel/asm-offsets.c +@@ -4,6 +4,7 @@ + * This code generates raw asm output which is post-processed to extract + * and format the required data. + */ ++#define COMPILE_OFFSETS + + #include <linux/types.h> + #include <linux/stddef.h> +diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c +index f77deb7991757e..2978da85fcb65b 100644 +--- a/arch/arc/kernel/asm-offsets.c ++++ b/arch/arc/kernel/asm-offsets.c +@@ -2,6 +2,7 @@ + /* + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) + */ ++#define COMPILE_OFFSETS + + #include <linux/sched.h> + #include <linux/mm.h> +diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c +index 219cbc7e5d134b..3840e1e22b7517 100644 +--- a/arch/arm/kernel/asm-offsets.c ++++ b/arch/arm/kernel/asm-offsets.c +@@ -7,6 +7,8 @@ + * This code generates raw asm output which is post-processed to extract + * and format the required data. + */ ++#define COMPILE_OFFSETS ++ + #include <linux/compiler.h> + #include <linux/sched.h> + #include <linux/mm.h> +diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c +index 5ff1942b04fcfd..ea2d740db81c52 100644 +--- a/arch/arm64/kernel/asm-offsets.c ++++ b/arch/arm64/kernel/asm-offsets.c +@@ -6,6 +6,7 @@ + * 2001-2002 Keith Owens + * Copyright (C) 2012 ARM Ltd. + */ ++#define COMPILE_OFFSETS + + #include <linux/arm_sdei.h> + #include <linux/sched.h> +diff --git a/arch/csky/kernel/asm-offsets.c b/arch/csky/kernel/asm-offsets.c +index d1e9035794733d..5525c8e7e1d9ea 100644 +--- a/arch/csky/kernel/asm-offsets.c ++++ b/arch/csky/kernel/asm-offsets.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. ++#define COMPILE_OFFSETS + + #include <linux/sched.h> + #include <linux/kernel_stat.h> +diff --git a/arch/hexagon/kernel/asm-offsets.c b/arch/hexagon/kernel/asm-offsets.c +index 03a7063f945614..50eea9fa6f1375 100644 +--- a/arch/hexagon/kernel/asm-offsets.c ++++ b/arch/hexagon/kernel/asm-offsets.c +@@ -8,6 +8,7 @@ + * + * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. + */ ++#define COMPILE_OFFSETS + + #include <linux/compat.h> + #include <linux/types.h> +diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c +index 8da0726777edb4..110afd3cc8f348 100644 +--- a/arch/loongarch/kernel/asm-offsets.c ++++ b/arch/loongarch/kernel/asm-offsets.c +@@ -4,6 +4,8 @@ + * + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited + */ ++#define COMPILE_OFFSETS ++ + #include <linux/types.h> + #include <linux/sched.h> + #include <linux/mm.h> +diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c +index 906d7323053744..67a1990f9d748f 100644 +--- a/arch/m68k/kernel/asm-offsets.c ++++ b/arch/m68k/kernel/asm-offsets.c +@@ -9,6 +9,7 @@ + * #defines from the assembly-language output. + */ + ++#define COMPILE_OFFSETS + #define ASM_OFFSETS_C + + #include <linux/stddef.h> +diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c +index 104c3ac5f30c88..b4b67d58e7f6ae 100644 +--- a/arch/microblaze/kernel/asm-offsets.c ++++ b/arch/microblaze/kernel/asm-offsets.c +@@ -7,6 +7,7 @@ + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ ++#define COMPILE_OFFSETS + + #include <linux/init.h> + #include <linux/stddef.h> +diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c +index cb1045ebab0621..22c99a2cd5707b 100644 +--- a/arch/mips/kernel/asm-offsets.c ++++ b/arch/mips/kernel/asm-offsets.c +@@ -9,6 +9,8 @@ + * Kevin Kissell, [email protected] and Carsten Langgaard, [email protected] + * Copyright (C) 2000 MIPS Technologies, Inc. + */ ++#define COMPILE_OFFSETS ++ + #include <linux/compat.h> + #include <linux/types.h> + #include <linux/sched.h> +diff --git a/arch/nios2/kernel/asm-offsets.c b/arch/nios2/kernel/asm-offsets.c +index e3d9b7b6fb48aa..88190b503ce5de 100644 +--- a/arch/nios2/kernel/asm-offsets.c ++++ b/arch/nios2/kernel/asm-offsets.c +@@ -2,6 +2,7 @@ + /* + * Copyright (C) 2011 Tobias Klauser <[email protected]> + */ ++#define COMPILE_OFFSETS + + #include <linux/stddef.h> + #include <linux/sched.h> +diff --git a/arch/openrisc/kernel/asm-offsets.c b/arch/openrisc/kernel/asm-offsets.c +index 710651d5aaae10..3cc826f2216b10 100644 +--- a/arch/openrisc/kernel/asm-offsets.c ++++ b/arch/openrisc/kernel/asm-offsets.c +@@ -18,6 +18,7 @@ + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ ++#define COMPILE_OFFSETS + + #include <linux/signal.h> + #include <linux/sched.h> +diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c +index 757816a7bd4b28..9abfe65492c65e 100644 +--- a/arch/parisc/kernel/asm-offsets.c ++++ b/arch/parisc/kernel/asm-offsets.c +@@ -13,6 +13,7 @@ + * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> + * Copyright (C) 2003 James Bottomley <jejb at parisc-linux.org> + */ ++#define COMPILE_OFFSETS + + #include <linux/types.h> + #include <linux/sched.h> +diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c +index 2affd30468bc4c..e2cee2f2ededdb 100644 +--- a/arch/powerpc/kernel/asm-offsets.c ++++ b/arch/powerpc/kernel/asm-offsets.c +@@ -8,6 +8,7 @@ + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ ++#define COMPILE_OFFSETS + + #include <linux/compat.h> + #include <linux/signal.h> +diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c +index 6a992cba2f2876..e4589457e6085d 100644 +--- a/arch/riscv/kernel/asm-offsets.c ++++ b/arch/riscv/kernel/asm-offsets.c +@@ -3,6 +3,7 @@ + * Copyright (C) 2012 Regents of the University of California + * Copyright (C) 2017 SiFive + */ ++#define COMPILE_OFFSETS + + #include <linux/kbuild.h> + #include <linux/mm.h> +diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c +index fa5f6885c74aa1..73a989dcfe2082 100644 +--- a/arch/s390/kernel/asm-offsets.c ++++ b/arch/s390/kernel/asm-offsets.c +@@ -4,6 +4,7 @@ + * This code generates raw asm output which is post-processed to extract + * and format the required data. + */ ++#define COMPILE_OFFSETS + + #define ASM_OFFSETS_C + +diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c +index a0322e8328456e..429b6a76314684 100644 +--- a/arch/sh/kernel/asm-offsets.c ++++ b/arch/sh/kernel/asm-offsets.c +@@ -8,6 +8,7 @@ + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ ++#define COMPILE_OFFSETS + + #include <linux/stddef.h> + #include <linux/types.h> +diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c +index 5784f2df489a4d..f1e27a7f800f41 100644 +--- a/arch/sparc/kernel/asm-offsets.c ++++ b/arch/sparc/kernel/asm-offsets.c +@@ -10,6 +10,7 @@ + * + * On sparc, thread_info data is static and TI_XXX offsets are computed by hand. + */ ++#define COMPILE_OFFSETS + + #include <linux/sched.h> + #include <linux/mm_types.h> +diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c +index 1fb12235ab9c84..a69873aa697f4f 100644 +--- a/arch/um/kernel/asm-offsets.c ++++ b/arch/um/kernel/asm-offsets.c +@@ -1 +1,3 @@ ++#define COMPILE_OFFSETS ++ + #include <sysdep/kernel-offsets.h> +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index 315926ccea0fa3..ef1d3a5024ed4b 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -1185,8 +1185,10 @@ static void __init retbleed_select_mitigation(void) + retbleed_mitigation = RETBLEED_MITIGATION_EIBRS; + break; + default: +- if (retbleed_mitigation != RETBLEED_MITIGATION_STUFF) ++ if (retbleed_mitigation != RETBLEED_MITIGATION_STUFF) { + pr_err(RETBLEED_INTEL_MSG); ++ retbleed_mitigation = RETBLEED_MITIGATION_NONE; ++ } + } + } + +@@ -1592,7 +1594,7 @@ spectre_v2_user_select_mitigation(void) + static const char * const spectre_v2_strings[] = { + [SPECTRE_V2_NONE] = "Vulnerable", + [SPECTRE_V2_RETPOLINE] = "Mitigation: Retpolines", +- [SPECTRE_V2_LFENCE] = "Mitigation: LFENCE", ++ [SPECTRE_V2_LFENCE] = "Vulnerable: LFENCE", + [SPECTRE_V2_EIBRS] = "Mitigation: Enhanced / Automatic IBRS", + [SPECTRE_V2_EIBRS_LFENCE] = "Mitigation: Enhanced / Automatic IBRS + LFENCE", + [SPECTRE_V2_EIBRS_RETPOLINE] = "Mitigation: Enhanced / Automatic IBRS + Retpolines", +@@ -3220,9 +3222,6 @@ static const char *spectre_bhi_state(void) + + static ssize_t spectre_v2_show_state(char *buf) + { +- if (spectre_v2_enabled == SPECTRE_V2_LFENCE) +- return sysfs_emit(buf, "Vulnerable: LFENCE\n"); +- + if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled()) + return sysfs_emit(buf, "Vulnerable: eIBRS with unprivileged eBPF\n"); + +diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c +index da38de20ae598b..cfbced95e944a4 100644 +--- a/arch/xtensa/kernel/asm-offsets.c ++++ b/arch/xtensa/kernel/asm-offsets.c +@@ -11,6 +11,7 @@ + * + * Chris Zankel <[email protected]> + */ ++#define COMPILE_OFFSETS + + #include <asm/processor.h> + #include <asm/coprocessor.h> +diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c +index 15f63452a9bec8..b01436d9ddaed8 100644 +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -306,6 +306,14 @@ DEVICE_CHANNEL(ch10_dimm_label, S_IRUGO | S_IWUSR, + channel_dimm_label_show, channel_dimm_label_store, 10); + DEVICE_CHANNEL(ch11_dimm_label, S_IRUGO | S_IWUSR, + channel_dimm_label_show, channel_dimm_label_store, 11); ++DEVICE_CHANNEL(ch12_dimm_label, S_IRUGO | S_IWUSR, ++ channel_dimm_label_show, channel_dimm_label_store, 12); ++DEVICE_CHANNEL(ch13_dimm_label, S_IRUGO | S_IWUSR, ++ channel_dimm_label_show, channel_dimm_label_store, 13); ++DEVICE_CHANNEL(ch14_dimm_label, S_IRUGO | S_IWUSR, ++ channel_dimm_label_show, channel_dimm_label_store, 14); ++DEVICE_CHANNEL(ch15_dimm_label, S_IRUGO | S_IWUSR, ++ channel_dimm_label_show, channel_dimm_label_store, 15); + + /* Total possible dynamic DIMM Label attribute file table */ + static struct attribute *dynamic_csrow_dimm_attr[] = { +@@ -321,6 +329,10 @@ static struct attribute *dynamic_csrow_dimm_attr[] = { + &dev_attr_legacy_ch9_dimm_label.attr.attr, + &dev_attr_legacy_ch10_dimm_label.attr.attr, + &dev_attr_legacy_ch11_dimm_label.attr.attr, ++ &dev_attr_legacy_ch12_dimm_label.attr.attr, ++ &dev_attr_legacy_ch13_dimm_label.attr.attr, ++ &dev_attr_legacy_ch14_dimm_label.attr.attr, ++ &dev_attr_legacy_ch15_dimm_label.attr.attr, + NULL + }; + +@@ -349,6 +361,14 @@ DEVICE_CHANNEL(ch10_ce_count, S_IRUGO, + channel_ce_count_show, NULL, 10); + DEVICE_CHANNEL(ch11_ce_count, S_IRUGO, + channel_ce_count_show, NULL, 11); ++DEVICE_CHANNEL(ch12_ce_count, S_IRUGO, ++ channel_ce_count_show, NULL, 12); ++DEVICE_CHANNEL(ch13_ce_count, S_IRUGO, ++ channel_ce_count_show, NULL, 13); ++DEVICE_CHANNEL(ch14_ce_count, S_IRUGO, ++ channel_ce_count_show, NULL, 14); ++DEVICE_CHANNEL(ch15_ce_count, S_IRUGO, ++ channel_ce_count_show, NULL, 15); + + /* Total possible dynamic ce_count attribute file table */ + static struct attribute *dynamic_csrow_ce_count_attr[] = { +@@ -364,6 +384,10 @@ static struct attribute *dynamic_csrow_ce_count_attr[] = { + &dev_attr_legacy_ch9_ce_count.attr.attr, + &dev_attr_legacy_ch10_ce_count.attr.attr, + &dev_attr_legacy_ch11_ce_count.attr.attr, ++ &dev_attr_legacy_ch12_ce_count.attr.attr, ++ &dev_attr_legacy_ch13_ce_count.attr.attr, ++ &dev_attr_legacy_ch14_ce_count.attr.attr, ++ &dev_attr_legacy_ch15_ce_count.attr.attr, + NULL + }; + +diff --git a/drivers/gpio/gpio-idio-16.c b/drivers/gpio/gpio-idio-16.c +index 53b1eb876a1257..e978fd0898aaa6 100644 +--- a/drivers/gpio/gpio-idio-16.c ++++ b/drivers/gpio/gpio-idio-16.c +@@ -3,6 +3,7 @@ + * GPIO library for the ACCES IDIO-16 family + * Copyright (C) 2022 William Breathitt Gray + */ ++#include <linux/bitmap.h> + #include <linux/bits.h> + #include <linux/device.h> + #include <linux/err.h> +@@ -106,6 +107,7 @@ int devm_idio_16_regmap_register(struct device *const dev, + struct idio_16_data *data; + struct regmap_irq_chip *chip; + struct regmap_irq_chip_data *chip_data; ++ DECLARE_BITMAP(fixed_direction_output, IDIO_16_NGPIO); + + if (!config->parent) + return -EINVAL; +@@ -163,6 +165,9 @@ int devm_idio_16_regmap_register(struct device *const dev, + gpio_config.irq_domain = regmap_irq_get_domain(chip_data); + gpio_config.reg_mask_xlate = idio_16_reg_mask_xlate; + ++ bitmap_from_u64(fixed_direction_output, GENMASK_U64(15, 0)); ++ gpio_config.fixed_direction_output = fixed_direction_output; ++ + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); + } + EXPORT_SYMBOL_GPL(devm_idio_16_regmap_register); +diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c +index c08c8e528867ee..fd986afa7db5f0 100644 +--- a/drivers/gpio/gpio-regmap.c ++++ b/drivers/gpio/gpio-regmap.c +@@ -29,6 +29,12 @@ struct gpio_regmap { + unsigned int reg_clr_base; + unsigned int reg_dir_in_base; + unsigned int reg_dir_out_base; ++ unsigned long *fixed_direction_output; ++ ++#ifdef CONFIG_REGMAP_IRQ ++ int regmap_irq_line; ++ struct regmap_irq_chip_data *irq_chip_data; ++#endif + + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, + unsigned int offset, unsigned int *reg, +@@ -117,6 +123,13 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip, + unsigned int base, val, reg, mask; + int invert, ret; + ++ if (gpio->fixed_direction_output) { ++ if (test_bit(offset, gpio->fixed_direction_output)) ++ return GPIO_LINE_DIRECTION_OUT; ++ else ++ return GPIO_LINE_DIRECTION_IN; ++ } ++ + if (gpio->reg_dat_base && !gpio->reg_set_base) + return GPIO_LINE_DIRECTION_IN; + if (gpio->reg_set_base && !gpio->reg_dat_base) +@@ -203,6 +216,7 @@ EXPORT_SYMBOL_GPL(gpio_regmap_get_drvdata); + */ + struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config) + { ++ struct irq_domain *irq_domain; + struct gpio_regmap *gpio; + struct gpio_chip *chip; + int ret; +@@ -274,12 +288,37 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config + chip->direction_output = gpio_regmap_direction_output; + } + ++ if (config->fixed_direction_output) { ++ gpio->fixed_direction_output = bitmap_alloc(chip->ngpio, ++ GFP_KERNEL); ++ if (!gpio->fixed_direction_output) { ++ ret = -ENOMEM; ++ goto err_free_gpio; ++ } ++ bitmap_copy(gpio->fixed_direction_output, ++ config->fixed_direction_output, chip->ngpio); ++ } ++ + ret = gpiochip_add_data(chip, gpio); + if (ret < 0) +- goto err_free_gpio; ++ goto err_free_bitmap; ++ ++#ifdef CONFIG_REGMAP_IRQ ++ if (config->regmap_irq_chip) { ++ gpio->regmap_irq_line = config->regmap_irq_line; ++ ret = regmap_add_irq_chip_fwnode(dev_fwnode(config->parent), config->regmap, ++ config->regmap_irq_line, config->regmap_irq_flags, ++ 0, config->regmap_irq_chip, &gpio->irq_chip_data); ++ if (ret) ++ goto err_free_bitmap; + +- if (config->irq_domain) { +- ret = gpiochip_irqchip_add_domain(chip, config->irq_domain); ++ irq_domain = regmap_irq_get_domain(gpio->irq_chip_data); ++ } else ++#endif ++ irq_domain = config->irq_domain; ++ ++ if (irq_domain) { ++ ret = gpiochip_irqchip_add_domain(chip, irq_domain); + if (ret) + goto err_remove_gpiochip; + } +@@ -288,6 +327,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config + + err_remove_gpiochip: + gpiochip_remove(chip); ++err_free_bitmap: ++ bitmap_free(gpio->fixed_direction_output); + err_free_gpio: + kfree(gpio); + return ERR_PTR(ret); +@@ -300,7 +341,13 @@ EXPORT_SYMBOL_GPL(gpio_regmap_register); + */ + void gpio_regmap_unregister(struct gpio_regmap *gpio) + { ++#ifdef CONFIG_REGMAP_IRQ ++ if (gpio->irq_chip_data) ++ regmap_del_irq_chip(gpio->regmap_irq_line, gpio->irq_chip_data); ++#endif ++ + gpiochip_remove(&gpio->gpio_chip); ++ bitmap_free(gpio->fixed_direction_output); + kfree(gpio); + } + EXPORT_SYMBOL_GPL(gpio_regmap_unregister); +diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c +index 66a88bba8f15b8..b5f9a40f4a8196 100644 +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -329,8 +329,9 @@ struct sc16is7xx_one { + struct kthread_work reg_work; + struct kthread_delayed_work ms_work; + struct sc16is7xx_one_config config; +- bool irda_mode; + unsigned int old_mctrl; ++ u8 old_lcr; /* Value before EFR access. */ ++ bool irda_mode; + }; + + struct sc16is7xx_port { +@@ -355,10 +356,6 @@ static struct uart_driver sc16is7xx_uart = { + .nr = SC16IS7XX_MAX_DEVS, + }; + +-static void sc16is7xx_ier_set(struct uart_port *port, u8 bit); +-static void sc16is7xx_stop_tx(struct uart_port *port); +- +-#define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e))) + #define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e))) + + static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg) +@@ -416,6 +413,85 @@ static void sc16is7xx_power(struct uart_port *port, int on) + on ? 0 : SC16IS7XX_IER_SLEEP_BIT); + } + ++/* ++ * In an amazing feat of design, the Enhanced Features Register (EFR) ++ * shares the address of the Interrupt Identification Register (IIR). ++ * Access to EFR is switched on by writing a magic value (0xbf) to the ++ * Line Control Register (LCR). Any interrupt firing during this time will ++ * see the EFR where it expects the IIR to be, leading to ++ * "Unexpected interrupt" messages. ++ * ++ * Prevent this possibility by claiming a mutex while accessing the EFR, ++ * and claiming the same mutex from within the interrupt handler. This is ++ * similar to disabling the interrupt, but that doesn't work because the ++ * bulk of the interrupt processing is run as a workqueue job in thread ++ * context. ++ */ ++static void sc16is7xx_efr_lock(struct uart_port *port) ++{ ++ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); ++ ++ mutex_lock(&one->efr_lock); ++ ++ /* Backup content of LCR. */ ++ one->old_lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); ++ ++ /* Enable access to Enhanced register set */ ++ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_CONF_MODE_B); ++ ++ /* Disable cache updates when writing to EFR registers */ ++ regcache_cache_bypass(one->regmap, true); ++} ++ ++static void sc16is7xx_efr_unlock(struct uart_port *port) ++{ ++ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); ++ ++ /* Re-enable cache updates when writing to normal registers */ ++ regcache_cache_bypass(one->regmap, false); ++ ++ /* Restore original content of LCR */ ++ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, one->old_lcr); ++ ++ mutex_unlock(&one->efr_lock); ++} ++ ++static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit) ++{ ++ struct sc16is7xx_port *s = dev_get_drvdata(port->dev); ++ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); ++ ++ lockdep_assert_held_once(&port->lock); ++ ++ one->config.flags |= SC16IS7XX_RECONF_IER; ++ one->config.ier_mask |= bit; ++ one->config.ier_val &= ~bit; ++ kthread_queue_work(&s->kworker, &one->reg_work); ++} ++ ++static void sc16is7xx_ier_set(struct uart_port *port, u8 bit) ++{ ++ struct sc16is7xx_port *s = dev_get_drvdata(port->dev); ++ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); ++ ++ lockdep_assert_held_once(&port->lock); ++ ++ one->config.flags |= SC16IS7XX_RECONF_IER; ++ one->config.ier_mask |= bit; ++ one->config.ier_val |= bit; ++ kthread_queue_work(&s->kworker, &one->reg_work); ++} ++ ++static void sc16is7xx_stop_tx(struct uart_port *port) ++{ ++ sc16is7xx_ier_clear(port, SC16IS7XX_IER_THRI_BIT); ++} ++ ++static void sc16is7xx_stop_rx(struct uart_port *port) ++{ ++ sc16is7xx_ier_clear(port, SC16IS7XX_IER_RDI_BIT); ++} ++ + static const struct sc16is7xx_devtype sc16is74x_devtype = { + .name = "SC16IS74X", + .nr_gpio = 0, +@@ -506,40 +582,6 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) + div /= prescaler; + } + +- /* In an amazing feat of design, the Enhanced Features Register shares +- * the address of the Interrupt Identification Register, and is +- * switched in by writing a magic value (0xbf) to the Line Control +- * Register. Any interrupt firing during this time will see the EFR +- * where it expects the IIR to be, leading to "Unexpected interrupt" +- * messages. +- * +- * Prevent this possibility by claiming a mutex while accessing the +- * EFR, and claiming the same mutex from within the interrupt handler. +- * This is similar to disabling the interrupt, but that doesn't work +- * because the bulk of the interrupt processing is run as a workqueue +- * job in thread context. +- */ +- mutex_lock(&one->efr_lock); +- +- lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); +- +- /* Open the LCR divisors for configuration */ +- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, +- SC16IS7XX_LCR_CONF_MODE_B); +- +- /* Enable enhanced features */ +- regcache_cache_bypass(one->regmap, true); +- sc16is7xx_port_update(port, SC16IS7XX_EFR_REG, +- SC16IS7XX_EFR_ENABLE_BIT, +- SC16IS7XX_EFR_ENABLE_BIT); +- +- regcache_cache_bypass(one->regmap, false); +- +- /* Put LCR back to the normal mode */ +- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); +- +- mutex_unlock(&one->efr_lock); +- + /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */ + sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, + SC16IS7XX_MCR_CLKSEL_BIT, +@@ -547,7 +589,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) + + mutex_lock(&one->efr_lock); + +- /* Open the LCR divisors for configuration */ ++ /* Backup LCR and access special register set (DLL/DLH) */ ++ lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); + sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, + SC16IS7XX_LCR_CONF_MODE_A); + +@@ -557,7 +600,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) + sc16is7xx_port_write(port, SC16IS7XX_DLL_REG, div % 256); + regcache_cache_bypass(one->regmap, false); + +- /* Put LCR back to the normal mode */ ++ /* Restore LCR and access to general register set */ + sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); + + mutex_unlock(&one->efr_lock); +@@ -889,42 +932,6 @@ static void sc16is7xx_reg_proc(struct kthread_work *ws) + sc16is7xx_reconf_rs485(&one->port); + } + +-static void sc16is7xx_ier_clear(struct uart_port *port, u8 bit) +-{ +- struct sc16is7xx_port *s = dev_get_drvdata(port->dev); +- struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); +- +- lockdep_assert_held_once(&port->lock); +- +- one->config.flags |= SC16IS7XX_RECONF_IER; +- one->config.ier_mask |= bit; +- one->config.ier_val &= ~bit; +- kthread_queue_work(&s->kworker, &one->reg_work); +-} +- +-static void sc16is7xx_ier_set(struct uart_port *port, u8 bit) +-{ +- struct sc16is7xx_port *s = dev_get_drvdata(port->dev); +- struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); +- +- lockdep_assert_held_once(&port->lock); +- +- one->config.flags |= SC16IS7XX_RECONF_IER; +- one->config.ier_mask |= bit; +- one->config.ier_val |= bit; +- kthread_queue_work(&s->kworker, &one->reg_work); +-} +- +-static void sc16is7xx_stop_tx(struct uart_port *port) +-{ +- sc16is7xx_ier_clear(port, SC16IS7XX_IER_THRI_BIT); +-} +- +-static void sc16is7xx_stop_rx(struct uart_port *port) +-{ +- sc16is7xx_ier_clear(port, SC16IS7XX_IER_RDI_BIT); +-} +- + static void sc16is7xx_ms_proc(struct kthread_work *ws) + { + struct sc16is7xx_one *one = to_sc16is7xx_one(ws, ms_work.work); +@@ -1074,17 +1081,7 @@ static void sc16is7xx_set_termios(struct uart_port *port, + if (!(termios->c_cflag & CREAD)) + port->ignore_status_mask |= SC16IS7XX_LSR_BRK_ERROR_MASK; + +- /* As above, claim the mutex while accessing the EFR. */ +- mutex_lock(&one->efr_lock); +- +- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, +- SC16IS7XX_LCR_CONF_MODE_B); +- + /* Configure flow control */ +- regcache_cache_bypass(one->regmap, true); +- sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]); +- sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]); +- + port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); + if (termios->c_cflag & CRTSCTS) { + flow |= SC16IS7XX_EFR_AUTOCTS_BIT | +@@ -1096,16 +1093,16 @@ static void sc16is7xx_set_termios(struct uart_port *port, + if (termios->c_iflag & IXOFF) + flow |= SC16IS7XX_EFR_SWFLOW1_BIT; + +- sc16is7xx_port_update(port, +- SC16IS7XX_EFR_REG, +- SC16IS7XX_EFR_FLOWCTRL_BITS, +- flow); +- regcache_cache_bypass(one->regmap, false); +- + /* Update LCR register */ + sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); + +- mutex_unlock(&one->efr_lock); ++ /* Update EFR registers */ ++ sc16is7xx_efr_lock(port); ++ sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]); ++ sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]); ++ sc16is7xx_port_update(port, SC16IS7XX_EFR_REG, ++ SC16IS7XX_EFR_FLOWCTRL_BITS, flow); ++ sc16is7xx_efr_unlock(port); + + /* Get baud rate generator configuration */ + baud = uart_get_baud_rate(port, termios, old, +diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c +index bfd437269800cf..4d975b26a185cf 100644 +--- a/drivers/usb/host/xhci-dbgcap.c ++++ b/drivers/usb/host/xhci-dbgcap.c +@@ -665,7 +665,8 @@ static int xhci_dbc_start(struct xhci_dbc *dbc) + return ret; + } + +- return mod_delayed_work(system_wq, &dbc->event_work, 1); ++ return mod_delayed_work(system_wq, &dbc->event_work, ++ msecs_to_jiffies(dbc->poll_interval)); + } + + static void xhci_dbc_stop(struct xhci_dbc *dbc) +@@ -854,6 +855,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) + { + dma_addr_t deq; + union xhci_trb *evt; ++ enum evtreturn ret = EVT_DONE; + u32 ctrl, portsc; + bool update_erdp = false; + +@@ -878,7 +880,8 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) + dev_info(dbc->dev, "DbC configured\n"); + portsc = readl(&dbc->regs->portsc); + writel(portsc, &dbc->regs->portsc); +- return EVT_GSER; ++ ret = EVT_GSER; ++ break; + } + + return EVT_DONE; +@@ -938,6 +941,8 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) + break; + case TRB_TYPE(TRB_TRANSFER): + dbc_handle_xfer_event(dbc, evt); ++ if (ret != EVT_GSER) ++ ret = EVT_XFER_DONE; + break; + default: + break; +@@ -956,7 +961,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) + lo_hi_writeq(deq, &dbc->regs->erdp); + } + +- return EVT_DONE; ++ return ret; + } + + static void xhci_dbc_handle_events(struct work_struct *work) +@@ -964,8 +969,11 @@ static void xhci_dbc_handle_events(struct work_struct *work) + enum evtreturn evtr; + struct xhci_dbc *dbc; + unsigned long flags; ++ unsigned int poll_interval; ++ unsigned long busypoll_timelimit; + + dbc = container_of(to_delayed_work(work), struct xhci_dbc, event_work); ++ poll_interval = dbc->poll_interval; + + spin_lock_irqsave(&dbc->lock, flags); + evtr = xhci_dbc_do_handle_events(dbc); +@@ -981,13 +989,28 @@ static void xhci_dbc_handle_events(struct work_struct *work) + dbc->driver->disconnect(dbc); + break; + case EVT_DONE: ++ /* ++ * Set fast poll rate if there are pending out transfers, or ++ * a transfer was recently processed ++ */ ++ busypoll_timelimit = dbc->xfer_timestamp + ++ msecs_to_jiffies(DBC_XFER_INACTIVITY_TIMEOUT); ++ ++ if (!list_empty(&dbc->eps[BULK_OUT].list_pending) || ++ time_is_after_jiffies(busypoll_timelimit)) ++ poll_interval = 0; ++ break; ++ case EVT_XFER_DONE: ++ dbc->xfer_timestamp = jiffies; ++ poll_interval = 0; + break; + default: + dev_info(dbc->dev, "stop handling dbc events\n"); + return; + } + +- mod_delayed_work(system_wq, &dbc->event_work, 1); ++ mod_delayed_work(system_wq, &dbc->event_work, ++ msecs_to_jiffies(poll_interval)); + } + + static ssize_t dbc_show(struct device *dev, +@@ -1206,11 +1229,48 @@ static ssize_t dbc_bInterfaceProtocol_store(struct device *dev, + return size; + } + ++static ssize_t dbc_poll_interval_ms_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct xhci_dbc *dbc; ++ struct xhci_hcd *xhci; ++ ++ xhci = hcd_to_xhci(dev_get_drvdata(dev)); ++ dbc = xhci->dbc; ++ ++ return sysfs_emit(buf, "%u\n", dbc->poll_interval); ++} ++ ++static ssize_t dbc_poll_interval_ms_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct xhci_dbc *dbc; ++ struct xhci_hcd *xhci; ++ u32 value; ++ int ret; ++ ++ ret = kstrtou32(buf, 0, &value); ++ if (ret || value > DBC_POLL_INTERVAL_MAX) ++ return -EINVAL; ++ ++ xhci = hcd_to_xhci(dev_get_drvdata(dev)); ++ dbc = xhci->dbc; ++ ++ dbc->poll_interval = value; ++ ++ mod_delayed_work(system_wq, &dbc->event_work, 0); ++ ++ return size; ++} ++ + static DEVICE_ATTR_RW(dbc); + static DEVICE_ATTR_RW(dbc_idVendor); + static DEVICE_ATTR_RW(dbc_idProduct); + static DEVICE_ATTR_RW(dbc_bcdDevice); + static DEVICE_ATTR_RW(dbc_bInterfaceProtocol); ++static DEVICE_ATTR_RW(dbc_poll_interval_ms); + + static struct attribute *dbc_dev_attributes[] = { + &dev_attr_dbc.attr, +@@ -1218,6 +1278,7 @@ static struct attribute *dbc_dev_attributes[] = { + &dev_attr_dbc_idProduct.attr, + &dev_attr_dbc_bcdDevice.attr, + &dev_attr_dbc_bInterfaceProtocol.attr, ++ &dev_attr_dbc_poll_interval_ms.attr, + NULL + }; + +@@ -1242,6 +1303,7 @@ xhci_alloc_dbc(struct device *dev, void __iomem *base, const struct dbc_driver * + dbc->idVendor = DBC_VENDOR_ID; + dbc->bcdDevice = DBC_DEVICE_REV; + dbc->bInterfaceProtocol = DBC_PROTOCOL; ++ dbc->poll_interval = DBC_POLL_INTERVAL_DEFAULT; + + if (readl(&dbc->regs->control) & DBC_CTRL_DBC_ENABLE) + goto err; +diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h +index 2de0dc49a3e9f7..1fab3eb9c831d3 100644 +--- a/drivers/usb/host/xhci-dbgcap.h ++++ b/drivers/usb/host/xhci-dbgcap.h +@@ -93,7 +93,9 @@ struct dbc_ep { + + #define DBC_QUEUE_SIZE 16 + #define DBC_WRITE_BUF_SIZE 8192 +- ++#define DBC_POLL_INTERVAL_DEFAULT 64 /* milliseconds */ ++#define DBC_POLL_INTERVAL_MAX 5000 /* milliseconds */ ++#define DBC_XFER_INACTIVITY_TIMEOUT 10 /* milliseconds */ + /* + * Private structure for DbC hardware state: + */ +@@ -139,6 +141,8 @@ struct xhci_dbc { + + enum dbc_state state; + struct delayed_work event_work; ++ unsigned int poll_interval; /* ms */ ++ unsigned long xfer_timestamp; + unsigned resume_required:1; + struct dbc_ep eps[2]; + +@@ -184,6 +188,7 @@ struct dbc_request { + enum evtreturn { + EVT_ERR = -1, + EVT_DONE, ++ EVT_XFER_DONE, + EVT_GSER, + EVT_DISC, + }; +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index bb5f7911d473cb..7ad1734cbbfc91 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -2080,10 +2080,10 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info, + + /* returns with log_tree_root freed on success */ + ret = btrfs_recover_log_trees(log_tree_root); ++ btrfs_put_root(log_tree_root); + if (ret) { + btrfs_handle_fs_error(fs_info, ret, + "Failed to recover log tree"); +- btrfs_put_root(log_tree_root); + return ret; + } + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 8248113eb067fa..5e3d1a87b7e9da 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4175,7 +4175,8 @@ static int prepare_allocation_clustered(struct btrfs_fs_info *fs_info, + } + + static int prepare_allocation_zoned(struct btrfs_fs_info *fs_info, +- struct find_free_extent_ctl *ffe_ctl) ++ struct find_free_extent_ctl *ffe_ctl, ++ struct btrfs_space_info *space_info) + { + if (ffe_ctl->for_treelog) { + spin_lock(&fs_info->treelog_bg_lock); +@@ -4199,6 +4200,7 @@ static int prepare_allocation_zoned(struct btrfs_fs_info *fs_info, + u64 avail = block_group->zone_capacity - block_group->alloc_offset; + + if (block_group_bits(block_group, ffe_ctl->flags) && ++ block_group->space_info == space_info && + avail >= ffe_ctl->num_bytes) { + ffe_ctl->hint_byte = block_group->start; + break; +@@ -4220,7 +4222,7 @@ static int prepare_allocation(struct btrfs_fs_info *fs_info, + return prepare_allocation_clustered(fs_info, ffe_ctl, + space_info, ins); + case BTRFS_EXTENT_ALLOC_ZONED: +- return prepare_allocation_zoned(fs_info, ffe_ctl); ++ return prepare_allocation_zoned(fs_info, ffe_ctl, space_info); + default: + BUG(); + } +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index ee5ffeab85bb78..b1be3e0fe72823 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3051,9 +3051,10 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent) + goto out; + } + +- if (btrfs_is_zoned(fs_info)) +- btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr, +- ordered_extent->disk_num_bytes); ++ ret = btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr, ++ ordered_extent->disk_num_bytes); ++ if (ret) ++ goto out; + + if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered_extent->flags)) { + truncated = true; +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index 7632d652a1257d..4a5a5ee360e579 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -1271,8 +1271,7 @@ static void scrub_throttle_dev_io(struct scrub_ctx *sctx, struct btrfs_device *d + * Slice is divided into intervals when the IO is submitted, adjust by + * bwlimit and maximum of 64 intervals. + */ +- div = max_t(u32, 1, (u32)(bwlimit / (16 * 1024 * 1024))); +- div = min_t(u32, 64, div); ++ div = clamp(bwlimit / (16 * 1024 * 1024), 1, 64); + + /* Start new epoch, set deadline */ + now = ktime_get(); +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 3989cb19cdae70..20add63421b3d8 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1796,7 +1796,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, + } + /* see comments in should_cow_block() */ + set_bit(BTRFS_ROOT_FORCE_COW, &root->state); +- smp_wmb(); ++ smp_mb__after_atomic(); + + btrfs_set_root_node(new_root_item, tmp); + /* record when the snapshot was created in key.offset */ +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 4b53e19f7520fe..5512991b24faa8 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -2493,15 +2493,13 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, + int i; + int ret; + ++ if (level != 0) ++ return 0; ++ + ret = btrfs_read_extent_buffer(eb, &check); + if (ret) + return ret; + +- level = btrfs_header_level(eb); +- +- if (level != 0) +- return 0; +- + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; +@@ -7422,7 +7420,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) + + log_root_tree->log_root = NULL; + clear_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags); +- btrfs_put_root(log_root_tree); + + return 0; + error: +diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c +index 3622ba1d8e09f4..6e8b8c46ba18f6 100644 +--- a/fs/btrfs/zoned.c ++++ b/fs/btrfs/zoned.c +@@ -2263,16 +2263,17 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags) + return ret; + } + +-void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 length) ++int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 length) + { + struct btrfs_block_group *block_group; + u64 min_alloc_bytes; + + if (!btrfs_is_zoned(fs_info)) +- return; ++ return 0; + + block_group = btrfs_lookup_block_group(fs_info, logical); +- ASSERT(block_group); ++ if (WARN_ON_ONCE(!block_group)) ++ return -ENOENT; + + /* No MIXED_BG on zoned btrfs. */ + if (block_group->flags & BTRFS_BLOCK_GROUP_DATA) +@@ -2289,6 +2290,7 @@ void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 len + + out: + btrfs_put_block_group(block_group); ++ return 0; + } + + static void btrfs_zone_finish_endio_workfn(struct work_struct *work) +diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h +index 448955641d1143..c18f31d3dc25f6 100644 +--- a/fs/btrfs/zoned.h ++++ b/fs/btrfs/zoned.h +@@ -71,7 +71,7 @@ int btrfs_sync_zone_write_pointer(struct btrfs_device *tgt_dev, u64 logical, + bool btrfs_zone_activate(struct btrfs_block_group *block_group); + int btrfs_zone_finish(struct btrfs_block_group *block_group); + bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags); +-void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, ++int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, + u64 length); + void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, + struct extent_buffer *eb); +@@ -227,8 +227,11 @@ static inline bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, + return true; + } + +-static inline void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, +- u64 logical, u64 length) { } ++static inline int btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, ++ u64 logical, u64 length) ++{ ++ return 0; ++} + + static inline void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, + struct extent_buffer *eb) { } +diff --git a/include/linux/audit.h b/include/linux/audit.h +index 335e1ba5a23271..7ca75f8873799d 100644 +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -526,7 +526,7 @@ static inline void audit_log_kern_module(const char *name) + + static inline void audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar) + { +- if (!audit_dummy_context()) ++ if (audit_enabled) + __audit_fanotify(response, friar); + } + +diff --git a/include/linux/bitops.h b/include/linux/bitops.h +index f7f5a783da2aa8..b2342eebc8d226 100644 +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -15,7 +15,6 @@ + # define aligned_byte_mask(n) (~0xffUL << (BITS_PER_LONG - 8 - 8*(n))) + #endif + +-#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) + #define BITS_TO_LONGS(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long)) + #define BITS_TO_U64(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64)) + #define BITS_TO_U32(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32)) +diff --git a/include/linux/bits.h b/include/linux/bits.h +index 7c0cf5031abe87..09e167bc453046 100644 +--- a/include/linux/bits.h ++++ b/include/linux/bits.h +@@ -11,6 +11,7 @@ + #define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) + #define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) + #define BITS_PER_BYTE 8 ++#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) + + /* + * Create a contiguous bitmask starting at bit position @l and ending at +@@ -18,17 +19,50 @@ + * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ + #if !defined(__ASSEMBLY__) ++ ++/* ++ * Missing asm support ++ * ++ * GENMASK_U*() depend on BITS_PER_TYPE() which relies on sizeof(), ++ * something not available in asm. Nevertheless, fixed width integers is a C ++ * concept. Assembly code can rely on the long and long long versions instead. ++ */ ++ + #include <linux/build_bug.h> ++#include <linux/overflow.h> + #define GENMASK_INPUT_CHECK(h, l) \ + (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \ + __is_constexpr((l) > (h)), (l) > (h), 0))) +-#else ++ ++/* ++ * Generate a mask for the specified type @t. Additional checks are made to ++ * guarantee the value returned fits in that type, relying on ++ * -Wshift-count-overflow compiler check to detect incompatible arguments. ++ * For example, all these create build errors or warnings: ++ * ++ * - GENMASK(15, 20): wrong argument order ++ * - GENMASK(72, 15): doesn't fit unsigned long ++ * - GENMASK_U32(33, 15): doesn't fit in a u32 ++ */ ++#define GENMASK_TYPE(t, h, l) \ ++ ((t)(GENMASK_INPUT_CHECK(h, l) + \ ++ (type_max(t) << (l) & \ ++ type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h))))) ++ ++#define GENMASK_U8(h, l) GENMASK_TYPE(u8, h, l) ++#define GENMASK_U16(h, l) GENMASK_TYPE(u16, h, l) ++#define GENMASK_U32(h, l) GENMASK_TYPE(u32, h, l) ++#define GENMASK_U64(h, l) GENMASK_TYPE(u64, h, l) ++ ++#else /* defined(__ASSEMBLY__) */ ++ + /* + * BUILD_BUG_ON_ZERO is not available in h files included from asm files, + * disable the input check if that is the case. + */ + #define GENMASK_INPUT_CHECK(h, l) 0 +-#endif ++ ++#endif /* !defined(__ASSEMBLY__) */ + + #define __GENMASK(h, l) \ + (((~UL(0)) - (UL(1) << (l)) + 1) & \ +diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h +index a9f7b7faf57b0d..cf55202aaec264 100644 +--- a/include/linux/gpio/regmap.h ++++ b/include/linux/gpio/regmap.h +@@ -37,9 +37,18 @@ struct regmap; + * offset to a register/bitmask pair. If not + * given the default gpio_regmap_simple_xlate() + * is used. ++ * @fixed_direction_output: ++ * (Optional) Bitmap representing the fixed direction of ++ * the GPIO lines. Useful when there are GPIO lines with a ++ * fixed direction mixed together in the same register. + * @drvdata: (Optional) Pointer to driver specific data which is + * not used by gpio-remap but is provided "as is" to the + * driver callback(s). ++ * @regmap_irq_chip: (Optional) Pointer on an regmap_irq_chip structure. If ++ * set, a regmap-irq device will be created and the IRQ ++ * domain will be set accordingly. ++ * @regmap_irq_line (Optional) The IRQ the device uses to signal interrupts. ++ * @regmap_irq_flags (Optional) The IRQF_ flags to use for the interrupt. + * + * The ->reg_mask_xlate translates a given base address and GPIO offset to + * register and mask pair. The base address is one of the given register +@@ -77,6 +86,13 @@ struct gpio_regmap_config { + int reg_stride; + int ngpio_per_reg; + struct irq_domain *irq_domain; ++ unsigned long *fixed_direction_output; ++ ++#ifdef CONFIG_REGMAP_IRQ ++ struct regmap_irq_chip *regmap_irq_chip; ++ int regmap_irq_line; ++ unsigned long regmap_irq_flags; ++#endif + + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int base, + unsigned int offset, unsigned int *reg, +diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h +index 15960564e0c364..4d72d24b1f33e7 100644 +--- a/include/net/pkt_sched.h ++++ b/include/net/pkt_sched.h +@@ -112,7 +112,6 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, + struct netlink_ext_ack *extack); + void qdisc_put_rtab(struct qdisc_rate_table *tab); + void qdisc_put_stab(struct qdisc_size_table *tab); +-void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc); + bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + struct net_device *dev, struct netdev_queue *txq, + spinlock_t *root_lock, bool validate); +@@ -306,4 +305,28 @@ static inline bool tc_qdisc_stats_dump(struct Qdisc *sch, + return true; + } + ++static inline void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc) ++{ ++ if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { ++ pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", ++ txt, qdisc->ops->id, qdisc->handle >> 16); ++ qdisc->flags |= TCQ_F_WARN_NONWC; ++ } ++} ++ ++static inline unsigned int qdisc_peek_len(struct Qdisc *sch) ++{ ++ struct sk_buff *skb; ++ unsigned int len; ++ ++ skb = sch->ops->peek(sch); ++ if (unlikely(skb == NULL)) { ++ qdisc_warn_nonwc("qdisc_peek_len", sch); ++ return 0; ++ } ++ len = qdisc_pkt_len(skb); ++ ++ return len; ++} ++ + #endif +diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c +index 1273be84392cfc..ee01cfcc35064a 100644 +--- a/kernel/events/callchain.c ++++ b/kernel/events/callchain.c +@@ -184,6 +184,10 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, + struct perf_callchain_entry_ctx ctx; + int rctx; + ++ /* crosstask is not supported for user stacks */ ++ if (crosstask && user && !kernel) ++ return NULL; ++ + entry = get_callchain_entry(&rctx); + if (!entry) + return NULL; +@@ -200,18 +204,15 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, + perf_callchain_kernel(&ctx, regs); + } + +- if (user) { ++ if (user && !crosstask) { + if (!user_mode(regs)) { +- if (current->mm) +- regs = task_pt_regs(current); +- else ++ if (current->flags & (PF_KTHREAD | PF_USER_WORKER)) + regs = NULL; ++ else ++ regs = task_pt_regs(current); + } + + if (regs) { +- if (crosstask) +- goto exit_put; +- + if (add_mark) + perf_callchain_store_context(&ctx, PERF_CONTEXT_USER); + +@@ -219,7 +220,6 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, + } + } + +-exit_put: + put_callchain_entry(rctx); + + return entry; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index b73f5c44113d64..c9a3fb6fdb2f64 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6985,7 +6985,7 @@ static void perf_sample_regs_user(struct perf_regs *regs_user, + if (user_mode(regs)) { + regs_user->abi = perf_reg_abi(current); + regs_user->regs = regs; +- } else if (!(current->flags & PF_KTHREAD)) { ++ } else if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER))) { + perf_get_regs_user(regs_user, regs); + } else { + regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; +@@ -7612,7 +7612,7 @@ static u64 perf_virt_to_phys(u64 virt) + * Try IRQ-safe get_user_page_fast_only first. + * If failed, leave phys_addr as 0. + */ +- if (current->mm != NULL) { ++ if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER))) { + struct page *p; + + pagefault_disable(); +@@ -7724,7 +7724,8 @@ struct perf_callchain_entry * + perf_callchain(struct perf_event *event, struct pt_regs *regs) + { + bool kernel = !event->attr.exclude_callchain_kernel; +- bool user = !event->attr.exclude_callchain_user; ++ bool user = !event->attr.exclude_callchain_user && ++ !(current->flags & (PF_KTHREAD | PF_USER_WORKER)); + /* Disallow cross-task user callchains. */ + bool crosstask = event->ctx->task && event->ctx->task != current; + const u32 max_stack = event->attr.sample_max_stack; +diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c +index 9d2c38421f7a2b..7fd6714f41fe79 100644 +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -619,6 +619,10 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + } + + subflow: ++ /* No need to try establishing subflows to remote id0 if not allowed */ ++ if (mptcp_pm_add_addr_c_flag_case(msk)) ++ goto exit; ++ + /* check if should create a new subflow */ + while (msk->pm.local_addr_used < local_addr_max && + msk->pm.subflows < subflows_max) { +@@ -650,6 +654,8 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) + __mptcp_subflow_connect(sk, &local.addr, &addrs[i]); + spin_lock_bh(&msk->pm.lock); + } ++ ++exit: + mptcp_pm_nl_check_work_pending(msk); + } + +diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c +index a300e8c1b53aaa..b20dc987b907fc 100644 +--- a/net/sched/sch_api.c ++++ b/net/sched/sch_api.c +@@ -599,16 +599,6 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, + qdisc_skb_cb(skb)->pkt_len = pkt_len; + } + +-void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc) +-{ +- if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { +- pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", +- txt, qdisc->ops->id, qdisc->handle >> 16); +- qdisc->flags |= TCQ_F_WARN_NONWC; +- } +-} +-EXPORT_SYMBOL(qdisc_warn_nonwc); +- + static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) + { + struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, +diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c +index afcb83d469ff60..751b1e2c35b3f9 100644 +--- a/net/sched/sch_hfsc.c ++++ b/net/sched/sch_hfsc.c +@@ -835,22 +835,6 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time) + } + } + +-static unsigned int +-qdisc_peek_len(struct Qdisc *sch) +-{ +- struct sk_buff *skb; +- unsigned int len; +- +- skb = sch->ops->peek(sch); +- if (unlikely(skb == NULL)) { +- qdisc_warn_nonwc("qdisc_peek_len", sch); +- return 0; +- } +- len = qdisc_pkt_len(skb); +- +- return len; +-} +- + static void + hfsc_adjust_levels(struct hfsc_class *cl) + { +diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c +index c3f9a6375b4ea6..69fdbbbb3b6346 100644 +--- a/net/sched/sch_qfq.c ++++ b/net/sched/sch_qfq.c +@@ -1002,7 +1002,7 @@ static struct sk_buff *agg_dequeue(struct qfq_aggregate *agg, + + if (cl->qdisc->q.qlen == 0) /* no more packets, remove from list */ + list_del_init(&cl->alist); +- else if (cl->deficit < qdisc_pkt_len(cl->qdisc->ops->peek(cl->qdisc))) { ++ else if (cl->deficit < qdisc_peek_len(cl->qdisc)) { + cl->deficit += agg->lmax; + list_move_tail(&cl->alist, &agg->active); + } +diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh +index d30314532bb71d..b9cc3d51dc2857 100755 +--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh ++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh +@@ -3837,7 +3837,8 @@ endpoint_tests() + + # remove and re-add + if reset_with_events "delete re-add signal" && +- mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then ++ continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then ++ ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=0 + pm_nl_set_limits $ns1 0 3 + pm_nl_set_limits $ns2 3 3 + pm_nl_add_endpoint $ns1 10.0.2.1 id 1 flags signal
