On Fri, Aug 17, 2012 at 01:38:22PM -0400, Gregs git-bot wrote: > commit: 50d0206fcaea3e736f912fd5b00ec6233fb4ce44 > From: Sarah Sharp <[email protected]> > Date: Thu, 26 Jul 2012 12:03:59 -0700 > Subject: xhci: Fix bug after deq ptr set to link TRB. > > This patch fixes a particularly nasty bug that was revealed by the ring > expansion patches. The bug has been present since the very beginning of > the xHCI driver history, and could have caused general protection faults > from bad memory accesses. > > The first thing to note is that a Set TR Dequeue Pointer command can > move the dequeue pointer to a link TRB, if the canceled or stalled > transfer TD ended just before a link TRB. The function to increment the > dequeue pointer, inc_deq, was written before cancellation and stall > support was added. It assumed that the dequeue pointer could never > point to a link TRB. It would unconditionally increment the dequeue > pointer at the start of the function, check if the pointer was now on a > link TRB, and move it to the top of the next segment if so. > > This means that if a Set TR Dequeue Point command moved the dequeue > pointer to a link TRB, a subsequent call to inc_deq() would move the > pointer off the segment and into la-la-land. It would then read from > that memory to determine if it was a link TRB. Other functions would > often call inc_deq() until the dequeue pointer matched some other > pointer, which means this function would quite happily read all of > system memory before wrapping around to the right pointer value. > > Often, there would be another endpoint segment from a different ring > allocated from the same DMA pool, which would be contiguous to the > segment inc_deq just stepped off of. inc_deq would eventually find the > link TRB in that segment, and blindly move the dequeue pointer back to > the top of the correct ring segment. > > The only reason the original code worked at all is because there was > only one ring segment. With the ring expansion patches, the dequeue > pointer would eventually wrap into place, but the dequeue segment would > be out-of-sync. On the second TD after the dequeue pointer was moved to > a link TRB, trb_in_td() would fail (because the dequeue pointer and > dequeue segment were out-of-sync), and this message would appear: > > ERROR Transfer event TRB DMA ptr not part of current TD > > This fixes bugzilla entry 4333 (option-based modem unhappy on USB 3.0 > port: "Transfer event TRB DMA ptr not part of current TD", "rejecting > I/O to offline device"), > > https://bugzilla.kernel.org/show_bug.cgi?id=43333 > > and possibly other general protection fault bugs as well. > > This patch should be backported to kernels as old as 2.6.31. A separate > patch will be created for kernels older than 3.4, since inc_deq was > modified in 3.4 and this patch will not apply.
Care to provide that patch now? thanks, greg k-h -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
