diff options
-rw-r--r-- | drivers/usb/host/ohci-dbg.c | 213 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 18 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 7 |
3 files changed, 209 insertions, 29 deletions
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 9bd589806245..a22c30aa745d 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -401,6 +401,42 @@ static inline void remove_debug_files (struct ohci_hcd *bus) { } | |||
401 | 401 | ||
402 | #else | 402 | #else |
403 | 403 | ||
404 | static int debug_async_open(struct inode *, struct file *); | ||
405 | static int debug_periodic_open(struct inode *, struct file *); | ||
406 | static int debug_registers_open(struct inode *, struct file *); | ||
407 | static int debug_async_open(struct inode *, struct file *); | ||
408 | static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); | ||
409 | static int debug_close(struct inode *, struct file *); | ||
410 | |||
411 | static const struct file_operations debug_async_fops = { | ||
412 | .owner = THIS_MODULE, | ||
413 | .open = debug_async_open, | ||
414 | .read = debug_output, | ||
415 | .release = debug_close, | ||
416 | }; | ||
417 | static const struct file_operations debug_periodic_fops = { | ||
418 | .owner = THIS_MODULE, | ||
419 | .open = debug_periodic_open, | ||
420 | .read = debug_output, | ||
421 | .release = debug_close, | ||
422 | }; | ||
423 | static const struct file_operations debug_registers_fops = { | ||
424 | .owner = THIS_MODULE, | ||
425 | .open = debug_registers_open, | ||
426 | .read = debug_output, | ||
427 | .release = debug_close, | ||
428 | }; | ||
429 | |||
430 | static struct dentry *ohci_debug_root; | ||
431 | |||
432 | struct debug_buffer { | ||
433 | ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ | ||
434 | struct device *dev; | ||
435 | struct mutex mutex; /* protect filling of buffer */ | ||
436 | size_t count; /* number of characters filled into buffer */ | ||
437 | char *page; | ||
438 | }; | ||
439 | |||
404 | static ssize_t | 440 | static ssize_t |
405 | show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) | 441 | show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) |
406 | { | 442 | { |
@@ -467,8 +503,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) | |||
467 | return count - size; | 503 | return count - size; |
468 | } | 504 | } |
469 | 505 | ||
470 | static ssize_t | 506 | static ssize_t fill_async_buffer(struct debug_buffer *buf) |
471 | show_async(struct device *dev, struct device_attribute *attr, char *buf) | ||
472 | { | 507 | { |
473 | struct usb_bus *bus; | 508 | struct usb_bus *bus; |
474 | struct usb_hcd *hcd; | 509 | struct usb_hcd *hcd; |
@@ -476,25 +511,23 @@ show_async(struct device *dev, struct device_attribute *attr, char *buf) | |||
476 | size_t temp; | 511 | size_t temp; |
477 | unsigned long flags; | 512 | unsigned long flags; |
478 | 513 | ||
479 | bus = dev_get_drvdata(dev); | 514 | bus = dev_get_drvdata(buf->dev); |
480 | hcd = bus_to_hcd(bus); | 515 | hcd = bus_to_hcd(bus); |
481 | ohci = hcd_to_ohci(hcd); | 516 | ohci = hcd_to_ohci(hcd); |
482 | 517 | ||
483 | /* display control and bulk lists together, for simplicity */ | 518 | /* display control and bulk lists together, for simplicity */ |
484 | spin_lock_irqsave (&ohci->lock, flags); | 519 | spin_lock_irqsave (&ohci->lock, flags); |
485 | temp = show_list (ohci, buf, PAGE_SIZE, ohci->ed_controltail); | 520 | temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail); |
486 | temp += show_list (ohci, buf + temp, PAGE_SIZE - temp, ohci->ed_bulktail); | 521 | temp += show_list(ohci, buf->page + temp, buf->count - temp, |
522 | ohci->ed_bulktail); | ||
487 | spin_unlock_irqrestore (&ohci->lock, flags); | 523 | spin_unlock_irqrestore (&ohci->lock, flags); |
488 | 524 | ||
489 | return temp; | 525 | return temp; |
490 | } | 526 | } |
491 | static DEVICE_ATTR(async, S_IRUGO, show_async, NULL); | ||
492 | |||
493 | 527 | ||
494 | #define DBG_SCHED_LIMIT 64 | 528 | #define DBG_SCHED_LIMIT 64 |
495 | 529 | ||
496 | static ssize_t | 530 | static ssize_t fill_periodic_buffer(struct debug_buffer *buf) |
497 | show_periodic(struct device *dev, struct device_attribute *attr, char *buf) | ||
498 | { | 531 | { |
499 | struct usb_bus *bus; | 532 | struct usb_bus *bus; |
500 | struct usb_hcd *hcd; | 533 | struct usb_hcd *hcd; |
@@ -509,10 +542,10 @@ show_periodic(struct device *dev, struct device_attribute *attr, char *buf) | |||
509 | return 0; | 542 | return 0; |
510 | seen_count = 0; | 543 | seen_count = 0; |
511 | 544 | ||
512 | bus = dev_get_drvdata(dev); | 545 | bus = (struct usb_bus *)dev_get_drvdata(buf->dev); |
513 | hcd = bus_to_hcd(bus); | 546 | hcd = bus_to_hcd(bus); |
514 | ohci = hcd_to_ohci(hcd); | 547 | ohci = hcd_to_ohci(hcd); |
515 | next = buf; | 548 | next = buf->page; |
516 | size = PAGE_SIZE; | 549 | size = PAGE_SIZE; |
517 | 550 | ||
518 | temp = scnprintf (next, size, "size = %d\n", NUM_INTS); | 551 | temp = scnprintf (next, size, "size = %d\n", NUM_INTS); |
@@ -589,13 +622,9 @@ show_periodic(struct device *dev, struct device_attribute *attr, char *buf) | |||
589 | 622 | ||
590 | return PAGE_SIZE - size; | 623 | return PAGE_SIZE - size; |
591 | } | 624 | } |
592 | static DEVICE_ATTR(periodic, S_IRUGO, show_periodic, NULL); | ||
593 | |||
594 | |||
595 | #undef DBG_SCHED_LIMIT | 625 | #undef DBG_SCHED_LIMIT |
596 | 626 | ||
597 | static ssize_t | 627 | static ssize_t fill_registers_buffer(struct debug_buffer *buf) |
598 | show_registers(struct device *dev, struct device_attribute *attr, char *buf) | ||
599 | { | 628 | { |
600 | struct usb_bus *bus; | 629 | struct usb_bus *bus; |
601 | struct usb_hcd *hcd; | 630 | struct usb_hcd *hcd; |
@@ -606,11 +635,11 @@ show_registers(struct device *dev, struct device_attribute *attr, char *buf) | |||
606 | char *next; | 635 | char *next; |
607 | u32 rdata; | 636 | u32 rdata; |
608 | 637 | ||
609 | bus = dev_get_drvdata(dev); | 638 | bus = (struct usb_bus *)dev_get_drvdata(buf->dev); |
610 | hcd = bus_to_hcd(bus); | 639 | hcd = bus_to_hcd(bus); |
611 | ohci = hcd_to_ohci(hcd); | 640 | ohci = hcd_to_ohci(hcd); |
612 | regs = ohci->regs; | 641 | regs = ohci->regs; |
613 | next = buf; | 642 | next = buf->page; |
614 | size = PAGE_SIZE; | 643 | size = PAGE_SIZE; |
615 | 644 | ||
616 | spin_lock_irqsave (&ohci->lock, flags); | 645 | spin_lock_irqsave (&ohci->lock, flags); |
@@ -677,29 +706,155 @@ show_registers(struct device *dev, struct device_attribute *attr, char *buf) | |||
677 | 706 | ||
678 | done: | 707 | done: |
679 | spin_unlock_irqrestore (&ohci->lock, flags); | 708 | spin_unlock_irqrestore (&ohci->lock, flags); |
709 | |||
680 | return PAGE_SIZE - size; | 710 | return PAGE_SIZE - size; |
681 | } | 711 | } |
682 | static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); | ||
683 | 712 | ||
713 | static struct debug_buffer *alloc_buffer(struct device *dev, | ||
714 | ssize_t (*fill_func)(struct debug_buffer *)) | ||
715 | { | ||
716 | struct debug_buffer *buf; | ||
717 | |||
718 | buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); | ||
684 | 719 | ||
720 | if (buf) { | ||
721 | buf->dev = dev; | ||
722 | buf->fill_func = fill_func; | ||
723 | mutex_init(&buf->mutex); | ||
724 | } | ||
725 | |||
726 | return buf; | ||
727 | } | ||
728 | |||
729 | static int fill_buffer(struct debug_buffer *buf) | ||
730 | { | ||
731 | int ret = 0; | ||
732 | |||
733 | if (!buf->page) | ||
734 | buf->page = (char *)get_zeroed_page(GFP_KERNEL); | ||
735 | |||
736 | if (!buf->page) { | ||
737 | ret = -ENOMEM; | ||
738 | goto out; | ||
739 | } | ||
740 | |||
741 | ret = buf->fill_func(buf); | ||
742 | |||
743 | if (ret >= 0) { | ||
744 | buf->count = ret; | ||
745 | ret = 0; | ||
746 | } | ||
747 | |||
748 | out: | ||
749 | return ret; | ||
750 | } | ||
751 | |||
752 | static ssize_t debug_output(struct file *file, char __user *user_buf, | ||
753 | size_t len, loff_t *offset) | ||
754 | { | ||
755 | struct debug_buffer *buf = file->private_data; | ||
756 | int ret = 0; | ||
757 | |||
758 | mutex_lock(&buf->mutex); | ||
759 | if (buf->count == 0) { | ||
760 | ret = fill_buffer(buf); | ||
761 | if (ret != 0) { | ||
762 | mutex_unlock(&buf->mutex); | ||
763 | goto out; | ||
764 | } | ||
765 | } | ||
766 | mutex_unlock(&buf->mutex); | ||
767 | |||
768 | ret = simple_read_from_buffer(user_buf, len, offset, | ||
769 | buf->page, buf->count); | ||
770 | |||
771 | out: | ||
772 | return ret; | ||
773 | |||
774 | } | ||
775 | |||
776 | static int debug_close(struct inode *inode, struct file *file) | ||
777 | { | ||
778 | struct debug_buffer *buf = file->private_data; | ||
779 | |||
780 | if (buf) { | ||
781 | if (buf->page) | ||
782 | free_page((unsigned long)buf->page); | ||
783 | kfree(buf); | ||
784 | } | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | static int debug_async_open(struct inode *inode, struct file *file) | ||
789 | { | ||
790 | file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); | ||
791 | |||
792 | return file->private_data ? 0 : -ENOMEM; | ||
793 | } | ||
794 | |||
795 | static int debug_periodic_open(struct inode *inode, struct file *file) | ||
796 | { | ||
797 | file->private_data = alloc_buffer(inode->i_private, | ||
798 | fill_periodic_buffer); | ||
799 | |||
800 | return file->private_data ? 0 : -ENOMEM; | ||
801 | } | ||
802 | |||
803 | static int debug_registers_open(struct inode *inode, struct file *file) | ||
804 | { | ||
805 | file->private_data = alloc_buffer(inode->i_private, | ||
806 | fill_registers_buffer); | ||
807 | |||
808 | return file->private_data ? 0 : -ENOMEM; | ||
809 | } | ||
685 | static inline void create_debug_files (struct ohci_hcd *ohci) | 810 | static inline void create_debug_files (struct ohci_hcd *ohci) |
686 | { | 811 | { |
687 | struct device *dev = ohci_to_hcd(ohci)->self.dev; | 812 | struct usb_bus *bus = &ohci_to_hcd(ohci)->self; |
688 | int retval; | 813 | struct device *dev = bus->dev; |
814 | |||
815 | ohci->debug_dir = debugfs_create_dir(bus->bus_name, ohci_debug_root); | ||
816 | if (!ohci->debug_dir) | ||
817 | goto dir_error; | ||
818 | |||
819 | ohci->debug_async = debugfs_create_file("async", S_IRUGO, | ||
820 | ohci->debug_dir, dev, | ||
821 | &debug_async_fops); | ||
822 | if (!ohci->debug_async) | ||
823 | goto async_error; | ||
824 | |||
825 | ohci->debug_periodic = debugfs_create_file("periodic", S_IRUGO, | ||
826 | ohci->debug_dir, dev, | ||
827 | &debug_periodic_fops); | ||
828 | if (!ohci->debug_periodic) | ||
829 | goto periodic_error; | ||
830 | |||
831 | ohci->debug_registers = debugfs_create_file("registers", S_IRUGO, | ||
832 | ohci->debug_dir, dev, | ||
833 | &debug_registers_fops); | ||
834 | if (!ohci->debug_registers) | ||
835 | goto registers_error; | ||
689 | 836 | ||
690 | retval = device_create_file(dev, &dev_attr_async); | ||
691 | retval = device_create_file(dev, &dev_attr_periodic); | ||
692 | retval = device_create_file(dev, &dev_attr_registers); | ||
693 | ohci_dbg (ohci, "created debug files\n"); | 837 | ohci_dbg (ohci, "created debug files\n"); |
838 | return; | ||
839 | |||
840 | registers_error: | ||
841 | debugfs_remove(ohci->debug_periodic); | ||
842 | periodic_error: | ||
843 | debugfs_remove(ohci->debug_async); | ||
844 | async_error: | ||
845 | debugfs_remove(ohci->debug_dir); | ||
846 | dir_error: | ||
847 | ohci->debug_periodic = NULL; | ||
848 | ohci->debug_async = NULL; | ||
849 | ohci->debug_dir = NULL; | ||
694 | } | 850 | } |
695 | 851 | ||
696 | static inline void remove_debug_files (struct ohci_hcd *ohci) | 852 | static inline void remove_debug_files (struct ohci_hcd *ohci) |
697 | { | 853 | { |
698 | struct device *dev = ohci_to_hcd(ohci)->self.dev; | 854 | debugfs_remove(ohci->debug_registers); |
699 | 855 | debugfs_remove(ohci->debug_periodic); | |
700 | device_remove_file(dev, &dev_attr_async); | 856 | debugfs_remove(ohci->debug_async); |
701 | device_remove_file(dev, &dev_attr_periodic); | 857 | debugfs_remove(ohci->debug_dir); |
702 | device_remove_file(dev, &dev_attr_registers); | ||
703 | } | 858 | } |
704 | 859 | ||
705 | #endif | 860 | #endif |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ddd4ee1f2413..baca09af6076 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/dmapool.h> | 36 | #include <linux/dmapool.h> |
37 | #include <linux/reboot.h> | 37 | #include <linux/reboot.h> |
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | #include <linux/debugfs.h> | ||
39 | 40 | ||
40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
41 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
@@ -1068,6 +1069,14 @@ static int __init ohci_hcd_mod_init(void) | |||
1068 | pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, | 1069 | pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, |
1069 | sizeof (struct ed), sizeof (struct td)); | 1070 | sizeof (struct ed), sizeof (struct td)); |
1070 | 1071 | ||
1072 | #ifdef DEBUG | ||
1073 | ohci_debug_root = debugfs_create_dir("ohci", NULL); | ||
1074 | if (!ohci_debug_root) { | ||
1075 | retval = -ENOENT; | ||
1076 | goto error_debug; | ||
1077 | } | ||
1078 | #endif | ||
1079 | |||
1071 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1080 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1072 | retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); | 1081 | retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
1073 | if (retval < 0) | 1082 | if (retval < 0) |
@@ -1130,6 +1139,12 @@ static int __init ohci_hcd_mod_init(void) | |||
1130 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | 1139 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1131 | error_ps3: | 1140 | error_ps3: |
1132 | #endif | 1141 | #endif |
1142 | #ifdef DEBUG | ||
1143 | debugfs_remove(ohci_debug_root); | ||
1144 | ohci_debug_root = NULL; | ||
1145 | error_debug: | ||
1146 | #endif | ||
1147 | |||
1133 | return retval; | 1148 | return retval; |
1134 | } | 1149 | } |
1135 | module_init(ohci_hcd_mod_init); | 1150 | module_init(ohci_hcd_mod_init); |
@@ -1154,6 +1169,9 @@ static void __exit ohci_hcd_mod_exit(void) | |||
1154 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1169 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1155 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | 1170 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1156 | #endif | 1171 | #endif |
1172 | #ifdef DEBUG | ||
1173 | debugfs_remove(ohci_debug_root); | ||
1174 | #endif | ||
1157 | } | 1175 | } |
1158 | module_exit(ohci_hcd_mod_exit); | 1176 | module_exit(ohci_hcd_mod_exit); |
1159 | 1177 | ||
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 47c5c66a282c..dc544ddc7849 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -408,6 +408,13 @@ struct ohci_hcd { | |||
408 | unsigned eds_scheduled; | 408 | unsigned eds_scheduled; |
409 | struct ed *ed_to_check; | 409 | struct ed *ed_to_check; |
410 | unsigned zf_delay; | 410 | unsigned zf_delay; |
411 | |||
412 | #ifdef DEBUG | ||
413 | struct dentry *debug_dir; | ||
414 | struct dentry *debug_async; | ||
415 | struct dentry *debug_periodic; | ||
416 | struct dentry *debug_registers; | ||
417 | #endif | ||
411 | }; | 418 | }; |
412 | 419 | ||
413 | #ifdef CONFIG_PCI | 420 | #ifdef CONFIG_PCI |