aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ehci-dbg.c227
-rw-r--r--drivers/usb/host/ehci-hcd.c25
-rw-r--r--drivers/usb/host/ehci.h8
3 files changed, 219 insertions, 41 deletions
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 754a146cf828..39673f8194d9 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -323,7 +323,43 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
323 323
324#else 324#else
325 325
326/* troubleshooting help: expose state in sysfs */ 326/* troubleshooting help: expose state in debugfs */
327
328static int debug_async_open(struct inode *, struct file *);
329static int debug_periodic_open(struct inode *, struct file *);
330static int debug_registers_open(struct inode *, struct file *);
331static int debug_async_open(struct inode *, struct file *);
332static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
333static int debug_close(struct inode *, struct file *);
334
335static const struct file_operations debug_async_fops = {
336 .owner = THIS_MODULE,
337 .open = debug_async_open,
338 .read = debug_output,
339 .release = debug_close,
340};
341static const struct file_operations debug_periodic_fops = {
342 .owner = THIS_MODULE,
343 .open = debug_periodic_open,
344 .read = debug_output,
345 .release = debug_close,
346};
347static const struct file_operations debug_registers_fops = {
348 .owner = THIS_MODULE,
349 .open = debug_registers_open,
350 .read = debug_output,
351 .release = debug_close,
352};
353
354static struct dentry *ehci_debug_root;
355
356struct debug_buffer {
357 ssize_t (*fill_func)(struct debug_buffer *); /* fill method */
358 struct usb_bus *bus;
359 struct mutex mutex; /* protect filling of buffer */
360 size_t count; /* number of characters filled into buffer */
361 char *page;
362};
327 363
328#define speed_char(info1) ({ char tmp; \ 364#define speed_char(info1) ({ char tmp; \
329 switch (info1 & (3 << 12)) { \ 365 switch (info1 & (3 << 12)) { \
@@ -441,10 +477,8 @@ done:
441 *nextp = next; 477 *nextp = next;
442} 478}
443 479
444static ssize_t 480static ssize_t fill_async_buffer(struct debug_buffer *buf)
445show_async(struct device *dev, struct device_attribute *attr, char *buf)
446{ 481{
447 struct usb_bus *bus;
448 struct usb_hcd *hcd; 482 struct usb_hcd *hcd;
449 struct ehci_hcd *ehci; 483 struct ehci_hcd *ehci;
450 unsigned long flags; 484 unsigned long flags;
@@ -452,14 +486,13 @@ show_async(struct device *dev, struct device_attribute *attr, char *buf)
452 char *next; 486 char *next;
453 struct ehci_qh *qh; 487 struct ehci_qh *qh;
454 488
455 *buf = 0; 489 hcd = bus_to_hcd(buf->bus);
456
457 bus = dev_get_drvdata(dev);
458 hcd = bus_to_hcd(bus);
459 ehci = hcd_to_ehci (hcd); 490 ehci = hcd_to_ehci (hcd);
460 next = buf; 491 next = buf->page;
461 size = PAGE_SIZE; 492 size = PAGE_SIZE;
462 493
494 *next = 0;
495
463 /* dumps a snapshot of the async schedule. 496 /* dumps a snapshot of the async schedule.
464 * usually empty except for long-term bulk reads, or head. 497 * usually empty except for long-term bulk reads, or head.
465 * one QH per line, and TDs we know about 498 * one QH per line, and TDs we know about
@@ -477,16 +510,12 @@ show_async(struct device *dev, struct device_attribute *attr, char *buf)
477 } 510 }
478 spin_unlock_irqrestore (&ehci->lock, flags); 511 spin_unlock_irqrestore (&ehci->lock, flags);
479 512
480 return strlen (buf); 513 return strlen(buf->page);
481} 514}
482static DEVICE_ATTR(async, S_IRUGO, show_async, NULL);
483 515
484#define DBG_SCHED_LIMIT 64 516#define DBG_SCHED_LIMIT 64
485 517static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
486static ssize_t
487show_periodic(struct device *dev, struct device_attribute *attr, char *buf)
488{ 518{
489 struct usb_bus *bus;
490 struct usb_hcd *hcd; 519 struct usb_hcd *hcd;
491 struct ehci_hcd *ehci; 520 struct ehci_hcd *ehci;
492 unsigned long flags; 521 unsigned long flags;
@@ -500,10 +529,9 @@ show_periodic(struct device *dev, struct device_attribute *attr, char *buf)
500 return 0; 529 return 0;
501 seen_count = 0; 530 seen_count = 0;
502 531
503 bus = dev_get_drvdata(dev); 532 hcd = bus_to_hcd(buf->bus);
504 hcd = bus_to_hcd(bus);
505 ehci = hcd_to_ehci (hcd); 533 ehci = hcd_to_ehci (hcd);
506 next = buf; 534 next = buf->page;
507 size = PAGE_SIZE; 535 size = PAGE_SIZE;
508 536
509 temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); 537 temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size);
@@ -623,14 +651,10 @@ show_periodic(struct device *dev, struct device_attribute *attr, char *buf)
623 651
624 return PAGE_SIZE - size; 652 return PAGE_SIZE - size;
625} 653}
626static DEVICE_ATTR(periodic, S_IRUGO, show_periodic, NULL);
627
628#undef DBG_SCHED_LIMIT 654#undef DBG_SCHED_LIMIT
629 655
630static ssize_t 656static ssize_t fill_registers_buffer(struct debug_buffer *buf)
631show_registers(struct device *dev, struct device_attribute *attr, char *buf)
632{ 657{
633 struct usb_bus *bus;
634 struct usb_hcd *hcd; 658 struct usb_hcd *hcd;
635 struct ehci_hcd *ehci; 659 struct ehci_hcd *ehci;
636 unsigned long flags; 660 unsigned long flags;
@@ -639,15 +663,14 @@ show_registers(struct device *dev, struct device_attribute *attr, char *buf)
639 static char fmt [] = "%*s\n"; 663 static char fmt [] = "%*s\n";
640 static char label [] = ""; 664 static char label [] = "";
641 665
642 bus = dev_get_drvdata(dev); 666 hcd = bus_to_hcd(buf->bus);
643 hcd = bus_to_hcd(bus);
644 ehci = hcd_to_ehci (hcd); 667 ehci = hcd_to_ehci (hcd);
645 next = buf; 668 next = buf->page;
646 size = PAGE_SIZE; 669 size = PAGE_SIZE;
647 670
648 spin_lock_irqsave (&ehci->lock, flags); 671 spin_lock_irqsave (&ehci->lock, flags);
649 672
650 if (bus->controller->power.power_state.event) { 673 if (buf->bus->controller->power.power_state.event) {
651 size = scnprintf (next, size, 674 size = scnprintf (next, size,
652 "bus %s, device %s (driver " DRIVER_VERSION ")\n" 675 "bus %s, device %s (driver " DRIVER_VERSION ")\n"
653 "%s\n" 676 "%s\n"
@@ -789,26 +812,150 @@ done:
789 812
790 return PAGE_SIZE - size; 813 return PAGE_SIZE - size;
791} 814}
792static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
793 815
794static inline void create_debug_files (struct ehci_hcd *ehci) 816static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
817 ssize_t (*fill_func)(struct debug_buffer *))
795{ 818{
796 struct device *dev = ehci_to_hcd(ehci)->self.dev; 819 struct debug_buffer *buf;
797 int retval; 820
821 buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
798 822
799 retval = device_create_file(dev, &dev_attr_async); 823 if (buf) {
800 retval = device_create_file(dev, &dev_attr_periodic); 824 buf->bus = bus;
801 retval = device_create_file(dev, &dev_attr_registers); 825 buf->fill_func = fill_func;
826 mutex_init(&buf->mutex);
827 }
828
829 return buf;
802} 830}
803 831
804static inline void remove_debug_files (struct ehci_hcd *ehci) 832static int fill_buffer(struct debug_buffer *buf)
805{ 833{
806 struct device *dev = ehci_to_hcd(ehci)->self.dev; 834 int ret = 0;
835
836 if (!buf->page)
837 buf->page = (char *)get_zeroed_page(GFP_KERNEL);
838
839 if (!buf->page) {
840 ret = -ENOMEM;
841 goto out;
842 }
843
844 ret = buf->fill_func(buf);
807 845
808 device_remove_file(dev, &dev_attr_async); 846 if (ret >= 0) {
809 device_remove_file(dev, &dev_attr_periodic); 847 buf->count = ret;
810 device_remove_file(dev, &dev_attr_registers); 848 ret = 0;
849 }
850
851out:
852 return ret;
811} 853}
812 854
813#endif /* STUB_DEBUG_FILES */ 855static ssize_t debug_output(struct file *file, char __user *user_buf,
856 size_t len, loff_t *offset)
857{
858 struct debug_buffer *buf = file->private_data;
859 int ret = 0;
860
861 mutex_lock(&buf->mutex);
862 if (buf->count == 0) {
863 ret = fill_buffer(buf);
864 if (ret != 0) {
865 mutex_unlock(&buf->mutex);
866 goto out;
867 }
868 }
869 mutex_unlock(&buf->mutex);
870
871 ret = simple_read_from_buffer(user_buf, len, offset,
872 buf->page, buf->count);
873
874out:
875 return ret;
876
877}
878
879static int debug_close(struct inode *inode, struct file *file)
880{
881 struct debug_buffer *buf = file->private_data;
814 882
883 if (buf) {
884 if (buf->page)
885 free_page((unsigned long)buf->page);
886 kfree(buf);
887 }
888
889 return 0;
890}
891static int debug_async_open(struct inode *inode, struct file *file)
892{
893 file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
894
895 return file->private_data ? 0 : -ENOMEM;
896}
897
898static int debug_periodic_open(struct inode *inode, struct file *file)
899{
900 file->private_data = alloc_buffer(inode->i_private,
901 fill_periodic_buffer);
902
903 return file->private_data ? 0 : -ENOMEM;
904}
905
906static int debug_registers_open(struct inode *inode, struct file *file)
907{
908 file->private_data = alloc_buffer(inode->i_private,
909 fill_registers_buffer);
910
911 return file->private_data ? 0 : -ENOMEM;
912}
913
914static inline void create_debug_files (struct ehci_hcd *ehci)
915{
916 struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
917
918 ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root);
919 if (!ehci->debug_dir)
920 goto dir_error;
921
922 ehci->debug_async = debugfs_create_file("async", S_IRUGO,
923 ehci->debug_dir, bus,
924 &debug_async_fops);
925 if (!ehci->debug_async)
926 goto async_error;
927
928 ehci->debug_periodic = debugfs_create_file("periodic", S_IRUGO,
929 ehci->debug_dir, bus,
930 &debug_periodic_fops);
931 if (!ehci->debug_periodic)
932 goto periodic_error;
933
934 ehci->debug_registers = debugfs_create_file("registers", S_IRUGO,
935 ehci->debug_dir, bus,
936 &debug_registers_fops);
937 if (!ehci->debug_registers)
938 goto registers_error;
939 return;
940
941registers_error:
942 debugfs_remove(ehci->debug_periodic);
943periodic_error:
944 debugfs_remove(ehci->debug_async);
945async_error:
946 debugfs_remove(ehci->debug_dir);
947dir_error:
948 ehci->debug_periodic = NULL;
949 ehci->debug_async = NULL;
950 ehci->debug_dir = NULL;
951}
952
953static inline void remove_debug_files (struct ehci_hcd *ehci)
954{
955 debugfs_remove(ehci->debug_registers);
956 debugfs_remove(ehci->debug_periodic);
957 debugfs_remove(ehci->debug_async);
958 debugfs_remove(ehci->debug_dir);
959}
960
961#endif /* STUB_DEBUG_FILES */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5f2d74ed5ad7..264182654f4c 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -33,6 +33,7 @@
33#include <linux/usb.h> 33#include <linux/usb.h>
34#include <linux/moduleparam.h> 34#include <linux/moduleparam.h>
35#include <linux/dma-mapping.h> 35#include <linux/dma-mapping.h>
36#include <linux/debugfs.h>
36 37
37#include "../core/hcd.h" 38#include "../core/hcd.h"
38 39
@@ -978,15 +979,30 @@ static int __init ehci_hcd_init(void)
978 sizeof(struct ehci_qh), sizeof(struct ehci_qtd), 979 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
979 sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); 980 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
980 981
982#ifdef DEBUG
983 ehci_debug_root = debugfs_create_dir("ehci", NULL);
984 if (!ehci_debug_root)
985 return -ENOENT;
986#endif
987
981#ifdef PLATFORM_DRIVER 988#ifdef PLATFORM_DRIVER
982 retval = platform_driver_register(&PLATFORM_DRIVER); 989 retval = platform_driver_register(&PLATFORM_DRIVER);
983 if (retval < 0) 990 if (retval < 0) {
991#ifdef DEBUG
992 debugfs_remove(ehci_debug_root);
993 ehci_debug_root = NULL;
994#endif
984 return retval; 995 return retval;
996 }
985#endif 997#endif
986 998
987#ifdef PCI_DRIVER 999#ifdef PCI_DRIVER
988 retval = pci_register_driver(&PCI_DRIVER); 1000 retval = pci_register_driver(&PCI_DRIVER);
989 if (retval < 0) { 1001 if (retval < 0) {
1002#ifdef DEBUG
1003 debugfs_remove(ehci_debug_root);
1004 ehci_debug_root = NULL;
1005#endif
990#ifdef PLATFORM_DRIVER 1006#ifdef PLATFORM_DRIVER
991 platform_driver_unregister(&PLATFORM_DRIVER); 1007 platform_driver_unregister(&PLATFORM_DRIVER);
992#endif 1008#endif
@@ -997,6 +1013,10 @@ static int __init ehci_hcd_init(void)
997#ifdef PS3_SYSTEM_BUS_DRIVER 1013#ifdef PS3_SYSTEM_BUS_DRIVER
998 retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); 1014 retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
999 if (retval < 0) { 1015 if (retval < 0) {
1016#ifdef DEBUG
1017 debugfs_remove(ehci_debug_root);
1018 ehci_debug_root = NULL;
1019#endif
1000#ifdef PLATFORM_DRIVER 1020#ifdef PLATFORM_DRIVER
1001 platform_driver_unregister(&PLATFORM_DRIVER); 1021 platform_driver_unregister(&PLATFORM_DRIVER);
1002#endif 1022#endif
@@ -1022,6 +1042,9 @@ static void __exit ehci_hcd_cleanup(void)
1022#ifdef PS3_SYSTEM_BUS_DRIVER 1042#ifdef PS3_SYSTEM_BUS_DRIVER
1023 ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); 1043 ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
1024#endif 1044#endif
1045#ifdef DEBUG
1046 debugfs_remove(ehci_debug_root);
1047#endif
1025} 1048}
1026module_exit(ehci_hcd_cleanup); 1049module_exit(ehci_hcd_cleanup);
1027 1050
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 951d69fec513..10e71417c352 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -127,6 +127,14 @@ struct ehci_hcd { /* one per controller */
127#else 127#else
128# define COUNT(x) do {} while (0) 128# define COUNT(x) do {} while (0)
129#endif 129#endif
130
131 /* debug files */
132#ifdef DEBUG
133 struct dentry *debug_dir;
134 struct dentry *debug_async;
135 struct dentry *debug_periodic;
136 struct dentry *debug_registers;
137#endif
130}; 138};
131 139
132/* convert between an HCD pointer and the corresponding EHCI_HCD */ 140/* convert between an HCD pointer and the corresponding EHCI_HCD */