From 74b96e0de35261d1d110be02e6a121f2abd2a60e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 6 Nov 2009 12:32:23 -0500 Subject: [PATCH] --- yaml --- r: 174927 b: refs/heads/master c: b375e1169d8ecc9e9db3ecba8147d484b5510833 h: refs/heads/master i: 174925: 7279e1f9dc64a795048b911cfd270ac822cfafab 174923: 13151defd17bc3280119da9f710aa032dd9078d0 174919: c0f93c4477426980c87b5f52c96d5df9584be5fb 174911: e244c5936281bdb5f0426dea75649cb218405a05 v: v3 --- [refs] | 2 +- trunk/drivers/usb/mon/mon_bin.c | 51 ++++++++++++++++++++++++++------ trunk/drivers/usb/mon/mon_text.c | 23 ++++++++++++-- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/[refs] b/[refs] index 95169720cf19..e83968b313c7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 40f8db8f8f5af2cafeb976ae15e11aca641a931d +refs/heads/master: b375e1169d8ecc9e9db3ecba8147d484b5510833 diff --git a/trunk/drivers/usb/mon/mon_bin.c b/trunk/drivers/usb/mon/mon_bin.c index 10f3205798e8..385ec0520167 100644 --- a/trunk/drivers/usb/mon/mon_bin.c +++ b/trunk/drivers/usb/mon/mon_bin.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -221,7 +222,7 @@ static void mon_free_buff(struct mon_pgmap *map, int npages); /* * This is a "chunked memcpy". It does not manipulate any counters. */ -static void mon_copy_to_buff(const struct mon_reader_bin *this, +static unsigned int mon_copy_to_buff(const struct mon_reader_bin *this, unsigned int off, const unsigned char *from, unsigned int length) { unsigned int step_len; @@ -246,6 +247,7 @@ static void mon_copy_to_buff(const struct mon_reader_bin *this, from += step_len; length -= step_len; } + return off; } /* @@ -394,14 +396,44 @@ static inline char mon_bin_get_setup(unsigned char *setupb, return 0; } -static char mon_bin_get_data(const struct mon_reader_bin *rp, - unsigned int offset, struct urb *urb, unsigned int length) +static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp, + unsigned int offset, struct urb *urb, unsigned int length, + char *flag) { + int i; + struct scatterlist *sg; + unsigned int this_len; + + *flag = 0; + if (urb->num_sgs == 0) { + if (urb->transfer_buffer == NULL) { + *flag = 'Z'; + return length; + } + mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); + length = 0; - if (urb->transfer_buffer == NULL) - return 'Z'; - mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); - return 0; + } else { + /* If IOMMU coalescing occurred, we cannot trust sg_page */ + if (urb->sg->nents != urb->num_sgs) { + *flag = 'D'; + return length; + } + + /* Copy up to the first non-addressable segment */ + for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) { + if (length == 0 || PageHighMem(sg_page(sg))) + break; + this_len = min_t(unsigned int, sg->length, length); + offset = mon_copy_to_buff(rp, offset, sg_virt(sg), + this_len); + length -= this_len; + } + if (i == 0) + *flag = 'D'; + } + + return length; } static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, @@ -536,8 +568,9 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, } if (length != 0) { - ep->flag_data = mon_bin_get_data(rp, offset, urb, length); - if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ + length = mon_bin_get_data(rp, offset, urb, length, + &ep->flag_data); + if (length > 0) { delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); ep->len_cap -= length; delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); diff --git a/trunk/drivers/usb/mon/mon_text.c b/trunk/drivers/usb/mon/mon_text.c index 9f1a9227ebe6..047568ff223d 100644 --- a/trunk/drivers/usb/mon/mon_text.c +++ b/trunk/drivers/usb/mon/mon_text.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #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; }