소스 검색

[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>
Alan Stern 19 년 전
부모
커밋
8d402e1ae0
4개의 변경된 파일70개의 추가작업 그리고 39개의 파일을 삭제
  1. 29 7
      drivers/usb/host/uhci-debug.c
  2. 39 21
      drivers/usb/host/uhci-hcd.c
  3. 1 0
      drivers/usb/host/uhci-hcd.h
  4. 1 11
      drivers/usb/host/uhci-q.c

+ 29 - 7
drivers/usb/host/uhci-debug.c

@@ -17,10 +17,13 @@
 
 
 #include "uhci-hcd.h"
 #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 */
 /* Handle REALLY large printks so we don't overflow buffers */
-static inline void lprintk(char *buf)
+static void lprintk(char *buf)
 {
 {
 	char *p;
 	char *p;
 
 
@@ -196,7 +199,6 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
 	return out - buf;
 	return out - buf;
 }
 }
 
 
-#ifdef CONFIG_PROC_FS
 static const char * const qh_names[] = {
 static const char * const qh_names[] = {
   "skel_unlink_qh", "skel_iso_qh",
   "skel_unlink_qh", "skel_iso_qh",
   "skel_int128_qh", "skel_int64_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;
 	return out - buf;
 }
 }
 
 
+#ifdef CONFIG_DEBUG_FS
+
 #define MAX_OUTPUT	(64 * 1024)
 #define MAX_OUTPUT	(64 * 1024)
 
 
 struct uhci_debug {
 struct uhci_debug {
 	int size;
 	int size;
 	char *data;
 	char *data;
-	struct uhci_hcd *uhci;
 };
 };
 
 
 static int uhci_debug_open(struct inode *inode, struct file *file)
 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;
 		goto out;
 	}
 	}
 
 
+	up->size = 0;
 	spin_lock_irqsave(&uhci->lock, flags);
 	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);
 	spin_unlock_irqrestore(&uhci->lock, flags);
 
 
 	file->private_data = up;
 	file->private_data = up;
@@ -472,15 +477,32 @@ static int uhci_debug_release(struct inode *inode, struct file *file)
 	return 0;
 	return 0;
 }
 }
 
 
