aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/mon/mon_bin.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/mon/mon_bin.c')
-rw-r--r--drivers/usb/mon/mon_bin.c59
1 files changed, 49 insertions, 10 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 */
224static void mon_copy_to_buff(const struct mon_reader_bin *this, 226static 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
397static char mon_bin_get_data(const struct mon_reader_bin *rp, 400static 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
407static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, 440static 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)
567static void mon_bin_error(void *data, struct urb *urb, int error) 601static 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 = '-';