USB: xHCI: Fix bug in link TRB activation change.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Thu, 10 Jun 2010 19:25:28 +0000 (12:25 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 30 Jun 2010 15:16:05 +0000 (08:16 -0700)
commit6cc30d85a5bf61248ff0e1f0e0f15fe718bae378
treee456498c6b9932e78a6d406095606427902d65e3
parentf588c0db39ca35f69f815dabe5682759daa25098
USB: xHCI: Fix bug in link TRB activation change.

Commit 6c12db90f19727c76990e7f4801c67a148b30111 introduced a bug for
control transfers.  The patch was supposed to change when the link TRBs at
the end of each ring segment were given to the hardware.  If a transfer
descriptor (TD) ended just before the link TRB, the code wouldn't give
back the link TRB to the hardware; instead it would be given back in
prepare_ring() just before the next TD was enqueued at the top of the
ring.

Unfortunately, the code relied on checking the chain bit of the TRB to
determine whether the TD ended just before the link TRB.  It assumed that
the ring enqueuing code would call prepare_ring() before enqueuing the
next TD.  However, control transfers are made of multiple TDs, and
prepare_ring() is only called once before enqueuing two or three TDs.

If the first or second TD of the control transfer ended just before the
link TRB, then the code in inc_enq() would not move the enqueue pointer
past the link TRB, and the link TRB would get overwritten.  This would
cause the xHCI driver to start writing to memory past the ring segment,
and eventually the system would crash or hang.

The fix is to add a flag to inc_enq() that says whether the caller will
enqueue more TDs before calling prepare_ring().  If the chain bit is
cleared (meaning this is the last TRB in a TD), and the caller will not
enqueue more TDs, then we defer giving back the link TRB.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/xhci-ring.c