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

Dan Williams dcbw at redhat.com
Mon Apr 16 17:45:32 EDT 2012


On Mon, 2012-04-09 at 21:23 +0100, Daniel Drake wrote:
> Signed-off-by: Daniel Drake <dsd at laptop.org>
> ---
>  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);
>  }
>  
> 





More information about the libertas-dev mailing list