[PATCH] libertas: Fix sd8686 firmware reload

Dan Williams dcbw at redhat.com
Wed Oct 13 12:15:19 EDT 2010


On Sun, 2010-10-10 at 10:53 +0100, Daniel Drake wrote:
> From: Paul Fox <pgf at laptop.org>
> 
> The firmware presence check is not fully reliable. Broaden the check
> to see if the firmware is running.

I'm not against this per-se, but the firmware spec clearly indicates
that the procedure for checking whether firmware is active is to read
FN0 and FN1 and look for 0xDC and 0xFE respectively.  This patch
modifies that for sd8686 to look for *any* value.  Second, Marvell
reference SD8686 driver "SD-8686-LINUX26-MONAHANS-9.70.3.p30-26409.P51"
also looks only for 0xFEDC, as does the Motorola A980 SD8385 driver
version 138.p23.

Can we get some guidance from Marvell as to why these registers would be
different on the 8686 and if that indeed does indicate that the firmware
is already active?

Dan

> The module can now be unloaded/reloaded successfully.
> 
> Based on the implementation from libertas_tf.
> 
> Signed-off-by: Daniel Drake <dsd at laptop.org>
> ---
>  drivers/net/wireless/libertas/if_sdio.c |   23 +++++++++++++++++++----
>  1 files changed, 19 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
> index 87b6349..d6b834a 100644
> --- a/drivers/net/wireless/libertas/if_sdio.c
> +++ b/drivers/net/wireless/libertas/if_sdio.c
> @@ -704,28 +704,43 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
>  
>  	lbs_deb_enter(LBS_DEB_SDIO);
>  
> +	/*
> +	 * Disable interrupts
> +	 */
> +	sdio_claim_host(card->func);
> +	sdio_writeb(card->func, 0x00, IF_SDIO_H_INT_MASK, &ret);
> +	sdio_release_host(card->func);
> +
>  	sdio_claim_host(card->func);
>  	scratch = if_sdio_read_scratch(card, &ret);
>  	sdio_release_host(card->func);
>  
> +	lbs_deb_sdio("firmware status = %#x\n", scratch);
> +	lbs_deb_sdio("scratch ret = %d\n", ret);
> +
>  	if (ret)
>  		goto out;
>  
> -	lbs_deb_sdio("firmware status = %#x\n", scratch);
> -
>  	if (scratch == IF_SDIO_FIRMWARE_OK) {
>  		lbs_deb_sdio("firmware already loaded\n");
>  		goto success;
> +	} else if ((card->model == IF_SDIO_MODEL_8686) && (scratch > 0)) {
> +		lbs_deb_sdio("firmware may be running\n");
> +		goto success;
>  	}
>  
>  	ret = if_sdio_prog_helper(card);
>  	if (ret)
>  		goto out;
>  
> +	lbs_deb_sdio("Helper firmware loaded\n");
> +
>  	ret = if_sdio_prog_real(card);
>  	if (ret)
>  		goto out;
>  
> +	lbs_deb_sdio("Firmware loaded\n");
> +
>  success:
>  	sdio_claim_host(card->func);
>  	sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
> @@ -1083,8 +1098,6 @@ static int if_sdio_probe(struct sdio_func *func,
>  	priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
>  	priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
>  
> -	priv->fw_ready = 1;
> -
>  	sdio_claim_host(func);
>  
>  	/*
> @@ -1105,6 +1118,8 @@ static int if_sdio_probe(struct sdio_func *func,
>  	if (ret)
>  		goto reclaim;
>  
> +	priv->fw_ready = 1;
> +
>  	/*
>  	 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
>  	 */





More information about the libertas-dev mailing list