diff options
author | Daniel Drake <dsd@laptop.org> | 2012-04-16 18:53:55 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-17 14:57:14 -0400 |
commit | ce84bb69f50e6f6cfeabc9b965365290f4184417 (patch) | |
tree | 39a077b8bdd5082cda8c8addec4ad229bb4568cf /drivers/net/wireless | |
parent | 66d647efe5e845c77f745478480c5e96218b7f3d (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.c | 102 |
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 */ | ||
45 | static 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 | |||
44 | static struct usb_device_id if_usb_table[] = { | 54 | static 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 | ||
53 | static void if_usb_receive(struct urb *urb); | 63 | static void if_usb_receive(struct urb *urb); |
54 | static void if_usb_receive_fwload(struct urb *urb); | 64 | static void if_usb_receive_fwload(struct urb *urb); |
55 | static int if_usb_prog_firmware(struct if_usb_card *cardp); | 65 | static void if_usb_prog_firmware(struct lbs_private *priv, int ret, |
66 | const struct firmware *fw, | ||
67 | const struct firmware *unused); | ||
56 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | 68 | static 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); |
58 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | 70 | static 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 | ||
289 | err_start_card: | 286 | err_get_fw: |
290 | lbs_remove_card(priv); | 287 | lbs_remove_card(priv); |
291 | err_prog_firmware: | 288 | err_add_card: |
292 | if_usb_reset_device(cardp); | 289 | if_usb_reset_device(cardp); |
293 | dealloc: | 290 | dealloc: |
294 | if_usb_free(cardp); | 291 | if_usb_free(cardp); |
295 | 292 | ||
296 | error: | 293 | error: |
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 */ | 829 | static void if_usb_prog_firmware(struct lbs_private *priv, int ret, |
833 | static 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 | |||
845 | static 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 | |||
861 | static 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 | ||