aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-12-26 12:22:29 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-04 14:35:13 -0500
commit97e2c40269e168df986daf94af1c62e07d4fc599 (patch)
tree925c80b75d11ae33e2da9906a4507187decacc8c
parent3b386510f49ff5c6e6ac1001da4f3c922ae7de3f (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.c53
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
940err_stop:
941 carl9170_usb_stop(ar);
942
922err_unrx: 943err_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