aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/mon
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/usb/mon
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/usb/mon')
-rw-r--r--drivers/usb/mon/mon_bin.c59
-rw-r--r--drivers/usb/mon/mon_main.c1
-rw-r--r--drivers/usb/mon/mon_stat.c1
-rw-r--r--drivers/usb/mon/mon_text.c30
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 */
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 = '-';
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,
137static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, 139static 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