aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-06-23 15:44:58 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-23 15:44:58 -0700
commit5d5d193f7d75d30ae848a96129cb521b41f62693 (patch)
tree1280928a5f26ab9714ba0271d00ec141a50ebce3 /usb
parent542fc82d283978333985aa403c4638e44698bacf (diff)
downloadpatches-5d5d193f7d75d30ae848a96129cb521b41f62693.tar.gz
start working on my to-apply queue
Diffstat (limited to 'usb')
-rw-r--r--usb/usb-ehci-dbg.c-no-need-for-checking-it-before-call-vfree.patch31
-rw-r--r--usb/usb-let-usb_sg_init-to-set-transfer_buffer-more-often.patch72
-rw-r--r--usb/usb-sisusbvga-drop-usb_buffer_alloc.patch173
-rw-r--r--usb/usb-usbmon-drop-kconfig-defaults.patch37
-rw-r--r--usb/usb-usbmon-end-ugly-tricks-with-dma-peeking.patch292
-rw-r--r--usb/usb-usbmon-touch-up-the-documentation.patch30
6 files changed, 635 insertions, 0 deletions
diff --git a/usb/usb-ehci-dbg.c-no-need-for-checking-it-before-call-vfree.patch b/usb/usb-ehci-dbg.c-no-need-for-checking-it-before-call-vfree.patch
new file mode 100644
index 00000000000000..4f41cbe210c23a
--- /dev/null
+++ b/usb/usb-ehci-dbg.c-no-need-for-checking-it-before-call-vfree.patch
@@ -0,0 +1,31 @@
+From figo1802@gmail.com Tue Jun 23 14:44:30 2009
+From: "Figo.zhang" <figo1802@gmail.com>
+Date: Sat, 06 Jun 2009 20:31:49 +0800
+Subject: USB: ehci-dbg.c: no need for checking it before call vfree
+To: Greg Kroah-Hartman <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org, Alan Stern <stern@rowland.harvard.edu>, David Brownell <dbrownell@users.sourceforge.net>
+Message-ID: <1244291509.3185.48.camel@myhost>
+
+
+vfree() does it's own NULL checking,so no need for check before
+calling it.
+
+Signed-off-by: Figo.zhang <figo1802@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/ehci-dbg.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/usb/host/ehci-dbg.c
++++ b/drivers/usb/host/ehci-dbg.c
+@@ -879,8 +879,7 @@ static int debug_close(struct inode *ino
+ struct debug_buffer *buf = file->private_data;
+
+ if (buf) {
+- if (buf->output_buf)
+- vfree(buf->output_buf);
++ vfree(buf->output_buf);
+ kfree(buf);
+ }
+
diff --git a/usb/usb-let-usb_sg_init-to-set-transfer_buffer-more-often.patch b/usb/usb-let-usb_sg_init-to-set-transfer_buffer-more-often.patch
new file mode 100644
index 00000000000000..cce04f92079bfc
--- /dev/null
+++ b/usb/usb-let-usb_sg_init-to-set-transfer_buffer-more-often.patch
@@ -0,0 +1,72 @@
+From zaitcev@redhat.com Tue Jun 23 14:55:50 2009
+From: Pete Zaitcev <zaitcev@redhat.com>
+Date: Thu, 11 Jun 2009 08:40:39 -0600
+Subject: USB: Let usb_sg_init to set transfer_buffer more often
+To: greg@kroah.com
+Cc: linux-usb@vger.kernel.org
+Message-ID: <20090611084039.c62e0b9d.zaitcev@redhat.com>
+
+
+This fix permits the "new" usbmon to access usb-storage's data buffer
+without DMA remapping tricks. It should be compatible with PIO controllers
+and not add any new crashes. Note that from now on PIO controllers and
+usbmon are uniform in their access pattern and if one crashes then
+the other will too. Hopefuly neither does.
+
+As a side effect, we get rid for #ifdefs, which were a little ugly.
+
+Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/message.c | 32 ++++++++++----------------------
+ 1 file changed, 10 insertions(+), 22 deletions(-)
+
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -459,35 +459,23 @@ int usb_sg_init(struct usb_sg_request *i
+ io->urbs[i]->context = io;
+
+ /*
+- * Some systems need to revert to PIO when DMA is
+- * temporarily unavailable. For their sakes, both
+- * transfer_buffer and transfer_dma are set when
+- * possible. However this can only work on systems
+- * without:
++ * Some systems need to revert to PIO when DMA is temporarily
++ * unavailable. For their sakes, both transfer_buffer and
++ * transfer_dma are set when possible.
+ *
+- * - HIGHMEM, since DMA buffers located in high memory
+- * are not directly addressable by the CPU for PIO;
+- *
+- * - IOMMU, since dma_map_sg() is allowed to use an
+- * IOMMU to make virtually discontiguous buffers be
+- * "dma-contiguous" so that PIO and DMA need diferent
+- * numbers of URBs.
+- *
+- * So when HIGHMEM or IOMMU are in use, transfer_buffer
+- * is NULL to prevent stale pointers and to help spot
+- * bugs.
++ * Note that if IOMMU coalescing occurred, we cannot
++ * trust sg_page anymore, so check if S/G list shrunk.
+ */
++ if (io->nents == io->entries && !PageHighMem(sg_page(sg)))
++ io->urbs[i]->transfer_buffer = sg_virt(sg);
++ else
++ io->urbs[i]->transfer_buffer = NULL;
++
+ if (dma) {
+ io->urbs[i]->transfer_dma = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+-#if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
+- io->urbs[i]->transfer_buffer = NULL;
+-#else
+- io->urbs[i]->transfer_buffer = sg_virt(sg);
+-#endif
+ } else {
+ /* hc may use _only_ transfer_buffer */
+- io->urbs[i]->transfer_buffer = sg_virt(sg);
+ len = sg->length;
+ }
+
diff --git a/usb/usb-sisusbvga-drop-usb_buffer_alloc.patch b/usb/usb-sisusbvga-drop-usb_buffer_alloc.patch
new file mode 100644
index 00000000000000..cdf6152bf6f9e7
--- /dev/null
+++ b/usb/usb-sisusbvga-drop-usb_buffer_alloc.patch
@@ -0,0 +1,173 @@
+From zaitcev@redhat.com Tue Jun 23 14:53:56 2009
+From: Pete Zaitcev <zaitcev@redhat.com>
+Date: Wed, 10 Jun 2009 14:15:52 -0600
+Subject: USB: sisusbvga: drop usb_buffer_alloc
+To: greg@kroah.com
+Cc: linux-usb@vger.kernel.org, zaitcev@redhat.com
+Message-ID: <20090610141552.bda8b650.zaitcev@redhat.com>
+
+
+This patch falls out of my work to fix usbmon so it uses virtual addresses.
+It is not necessary, the "new" usbmon should work just fine with sisusbvga.
+However, it seems ridiculous that anyone would use uncached memory to
+transfer bulk data. Dropping the unnecessary use of usb_buffer_alloc
+should be beneficial here, in case anyone ever uses the dongle on
+anything beyond x86.
+
+I had no success in raising the author of the driver by e-mail, so
+the patch is not actually tested.
+
+Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/misc/sisusbvga/sisusb.c | 53 ++++++++----------------------------
+ drivers/usb/misc/sisusbvga/sisusb.h | 2 -
+ 2 files changed, 13 insertions(+), 42 deletions(-)
+
+--- a/drivers/usb/misc/sisusbvga/sisusb.c
++++ b/drivers/usb/misc/sisusbvga/sisusb.c
+@@ -79,14 +79,12 @@ sisusb_free_buffers(struct sisusb_usb_da
+
+ for (i = 0; i < NUMOBUFS; i++) {
+ if (sisusb->obuf[i]) {
+- usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
+- sisusb->obuf[i], sisusb->transfer_dma_out[i]);
++ kfree(sisusb->obuf[i]);
+ sisusb->obuf[i] = NULL;
+ }
+ }
+ if (sisusb->ibuf) {
+- usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
+- sisusb->ibuf, sisusb->transfer_dma_in);
++ kfree(sisusb->ibuf);
+ sisusb->ibuf = NULL;
+ }
+ }
+@@ -230,8 +228,7 @@ sisusb_bulk_completeout(struct urb *urb)
+
+ static int
+ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
+- int len, int *actual_length, int timeout, unsigned int tflags,
+- dma_addr_t transfer_dma)
++ int len, int *actual_length, int timeout, unsigned int tflags)
+ {
+ struct urb *urb = sisusb->sisurbout[index];
+ int retval, byteswritten = 0;
+@@ -245,9 +242,6 @@ sisusb_bulkout_msg(struct sisusb_usb_dat
+ urb->transfer_flags |= tflags;
+ urb->actual_length = 0;
+
+- if ((urb->transfer_dma = transfer_dma))
+- urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+-
+ /* Set up context */
+ sisusb->urbout_context[index].actual_length = (timeout) ?
+ NULL : actual_length;
+@@ -297,8 +291,8 @@ sisusb_bulk_completein(struct urb *urb)
+ }
+
+ static int
+-sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
+- int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
++sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
++ int len, int *actual_length, int timeout, unsigned int tflags)
+ {
+ struct urb *urb = sisusb->sisurbin;
+ int retval, readbytes = 0;
+@@ -311,9 +305,6 @@ sisusb_bulkin_msg(struct sisusb_usb_data
+ urb->transfer_flags |= tflags;
+ urb->actual_length = 0;
+
+- if ((urb->transfer_dma = transfer_dma))
+- urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+-
+ sisusb->completein = 0;
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval == 0) {
+@@ -422,8 +413,7 @@ static int sisusb_send_bulk_msg(struct s
+ thispass,
+ &transferred_len,
+ async ? 0 : 5 * HZ,
+- tflags,
+- sisusb->transfer_dma_out[index]);
++ tflags);
+
+ if (result == -ETIMEDOUT) {
+
+@@ -432,29 +422,16 @@ static int sisusb_send_bulk_msg(struct s
+ return -ETIME;
+
+ continue;
++ }
+
+- } else if ((result == 0) && !async && transferred_len) {
++ if ((result == 0) && !async && transferred_len) {
+
+ thispass -= transferred_len;
+- if (thispass) {
+- if (sisusb->transfer_dma_out) {
+- /* If DMA, copy remaining
+- * to beginning of buffer
+- */
+- memcpy(buffer,
+- buffer + transferred_len,
+- thispass);
+- } else {
+- /* If not DMA, simply increase
+- * the pointer
+- */
+- buffer += transferred_len;
+- }
+- }
++ buffer += transferred_len;
+
+ } else
+ break;
+- };
++ }
+
+ if (result)
+ return result;
+@@ -530,8 +507,7 @@ static int sisusb_recv_bulk_msg(struct s
+ thispass,
+ &transferred_len,
+ 5 * HZ,
+- tflags,
+- sisusb->transfer_dma_in);
++ tflags);
+
+ if (transferred_len)
+ thispass = transferred_len;
+@@ -3132,8 +3108,7 @@ static int sisusb_probe(struct usb_inter
+
+ /* Allocate buffers */
+ sisusb->ibufsize = SISUSB_IBUF_SIZE;
+- if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
+- GFP_KERNEL, &sisusb->transfer_dma_in))) {
++ if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) {
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer");
+ retval = -ENOMEM;
+ goto error_2;
+@@ -3142,9 +3117,7 @@ static int sisusb_probe(struct usb_inter
+ sisusb->numobufs = 0;
+ sisusb->obufsize = SISUSB_OBUF_SIZE;
+ for (i = 0; i < NUMOBUFS; i++) {
+- if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
+- GFP_KERNEL,
+- &sisusb->transfer_dma_out[i]))) {
++ if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) {
+ if (i == 0) {
+ dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n");
+ retval = -ENOMEM;
+--- a/drivers/usb/misc/sisusbvga/sisusb.h
++++ b/drivers/usb/misc/sisusbvga/sisusb.h
+@@ -123,8 +123,6 @@ struct sisusb_usb_data {
+ int numobufs; /* number of obufs = number of out urbs */
+ char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */
+ int obufsize, ibufsize;
+- dma_addr_t transfer_dma_out[NUMOBUFS];
+- dma_addr_t transfer_dma_in;
+ struct urb *sisurbout[NUMOBUFS];
+ struct urb *sisurbin;
+ unsigned char urbstatus[NUMOBUFS];
diff --git a/usb/usb-usbmon-drop-kconfig-defaults.patch b/usb/usb-usbmon-drop-kconfig-defaults.patch
new file mode 100644
index 00000000000000..4d35b74a3fd689
--- /dev/null
+++ b/usb/usb-usbmon-drop-kconfig-defaults.patch
@@ -0,0 +1,37 @@
+From zaitcev@redhat.com Tue Jun 23 14:54:10 2009
+From: Pete Zaitcev <zaitcev@redhat.com>
+Date: Wed, 10 Jun 2009 15:21:24 -0600
+Subject: USB: usbmon: drop Kconfig defaults
+To: linux-usb@vger.kernel.org, <greg@kroah.com>
+Cc: Paul Bolle <pebolle@tiscali.nl>, Alan Stern <stern@rowland.harvard.edu>, David Brownell <david-b@pacbell.net>, zaitcev@redhat.com
+Message-ID: <20090610152124.ee8df387.zaitcev@redhat.com>
+
+
+These statements seem to be unnecessary. No idea why, but I built all
+possible configurations and everything gets built just as before.
+
+It's an old patch that popped from discussion with Paul in November 2008.
+Obviously not a very high priority but better late than never.
+
+Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/mon/Kconfig | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/usb/mon/Kconfig
++++ b/drivers/usb/mon/Kconfig
+@@ -5,11 +5,9 @@
+ config USB_MON
+ tristate "USB Monitor"
+ depends on USB
+- default y if USB=y
+- default m if USB=m
+ help
+ If you select this option, a component which captures the USB traffic
+ between peripheral-specific drivers and HC drivers will be built.
+ For more information, see <file:Documentation/usb/usbmon.txt>.
+
+- If unsure, say Y (if allowed), otherwise M.
++ If unsure, say Y, if allowed, otherwise M.
diff --git a/usb/usb-usbmon-end-ugly-tricks-with-dma-peeking.patch b/usb/usb-usbmon-end-ugly-tricks-with-dma-peeking.patch
new file mode 100644
index 00000000000000..ac9105d6514a83
--- /dev/null
+++ b/usb/usb-usbmon-end-ugly-tricks-with-dma-peeking.patch
@@ -0,0 +1,292 @@
+From zaitcev@redhat.com Tue Jun 23 14:57:55 2009
+From: Pete Zaitcev <zaitcev@redhat.com>
+Date: Thu, 11 Jun 2009 08:53:20 -0600
+Subject: USB: usbmon: end ugly tricks with DMA peeking
+To: greg@kroah.com
+Cc: zaitcev@redhat.com, linux-usb@vger.kernel.org
+Message-ID: <20090611085320.dc54a513.zaitcev@redhat.com>
+
+
+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>
+
+---
+ drivers/usb/mon/Makefile | 2
+ drivers/usb/mon/mon_bin.c | 12 -----
+ drivers/usb/mon/mon_dma.c | 95 ---------------------------------------------
+ drivers/usb/mon/mon_main.c | 1
+ drivers/usb/mon/mon_text.c | 14 ------
+ drivers/usb/mon/usb_mon.h | 14 ------
+ include/linux/usb.h | 19 ++++++---
+ 7 files changed, 15 insertions(+), 142 deletions(-)
+
+--- a/drivers/usb/mon/Makefile
++++ b/drivers/usb/mon/Makefile
+@@ -2,6 +2,6 @@
+ # Makefile for USB monitor
+ #
+
+-usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o
++usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o
+
+ obj-$(CONFIG_USB_MON) += usbmon.o
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -220,9 +220,8 @@ static void mon_free_buff(struct mon_pgm
+
+ /*
+ * This is a "chunked memcpy". It does not manipulate any counters.
+- * But it returns the new offset for repeated application.
+ */
+-unsigned int mon_copy_to_buff(const struct mon_reader_bin *this,
++static void mon_copy_to_buff(const struct mon_reader_bin *this,
+ unsigned int off, const unsigned char *from, unsigned int length)
+ {
+ unsigned int step_len;
+@@ -247,7 +246,6 @@ unsigned int mon_copy_to_buff(const stru
+ from += step_len;
+ length -= step_len;
+ }
+- return off;
+ }
+
+ /*
+@@ -400,15 +398,8 @@ static char mon_bin_get_data(const struc
+ unsigned int offset, struct urb *urb, unsigned int length)
+ {
+
+- if (urb->dev->bus->uses_dma &&
+- (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+- mon_dmapeek_vec(rp, offset, urb->transfer_dma, length);
+- return 0;
+- }
+-
+ if (urb->transfer_buffer == NULL)
+ return 'Z';
+-
+ mon_copy_to_buff(rp, offset, urb->transfer_buffer, length);
+ return 0;
+ }
+@@ -635,7 +626,6 @@ static int mon_bin_open(struct inode *in
+ spin_lock_init(&rp->b_lock);
+ init_waitqueue_head(&rp->b_wait);
+ mutex_init(&rp->fetch_lock);
+-
+ rp->b_size = BUFF_DFL;
+
+ size = sizeof(struct mon_pgmap) * (rp->b_size/CHUNK_SIZE);
+--- a/drivers/usb/mon/mon_dma.c
++++ /dev/null
+@@ -1,95 +0,0 @@
+-/*
+- * The USB Monitor, inspired by Dave Harding's USBMon.
+- *
+- * mon_dma.c: Library which snoops on DMA areas.
+- *
+- * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com)
+- */
+-#include <linux/kernel.h>
+-#include <linux/list.h>
+-#include <linux/highmem.h>
+-#include <asm/page.h>
+-
+-#include <linux/usb.h> /* Only needed for declarations in usb_mon.h */
+-#include "usb_mon.h"
+-
+-/*
+- * PC-compatibles, are, fortunately, sufficiently cache-coherent for this.
+- */
+-#if defined(__i386__) || defined(__x86_64__) /* CONFIG_ARCH_I386 doesn't exit */
+-#define MON_HAS_UNMAP 1
+-
+-#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
+-
+-char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len)
+-{
+- struct page *pg;
+- unsigned long flags;
+- unsigned char *map;
+- unsigned char *ptr;
+-
+- /*
+- * On i386, a DMA handle is the "physical" address of a page.
+- * In other words, the bus address is equal to physical address.
+- * There is no IOMMU.
+- */
+- pg = phys_to_page(dma_addr);
+-
+- /*
+- * We are called from hardware IRQs in case of callbacks.
+- * But we can be called from softirq or process context in case
+- * of submissions. In such case, we need to protect KM_IRQ0.
+- */
+- local_irq_save(flags);
+- map = kmap_atomic(pg, KM_IRQ0);
+- ptr = map + (dma_addr & (PAGE_SIZE-1));
+- memcpy(dst, ptr, len);
+- kunmap_atomic(map, KM_IRQ0);
+- local_irq_restore(flags);
+- return 0;
+-}
+-
+-void mon_dmapeek_vec(const struct mon_reader_bin *rp,
+- unsigned int offset, dma_addr_t dma_addr, unsigned int length)
+-{
+- unsigned long flags;
+- unsigned int step_len;
+- struct page *pg;
+- unsigned char *map;
+- unsigned long page_off, page_len;
+-
+- local_irq_save(flags);
+- while (length) {
+- /* compute number of bytes we are going to copy in this page */
+- step_len = length;
+- page_off = dma_addr & (PAGE_SIZE-1);
+- page_len = PAGE_SIZE - page_off;
+- if (page_len < step_len)
+- step_len = page_len;
+-
+- /* copy data and advance pointers */
+- pg = phys_to_page(dma_addr);
+- map = kmap_atomic(pg, KM_IRQ0);
+- offset = mon_copy_to_buff(rp, offset, map + page_off, step_len);
+- kunmap_atomic(map, KM_IRQ0);
+- dma_addr += step_len;
+- length -= step_len;
+- }
+- local_irq_restore(flags);
+-}
+-
+-#endif /* __i386__ */
+-
+-#ifndef MON_HAS_UNMAP
+-char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len)
+-{
+- return 'D';
+-}
+-
+-void mon_dmapeek_vec(const struct mon_reader_bin *rp,
+- unsigned int offset, dma_addr_t dma_addr, unsigned int length)
+-{
+- ;
+-}
+-
+-#endif /* MON_HAS_UNMAP */
+--- a/drivers/usb/mon/mon_main.c
++++ b/drivers/usb/mon/mon_main.c
+@@ -361,7 +361,6 @@ static int __init mon_init(void)
+ }
+ // MOD_INC_USE_COUNT(which_module?);
+
+-
+ mutex_lock(&usb_bus_list_lock);
+ list_for_each_entry (ubus, &usb_bus_list, bus_list) {
+ mon_bus_init(ubus);
+--- a/drivers/usb/mon/mon_text.c
++++ b/drivers/usb/mon/mon_text.c
+@@ -150,20 +150,6 @@ static inline char mon_text_get_data(str
+ return '>';
+ }
+
+- /*
+- * The check to see if it's safe to poke at data has an enormous
+- * number of corner cases, but it seems that the following is
+- * more or less safe.
+- *
+- * We do not even try to look at transfer_buffer, because it can
+- * contain non-NULL garbage in case the upper level promised to
+- * set DMA for the HCD.
+- */
+- if (urb->dev->bus->uses_dma &&
+- (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+- return mon_dmapeek(ep->data, urb->transfer_dma, len);
+- }
+-
+ if (urb->transfer_buffer == NULL)
+ return 'Z'; /* '0' would be not as pretty. */
+
+--- a/drivers/usb/mon/usb_mon.h
++++ b/drivers/usb/mon/usb_mon.h
+@@ -65,20 +65,6 @@ int __init mon_bin_init(void);
+ void mon_bin_exit(void);
+
+ /*
+- * DMA interface.
+- *
+- * XXX The vectored side needs a serious re-thinking. Abstracting vectors,
+- * like in Paolo's original patch, produces a double pkmap. We need an idea.
+-*/
+-extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len);
+-
+-struct mon_reader_bin;
+-extern void mon_dmapeek_vec(const struct mon_reader_bin *rp,
+- unsigned int offset, dma_addr_t dma_addr, unsigned int len);
+-extern unsigned int mon_copy_to_buff(const struct mon_reader_bin *rp,
+- unsigned int offset, const unsigned char *from, unsigned int len);
+-
+-/*
+ */
+ extern struct mutex mon_lock;
+
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -1036,9 +1036,10 @@ typedef void (*usb_complete_t)(struct ur
+ * @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.
+@@ -1102,9 +1103,15 @@ typedef void (*usb_complete_t)(struct ur
+ * 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:
+ *
diff --git a/usb/usb-usbmon-touch-up-the-documentation.patch b/usb/usb-usbmon-touch-up-the-documentation.patch
new file mode 100644
index 00000000000000..8b0069d8f396be
--- /dev/null
+++ b/usb/usb-usbmon-touch-up-the-documentation.patch
@@ -0,0 +1,30 @@
+From zaitcev@redhat.com Tue Jun 23 14:54:22 2009
+From: Pete Zaitcev <zaitcev@redhat.com>
+Date: Wed, 10 Jun 2009 15:23:52 -0600
+Subject: USB: usbmon: touch up the documentation
+To: greg@kroah.com
+Cc: linux-usb@vger.kernel.org
+Message-ID: <20090610152352.c25a7d99.zaitcev@redhat.com>
+
+
+I think this sentence was confusing regarding the possible size
+of the data area.
+
+Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ Documentation/usb/usbmon.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/Documentation/usb/usbmon.txt
++++ b/Documentation/usb/usbmon.txt
+@@ -305,7 +305,7 @@ Before the call, hdr, data, and alloc sh
+ pointed by hdr contains the next event structure, and the data buffer contains
+ the data, if any. The event is removed from the kernel buffer.
+
+-The MON_IOCX_GET copies 48 bytes, MON_IOCX_GETX copies 64 bytes.
++The MON_IOCX_GET copies 48 bytes to hdr area, MON_IOCX_GETX copies 64 bytes.
+
+ MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg)
+