[PATCH] UHCI: improve debugging code
Alan Stern [Sat, 17 Dec 2005 23:03:37 +0000 (18:03 -0500)]
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>

drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-q.c

index f2f5f8c..e123931 100644 (file)
 
 #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 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
        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 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
        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 @@ static int uhci_debug_open(struct inode *inode, struct file *file)
                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 @@ static int uhci_debug_release(struct inode *inode, struct file *file)
        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
index 9865f30..4edb833 100644 (file)
@@ -68,12 +68,16 @@ Alan Stern"
  * 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 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
                                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 @@ static void release_uhci(struct uhci_hcd *uhci)
 {
        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 @@ static void release_uhci(struct uhci_hcd *uhci)
        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 @@ static int uhci_start(struct usb_hcd *hcd)
 
        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 @@ static int uhci_start(struct usb_hcd *hcd)
 
        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 @@ static int uhci_start(struct usb_hcd *hcd)
        mb();
 
        configure_hc(uhci);
+       uhci->is_initialized = 1;
        start_rh(uhci);
        return 0;
 
@@ -872,16 +891,15 @@ static int __init uhci_hcd_init(void)
        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)
index 7e96bef..4a69c7e 100644 (file)
@@ -411,6 +411,7 @@ struct uhci_hcd {
        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 */
index 44bba9a..5d6c4f7 100644 (file)
@@ -736,7 +736,6 @@ err:
                if (errbuf) {
                        /* Print the chain for debugging purposes */
                        uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
                        lprintk(errbuf);
                }
        }
@@ -924,26 +923,17 @@ td_error:
        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;