patch-2.4.25 linux-2.4.25/drivers/net/typhoon.c

Next file: linux-2.4.25/drivers/net/wan/8253x/crc32dcl.h
Previous file: linux-2.4.25/drivers/net/tokenring/olympic.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.24/drivers/net/typhoon.c linux-2.4.25/drivers/net/typhoon.c
@@ -85,8 +85,8 @@
 #define PKT_BUF_SZ		1536
 
 #define DRV_MODULE_NAME		"typhoon"
-#define DRV_MODULE_VERSION 	"1.4.1"
-#define DRV_MODULE_RELDATE	"03/06/26"
+#define DRV_MODULE_VERSION 	"1.4.2"
+#define DRV_MODULE_RELDATE	"03/11/25"
 #define PFX			DRV_MODULE_NAME ": "
 #define ERR_PFX			KERN_ERR PFX
 
@@ -127,7 +127,7 @@
 static char version[] __devinitdata =
     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
-MODULE_AUTHOR("David Dillow <dillowd@y12.doe.gov>");
+MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
 MODULE_PARM(rx_copybreak, "i");
@@ -146,11 +146,12 @@
 	int capabilities;
 };
 
-#define TYPHOON_CRYPTO_NONE		0
-#define TYPHOON_CRYPTO_DES		1
-#define TYPHOON_CRYPTO_3DES		2
-#define	TYPHOON_CRYPTO_VARIABLE		4
-#define TYPHOON_FIBER			8
+#define TYPHOON_CRYPTO_NONE		0x00
+#define TYPHOON_CRYPTO_DES		0x01
+#define TYPHOON_CRYPTO_3DES		0x02
+#define	TYPHOON_CRYPTO_VARIABLE		0x04
+#define TYPHOON_FIBER			0x08
+#define TYPHOON_WAKEUP_NEEDS_RESET	0x10
 
 enum typhoon_cards {
 	TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR,
@@ -307,7 +308,8 @@
 /* We'll wait up to six seconds for a reset, and half a second normally.
  */
 #define TYPHOON_UDELAY			50
-#define TYPHOON_RESET_TIMEOUT		(6 * HZ)
+#define TYPHOON_RESET_TIMEOUT_SLEEP	(6 * HZ)
+#define TYPHOON_RESET_TIMEOUT_NOSLEEP	((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT		((1000000 / 2) / TYPHOON_UDELAY)
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
@@ -375,10 +377,12 @@
 typhoon_reset(unsigned long ioaddr, int wait_type)
 {
 	int i, err = 0;
-	int timeout = TYPHOON_RESET_TIMEOUT;
+	int timeout;
 
 	if(wait_type == WaitNoSleep)
-		timeout = (timeout * 1000000) / (HZ * TYPHOON_UDELAY);
+		timeout = TYPHOON_RESET_TIMEOUT_NOSLEEP;
+	else
+		timeout = TYPHOON_RESET_TIMEOUT_SLEEP;
 
 	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
 	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
@@ -1857,6 +1861,11 @@
 	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_SLEEPING) < 0)
 		return -ETIMEDOUT;
 
+	/* Since we cannot monitor the status of the link while sleeping,
+	 * tell the world it went away.
+	 */
+	netif_carrier_off(tp->dev);
+
 	pci_enable_wake(tp->pdev, state, 1);
 	pci_disable_device(pdev);
 	return pci_set_power_state(pdev, state);
@@ -1871,8 +1880,13 @@
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, tp->pci_state);
 
+	/* Post 2.x.x versions of the Sleep Image require a reset before
+	 * we can download the Runtime Image. But let's not make users of
+	 * the old firmware pay for the reset.
+	 */
 	writel(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
-	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0)
+	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 ||
+			(tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET))
 		return typhoon_reset(ioaddr, wait_type);
 
 	return 0;
@@ -2250,7 +2264,7 @@
 	void *shared;
 	dma_addr_t shared_dma;
 	struct cmd_desc xp_cmd;
