diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-12-17 18:03:37 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-20 17:49:57 -0500 |
commit | 8d402e1ae03656c1ad215514f8885ef4793f0948 (patch) | |
tree | ceac7800d7e07be1a7320a0b729156b12fbf26d6 /drivers/usb/host | |
parent | 0ed8fee1c1d38a62e981025ba40b5eba30c4ce2a (diff) |
[PATCH] UHCI: improve debugging code
This patch (as626) makes some improvements to the debugging code in
uhci-hcd. The main change is that now the code won't get compiled if
CONFIG_USB_DEBUG isn't set. But there are other changes too, like
adding a missing .owner field and printing a debugging dump if the
controller dies.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/uhci-debug.c | 36 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 60 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/uhci-q.c | 12 |
4 files changed, 70 insertions, 39 deletions
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index f2f5f8ce1715..e1239319655c 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -17,10 +17,13 @@ | |||
17 | 17 | ||
18 | #include "uhci-hcd.h" | 18 | #include "uhci-hcd.h" |
19 | 19 | ||
20 | static struct dentry *uhci_debugfs_root = NULL; | 20 | #define uhci_debug_operations (* (struct file_operations *) NULL) |
21 | static struct dentry *uhci_debugfs_root; | ||
22 | |||
23 | #ifdef DEBUG | ||
21 | 24 | ||
22 | /* Handle REALLY large printks so we don't overflow buffers */ | 25 | /* Handle REALLY large printks so we don't overflow buffers */ |
23 | static inline void lprintk(char *buf) | 26 | static void lprintk(char *buf) |
24 | { | 27 | { |
25 | char *p; | 28 | char *p; |
26 | 29 | ||
@@ -196,7 +199,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
196 | return out - buf; | 199 | return out - buf; |
197 | } | 200 | } |
198 | 201 | ||
199 | #ifdef CONFIG_PROC_FS | ||
200 | static const char * const qh_names[] = { | 202 | static const char * const qh_names[] = { |
201 | "skel_unlink_qh", "skel_iso_qh", | 203 | "skel_unlink_qh", "skel_iso_qh", |
202 | "skel_int128_qh", "skel_int64_qh", | 204 | "skel_int128_qh", "skel_int64_qh", |
@@ -393,12 +395,13 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
393 | return out - buf; | 395 | return out - buf; |
394 | } | 396 | } |
395 | 397 | ||
398 | #ifdef CONFIG_DEBUG_FS | ||
399 | |||
396 | #define MAX_OUTPUT (64 * 1024) | 400 | #define MAX_OUTPUT (64 * 1024) |
397 | 401 | ||
398 | struct uhci_debug { | 402 | struct uhci_debug { |
399 | int size; | 403 | int size; |
400 | char *data; | 404 | char *data; |
401 | struct uhci_hcd *uhci; | ||
402 | }; | 405 | }; |
403 | 406 | ||
404 | static int uhci_debug_open(struct inode *inode, struct file *file) | 407 | static int uhci_debug_open(struct inode *inode, struct file *file) |
@@ -419,8 +422,10 @@ static int uhci_debug_open(struct inode *inode, struct file *file) | |||
419 | goto out; | 422 | goto out; |
420 | } | 423 | } |
421 | 424 | ||
425 | up->size = 0; | ||
422 | spin_lock_irqsave(&uhci->lock, flags); | 426 | spin_lock_irqsave(&uhci->lock, flags); |
423 | up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); | 427 | if (uhci->is_initialized) |
428 | up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); | ||
424 | spin_unlock_irqrestore(&uhci->lock, flags); | 429 | spin_unlock_irqrestore(&uhci->lock, flags); |
425 | 430 | ||
426 | file->private_data = up; | 431 | file->private_data = up; |
@@ -472,15 +477,32 @@ static int uhci_debug_release(struct inode *inode, struct file *file) | |||
472 | return 0; | 477 | return 0; |
473 | } | 478 | } |
474 | 479 | ||
480 | #undef uhci_debug_operations | ||
475 | static struct file_operations uhci_debug_operations = { | 481 | static struct file_operations uhci_debug_operations = { |
482 | .owner = THIS_MODULE, | ||
476 | .open = uhci_debug_open, | 483 | .open = uhci_debug_open, |
477 | .llseek = uhci_debug_lseek, | 484 | .llseek = uhci_debug_lseek, |
478 | .read = uhci_debug_read, | 485 | .read = uhci_debug_read, |
479 | .release = uhci_debug_release, | 486 | .release = uhci_debug_release, |
480 | }; | 487 | }; |
481 | 488 | ||
482 | #else /* CONFIG_DEBUG_FS */ | 489 | #endif /* CONFIG_DEBUG_FS */ |
483 | 490 | ||
484 | #define uhci_debug_operations (* (struct file_operations *) NULL) | 491 | #else /* DEBUG */ |
492 | |||
493 | static inline void lprintk(char *buf) | ||
494 | {} | ||
495 | |||
496 | static inline int uhci_show_qh(struct uhci_qh *qh, char *buf, | ||
497 | int len, int space) | ||
498 | { | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static inline int uhci_sprint_schedule(struct uhci_hcd *uhci, | ||
503 | char *buf, int len) | ||
504 | { | ||
505 | return 0; | ||
506 | } | ||
485 | 507 | ||
486 | #endif | 508 | #endif |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 9865f303d3fc..4edb8330c440 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -68,12 +68,16 @@ Alan Stern" | |||
68 | * debug = 3, show all TDs in URBs when dumping | 68 | * debug = 3, show all TDs in URBs when dumping |
69 | */ | 69 | */ |
70 | #ifdef DEBUG | 70 | #ifdef DEBUG |
71 | #define DEBUG_CONFIGURED 1 | ||
71 | static int debug = 1; | 72 | static int debug = 1; |
72 | #else | ||
73 | static int debug = 0; | ||
74 | #endif | ||
75 | module_param(debug, int, S_IRUGO | S_IWUSR); | 73 | module_param(debug, int, S_IRUGO | S_IWUSR); |
76 | MODULE_PARM_DESC(debug, "Debug level"); | 74 | MODULE_PARM_DESC(debug, "Debug level"); |
75 | |||
76 | #else | ||
77 | #define DEBUG_CONFIGURED 0 | ||
78 | #define debug 0 | ||
79 | #endif | ||
80 | |||
77 | static char *errbuf; | 81 | static char *errbuf; |
78 | #define ERRBUF_LEN (32 * 1024) | 82 | #define ERRBUF_LEN (32 * 1024) |
79 | 83 | ||
@@ -338,6 +342,12 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
338 | dev_err(uhci_dev(uhci), | 342 | dev_err(uhci_dev(uhci), |
339 | "host controller halted, " | 343 | "host controller halted, " |
340 | "very bad!\n"); | 344 | "very bad!\n"); |
345 | if (debug > 1 && errbuf) { | ||
346 | /* Print the schedule for debugging */ | ||
347 | uhci_sprint_schedule(uhci, | ||
348 | errbuf, ERRBUF_LEN); | ||
349 | lprintk(errbuf); | ||
350 | } | ||
341 | hc_died(uhci); | 351 | hc_died(uhci); |
342 | 352 | ||
343 | /* Force a callback in case there are | 353 | /* Force a callback in case there are |
@@ -376,6 +386,14 @@ static void release_uhci(struct uhci_hcd *uhci) | |||
376 | { | 386 | { |
377 | int i; | 387 | int i; |
378 | 388 | ||
389 | if (DEBUG_CONFIGURED) { | ||
390 | spin_lock_irq(&uhci->lock); | ||
391 | uhci->is_initialized = 0; | ||
392 | spin_unlock_irq(&uhci->lock); | ||
393 | |||
394 | debugfs_remove(uhci->dentry); | ||
395 | } | ||
396 | |||
379 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 397 | for (i = 0; i < UHCI_NUM_SKELQH; i++) |
380 | uhci_free_qh(uhci, uhci->skelqh[i]); | 398 | uhci_free_qh(uhci, uhci->skelqh[i]); |
381 | 399 | ||
@@ -390,8 +408,6 @@ static void release_uhci(struct uhci_hcd *uhci) | |||
390 | dma_free_coherent(uhci_dev(uhci), | 408 | dma_free_coherent(uhci_dev(uhci), |
391 | UHCI_NUMFRAMES * sizeof(*uhci->frame), | 409 | UHCI_NUMFRAMES * sizeof(*uhci->frame), |
392 | uhci->frame, uhci->frame_dma_handle); | 410 | uhci->frame, uhci->frame_dma_handle); |
393 | |||
394 | debugfs_remove(uhci->dentry); | ||
395 | } | 411 | } |
396 | 412 | ||
397 | static int uhci_reset(struct usb_hcd *hcd) | 413 | static int uhci_reset(struct usb_hcd *hcd) |
@@ -474,17 +490,6 @@ static int uhci_start(struct usb_hcd *hcd) | |||
474 | 490 | ||
475 | hcd->uses_new_polling = 1; | 491 | hcd->uses_new_polling = 1; |
476 | 492 | ||
477 | dentry = debugfs_create_file(hcd->self.bus_name, | ||
478 | S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, | ||
479 | &uhci_debug_operations); | ||
480 | if (!dentry) { | ||
481 | dev_err(uhci_dev(uhci), | ||
482 | "couldn't create uhci debugfs entry\n"); | ||
483 | retval = -ENOMEM; | ||
484 | goto err_create_debug_entry; | ||
485 | } | ||
486 | uhci->dentry = dentry; | ||
487 | |||
488 | uhci->fsbr = 0; | 493 | uhci->fsbr = 0; |
489 | uhci->fsbrtimeout = 0; | 494 | uhci->fsbrtimeout = 0; |
490 | 495 | ||
@@ -495,6 +500,19 @@ static int uhci_start(struct usb_hcd *hcd) | |||
495 | 500 | ||
496 | init_waitqueue_head(&uhci->waitqh); | 501 | init_waitqueue_head(&uhci->waitqh); |
497 | 502 | ||
503 | if (DEBUG_CONFIGURED) { | ||
504 | dentry = debugfs_create_file(hcd->self.bus_name, | ||
505 | S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, | ||
506 | uhci, &uhci_debug_operations); | ||
507 | if (!dentry) { | ||
508 | dev_err(uhci_dev(uhci), "couldn't create uhci " | ||
509 | "debugfs entry\n"); | ||
510 | retval = -ENOMEM; | ||
511 | goto err_create_debug_entry; | ||
512 | } | ||
513 | uhci->dentry = dentry; | ||
514 | } | ||
515 | |||
498 | uhci->frame = dma_alloc_coherent(uhci_dev(uhci), | 516 | uhci->frame = dma_alloc_coherent(uhci_dev(uhci), |
499 | UHCI_NUMFRAMES * sizeof(*uhci->frame), | 517 | UHCI_NUMFRAMES * sizeof(*uhci->frame), |
500 | &uhci->frame_dma_handle, 0); | 518 | &uhci->frame_dma_handle, 0); |
@@ -609,6 +627,7 @@ static int uhci_start(struct usb_hcd *hcd) | |||
609 | mb(); | 627 | mb(); |
610 | 628 | ||
611 | configure_hc(uhci); | 629 | configure_hc(uhci); |
630 | uhci->is_initialized = 1; | ||
612 | start_rh(uhci); | 631 | start_rh(uhci); |
613 | return 0; | 632 | return 0; |
614 | 633 | ||
@@ -872,16 +891,15 @@ static int __init uhci_hcd_init(void) | |||
872 | if (usb_disabled()) | 891 | if (usb_disabled()) |
873 | return -ENODEV; | 892 | return -ENODEV; |
874 | 893 | ||
875 | if (debug) { | 894 | if (DEBUG_CONFIGURED) { |
876 | errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); | 895 | errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); |
877 | if (!errbuf) | 896 | if (!errbuf) |
878 | goto errbuf_failed; | 897 | goto errbuf_failed; |
898 | uhci_debugfs_root = debugfs_create_dir("uhci", NULL); | ||
899 | if (!uhci_debugfs_root) | ||
900 | goto debug_failed; | ||
879 | } | 901 | } |
880 | 902 | ||
881 | uhci_debugfs_root = debugfs_create_dir("uhci", NULL); | ||
882 | if (!uhci_debugfs_root) | ||
883 | goto debug_failed; | ||
884 | |||
885 | uhci_up_cachep = kmem_cache_create("uhci_urb_priv", | 903 | uhci_up_cachep = kmem_cache_create("uhci_urb_priv", |
886 | sizeof(struct urb_priv), 0, 0, NULL, NULL); | 904 | sizeof(struct urb_priv), 0, 0, NULL, NULL); |
887 | if (!uhci_up_cachep) | 905 | if (!uhci_up_cachep) |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7e96bef2e88f..4a69c7eb09bd 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -411,6 +411,7 @@ struct uhci_hcd { | |||
411 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ | 411 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ |
412 | unsigned int working_RD:1; /* Suspended root hub doesn't | 412 | unsigned int working_RD:1; /* Suspended root hub doesn't |
413 | need to be polled */ | 413 | need to be polled */ |
414 | unsigned int is_initialized:1; /* Data structure is usable */ | ||
414 | 415 | ||
415 | /* Support for port suspend/resume/reset */ | 416 | /* Support for port suspend/resume/reset */ |
416 | unsigned long port_c_suspend; /* Bit-arrays of ports */ | 417 | unsigned long port_c_suspend; /* Bit-arrays of ports */ |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 44bba9a6d196..5d6c4f75d0d8 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -736,7 +736,6 @@ err: | |||
736 | if (errbuf) { | 736 | if (errbuf) { |
737 | /* Print the chain for debugging purposes */ | 737 | /* Print the chain for debugging purposes */ |
738 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); | 738 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); |
739 | |||
740 | lprintk(errbuf); | 739 | lprintk(errbuf); |
741 | } | 740 | } |
742 | } | 741 | } |
@@ -924,26 +923,17 @@ td_error: | |||
924 | ret = uhci_map_status(status, uhci_packetout(td_token(td))); | 923 | ret = uhci_map_status(status, uhci_packetout(td_token(td))); |
925 | 924 | ||
926 | err: | 925 | err: |
927 | /* | ||
928 | * Enable this chunk of code if you want to see some more debugging. | ||
929 | * But be careful, it has the tendancy to starve out khubd and prevent | ||
930 | * disconnects from happening successfully if you have a slow debug | ||
931 | * log interface (like a serial console. | ||
932 | */ | ||
933 | #if 0 | ||
934 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { | 926 | if ((debug == 1 && ret != -EPIPE) || debug > 1) { |
935 | /* Some debugging code */ | 927 | /* Some debugging code */ |
936 | dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", | 928 | dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", |
937 | __FUNCTION__, status); | 929 | __FUNCTION__, status); |
938 | 930 | ||
939 | if (errbuf) { | 931 | if (debug > 1 && errbuf) { |
940 | /* Print the chain for debugging purposes */ | 932 | /* Print the chain for debugging purposes */ |
941 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); | 933 | uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); |
942 | |||
943 | lprintk(errbuf); | 934 | lprintk(errbuf); |
944 | } | 935 | } |
945 | } | 936 | } |
946 | #endif | ||
947 | 937 | ||
948 | /* Note that the queue has stopped and save the next toggle value */ | 938 | /* Note that the queue has stopped and save the next toggle value */ |
949 | urbp->qh->element = UHCI_PTR_TERM; | 939 | urbp->qh->element = UHCI_PTR_TERM; |