aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/mon
diff options
context:
space:
mode:
authorPete Zaitcev <zaitcev@redhat.com>2007-02-24 22:27:33 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-04-27 16:28:33 -0400
commitf1c9e30b5e4cdd8aae5f0ea87004b1b61ec41881 (patch)
tree9ea740745c04780171662529c520b0a9c02ca64d /drivers/usb/mon
parent2e85c91e2e0f4e58fb54354bb7f6cc7dd3466dd9 (diff)
usbmon: Extended text API
This patch adds a new text API, codenamed '1u', which captures more URB fields than old '1t' interface did. Also the '1u' text API is compatible with the future "bus zero" extension. Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/mon')
-rw-r--r--drivers/usb/mon/mon_text.c296
-rw-r--r--drivers/usb/mon/usb_mon.h1
2 files changed, 257 insertions, 40 deletions
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 494ee3b9a226..bbf54396e5f2 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -31,9 +31,21 @@
31 * to a local DoS. But we have to keep to root in order to prevent 31 * to a local DoS. But we have to keep to root in order to prevent
32 * password sniffing from HID devices. 32 * password sniffing from HID devices.
33 */ 33 */
34#define EVENT_MAX (2*PAGE_SIZE / sizeof(struct mon_event_text)) 34#define EVENT_MAX (4*PAGE_SIZE / sizeof(struct mon_event_text))
35 35
36#define PRINTF_DFL 160 36/*
37 * Potentially unlimited number; we limit it for similar allocations.
38 * The usbfs limits this to 128, but we're not quite as generous.
39 */
40#define ISODESC_MAX 5
41
42#define PRINTF_DFL 250 /* with 5 ISOs segs */
43
44struct mon_iso_desc {
45 int status;
46 unsigned int offset;
47 unsigned int length; /* Unsigned here, signed in URB. Historic. */
48};
37 49
38struct mon_event_text { 50struct mon_event_text {
39 struct list_head e_link; 51 struct list_head e_link;
@@ -41,10 +53,16 @@ struct mon_event_text {
41 unsigned int pipe; /* Pipe */ 53 unsigned int pipe; /* Pipe */
42 unsigned long id; /* From pointer, most of the time */ 54 unsigned long id; /* From pointer, most of the time */
43 unsigned int tstamp; 55 unsigned int tstamp;
56 int busnum;
44 int length; /* Depends on type: xfer length or act length */ 57 int length; /* Depends on type: xfer length or act length */
45 int status; 58 int status;
59 int interval;
60 int start_frame;
61 int error_count;
46 char setup_flag; 62 char setup_flag;
47 char data_flag; 63 char data_flag;
64 int numdesc; /* Full number */
65 struct mon_iso_desc isodesc[ISODESC_MAX];
48 unsigned char setup[SETUP_MAX]; 66 unsigned char setup[SETUP_MAX];
49 unsigned char data[DATA_MAX]; 67 unsigned char data[DATA_MAX];
50}; 68};
@@ -68,6 +86,28 @@ static struct dentry *mon_dir; /* Usually /sys/kernel/debug/usbmon */
68 86
69static void mon_text_ctor(void *, struct kmem_cache *, unsigned long); 87static void mon_text_ctor(void *, struct kmem_cache *, unsigned long);
70 88
89struct mon_text_ptr {
90 int cnt, limit;
91 char *pbuf;
92};
93
94static struct mon_event_text *
95 mon_text_read_wait(struct mon_reader_text *rp, struct file *file);
96static void mon_text_read_head_t(struct mon_reader_text *rp,
97 struct mon_text_ptr *p, const struct mon_event_text *ep);
98static void mon_text_read_head_u(struct mon_reader_text *rp,
99 struct mon_text_ptr *p, const struct mon_event_text *ep);
100static void mon_text_read_statset(struct mon_reader_text *rp,
101 struct mon_text_ptr *p, const struct mon_event_text *ep);
102static void mon_text_read_intstat(struct mon_reader_text *rp,
103 struct mon_text_ptr *p, const struct mon_event_text *ep);
104static void mon_text_read_isostat(struct mon_reader_text *rp,
105 struct mon_text_ptr *p, const struct mon_event_text *ep);
106static void mon_text_read_isodesc(struct mon_reader_text *rp,
107 struct mon_text_ptr *p, const struct mon_event_text *ep);
108static void mon_text_read_data(struct mon_reader_text *rp,
109 struct mon_text_ptr *p, const struct mon_event_text *ep);
110
71/* 111/*
72 * mon_text_submit 112 * mon_text_submit
73 * mon_text_complete 113 * mon_text_complete
@@ -104,10 +144,10 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
104 len = DATA_MAX; 144 len = DATA_MAX;
105 145
106 if (usb_pipein(pipe)) { 146 if (usb_pipein(pipe)) {
107 if (ev_type == 'S') 147 if (ev_type != 'C')
108 return '<'; 148 return '<';
109 } else { 149 } else {
110 if (ev_type == 'C') 150 if (ev_type != 'S')
111 return '>'; 151 return '>';
112 } 152 }
113 153
@@ -146,6 +186,9 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
146{ 186{
147 struct mon_event_text *ep; 187 struct mon_event_text *ep;
148 unsigned int stamp; 188 unsigned int stamp;
189 struct usb_iso_packet_descriptor *fp;
190 struct mon_iso_desc *dp;
191 int i, ndesc;
149 192
150 stamp = mon_get_timestamp(); 193 stamp = mon_get_timestamp();
151 194
@@ -158,12 +201,36 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
158 ep->type = ev_type; 201 ep->type = ev_type;
159 ep->pipe = urb->pipe; 202 ep->pipe = urb->pipe;
160 ep->id = (unsigned long) urb; 203 ep->id = (unsigned long) urb;
204 ep->busnum = rp->r.m_bus->u_bus->busnum;
161 ep->tstamp = stamp; 205 ep->tstamp = stamp;
162 ep->length = (ev_type == 'S') ? 206 ep->length = (ev_type == 'S') ?
163 urb->transfer_buffer_length : urb->actual_length; 207 urb->transfer_buffer_length : urb->actual_length;
164 /* Collecting status makes debugging sense for submits, too */ 208 /* Collecting status makes debugging sense for submits, too */
165 ep->status = urb->status; 209 ep->status = urb->status;
166 210
211 if (usb_pipeint(urb->pipe)) {
212 ep->interval = urb->interval;
213 } else if (usb_pipeisoc(urb->pipe)) {
214 ep->interval = urb->interval;
215 ep->start_frame = urb->start_frame;
216 ep->error_count = urb->error_count;
217 }
218 ep->numdesc = urb->number_of_packets;
219 if (usb_pipeisoc(urb->pipe) && urb->number_of_packets > 0) {
220 if ((ndesc = urb->number_of_packets) > ISODESC_MAX)
221 ndesc = ISODESC_MAX;
222 fp = urb->iso_frame_desc;
223 dp = ep->isodesc;
224 for (i = 0; i < ndesc; i++) {
225 dp->status = fp->status;
226 dp->offset = fp->offset;
227 dp->length = (ev_type == 'S') ?
228 fp->length : fp->actual_length;
229 fp++;
230 dp++;
231 }
232 }
233
167 ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus); 234 ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
168 ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type, 235 ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
169 rp->r.m_bus); 236 rp->r.m_bus);
@@ -199,6 +266,7 @@ static void mon_text_error(void *data, struct urb *urb, int error)
199 ep->type = 'E'; 266 ep->type = 'E';
200 ep->pipe = urb->pipe; 267 ep->pipe = urb->pipe;
201 ep->id = (unsigned long) urb; 268 ep->id = (unsigned long) urb;
269 ep->busnum = 0;
202 ep->tstamp = 0; 270 ep->tstamp = 0;
203 ep->length = 0; 271 ep->length = 0;
204 ep->status = error; 272 ep->status = error;
@@ -300,17 +368,75 @@ err_alloc:
300 * dd if=/dbg/usbmon/0t bs=10 368 * dd if=/dbg/usbmon/0t bs=10
301 * Also, we do not allow seeks and do not bother advancing the offset. 369 * Also, we do not allow seeks and do not bother advancing the offset.
302 */ 370 */
303static ssize_t mon_text_read(struct file *file, char __user *buf, 371static ssize_t mon_text_read_t(struct file *file, char __user *buf,
372 size_t nbytes, loff_t *ppos)
373{
374 struct mon_reader_text *rp = file->private_data;
375 struct mon_event_text *ep;
376 struct mon_text_ptr ptr;
377
378 if (IS_ERR(ep = mon_text_read_wait(rp, file)))
379 return PTR_ERR(ep);
380 mutex_lock(&rp->printf_lock);
381 ptr.cnt = 0;
382 ptr.pbuf = rp->printf_buf;
383 ptr.limit = rp->printf_size;
384
385 mon_text_read_head_t(rp, &ptr, ep);
386 mon_text_read_statset(rp, &ptr, ep);
387 ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
388 " %d", ep->length);
389 mon_text_read_data(rp, &ptr, ep);
390
391 if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
392 ptr.cnt = -EFAULT;
393 mutex_unlock(&rp->printf_lock);
394 kmem_cache_free(rp->e_slab, ep);
395 return ptr.cnt;
396}
397
398static ssize_t mon_text_read_u(struct file *file, char __user *buf,
304 size_t nbytes, loff_t *ppos) 399 size_t nbytes, loff_t *ppos)
305{ 400{
306 struct mon_reader_text *rp = file->private_data; 401 struct mon_reader_text *rp = file->private_data;
402 struct mon_event_text *ep;
403 struct mon_text_ptr ptr;
404
405 if (IS_ERR(ep = mon_text_read_wait(rp, file)))
406 return PTR_ERR(ep);
407 mutex_lock(&rp->printf_lock);
408 ptr.cnt = 0;
409 ptr.pbuf = rp->printf_buf;
410 ptr.limit = rp->printf_size;
411
412 mon_text_read_head_u(rp, &ptr, ep);
413 if (ep->type == 'E') {
414 mon_text_read_statset(rp, &ptr, ep);
415 } else if (usb_pipeisoc(ep->pipe)) {
416 mon_text_read_isostat(rp, &ptr, ep);
417 mon_text_read_isodesc(rp, &ptr, ep);
418 } else if (usb_pipeint(ep->pipe)) {
419 mon_text_read_intstat(rp, &ptr, ep);
420 } else {
421 mon_text_read_statset(rp, &ptr, ep);
422 }
423 ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
424 " %d", ep->length);
425 mon_text_read_data(rp, &ptr, ep);
426
427 if (copy_to_user(buf, rp->printf_buf, ptr.cnt))
428 ptr.cnt = -EFAULT;
429 mutex_unlock(&rp->printf_lock);
430 kmem_cache_free(rp->e_slab, ep);
431 return ptr.cnt;
432}
433
434static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp,
435 struct file *file)
436{
307 struct mon_bus *mbus = rp->r.m_bus; 437 struct mon_bus *mbus = rp->r.m_bus;
308 DECLARE_WAITQUEUE(waita, current); 438 DECLARE_WAITQUEUE(waita, current);
309 struct mon_event_text *ep; 439 struct mon_event_text *ep;
310 int cnt, limit;
311 char *pbuf;
312 char udir, utype;
313 int data_len, i;
314 440
315 add_wait_queue(&rp->wait, &waita); 441 add_wait_queue(&rp->wait, &waita);
316 set_current_state(TASK_INTERRUPTIBLE); 442 set_current_state(TASK_INTERRUPTIBLE);
@@ -318,7 +444,7 @@ static ssize_t mon_text_read(struct file *file, char __user *buf,
318 if (file->f_flags & O_NONBLOCK) { 444 if (file->f_flags & O_NONBLOCK) {
319 set_current_state(TASK_RUNNING); 445 set_current_state(TASK_RUNNING);
320 remove_wait_queue(&rp->wait, &waita); 446 remove_wait_queue(&rp->wait, &waita);
321 return -EWOULDBLOCK; /* Same as EAGAIN in Linux */ 447 return ERR_PTR(-EWOULDBLOCK);
322 } 448 }
323 /* 449 /*
324 * We do not count nwaiters, because ->release is supposed 450 * We do not count nwaiters, because ->release is supposed
@@ -327,17 +453,19 @@ static ssize_t mon_text_read(struct file *file, char __user *buf,
327 schedule(); 453 schedule();
328 if (signal_pending(current)) { 454 if (signal_pending(current)) {
329 remove_wait_queue(&rp->wait, &waita); 455 remove_wait_queue(&rp->wait, &waita);
330 return -EINTR; 456 return ERR_PTR(-EINTR);
331 } 457 }
332 set_current_state(TASK_INTERRUPTIBLE); 458 set_current_state(TASK_INTERRUPTIBLE);
333 } 459 }
334 set_current_state(TASK_RUNNING); 460 set_current_state(TASK_RUNNING);
335 remove_wait_queue(&rp->wait, &waita); 461 remove_wait_queue(&rp->wait, &waita);
462 return ep;
463}
336 464
337 mutex_lock(&rp->printf_lock); 465static void mon_text_read_head_t(struct mon_reader_text *rp,
338 cnt = 0; 466 struct mon_text_ptr *p, const struct mon_event_text *ep)
339 pbuf = rp->printf_buf; 467{
340 limit = rp->printf_size; 468 char udir, utype;
341 469
342 udir = usb_pipein(ep->pipe) ? 'i' : 'o'; 470 udir = usb_pipein(ep->pipe) ? 'i' : 'o';
343 switch (usb_pipetype(ep->pipe)) { 471 switch (usb_pipetype(ep->pipe)) {
@@ -346,13 +474,38 @@ static ssize_t mon_text_read(struct file *file, char __user *buf,
346 case PIPE_CONTROL: utype = 'C'; break; 474 case PIPE_CONTROL: utype = 'C'; break;
347 default: /* PIPE_BULK */ utype = 'B'; 475 default: /* PIPE_BULK */ utype = 'B';
348 } 476 }
349 cnt += snprintf(pbuf + cnt, limit - cnt, 477 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
350 "%lx %u %c %c%c:%03u:%02u", 478 "%lx %u %c %c%c:%03u:%02u",
351 ep->id, ep->tstamp, ep->type, 479 ep->id, ep->tstamp, ep->type,
352 utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe)); 480 utype, udir,
481 usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
482}
483
484static void mon_text_read_head_u(struct mon_reader_text *rp,
485 struct mon_text_ptr *p, const struct mon_event_text *ep)
486{
487 char udir, utype;
488
489 udir = usb_pipein(ep->pipe) ? 'i' : 'o';
490 switch (usb_pipetype(ep->pipe)) {
491 case PIPE_ISOCHRONOUS: utype = 'Z'; break;
492 case PIPE_INTERRUPT: utype = 'I'; break;
493 case PIPE_CONTROL: utype = 'C'; break;
494 default: /* PIPE_BULK */ utype = 'B';
495 }
496 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
497 "%lx %u %c %c%c:%d:%03u:%u",
498 ep->id, ep->tstamp, ep->type,
499 utype, udir,
500 ep->busnum, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
501}
502
503static void mon_text_read_statset(struct mon_reader_text *rp,
504 struct mon_text_ptr *p, const struct mon_event_text *ep)
505{
353 506
354 if (ep->setup_flag == 0) { /* Setup packet is present and captured */ 507 if (ep->setup_flag == 0) { /* Setup packet is present and captured */
355 cnt += snprintf(pbuf + cnt, limit - cnt, 508 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
356 " s %02x %02x %04x %04x %04x", 509 " s %02x %02x %04x %04x %04x",
357 ep->setup[0], 510 ep->setup[0],
358 ep->setup[1], 511 ep->setup[1],
@@ -360,40 +513,86 @@ static ssize_t mon_text_read(struct file *file, char __user *buf,
360 (ep->setup[5] << 8) | ep->setup[4], 513 (ep->setup[5] << 8) | ep->setup[4],
361 (ep->setup[7] << 8) | ep->setup[6]); 514 (ep->setup[7] << 8) | ep->setup[6]);
362 } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */ 515 } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */
363 cnt += snprintf(pbuf + cnt, limit - cnt, 516 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
364 " %c __ __ ____ ____ ____", ep->setup_flag); 517 " %c __ __ ____ ____ ____", ep->setup_flag);
365 } else { /* No setup for this kind of URB */ 518 } else { /* No setup for this kind of URB */
366 cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status); 519 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
520 " %d", ep->status);
521 }
522}
523
524static void mon_text_read_intstat(struct mon_reader_text *rp,
525 struct mon_text_ptr *p, const struct mon_event_text *ep)
526{
527 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
528 " %d:%d", ep->status, ep->interval);
529}
530
531static void mon_text_read_isostat(struct mon_reader_text *rp,
532 struct mon_text_ptr *p, const struct mon_event_text *ep)
533{
534 if (ep->type == 'S') {
535 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
536 " %d:%d:%d", ep->status, ep->interval, ep->start_frame);
537 } else {
538 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
539 " %d:%d:%d:%d",
540 ep->status, ep->interval, ep->start_frame, ep->error_count);
367 } 541 }
368 cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length); 542}
543
544static void mon_text_read_isodesc(struct mon_reader_text *rp,
545 struct mon_text_ptr *p, const struct mon_event_text *ep)
546{
547 int ndesc; /* Display this many */
548 int i;
549 const struct mon_iso_desc *dp;
550
551 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
552 " %d", ep->numdesc);
553 ndesc = ep->numdesc;
554 if (ndesc > ISODESC_MAX)
555 ndesc = ISODESC_MAX;
556 if (ndesc < 0)
557 ndesc = 0;
558 dp = ep->isodesc;
559 for (i = 0; i < ndesc; i++) {
560 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
561 " %d:%u:%u", dp->status, dp->offset, dp->length);
562 dp++;
563 }
564}
565
566static void mon_text_read_data(struct mon_reader_text *rp,
567 struct mon_text_ptr *p, const struct mon_event_text *ep)
568{
569 int data_len, i;
369 570
370 if ((data_len = ep->length) > 0) { 571 if ((data_len = ep->length) > 0) {
371 if (ep->data_flag == 0) { 572 if (ep->data_flag == 0) {
372 cnt += snprintf(pbuf + cnt, limit - cnt, " ="); 573 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
574 " =");
373 if (data_len >= DATA_MAX) 575 if (data_len >= DATA_MAX)
374 data_len = DATA_MAX; 576 data_len = DATA_MAX;
375 for (i = 0; i < data_len; i++) { 577 for (i = 0; i < data_len; i++) {
376 if (i % 4 == 0) { 578 if (i % 4 == 0) {
377 cnt += snprintf(pbuf + cnt, limit - cnt, 579 p->cnt += snprintf(p->pbuf + p->cnt,
580 p->limit - p->cnt,
378 " "); 581 " ");
379 } 582 }
380 cnt += snprintf(pbuf + cnt, limit - cnt, 583 p->cnt += snprintf(p->pbuf + p->cnt,
584 p->limit - p->cnt,
381 "%02x", ep->data[i]); 585 "%02x", ep->data[i]);
382 } 586 }
383 cnt += snprintf(pbuf + cnt, limit - cnt, "\n"); 587 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
588 "\n");
384 } else { 589 } else {
385 cnt += snprintf(pbuf + cnt, limit - cnt, 590 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
386 " %c\n", ep->data_flag); 591 " %c\n", ep->data_flag);
387 } 592 }
388 } else { 593 } else {
389 cnt += snprintf(pbuf + cnt, limit - cnt, "\n"); 594 p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n");
390 } 595 }
391
392 if (copy_to_user(buf, rp->printf_buf, cnt))
393 cnt = -EFAULT;
394 mutex_unlock(&rp->printf_lock);
395 kmem_cache_free(rp->e_slab, ep);
396 return cnt;
397} 596}
398 597
399static int mon_text_release(struct inode *inode, struct file *file) 598static int mon_text_release(struct inode *inode, struct file *file)
@@ -439,14 +638,19 @@ static int mon_text_release(struct inode *inode, struct file *file)
439 return 0; 638 return 0;
440} 639}
441 640
442static const struct file_operations mon_fops_text = { 641static const struct file_operations mon_fops_text_t = {
443 .owner = THIS_MODULE, 642 .owner = THIS_MODULE,
444 .open = mon_text_open, 643 .open = mon_text_open,
445 .llseek = no_llseek, 644 .llseek = no_llseek,
446 .read = mon_text_read, 645 .read = mon_text_read_t,
447 /* .write = mon_text_write, */ 646 .release = mon_text_release,
448 /* .poll = mon_text_poll, */ 647};
449 /* .ioctl = mon_text_ioctl, */ 648
649static const struct file_operations mon_fops_text_u = {
650 .owner = THIS_MODULE,
651 .open = mon_text_open,
652 .llseek = no_llseek,
653 .read = mon_text_read_u,
450 .release = mon_text_release, 654 .release = mon_text_release,
451}; 655};
452 656
@@ -460,12 +664,19 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
460 rc = snprintf(name, NAMESZ, "%dt", ubus->busnum); 664 rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
461 if (rc <= 0 || rc >= NAMESZ) 665 if (rc <= 0 || rc >= NAMESZ)
462 goto err_print_t; 666 goto err_print_t;
463 d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text); 667 d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t);
464 if (d == NULL) 668 if (d == NULL)
465 goto err_create_t; 669 goto err_create_t;
466 mbus->dent_t = d; 670 mbus->dent_t = d;
467 671
468 /* XXX The stats do not belong to here (text API), but oh well... */ 672 rc = snprintf(name, NAMESZ, "%du", ubus->busnum);
673 if (rc <= 0 || rc >= NAMESZ)
674 goto err_print_u;
675 d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_u);
676 if (d == NULL)
677 goto err_create_u;
678 mbus->dent_u = d;
679
469 rc = snprintf(name, NAMESZ, "%ds", ubus->busnum); 680 rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
470 if (rc <= 0 || rc >= NAMESZ) 681 if (rc <= 0 || rc >= NAMESZ)
471 goto err_print_s; 682 goto err_print_s;
@@ -478,6 +689,10 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
478 689
479err_create_s: 690err_create_s:
480err_print_s: 691err_print_s:
692 debugfs_remove(mbus->dent_u);
693 mbus->dent_u = NULL;
694err_create_u:
695err_print_u:
481 debugfs_remove(mbus->dent_t); 696 debugfs_remove(mbus->dent_t);
482 mbus->dent_t = NULL; 697 mbus->dent_t = NULL;
483err_create_t: 698err_create_t:
@@ -487,6 +702,7 @@ err_print_t:
487 702
488void mon_text_del(struct mon_bus *mbus) 703void mon_text_del(struct mon_bus *mbus)
489{ 704{
705 debugfs_remove(mbus->dent_u);
490 debugfs_remove(mbus->dent_t); 706 debugfs_remove(mbus->dent_t);
491 debugfs_remove(mbus->dent_s); 707 debugfs_remove(mbus->dent_s);
492} 708}
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index efdfd8993d9e..a1e2b8e9d777 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -22,6 +22,7 @@ struct mon_bus {
22 int text_inited; 22 int text_inited;
23 struct dentry *dent_s; /* Debugging file */ 23 struct dentry *dent_s; /* Debugging file */
24 struct dentry *dent_t; /* Text interface file */ 24 struct dentry *dent_t; /* Text interface file */
25 struct dentry *dent_u; /* Second text interface file */
25 int uses_dma; 26 int uses_dma;
26 27
27 /* Ref */ 28 /* Ref */