All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libertas: Fix sd8686 firmware reload
@ 2010-10-13 19:14 Daniel Drake
  2010-10-13 20:51 ` Steve deRosier
  2010-10-14 15:58 ` Dan Williams
  0 siblings, 2 replies; 3+ messages in thread
From: Daniel Drake @ 2010-10-13 19:14 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, libertas-dev, dcbw, pgf, steve

From: Paul Fox <pgf@laptop.org>

For the SD8686, we cannot rely on the scratch register to read the firmware
load status, because the same register is used for storing RX packet length.
Broaden the check to account for this.

The module can now be unloaded/reloaded successfully.

Based on the implementation from libertas_tf.

Signed-off-by: Daniel Drake <dsd@laptop.org>
---
 drivers/net/wireless/libertas/if_sdio.c |   32 ++++++++++++++++++++++++++++--
 1 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 87b6349..d2e5193 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -704,28 +704,54 @@ 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);
 
+	/*
+	 * The manual clearly describes that FEDC is the right code to use
+	 * to detect firmware presence, but for SD8686 it is not that simple.
+	 * Scratch is also used to store the RX packet length, so we lose
+	 * the FEDC value early on. So we use a non-zero check in order
+	 * to validate firmware presence.
+	 * Additionally, the SD8686 in the Gumstix always has the high scratch
+	 * bit set, even when the firmware is not loaded. So we have to
+	 * exclude that from the test.
+	 */
 	if (scratch == IF_SDIO_FIRMWARE_OK) {
 		lbs_deb_sdio("firmware already loaded\n");
 		goto success;
+	} else if ((card->model == IF_SDIO_MODEL_8686) && (scratch & 0x7fff)) {
+		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 +1109,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 +1129,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
 	 */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] libertas: Fix sd8686 firmware reload
  2010-10-13 19:14 [PATCH] libertas: Fix sd8686 firmware reload Daniel Drake
@ 2010-10-13 20:51 ` Steve deRosier
  2010-10-14 15:58 ` Dan Williams
  1 sibling, 0 replies; 3+ messages in thread
From: Steve deRosier @ 2010-10-13 20:51 UTC (permalink / raw)
  To: Daniel Drake; +Cc: linville, linux-wireless, libertas-dev, dcbw, pgf

On Wed, Oct 13, 2010 at 12:14 PM, Daniel Drake <dsd@laptop.org> wrote:
> From: Paul Fox <pgf@laptop.org>
>
> For the SD8686, we cannot rely on the scratch register to read the firmware
> load status, because the same register is used for storing RX packet length.
> Broaden the check to account for this.
>
> The module can now be unloaded/reloaded successfully.
>
> Based on the implementation from libertas_tf.
>
> Signed-off-by: Daniel Drake <dsd@laptop.org>

Signed-off-by: Steve deRosier <steve@cozybit.com>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] libertas: Fix sd8686 firmware reload
  2010-10-13 19:14 [PATCH] libertas: Fix sd8686 firmware reload Daniel Drake
  2010-10-13 20:51 ` Steve deRosier
@ 2010-10-14 15:58 ` Dan Williams
  1 sibling, 0 replies; 3+ messages in thread
From: Dan Williams @ 2010-10-14 15:58 UTC (permalink / raw)
  To: Daniel Drake; +Cc: linville, linux-wireless, libertas-dev, pgf, steve

On Wed, 2010-10-13 at 20:14 +0100, Daniel Drake wrote:
> From: Paul Fox <pgf@laptop.org>
> 
> For the SD8686, we cannot rely on the scratch register to read the firmware
> load status, because the same register is used for storing RX packet length.
> Broaden the check to account for this.
> 
> The module can now be unloaded/reloaded successfully.
> 
> Based on the implementation from libertas_tf.
> 
> Signed-off-by: Daniel Drake <dsd@laptop.org>

Acked-by: Dan Williams <dcbw@redhat.com>

> ---
>  drivers/net/wireless/libertas/if_sdio.c |   32 ++++++++++++++++++++++++++++--
>  1 files changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
> index 87b6349..d2e5193 100644
> --- a/drivers/net/wireless/libertas/if_sdio.c
> +++ b/drivers/net/wireless/libertas/if_sdio.c
> @@ -704,28 +704,54 @@ 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);
>  
> +	/*
> +	 * The manual clearly describes that FEDC is the right code to use
> +	 * to detect firmware presence, but for SD8686 it is not that simple.
> +	 * Scratch is also used to store the RX packet length, so we lose
> +	 * the FEDC value early on. So we use a non-zero check in order
> +	 * to validate firmware presence.
> +	 * Additionally, the SD8686 in the Gumstix always has the high scratch
> +	 * bit set, even when the firmware is not loaded. So we have to
> +	 * exclude that from the test.
> +	 */
>  	if (scratch == IF_SDIO_FIRMWARE_OK) {
>  		lbs_deb_sdio("firmware already loaded\n");
>  		goto success;
> +	} else if ((card->model == IF_SDIO_MODEL_8686) && (scratch & 0x7fff)) {
> +		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 +1109,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 +1129,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
>  	 */



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-10-14 15:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-13 19:14 [PATCH] libertas: Fix sd8686 firmware reload Daniel Drake
2010-10-13 20:51 ` Steve deRosier
2010-10-14 15:58 ` Dan Williams

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.