Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Side by Side Diff: drivers/usb/storage/realtek_cr.c

Issue 2064009: Version 1.02 of the Realtek USB card reader driver fixes the lsusb hang. (Closed) Base URL: ssh://git@chromiumos-git/kernel.git
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Driver for Realtek RTS51xx USB card reader 1 /* Driver for Realtek RTS51xx USB card reader
2 * 2 *
3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. 3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the 6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any 7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version. 8 * later version.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, but 10 * This program is distributed in the hope that it will be useful, but
(...skipping 26 matching lines...) Expand all
37 #include <linux/usb_usual.h> 37 #include <linux/usb_usual.h>
38 38
39 #include "usb.h" 39 #include "usb.h"
40 #include "transport.h" 40 #include "transport.h"
41 #include "protocol.h" 41 #include "protocol.h"
42 #include "debug.h" 42 #include "debug.h"
43 43
44 MODULE_DESCRIPTION("Driver for Realtek USB Card Reader"); 44 MODULE_DESCRIPTION("Driver for Realtek USB Card Reader");
45 MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>"); 45 MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>");
46 MODULE_LICENSE("GPL"); 46 MODULE_LICENSE("GPL");
47 MODULE_VERSION("1.02");
47 48
48 static int ss_en = 1; 49 static int ss_en = 1;
49 module_param(ss_en, int, S_IRUGO | S_IWUSR); 50 module_param(ss_en, int, S_IRUGO | S_IWUSR);
50 MODULE_PARM_DESC(ss_en, "enable selective suspend"); 51 MODULE_PARM_DESC(ss_en, "enable selective suspend");
51 52
52 static int ss_delay = 20; 53 static int ss_delay = 50;
53 module_param(ss_delay, int, S_IRUGO | S_IWUSR); 54 module_param(ss_delay, int, S_IRUGO | S_IWUSR);
54 MODULE_PARM_DESC(ss_delay, "seconds to delay before entering selective suspend") ; 55 MODULE_PARM_DESC(ss_delay, "seconds to delay before entering selective suspend") ;
55 56
56 static int needs_remote_wakeup = 0; 57 static int needs_remote_wakeup = 0;
57 module_param(needs_remote_wakeup, int, S_IRUGO | S_IWUSR); 58 module_param(needs_remote_wakeup, int, S_IRUGO | S_IWUSR);
58 MODULE_PARM_DESC(needs_remote_wakeup, "ss state needs remote wakeup supported"); 59 MODULE_PARM_DESC(needs_remote_wakeup, "ss state needs remote wakeup supported");
59 60
60 static int auto_delink_en = 1; 61 static int auto_delink_en = 1;
61 module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); 62 module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
62 MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); 63 MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
63 64
64 enum CHIP_STAT» {STAT_INIT, STAT_IDLE, STAT_RUN, STAT_SS_PRE, STAT_SS}; 65 enum CHIP_STAT» {STAT_INIT, STAT_IDLE, STAT_RUN, STAT_SS_PRE, STAT_SS, STAT_SUSP END};
65 66
66 struct rts51x_status { 67 struct rts51x_status {
67 u16 vid; 68 u16 vid;
68 u16 pid; 69 u16 pid;
69 u8 cur_lun; 70 u8 cur_lun;
70 u8 card_type; 71 u8 card_type;
71 u8 total_lun; 72 u8 total_lun;
72 u16 fw_ver; 73 u16 fw_ver;
73 u8 phy_exist; 74 u8 phy_exist;
74 u8 multi_flag; 75 u8 multi_flag;
75 u8 multi_card; 76 u8 multi_card;
76 u8 log_exist; 77 u8 log_exist;
77 union { 78 union {
78 u8 detailed_type1; 79 u8 detailed_type1;
79 u8 detailed_type2; 80 u8 detailed_type2;
80 } detailed_type; 81 } detailed_type;
81 u8 function[2]; 82 u8 function[2];
82 }; 83 };
83 84
84 struct rts51x_chip { 85 struct rts51x_chip {
85 u16 vendor_id; 86 u16 vendor_id;
86 u16 product_id; 87 u16 product_id;
87 char max_lun; 88 char max_lun;
88 89
89 int ss_counter; 90 int ss_counter;
90 int idle_counter; 91 int idle_counter;
91 enum CHIP_STAT chip_stat; 92 enum CHIP_STAT chip_stat;
92 93
94 int resume_from_scsi;
95
93 struct rts51x_status *status; 96 struct rts51x_status *status;
94 int status_len; 97 int status_len;
95 u8 lun_ready; 98 u8 lun_ready;
96 99
97 u32 flag; 100 u32 flag;
98 101
99 struct task_struct *polling_thread; /* the polling thread */ 102 struct task_struct *polling_thread; /* the polling thread */
100 }; 103 };
101 104
102 // flag definition 105 // flag definition
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 { 418 {
416 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); 419 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
417 int retval; 420 int retval;
418 u8 buf[16]; 421 u8 buf[16];
419 422
420 retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len)); 423 retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len));
421 if (retval < 0) { 424 if (retval < 0) {
422 return -EIO; 425 return -EIO;
423 } 426 }
424 427
428 US_DEBUGP("chip->status_len = %d\n", chip->status_len);
429
425 chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1]; 430 chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1];
426 chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3]; 431 chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3];
427 chip->status[lun].cur_lun = buf[4]; 432 chip->status[lun].cur_lun = buf[4];
428 chip->status[lun].card_type = buf[5]; 433 chip->status[lun].card_type = buf[5];
429 chip->status[lun].total_lun = buf[6]; 434 chip->status[lun].total_lun = buf[6];
430 chip->status[lun].fw_ver = ((u16)buf[7] << 8) | buf[8]; 435 chip->status[lun].fw_ver = ((u16)buf[7] << 8) | buf[8];
431 chip->status[lun].phy_exist = buf[9]; 436 chip->status[lun].phy_exist = buf[9];
432 chip->status[lun].multi_flag = buf[10]; 437 chip->status[lun].multi_flag = buf[10];
433 chip->status[lun].multi_card = buf[11]; 438 chip->status[lun].multi_card = buf[11];
434 chip->status[lun].log_exist = buf[12]; 439 chip->status[lun].log_exist = buf[12];
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 } 653 }
649 } 654 }
650 } 655 }
651 656
652 return 0; 657 return 0;
653 } 658 }
654 659
655 static void rts51x_polling_func(struct us_data *us) 660 static void rts51x_polling_func(struct us_data *us)
656 { 661 {
657 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); 662 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
663
664 /* lock the device pointers */
665 mutex_lock(&(us->dev_mutex));
658 666
659 if (RTS51X_CHK_STAT(chip, STAT_SS) || RTS51X_CHK_STAT(chip, STAT_SS_PRE) ) { 667 if (RTS51X_CHK_STAT(chip, STAT_SS) || RTS51X_CHK_STAT(chip, STAT_SS_PRE) ) {
668 /* unlock the device pointers */
669 mutex_unlock(&(us->dev_mutex));
660 return; 670 return;
661 } 671 }
662 672
663 #ifdef CONFIG_PM 673 #ifdef CONFIG_PM
664 if (ss_en) { 674 if (ss_en) {
665 if (RTS51X_CHK_STAT(chip, STAT_IDLE)) { 675 if (RTS51X_CHK_STAT(chip, STAT_IDLE)) {
666 if (chip->ss_counter < (ss_delay * 1000 / POLLING_INTERV AL)) { 676 if (chip->ss_counter < (ss_delay * 1000 / POLLING_INTERV AL)) {
667 chip->ss_counter ++; 677 chip->ss_counter ++;
668 } else { 678 } else {
669 US_DEBUGP("Ready to enter SS state\n"); 679 US_DEBUGP("Ready to enter SS state\n");
670 RTS51X_SET_STAT(chip, STAT_SS_PRE); // Prepare SS state 680 RTS51X_SET_STAT(chip, STAT_SS_PRE); // Prepare SS state
681
682 /* unlock the device pointers */
683 mutex_unlock(&(us->dev_mutex));
671 usb_autopm_enable(us->pusb_intf); 684 usb_autopm_enable(us->pusb_intf);
672 return; 685 return;
673 } 686 }
674 } else { 687 } else {
675 chip->ss_counter = 0; 688 chip->ss_counter = 0;
676 } 689 }
677 } 690 }
678 #endif 691 #endif
679 692
680 if (chip->idle_counter < IDLE_MAX_COUNT) { 693 if (chip->idle_counter < IDLE_MAX_COUNT) {
681 chip->idle_counter ++; 694 chip->idle_counter ++;
682 } else { 695 } else {
683 if (!RTS51X_CHK_STAT(chip, STAT_IDLE)) { 696 if (!RTS51X_CHK_STAT(chip, STAT_IDLE)) {
684 US_DEBUGP("Idle state\n"); 697 US_DEBUGP("Idle state\n");
685 RTS51X_SET_STAT(chip, STAT_IDLE); 698 RTS51X_SET_STAT(chip, STAT_IDLE);
686 } 699 }
687 } 700 }
688 701
689 » switch (RTS51X_GET_STAT(chip)) { 702 » /* unlock the device pointers */
690 » case STAT_RUN: 703 » mutex_unlock(&(us->dev_mutex));
691 » » break;
692
693 » case STAT_IDLE:
694 » » break;
695
696 » default:
697 » » break;
698 » }
699 } 704 }
700 705
701 static int rts51x_polling_thread(void * __us) 706 static int rts51x_polling_thread(void * __us)
702 { 707 {
703 struct us_data *us = (struct us_data *)__us; 708 struct us_data *us = (struct us_data *)__us;
704 709
705 // Wait until SCSI scan finished 710 // Wait until SCSI scan finished
706 wait_timeout(10 * HZ); 711 wait_timeout(10 * HZ);
707 712
708 for(;;) { 713 for(;;) {
709 wait_timeout(POLLING_INTERVAL); 714 wait_timeout(POLLING_INTERVAL);
710 715
711 /* if the device has disconnected, we are free to exit */ 716 /* if the device has disconnected, we are free to exit */
712 if (kthread_should_stop()) { 717 if (kthread_should_stop()) {
713 printk(KERN_INFO "Stop polling thread!\n"); 718 printk(KERN_INFO "Stop polling thread!\n");
714 break; 719 break;
715 } 720 }
716 721
717 /* lock the device pointers */
718 mutex_lock(&(us->dev_mutex));
719
720 rts51x_polling_func(us); 722 rts51x_polling_func(us);
721 » » 723
722 » » /* unlock the device pointers */
723 » » mutex_unlock(&(us->dev_mutex));
724 } /* for (;;) */ 724 } /* for (;;) */
725 725
726 __set_current_state(TASK_RUNNING); 726 __set_current_state(TASK_RUNNING);
727 return 0; 727 return 0;
728 } 728 }
729 729
730 #ifdef CONFIG_PM 730 #ifdef CONFIG_PM
731 static void rts51x_handle_pm(struct us_data *us, int pwr_state) 731 int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
732 { 732 {
733 struct us_data *us = usb_get_intfdata(iface);
733 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); 734 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
735
736 US_DEBUGP("%s, message.event = 0x%x\n", __func__, message.event);
734 737
735 » US_DEBUGP("Handle pm state: %s\n", pwr_state ? "resume" : "suspend"); 738 » /* Wait until no command is running */
739 » mutex_lock(&us->dev_mutex);
740 »
741 » if (message.event == PM_EVENT_AUTO_SUSPEND) {
742 » » US_DEBUGP("Enter SS state");
743 » » chip->resume_from_scsi = 0;
744 » » RTS51X_SET_STAT(chip, STAT_SS);
745 » } else {
746 » » US_DEBUGP("Enter SUSPEND state");
747 » » RTS51X_SET_STAT(chip, STAT_SUSPEND);
748 » }
749 » (void)config_autodelink_before_power_down(us);
736 750
737 » if (pwr_state == US_RESUME) { 751 » /* When runtime PM is working, we'll set a flag to indicate
752 » * whether we should autoresume when a SCSI request arrives. */
753
754 » mutex_unlock(&us->dev_mutex);
755
756 » return 0;
757 }
758
759 int realtek_cr_resume(struct usb_interface *iface)
760 {
761 » struct us_data *us = usb_get_intfdata(iface);
762 » struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
763
764 » US_DEBUGP("%s\n", __func__);
765 »
766 » if (!RTS51X_CHK_STAT(chip, STAT_SS) || !chip->resume_from_scsi) {
767 » » mutex_lock(&us->dev_mutex);
768
738 if (GET_PM_USAGE_CNT(us) <= 0) { 769 if (GET_PM_USAGE_CNT(us) <= 0) {
739 // Remote wake up, increase pm_usage_cnt 770 // Remote wake up, increase pm_usage_cnt
740 US_DEBUGP("Incr pm_usage_cnt\n"); 771 US_DEBUGP("Incr pm_usage_cnt\n");
741 SET_PM_USAGE_CNT(us, 1); 772 SET_PM_USAGE_CNT(us, 1);
742 RTS51X_SET_STAT(chip, STAT_RUN);
743 } 773 }
744 » » 774
745 (void)config_autodelink_after_power_on(us); 775 (void)config_autodelink_after_power_on(us);
746 » } else { 776
747 » » if (RTS51X_CHK_STAT(chip, STAT_SS_PRE)) { 777 » » RTS51X_SET_STAT(chip, STAT_RUN);
748 » » » US_DEBUGP("Enter SS state"); 778 »
749 » » » RTS51X_SET_STAT(chip, STAT_SS); 779 » » mutex_unlock(&us->dev_mutex);
750 » » }
751 » »
752 » » (void)config_autodelink_before_power_down(us);
753 } 780 }
754 781
755 » US_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(us)); 782 » return 0;
756 } 783 }
757 #endif 784 #endif
758 785
759 static void realtek_cr_destructor(void *extra) 786 static void realtek_cr_destructor(void *extra)
760 { 787 {
761 struct rts51x_chip *chip = (struct rts51x_chip *)extra; 788 struct rts51x_chip *chip = (struct rts51x_chip *)extra;
762 789
763 if (!chip) 790 if (!chip)
764 return; 791 return;
765 792
(...skipping 13 matching lines...) Expand all
779 int size, i, retval; 806 int size, i, retval;
780 struct task_struct *th; 807 struct task_struct *th;
781 808
782 chip = kzalloc(sizeof(struct rts51x_chip), GFP_KERNEL); 809 chip = kzalloc(sizeof(struct rts51x_chip), GFP_KERNEL);
783 if (!chip) 810 if (!chip)
784 return -ENOMEM; 811 return -ENOMEM;
785 812
786 us->extra = chip; 813 us->extra = chip;
787 us->extra_destructor = realtek_cr_destructor; 814 us->extra_destructor = realtek_cr_destructor;
788 815
789 #ifdef CONFIG_PM
790 us->suspend_resume_hook = rts51x_handle_pm;
791 #endif
792
793 us->max_lun = chip->max_lun = rts51x_get_max_lun(us); 816 us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
794 817
795 US_DEBUGP("chip->max_lun = %d\n", chip->max_lun); 818 US_DEBUGP("chip->max_lun = %d\n", chip->max_lun);
796 819
797 size = (chip->max_lun + 1) * sizeof(struct rts51x_status); 820 size = (chip->max_lun + 1) * sizeof(struct rts51x_status);
798 chip->status = (struct rts51x_status *)kzalloc(size, GFP_KERNEL); 821 chip->status = (struct rts51x_status *)kzalloc(size, GFP_KERNEL);
799 if (!chip->status) { 822 if (!chip->status) {
800 goto INIT_FAIL; 823 goto INIT_FAIL;
801 } 824 }
802 825
803 for (i = 0; i <= (int)(chip->max_lun); i++) { 826 for (i = 0; i <= (int)(chip->max_lun); i++) {
804 retval = rts51x_check_status(us, (u8)i); 827 retval = rts51x_check_status(us, (u8)i);
805 if (retval < 0) { 828 if (retval < 0) {
806 goto INIT_FAIL; 829 goto INIT_FAIL;
807 } 830 }
808 } 831 }
809 832
810 if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) || 833 if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
811 CHECK_FW_VER(chip, 0x5901)) { 834 CHECK_FW_VER(chip, 0x5901)) {
812 SET_AUTO_DELINK(chip); 835 SET_AUTO_DELINK(chip);
813 } 836 }
814 if (STATUS_LEN(chip) == 16) { 837 if (STATUS_LEN(chip) == 16) {
815 if (SUPPORT_AUTO_DELINK(chip)) { 838 if (SUPPORT_AUTO_DELINK(chip)) {
816 SET_AUTO_DELINK(chip); 839 SET_AUTO_DELINK(chip);
817 } 840 }
818 } 841 }
819 842
843 US_DEBUGP("chip->flag = 0x%x\n", chip->flag);
844
820 (void)config_autodelink_after_power_on(us); 845 (void)config_autodelink_after_power_on(us);
821 846
822 #ifdef CONFIG_PM 847 #ifdef CONFIG_PM
823 if (ss_en) { 848 if (ss_en) {
824 us->pusb_intf->needs_remote_wakeup = needs_remote_wakeup; 849 us->pusb_intf->needs_remote_wakeup = needs_remote_wakeup;
825 SET_PM_USAGE_CNT(us, 1); 850 SET_PM_USAGE_CNT(us, 1);
826 US_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(us)); 851 US_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(us));
827 852
828 // Enable autosuspend 853 // Enable autosuspend
829 us->pusb_dev->autosuspend_disabled = 0; 854 us->pusb_dev->autosuspend_disabled = 0;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 } else { 913 } else {
889 result = USB_STOR_TRANSPORT_GOOD; 914 result = USB_STOR_TRANSPORT_GOOD;
890 } 915 }
891 916
892 goto FINISH; 917 goto FINISH;
893 } 918 }
894 } else { 919 } else {
895 if (RTS51X_CHK_STAT(chip, STAT_SS)) { 920 if (RTS51X_CHK_STAT(chip, STAT_SS)) {
896 // Wake up device 921 // Wake up device
897 US_DEBUGP("Try to wake up device\n"); 922 US_DEBUGP("Try to wake up device\n");
898 » » » » mutex_unlock(&(us->dev_mutex)); 923 » » » » chip->resume_from_scsi = 1;
899 usb_autopm_disable(us->pusb_intf); 924 usb_autopm_disable(us->pusb_intf);
900 wait_timeout(3000); 925 wait_timeout(3000);
901 » » » » mutex_lock(&(us->dev_mutex)); 926 » » » »
927 » » » » (void)config_autodelink_after_power_on(us);
902 rts51x_reset_card(us, lun); 928 rts51x_reset_card(us, lun);
903 } 929 }
904 RTS51X_SET_STAT(chip, STAT_RUN); 930 RTS51X_SET_STAT(chip, STAT_RUN);
905 } 931 }
906 } 932 }
907 else 933 else
908 #endif 934 #endif
909 { 935 {
910 RTS51X_SET_STAT(chip, STAT_RUN); 936 RTS51X_SET_STAT(chip, STAT_RUN);
911 } 937 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 us->max_lun = 0; 969 us->max_lun = 0;
944 970
945 result = usb_stor_probe2(us); 971 result = usb_stor_probe2(us);
946 return result; 972 return result;
947 } 973 }
948 974
949 static struct usb_driver realtek_cr_driver = { 975 static struct usb_driver realtek_cr_driver = {
950 .name = "ums-realtek", 976 .name = "ums-realtek",
951 .probe = realtek_cr_probe, 977 .probe = realtek_cr_probe,
952 .disconnect = usb_stor_disconnect, 978 .disconnect = usb_stor_disconnect,
953 » .suspend =» usb_stor_suspend, 979 » .suspend =» realtek_cr_suspend,
954 » .resume =» usb_stor_resume, 980 » .resume =» realtek_cr_resume,
955 .reset_resume = usb_stor_reset_resume, 981 .reset_resume = usb_stor_reset_resume,
956 .pre_reset = usb_stor_pre_reset, 982 .pre_reset = usb_stor_pre_reset,
957 .post_reset = usb_stor_post_reset, 983 .post_reset = usb_stor_post_reset,
958 .id_table = realtek_cr_ids, 984 .id_table = realtek_cr_ids,
959 .soft_unbind = 1, 985 .soft_unbind = 1,
960 }; 986 };
961 987
962 static int __init realtek_cr_init(void) 988 static int __init realtek_cr_init(void)
963 { 989 {
964 return usb_register(&realtek_cr_driver); 990 return usb_register(&realtek_cr_driver);
965 } 991 }
966 992
967 static void __exit realtek_cr_exit(void) 993 static void __exit realtek_cr_exit(void)
968 { 994 {
969 usb_deregister(&realtek_cr_driver); 995 usb_deregister(&realtek_cr_driver);
970 } 996 }
971 997
972 module_init(realtek_cr_init); 998 module_init(realtek_cr_init);
973 module_exit(realtek_cr_exit); 999 module_exit(realtek_cr_exit);
974 1000
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698