--- /dev/null
+From 004eb8ba776ccd3e296ea6f78f7ae7985b12824e Mon Sep 17 00:00:00 2001
+From: Lianqin Hu <hulianqin@vivo.com>
+Date: Sun, 11 Aug 2024 08:30:11 +0000
+Subject: ALSA: usb-audio: Add delay quirk for VIVO USB-C-XE710 HEADSET
+
+From: Lianqin Hu <hulianqin@vivo.com>
+
+commit 004eb8ba776ccd3e296ea6f78f7ae7985b12824e upstream.
+
+Audio control requests that sets sampling frequency sometimes fail on
+this card. Adding delay between control messages eliminates that problem.
+
+Signed-off-by: Lianqin Hu <hulianqin@vivo.com>
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/TYUPR06MB6217FF67076AF3E49E12C877D2842@TYUPR06MB6217.apcprd06.prod.outlook.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/quirks.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1900,6 +1900,8 @@ static const struct usb_audio_quirk_flag
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
++ DEVICE_FLG(0x2d95, 0x8021, /* VIVO USB-C-XE710 HEADSET */
++ QUIRK_FLAG_CTL_MSG_DELAY_1M),
+ DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
--- /dev/null
+From c286f204ce6ba7b48e3dcba53eda7df8eaa64dd9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Juan=20Jos=C3=A9=20Arboleda?= <soyjuanarbol@gmail.com>
+Date: Tue, 13 Aug 2024 11:10:53 -0500
+Subject: ALSA: usb-audio: Support Yamaha P-125 quirk entry
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Juan José Arboleda <soyjuanarbol@gmail.com>
+
+commit c286f204ce6ba7b48e3dcba53eda7df8eaa64dd9 upstream.
+
+This patch adds a USB quirk for the Yamaha P-125 digital piano.
+
+Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com>
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20240813161053.70256-1-soyjuanarbol@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/quirks-table.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/usb/quirks-table.h
++++ b/sound/usb/quirks-table.h
+@@ -273,6 +273,7 @@ YAMAHA_DEVICE(0x105a, NULL),
+ YAMAHA_DEVICE(0x105b, NULL),
+ YAMAHA_DEVICE(0x105c, NULL),
+ YAMAHA_DEVICE(0x105d, NULL),
++YAMAHA_DEVICE(0x1718, "P-125"),
+ {
+ USB_DEVICE(0x0499, 0x1503),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
--- /dev/null
+From a21dcf0ea8566ebbe011c79d6ed08cdfea771de3 Mon Sep 17 00:00:00 2001
+From: Haibo Xu <haibo1.xu@intel.com>
+Date: Mon, 5 Aug 2024 11:30:24 +0800
+Subject: arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to NUMA_NO_NODE
+
+From: Haibo Xu <haibo1.xu@intel.com>
+
+commit a21dcf0ea8566ebbe011c79d6ed08cdfea771de3 upstream.
+
+Currently, only acpi_early_node_map[0] was initialized to NUMA_NO_NODE.
+To ensure all the values were properly initialized, switch to initialize
+all of them to NUMA_NO_NODE.
+
+Fixes: e18962491696 ("arm64: numa: rework ACPI NUMA initialization")
+Cc: <stable@vger.kernel.org> # 4.19.x
+Reported-by: Andrew Jones <ajones@ventanamicro.com>
+Suggested-by: Andrew Jones <ajones@ventanamicro.com>
+Signed-off-by: Haibo Xu <haibo1.xu@intel.com>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
+Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
+Acked-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Reviewed-by: Hanjun Guo <guohanjun@huawei.com>
+Link: https://lore.kernel.org/r/853d7f74aa243f6f5999e203246f0d1ae92d2b61.1722828421.git.haibo1.xu@intel.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/acpi_numa.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/kernel/acpi_numa.c
++++ b/arch/arm64/kernel/acpi_numa.c
+@@ -27,7 +27,7 @@
+
+ #include <asm/numa.h>
+
+-static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
++static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE };
+
+ int __init acpi_numa_get_nid(unsigned int cpu)
+ {
--- /dev/null
+From a37fbe666c016fd89e4460d0ebfcea05baba46dc Mon Sep 17 00:00:00 2001
+From: Alexander Lobakin <aleksander.lobakin@intel.com>
+Date: Wed, 27 Mar 2024 16:23:49 +0100
+Subject: bitmap: introduce generic optimized bitmap_size()
+
+From: Alexander Lobakin <aleksander.lobakin@intel.com>
+
+commit a37fbe666c016fd89e4460d0ebfcea05baba46dc upstream.
+
+The number of times yet another open coded
+`BITS_TO_LONGS(nbits) * sizeof(long)` can be spotted is huge.
+Some generic helper is long overdue.
+
+Add one, bitmap_size(), but with one detail.
+BITS_TO_LONGS() uses DIV_ROUND_UP(). The latter works well when both
+divident and divisor are compile-time constants or when the divisor
+is not a pow-of-2. When it is however, the compilers sometimes tend
+to generate suboptimal code (GCC 13):
+
+48 83 c0 3f add $0x3f,%rax
+48 c1 e8 06 shr $0x6,%rax
+48 8d 14 c5 00 00 00 00 lea 0x0(,%rax,8),%rdx
+
+%BITS_PER_LONG is always a pow-2 (either 32 or 64), but GCC still does
+full division of `nbits + 63` by it and then multiplication by 8.
+Instead of BITS_TO_LONGS(), use ALIGN() and then divide by 8. GCC:
+
+8d 50 3f lea 0x3f(%rax),%edx
+c1 ea 03 shr $0x3,%edx
+81 e2 f8 ff ff 1f and $0x1ffffff8,%edx
+
+Now it shifts `nbits + 63` by 3 positions (IOW performs fast division
+by 8) and then masks bits[2:0]. bloat-o-meter:
+
+add/remove: 0/0 grow/shrink: 20/133 up/down: 156/-773 (-617)
+
+Clang does it better and generates the same code before/after starting
+from -O1, except that with the ALIGN() approach it uses %edx and thus
+still saves some bytes:
+
+add/remove: 0/0 grow/shrink: 9/133 up/down: 18/-538 (-520)
+
+Note that we can't expand DIV_ROUND_UP() by adding a check and using
+this approach there, as it's used in array declarations where
+expressions are not allowed.
+Add this helper to tools/ as well.
+
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Acked-by: Yury Norov <yury.norov@gmail.com>
+Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-clone-metadata.c | 5 -----
+ drivers/s390/cio/idset.c | 2 +-
+ include/linux/bitmap.h | 8 +++++---
+ include/linux/cpumask.h | 2 +-
+ lib/math/prime_numbers.c | 2 --
+ tools/include/linux/bitmap.h | 7 ++++---
+ 6 files changed, 11 insertions(+), 15 deletions(-)
+
+--- a/drivers/md/dm-clone-metadata.c
++++ b/drivers/md/dm-clone-metadata.c
+@@ -465,11 +465,6 @@ static void __destroy_persistent_data_st
+
+ /*---------------------------------------------------------------------------*/
+
+-static size_t bitmap_size(unsigned long nr_bits)
+-{
+- return BITS_TO_LONGS(nr_bits) * sizeof(long);
+-}
+-
+ static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
+ unsigned long nr_regions)
+ {
+--- a/drivers/s390/cio/idset.c
++++ b/drivers/s390/cio/idset.c
+@@ -18,7 +18,7 @@ struct idset {
+
+ static inline unsigned long bitmap_size(int num_ssid, int num_id)
+ {
+- return BITS_TO_LONGS(num_ssid * num_id) * sizeof(unsigned long);
++ return bitmap_size(size_mul(num_ssid, num_id));
+ }
+
+ static struct idset *idset_new(int num_ssid, int num_id)
+--- a/include/linux/bitmap.h
++++ b/include/linux/bitmap.h
+@@ -236,22 +236,24 @@ extern int bitmap_print_list_to_buf(char
+ #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
+ #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
+
++#define bitmap_size(nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE)
++
+ static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
+ {
+- unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
++ unsigned int len = bitmap_size(nbits);
+ memset(dst, 0, len);
+ }
+
+ static inline void bitmap_fill(unsigned long *dst, unsigned int nbits)
+ {
+- unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
++ unsigned int len = bitmap_size(nbits);
+ memset(dst, 0xff, len);
+ }
+
+ static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
+ unsigned int nbits)
+ {
+- unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
++ unsigned int len = bitmap_size(nbits);
+ memcpy(dst, src, len);
+ }
+
+--- a/include/linux/cpumask.h
++++ b/include/linux/cpumask.h
+@@ -667,7 +667,7 @@ static inline int cpulist_parse(const ch
+ */
+ static inline unsigned int cpumask_size(void)
+ {
+- return BITS_TO_LONGS(nr_cpumask_bits) * sizeof(long);
++ return bitmap_size(nr_cpumask_bits);
+ }
+
+ /*
+--- a/lib/math/prime_numbers.c
++++ b/lib/math/prime_numbers.c
+@@ -6,8 +6,6 @@
+ #include <linux/prime_numbers.h>
+ #include <linux/slab.h>
+
+-#define bitmap_size(nbits) (BITS_TO_LONGS(nbits) * sizeof(unsigned long))
+-
+ struct primes {
+ struct rcu_head rcu;
+ unsigned long last, sz;
+--- a/tools/include/linux/bitmap.h
++++ b/tools/include/linux/bitmap.h
+@@ -24,13 +24,14 @@ int __bitmap_intersects(const unsigned l
+ #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
+ #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
+
++#define bitmap_size(nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE)
++
+ static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
+ {
+ if (small_const_nbits(nbits))
+ *dst = 0UL;
+ else {
+- int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+- memset(dst, 0, len);
++ memset(dst, 0, bitmap_size(nbits));
+ }
+ }
+
+@@ -116,7 +117,7 @@ static inline int test_and_clear_bit(int
+ */
+ static inline unsigned long *bitmap_zalloc(int nbits)
+ {
+- return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long));
++ return calloc(1, bitmap_size(nbits));
+ }
+
+ /*
--- /dev/null
+From 008e2512dc5696ab2dc5bf264e98a9fe9ceb830e Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Sun, 11 Aug 2024 15:00:22 +0930
+Subject: btrfs: tree-checker: add dev extent item checks
+
+From: Qu Wenruo <wqu@suse.com>
+
+commit 008e2512dc5696ab2dc5bf264e98a9fe9ceb830e upstream.
+
+[REPORT]
+There is a corruption report that btrfs refused to mount a fs that has
+overlapping dev extents:
+
+ BTRFS error (device sdc): dev extent devid 4 physical offset 14263979671552 overlap with previous dev extent end 14263980982272
+ BTRFS error (device sdc): failed to verify dev extents against chunks: -117
+ BTRFS error (device sdc): open_ctree failed
+
+[CAUSE]
+The direct cause is very obvious, there is a bad dev extent item with
+incorrect length.
+
+With btrfs check reporting two overlapping extents, the second one shows
+some clue on the cause:
+
+ ERROR: dev extent devid 4 offset 14263979671552 len 6488064 overlap with previous dev extent end 14263980982272
+ ERROR: dev extent devid 13 offset 2257707008000 len 6488064 overlap with previous dev extent end 2257707270144
+ ERROR: errors found in extent allocation tree or chunk allocation
+
+The second one looks like a bitflip happened during new chunk
+allocation:
+hex(2257707008000) = 0x20da9d30000
+hex(2257707270144) = 0x20da9d70000
+diff = 0x00000040000
+
+So it looks like a bitflip happened during new dev extent allocation,
+resulting the second overlap.
+
+Currently we only do the dev-extent verification at mount time, but if the
+corruption is caused by memory bitflip, we really want to catch it before
+writing the corruption to the storage.
+
+Furthermore the dev extent items has the following key definition:
+
+ (<device id> DEV_EXTENT <physical offset>)
+
+Thus we can not just rely on the generic key order check to make sure
+there is no overlapping.
+
+[ENHANCEMENT]
+Introduce dedicated dev extent checks, including:
+
+- Fixed member checks
+ * chunk_tree should always be BTRFS_CHUNK_TREE_OBJECTID (3)
+ * chunk_objectid should always be
+ BTRFS_FIRST_CHUNK_CHUNK_TREE_OBJECTID (256)
+
+- Alignment checks
+ * chunk_offset should be aligned to sectorsize
+ * length should be aligned to sectorsize
+ * key.offset should be aligned to sectorsize
+
+- Overlap checks
+ If the previous key is also a dev-extent item, with the same
+ device id, make sure we do not overlap with the previous dev extent.
+
+Reported: Stefan N <stefannnau@gmail.com>
+Link: https://lore.kernel.org/linux-btrfs/CA+W5K0rSO3koYTo=nzxxTm1-Pdu1HYgVxEpgJ=aGc7d=E8mGEg@mail.gmail.com/
+CC: stable@vger.kernel.org # 5.10+
+Reviewed-by: Anand Jain <anand.jain@oracle.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/tree-checker.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
+
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -1596,6 +1596,72 @@ static int check_inode_ref(struct extent
+ return 0;
+ }
+
++static int check_dev_extent_item(const struct extent_buffer *leaf,
++ const struct btrfs_key *key,
++ int slot,
++ struct btrfs_key *prev_key)
++{
++ struct btrfs_dev_extent *de;
++ const u32 sectorsize = leaf->fs_info->sectorsize;
++
++ de = btrfs_item_ptr(leaf, slot, struct btrfs_dev_extent);
++ /* Basic fixed member checks. */
++ if (unlikely(btrfs_dev_extent_chunk_tree(leaf, de) !=
++ BTRFS_CHUNK_TREE_OBJECTID)) {
++ generic_err(leaf, slot,
++ "invalid dev extent chunk tree id, has %llu expect %llu",
++ btrfs_dev_extent_chunk_tree(leaf, de),
++ BTRFS_CHUNK_TREE_OBJECTID);
++ return -EUCLEAN;
++ }
++ if (unlikely(btrfs_dev_extent_chunk_objectid(leaf, de) !=
++ BTRFS_FIRST_CHUNK_TREE_OBJECTID)) {
++ generic_err(leaf, slot,
++ "invalid dev extent chunk objectid, has %llu expect %llu",
++ btrfs_dev_extent_chunk_objectid(leaf, de),
++ BTRFS_FIRST_CHUNK_TREE_OBJECTID);
++ return -EUCLEAN;
++ }
++ /* Alignment check. */
++ if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) {
++ generic_err(leaf, slot,
++ "invalid dev extent key.offset, has %llu not aligned to %u",
++ key->offset, sectorsize);
++ return -EUCLEAN;
++ }
++ if (unlikely(!IS_ALIGNED(btrfs_dev_extent_chunk_offset(leaf, de),
++ sectorsize))) {
++ generic_err(leaf, slot,
++ "invalid dev extent chunk offset, has %llu not aligned to %u",
++ btrfs_dev_extent_chunk_objectid(leaf, de),
++ sectorsize);
++ return -EUCLEAN;
++ }
++ if (unlikely(!IS_ALIGNED(btrfs_dev_extent_length(leaf, de),
++ sectorsize))) {
++ generic_err(leaf, slot,
++ "invalid dev extent length, has %llu not aligned to %u",
++ btrfs_dev_extent_length(leaf, de), sectorsize);
++ return -EUCLEAN;
++ }
++ /* Overlap check with previous dev extent. */
++ if (slot && prev_key->objectid == key->objectid &&
++ prev_key->type == key->type) {
++ struct btrfs_dev_extent *prev_de;
++ u64 prev_len;
++
++ prev_de = btrfs_item_ptr(leaf, slot - 1, struct btrfs_dev_extent);
++ prev_len = btrfs_dev_extent_length(leaf, prev_de);
++ if (unlikely(prev_key->offset + prev_len > key->offset)) {
++ generic_err(leaf, slot,
++ "dev extent overlap, prev offset %llu len %llu current offset %llu",
++ prev_key->objectid, prev_len, key->offset);
++ return -EUCLEAN;
++ }
++ }
++ return 0;
++}
++
+ /*
+ * Common point to switch the item-specific validation.
+ */
+@@ -1631,6 +1697,9 @@ static int check_leaf_item(struct extent
+ case BTRFS_DEV_ITEM_KEY:
+ ret = check_dev_item(leaf, key, slot);
+ break;
++ case BTRFS_DEV_EXTENT_KEY:
++ ret = check_dev_extent_item(leaf, key, slot, prev_key);
++ break;
+ case BTRFS_INODE_ITEM_KEY:
+ ret = check_inode_item(leaf, key, slot);
+ break;
--- /dev/null
+From 2374bf7558de915edc6ec8cb10ec3291dfab9594 Mon Sep 17 00:00:00 2001
+From: Eli Billauer <eli.billauer@gmail.com>
+Date: Fri, 16 Aug 2024 10:02:00 +0300
+Subject: char: xillybus: Check USB endpoints when probing device
+
+From: Eli Billauer <eli.billauer@gmail.com>
+
+commit 2374bf7558de915edc6ec8cb10ec3291dfab9594 upstream.
+
+Ensure, as the driver probes the device, that all endpoints that the
+driver may attempt to access exist and are of the correct type.
+
+All XillyUSB devices must have a Bulk IN and Bulk OUT endpoint at
+address 1. This is verified in xillyusb_setup_base_eps().
+
+On top of that, a XillyUSB device may have additional Bulk OUT
+endpoints. The information about these endpoints' addresses is deduced
+from a data structure (the IDT) that the driver fetches from the device
+while probing it. These endpoints are checked in setup_channels().
+
+A XillyUSB device never has more than one IN endpoint, as all data
+towards the host is multiplexed in this single Bulk IN endpoint. This is
+why setup_channels() only checks OUT endpoints.
+
+Reported-by: syzbot+eac39cba052f2e750dbe@syzkaller.appspotmail.com
+Cc: stable <stable@kernel.org>
+Closes: https://lore.kernel.org/all/0000000000001d44a6061f7a54ee@google.com/T/
+Fixes: a53d1202aef1 ("char: xillybus: Add driver for XillyUSB (Xillybus variant for USB)").
+Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
+Link: https://lore.kernel.org/r/20240816070200.50695-2-eli.billauer@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/xillybus/xillyusb.c | 22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/xillybus/xillyusb.c
++++ b/drivers/char/xillybus/xillyusb.c
+@@ -1889,6 +1889,13 @@ static const struct file_operations xill
+
+ static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev)
+ {
++ struct usb_device *udev = xdev->udev;
++
++ /* Verify that device has the two fundamental bulk in/out endpoints */
++ if (usb_pipe_type_check(udev, usb_sndbulkpipe(udev, MSG_EP_NUM)) ||
++ usb_pipe_type_check(udev, usb_rcvbulkpipe(udev, IN_EP_NUM)))
++ return -ENODEV;
++
+ xdev->msg_ep = endpoint_alloc(xdev, MSG_EP_NUM | USB_DIR_OUT,
+ bulk_out_work, 1, 2);
+ if (!xdev->msg_ep)
+@@ -1918,14 +1925,15 @@ static int setup_channels(struct xillyus
+ __le16 *chandesc,
+ int num_channels)
+ {
+- struct xillyusb_channel *chan;
++ struct usb_device *udev = xdev->udev;
++ struct xillyusb_channel *chan, *new_channels;
+ int i;
+
+ chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL);
+ if (!chan)
+ return -ENOMEM;
+
+- xdev->channels = chan;
++ new_channels = chan;
+
+ for (i = 0; i < num_channels; i++, chan++) {
+ unsigned int in_desc = le16_to_cpu(*chandesc++);
+@@ -1954,6 +1962,15 @@ static int setup_channels(struct xillyus
+ */
+
+ if ((out_desc & 0x80) && i < 14) { /* Entry is valid */
++ if (usb_pipe_type_check(udev,
++ usb_sndbulkpipe(udev, i + 2))) {
++ dev_err(xdev->dev,
++ "Missing BULK OUT endpoint %d\n",
++ i + 2);
++ kfree(new_channels);
++ return -ENODEV;
++ }
++
+ chan->writable = 1;
+ chan->out_synchronous = !!(out_desc & 0x40);
+ chan->out_seekable = !!(out_desc & 0x20);
+@@ -1963,6 +1980,7 @@ static int setup_channels(struct xillyus
+ }
+ }
+
++ xdev->channels = new_channels;
+ return 0;
+ }
+
--- /dev/null
+From ccbde4b128ef9c73d14d0d7817d68ef795f6d131 Mon Sep 17 00:00:00 2001
+From: Eli Billauer <eli.billauer@gmail.com>
+Date: Thu, 1 Aug 2024 15:11:26 +0300
+Subject: char: xillybus: Don't destroy workqueue from work item running on it
+
+From: Eli Billauer <eli.billauer@gmail.com>
+
+commit ccbde4b128ef9c73d14d0d7817d68ef795f6d131 upstream.
+
+Triggered by a kref decrement, destroy_workqueue() may be called from
+within a work item for destroying its own workqueue. This illegal
+situation is averted by adding a module-global workqueue for exclusive
+use of the offending work item. Other work items continue to be queued
+on per-device workqueues to ensure performance.
+
+Reported-by: syzbot+91dbdfecdd3287734d8e@syzkaller.appspotmail.com
+Cc: stable <stable@kernel.org>
+Closes: https://lore.kernel.org/lkml/0000000000000ab25a061e1dfe9f@google.com/
+Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
+Link: https://lore.kernel.org/r/20240801121126.60183-1-eli.billauer@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/xillybus/xillyusb.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/drivers/char/xillybus/xillyusb.c
++++ b/drivers/char/xillybus/xillyusb.c
+@@ -50,6 +50,7 @@ MODULE_LICENSE("GPL v2");
+ static const char xillyname[] = "xillyusb";
+
+ static unsigned int fifo_buf_order;
++static struct workqueue_struct *wakeup_wq;
+
+ #define USB_VENDOR_ID_XILINX 0x03fd
+ #define USB_VENDOR_ID_ALTERA 0x09fb
+@@ -561,10 +562,6 @@ static void cleanup_dev(struct kref *kre
+ * errors if executed. The mechanism relies on that xdev->error is assigned
+ * a non-zero value by report_io_error() prior to queueing wakeup_all(),
+ * which prevents bulk_in_work() from calling process_bulk_in().
+- *
+- * The fact that wakeup_all() and bulk_in_work() are queued on the same
+- * workqueue makes their concurrent execution very unlikely, however the
+- * kernel's API doesn't seem to ensure this strictly.
+ */
+
+ static void wakeup_all(struct work_struct *work)
+@@ -619,7 +616,7 @@ static void report_io_error(struct xilly
+
+ if (do_once) {
+ kref_get(&xdev->kref); /* xdev is used by work item */
+- queue_work(xdev->workq, &xdev->wakeup_workitem);
++ queue_work(wakeup_wq, &xdev->wakeup_workitem);
+ }
+ }
+
+@@ -2242,6 +2239,10 @@ static int __init xillyusb_init(void)
+ {
+ int rc = 0;
+
++ wakeup_wq = alloc_workqueue(xillyname, 0, 0);
++ if (!wakeup_wq)
++ return -ENOMEM;
++
+ if (LOG2_INITIAL_FIFO_BUF_SIZE > PAGE_SHIFT)
+ fifo_buf_order = LOG2_INITIAL_FIFO_BUF_SIZE - PAGE_SHIFT;
+ else
+@@ -2249,11 +2250,16 @@ static int __init xillyusb_init(void)
+
+ rc = usb_register(&xillyusb_driver);
+
++ if (rc)
++ destroy_workqueue(wakeup_wq);
++
+ return rc;
+ }
+
+ static void __exit xillyusb_exit(void)
+ {
++ destroy_workqueue(wakeup_wq);
++
+ usb_deregister(&xillyusb_driver);
+ }
+
--- /dev/null
+From ad899c301c880766cc709aad277991b3ab671b66 Mon Sep 17 00:00:00 2001
+From: Eli Billauer <eli.billauer@gmail.com>
+Date: Fri, 16 Aug 2024 10:01:59 +0300
+Subject: char: xillybus: Refine workqueue handling
+
+From: Eli Billauer <eli.billauer@gmail.com>
+
+commit ad899c301c880766cc709aad277991b3ab671b66 upstream.
+
+As the wakeup work item now runs on a separate workqueue, it needs to be
+flushed separately along with flushing the device's workqueue.
+
+Also, move the destroy_workqueue() call to the end of the exit method,
+so that deinitialization is done in the opposite order of
+initialization.
+
+Fixes: ccbde4b128ef ("char: xillybus: Don't destroy workqueue from work item running on it")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Eli Billauer <eli.billauer@gmail.com>
+Link: https://lore.kernel.org/r/20240816070200.50695-1-eli.billauer@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/xillybus/xillyusb.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/char/xillybus/xillyusb.c
++++ b/drivers/char/xillybus/xillyusb.c
+@@ -2079,9 +2079,11 @@ static int xillyusb_discovery(struct usb
+ * just after responding with the IDT, there is no reason for any
+ * work item to be running now. To be sure that xdev->channels
+ * is updated on anything that might run in parallel, flush the
+- * workqueue, which rarely does anything.
++ * device's workqueue and the wakeup work item. This rarely
++ * does anything.
+ */
+ flush_workqueue(xdev->workq);
++ flush_work(&xdev->wakeup_workitem);
+
+ xdev->num_channels = num_channels;
+
+@@ -2258,9 +2260,9 @@ static int __init xillyusb_init(void)
+
+ static void __exit xillyusb_exit(void)
+ {
+- destroy_workqueue(wakeup_wq);
+-
+ usb_deregister(&xillyusb_driver);
++
++ destroy_workqueue(wakeup_wq);
+ }
+
+ module_init(xillyusb_init);
--- /dev/null
+From faada2174c08662ae98b439c69efe3e79382c538 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 13 Aug 2024 16:35:14 +0200
+Subject: dm persistent data: fix memory allocation failure
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit faada2174c08662ae98b439c69efe3e79382c538 upstream.
+
+kmalloc is unreliable when allocating more than 8 pages of memory. It may
+fail when there is plenty of free memory but the memory is fragmented.
+Zdenek Kabelac observed such failure in his tests.
+
+This commit changes kmalloc to kvmalloc - kvmalloc will fall back to
+vmalloc if the large allocation fails.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Reported-by: Zdenek Kabelac <zkabelac@redhat.com>
+Reviewed-by: Mike Snitzer <snitzer@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/persistent-data/dm-space-map-metadata.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/persistent-data/dm-space-map-metadata.c
++++ b/drivers/md/persistent-data/dm-space-map-metadata.c
+@@ -274,7 +274,7 @@ static void sm_metadata_destroy(struct d
+ {
+ struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
+
+- kfree(smm);
++ kvfree(smm);
+ }
+
+ static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
+@@ -768,7 +768,7 @@ struct dm_space_map *dm_sm_metadata_init
+ {
+ struct sm_metadata *smm;
+
+- smm = kmalloc(sizeof(*smm), GFP_KERNEL);
++ smm = kvmalloc(sizeof(*smm), GFP_KERNEL);
+ if (!smm)
+ return ERR_PTR(-ENOMEM);
+
--- /dev/null
+From 7a636b4f03af9d541205f69e373672e7b2b60a8a Mon Sep 17 00:00:00 2001
+From: Khazhismel Kumykov <khazhy@google.com>
+Date: Tue, 13 Aug 2024 12:39:52 +0200
+Subject: dm resume: don't return EINVAL when signalled
+
+From: Khazhismel Kumykov <khazhy@google.com>
+
+commit 7a636b4f03af9d541205f69e373672e7b2b60a8a upstream.
+
+If the dm_resume method is called on a device that is not suspended, the
+method will suspend the device briefly, before resuming it (so that the
+table will be swapped).
+
+However, there was a bug that the return value of dm_suspended_md was not
+checked. dm_suspended_md may return an error when it is interrupted by a
+signal. In this case, do_resume would call dm_swap_table, which would
+return -EINVAL.
+
+This commit fixes the logic, so that error returned by dm_suspend is
+checked and the resume operation is undone.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Khazhismel Kumykov <khazhy@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-ioctl.c | 22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/dm-ioctl.c
++++ b/drivers/md/dm-ioctl.c
+@@ -1151,8 +1151,26 @@ static int do_resume(struct dm_ioctl *pa
+ suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
+ if (param->flags & DM_NOFLUSH_FLAG)
+ suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
+- if (!dm_suspended_md(md))
+- dm_suspend(md, suspend_flags);
++ if (!dm_suspended_md(md)) {
++ r = dm_suspend(md, suspend_flags);
++ if (r) {
++ down_write(&_hash_lock);
++ hc = dm_get_mdptr(md);
++ if (hc && !hc->new_map) {
++ hc->new_map = new_map;
++ new_map = NULL;
++ } else {
++ r = -ENXIO;
++ }
++ up_write(&_hash_lock);
++ if (new_map) {
++ dm_sync_table(md);
++ dm_table_destroy(new_map);
++ }
++ dm_put(md);
++ return r;
++ }
++ }
+
+ old_size = dm_get_size(md);
+ old_map = dm_swap_table(md, new_map);
--- /dev/null
+From 0573a1e2ea7e35bff08944a40f1adf2bb35cea61 Mon Sep 17 00:00:00 2001
+From: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+Date: Tue, 6 Aug 2024 22:27:32 +0200
+Subject: drm/amdgpu: Actually check flags for all context ops.
+
+From: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+
+commit 0573a1e2ea7e35bff08944a40f1adf2bb35cea61 upstream.
+
+Missing validation ...
+
+Checked libdrm and it clears all the structs, so we should be
+safe to just check everything.
+
+Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit c6b86421f1f9ddf9d706f2453159813ee39d0cf9)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+@@ -413,16 +413,24 @@ int amdgpu_ctx_ioctl(struct drm_device *
+
+ switch (args->in.op) {
+ case AMDGPU_CTX_OP_ALLOC_CTX:
++ if (args->in.flags)
++ return -EINVAL;
+ r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
+ args->out.alloc.ctx_id = id;
+ break;
+ case AMDGPU_CTX_OP_FREE_CTX:
++ if (args->in.flags)
++ return -EINVAL;
+ r = amdgpu_ctx_free(fpriv, id);
+ break;
+ case AMDGPU_CTX_OP_QUERY_STATE:
++ if (args->in.flags)
++ return -EINVAL;
+ r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
+ break;
+ case AMDGPU_CTX_OP_QUERY_STATE2:
++ if (args->in.flags)
++ return -EINVAL;
+ r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
+ break;
+ default:
--- /dev/null
+From 9a2fa1472083580b6c66bdaf291f591e1170123a Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sat, 3 Aug 2024 18:02:00 -0400
+Subject: fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 9a2fa1472083580b6c66bdaf291f591e1170123a upstream.
+
+copy_fd_bitmaps(new, old, count) is expected to copy the first
+count/BITS_PER_LONG bits from old->full_fds_bits[] and fill
+the rest with zeroes. What it does is copying enough words
+(BITS_TO_LONGS(count/BITS_PER_LONG)), then memsets the rest.
+That works fine, *if* all bits past the cutoff point are
+clear. Otherwise we are risking garbage from the last word
+we'd copied.
+
+For most of the callers that is true - expand_fdtable() has
+count equal to old->max_fds, so there's no open descriptors
+past count, let alone fully occupied words in ->open_fds[],
+which is what bits in ->full_fds_bits[] correspond to.
+
+The other caller (dup_fd()) passes sane_fdtable_size(old_fdt, max_fds),
+which is the smallest multiple of BITS_PER_LONG that covers all
+opened descriptors below max_fds. In the common case (copying on
+fork()) max_fds is ~0U, so all opened descriptors will be below
+it and we are fine, by the same reasons why the call in expand_fdtable()
+is safe.
+
+Unfortunately, there is a case where max_fds is less than that
+and where we might, indeed, end up with junk in ->full_fds_bits[] -
+close_range(from, to, CLOSE_RANGE_UNSHARE) with
+ * descriptor table being currently shared
+ * 'to' being above the current capacity of descriptor table
+ * 'from' being just under some chunk of opened descriptors.
+In that case we end up with observably wrong behaviour - e.g. spawn
+a child with CLONE_FILES, get all descriptors in range 0..127 open,
+then close_range(64, ~0U, CLOSE_RANGE_UNSHARE) and watch dup(0) ending
+up with descriptor #128, despite #64 being observably not open.
+
+The minimally invasive fix would be to deal with that in dup_fd().
+If this proves to add measurable overhead, we can go that way, but
+let's try to fix copy_fd_bitmaps() first.
+
+* new helper: bitmap_copy_and_expand(to, from, bits_to_copy, size).
+* make copy_fd_bitmaps() take the bitmap size in words, rather than
+bits; it's 'count' argument is always a multiple of BITS_PER_LONG,
+so we are not losing any information, and that way we can use the
+same helper for all three bitmaps - compiler will see that count
+is a multiple of BITS_PER_LONG for the large ones, so it'll generate
+plain memcpy()+memset().
+
+Reproducer added to tools/testing/selftests/core/close_range_test.c
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/file.c | 28 ++++++++-----------
+ include/linux/bitmap.h | 12 ++++++++
+ tools/testing/selftests/core/close_range_test.c | 35 ++++++++++++++++++++++++
+ 3 files changed, 59 insertions(+), 16 deletions(-)
+
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -46,27 +46,23 @@ static void free_fdtable_rcu(struct rcu_
+ #define BITBIT_NR(nr) BITS_TO_LONGS(BITS_TO_LONGS(nr))
+ #define BITBIT_SIZE(nr) (BITBIT_NR(nr) * sizeof(long))
+
++#define fdt_words(fdt) ((fdt)->max_fds / BITS_PER_LONG) // words in ->open_fds
+ /*
+ * Copy 'count' fd bits from the old table to the new table and clear the extra
+ * space if any. This does not copy the file pointers. Called with the files
+ * spinlock held for write.
+ */
+-static void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt,
+- unsigned int count)
++static inline void copy_fd_bitmaps(struct fdtable *nfdt, struct fdtable *ofdt,
++ unsigned int copy_words)
+ {
+- unsigned int cpy, set;
++ unsigned int nwords = fdt_words(nfdt);
+
+- cpy = count / BITS_PER_BYTE;
+- set = (nfdt->max_fds - count) / BITS_PER_BYTE;
+- memcpy(nfdt->open_fds, ofdt->open_fds, cpy);
+- memset((char *)nfdt->open_fds + cpy, 0, set);
+- memcpy(nfdt->close_on_exec, ofdt->close_on_exec, cpy);
+- memset((char *)nfdt->close_on_exec + cpy, 0, set);
+-
+- cpy = BITBIT_SIZE(count);
+- set = BITBIT_SIZE(nfdt->max_fds) - cpy;
+- memcpy(nfdt->full_fds_bits, ofdt->full_fds_bits, cpy);
+- memset((char *)nfdt->full_fds_bits + cpy, 0, set);
++ bitmap_copy_and_extend(nfdt->open_fds, ofdt->open_fds,
++ copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG);
++ bitmap_copy_and_extend(nfdt->close_on_exec, ofdt->close_on_exec,
++ copy_words * BITS_PER_LONG, nwords * BITS_PER_LONG);
++ bitmap_copy_and_extend(nfdt->full_fds_bits, ofdt->full_fds_bits,
++ copy_words, nwords);
+ }
+
+ /*
+@@ -84,7 +80,7 @@ static void copy_fdtable(struct fdtable
+ memcpy(nfdt->fd, ofdt->fd, cpy);
+ memset((char *)nfdt->fd + cpy, 0, set);
+
+- copy_fd_bitmaps(nfdt, ofdt, ofdt->max_fds);
++ copy_fd_bitmaps(nfdt, ofdt, fdt_words(ofdt));
+ }
+
+ /*
+@@ -374,7 +370,7 @@ struct files_struct *dup_fd(struct files
+ open_files = sane_fdtable_size(old_fdt, max_fds);
+ }
+
+- copy_fd_bitmaps(new_fdt, old_fdt, open_files);
++ copy_fd_bitmaps(new_fdt, old_fdt, open_files / BITS_PER_LONG);
+
+ old_fds = old_fdt->fd;
+ new_fds = new_fdt->fd;
+--- a/include/linux/bitmap.h
++++ b/include/linux/bitmap.h
+@@ -268,6 +268,18 @@ static inline void bitmap_copy_clear_tai
+ dst[nbits / BITS_PER_LONG] &= BITMAP_LAST_WORD_MASK(nbits);
+ }
+
++static inline void bitmap_copy_and_extend(unsigned long *to,
++ const unsigned long *from,
++ unsigned int count, unsigned int size)
++{
++ unsigned int copy = BITS_TO_LONGS(count);
++
++ memcpy(to, from, copy * sizeof(long));
++ if (count % BITS_PER_LONG)
++ to[copy - 1] &= BITMAP_LAST_WORD_MASK(count);
++ memset(to + copy, 0, bitmap_size(size) - copy * sizeof(long));
++}
++
+ /*
+ * On 32-bit systems bitmaps are represented as u32 arrays internally, and
+ * therefore conversion is not needed when copying data from/to arrays of u32.
+--- a/tools/testing/selftests/core/close_range_test.c
++++ b/tools/testing/selftests/core/close_range_test.c
+@@ -567,4 +567,39 @@ TEST(close_range_cloexec_unshare_syzbot)
+ EXPECT_EQ(close(fd3), 0);
+ }
+
++TEST(close_range_bitmap_corruption)
++{
++ pid_t pid;
++ int status;
++ struct __clone_args args = {
++ .flags = CLONE_FILES,
++ .exit_signal = SIGCHLD,
++ };
++
++ /* get the first 128 descriptors open */
++ for (int i = 2; i < 128; i++)
++ EXPECT_GE(dup2(0, i), 0);
++
++ /* get descriptor table shared */
++ pid = sys_clone3(&args, sizeof(args));
++ ASSERT_GE(pid, 0);
++
++ if (pid == 0) {
++ /* unshare and truncate descriptor table down to 64 */
++ if (sys_close_range(64, ~0U, CLOSE_RANGE_UNSHARE))
++ exit(EXIT_FAILURE);
++
++ ASSERT_EQ(fcntl(64, F_GETFD), -1);
++ /* ... and verify that the range 64..127 is not
++ stuck "fully used" according to secondary bitmap */
++ EXPECT_EQ(dup(0), 64)
++ exit(EXIT_FAILURE);
++ exit(EXIT_SUCCESS);
++ }
++
++ EXPECT_EQ(waitpid(pid, &status, 0), pid);
++ EXPECT_EQ(true, WIFEXITED(status));
++ EXPECT_EQ(0, WEXITSTATUS(status));
++}
++
+ TEST_HARNESS_MAIN
--- /dev/null
+From 046667c4d3196938e992fba0dfcde570aa85cd0e Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 21 Jul 2024 14:45:08 -0400
+Subject: memcg_write_event_control(): fix a user-triggerable oops
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 046667c4d3196938e992fba0dfcde570aa85cd0e upstream.
+
+we are *not* guaranteed that anything past the terminating NUL
+is mapped (let alone initialized with anything sane).
+
+Fixes: 0dea116876ee ("cgroup: implement eventfd-based generic API for notifications")
+Cc: stable@vger.kernel.org
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memcontrol.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -4807,9 +4807,12 @@ static ssize_t memcg_write_event_control
+ buf = endp + 1;
+
+ cfd = simple_strtoul(buf, &endp, 10);
+- if ((*endp != ' ') && (*endp != '\0'))
++ if (*endp == '\0')
++ buf = endp;
++ else if (*endp == ' ')
++ buf = endp + 1;
++ else
+ return -EINVAL;
+- buf = endp + 1;
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
--- /dev/null
+From 7db4042336580dfd75cb5faa82c12cd51098c90b Mon Sep 17 00:00:00 2001
+From: Stefan Haberland <sth@linux.ibm.com>
+Date: Mon, 12 Aug 2024 14:57:33 +0200
+Subject: s390/dasd: fix error recovery leading to data corruption on ESE devices
+
+From: Stefan Haberland <sth@linux.ibm.com>
+
+commit 7db4042336580dfd75cb5faa82c12cd51098c90b upstream.
+
+Extent Space Efficient (ESE) or thin provisioned volumes need to be
+formatted on demand during usual IO processing.
+
+The dasd_ese_needs_format function checks for error codes that signal
+the non existence of a proper track format.
+
+The check for incorrect length is to imprecise since other error cases
+leading to transport of insufficient data also have this flag set.
+This might lead to data corruption in certain error cases for example
+during a storage server warmstart.
+
+Fix by removing the check for incorrect length and replacing by
+explicitly checking for invalid track format in transport mode.
+
+Also remove the check for file protected since this is not a valid
+ESE handling case.
+
+Cc: stable@vger.kernel.org # 5.3+
+Fixes: 5e2b17e712cf ("s390/dasd: Add dynamic formatting support for ESE volumes")
+Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
+Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
+Link: https://lore.kernel.org/r/20240812125733.126431-3-sth@linux.ibm.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/s390/block/dasd.c | 36 +++++++++++++++---------
+ drivers/s390/block/dasd_3990_erp.c | 10 +-----
+ drivers/s390/block/dasd_eckd.c | 55 ++++++++++++++++---------------------
+ drivers/s390/block/dasd_int.h | 2 -
+ 4 files changed, 50 insertions(+), 53 deletions(-)
+
+--- a/drivers/s390/block/dasd.c
++++ b/drivers/s390/block/dasd.c
+@@ -1622,9 +1622,15 @@ static int dasd_ese_needs_format(struct
+ if (!sense)
+ return 0;
+
+- return !!(sense[1] & SNS1_NO_REC_FOUND) ||
+- !!(sense[1] & SNS1_FILE_PROTECTED) ||
+- scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN;
++ if (sense[1] & SNS1_NO_REC_FOUND)
++ return 1;
++
++ if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&
++ scsw_is_tm(&irb->scsw) &&
++ !(sense[2] & SNS2_ENV_DATA_PRESENT))
++ return 1;
++
++ return 0;
+ }
+
+ static int dasd_ese_oos_cond(u8 *sense)
+@@ -1645,7 +1651,7 @@ void dasd_int_handler(struct ccw_device
+ struct dasd_device *device;
+ unsigned long now;
+ int nrf_suppressed = 0;
+- int fp_suppressed = 0;
++ int it_suppressed = 0;
+ struct request *req;
+ u8 *sense = NULL;
+ int expires;
+@@ -1700,8 +1706,9 @@ void dasd_int_handler(struct ccw_device
+ */
+ sense = dasd_get_sense(irb);
+ if (sense) {
+- fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) &&
+- test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
++ it_suppressed = (sense[1] & SNS1_INV_TRACK_FORMAT) &&
++ !(sense[2] & SNS2_ENV_DATA_PRESENT) &&
++ test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
+ nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) &&
+ test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+
+@@ -1716,7 +1723,7 @@ void dasd_int_handler(struct ccw_device
+ return;
+ }
+ }
+- if (!(fp_suppressed || nrf_suppressed))
++ if (!(it_suppressed || nrf_suppressed))
+ device->discipline->dump_sense_dbf(device, irb, "int");
+
+ if (device->features & DASD_FEATURE_ERPLOG)
+@@ -2474,14 +2481,17 @@ retry:
+ rc = 0;
+ list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
+ /*
+- * In some cases the 'File Protected' or 'Incorrect Length'
+- * error might be expected and error recovery would be
+- * unnecessary in these cases. Check if the according suppress
+- * bit is set.
++ * In some cases certain errors might be expected and
++ * error recovery would be unnecessary in these cases.
++ * Check if the according suppress bit is set.
+ */
+ sense = dasd_get_sense(&cqr->irb);
+- if (sense && sense[1] & SNS1_FILE_PROTECTED &&
+- test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags))
++ if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
++ !(sense[2] & SNS2_ENV_DATA_PRESENT) &&
++ test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags))
++ continue;
++ if (sense && (sense[1] & SNS1_NO_REC_FOUND) &&
++ test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags))
+ continue;
+ if (scsw_cstat(&cqr->irb.scsw) == 0x40 &&
+ test_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags))
+--- a/drivers/s390/block/dasd_3990_erp.c
++++ b/drivers/s390/block/dasd_3990_erp.c
+@@ -1401,14 +1401,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_
+
+ struct dasd_device *device = erp->startdev;
+
+- /*
+- * In some cases the 'File Protected' error might be expected and
+- * log messages shouldn't be written then.
+- * Check if the according suppress bit is set.
+- */
+- if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags))
+- dev_err(&device->cdev->dev,
+- "Accessing the DASD failed because of a hardware error\n");
++ dev_err(&device->cdev->dev,
++ "Accessing the DASD failed because of a hardware error\n");
+
+ return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
+
+--- a/drivers/s390/block/dasd_eckd.c
++++ b/drivers/s390/block/dasd_eckd.c
+@@ -2301,6 +2301,7 @@ dasd_eckd_analysis_ccw(struct dasd_devic
+ cqr->status = DASD_CQR_FILLED;
+ /* Set flags to suppress output for expected errors */
+ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
++ set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
+
+ return cqr;
+ }
+@@ -2582,7 +2583,6 @@ dasd_eckd_build_check_tcw(struct dasd_de
+ cqr->buildclk = get_tod_clock();
+ cqr->status = DASD_CQR_FILLED;
+ /* Set flags to suppress output for expected errors */
+- set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
+ set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
+
+ return cqr;
+@@ -4131,8 +4131,6 @@ static struct dasd_ccw_req *dasd_eckd_bu
+
+ /* Set flags to suppress output for expected errors */
+ if (dasd_eckd_is_ese(basedev)) {
+- set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
+- set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
+ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+ }
+
+@@ -4634,9 +4632,8 @@ static struct dasd_ccw_req *dasd_eckd_bu
+
+ /* Set flags to suppress output for expected errors */
+ if (dasd_eckd_is_ese(basedev)) {
+- set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
+- set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
+ set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
++ set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
+ }
+
+ return cqr;
+@@ -5806,36 +5803,32 @@ static void dasd_eckd_dump_sense(struct
+ {
+ u8 *sense = dasd_get_sense(irb);
+
+- if (scsw_is_tm(&irb->scsw)) {
+- /*
+- * In some cases the 'File Protected' or 'Incorrect Length'
+- * error might be expected and log messages shouldn't be written
+- * then. Check if the according suppress bit is set.
+- */
+- if (sense && (sense[1] & SNS1_FILE_PROTECTED) &&
+- test_bit(DASD_CQR_SUPPRESS_FP, &req->flags))
+- return;
+- if (scsw_cstat(&irb->scsw) == 0x40 &&
+- test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
+- return;
++ /*
++ * In some cases certain errors might be expected and
++ * log messages shouldn't be written then.
++ * Check if the according suppress bit is set.
++ */
++ if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
++ !(sense[2] & SNS2_ENV_DATA_PRESENT) &&
++ test_bit(DASD_CQR_SUPPRESS_IT, &req->flags))
++ return;
+
+- dasd_eckd_dump_sense_tcw(device, req, irb);
+- } else {
+- /*
+- * In some cases the 'Command Reject' or 'No Record Found'
+- * error might be expected and log messages shouldn't be
+- * written then. Check if the according suppress bit is set.
+- */
+- if (sense && sense[0] & SNS0_CMD_REJECT &&
+- test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
+- return;
++ if (sense && sense[0] & SNS0_CMD_REJECT &&
++ test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
++ return;
+
+- if (sense && sense[1] & SNS1_NO_REC_FOUND &&
+- test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
+- return;
++ if (sense && sense[1] & SNS1_NO_REC_FOUND &&
++ test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
++ return;
+
++ if (scsw_cstat(&irb->scsw) == 0x40 &&
++ test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
++ return;
++
++ if (scsw_is_tm(&irb->scsw))
++ dasd_eckd_dump_sense_tcw(device, req, irb);
++ else
+ dasd_eckd_dump_sense_ccw(device, req, irb);
+- }
+ }
+
+ static int dasd_eckd_reload_device(struct dasd_device *device)
+--- a/drivers/s390/block/dasd_int.h
++++ b/drivers/s390/block/dasd_int.h
+@@ -226,7 +226,7 @@ struct dasd_ccw_req {
+ * The following flags are used to suppress output of certain errors.
+ */
+ #define DASD_CQR_SUPPRESS_NRF 4 /* Suppress 'No Record Found' error */
+-#define DASD_CQR_SUPPRESS_FP 5 /* Suppress 'File Protected' error*/
++#define DASD_CQR_SUPPRESS_IT 5 /* Suppress 'Invalid Track' error*/
+ #define DASD_CQR_SUPPRESS_IL 6 /* Suppress 'Incorrect Length' error */
+ #define DASD_CQR_SUPPRESS_CR 7 /* Suppress 'Command Reject' error */
+
--- /dev/null
+From 379d9af3f3da2da1bbfa67baf1820c72a080d1f1 Mon Sep 17 00:00:00 2001
+From: Zhen Lei <thunder.leizhen@huawei.com>
+Date: Tue, 6 Aug 2024 14:51:13 +0800
+Subject: selinux: fix potential counting error in avc_add_xperms_decision()
+
+From: Zhen Lei <thunder.leizhen@huawei.com>
+
+commit 379d9af3f3da2da1bbfa67baf1820c72a080d1f1 upstream.
+
+The count increases only when a node is successfully added to
+the linked list.
+
+Cc: stable@vger.kernel.org
+Fixes: fa1aa143ac4a ("selinux: extended permissions for ioctls")
+Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
+Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/selinux/avc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/security/selinux/avc.c
++++ b/security/selinux/avc.c
+@@ -332,12 +332,12 @@ static int avc_add_xperms_decision(struc
+ {
+ struct avc_xperms_decision_node *dest_xpd;
+
+- node->ae.xp_node->xp.len++;
+ dest_xpd = avc_xperms_decision_alloc(src->used);
+ if (!dest_xpd)
+ return -ENOMEM;
+ avc_copy_xperms_decision(&dest_xpd->xpd, src);
+ list_add(&dest_xpd->xpd_list, &node->ae.xp_node->xpd_head);
++ node->ae.xp_node->xp.len++;
+ return 0;
+ }
+
fuse-initialize-beyond-eof-page-contents-before-setting-uptodate.patch
+char-xillybus-don-t-destroy-workqueue-from-work-item-running-on-it.patch
+char-xillybus-refine-workqueue-handling.patch
+char-xillybus-check-usb-endpoints-when-probing-device.patch
+alsa-usb-audio-add-delay-quirk-for-vivo-usb-c-xe710-headset.patch
+alsa-usb-audio-support-yamaha-p-125-quirk-entry.patch
+xhci-fix-panther-point-null-pointer-deref-at-full-speed-re-enumeration.patch
+thunderbolt-mark-xdomain-as-unplugged-when-router-is-removed.patch
+s390-dasd-fix-error-recovery-leading-to-data-corruption-on-ese-devices.patch
+arm64-acpi-numa-initialize-all-values-of-acpi_early_node_map-to-numa_no_node.patch
+dm-resume-don-t-return-einval-when-signalled.patch
+dm-persistent-data-fix-memory-allocation-failure.patch
+vfs-don-t-evict-inode-under-the-inode-lru-traversing-context.patch
+bitmap-introduce-generic-optimized-bitmap_size.patch
+fix-bitmap-corruption-on-close_range-with-close_range_unshare.patch
+selinux-fix-potential-counting-error-in-avc_add_xperms_decision.patch
+btrfs-tree-checker-add-dev-extent-item-checks.patch
+drm-amdgpu-actually-check-flags-for-all-context-ops.patch
+memcg_write_event_control-fix-a-user-triggerable-oops.patch
--- /dev/null
+From e2006140ad2e01a02ed0aff49cc2ae3ceeb11f8d Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Thu, 13 Jun 2024 15:05:03 +0300
+Subject: thunderbolt: Mark XDomain as unplugged when router is removed
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+commit e2006140ad2e01a02ed0aff49cc2ae3ceeb11f8d upstream.
+
+I noticed that when we do discrete host router NVM upgrade and it gets
+hot-removed from the PCIe side as a result of NVM firmware authentication,
+if there is another host connected with enabled paths we hang in tearing
+them down. This is due to fact that the Thunderbolt networking driver
+also tries to cleanup the paths and ends up blocking in
+tb_disconnect_xdomain_paths() waiting for the domain lock.
+
+However, at this point we already cleaned the paths in tb_stop() so
+there is really no need for tb_disconnect_xdomain_paths() to do that
+anymore. Furthermore it already checks if the XDomain is unplugged and
+bails out early so take advantage of that and mark the XDomain as
+unplugged when we remove the parent router.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/switch.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/thunderbolt/switch.c
++++ b/drivers/thunderbolt/switch.c
+@@ -2877,6 +2877,7 @@ void tb_switch_remove(struct tb_switch *
+ tb_switch_remove(port->remote->sw);
+ port->remote = NULL;
+ } else if (port->xdomain) {
++ port->xdomain->is_unplugged = true;
+ tb_xdomain_remove(port->xdomain);
+ port->xdomain = NULL;
+ }
--- /dev/null
+From 2a0629834cd82f05d424bbc193374f9a43d1f87d Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Fri, 9 Aug 2024 11:16:28 +0800
+Subject: vfs: Don't evict inode under the inode lru traversing context
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit 2a0629834cd82f05d424bbc193374f9a43d1f87d upstream.
+
+The inode reclaiming process(See function prune_icache_sb) collects all
+reclaimable inodes and mark them with I_FREEING flag at first, at that
+time, other processes will be stuck if they try getting these inodes
+(See function find_inode_fast), then the reclaiming process destroy the
+inodes by function dispose_list(). Some filesystems(eg. ext4 with
+ea_inode feature, ubifs with xattr) may do inode lookup in the inode
+evicting callback function, if the inode lookup is operated under the
+inode lru traversing context, deadlock problems may happen.
+
+Case 1: In function ext4_evict_inode(), the ea inode lookup could happen
+ if ea_inode feature is enabled, the lookup process will be stuck
+ under the evicting context like this:
+
+ 1. File A has inode i_reg and an ea inode i_ea
+ 2. getfattr(A, xattr_buf) // i_ea is added into lru // lru->i_ea
+ 3. Then, following three processes running like this:
+
+ PA PB
+ echo 2 > /proc/sys/vm/drop_caches
+ shrink_slab
+ prune_dcache_sb
+ // i_reg is added into lru, lru->i_ea->i_reg
+ prune_icache_sb
+ list_lru_walk_one
+ inode_lru_isolate
+ i_ea->i_state |= I_FREEING // set inode state
+ inode_lru_isolate
+ __iget(i_reg)
+ spin_unlock(&i_reg->i_lock)
+ spin_unlock(lru_lock)
+ rm file A
+ i_reg->nlink = 0
+ iput(i_reg) // i_reg->nlink is 0, do evict
+ ext4_evict_inode
+ ext4_xattr_delete_inode
+ ext4_xattr_inode_dec_ref_all
+ ext4_xattr_inode_iget
+ ext4_iget(i_ea->i_ino)
+ iget_locked
+ find_inode_fast
+ __wait_on_freeing_inode(i_ea) ----→ AA deadlock
+ dispose_list // cannot be executed by prune_icache_sb
+ wake_up_bit(&i_ea->i_state)
+
+Case 2: In deleted inode writing function ubifs_jnl_write_inode(), file
+ deleting process holds BASEHD's wbuf->io_mutex while getting the
+ xattr inode, which could race with inode reclaiming process(The
+ reclaiming process could try locking BASEHD's wbuf->io_mutex in
+ inode evicting function), then an ABBA deadlock problem would
+ happen as following:
+
+ 1. File A has inode ia and a xattr(with inode ixa), regular file B has
+ inode ib and a xattr.
+ 2. getfattr(A, xattr_buf) // ixa is added into lru // lru->ixa
+ 3. Then, following three processes running like this:
+
+ PA PB PC
+ echo 2 > /proc/sys/vm/drop_caches
+ shrink_slab
+ prune_dcache_sb
+ // ib and ia are added into lru, lru->ixa->ib->ia
+ prune_icache_sb
+ list_lru_walk_one
+ inode_lru_isolate
+ ixa->i_state |= I_FREEING // set inode state
+ inode_lru_isolate
+ __iget(ib)
+ spin_unlock(&ib->i_lock)
+ spin_unlock(lru_lock)
+ rm file B
+ ib->nlink = 0
+ rm file A
+ iput(ia)
+ ubifs_evict_inode(ia)
+ ubifs_jnl_delete_inode(ia)
+ ubifs_jnl_write_inode(ia)
+ make_reservation(BASEHD) // Lock wbuf->io_mutex
+ ubifs_iget(ixa->i_ino)
+ iget_locked
+ find_inode_fast
+ __wait_on_freeing_inode(ixa)
+ | iput(ib) // ib->nlink is 0, do evict
+ | ubifs_evict_inode
+ | ubifs_jnl_delete_inode(ib)
+ ↓ ubifs_jnl_write_inode
+ ABBA deadlock ←-----make_reservation(BASEHD)
+ dispose_list // cannot be executed by prune_icache_sb
+ wake_up_bit(&ixa->i_state)
+
+Fix the possible deadlock by using new inode state flag I_LRU_ISOLATING
+to pin the inode in memory while inode_lru_isolate() reclaims its pages
+instead of using ordinary inode reference. This way inode deletion
+cannot be triggered from inode_lru_isolate() thus avoiding the deadlock.
+evict() is made to wait for I_LRU_ISOLATING to be cleared before
+proceeding with inode cleanup.
+
+Link: https://lore.kernel.org/all/37c29c42-7685-d1f0-067d-63582ffac405@huaweicloud.com/
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219022
+Fixes: e50e5129f384 ("ext4: xattr-in-inode support")
+Fixes: 7959cf3a7506 ("ubifs: journal: Handle xattrs like files")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Link: https://lore.kernel.org/r/20240809031628.1069873-1-chengzhihao@huaweicloud.com
+Reviewed-by: Jan Kara <jack@suse.cz>
+Suggested-by: Jan Kara <jack@suse.cz>
+Suggested-by: Mateusz Guzik <mjguzik@gmail.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/inode.c | 39 +++++++++++++++++++++++++++++++++++++--
+ include/linux/fs.h | 5 +++++
+ 2 files changed, 42 insertions(+), 2 deletions(-)
+
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -456,6 +456,39 @@ static void inode_lru_list_del(struct in
+ this_cpu_dec(nr_unused);
+ }
+
++static void inode_pin_lru_isolating(struct inode *inode)
++{
++ lockdep_assert_held(&inode->i_lock);
++ WARN_ON(inode->i_state & (I_LRU_ISOLATING | I_FREEING | I_WILL_FREE));
++ inode->i_state |= I_LRU_ISOLATING;
++}
++
++static void inode_unpin_lru_isolating(struct inode *inode)
++{
++ spin_lock(&inode->i_lock);
++ WARN_ON(!(inode->i_state & I_LRU_ISOLATING));
++ inode->i_state &= ~I_LRU_ISOLATING;
++ smp_mb();
++ wake_up_bit(&inode->i_state, __I_LRU_ISOLATING);
++ spin_unlock(&inode->i_lock);
++}
++
++static void inode_wait_for_lru_isolating(struct inode *inode)
++{
++ spin_lock(&inode->i_lock);
++ if (inode->i_state & I_LRU_ISOLATING) {
++ DEFINE_WAIT_BIT(wq, &inode->i_state, __I_LRU_ISOLATING);
++ wait_queue_head_t *wqh;
++
++ wqh = bit_waitqueue(&inode->i_state, __I_LRU_ISOLATING);
++ spin_unlock(&inode->i_lock);
++ __wait_on_bit(wqh, &wq, bit_wait, TASK_UNINTERRUPTIBLE);
++ spin_lock(&inode->i_lock);
++ WARN_ON(inode->i_state & I_LRU_ISOLATING);
++ }
++ spin_unlock(&inode->i_lock);
++}
++
+ /**
+ * inode_sb_list_add - add inode to the superblock list of inodes
+ * @inode: inode to add
+@@ -575,6 +608,8 @@ static void evict(struct inode *inode)
+
+ inode_sb_list_del(inode);
+
++ inode_wait_for_lru_isolating(inode);
++
+ /*
+ * Wait for flusher thread to be done with the inode so that filesystem
+ * does not start destroying it while writeback is still running. Since
+@@ -772,7 +807,7 @@ static enum lru_status inode_lru_isolate
+ }
+
+ if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) {
+- __iget(inode);
++ inode_pin_lru_isolating(inode);
+ spin_unlock(&inode->i_lock);
+ spin_unlock(lru_lock);
+ if (remove_inode_buffers(inode)) {
+@@ -785,7 +820,7 @@ static enum lru_status inode_lru_isolate
+ if (current->reclaim_state)
+ current->reclaim_state->reclaimed_slab += reap;
+ }
+- iput(inode);
++ inode_unpin_lru_isolating(inode);
+ spin_lock(lru_lock);
+ return LRU_RETRY;
+ }
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2429,6 +2429,9 @@ static inline void kiocb_clone(struct ki
+ * Used to detect that mark_inode_dirty() should not move
+ * inode between dirty lists.
+ *
++ * I_LRU_ISOLATING Inode is pinned being isolated from LRU without holding
++ * i_count.
++ *
+ * Q: What is the difference between I_WILL_FREE and I_FREEING?
+ */
+ #define I_DIRTY_SYNC (1 << 0)
+@@ -2451,6 +2454,8 @@ static inline void kiocb_clone(struct ki
+ #define I_CREATING (1 << 15)
+ #define I_DONTCACHE (1 << 16)
+ #define I_SYNC_QUEUED (1 << 17)
++#define __I_LRU_ISOLATING 19
++#define I_LRU_ISOLATING (1 << __I_LRU_ISOLATING)
+
+ #define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
+ #define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
--- /dev/null
+From af8e119f52e9c13e556be9e03f27957554a84656 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 15 Aug 2024 17:11:17 +0300
+Subject: xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit af8e119f52e9c13e556be9e03f27957554a84656 upstream.
+
+re-enumerating full-speed devices after a failed address device command
+can trigger a NULL pointer dereference.
+
+Full-speed devices may need to reconfigure the endpoint 0 Max Packet Size
+value during enumeration. Usb core calls usb_ep0_reinit() in this case,
+which ends up calling xhci_configure_endpoint().
+
+On Panther point xHC the xhci_configure_endpoint() function will
+additionally check and reserve bandwidth in software. Other hosts do
+this in hardware
+
+If xHC address device command fails then a new xhci_virt_device structure
+is allocated as part of re-enabling the slot, but the bandwidth table
+pointers are not set up properly here.
+This triggers the NULL pointer dereference the next time usb_ep0_reinit()
+is called and xhci_configure_endpoint() tries to check and reserve
+bandwidth
+
+[46710.713538] usb 3-1: new full-speed USB device number 5 using xhci_hcd
+[46710.713699] usb 3-1: Device not responding to setup address.
+[46710.917684] usb 3-1: Device not responding to setup address.
+[46711.125536] usb 3-1: device not accepting address 5, error -71
+[46711.125594] BUG: kernel NULL pointer dereference, address: 0000000000000008
+[46711.125600] #PF: supervisor read access in kernel mode
+[46711.125603] #PF: error_code(0x0000) - not-present page
+[46711.125606] PGD 0 P4D 0
+[46711.125610] Oops: Oops: 0000 [#1] PREEMPT SMP PTI
+[46711.125615] CPU: 1 PID: 25760 Comm: kworker/1:2 Not tainted 6.10.3_2 #1
+[46711.125620] Hardware name: Gigabyte Technology Co., Ltd.
+[46711.125623] Workqueue: usb_hub_wq hub_event [usbcore]
+[46711.125668] RIP: 0010:xhci_reserve_bandwidth (drivers/usb/host/xhci.c
+
+Fix this by making sure bandwidth table pointers are set up correctly
+after a failed address device command, and additionally by avoiding
+checking for bandwidth in cases like this where no actual endpoints are
+added or removed, i.e. only context for default control endpoint 0 is
+evaluated.
+
+Reported-by: Karel Balej <balejk@matfyz.cz>
+Closes: https://lore.kernel.org/linux-usb/D3CKQQAETH47.1MUO22RTCH2O3@matfyz.cz/
+Cc: stable@vger.kernel.org
+Fixes: 651aaf36a7d7 ("usb: xhci: Handle USB transaction error on address command")
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20240815141117.2702314-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -2954,7 +2954,7 @@ static int xhci_configure_endpoint(struc
+ xhci->num_active_eps);
+ return -ENOMEM;
+ }
+- if ((xhci->quirks & XHCI_SW_BW_CHECKING) &&
++ if ((xhci->quirks & XHCI_SW_BW_CHECKING) && !ctx_change &&
+ xhci_reserve_bandwidth(xhci, virt_dev, command->in_ctx)) {
+ if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
+ xhci_free_host_resources(xhci, ctrl_ctx);
+@@ -4294,8 +4294,10 @@ static int xhci_setup_device(struct usb_
+ mutex_unlock(&xhci->mutex);
+ ret = xhci_disable_slot(xhci, udev->slot_id);
+ xhci_free_virt_device(xhci, udev->slot_id);
+- if (!ret)
+- xhci_alloc_dev(hcd, udev);
++ if (!ret) {
++ if (xhci_alloc_dev(hcd, udev) == 1)
++ xhci_setup_addressable_virt_dev(xhci, udev);
++ }
+ kfree(command->completion);
+ kfree(command);
+ return -EPROTO;