USB: usbmon: end ugly tricks with DMA peeking
This patch fixes crashes when usbmon attempts to access GART aperture. The old code attempted to take a bus address and convert it into a virtual address, which clearly was impossible on systems with actual IOMMUs. Let us not persist in this foolishness, and use transfer_buffer in all cases instead. I think downsides are negligible. The ones I see are: - A driver may pass an address of one buffer down as transfer_buffer, and entirely different entity mapped for DMA, resulting in misleading output of usbmon. Note, however, that PIO based controllers would do transfer the same data that usbmon sees here. - Out of tree drivers may crash usbmon if they store garbage in transfer_buffer. I inspected the in-tree drivers, and clarified the documentation in comments. - Drivers that use get_user_pages will not be possible to monitor. I only found one driver with this problem (drivers/staging/rspiusb). - Same happens with with usb_storage transferring from highmem, but it works fine on 64-bit systems, so I think it's not a concern. At least we don't crash anymore. Why didn't we do this in 2.6.10? That's because back in those days it was popular not to fill in transfer_buffer, so almost all traffic would be invisible (e.g. all of HID was like that). But now, the tree is almost 100% PIO friendly, so we can do the right thing at last. Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f4e2332cfc
commit
4e9e920035
@ -1036,9 +1036,10 @@ typedef void (*usb_complete_t)(struct urb *);
|
||||
* @transfer_flags: A variety of flags may be used to affect how URB
|
||||
* submission, unlinking, or operation are handled. Different
|
||||
* kinds of URB can use different flags.
|
||||
* @transfer_buffer: This identifies the buffer to (or from) which
|
||||
* the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP
|
||||
* is set). This buffer must be suitable for DMA; allocate it with
|
||||
* @transfer_buffer: This identifies the buffer to (or from) which the I/O
|
||||
* request will be performed unless URB_NO_TRANSFER_DMA_MAP is set
|
||||
* (however, do not leave garbage in transfer_buffer even then).
|
||||
* This buffer must be suitable for DMA; allocate it with
|
||||
* kmalloc() or equivalent. For transfers to "in" endpoints, contents
|
||||
* of this buffer will be modified. This buffer is used for the data
|
||||
* stage of control transfers.
|
||||
@ -1104,9 +1105,15 @@ typedef void (*usb_complete_t)(struct urb *);
|
||||
* allocate a DMA buffer with usb_buffer_alloc() or call usb_buffer_map().
|
||||
* When these transfer flags are provided, host controller drivers will
|
||||
* attempt to use the dma addresses found in the transfer_dma and/or
|
||||
* setup_dma fields rather than determining a dma address themselves. (Note
|
||||
* that transfer_buffer and setup_packet must still be set because not all
|
||||
* host controllers use DMA, nor do virtual root hubs).
|
||||
* setup_dma fields rather than determining a dma address themselves.
|
||||
*
|
||||
* Note that transfer_buffer must still be set if the controller
|
||||
* does not support DMA (as indicated by bus.uses_dma) and when talking
|
||||
* to root hub. If you have to trasfer between highmem zone and the device
|
||||
* on such controller, create a bounce buffer or bail out with an error.
|
||||
* If transfer_buffer cannot be set (is in highmem) and the controller is DMA
|
||||
* capable, assign NULL to it, so that usbmon knows not to use the value.
|
||||
* The setup_packet must always be set, so it cannot be located in highmem.
|
||||
*
|
||||
* Initialization:
|
||||
*
|
||||
|
Reference in New Issue
Block a user