diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2010-04-02 13:27:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:37 -0400 |
commit | ff9c895f07d36193c75533bda8193bde8ca99d02 (patch) | |
tree | 386ca8e37734c4810e59a55eaba92e4e88275d14 /drivers/usb/mon | |
parent | 0ff8d1b3c858ea7c8daa54f7577971a76d04d283 (diff) |
USB: fix usbmon and DMA mapping for scatter-gather URBs
This patch (as1368) fixes a rather obscure bug in usbmon: When tracing
URBs sent by the scatter-gather library, it accesses the data buffers
while they are still mapped for DMA.
The solution is to move the mapping and unmapping out of the s-g
library and into the usual place in hcd.c. This requires the addition
of new URB flag bits to describe the kind of mapping needed, since we
have to call dma_map_sg() if the HCD supports native scatter-gather
operation and dma_map_page() if it doesn't. The nice thing about
having the new flags is that they simplify the testing for unmapping.
The patch removes the only caller of usb_buffer_[un]map_sg(), so those
functions are #if'ed out. A later patch will remove them entirely.
As a result of this change, urb->sg will be set in situations where
it wasn't set previously. Hence the xhci and whci drivers are
adjusted to test urb->num_sgs instead, which retains its original
meaning and is nonzero only when the HCD has to handle a scatterlist.
Finally, even when a submission error occurs we don't want to hand
URBs to usbmon before they are unmapped. The submission path is
rearranged so that map_urb_for_dma() is called only for non-root-hub
URBs and unmap_urb_for_dma() is called immediately after a submission
error. This simplifies the error handling.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/mon')
-rw-r--r-- | drivers/usb/mon/mon_bin.c | 2 | ||||
-rw-r--r-- | drivers/usb/mon/mon_text.c | 4 |
2 files changed, 2 insertions, 4 deletions
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index ddf7f9a1b336..8a7968df278f 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -416,7 +416,7 @@ static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp, | |||
416 | 416 | ||
417 | } else { | 417 | } else { |
418 | /* If IOMMU coalescing occurred, we cannot trust sg_page */ | 418 | /* If IOMMU coalescing occurred, we cannot trust sg_page */ |
419 | if (urb->sg->nents != urb->num_sgs) { | 419 | if (urb->transfer_flags & URB_DMA_SG_COMBINED) { |
420 | *flag = 'D'; | 420 | *flag = 'D'; |
421 | return length; | 421 | return length; |
422 | } | 422 | } |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 4d0be130f49b..d56260280f54 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -161,9 +161,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | |||
161 | } else { | 161 | } else { |
162 | struct scatterlist *sg = urb->sg->sg; | 162 | struct scatterlist *sg = urb->sg->sg; |
163 | 163 | ||
164 | /* If IOMMU coalescing occurred, we cannot trust sg_page */ | 164 | if (PageHighMem(sg_page(sg))) |
165 | if (urb->sg->nents != urb->num_sgs || | ||
166 | PageHighMem(sg_page(sg))) | ||
167 | return 'D'; | 165 | return 'D'; |
168 | 166 | ||
169 | /* For the text interface we copy only the first sg buffer */ | 167 | /* For the text interface we copy only the first sg buffer */ |