Skip to content

Commit 5aed5b7

Browse files
matnymangregkh
authored andcommitted
xhci: Remove device endpoints from bandwidth list when freeing the device
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: [email protected] Reported-by: Marek Marczykowski-Górecki <[email protected]> Tested-by: Marek Marczykowski-Górecki <[email protected]> Signed-off-by: Mathias Nyman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a611bf4 commit 5aed5b7

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

drivers/usb/host/xhci-mem.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -889,15 +889,19 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
889889
if (dev->eps[i].stream_info)
890890
xhci_free_stream_info(xhci,
891891
dev->eps[i].stream_info);
892-
/* Endpoints on the TT/root port lists should have been removed
893-
* when usb_disable_device() was called for the device.
894-
* We can't drop them anyway, because the udev might have gone
895-
* away by this point, and we can't tell what speed it was.
892+
/*
893+
* Endpoints are normally deleted from the bandwidth list when
894+
* endpoints are dropped, before device is freed.
895+
* If host is dying or being removed then endpoints aren't
896+
* dropped cleanly, so delete the endpoint from list here.
897+
* Only applicable for hosts with software bandwidth checking.
896898
*/
897-
if (!list_empty(&dev->eps[i].bw_endpoint_list))
898-
xhci_warn(xhci, "Slot %u endpoint %u "
899-
"not removed from BW list!\n",
900-
slot_id, i);
899+
900+
if (!list_empty(&dev->eps[i].bw_endpoint_list)) {
901+
list_del_init(&dev->eps[i].bw_endpoint_list);
902+
xhci_dbg(xhci, "Slot %u endpoint %u not removed from BW list!\n",
903+
slot_id, i);
904+
}
901905
}
902906
/* If this is a hub, free the TT(s) from the TT list */
903907
xhci_free_tt_info(xhci, dev, slot_id);

0 commit comments

Comments
 (0)