Index: linux-2.6.25.4/drivers/usb/host/adm5120.h
===================================================================
--- linux-2.6.25.4.orig/drivers/usb/host/adm5120.h
+++ linux-2.6.25.4/drivers/usb/host/adm5120.h
@@ -431,6 +431,13 @@ struct admhcd {
 #define	OHCI_QUIRK_BE_MMIO	0x10			/* BE registers */
 #define	OHCI_QUIRK_ZFMICRO	0x20			/* Compaq ZFMicro chipset*/
 	// there are also chip quirks/bugs in init logic
+
+#ifdef DEBUG
+	struct dentry		*debug_dir;
+	struct dentry		*debug_async;
+	struct dentry		*debug_periodic;
+	struct dentry		*debug_registers;
+#endif
 };
 
 /* convert between an hcd pointer and the corresponding ahcd_hcd */
Index: linux-2.6.25.4/drivers/usb/host/adm5120-hcd.c
===================================================================
--- linux-2.6.25.4.orig/drivers/usb/host/adm5120-hcd.c
+++ linux-2.6.25.4/drivers/usb/host/adm5120-hcd.c
@@ -35,6 +35,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
+#include <linux/debugfs.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -799,6 +800,14 @@ static int __init admhc_hcd_mod_init(voi
 	pr_info("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
 		sizeof (struct ed), sizeof (struct td));
 
+#ifdef DEBUG
+	admhc_debug_root = debugfs_create_dir("admhc", NULL);
+	if (!admhc_debug_root) {
+		ret = -ENOENT;
+		goto error_debug;
+	}
+#endif
+
 #ifdef PLATFORM_DRIVER
 	ret = platform_driver_register(&PLATFORM_DRIVER);
 	if (ret < 0)
@@ -811,6 +820,12 @@ static int __init admhc_hcd_mod_init(voi
 	platform_driver_unregister(&PLATFORM_DRIVER);
 error_platform:
 #endif
+
+#ifdef DEBUG
+	debugfs_remove(admhc_debug_root);
+	admhc_debug_root = NULL;
+error_debug:
+#endif
 	return ret;
 }
 module_init(admhc_hcd_mod_init);
@@ -818,6 +833,9 @@ module_init(admhc_hcd_mod_init);
 static void __exit admhc_hcd_mod_exit(void)
 {
 	platform_driver_unregister(&PLATFORM_DRIVER);
+#ifdef DEBUG
+	debugfs_remove(admhc_debug_root);
+#endif
 }
 module_exit(admhc_hcd_mod_exit);
 
