]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Aug 2024 09:37:03 +0000 (11:37 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Aug 2024 09:37:03 +0000 (11:37 +0200)
added patches:
alsa-usb-audio-support-yamaha-p-125-quirk-entry.patch
arm64-acpi-numa-initialize-all-values-of-acpi_early_node_map-to-numa_no_node.patch
dm-persistent-data-fix-memory-allocation-failure.patch
dm-resume-don-t-return-einval-when-signalled.patch
fix-bitmap-corruption-on-close_range-with-close_range_unshare.patch
xhci-fix-panther-point-null-pointer-deref-at-full-speed-re-enumeration.patch

queue-4.19/alsa-usb-audio-support-yamaha-p-125-quirk-entry.patch [new file with mode: 0644]
queue-4.19/arm64-acpi-numa-initialize-all-values-of-acpi_early_node_map-to-numa_no_node.patch [new file with mode: 0644]
queue-4.19/dm-persistent-data-fix-memory-allocation-failure.patch [new file with mode: 0644]
queue-4.19/dm-resume-don-t-return-einval-when-signalled.patch [new file with mode: 0644]
queue-4.19/fix-bitmap-corruption-on-close_range-with-close_range_unshare.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/xhci-fix-panther-point-null-pointer-deref-at-full-speed-re-enumeration.patch [new file with mode: 0644]

diff --git a/queue-4.19/alsa-usb-audio-support-yamaha-p-125-quirk-entry.patch b/queue-4.19/alsa-usb-audio-support-yamaha-p-125-quirk-entry.patch
new file mode 100644 (file)
index 0000000..871ecc7
--- /dev/null
@@ -0,0 +1,33 @@
+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
+@@ -352,6 +352,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) {
diff --git a/queue-4.19/arm64-acpi-numa-initialize-all-values-of-acpi_early_node_map-to-numa_no_node.patch b/queue-4.19/arm64-acpi-numa-initialize-all-values-of-acpi_early_node_map-to-numa_no_node.patch
new file mode 100644 (file)
index 0000000..fca8a44
--- /dev/null
@@ -0,0 +1,42 @@
+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
+@@ -28,7 +28,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)
+ {
diff --git a/queue-4.19/dm-persistent-data-fix-memory-allocation-failure.patch b/queue-4.19/dm-persistent-data-fix-memory-allocation-failure.patch
new file mode 100644 (file)
index 0000000..da31b40
--- /dev/null
@@ -0,0 +1,45 @@
+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
+@@ -275,7 +275,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)
+@@ -759,7 +759,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);
diff --git a/queue-4.19/dm-resume-don-t-return-einval-when-signalled.patch b/queue-4.19/dm-resume-don-t-return-einval-when-signalled.patch
new file mode 100644 (file)
index 0000000..5cc6531
--- /dev/null
@@ -0,0 +1,60 @@
+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
+@@ -1039,8 +1039,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_map = dm_swap_table(md, new_map);
+               if (IS_ERR(old_map)) {
diff --git a/queue-4.19/fix-bitmap-corruption-on-close_range-with-close_range_unshare.patch b/queue-4.19/fix-bitmap-corruption-on-close_range-with-close_range_unshare.patch
new file mode 100644 (file)
index 0000000..61aa616
--- /dev/null
@@ -0,0 +1,193 @@
+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 +++++++
+ .../testing/selftests/core/close_range_test.c | 35 +++++++++++++++++++
+ 3 files changed, 59 insertions(+), 16 deletions(-)
+
+diff --git a/fs/file.c b/fs/file.c
+index a11e59b5d602..655338effe9c 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -46,27 +46,23 @@ static void free_fdtable_rcu(struct rcu_head *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 *nfdt, struct fdtable *ofdt)
+       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));
+ }
+ /*
+@@ -379,7 +375,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds, int
+               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;
+diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
+index 8c4768c44a01..d3b66d77df7a 100644
+--- a/include/linux/bitmap.h
++++ b/include/linux/bitmap.h
+@@ -270,6 +270,18 @@ static inline void bitmap_copy_clear_tail(unsigned long *dst,
+               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. On LE64
+  * machines the order of hi and lo parts of numbers match the bitmap structure.
+diff --git a/tools/testing/selftests/core/close_range_test.c b/tools/testing/selftests/core/close_range_test.c
+index 991c473e3859..12b4eb9d0434 100644
+--- a/tools/testing/selftests/core/close_range_test.c
++++ b/tools/testing/selftests/core/close_range_test.c
+@@ -589,4 +589,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
+-- 
+2.46.0
+
index e834c81ba8ef23c48819d4a77cfed7e46e5f42bd..6803eea792c32853fbd89347b37f0087c645f287 100644 (file)
@@ -1 +1,7 @@
 fuse-initialize-beyond-eof-page-contents-before-setting-uptodate.patch
+alsa-usb-audio-support-yamaha-p-125-quirk-entry.patch
+xhci-fix-panther-point-null-pointer-deref-at-full-speed-re-enumeration.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
+fix-bitmap-corruption-on-close_range-with-close_range_unshare.patch
diff --git a/queue-4.19/xhci-fix-panther-point-null-pointer-deref-at-full-speed-re-enumeration.patch b/queue-4.19/xhci-fix-panther-point-null-pointer-deref-at-full-speed-re-enumeration.patch
new file mode 100644 (file)
index 0000000..64e13f0
--- /dev/null
@@ -0,0 +1,82 @@
+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
+@@ -2790,7 +2790,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);
+@@ -4145,8 +4145,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;