diff options
author | Pete Zaitcev <zaitcev@redhat.com> | 2009-06-11 10:53:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-23 09:46:19 -0400 |
commit | 4e9e92003529e5c7bb11281f7c2c9b3fe8858403 (patch) | |
tree | 07169c9a996a119aebb5865a76ff1177afe90a22 /include/linux | |
parent | f4e2332cfcf900e0a926c4e0fc35f751bcbcaa1b (diff) |
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>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/usb.h | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/include/linux/usb.h b/include/linux/usb.h index 19fabc487beb..3b45a0d27b80 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -1036,9 +1036,10 @@ typedef void (*usb_complete_t)(struct urb *); | |||
1036 | * @transfer_flags: A variety of flags may be used to affect how URB | 1036 | * @transfer_flags: A variety of flags may be used to affect how URB |
1037 | * submission, unlinking, or operation are handled. Different | 1037 | * submission, unlinking, or operation are handled. Different |
1038 | * kinds of URB can use different flags. | 1038 | * kinds of URB can use different flags. |
1039 | * @transfer_buffer: This identifies the buffer to (or from) which | 1039 | * @transfer_buffer: This identifies the buffer to (or from) which the I/O |
1040 | * the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP | 1040 | * request will be performed unless URB_NO_TRANSFER_DMA_MAP is set |
1041 | * is set). This buffer must be suitable for DMA; allocate it with | 1041 | * (however, do not leave garbage in transfer_buffer even then). |
1042 | * This buffer must be suitable for DMA; allocate it with | ||
1042 | * kmalloc() or equivalent. For transfers to "in" endpoints, contents | 1043 | * kmalloc() or equivalent. For transfers to "in" endpoints, contents |
1043 | * of this buffer will be modified. This buffer is used for the data | 1044 | * of this buffer will be modified. This buffer is used for the data |
1044 | * stage of control transfers. | 1045 | * stage of control transfers. |
@@ -1104,9 +1105,15 @@ typedef void (*usb_complete_t)(struct urb *); | |||
1104 | * allocate a DMA buffer with usb_buffer_alloc() or call usb_buffer_map(). | 1105 | * allocate a DMA buffer with usb_buffer_alloc() or call usb_buffer_map(). |
1105 | * When these transfer flags are provided, host controller drivers will | 1106 | * When these transfer flags are provided, host controller drivers will |
1106 | * attempt to use the dma addresses found in the transfer_dma and/or | 1107 | * attempt to use the dma addresses found in the transfer_dma and/or |
1107 | * setup_dma fields rather than determining a dma address themselves. (Note | 1108 | * setup_dma fields rather than determining a dma address themselves. |
1108 | * that transfer_buffer and setup_packet must still be set because not all | 1109 | * |
1109 | * host controllers use DMA, nor do virtual root hubs). | 1110 | * Note that transfer_buffer must still be set if the controller |
1111 | * does not support DMA (as indicated by bus.uses_dma) and when talking | ||
1112 | * to root hub. If you have to trasfer between highmem zone and the device | ||
1113 | * on such controller, create a bounce buffer or bail out with an error. | ||
1114 | * If transfer_buffer cannot be set (is in highmem) and the controller is DMA | ||
1115 | * capable, assign NULL to it, so that usbmon knows not to use the value. | ||
1116 | * The setup_packet must always be set, so it cannot be located in highmem. | ||
1110 | * | 1117 | * |
1111 | * Initialization: | 1118 | * Initialization: |
1112 | * | 1119 | * |