aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2012-01-30 03:47:18 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-01-30 15:48:42 -0500
commit0ed7b93e307fd02188a33b80897069d3acc76485 (patch)
tree889bd982d2cd0b00f24723c70ebedd5754e3ef69
parented072f9e80f02e5ae4150ad5a605fc3906e9fbc7 (diff)
ath9k_htc: Load firmware asynchronously
This patch modifies ath9k_htc to load the needed firmware in an asynchronous manner, fixing timeouts that were introduced with the new udev changes. Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c154
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.h3
2 files changed, 101 insertions, 56 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 77c8ded8de57..f317515d8bf3 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -968,8 +968,7 @@ static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
968 ath9k_hif_usb_dealloc_rx_urbs(hif_dev); 968 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
969} 969}
970 970
971static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev, 971static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
972 u32 drv_info)
973{ 972{
974 int transfer, err; 973 int transfer, err;
975 const void *data = hif_dev->firmware->data; 974 const void *data = hif_dev->firmware->data;
@@ -1000,7 +999,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
1000 } 999 }
1001 kfree(buf); 1000 kfree(buf);
1002 1001
1003 if (IS_AR7010_DEVICE(drv_info)) 1002 if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info))
1004 firm_offset = AR7010_FIRMWARE_TEXT; 1003 firm_offset = AR7010_FIRMWARE_TEXT;
1005 else 1004 else
1006 firm_offset = AR9271_FIRMWARE_TEXT; 1005 firm_offset = AR9271_FIRMWARE_TEXT;
@@ -1021,28 +1020,18 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
1021 return 0; 1020 return 0;
1022} 1021}
1023 1022
1024static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info) 1023static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
1025{ 1024{
1026 int ret, idx;
1027 struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; 1025 struct usb_host_interface *alt = &hif_dev->interface->altsetting[0];
1028 struct usb_endpoint_descriptor *endp; 1026 struct usb_endpoint_descriptor *endp;
1027 int ret, idx;
1029 1028
1030 /* Request firmware */ 1029 ret = ath9k_hif_usb_download_fw(hif_dev);
1031 ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name,
1032 &hif_dev->udev->dev);
1033 if (ret) {
1034 dev_err(&hif_dev->udev->dev,
1035 "ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name);
1036 goto err_fw_req;
1037 }
1038
1039 /* Download firmware */
1040 ret = ath9k_hif_usb_download_fw(hif_dev, drv_info);
1041 if (ret) { 1030 if (ret) {
1042 dev_err(&hif_dev->udev->dev, 1031 dev_err(&hif_dev->udev->dev,
1043 "ath9k_htc: Firmware - %s download failed\n", 1032 "ath9k_htc: Firmware - %s download failed\n",
1044 hif_dev->fw_name); 1033 hif_dev->fw_name);
1045 goto err_fw_download; 1034 return ret;
1046 } 1035 }
1047 1036
1048 /* On downloading the firmware to the target, the USB descriptor of EP4 1037 /* On downloading the firmware to the target, the USB descriptor of EP4
@@ -1064,23 +1053,84 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info)
1064 if (ret) { 1053 if (ret) {
1065 dev_err(&hif_dev->udev->dev, 1054 dev_err(&hif_dev->udev->dev,
1066 "ath9k_htc: Unable to allocate URBs\n"); 1055 "ath9k_htc: Unable to allocate URBs\n");
1067 goto err_fw_download; 1056 return ret;
1068 } 1057 }
1069 1058
1070 return 0; 1059 return 0;
1071
1072err_fw_download:
1073 release_firmware(hif_dev->firmware);
1074err_fw_req:
1075 hif_dev->firmware = NULL;
1076 return ret;
1077} 1060}
1078 1061
1079static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) 1062static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
1080{ 1063{
1081 ath9k_hif_usb_dealloc_urbs(hif_dev); 1064 ath9k_hif_usb_dealloc_urbs(hif_dev);
1082 if (hif_dev->firmware) 1065}
1083 release_firmware(hif_dev->firmware); 1066
1067/*
1068 * If initialization fails or the FW cannot be retrieved,
1069 * detach the device.
1070 */
1071static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev)
1072{
1073 struct device *parent = hif_dev->udev->dev.parent;
1074
1075 complete(&hif_dev->fw_done);
1076
1077 if (parent)
1078 device_lock(parent);
1079
1080 device_release_driver(&hif_dev->udev->dev);
1081
1082 if (parent)
1083 device_unlock(parent);
1084}
1085
1086static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context)
1087{
1088 struct hif_device_usb *hif_dev = context;
1089 int ret;
1090
1091 if (!fw) {
1092 dev_err(&hif_dev->udev->dev,
1093 "ath9k_htc: Failed to get firmware %s\n",
1094 hif_dev->fw_name);
1095 goto err_fw;
1096 }
1097
1098 hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
1099 &hif_dev->udev->dev);
1100 if (hif_dev->htc_handle == NULL) {
1101 goto err_fw;
1102 }
1103
1104 hif_dev->firmware = fw;
1105
1106 /* Proceed with initialization */
1107
1108 ret = ath9k_hif_usb_dev_init(hif_dev);
1109 if (ret)
1110 goto err_dev_init;
1111
1112 ret = ath9k_htc_hw_init(hif_dev->htc_handle,
1113 &hif_dev->interface->dev,
1114 hif_dev->usb_device_id->idProduct,
1115 hif_dev->udev->product,
1116 hif_dev->usb_device_id->driver_info);
1117 if (ret) {
1118 ret = -EINVAL;
1119 goto err_htc_hw_init;
1120 }
1121
1122 complete(&hif_dev->fw_done);
1123
1124 return;
1125
1126err_htc_hw_init:
1127 ath9k_hif_usb_dev_deinit(hif_dev);
1128err_dev_init:
1129 ath9k_htc_hw_free(hif_dev->htc_handle);
1130 release_firmware(fw);
1131 hif_dev->firmware = NULL;
1132err_fw:
1133 ath9k_hif_usb_firmware_fail(hif_dev);
1084} 1134}
1085 1135
1086/* 1136/*
@@ -1155,20 +1205,16 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
1155 } 1205 }
1156 1206
1157 usb_get_dev(udev); 1207 usb_get_dev(udev);
1208
1158 hif_dev->udev = udev; 1209 hif_dev->udev = udev;
1159 hif_dev->interface = interface; 1210 hif_dev->interface = interface;
1160 hif_dev->device_id = id->idProduct; 1211 hif_dev->usb_device_id = id;
1161#ifdef CONFIG_PM 1212#ifdef CONFIG_PM
1162 udev->reset_resume = 1; 1213 udev->reset_resume = 1;
1163#endif 1214#endif
1164 usb_set_intfdata(interface, hif_dev); 1215 usb_set_intfdata(interface, hif_dev);
1165 1216
1166 hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb, 1217 init_completion(&hif_dev->fw_done);
1167 &hif_dev->udev->dev);
1168 if (hif_dev->htc_handle == NULL) {
1169 ret = -ENOMEM;
1170 goto err_htc_hw_alloc;
1171 }
1172 1218
1173 /* Find out which firmware to load */ 1219 /* Find out which firmware to load */
1174 1220
@@ -1177,29 +1223,22 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
1177 else 1223 else
1178 hif_dev->fw_name = FIRMWARE_AR9271; 1224 hif_dev->fw_name = FIRMWARE_AR9271;
1179 1225
1180 ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info); 1226 ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
1181 if (ret) { 1227 &hif_dev->udev->dev, GFP_KERNEL,
1182 ret = -EINVAL; 1228 hif_dev, ath9k_hif_usb_firmware_cb);
1183 goto err_hif_init_usb;
1184 }
1185
1186 ret = ath9k_htc_hw_init(hif_dev->htc_handle,
1187 &interface->dev, hif_dev->device_id,
1188 hif_dev->udev->product, id->driver_info);
1189 if (ret) { 1229 if (ret) {
1190 ret = -EINVAL; 1230 dev_err(&hif_dev->udev->dev,
1191 goto err_htc_hw_init; 1231 "ath9k_htc: Async request for firmware %s failed\n",
1232 hif_dev->fw_name);
1233 goto err_fw_req;
1192 } 1234 }
1193 1235
1194 dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n"); 1236 dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
1237 hif_dev->fw_name);
1195 1238
1196 return 0; 1239 return 0;
1197 1240
1198err_htc_hw_init: 1241err_fw_req:
1199 ath9k_hif_usb_dev_deinit(hif_dev);
1200err_hif_init_usb:
1201 ath9k_htc_hw_free(hif_dev->htc_handle);
1202err_htc_hw_alloc:
1203 usb_set_intfdata(interface, NULL); 1242 usb_set_intfdata(interface, NULL);
1204 kfree(hif_dev); 1243 kfree(hif_dev);
1205 usb_put_dev(udev); 1244 usb_put_dev(udev);
@@ -1234,9 +1273,15 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
1234 if (!hif_dev) 1273 if (!hif_dev)
1235 return; 1274 return;
1236 1275
1237 ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); 1276 wait_for_completion(&hif_dev->fw_done);
1238 ath9k_htc_hw_free(hif_dev->htc_handle); 1277
1239 ath9k_hif_usb_dev_deinit(hif_dev); 1278 if (hif_dev->firmware) {
1279 ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
1280 ath9k_htc_hw_free(hif_dev->htc_handle);
1281 ath9k_hif_usb_dev_deinit(hif_dev);
1282 release_firmware(hif_dev->firmware);
1283 }
1284
1240 usb_set_intfdata(interface, NULL); 1285 usb_set_intfdata(interface, NULL);
1241 1286
1242 if (!unplugged && (hif_dev->flags & HIF_USB_START)) 1287 if (!unplugged && (hif_dev->flags & HIF_USB_START))
@@ -1276,8 +1321,7 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface)
1276 return ret; 1321 return ret;
1277 1322
1278 if (hif_dev->firmware) { 1323 if (hif_dev->firmware) {
1279 ret = ath9k_hif_usb_download_fw(hif_dev, 1324 ret = ath9k_hif_usb_download_fw(hif_dev);
1280 htc_handle->drv_priv->ah->hw_version.usbdev);
1281 if (ret) 1325 if (ret)
1282 goto fail_resume; 1326 goto fail_resume;
1283 } else { 1327 } else {
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h
index 794f63094e5d..487ff658b4c1 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -87,10 +87,11 @@ struct cmd_buf {
87#define HIF_USB_START BIT(0) 87#define HIF_USB_START BIT(0)
88 88
89struct hif_device_usb { 89struct hif_device_usb {
90 u16 device_id;
91 struct usb_device *udev; 90 struct usb_device *udev;
92 struct usb_interface *interface; 91 struct usb_interface *interface;
92 const struct usb_device_id *usb_device_id;
93 const struct firmware *firmware; 93 const struct firmware *firmware;
94 struct completion fw_done;
94 struct htc_target *htc_handle; 95 struct htc_target *htc_handle;
95 struct hif_usb_tx tx; 96 struct hif_usb_tx tx;
96 struct usb_anchor regout_submitted; 97 struct usb_anchor regout_submitted;