-	struct resp_desc xp_resp;
+	struct resp_desc xp_resp[3];
 	int i;
 	int err = 0;
 
@@ -2378,15 +2392,15 @@
 	}
 
 	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS);
-	if(typhoon_issue_command(tp, 1, &xp_cmd, 1, &xp_resp) < 0) {
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp) < 0) {
 		printk(ERR_PFX "%s: cannot read MAC address\n",
 		       pdev->slot_name);
 		err = -EIO;
 		goto error_out_reset;
 	}
 
-	*(u16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp.parm1));
-	*(u32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp.parm2));
+	*(u16 *)&dev->dev_addr[0] = htons(le16_to_cpu(xp_resp[0].parm1));
+	*(u32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2));
 
 	if(!is_valid_ether_addr(dev->dev_addr)) {
 		printk(ERR_PFX "%s: Could not obtain valid ethernet address, "
@@ -2394,6 +2408,28 @@
 		goto error_out_reset;
 	}
 
+	/* Read the Sleep Image version last, so the response is valid
+	 * later when we print out the version reported.
+	 */
+	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
+	if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
+		printk(ERR_PFX "%s: Could not get Sleep Image version\n",
+			pdev->slot_name);
+		goto error_out_reset;
+	}
+
+	tp->capabilities = typhoon_card_info[card_id].capabilities;
+	tp->xcvr_select = TYPHOON_XCVR_AUTONEG;
+
+	/* Typhoon 1.0 Sleep Images return one response descriptor to the
+	 * READ_VERSIONS command. Those versions are OK after waking up
+	 * from sleep without needing a reset. Typhoon 1.1+ Sleep Images
+	 * seem to need a little extra help to get started. Since we don't
+	 * know how to nudge it along, just kick it.
+	 */
+	if(xp_resp[0].numDesc != 0)
+		tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET;
+
 	if(typhoon_sleep(tp, 3, 0) < 0) {
 		printk(ERR_PFX "%s: cannot put adapter to sleep\n",
 		       pdev->slot_name);
@@ -2401,9 +2437,6 @@
 		goto error_out_reset;
 	}
 
-	tp->capabilities = typhoon_card_info[card_id].capabilities;
-	tp->xcvr_select = TYPHOON_XCVR_AUTONEG;
-
 	/* The chip-specific entries in the device structure. */
 	dev->open		= typhoon_open;
 	dev->hard_start_xmit	= typhoon_start_tx;
@@ -2440,6 +2473,32 @@
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x\n", dev->dev_addr[i]);
 
+	/* xp_resp still contains the response to the READ_VERSIONS command.
+	 * For debugging, let the user know what version he has.
+	 */
+	if(xp_resp[0].numDesc == 0) {
+		/* This is the Typhoon 1.0 type Sleep Image, last 16 bits
+		 * of version is Month/Day of build.
+		 */
+		u16 monthday = le32_to_cpu(xp_resp[0].parm2) & 0xffff;
+		printk(KERN_INFO "%s: Typhoon 1.0 Sleep Image built "
+			"%02u/%02u/2000\n", dev->name, monthday >> 8,
+			monthday & 0xff);
+	} else if(xp_resp[0].numDesc == 2) {
+		/* This is the Typhoon 1.1+ type Sleep Image
+		 */
+		u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2);
+		u8 *ver_string = (u8 *) &xp_resp[1];
+		ver_string[25] = 0;
+		printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version "
+			"%u.%u.%u.%u %s\n", dev->name, HIPQUAD(sleep_ver),
+			ver_string);
+	} else {
+		printk(KERN_WARNING "%s: Unknown Sleep Image version "
+			"(%u:%04x)\n", dev->name, xp_resp[0].numDesc,
+			le32_to_cpu(xp_resp[0].parm2));
+	}
+		
 	return 0;
 
 error_out_reset:

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)