aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/mon/mon_text.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/mon/mon_text.c')
-rw-r--r--drivers/usb/mon/mon_text.c126
1 files changed, 78 insertions, 48 deletions
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index f5e1bb5e5217..984f7e12a6a5 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -85,6 +85,8 @@ struct mon_reader_text {
85 85
86 wait_queue_head_t wait; 86 wait_queue_head_t wait;
87 int printf_size; 87 int printf_size;
88 size_t printf_offset;
89 size_t printf_togo;
88 char *printf_buf; 90 char *printf_buf;
89 struct mutex printf_lock; 91 struct mutex printf_lock;
90 92
@@ -376,75 +378,103 @@ err_alloc:
376 return rc; 378 return rc;
377} 379}
378 380
379/* 381static ssize_t mon_text_copy_to_user(struct mon_reader_text *rp,
380 * For simplicity, we read one record in one system call and throw out 382 char __user * const buf, const size_t nbytes)
381 * what does not fit. This means that the following does not work: 383{
382 * dd if=/dbg/usbmon/0t bs=10 384 const size_t togo = min(nbytes, rp->printf_togo);
383 * Also, we do not allow seeks and do not bother advancing the offset. 385
384 */ 386 if (copy_to_user(buf, &rp->printf_buf[rp->printf_offset], togo))
387 return -EFAULT;
388 rp->printf_togo -= togo;
389 rp->printf_offset += togo;
390 return togo;
391}
392
393/* ppos is not advanced since the llseek operation is not permitted. */
385static ssize_t mon_text_read_t(struct file *file, char __user *buf, 394static ssize_t mon_text_read_t(struct file *file, char __user *buf,
386 size_t nbytes, loff_t *ppos) 395 size_t nbytes, loff_t *ppos)
387{ 396{
388 struct mon_reader_text *rp = file->private_data; 397 struct mon_reader_text *rp = file->private_data;
389 struct mon_event_text *ep; 398 struct mon_event_text *ep;
390 struct mon_text_ptr ptr; 399 struct mon_text_ptr ptr;
400 ssize_t ret;
391 401
392 ep = mon_text_read_wait(rp, file);
393 if (IS_ERR(ep))
394 return PTR_ERR(ep);
395 mutex_lock(&rp->printf_lock); 402 mutex_lock(&rp->printf_lock);
396 ptr.cnt = 0; 403
397 ptr.pbuf = rp->printf_buf; 404 if (rp->printf_togo == 0) {
398 ptr.limit = rp->printf_size; 405
399 406 ep = mon_text_read_wait(rp, file);
400 mon_text_read_head_t(rp, &ptr, ep); 407 if (IS_ERR(ep)) {
401 mon_text_read_statset(rp, &ptr, ep); 408 mutex_unlock(&rp->printf_lock);
402 ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, 409 return PTR_ERR(ep);
403 " %d", ep->length); 410 }
404 mon_text_read_data(rp, &ptr, ep); 411 ptr.cnt = 0;
405 412 ptr.pbuf = rp->printf_buf;
406 if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) 413 ptr.limit = rp->printf_size;
407 ptr.cnt = -EFAULT; 414
415 mon_text_read_head_t(rp, &ptr, ep);
416 mon_text_read_statset(rp, &ptr, ep);
417 ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
418 " %d", ep->length);
419 mon_text_read_data(rp, &ptr, ep);
420
421 rp->printf_togo = ptr.cnt;
422 rp->printf_offset = 0;
423
424 kmem_cache_free(rp->e_slab, ep);
425 }
426
427 ret = mon_text_copy_to_user(rp, buf, nbytes);
408 mutex_unlock(&rp->printf_lock); 428 mutex_unlock(&rp->printf_lock);
409 kmem_cache_free(rp->e_slab, ep); 429 return ret;
410 return ptr.cnt;
411} 430}
412 431
432/* ppos is not advanced since the llseek operation is not permitted. */
413static ssize_t mon_text_read_u(struct file *file, char __user *buf, 433static ssize_t mon_text_read_u(struct file *file, char __user *buf,
414 size_t nbytes, loff_t *ppos) 434 size_t nbytes, loff_t *ppos)
415{ 435{
416 struct mon_reader_text *rp = file->private_data; 436 struct mon_reader_text *rp = file->private_data;
417 struct mon_event_text *ep; 437 struct mon_event_text *ep;
418 struct mon_text_ptr ptr; 438 struct mon_text_ptr ptr;
439 ssize_t ret;
419 440
420 ep = mon_text_read_wait(rp, file);
421 if (IS_ERR(ep))
422 return PTR_ERR(ep);
423 mutex_lock(&rp->printf_lock); 441 mutex_lock(&rp->printf_lock);
424 ptr.cnt = 0;
425 ptr.pbuf = rp->printf_buf;
426 ptr.limit = rp->printf_size;
427 442
428 mon_text_read_head_u(rp, &ptr, ep); 443 if (rp->printf_togo == 0) {
429 if (ep->type == 'E') { 444
430 mon_text_read_statset(rp, &ptr, ep); 445 ep = mon_text_read_wait(rp, file);
431 } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { 446 if (IS_ERR(ep)) {
432 mon_text_read_isostat(rp, &ptr, ep); 447 mutex_unlock(&rp->printf_lock);
433 mon_text_read_isodesc(rp, &ptr, ep); 448 return PTR_ERR(ep);
434 } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { 449 }
435 mon_text_read_intstat(rp, &ptr, ep); 450 ptr.cnt = 0;
436 } else { 451 ptr.pbuf = rp->printf_buf;
437 mon_text_read_statset(rp, &ptr, ep); 452 ptr.limit = rp->printf_size;
453
454 mon_text_read_head_u(rp, &ptr, ep);
455 if (ep->type == 'E') {
456 mon_text_read_statset(rp, &ptr, ep);
457 } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) {
458 mon_text_read_isostat(rp, &ptr, ep);
459 mon_text_read_isodesc(rp, &ptr, ep);
460 } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) {
461 mon_text_read_intstat(rp, &ptr, ep);
462 } else {
463 mon_text_read_statset(rp, &ptr, ep);
464 }
465 ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
466 " %d", ep->length);
467 mon_text_read_data(rp, &ptr, ep);
468
469 rp->printf_togo = ptr.cnt;
470 rp->printf_offset = 0;
471
472 kmem_cache_free(rp->e_slab, ep);
438 } 473 }
439 ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
440 " %d", ep->length);
441 mon_text_read_data(rp, &ptr, ep);
442 474
443 if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) 475 ret = mon_text_copy_to_user(rp, buf, nbytes);
444 ptr.cnt = -EFAULT;
445 mutex_unlock(&rp->printf_lock); 476 mutex_unlock(&rp->printf_lock);
446 kmem_cache_free(rp->e_slab, ep); 477 return ret;
447 return ptr.cnt;
448} 478}
449 479
450static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp, 480static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp,