diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2009-11-06 12:32:23 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-12-11 11:55:20 -0800 |
commit | b375e1169d8ecc9e9db3ecba8147d484b5510833 (patch) | |
tree | 6e82dd614c4a36d725b7250ced5a48a76c301607 /drivers/usb/mon/mon_text.c | |
parent | 40f8db8f8f5af2cafeb976ae15e11aca641a931d (diff) |
USB: add scatter-gather support to usbmon
This patch (as1301) adds support to usbmon for scatter-gather URBs.
The text interface looks at only the first scatterlist element, since
it never copies more than 32 bytes of data anyway. The binary
interface copies as much data as possible up to the first
non-addressable buffer.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/mon/mon_text.c')
-rw-r--r-- | drivers/usb/mon/mon_text.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 9f1a9227ebe6..047568ff223d 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -10,6 +10,7 @@ #include <linux/time.h> #include <linux/mutex.h> #include <linux/debugfs.h> +#include <linux/scatterlist.h> #include <asm/uaccess.h> #include "usb_mon.h" @@ -137,6 +138,8 @@ static inline char mon_text_get_setup(struct mon_event_text *ep, static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, int len, char ev_type, struct mon_bus *mbus) { + void *src; + if (len <= 0) return 'L'; if (len >= DATA_MAX) @@ -150,10 +153,24 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, return '>'; } - if (urb->transfer_buffer == NULL) - return 'Z'; /* '0' would be not as pretty. */ + if (urb->num_sgs == 0) { + src = urb->transfer_buffer; + if (src == NULL) + return 'Z'; /* '0' would be not as pretty. */ + } else { + struct scatterlist *sg = urb->sg->sg; + + /* If IOMMU coalescing occurred, we cannot trust sg_page */ + if (urb->sg->nents != urb->num_sgs || + PageHighMem(sg_page(sg))) + return 'D'; + + /* For the text interface we copy only the first sg buffer */ + len = min_t(int, sg->length, len); + src = sg_virt(sg); + } - memcpy(ep->data, urb->transfer_buffer, len); + memcpy(ep->data, src, len); return 0; } |