xhci: Remove TDs from TD lists when URBs are canceled.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Tue, 2 Aug 2011 22:43:40 +0000 (15:43 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 3 Oct 2011 18:39:53 +0000 (11:39 -0700)
commit4343d2a21eeab544544646fed30252c184b358a9
tree8114edb11b0bc0beebaa13579a46743840f42724
parent8a8045bd9b07df6def0ae16b91ecbe8225267b35
xhci: Remove TDs from TD lists when URBs are canceled.

commit 585df1d90cb07a02ca6c7a7d339e56e46d50dafb upstream.

When a driver tries to cancel an URB, and the host controller is dying,
xhci_urb_dequeue will giveback the URB without removing the xhci_tds
that comprise that URB from the td_list or the cancelled_td_list.  This
can cause a race condition between the driver calling URB dequeue and
the stop endpoint command watchdog timer.

If the timer fires on a dying host, and a driver attempts to resubmit
while the watchdog timer has dropped the xhci->lock to giveback a
cancelled URB, URBs may be given back by the xhci_urb_dequeue() function.
At that point, the URB's priv pointer will be freed and set to NULL, but
the TDs will remain on the td_list.  This will cause an oops in
xhci_giveback_urb_in_irq() when the watchdog timer attempts to loop
through the endpoints' td_lists, giving back killed URBs.

Make sure that xhci_urb_dequeue() removes TDs from the TD lists and
canceled TD lists before it gives back the URB.

This patch should be backported to kernels as old as 2.6.36.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: Andiry Xu <andiry.xu@amd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c