diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2010-12-26 12:22:29 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-01-04 14:35:13 -0500 |
commit | 97e2c40269e168df986daf94af1c62e07d4fc599 (patch) | |
tree | 925c80b75d11ae33e2da9906a4507187decacc8c | |
parent | 3b386510f49ff5c6e6ac1001da4f3c922ae7de3f (diff) |
carl9170: fix usb pm suspend->resume woes
This patch revamps some common code-paths which are
shared between (re-)initialization and suspend/resume
subroutines. It also adds some helpful comments
about quirks and associated difficulties.
It's quite big, but it should fix #25382:
<https://bugzilla.kernel.org/show_bug.cgi?id=25382>
And hopefully the code is robust enough to deal with
all possible suspend/resume scenarios without requiring
the user to do any sort of manual and possibly
dangerous work.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/carl9170/usb.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index 2d947a30d29e..537732e5964f 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c | |||
@@ -834,7 +834,7 @@ static int carl9170_usb_load_firmware(struct ar9170 *ar) | |||
834 | if (err) | 834 | if (err) |
835 | goto err_out; | 835 | goto err_out; |
836 | 836 | ||
837 | /* firmware restarts cmd counter */ | 837 | /* now, start the command response counter */ |
838 | ar->cmd_seq = -1; | 838 | ar->cmd_seq = -1; |
839 | 839 | ||
840 | return 0; | 840 | return 0; |
@@ -851,7 +851,12 @@ int carl9170_usb_restart(struct ar9170 *ar) | |||
851 | if (ar->intf->condition != USB_INTERFACE_BOUND) | 851 | if (ar->intf->condition != USB_INTERFACE_BOUND) |
852 | return 0; | 852 | return 0; |
853 | 853 | ||
854 | /* Disable command response sequence counter. */ | 854 | /* |
855 | * Disable the command response sequence counter check. | ||
856 | * We already know that the device/firmware is in a bad state. | ||
857 | * So, no extra points are awarded to anyone who reminds the | ||
858 | * driver about that. | ||
859 | */ | ||
855 | ar->cmd_seq = -2; | 860 | ar->cmd_seq = -2; |
856 | 861 | ||
857 | err = carl9170_reboot(ar); | 862 | err = carl9170_reboot(ar); |
@@ -903,6 +908,15 @@ static int carl9170_usb_init_device(struct ar9170 *ar) | |||
903 | { | 908 | { |
904 | int err; | 909 | int err; |
905 | 910 | ||
911 | /* | ||
912 | * The carl9170 firmware let's the driver know when it's | ||
913 | * ready for action. But we have to be prepared to gracefully | ||
914 | * handle all spurious [flushed] messages after each (re-)boot. | ||
915 | * Thus the command response counter remains disabled until it | ||
916 | * can be safely synchronized. | ||
917 | */ | ||
918 | ar->cmd_seq = -2; | ||
919 | |||
906 | err = carl9170_usb_send_rx_irq_urb(ar); | 920 | err = carl9170_usb_send_rx_irq_urb(ar); |
907 | if (err) | 921 | if (err) |
908 | goto err_out; | 922 | goto err_out; |
@@ -911,14 +925,21 @@ static int carl9170_usb_init_device(struct ar9170 *ar) | |||
911 | if (err) | 925 | if (err) |
912 | goto err_unrx; | 926 | goto err_unrx; |
913 | 927 | ||
928 | err = carl9170_usb_open(ar); | ||
929 | if (err) | ||
930 | goto err_unrx; | ||
931 | |||
914 | mutex_lock(&ar->mutex); | 932 | mutex_lock(&ar->mutex); |
915 | err = carl9170_usb_load_firmware(ar); | 933 | err = carl9170_usb_load_firmware(ar); |
916 | mutex_unlock(&ar->mutex); | 934 | mutex_unlock(&ar->mutex); |
917 | if (err) | 935 | if (err) |
918 | goto err_unrx; | 936 | goto err_stop; |
919 | 937 | ||
920 | return 0; | 938 | return 0; |
921 | 939 | ||
940 | err_stop: | ||
941 | carl9170_usb_stop(ar); | ||
942 | |||
922 | err_unrx: | 943 | err_unrx: |
923 | carl9170_usb_cancel_urbs(ar); | 944 | carl9170_usb_cancel_urbs(ar); |
924 | 945 | ||
@@ -964,10 +985,6 @@ static void carl9170_usb_firmware_finish(struct ar9170 *ar) | |||
964 | if (err) | 985 | if (err) |
965 | goto err_freefw; | 986 | goto err_freefw; |
966 | 987 | ||
967 | err = carl9170_usb_open(ar); | ||
968 | if (err) | ||
969 | goto err_unrx; | ||
970 | |||
971 | err = carl9170_register(ar); | 988 | err = carl9170_register(ar); |
972 | 989 | ||
973 | carl9170_usb_stop(ar); | 990 | carl9170_usb_stop(ar); |
@@ -1043,7 +1060,6 @@ static int carl9170_usb_probe(struct usb_interface *intf, | |||
1043 | atomic_set(&ar->rx_work_urbs, 0); | 1060 | atomic_set(&ar->rx_work_urbs, 0); |
1044 | atomic_set(&ar->rx_anch_urbs, 0); | 1061 | atomic_set(&ar->rx_anch_urbs, 0); |
1045 | atomic_set(&ar->rx_pool_urbs, 0); | 1062 | atomic_set(&ar->rx_pool_urbs, 0); |
1046 | ar->cmd_seq = -2; | ||
1047 | 1063 | ||
1048 | usb_get_dev(ar->udev); | 1064 | usb_get_dev(ar->udev); |
1049 | 1065 | ||
@@ -1090,10 +1106,6 @@ static int carl9170_usb_suspend(struct usb_interface *intf, | |||
1090 | 1106 | ||
1091 | carl9170_usb_cancel_urbs(ar); | 1107 | carl9170_usb_cancel_urbs(ar); |
1092 | 1108 | ||
1093 | /* | ||
1094 | * firmware automatically reboots for usb suspend. | ||
1095 | */ | ||
1096 | |||
1097 | return 0; | 1109 | return 0; |
1098 | } | 1110 | } |
1099 | 1111 | ||
@@ -1106,12 +1118,20 @@ static int carl9170_usb_resume(struct usb_interface *intf) | |||
1106 | return -ENODEV; | 1118 | return -ENODEV; |
1107 | 1119 | ||
1108 | usb_unpoison_anchored_urbs(&ar->rx_anch); | 1120 | usb_unpoison_anchored_urbs(&ar->rx_anch); |
1121 | carl9170_set_state(ar, CARL9170_STOPPED); | ||
1109 | 1122 | ||
1110 | err = carl9170_usb_init_device(ar); | 1123 | /* |
1111 | if (err) | 1124 | * The USB documentation demands that [for suspend] all traffic |
1112 | goto err_unrx; | 1125 | * to and from the device has to stop. This would be fine, but |
1126 | * there's a catch: the device[usb phy] does not come back. | ||
1127 | * | ||
1128 | * Upon resume the firmware will "kill" itself and the | ||
1129 | * boot-code sorts out the magic voodoo. | ||
1130 | * Not very nice, but there's not much what could go wrong. | ||
1131 | */ | ||
1132 | msleep(1100); | ||
1113 | 1133 | ||
1114 | err = carl9170_usb_open(ar); | 1134 | err = carl9170_usb_init_device(ar); |
1115 | if (err) | 1135 | if (err) |
1116 | goto err_unrx; | 1136 | goto err_unrx; |
1117 | 1137 | ||
@@ -1133,6 +1153,7 @@ static struct usb_driver carl9170_driver = { | |||
1133 | #ifdef CONFIG_PM | 1153 | #ifdef CONFIG_PM |
1134 | .suspend = carl9170_usb_suspend, | 1154 | .suspend = carl9170_usb_suspend, |
1135 | .resume = carl9170_usb_resume, | 1155 | .resume = carl9170_usb_resume, |
1156 | .reset_resume = carl9170_usb_resume, | ||
1136 | #endif /* CONFIG_PM */ | 1157 | #endif /* CONFIG_PM */ |
1137 | }; | 1158 | }; |
1138 | 1159 | ||