2012-04-09 20:23:43

by Daniel Drake

[permalink] [raw]
Subject: [RFC 5/4] libertas USB: convert to asynchronous firmware loading

Signed-off-by: Daniel Drake <[email protected]>
---
drivers/net/wireless/libertas/if_usb.c | 102 +++++++++++++------------------
1 files changed, 43 insertions(+), 59 deletions(-)

Continuing the patch series from last week:

[RFC 1/4] libertas: Firmware loading simplifications
[RFC 2/4] libertas: harden-up exit paths
[RFC 3/4] libertas: add asynchronous firmware loading capability
[RFC 4/4] libertas SDIO: convert to asynchronous firmware loading

This patch moves the USB driver to async firmware loading.

diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 3dde3e0..d5c02a7 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -41,6 +41,16 @@ enum {
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[] = {
/* Enter the device signature inside */
{ USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
@@ -52,7 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);

static void if_usb_receive(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,
uint8_t *payload, uint16_t nb);
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,
struct usb_endpoint_descriptor *endpoint;
struct lbs_private *priv;
struct if_usb_card *cardp;
+ int r = -ENOMEM;
int i;

udev = interface_to_usbdev(intf);
@@ -244,17 +257,10 @@ static int if_usb_probe(struct usb_interface *intf,
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)))
- goto err_prog_firmware;
+ goto err_add_card;

cardp->priv = priv;
- cardp->priv->fw_ready = 1;

priv->hw_host_to_card = if_usb_host_to_card;
priv->enter_deep_sleep = NULL;
@@ -267,34 +273,25 @@ static int if_usb_probe(struct usb_interface *intf,

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_set_intfdata(intf, cardp);

- /*
- * 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;
+ r = lbs_get_firmware_async(priv, &udev->dev, cardp->model,
+ fw_table, if_usb_prog_firmware);
+ if (r)
+ goto err_get_fw;

return 0;

-err_start_card:
+err_get_fw:
lbs_remove_card(priv);
-err_prog_firmware:
+err_add_card:
if_usb_reset_device(cardp);
dealloc:
if_usb_free(cardp);

error:
- return -ENOMEM;
+ return r;
}

/**
@@ -829,49 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
return ret;
}

-/* table of firmware file names */
-static const struct {
- u32 model;
- 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)
+static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
+ const struct firmware *fw,
+ const struct firmware *unused)
{
+ struct if_usb_card *cardp = priv->card;
int i = 0;
static int reset_count = 10;
- int ret = 0;

lbs_deb_enter(LBS_DEB_USB);

- ret = get_fw(cardp);
if (ret) {
pr_err("failed to find firmware (%d)\n", ret);
goto done;
}

+ cardp->fw = fw;
if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
ret = -EINVAL;
goto release_fw;
@@ -954,13 +924,27 @@ restart:
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_firmware(cardp->fw);
cardp->fw = NULL;

done:
- lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
- return ret;
+ lbs_deb_leave(LBS_DEB_USB);
}


--
1.7.7.6



2012-04-16 21:45:36

by Dan Williams

[permalink] [raw]
Subject: Re: [RFC 5/4] libertas USB: convert to asynchronous firmware loading

On Mon, 2012-04-09 at 21:23 +0100, Daniel Drake wrote:
> Signed-off-by: Daniel Drake <[email protected]>
> ---
> drivers/net/wireless/libertas/if_usb.c | 102 +++++++++++++------------------
> 1 files changed, 43 insertions(+), 59 deletions(-)
>
> Continuing the patch series from last week:
>
> [RFC 1/4] libertas: Firmware loading simplifications
> [RFC 2/4] libertas: harden-up exit paths
> [RFC 3/4] libertas: add asynchronous firmware loading capability
> [RFC 4/4] libertas SDIO: convert to asynchronous firmware loading
>
> This patch moves the USB driver to async firmware loading.

Works on my standlone 8388 dongle. Same unregistered net_device as for
the 8686 though:

[32173.742533] usb8xxx 2-1:1.0: (unregistered net_device):
00:50:43:28:0b:88, fw 5.110.22p23, cap 0x00000303

Dan

> diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
> index 3dde3e0..d5c02a7 100644
> --- a/drivers/net/wireless/libertas/if_usb.c
> +++ b/drivers/net/wireless/libertas/if_usb.c
> @@ -41,6 +41,16 @@ enum {
> 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[] = {
> /* Enter the device signature inside */
> { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 },
> @@ -52,7 +62,9 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
>
> static void if_usb_receive(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,
> uint8_t *payload, uint16_t nb);
> 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,
> struct usb_endpoint_descriptor *endpoint;
> struct lbs_private *priv;
> struct if_usb_card *cardp;
> + int r = -ENOMEM;
> int i;
>
> udev = interface_to_usbdev(intf);
> @@ -244,17 +257,10 @@ static int if_usb_probe(struct usb_interface *intf,
> 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)))
> - goto err_prog_firmware;
> + goto err_add_card;
>
> cardp->priv = priv;
> - cardp->priv->fw_ready = 1;
>
> priv->hw_host_to_card = if_usb_host_to_card;
> priv->enter_deep_sleep = NULL;
> @@ -267,34 +273,25 @@ static int if_usb_probe(struct usb_interface *intf,
>
> 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_set_intfdata(intf, cardp);
>
> - /*
> - * 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;
> + r = lbs_get_firmware_async(priv, &udev->dev, cardp->model,
> + fw_table, if_usb_prog_firmware);
> + if (r)
> + goto err_get_fw;
>
> return 0;
>
> -err_start_card:
> +err_get_fw:
> lbs_remove_card(priv);
> -err_prog_firmware:
> +err_add_card:
> if_usb_reset_device(cardp);
> dealloc:
> if_usb_free(cardp);
>
> error:
> - return -ENOMEM;
> + return r;
> }
>
> /**
> @@ -829,49 +826,22 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen)
> return ret;
> }
>
> -/* table of firmware file names */
> -static const struct {
> - u32 model;
> - 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)
> +static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
> + const struct firmware *fw,
> + const struct firmware *unused)
> {
> + struct if_usb_card *cardp = priv->card;
> int i = 0;
> static int reset_count = 10;
> - int ret = 0;
>
> lbs_deb_enter(LBS_DEB_USB);
>
> - ret = get_fw(cardp);
> if (ret) {
> pr_err("failed to find firmware (%d)\n", ret);
> goto done;
> }
>
> + cardp->fw = fw;
> if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
> ret = -EINVAL;
> goto release_fw;
> @@ -954,13 +924,27 @@ restart:
> 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_firmware(cardp->fw);
> cardp->fw = NULL;
>
> done:
> - lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
> - return ret;
> + lbs_deb_leave(LBS_DEB_USB);
> }
>
>