diff options
Diffstat (limited to 'drivers/usb/mon')
-rw-r--r-- | drivers/usb/mon/mon_bin.c | 59 | ||||
-rw-r--r-- | drivers/usb/mon/mon_main.c | 1 | ||||
-rw-r--r-- | drivers/usb/mon/mon_stat.c | 1 | ||||
-rw-r--r-- | drivers/usb/mon/mon_text.c | 30 |
4 files changed, 75 insertions, 16 deletions
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 10f3205798e8..ddf7f9a1b336 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/compat.h> | 16 | #include <linux/compat.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/smp_lock.h> | 18 | #include <linux/smp_lock.h> |
19 | #include <linux/scatterlist.h> | ||
20 | #include <linux/slab.h> | ||
19 | 21 | ||
20 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
21 | 23 | ||
@@ -221,7 +223,7 @@ static void mon_free_buff(struct mon_pgmap *map, int npages); | |||
221 | /* | 223 | /* |
222 | * This is a "chunked memcpy". It does not manipulate any counters. | 224 | * This is a "chunked memcpy". It does not manipulate any counters. |
223 | */ | 225 | */ |
224 | static void mon_copy_to_buff(const struct mon_reader_bin *this, | 226 | static unsigned int mon_copy_to_buff(const struct mon_reader_bin *this, |
225 | unsigned int off, const unsigned char *from, unsigned int length) | 227 | unsigned int off, const unsigned char *from, unsigned int length) |
226 | { | 228 | { |
227 | unsigned int step_len; | 229 | unsigned int step_len; |
@@ -246,6 +248,7 @@ static void mon_copy_to_buff(const struct mon_reader_bin *this, | |||
246 | from += step_len; | 248 | from += step_len; |
247 | length -= step_len; | 249 | length -= step_len; |
248 | } | 250 | } |
251 | return off; | ||
249 | } | 252 | } |
250 | 253 | ||
251 | /* | 254 | /* |
@@ -394,14 +397,44 @@ static inline char mon_bin_get_setup(unsigned char *setupb, | |||
394 | return 0; | 397 | return 0; |
395 | } | 398 | } |
396 | 399 | ||
397 | static char mon_bin_get_data(const struct mon_reader_bin *rp, | 400 | static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp, |
398 | unsigned int offset, struct urb *urb, unsigned int length) | 401 | unsigned int offset, struct urb *urb, unsigned int length, |
402 | char *flag) | ||
399 | { | 403 | { |
404 | int i; | ||
405 | struct scatterlist *sg; | ||
406 | unsigned int this_len; | ||
407 | |||
408 | *flag = 0; | ||
409 | if (urb->num_sgs == 0) { | ||
410 | if (urb->transfer_buffer == NULL) { | ||
411 | *flag = 'Z'; | ||
412 | return length; | ||
413 | } | ||
414 | mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); | ||
415 | length = 0; | ||
400 | 416 | ||
401 | if (urb->transfer_buffer == NULL) | 417 | } else { |
402 | return 'Z'; | 418 | /* If IOMMU coalescing occurred, we cannot trust sg_page */ |
403 | mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); | 419 | if (urb->sg->nents != urb->num_sgs) { |
404 | return 0; | 420 | *flag = 'D'; |
421 | return length; | ||
422 | } | ||
423 | |||
424 | /* Copy up to the first non-addressable segment */ | ||
425 | for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) { | ||
426 | if (length == 0 || PageHighMem(sg_page(sg))) | ||
427 | break; | ||
428 | this_len = min_t(unsigned int, sg->length, length); | ||
429 | offset = mon_copy_to_buff(rp, offset, sg_virt(sg), | ||
430 | this_len); | ||
431 | length -= this_len; | ||
432 | } | ||
433 | if (i == 0) | ||
434 | *flag = 'D'; | ||
435 | } | ||
436 | |||
437 | return length; | ||
405 | } | 438 | } |
406 | 439 | ||
407 | static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, | 440 | static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, |
@@ -428,8 +461,8 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, | |||
428 | char ev_type, int status) | 461 | char ev_type, int status) |
429 | { | 462 | { |
430 | const struct usb_endpoint_descriptor *epd = &urb->ep->desc; | 463 | const struct usb_endpoint_descriptor *epd = &urb->ep->desc; |
431 | unsigned long flags; | ||
432 | struct timeval ts; | 464 | struct timeval ts; |
465 | unsigned long flags; | ||
433 | unsigned int urb_length; | 466 | unsigned int urb_length; |
434 | unsigned int offset; | 467 | unsigned int offset; |
435 | unsigned int length; | 468 | unsigned int length; |
@@ -536,8 +569,9 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, | |||
536 | } | 569 | } |
537 | 570 | ||
538 | if (length != 0) { | 571 | if (length != 0) { |
539 | ep->flag_data = mon_bin_get_data(rp, offset, urb, length); | 572 | length = mon_bin_get_data(rp, offset, urb, length, |
540 | if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ | 573 | &ep->flag_data); |
574 | if (length > 0) { | ||
541 | delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); | 575 | delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); |
542 | ep->len_cap -= length; | 576 | ep->len_cap -= length; |
543 | delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); | 577 | delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1); |
@@ -567,10 +601,13 @@ static void mon_bin_complete(void *data, struct urb *urb, int status) | |||
567 | static void mon_bin_error(void *data, struct urb *urb, int error) | 601 | static void mon_bin_error(void *data, struct urb *urb, int error) |
568 | { | 602 | { |
569 | struct mon_reader_bin *rp = data; | 603 | struct mon_reader_bin *rp = data; |
604 | struct timeval ts; | ||
570 | unsigned long flags; | 605 | unsigned long flags; |
571 | unsigned int offset; | 606 | unsigned int offset; |
572 | struct mon_bin_hdr *ep; | 607 | struct mon_bin_hdr *ep; |
573 | 608 | ||
609 | do_gettimeofday(&ts); | ||
610 | |||
574 | spin_lock_irqsave(&rp->b_lock, flags); | 611 | spin_lock_irqsave(&rp->b_lock, flags); |
575 | 612 | ||
576 | offset = mon_buff_area_alloc(rp, PKT_SIZE); | 613 | offset = mon_buff_area_alloc(rp, PKT_SIZE); |
@@ -590,6 +627,8 @@ static void mon_bin_error(void *data, struct urb *urb, int error) | |||
590 | ep->devnum = urb->dev->devnum; | 627 | ep->devnum = urb->dev->devnum; |
591 | ep->busnum = urb->dev->bus->busnum; | 628 | ep->busnum = urb->dev->bus->busnum; |
592 | ep->id = (unsigned long) urb; | 629 | ep->id = (unsigned long) urb; |
630 | ep->ts_sec = ts.tv_sec; | ||
631 | ep->ts_usec = ts.tv_usec; | ||
593 | ep->status = error; | 632 | ep->status = error; |
594 | 633 | ||
595 | ep->flag_setup = '-'; | 634 | ep->flag_setup = '-'; |
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index e0c2db3b767b..e4af18b93c7d 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/usb.h> | 11 | #include <linux/usb.h> |
12 | #include <linux/slab.h> | ||
12 | #include <linux/notifier.h> | 13 | #include <linux/notifier.h> |
13 | #include <linux/mutex.h> | 14 | #include <linux/mutex.h> |
14 | 15 | ||
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c index ac8b0d5ce7f8..1becdc3837e6 100644 --- a/drivers/usb/mon/mon_stat.c +++ b/drivers/usb/mon/mon_stat.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/slab.h> | ||
11 | #include <linux/usb.h> | 12 | #include <linux/usb.h> |
12 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
13 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 9f1a9227ebe6..4d0be130f49b 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -7,9 +7,11 @@ | |||
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
8 | #include <linux/list.h> | 8 | #include <linux/list.h> |
9 | #include <linux/usb.h> | 9 | #include <linux/usb.h> |
10 | #include <linux/slab.h> | ||
10 | #include <linux/time.h> | 11 | #include <linux/time.h> |
11 | #include <linux/mutex.h> | 12 | #include <linux/mutex.h> |
12 | #include <linux/debugfs.h> | 13 | #include <linux/debugfs.h> |
14 | #include <linux/scatterlist.h> | ||
13 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
14 | 16 | ||
15 | #include "usb_mon.h" | 17 | #include "usb_mon.h" |
@@ -137,6 +139,8 @@ static inline char mon_text_get_setup(struct mon_event_text *ep, | |||
137 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | 139 | static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, |
138 | int len, char ev_type, struct mon_bus *mbus) | 140 | int len, char ev_type, struct mon_bus *mbus) |
139 | { | 141 | { |
142 | void *src; | ||
143 | |||
140 | if (len <= 0) | 144 | if (len <= 0) |
141 | return 'L'; | 145 | return 'L'; |
142 | if (len >= DATA_MAX) | 146 | if (len >= DATA_MAX) |
@@ -150,10 +154,24 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, | |||
150 | return '>'; | 154 | return '>'; |
151 | } | 155 | } |
152 | 156 | ||
153 | if (urb->transfer_buffer == NULL) | 157 | if (urb->num_sgs == 0) { |
154 | return 'Z'; /* '0' would be not as pretty. */ | 158 | src = urb->transfer_buffer; |
159 | if (src == NULL) | ||
160 | return 'Z'; /* '0' would be not as pretty. */ | ||
161 | } else { | ||
162 | struct scatterlist *sg = urb->sg->sg; | ||
163 | |||
164 | /* If IOMMU coalescing occurred, we cannot trust sg_page */ | ||
165 | if (urb->sg->nents != urb->num_sgs || | ||
166 | PageHighMem(sg_page(sg))) | ||
167 | return 'D'; | ||
155 | 168 | ||
156 | memcpy(ep->data, urb->transfer_buffer, len); | 169 | /* For the text interface we copy only the first sg buffer */ |
170 | len = min_t(int, sg->length, len); | ||
171 | src = sg_virt(sg); | ||
172 | } | ||
173 | |||
174 | memcpy(ep->data, src, len); | ||
157 | return 0; | 175 | return 0; |
158 | } | 176 | } |
159 | 177 | ||
@@ -163,7 +181,7 @@ static inline unsigned int mon_get_timestamp(void) | |||
163 | unsigned int stamp; | 181 | unsigned int stamp; |
164 | 182 | ||
165 | do_gettimeofday(&tval); | 183 | do_gettimeofday(&tval); |
166 | stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s. */ | 184 | stamp = tval.tv_sec & 0xFFF; /* 2^32 = 4294967296. Limit to 4096s. */ |
167 | stamp = stamp * 1000000 + tval.tv_usec; | 185 | stamp = stamp * 1000000 + tval.tv_usec; |
168 | return stamp; | 186 | return stamp; |
169 | } | 187 | } |
@@ -256,12 +274,12 @@ static void mon_text_error(void *data, struct urb *urb, int error) | |||
256 | 274 | ||
257 | ep->type = 'E'; | 275 | ep->type = 'E'; |
258 | ep->id = (unsigned long) urb; | 276 | ep->id = (unsigned long) urb; |
259 | ep->busnum = 0; | 277 | ep->busnum = urb->dev->bus->busnum; |
260 | ep->devnum = urb->dev->devnum; | 278 | ep->devnum = urb->dev->devnum; |
261 | ep->epnum = usb_endpoint_num(&urb->ep->desc); | 279 | ep->epnum = usb_endpoint_num(&urb->ep->desc); |
262 | ep->xfertype = usb_endpoint_type(&urb->ep->desc); | 280 | ep->xfertype = usb_endpoint_type(&urb->ep->desc); |
263 | ep->is_in = usb_urb_dir_in(urb); | 281 | ep->is_in = usb_urb_dir_in(urb); |
264 | ep->tstamp = 0; | 282 | ep->tstamp = mon_get_timestamp(); |
265 | ep->length = 0; | 283 | ep->length = 0; |
266 | ep->status = error; | 284 | ep->status = error; |
267 | 285 | ||