[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>
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index f2f5f8c..e123931 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -17,10 +17,13 @@
#include "uhci-hcd.h"
-static struct dentry *uhci_debugfs_root = NULL;
+#define uhci_debug_operations (* (struct file_operations *) NULL)
+static struct dentry *uhci_debugfs_root;
+
+#ifdef DEBUG
/* Handle REALLY large printks so we don't overflow buffers */
-static inline void lprintk(char *buf)
+static void lprintk(char *buf)
{
char *p;
@@ -196,7 +199,6 @@
return out - buf;
}
-#ifdef CONFIG_PROC_FS
static const char * const qh_names[] = {
"skel_unlink_qh", "skel_iso_qh",
"skel_int128_qh", "skel_int64_qh",
@@ -393,12 +395,13 @@
return out - buf;
}
+#ifdef CONFIG_DEBUG_FS
+
#define MAX_OUTPUT (64 * 1024)
struct uhci_debug {
int size;
char *data;
- struct uhci_hcd *uhci;
};
static int uhci_debug_open(struct inode *inode, struct file *file)
@@ -419,8 +422,10 @@
goto out;
}
+ up->size = 0;
spin_lock_irqsave(&uhci->lock, flags);
- up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
+ if (uhci->is_initialized)
+ up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
spin_unlock_irqrestore(&uhci->lock, flags);
file->private_data = up;
@@ -472,15 +477,32 @@
return 0;
}
+#undef uhci_debug_operations
static struct file_operations uhci_debug_operations = {
+ .owner = THIS_MODULE,
.open = uhci_debug_open,
.llseek = uhci_debug_lseek,
.read = uhci_debug_read,
.release = uhci_debug_release,
};
-#else /* CONFIG_DEBUG_FS */
+#endif /* CONFIG_DEBUG_FS */
-#define uhci_debug_operations (* (struct file_operations *) NULL)
+#else /* DEBUG */
+
+static inline void lprintk(char *buf)
+{}
+
+static inline int uhci_show_qh(struct uhci_qh *qh, char *buf,
+ int len, int space)
+{
+ return 0;
+}
+
+static inline int uhci_sprint_schedule(struct uhci_hcd *uhci,
+ char *buf, int len)
+{
+ return 0;
+}
#endif
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 9865f30..4edb833 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -68,12 +68,16 @@
* debug = 3, show all TDs in URBs when dumping
*/
#ifdef DEBUG
+#define DEBUG_CONFIGURED 1
static int debug = 1;
-#else
-static int debug = 0;
-#endif
module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug level");
+
+#else
+#define DEBUG_CONFIGURED 0
+#define debug 0
+#endif
+
static char *errbuf;
#define ERRBUF_LEN (32 * 1024)
@@ -338,6 +342,12 @@
dev_err(uhci_dev(uhci),
"host controller halted, "
"very bad!\n");
+ if (debug > 1 && errbuf) {
+ /* Print the schedule for debugging */
+ uhci_sprint_schedule(uhci,
+ errbuf, ERRBUF_LEN);
+ lprintk(errbuf);
+ }
hc_died(uhci);
/* Force a callback in case there are
@@ -376,6 +386,14 @@
{
int i;
+ if (DEBUG_CONFIGURED) {
+ spin_lock_irq(&uhci->lock);
+ uhci->is_initialized = 0;
+ spin_unlock_irq(&uhci->lock);
+
+ debugfs_remove(uhci->dentry);
+ }
+
for (i = 0; i < UHCI_NUM_SKELQH; i++)
uhci_free_qh(uhci, uhci->skelqh[i]);
@@ -390,8 +408,6 @@
dma_free_coherent(uhci_dev(uhci),
UHCI_NUMFRAMES * sizeof(*uhci->frame),
uhci->frame, uhci->frame_dma_handle);
-
- debugfs_remove(uhci->dentry);
}
static int uhci_reset(struct usb_hcd *hcd)
@@ -474,17 +490,6 @@
hcd->uses_new_polling = 1;
- dentry = debugfs_create_file(hcd->self.bus_name,
- S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
- &uhci_debug_operations);
- if (!dentry) {
- dev_err(uhci_dev(uhci),
- "couldn't create uhci debugfs entry\n");
- retval = -ENOMEM;
- goto err_create_debug_entry;
- }
- uhci->dentry = dentry;
-
uhci->fsbr = 0;
uhci->fsbrtimeout = 0;
@@ -495,6 +500,19 @@
init_waitqueue_head(&uhci->waitqh);
+ if (DEBUG_CONFIGURED) {
+ dentry = debugfs_create_file(hcd->self.bus_name,
+ S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root,
+ uhci, &uhci_debug_operations);
+ if (!dentry) {
+ dev_err(uhci_dev(uhci), "couldn't create uhci "
+ "debugfs entry\n");
+ retval = -ENOMEM;
+ goto err_create_debug_entry;
+ }
+ uhci->dentry = dentry;
+ }
+
uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
UHCI_NUMFRAMES * sizeof(*uhci->frame),
&uhci->frame_dma_handle, 0);
@@ -609,6 +627,7 @@
mb();
configure_hc(uhci);
+ uhci->is_initialized = 1;
start_rh(uhci);
return 0;
@@ -872,16 +891,15 @@
if (usb_disabled())
return -ENODEV;
- if (debug) {
+ if (DEBUG_CONFIGURED) {
errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
if (!errbuf)
goto errbuf_failed;
+ uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
+ if (!uhci_debugfs_root)
+ goto debug_failed;
}
- uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
- if (!uhci_debugfs_root)
- goto debug_failed;
-
uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
sizeof(struct urb_priv), 0, 0, NULL, NULL);
if (!uhci_up_cachep)
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 7e96bef..4a69c7e 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -411,6 +411,7 @@
unsigned int hc_inaccessible:1; /* HC is suspended or dead */
unsigned int working_RD:1; /* Suspended root hub doesn't
need to be polled */
+ unsigned int is_initialized:1; /* Data structure is usable */
/* Support for port suspend/resume/reset */
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 44bba9a..5d6c4f7 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -736,7 +736,6 @@
if (errbuf) {
/* Print the chain for debugging purposes */
uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
lprintk(errbuf);
}
}
@@ -924,26 +923,17 @@
ret = uhci_map_status(status, uhci_packetout(td_token(td)));
err:
- /*
- * Enable this chunk of code if you want to see some more debugging.
- * But be careful, it has the tendancy to starve out khubd and prevent
- * disconnects from happening successfully if you have a slow debug
- * log interface (like a serial console.
- */
-#if 0
if ((debug == 1 && ret != -EPIPE) || debug > 1) {
/* Some debugging code */
dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
__FUNCTION__, status);
- if (errbuf) {
+ if (debug > 1 && errbuf) {
/* Print the chain for debugging purposes */
uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
lprintk(errbuf);
}
}
-#endif
/* Note that the queue has stopped and save the next toggle value */
urbp->qh->element = UHCI_PTR_TERM;