Index: linux-2.6.25.4/drivers/usb/host/adm5120-dbg.c
===================================================================
--- linux-2.6.25.4.orig/drivers/usb/host/adm5120-dbg.c
+++ linux-2.6.25.4/drivers/usb/host/adm5120-dbg.c
@@ -390,6 +390,42 @@ static inline void remove_debug_files(st
 
 #else
 
+static int debug_async_open(struct inode *, struct file *);
+static int debug_periodic_open(struct inode *, struct file *);
+static int debug_registers_open(struct inode *, struct file *);
+static int debug_async_open(struct inode *, struct file *);
+static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
+static int debug_close(struct inode *, struct file *);
+
+static const struct file_operations debug_async_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_async_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_periodic_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_periodic_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_registers_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_registers_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+
+static struct dentry *admhc_debug_root;
+
+struct debug_buffer {
+	ssize_t (*fill_func)(struct debug_buffer *);    /* fill method */
+	struct device *dev;
+	struct mutex mutex;     /* protect filling of buffer */
+	size_t count;           /* number of characters filled into buffer */
+	char *page;
+};
+
 static ssize_t
 show_list(struct admhcd *ahcd, char *buf, size_t count, struct ed *ed)
 {
@@ -455,8 +491,7 @@ show_list(struct admhcd *ahcd, char *buf
 	return count - size;
 }
 
-static ssize_t
-show_async(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t fill_async_buffer(struct debug_buffer *buf)
 {
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
@@ -464,24 +499,22 @@ show_async(struct device *dev, struct de
 	size_t			temp;
 	unsigned long		flags;
 
-	bus = dev_get_drvdata(dev);
+	bus = dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	ahcd = hcd_to_admhcd(hcd);
 
 	/* display control and bulk lists together, for simplicity */
 	spin_lock_irqsave(&ahcd->lock, flags);
-	temp = show_list(ahcd, buf, PAGE_SIZE, ahcd->ed_head);
+	temp = show_list(ahcd, buf->page, buf->count, ahcd->ed_head);
 	spin_unlock_irqrestore(&ahcd->lock, flags);
 
 	return temp;
 }
-static DEVICE_ATTR(async, S_IRUGO, show_async, NULL);
 
 
 #define DBG_SCHED_LIMIT 64
 
-static ssize_t
-show_periodic(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 {
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
@@ -496,10 +529,10 @@ show_periodic(struct device *dev, struct
 		return 0;
 	seen_count = 0;
 
-	bus = dev_get_drvdata(dev);
+	bus = dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	ahcd = hcd_to_admhcd(hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 
 	temp = scnprintf(next, size, "size = %d\n", NUM_INTS);
@@ -574,13 +607,11 @@ show_periodic(struct device *dev, struct
 
 	return PAGE_SIZE - size;
 }
-static DEVICE_ATTR(periodic, S_IRUGO, show_periodic, NULL);
 
 
 #undef DBG_SCHED_LIMIT
 
-static ssize_t
-show_registers(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 {
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
@@ -591,11 +622,11 @@ show_registers(struct device *dev, struc
 	char			*next;
 	u32			rdata;
 
-	bus = dev_get_drvdata(dev);
+	bus = dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	ahcd = hcd_to_admhcd(hcd);
 	regs = ahcd->regs;
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 
 	spin_lock_irqsave(&ahcd->lock, flags);
@@ -656,27 +687,154 @@ done:
 	spin_unlock_irqrestore(&ahcd->lock, flags);
 	return PAGE_SIZE - size;
 }
-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
 
 
-static inline void create_debug_files (struct admhcd *ahcd)
+static struct debug_buffer *alloc_buffer(struct device *dev,
+				ssize_t (*fill_func)(struct debug_buffer *))
 {
-	struct device *dev = admhcd_to_hcd(ahcd)->self.dev;
-	int retval;
+	struct debug_buffer *buf;
 
-	retval = device_create_file(dev, &dev_attr_async);
-	retval = device_create_file(dev, &dev_attr_periodic);
-	retval = device_create_file(dev, &dev_attr_registers);
-	admhc_dbg(ahcd, "created debug files\n");
+	buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
+
+	if (buf) {
+		buf->dev = dev;
+		buf->fill_func = fill_func;
+		mutex_init(&buf->mutex);
+	}
+
+	return buf;
+}
+
+static int fill_buffer(struct debug_buffer *buf)
+{
+	int ret = 0;
+
+	if (!buf->page)
+		buf->page = (char *)get_zeroed_page(GFP_KERNEL);
+
+	if (!buf->page) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = buf->fill_func(buf);
+
+	if (ret >= 0) {
+		buf->count = ret;
+		ret = 0;
+	}
+
+out:
+	return ret;
+}
+
+static ssize_t debug_output(struct file *file, char __user *user_buf,
+			size_t len, loff_t *offset)
+{
+	struct debug_buffer *buf = file->private_data;
+	int ret = 0;
+
+	mutex_lock(&buf->mutex);
+	if (buf->count == 0) {
+		ret = fill_buffer(buf);
+		if (ret != 0) {
+			mutex_unlock(&buf->mutex);
+			goto out;
+		}
+	}
+	mutex_unlock(&buf->mutex);
+
+	ret = simple_read_from_buffer(user_buf, len, offset,
+					buf->page, buf->count);
+
+out:
+	return ret;
+}
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	struct debug_buffer *buf = file->private_data;
+
+	if (buf) {
+		if (buf->page)
+			free_page((unsigned long)buf->page);
+		kfree(buf);
+	}
+
+	return 0;
 }
 
-static inline void remove_debug_files (struct admhcd *ahcd)
+static int debug_async_open(struct inode *inode, struct file *file)
 {
-	struct device *dev = admhcd_to_hcd(ahcd)->self.dev;
+	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_periodic_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+						fill_periodic_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
 
-	device_remove_file(dev, &dev_attr_async);
-	device_remove_file(dev, &dev_attr_periodic);
-	device_remove_file(dev, &dev_attr_registers);
+static int debug_registers_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+						fill_registers_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static inline void create_debug_files(struct admhcd *ahcd)
+{
+	struct usb_bus *bus = &admhcd_to_hcd(ahcd)->self;
+	struct device *dev = bus->dev;
+
+	ahcd->debug_dir = debugfs_create_dir(bus->bus_name, admhc_debug_root);
+	if (!ahcd->debug_dir)
+		goto dir_error;
+
+	ahcd->debug_async = debugfs_create_file("async", S_IRUGO,
+						ahcd->debug_dir, dev,
+						&debug_async_fops);
+	if (!ahcd->debug_async)
+		goto async_error;
+
+	ahcd->debug_periodic = debugfs_create_file("periodic", S_IRUGO,
+						ahcd->debug_dir, dev,
+						&debug_periodic_fops);
+	if (!ahcd->debug_periodic)
+		goto periodic_error;
+
+	ahcd->debug_registers = debugfs_create_file("registers", S_IRUGO,
+						ahcd->debug_dir, dev,
+						&debug_registers_fops);
+	if (!ahcd->debug_registers)
+		goto registers_error;
+
+	admhc_dbg(ahcd, "created debug files\n");
+	return;
+
+registers_error:
+	debugfs_remove(ahcd->debug_periodic);
+periodic_error:
+	debugfs_remove(ahcd->debug_async);
+async_error:
+	debugfs_remove(ahcd->debug_dir);
+dir_error:
+	ahcd->debug_periodic = NULL;
+	ahcd->debug_async = NULL;
+	ahcd->debug_dir = NULL;
+}
+
+static inline void remove_debug_files(struct admhcd *ahcd)
+{
+	debugfs_remove(ahcd->debug_registers);
+	debugfs_remove(ahcd->debug_periodic);
+	debugfs_remove(ahcd->debug_async);
+	debugfs_remove(ahcd->debug_dir);
 }
 
 #endif