+#undef uhci_debug_operations
 static struct file_operations uhci_debug_operations = {
 static struct file_operations uhci_debug_operations = {
+	.owner =	THIS_MODULE,
 	.open =		uhci_debug_open,
 	.open =		uhci_debug_open,
 	.llseek =	uhci_debug_lseek,
 	.llseek =	uhci_debug_lseek,
 	.read =		uhci_debug_read,
 	.read =		uhci_debug_read,
 	.release =	uhci_debug_release,
 	.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
 #endif

+ 39 - 21
drivers/usb/host/uhci-hcd.c

@@ -68,12 +68,16 @@ Alan Stern"
  * debug = 3, show all TDs in URBs when dumping
  * debug = 3, show all TDs in URBs when dumping
  */
  */
 #ifdef DEBUG
 #ifdef DEBUG
+#define DEBUG_CONFIGURED	1
 static int debug = 1;
 static int debug = 1;
-#else
-static int debug = 0;
-#endif
 module_param(debug, int, S_IRUGO | S_IWUSR);
 module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level");
 MODULE_PARM_DESC(debug, "Debug level");
+
+#else
+#define DEBUG_CONFIGURED	0
+#define debug			0
+#endif
+
 static char *errbuf;
 static char *errbuf;
 #define ERRBUF_LEN    (32 * 1024)
 #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),
 				dev_err(uhci_dev(uhci),
 					"host controller halted, "
 					"host controller halted, "
 					"very bad!\n");
 					"very bad!\n");
+				if (debug > 1 && errbuf) {
+					/* Print the schedule for debugging */
+					uhci_sprint_schedule(uhci,
+							errbuf, ERRBUF_LEN);
+					lprintk(errbuf);
+				}
 				hc_died(uhci);
 				hc_died(uhci);
 
 
 				/* Force a callback in case there are
 				/* Force a callback in case there are
@@ -376,6 +386,14 @@ static void release_uhci(struct uhci_hcd *uhci)
 {
 {
 	int i;
 	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++)
 	for (i = 0; i < UHCI_NUM_SKELQH; i++)
 		uhci_free_qh(uhci, uhci->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),
 	dma_free_coherent(uhci_dev(uhci),
 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
 			uhci->frame, uhci->frame_dma_handle);
 			uhci->frame, uhci->frame_dma_handle);
-
-	debugfs_remove(uhci->dentry);
 }
 }
 
 
 static int uhci_reset(struct usb_hcd *hcd)
 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;
 	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->fsbr = 0;
 	uhci->fsbrtimeout = 0;
 	uhci->fsbrtimeout = 0;
 
 
@@ -495,6 +500,19 @@ static int uhci_start(struct usb_hcd *hcd)
 
 
 	init_waitqueue_head(&uhci->waitqh);
 	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->frame = dma_alloc_coherent(uhci_dev(uhci),
 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
 			UHCI_NUMFRAMES * sizeof(*uhci->frame),
 			&uhci->frame_dma_handle, 0);
 			&uhci->frame_dma_handle, 0);
@@ -609,6 +627,7 @@ static int uhci_start(struct usb_hcd *hcd)
 	mb();
 	mb();
 
 
 	configure_hc(uhci);
 	configure_hc(uhci);
+	uhci->is_initialized = 1;
 	start_rh(uhci);
 	start_rh(uhci);
 	return 0;
 	return 0;
 
 
@@ -872,16 +891,15 @@ static int __init uhci_hcd_init(void)
 	if (usb_disabled())
 	if (usb_disabled())
 		return -ENODEV;
 		return -ENODEV;
 
 
-	if (debug) {
+	if (DEBUG_CONFIGURED) {
 		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
 		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
 		if (!errbuf)
 		if (!errbuf)
 			goto errbuf_failed;
 			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",
 	uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
 		sizeof(struct urb_priv), 0, 0, NULL, NULL);
 		sizeof(struct urb_priv), 0, 0, NULL, NULL);
 	if (!uhci_up_cachep)
 	if (!uhci_up_cachep)

+ 1 - 0
drivers/usb/host/uhci-hcd.h

@@ -411,6 +411,7 @@ struct uhci_hcd {
 	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
 	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
 	unsigned int working_RD:1;		/* Suspended root hub doesn't
 	unsigned int working_RD:1;		/* Suspended root hub doesn't
 						   need to be polled */
 						   need to be polled */
+	unsigned int is_initialized:1;		/* Data structure is usable */
 
 
 	/* Support for port suspend/resume/reset */
 	/* Support for port suspend/resume/reset */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */

+ 1 - 11
drivers/usb/host/uhci-q.c

@@ -736,7 +736,6 @@ err:
 		if (errbuf) {
 		if (errbuf) {
 			/* Print the chain for debugging purposes */
 			/* Print the chain for debugging purposes */
 			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
 			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
 			lprintk(errbuf);
 			lprintk(errbuf);
 		}
 		}
 	}
 	}
@@ -924,26 +923,17 @@ td_error:
 	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
 	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
 
 
 err:
 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) {
 	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
 		/* Some debugging code */
 		/* Some debugging code */
 		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
 		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
 				__FUNCTION__, status);
 				__FUNCTION__, status);
 
 
-		if (errbuf) {
+		if (debug > 1 && errbuf) {
 			/* Print the chain for debugging purposes */
 			/* Print the chain for debugging purposes */
 			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
 			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
 			lprintk(errbuf);
 			lprintk(errbuf);
 		}
 		}
 	}
 	}
-#endif
 
 
 	/* Note that the queue has stopped and save the next toggle value */
 	/* Note that the queue has stopped and save the next toggle value */
 	urbp->qh->element = UHCI_PTR_TERM;
 	urbp->qh->element = UHCI_PTR_TERM;