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

Reply via email to