--- /dev/null
+From 5aed5b7c2430ce318a8e62f752f181e66f0d1053 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Mon, 24 Oct 2022 17:27:20 +0300
+Subject: xhci: Remove device endpoints from bandwidth list when freeing the device
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 5aed5b7c2430ce318a8e62f752f181e66f0d1053 upstream.
+
+Endpoints are normally deleted from the bandwidth list when they are
+dropped, before the virt device is freed.
+
+If xHC host is dying or being removed then the endpoints aren't dropped
+cleanly due to functions returning early to avoid interacting with a
+non-accessible host controller.
+
+So check and delete endpoints that are still on the bandwidth list when
+freeing the virt device.
+
+Solves a list_del corruption kernel crash when unbinding xhci-pci,
+caused by xhci_mem_cleanup() when it later tried to delete already freed
+endpoints from the bandwidth list.
+
+This only affects hosts that use software bandwidth checking, which
+currenty is only the xHC in intel Panther Point PCH (Ivy Bridge)
+
+Cc: stable@vger.kernel.org
+Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20221024142720.4122053-5-mathias.nyman@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-mem.c | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -906,15 +906,19 @@ void xhci_free_virt_device(struct xhci_h
+ if (dev->eps[i].stream_info)
+ xhci_free_stream_info(xhci,
+ dev->eps[i].stream_info);
+- /* Endpoints on the TT/root port lists should have been removed
+- * when usb_disable_device() was called for the device.
+- * We can't drop them anyway, because the udev might have gone
+- * away by this point, and we can't tell what speed it was.
++ /*
++ * Endpoints are normally deleted from the bandwidth list when
++ * endpoints are dropped, before device is freed.
++ * If host is dying or being removed then endpoints aren't
++ * dropped cleanly, so delete the endpoint from list here.
++ * Only applicable for hosts with software bandwidth checking.
+ */
+- if (!list_empty(&dev->eps[i].bw_endpoint_list))
+- xhci_warn(xhci, "Slot %u endpoint %u "
+- "not removed from BW list!\n",
+- slot_id, i);
++
++ if (!list_empty(&dev->eps[i].bw_endpoint_list)) {
++ list_del_init(&dev->eps[i].bw_endpoint_list);
++ xhci_dbg(xhci, "Slot %u endpoint %u not removed from BW list!\n",
++ slot_id, i);
++ }
+ }
+ /* If this is a hub, free the TT(s) from the TT list */
+ xhci_free_tt_info(xhci, dev, slot_id);