Commit ce84bb69 authored by Daniel Drake's avatar Daniel Drake Committed by John W. Linville

libertas USB: convert to asynchronous firmware loading

Signed-off-by: default avatarDaniel Drake <dsd@laptop.org>
Acked-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 66d647ef
...@@ -41,6 +41,16 @@ enum { ...@@ -41,6 +41,16 @@ enum {
MODEL_8682 = 0x2 MODEL_8682 = 0x2
}; };
/* table of firmware file names */
static const struct lbs_fw_table fw_table[] = {
{ MODEL_8388, "libertas/usb8388_olpc.bin", NULL },
{ MODEL_8388, "libertas/usb8388_v9.bin", NULL },
{ MODEL_8388, "libertas/usb8388_v5.bin", NULL },
{ MODEL_8388, "libertas/usb8388.bin", NULL },
{ MODEL_8388, "usb8388.bin", NULL },
{ MODEL_8682, "libertas/usb8682.bin", NULL }
};
static struct usb_device_id if_usb_table[] = { static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */ /* Enter the device signature inside */
{ USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
...@@ -52,7 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); ...@@ -52,7 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb); static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb); static void if_usb_receive_fwload(struct urb *urb);
static int if_usb_prog_firmware(struct if_usb_card *cardp); static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
const struct firmware *fw,
const struct firmware *unused);
static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
uint8_t *payload, uint16_t nb); uint8_t *payload, uint16_t nb);
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, 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,6 +199,7 @@ static int if_usb_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
struct lbs_private *priv; struct lbs_private *priv;
struct if_usb_card *cardp; struct if_usb_card *cardp;
int r = -ENOMEM;
int i; int i;
udev = interface_to_usbdev(intf); udev = interface_to_usbdev(intf);
...@@ -244,17 +257,10 @@ static int if_usb_probe(struct usb_interface *intf, ...@@ -244,17 +257,10 @@ static int if_usb_probe(struct usb_interface *intf,
goto dealloc; goto dealloc;
} }
/* Upload firmware */
if (if_usb_prog_firmware(cardp)) {
lbs_deb_usbd(&udev->dev, "FW upload failed\n");
goto err_prog_firmware;
}
if (!(priv = lbs_add_card(cardp, &intf->dev))) if (!(priv = lbs_add_card(cardp, &intf->dev)))
goto err_prog_firmware; goto err_add_card;
cardp->priv = priv; cardp->priv = priv;
cardp->priv->fw_ready = 1;
priv->hw_host_to_card = if_usb_host_to_card; priv->hw_host_to_card = if_usb_host_to_card;
priv->enter_deep_sleep = NULL; priv->enter_deep_sleep = NULL;
...@@ -267,34 +273,25 @@ static int if_usb_probe(struct usb_interface *intf, ...@@ -267,34 +273,25 @@ static int if_usb_probe(struct usb_interface *intf,
cardp->boot2_version = udev->descriptor.bcdDevice; cardp->boot2_version = udev->descriptor.bcdDevice;
if_usb_submit_rx_urb(cardp);
if (lbs_start_card(priv))
goto err_start_card;
if_usb_setup_firmware(priv);
usb_get_dev(udev); usb_get_dev(udev);
usb_set_intfdata(intf, cardp); usb_set_intfdata(intf, cardp);
/* r = lbs_get_firmware_async(priv, &udev->dev, cardp->model,
* EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. fw_table, if_usb_prog_firmware);
*/ if (r)
priv->wol_criteria = EHS_REMOVE_WAKEUP; goto err_get_fw;
if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
priv->ehs_remove_supported = false;
return 0; return 0;
err_start_card: err_get_fw:
lbs_remove_card(priv); lbs_remove_card(priv);
err_prog_firmware: err_add_card:
if_usb_reset_device(cardp); if_usb_reset_device(cardp);
dealloc: dealloc:
if_usb_free(cardp); if_usb_free(cardp);
error: error:
return -ENOMEM; return r;
} }
/** /**
...@@ -829,49 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) ...@@ -829,49 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
return ret; return ret;
} }
/* table of firmware file names */ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
static const struct { const struct firmware *fw,
u32 model; const struct firmware *unused)
const char *fwname;
} fw_table[] = {
{ MODEL_8388, "libertas/usb8388_olpc.bin" },
{ MODEL_8388, "libertas/usb8388_v9.bin" },
{ MODEL_8388, "libertas/usb8388_v5.bin" },
{ MODEL_8388, "libertas/usb8388.bin" },
{ MODEL_8388, "usb8388.bin" },
{ MODEL_8682, "libertas/usb8682.bin" }
};
static int get_fw(struct if_usb_card *cardp)
{
int i;
/* Otherwise search for firmware to use */
for (i = 0; i < ARRAY_SIZE(fw_table); i++) {
if (fw_table[i].model != cardp->model)
continue;
if (request_firmware(&cardp->fw, fw_table[i].fwname,
&cardp->udev->dev) == 0)
return 0;
}
return -ENOENT;
}
static int if_usb_prog_firmware(struct if_usb_card *cardp)
{ {
struct if_usb_card *cardp = priv->card;
int i = 0; int i = 0;
static int reset_count = 10; static int reset_count = 10;
int ret = 0;
lbs_deb_enter(LBS_DEB_USB); lbs_deb_enter(LBS_DEB_USB);
ret = get_fw(cardp);
if (ret) { if (ret) {
pr_err("failed to find firmware (%d)\n", ret); pr_err("failed to find firmware (%d)\n", ret);
goto done; goto done;
} }
cardp->fw = fw;
if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
ret = -EINVAL; ret = -EINVAL;
goto release_fw; goto release_fw;
...@@ -954,13 +924,27 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp) ...@@ -954,13 +924,27 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
goto release_fw; goto release_fw;
} }
cardp->priv->fw_ready = 1;
if_usb_submit_rx_urb(cardp);
if (lbs_start_card(priv))
goto release_fw;
if_usb_setup_firmware(priv);
/*
* EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
*/
priv->wol_criteria = EHS_REMOVE_WAKEUP;
if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
priv->ehs_remove_supported = false;
release_fw: release_fw:
release_firmware(cardp->fw); release_firmware(cardp->fw);
cardp->fw = NULL; cardp->fw = NULL;
done: done:
lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); lbs_deb_leave(LBS_DEB_USB);
return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment