usb: xhci: account for num_trbs_free when invalidating TDs
authorJonathan Bell <jonathan@raspberrypi.com>
Thu, 22 Sep 2022 13:55:54 +0000 (14:55 +0100)
committerPhil Elwell <8911409+pelwell@users.noreply.github.com>
Tue, 27 Sep 2022 14:35:58 +0000 (15:35 +0100)
commitdf0be5a8df1c9d266a08b5ea3e2784a147897f07
treeef48d2dcd7d8f80b4459358ee3223f89e64b477a
parentb5fb803e192afa566351481edf03bb44b56d48e7
usb: xhci: account for num_trbs_free when invalidating TDs

If a ring has a number of TDs enqueued past the dequeue pointer, and the
URBs corresponding to these TDs are dequeued, then num_trbs_free isn't
updated to show that these TDs have been converted to no-ops and
effectively "freed". This means that num_trbs_free creeps downwards
until the count is exhausted, which then triggers xhci_ring_expansion()
and effectively leaks memory by infinitely growing the transfer ring.

This is commonly encounted through the use of a usb-serial port where
the port is repeatedly opened, read, then closed.

Move the num_trbs_free crediting out of the Set TR Dequeue Pointer
handling and into xhci_invalidate_cancelled_tds().

There is a potential for overestimating the actual space on the ring if
the ring is nearly full and TDs are arbitrarily enqueued by a device
driver while it is dequeueing them, but dequeues are usually batched
during device close/shutdown or endpoint error recovery.

See https://github.com/raspberrypi/linux/issues/5088

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
drivers/usb/host/xhci-ring.c