libertas: resend initial boot command in case of non-response

Marcelo Tosatti mtosatti at redhat.unroutablecom
Sun Dec 24 04:30:49 EST 2006


Commit:     cad10c43037fc9688a7d69aaf83e9e5746ecf8bc
Parent:     261e40bb213130e55969e5df01180ede8fa12051
commit cad10c43037fc9688a7d69aaf83e9e5746ecf8bc
Author:     Marcelo Tosatti <mtosatti at redhat.com>
AuthorDate: Sat Dec 23 20:31:51 2006 -0200
Commit:     Marcelo Tosatti <mtosatti at redhat.com>
CommitDate: Sat Dec 23 20:31:51 2006 -0200

    libertas: resend initial boot command in case of non-response
    
    Workaround unknown problem in which the command is "lost" in the USB
    bus. Appears to be specific to the Geode.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
---
 drivers/net/wireless/libertas/if_bootcmd.c |   12 +------
 drivers/net/wireless/libertas/if_usb.c     |   51 ++++++++++++++++++++++++----
 drivers/net/wireless/libertas/if_usb.h     |    2 +
 3 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_bootcmd.c b/drivers/net/wireless/libertas/if_bootcmd.c
index 435d30d..87393e7 100644
--- a/drivers/net/wireless/libertas/if_bootcmd.c
+++ b/drivers/net/wireless/libertas/if_bootcmd.c
@@ -55,8 +55,8 @@ extern struct BootCMDStr	sBootCMD;
  */
 int if_usb_issue_boot_command(wlan_private *priv, int iValue)
 {
-	int i = 0;
 	struct usb_card_rec	*cardp = priv->wlan_dev.card;
+	int i;
 
 	/* Prepare Command */
 	sBootCMD.u32MagicNumber = BOOT_CMD_MAGIC_NUMBER;
@@ -66,17 +66,7 @@ int if_usb_issue_boot_command(wlan_priva
 	memcpy(cardp->bulk_out_buffer, &sBootCMD, sizeof(struct BootCMDStr));
 
 	/* Issue Command */
-	cardp->BootCMDACK = 0;
-	i = 0;
 	usb_tx_block(priv, cardp->bulk_out_buffer, sizeof(struct BootCMDStr));
 
-	/* Wait for the Reault */
-	do {
-		i ++;
-		msleep_interruptible(100);
-		if (priv->adapter->SurpriseRemoved || i>=20)
-			break;
-	} while (!cardp->BootCMDACK);
-
 	return WLAN_STATUS_SUCCESS;
 }
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 3c979b2..d88c675 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -112,7 +112,6 @@ static void if_usb_write_bulk_callback(s
 	wlan_private *priv = (wlan_private *) (urb->context);
 	wlan_adapter *adapter = priv->adapter;
 	struct net_device *dev = priv->wlan_dev.netdev;
-	struct usb_card_rec *cardp = priv->wlan_dev.card;
 
 	/* handle the transmission complete validations */
 
@@ -131,8 +130,6 @@ static void if_usb_write_bulk_callback(s
 			netif_wake_queue(dev);
 	}
 
-	cardp->BootCMDACK = 1;
-
 	return;
 }
 
@@ -453,6 +450,7 @@ rx_ret:
 	return ret;
 }
 
+struct BootCMDRespStr bootcmdresp;
 
 static void if_usb_receive_fwload(struct urb *urb)
 {
@@ -470,6 +468,30 @@ static void if_usb_receive_fwload(struct
 		return;
 	}
 
+	if (cardp->BootCMDResp == 0) {
+		memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
+			sizeof(bootcmdresp));
+		if (bootcmdresp.u32MagicNumber != BOOT_CMD_MAGIC_NUMBER) {
+			printk(KERN_INFO
+				"boot cmd response wrong magic number (0x%x)\n",
+				bootcmdresp.u32MagicNumber);
+		} else if (bootcmdresp.u8CMD_Tag != BOOT_CMD_FW_BY_USB) {
+			printk(KERN_INFO
+				"boot cmd response cmd_tag error (%d)\n",
+				bootcmdresp.u8CMD_Tag);
+		} else if (bootcmdresp.u8Result != BOOT_CMD_RESP_OK) {
+			printk(KERN_INFO
+				"boot cmd response result error (%d)\n",
+				bootcmdresp.u8Result);
+		} else {
+			cardp->BootCMDResp = 1;
+			dprintk(1, "Received valid boot command response\n");
+		}
+		kfree_skb(skb);
+		if_usb_submit_rx_urb_fwload(priv);
+		return;
+	}
+
 	SyncFWHeader = kmalloc(sizeof(struct FWSyncHeader), GFP_ATOMIC);
 	if (!SyncFWHeader) {
 		dprintk(1, "Failure to allocate SyncFWHeader\n");
@@ -875,17 +897,30 @@ int libertas_sbi_prog_firmware(wlan_priv
 
 	ENTER();
 
-#ifdef SUPPORT_BOOT_COMMAND
-	/* Issue Boot command = 1, Boot from Download-FW */
-	if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB);
-#endif
-
 	if (if_usb_submit_rx_urb_fwload(priv) < 0) {
 		dprintk(1, "URB submission is failed\n");
 		LEAVE();
 		return WLAN_STATUS_FAILURE;
 	}
 
+#ifdef SUPPORT_BOOT_COMMAND
+	cardp->BootCMDResp = 0;
+	do {
+		int j = 0;
+		i++;
+		/* Issue Boot command = 1, Boot from Download-FW */
+		if_usb_issue_boot_command(priv, BOOT_CMD_FW_BY_USB);
+		/* wait for command response */
+		do {
+			j++;
+			msleep_interruptible(100);
+		} while (cardp->BootCMDResp == 0 && j < 10);
+	} while (cardp->BootCMDResp == 0 && i < 5);
+
+	if (cardp->BootCMDResp == 0)
+		return WLAN_STATUS_FAILURE;
+#endif
+
 restart:
 	i = 0;
 	priv->adapter->fw_ready = 0;
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index c938baa..6e7d836 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -90,7 +90,7 @@ struct usb_card_rec {
 
 	u8 rx_urb_recall;
 
-	u8			BootCMDACK;
+	u8 BootCMDResp;
 };
 
 typedef void *(*usb_notifier_fn_add) (struct usb_card_rec *);


More information about the Commits-kernel mailing list