[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>
This commit is contained in:
parent
0ed8fee1c1
commit
8d402e1ae0
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue