aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2012-04-16 18:53:55 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-17 14:57:14 -0400
commitce84bb69f50e6f6cfeabc9b965365290f4184417 (patch)
tree39a077b8bdd5082cda8c8addec4ad229bb4568cf /drivers/net/wireless
parent66d647efe5e845c77f745478480c5e96218b7f3d (diff)
libertas USB: convert to asynchronous firmware loading
Signed-off-by: Daniel Drake <dsd@laptop.org> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/libertas/if_usb.c102
1 files changed, 43 insertions, 59 deletions
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index f29471b80603..75403e6e3990 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -41,6 +41,16 @@ enum {
41 MODEL_8682 = 0x2 41 MODEL_8682 = 0x2
42}; 42};
43 43
44/* table of firmware file names */
45static const struct lbs_fw_table fw_table[] = {
46 { MODEL_8388, "libertas/usb8388_olpc.bin", NULL },
47 { MODEL_8388, "libertas/usb8388_v9.bin", NULL },
48 { MODEL_8388, "libertas/usb8388_v5.bin", NULL },
49 { MODEL_8388, "libertas/usb8388.bin", NULL },
50 { MODEL_8388, "usb8388.bin", NULL },
51 { MODEL_8682, "libertas/usb8682.bin", NULL }
52};
53
44static struct usb_device_id if_usb_table[] = { 54static struct usb_device_id if_usb_table[] = {
45 /* Enter the device signature inside */ 55 /* Enter the device signature inside */
46 { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, 56 { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
@@ -52,7 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
52 62
53static void if_usb_receive(struct urb *urb); 63static void if_usb_receive(struct urb *urb);
54static void if_usb_receive_fwload(struct urb *urb); 64static void if_usb_receive_fwload(struct urb *urb);
55static int if_usb_prog_firmware(struct if_usb_card *cardp); 65static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
66 const struct firmware *fw,
67 const struct firmware *unused);
56static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, 68static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
57 uint8_t *payload, uint16_t nb); 69 uint8_t *payload, uint16_t nb);
58static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, 70static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
@@ -187,6 +199,7 @@ static int if_usb_probe(struct usb_interface *intf,
187 struct usb_endpoint_descriptor *endpoint; 199 struct usb_endpoint_descriptor *endpoint;
188 struct lbs_private *priv; 200 struct lbs_private *priv;
189 struct if_usb_card *cardp; 201 struct if_usb_card *cardp;
202 int r = -ENOMEM;
190 int i; 203 int i;
191 204
192 udev = interface_to_usbdev(intf); 205 udev = interface_to_usbdev(intf);
@@ -244,17 +257,10 @@ static int if_usb_probe(struct usb_interface *intf,
244 goto dealloc; 257 goto dealloc;
245 } 258 }
246 259
247 /* Upload firmware */
248 if (if_usb_prog_firmware(cardp)) {
249 lbs_deb_usbd(&udev->dev, "FW upload failed\n");
250 goto err_prog_firmware;
251 }
252
253 if (!(priv = lbs_add_card(cardp, &intf->dev))) 260 if (!(priv = lbs_add_card(cardp, &intf->dev)))
254 goto err_prog_firmware; 261 goto err_add_card;
255 262
256 cardp->priv = priv; 263 cardp->priv = priv;
257 cardp->priv->fw_ready = 1;
258 264
259 priv->hw_host_to_card = if_usb_host_to_card; 265 priv->hw_host_to_card = if_usb_host_to_card;
260 priv->enter_deep_sleep = NULL; 266 priv->enter_deep_sleep = NULL;
@@ -267,34 +273,25 @@ static int if_usb_probe(struct usb_interface *intf,
267 273
268 cardp->boot2_version = udev->descriptor.bcdDevice; 274 cardp->boot2_version = udev->descriptor.bcdDevice;
269 275
270 if_usb_submit_rx_urb(cardp);
271
272 if (lbs_start_card(priv))
273 goto err_start_card;
274
275 if_usb_setup_firmware(priv);
276
277 usb_get_dev(udev); 276 usb_get_dev(udev);
278 usb_set_intfdata(intf, cardp); 277 usb_set_intfdata(intf, cardp);
279 278
280 /* 279 r = lbs_get_firmware_async(priv, &udev->dev, cardp->model,
281 * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. 280 fw_table, if_usb_prog_firmware);
282 */ 281 if (r)
283 priv->wol_criteria = EHS_REMOVE_WAKEUP; 282 goto err_get_fw;
284 if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
285 priv->ehs_remove_supported = false;
286 283
287 return 0; 284 return 0;
288 285
289err_start_card: 286err_get_fw:
290 lbs_remove_card(priv); 287 lbs_remove_card(priv);
291err_prog_firmware: 288err_add_card:
292 if_usb_reset_device(cardp); 289 if_usb_reset_device(cardp);
293dealloc: 290dealloc:
294 if_usb_free(cardp); 291 if_usb_free(cardp);
295 292
296error: 293error:
297 return -ENOMEM; 294 return r;
298} 295}
299 296
300/** 297/**
@@ -829,49 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
829 return ret; 826 return ret;
830} 827}
831 828
832/* table of firmware file names */ 829static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
833static const struct { 830 const struct firmware *fw,
834 u32 model; 831 const struct firmware *unused)
835 const char *fwname;
836} fw_table[] = {
837 { MODEL_8388, "libertas/usb8388_olpc.bin" },
838 { MODEL_8388, "libertas/usb8388_v9.bin" },
839 { MODEL_8388, "libertas/usb8388_v5.bin" },
840 { MODEL_8388, "libertas/usb8388.bin" },
841 { MODEL_8388, "usb8388.bin" },
842 { MODEL_8682, "libertas/usb8682.bin" }
843};
844
845static int get_fw(struct if_usb_card *cardp)
846{
847 int i;
848
849 /* Otherwise search for firmware to use */
850 for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
851 if (fw_table[i].model != cardp->model)
852 continue;
853 if (request_firmware(&cardp->fw, fw_table[i].fwname,
854 &cardp->udev->dev) == 0)
855 return 0;
856 }
857
858 return -ENOENT;
859}
860
861static int if_usb_prog_firmware(struct if_usb_card *cardp)
862{ 832{
833 struct if_usb_card *cardp = priv->card;
863 int i = 0; 834 int i = 0;
864 static int reset_count = 10; 835 static int reset_count = 10;
865 int ret = 0;
866 836
867 lbs_deb_enter(LBS_DEB_USB); 837 lbs_deb_enter(LBS_DEB_USB);
868 838
869 ret = get_fw(cardp);
870 if (ret) { 839 if (ret) {
871 pr_err("failed to find firmware (%d)\n", ret); 840 pr_err("failed to find firmware (%d)\n", ret);
872 goto done; 841 goto done;
873 } 842 }
874 843
844 cardp->fw = fw;
875 if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { 845 if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
876 ret = -EINVAL; 846 ret = -EINVAL;
877 goto release_fw; 847 goto release_fw;
@@ -954,13 +924,27 @@ restart:
954 goto release_fw; 924 goto release_fw;
955 } 925 }
956 926
927 cardp->priv->fw_ready = 1;
928 if_usb_submit_rx_urb(cardp);
929
930 if (lbs_start_card(priv))
931 goto release_fw;
932
933 if_usb_setup_firmware(priv);
934
935 /*
936 * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
937 */
938 priv->wol_criteria = EHS_REMOVE_WAKEUP;
939 if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
940 priv->ehs_remove_supported = false;
941
957 release_fw: 942 release_fw:
958 release_firmware(cardp->fw); 943 release_firmware(cardp->fw);
959 cardp->fw = NULL; 944 cardp->fw = NULL;
960 945
961 done: 946 done:
962 lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); 947 lbs_deb_leave(LBS_DEB_USB);
963 return ret;
964} 948}
965 949
966 950