Search Linux Wireless

[PATCH 4/9] libertas_tf: Add firmware reset to sdio driver and attempt firmware reload

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds a method to do a firmware/chip reset to the sdio driver and
attempts to reload the firmware.

Signed-off-by: Steve deRosier <steve@xxxxxxxxxxx>
---
 drivers/net/wireless/libertas_tf/if_sdio.c |   40 +++++++++++++++++++++++----
 drivers/net/wireless/libertas_tf/main.c    |    7 ++++-
 2 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/libertas_tf/if_sdio.c b/drivers/net/wireless/libertas_tf/if_sdio.c
index fed5aff..1e72b4c 100644
--- a/drivers/net/wireless/libertas_tf/if_sdio.c
+++ b/drivers/net/wireless/libertas_tf/if_sdio.c
@@ -53,6 +53,8 @@ struct if_sdio_model {
 	const char *firmware;
 };
 
+extern unsigned int lbtf_reset_fw;
+
 static struct if_sdio_model if_sdio_models[] = {
 	{
 		/* 8686 */
@@ -673,6 +675,8 @@ out:
 	return ret;
 }
 
+static void if_sdio_reset_device(struct if_sdio_card *card);
+
 static int if_sdio_prog_firmware(struct if_sdio_card *card)
 {
 	int ret;
@@ -691,17 +695,29 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
 	scratch = if_sdio_read_scratch(card, &ret);
 	sdio_release_host(card->func);
 
+	lbtf_deb_sdio("firmware status = %#x\n", scratch);
+	lbtf_deb_sdio("scratch ret = %d\n", ret);
+
 	if (ret)
 		goto out;
 
-	lbtf_deb_sdio("firmware status = %#x\n", scratch);
-
 	if (scratch == IF_SDIO_FIRMWARE_OK) {
 		lbtf_deb_sdio("firmware already loaded\n");
 		goto success;
 	} else if ((card->model == IF_SDIO_MODEL_8686) && (scratch > 0)) {
 		lbtf_deb_sdio("firmware may be running\n");
-		goto success;
+		if( lbtf_reset_fw == 0 ) {
+			goto success;
+		} else {
+			int i = 0;
+			lbtf_deb_sdio("attempting to reset and reload firmware\n");
+
+			if_sdio_reset_device(card);
+			lbtf_reset_fw=0;
+
+			ret = if_sdio_prog_firmware(card);
+			goto out;
+		}
 	}
 
 	ret = if_sdio_prog_helper(card);
@@ -864,7 +880,7 @@ static void if_sdio_reset_device(struct if_sdio_card *card)
 
 	if_sdio_host_to_card(card->priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
 
-	msleep(100);
+	msleep(1000);
 
 	lbtf_deb_leave(LBTF_DEB_SDIO);
 
@@ -887,10 +903,12 @@ static void if_sdio_interrupt(struct sdio_func *func)
 	card = sdio_get_drvdata(func);
 
 	cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret);
+	lbtf_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
+	lbtf_deb_sdio("interrupt ret: 0x%X\n", ret);
 	if (ret)
 		goto out;
 
-	lbtf_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
+//	lbtf_deb_sdio("interrupt: 0x%X\n", (unsigned)cause);
 
 	sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret);
 	if (ret)
@@ -1061,13 +1079,23 @@ static int if_sdio_probe(struct sdio_func *func,
 	priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
 	priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
 	priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
-	priv->hw_reset_device = if_sdio_reset_device;
 	priv->enable_interrupts = if_sdio_enable_interrupts;
 	priv->disable_interrupts = if_sdio_disable_interrupts;
 
 	/* SD8385 & SD8686 do not have rx_unit.	*/
 	card->rx_unit = 0;
 
+	/*
+	 * Enable interrupts now that everything is set up
+	 */
+	ret = _if_sdio_enable_interrupts(card);
+	if (ret) {
+		pr_err("Error enabling interrupts: %d", ret);
+		goto err_activate_card;
+	}
+
+	priv->fw_ready = 1;
+
 out:
 	lbtf_deb_leave_args(LBTF_DEB_SDIO, "ret %d", ret);
 
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 5d34ad9..119d625 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -24,6 +24,10 @@ unsigned int lbtf_debug;
 EXPORT_SYMBOL_GPL(lbtf_debug);
 module_param_named(libertas_tf_debug, lbtf_debug, int, 0644);
 
+unsigned int lbtf_reset_fw;
+EXPORT_SYMBOL_GPL(lbtf_reset_fw);
+module_param_named(libertas_tf_reset_fw, lbtf_reset_fw, int, 0644);
+
 static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION
 #ifdef DEBUG
 	"-dbg"
@@ -360,7 +364,8 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
 	return 0;
 
 err_prog_firmware:
-//	priv->hw_reset_device(card);
+	if (priv->hw_reset_device)
+		priv->hw_reset_device(card);
 	lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programing fw; ret=%d", ret);
 	return ret;
 }
-- 
1.7.0

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux