[PATCH] S2io: Hardware and miscellaneous fixes

Hi,
This patch contains the following hardware related fixes and other
miscellaneous bug fixes.

1. Updated the definition of single and double-bit ECC errors
2. Earlier we were allocating Transmit descriptors equal to
   MAX_SKB_FRAGS. This was causing a boundary condition failure.
   Need to allocate MAX_SKB_FRAGS+1 descriptors.
3. On some platforms(like PPC), pci_alloc_consistent() can return
   a zero DMA address. Since the NIC cannot handle zero-addresses,
   a workaround has been provided. Basically, we don't use such
   that page. We reallocate.
4. If list_info allocation failed during driver load, check for
   it during driver exit and return instead of trying to dereference
   NULL pointer.
5. Increase the debug level of few non-critical debug messages.
6. Reset the card on critical ECC double errors only in case of
   XframeI since XframeII can recover from such errors.
7. Print copyright message on driver load.
8. Bumped up the driver version no. to 2.0.8.1

Signed-off-by: Ravinandan Arakali <ravinandan.arakali@neterion.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 5dda043..7cfe166 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1,5 +1,5 @@
 /************************************************************************
- * s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
+ * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
  * Copyright(c) 2002-2005 Neterion Inc.
 
  * This software may be used and distributed according to the terms of
@@ -28,7 +28,7 @@
  * explaination of all the variables.
  * rx_ring_num : This can be used to program the number of receive rings used
  * in the driver.
- * rx_ring_len: This defines the number of descriptors each ring can have. This
+ * rx_ring_sz: This defines the number of descriptors each ring can have. This
  * is also an array of size 8.
  * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
  * tx_fifo_len: This too is an array of 8. Each element defines the number of
@@ -67,7 +67,7 @@
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
-static char s2io_driver_version[] = "Version 2.0.3.1";
+static char s2io_driver_version[] = "Version 2.0.8.1";
 
 static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 {
@@ -404,7 +404,7 @@
 		    config->tx_cfg[i].fifo_len - 1;
 		mac_control->fifos[i].fifo_no = i;
 		mac_control->fifos[i].nic = nic;
-		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS;
+		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1;
 
 		for (j = 0; j < page_num; j++) {
 			int k = 0;
@@ -418,6 +418,26 @@
 				DBG_PRINT(ERR_DBG, "failed for TxDL\n");
 				return -ENOMEM;
 			}
+			/* If we got a zero DMA address(can happen on
+			 * certain platforms like PPC), reallocate.
+			 * Store virtual address of page we don't want,
+			 * to be freed later.
+			 */
+			if (!tmp_p) {
+				mac_control->zerodma_virt_addr = tmp_v;
+				DBG_PRINT(INIT_DBG, 
+				"%s: Zero DMA address for TxDL. ", dev->name);
+				DBG_PRINT(INIT_DBG, 
+				"Virtual address %llx\n", (u64)tmp_v);
+				tmp_v = pci_alloc_consistent(nic->pdev,
+						     PAGE_SIZE, &tmp_p);
+				if (!tmp_v) {
+					DBG_PRINT(ERR_DBG,
+					  "pci_alloc_consistent ");
+					DBG_PRINT(ERR_DBG, "failed for TxDL\n");
+					return -ENOMEM;
+				}
+			}
 			while (k < lst_per_page) {
 				int l = (j * lst_per_page) + k;
 				if (l == config->tx_cfg[i].fifo_len)
@@ -600,7 +620,7 @@
 	mac_info_t *mac_control;
 	struct config_param *config;
 	int lst_size, lst_per_page;
-
+	struct net_device *dev = nic->dev;
 
 	if (!nic)
 		return;
@@ -616,9 +636,10 @@
 						lst_per_page);
 		for (j = 0; j < page_num; j++) {
 			int mem_blks = (j * lst_per_page);
-			if ((!mac_control->fifos[i].list_info) ||
-				(!mac_control->fifos[i].list_info[mem_blks].
-				 list_virt_addr))
+			if (!mac_control->fifos[i].list_info)
+				return;	
+			if (!mac_control->fifos[i].list_info[mem_blks].
+				 list_virt_addr)
 				break;
 			pci_free_consistent(nic->pdev, PAGE_SIZE,
 					    mac_control->fifos[i].
@@ -628,6 +649,18 @@
 					    list_info[mem_blks].
 					    list_phy_addr);
 		}
+		/* If we got a zero DMA address during allocation,
+		 * free the page now
+		 */
+		if (mac_control->zerodma_virt_addr) {
+			pci_free_consistent(nic->pdev, PAGE_SIZE,
+					    mac_control->zerodma_virt_addr,
+					    (dma_addr_t)0);
+			DBG_PRINT(INIT_DBG, 
+			"%s: Freeing TxDL with zero DMA addr. ", dev->name);
+			DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
+			(u64)(mac_control->zerodma_virt_addr));
+		}
 		kfree(mac_control->fifos[i].list_info);
 	}
 
@@ -2479,9 +2512,10 @@
 #endif
 	spin_lock(&nic->rx_lock);
 	if (atomic_read(&nic->card_state) == CARD_DOWN) {
-		DBG_PRINT(ERR_DBG, "%s: %s going down for reset\n",
+		DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
 			  __FUNCTION__, dev->name);
 		spin_unlock(&nic->rx_lock);
+		return;
 	}
 
 	get_info = ring_data->rx_curr_get_info;
@@ -2596,8 +2630,14 @@
 		if (txdlp->Control_1 & TXD_T_CODE) {
 			unsigned long long err;
 			err = txdlp->Control_1 & TXD_T_CODE;
-			DBG_PRINT(ERR_DBG, "***TxD error %llx\n",
-				  err);
+			if ((err >> 48) == 0xA) {
+				DBG_PRINT(TX_DBG, "TxD returned due \
+						to loss of link\n");
+			}
+			else {
+				DBG_PRINT(ERR_DBG, "***TxD error \
+						%llx\n", err);
+			}
 		}
 
 		skb = (struct sk_buff *) ((unsigned long)
@@ -2689,12 +2729,16 @@
 		if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
 			nic->mac_control.stats_info->sw_stat.
 				double_ecc_errs++;
-			DBG_PRINT(ERR_DBG, "%s: Device indicates ",
+			DBG_PRINT(INIT_DBG, "%s: Device indicates ",
 				  dev->name);
-			DBG_PRINT(ERR_DBG, "double ECC error!!\n");
+			DBG_PRINT(INIT_DBG, "double ECC error!!\n");
 			if (nic->device_type != XFRAME_II_DEVICE) {
-				netif_stop_queue(dev);
-				schedule_work(&nic->rst_timer_task);
+				/* Reset XframeI only if critical error */
+				if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
+					     MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
+					netif_stop_queue(dev);
+					schedule_work(&nic->rst_timer_task);
+				}
 			}
 		} else {
 			nic->mac_control.stats_info->sw_stat.
@@ -2706,7 +2750,8 @@
 	val64 = readq(&bar0->serr_source);
 	if (val64 & SERR_SOURCE_ANY) {
 		DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
-		DBG_PRINT(ERR_DBG, "serious error!!\n");
+		DBG_PRINT(ERR_DBG, "serious error %llx!!\n", 
+			  (unsigned long long)val64);
 		netif_stop_queue(dev);
 		schedule_work(&nic->rst_timer_task);
 	}
@@ -3130,7 +3175,7 @@
 	queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
 	/* Avoid "put" pointer going beyond "get" pointer */
 	if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
-		DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n");
+		DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
 		netif_stop_queue(dev);
 		dev_kfree_skb(skb);
 		spin_unlock_irqrestore(&sp->tx_lock, flags);
@@ -3528,7 +3573,7 @@
 
 		val64 = readq(&bar0->mac_cfg);
 		sp->promisc_flg = 1;
-		DBG_PRINT(ERR_DBG, "%s: entered promiscuous mode\n",
+		DBG_PRINT(INFO_DBG, "%s: entered promiscuous mode\n",
 			  dev->name);
 	} else if (!(dev->flags & IFF_PROMISC) && (sp->promisc_flg)) {
 		/*  Remove the NIC from promiscuous mode */
@@ -3543,7 +3588,7 @@
 
 		val64 = readq(&bar0->mac_cfg);
 		sp->promisc_flg = 0;
-		DBG_PRINT(ERR_DBG, "%s: left promiscuous mode\n",
+		DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n",
 			  dev->name);
 	}
 
@@ -5325,7 +5370,7 @@
 			break;
 		}
 	}
-	config->max_txds = MAX_SKB_FRAGS;
+	config->max_txds = MAX_SKB_FRAGS + 1;
 
 	/* Rx side parameters. */
 	if (rx_ring_sz[0] == 0)
@@ -5525,9 +5570,14 @@
 	if (sp->device_type & XFRAME_II_DEVICE) {
 		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
 			  dev->name);
-		DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n",
+		DBG_PRINT(ERR_DBG, "(rev %d), %s",
 				get_xena_rev_id(sp->pdev),
 				s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+		DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+
+		DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
 		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
 			  sp->def_mac_addr[0].mac_addr[0],
 			  sp->def_mac_addr[0].mac_addr[1],
@@ -5544,9 +5594,13 @@
 	} else {
 		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
 			  dev->name);
-		DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n",
+		DBG_PRINT(ERR_DBG, "(rev %d), %s",
 					get_xena_rev_id(sp->pdev),
 					s2io_driver_version);
+#ifdef CONFIG_2BUFF_MODE
+		DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
+#endif
+		DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
 		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
 			  sp->def_mac_addr[0].mac_addr[0],
 			  sp->def_mac_addr[0].mac_addr[1],