linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / net / s2io.c
index e72e0e0..b7f00d6 100644 (file)
  *
  * The module loadable parameters that are supported by the driver and a brief
  * 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_sz: This defines the number of receive blocks each ring can have.
- *     This is also an array of size 8.
+ * rx_ring_sz: This defines the number of descriptors each ring can have. This
+ * is also an array of size 8.
  * rx_ring_mode: This defines the operation mode of all 8 rings. The valid
  *             values are 1, 2 and 3.
  * 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
  * Tx descriptors that can be associated with each corresponding FIFO.
- * intr_type: This defines the type of interrupt. The values can be 0(INTA),
- *     1(MSI), 2(MSI_X). Default value is '0(INTA)'
- * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
- *     Possible values '1' for enable '0' for disable. Default is '0'
- * lro_max_pkts: This parameter defines maximum number of packets can be
- *     aggregated as a single large packet
  ************************************************************************/
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <net/tcp.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/div64.h>
-#include <asm/irq.h>
 
 /* local include */
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.15.2"
+#define DRV_VERSION "Version 2.0.9.4"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
 static char s2io_driver_version[] = DRV_VERSION;
 
-static int rxd_size[4] = {32,48,48,64};
-static int rxd_count[4] = {127,85,85,63};
+int rxd_size[4] = {32,48,48,64};
+int rxd_count[4] = {127,85,85,63};
 
 static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 {
@@ -113,14 +102,18 @@ static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 #define LOW    2
 static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)
 {
+       int level = 0;
        mac_info_t *mac_control;
 
        mac_control = &sp->mac_control;
-       if (rxb_size <= rxd_count[sp->rxd_mode])
-               return PANIC;
-       else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
-               return  LOW;
-       return 0;
+       if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {
+               level = LOW;
+               if (rxb_size <= rxd_count[sp->rxd_mode]) {
+                       level = PANIC;
+               }
+       }
+
+       return level;
 }
 
 /* Ethtool related variables and Macros. */
@@ -139,11 +132,7 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"tmac_mcst_frms"},
        {"tmac_bcst_frms"},
        {"tmac_pause_ctrl_frms"},
-       {"tmac_ttl_octets"},
-       {"tmac_ucst_frms"},
-       {"tmac_nucst_frms"},
        {"tmac_any_err_frms"},
-       {"tmac_ttl_less_fb_octets"},
        {"tmac_vld_ip_octets"},
        {"tmac_vld_ip"},
        {"tmac_drop_ip"},
@@ -158,27 +147,13 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"rmac_vld_mcst_frms"},
        {"rmac_vld_bcst_frms"},
        {"rmac_in_rng_len_err_frms"},
-       {"rmac_out_rng_len_err_frms"},
        {"rmac_long_frms"},
        {"rmac_pause_ctrl_frms"},
-       {"rmac_unsup_ctrl_frms"},
-       {"rmac_ttl_octets"},
-       {"rmac_accepted_ucst_frms"},
-       {"rmac_accepted_nucst_frms"},
        {"rmac_discarded_frms"},
-       {"rmac_drop_events"},
-       {"rmac_ttl_less_fb_octets"},
-       {"rmac_ttl_frms"},
        {"rmac_usized_frms"},
        {"rmac_osized_frms"},
        {"rmac_frag_frms"},
        {"rmac_jabber_frms"},
-       {"rmac_ttl_64_frms"},
-       {"rmac_ttl_65_127_frms"},
-       {"rmac_ttl_128_255_frms"},
-       {"rmac_ttl_256_511_frms"},
-       {"rmac_ttl_512_1023_frms"},
-       {"rmac_ttl_1024_1518_frms"},
        {"rmac_ip"},
        {"rmac_ip_octets"},
        {"rmac_hdr_err_ip"},
@@ -187,87 +162,12 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"rmac_tcp"},
        {"rmac_udp"},
        {"rmac_err_drp_udp"},
-       {"rmac_xgmii_err_sym"},
-       {"rmac_frms_q0"},
-       {"rmac_frms_q1"},
-       {"rmac_frms_q2"},
-       {"rmac_frms_q3"},
-       {"rmac_frms_q4"},
-       {"rmac_frms_q5"},
-       {"rmac_frms_q6"},
-       {"rmac_frms_q7"},
-       {"rmac_full_q0"},
-       {"rmac_full_q1"},
-       {"rmac_full_q2"},
-       {"rmac_full_q3"},
-       {"rmac_full_q4"},
-       {"rmac_full_q5"},
-       {"rmac_full_q6"},
-       {"rmac_full_q7"},
        {"rmac_pause_cnt"},
-       {"rmac_xgmii_data_err_cnt"},
-       {"rmac_xgmii_ctrl_err_cnt"},
        {"rmac_accepted_ip"},
        {"rmac_err_tcp"},
-       {"rd_req_cnt"},
-       {"new_rd_req_cnt"},
-       {"new_rd_req_rtry_cnt"},
-       {"rd_rtry_cnt"},
-       {"wr_rtry_rd_ack_cnt"},
-       {"wr_req_cnt"},
-       {"new_wr_req_cnt"},
-       {"new_wr_req_rtry_cnt"},
-       {"wr_rtry_cnt"},
-       {"wr_disc_cnt"},
-       {"rd_rtry_wr_ack_cnt"},
-       {"txp_wr_cnt"},
-       {"txd_rd_cnt"},
-       {"txd_wr_cnt"},
-       {"rxd_rd_cnt"},
-       {"rxd_wr_cnt"},
-       {"txf_rd_cnt"},
-       {"rxf_wr_cnt"},
-       {"rmac_ttl_1519_4095_frms"},
-       {"rmac_ttl_4096_8191_frms"},
-       {"rmac_ttl_8192_max_frms"},
-       {"rmac_ttl_gt_max_frms"},
-       {"rmac_osized_alt_frms"},
-       {"rmac_jabber_alt_frms"},
-       {"rmac_gt_max_alt_frms"},
-       {"rmac_vlan_frms"},
-       {"rmac_len_discard"},
-       {"rmac_fcs_discard"},
-       {"rmac_pf_discard"},
-       {"rmac_da_discard"},
-       {"rmac_red_discard"},
-       {"rmac_rts_discard"},
-       {"rmac_ingm_full_discard"},
-       {"link_fault_cnt"},
        {"\n DRIVER STATISTICS"},
        {"single_bit_ecc_errs"},
        {"double_bit_ecc_errs"},
-       {"parity_err_cnt"},
-       {"serious_err_cnt"},
-       {"soft_reset_cnt"},
-       {"fifo_full_cnt"},
-       {"ring_full_cnt"},
-       ("alarm_transceiver_temp_high"),
-       ("alarm_transceiver_temp_low"),
-       ("alarm_laser_bias_current_high"),
-       ("alarm_laser_bias_current_low"),
-       ("alarm_laser_output_power_high"),
-       ("alarm_laser_output_power_low"),
-       ("warn_transceiver_temp_high"),
-       ("warn_transceiver_temp_low"),
-       ("warn_laser_bias_current_high"),
-       ("warn_laser_bias_current_low"),
-       ("warn_laser_output_power_high"),
-       ("warn_laser_output_power_low"),
-       ("lro_aggregated_pkts"),
-       ("lro_flush_both_count"),
-       ("lro_out_of_sequence_pkts"),
-       ("lro_flush_due_to_max_pkts"),
-       ("lro_avg_aggr_pkts"),
 };
 
 #define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN
@@ -311,8 +211,10 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
  * the XAUI.
  */
 
+#define SWITCH_SIGN    0xA5A5A5A5A5A5A5A5ULL
 #define        END_SIGN        0x0
-static const u64 herc_act_dtx_cfg[] = {
+
+static u64 herc_act_dtx_cfg[] = {
        /* Set address */
        0x8000051536750000ULL, 0x80000515367500E0ULL,
        /* Write data */
@@ -333,19 +235,37 @@ static const u64 herc_act_dtx_cfg[] = {
        END_SIGN
 };
 
-static const u64 xena_dtx_cfg[] = {
-       /* Set address */
+static u64 xena_mdio_cfg[] = {
+       /* Reset PMA PLL */
+       0xC001010000000000ULL, 0xC0010100000000E0ULL,
+       0xC0010100008000E4ULL,
+       /* Remove Reset from PMA PLL */
+       0xC001010000000000ULL, 0xC0010100000000E0ULL,
+       0xC0010100000000E4ULL,
+       END_SIGN
+};
+
+static u64 xena_dtx_cfg[] = {
        0x8000051500000000ULL, 0x80000515000000E0ULL,
-       /* Write data */
-       0x80000515D9350004ULL, 0x80000515D93500E4ULL,
-       /* Set address */
-       0x8001051500000000ULL, 0x80010515000000E0ULL,
-       /* Write data */
-       0x80010515001E0004ULL, 0x80010515001E00E4ULL,
-       /* Set address */
+       0x80000515D93500E4ULL, 0x8001051500000000ULL,
+       0x80010515000000E0ULL, 0x80010515001E00E4ULL,
        0x8002051500000000ULL, 0x80020515000000E0ULL,
-       /* Write data */
-       0x80020515F2100004ULL, 0x80020515F21000E4ULL,
+       0x80020515F21000E4ULL,
+       /* Set PADLOOPBACKN */
+       0x8002051500000000ULL, 0x80020515000000E0ULL,
+       0x80020515B20000E4ULL, 0x8003051500000000ULL,
+       0x80030515000000E0ULL, 0x80030515B20000E4ULL,
+       0x8004051500000000ULL, 0x80040515000000E0ULL,
+       0x80040515B20000E4ULL, 0x8005051500000000ULL,
+       0x80050515000000E0ULL, 0x80050515B20000E4ULL,
+       SWITCH_SIGN,
+       /* Remove PADLOOPBACKN */
+       0x8002051500000000ULL, 0x80020515000000E0ULL,
+       0x80020515F20000E4ULL, 0x8003051500000000ULL,
+       0x80030515000000E0ULL, 0x80030515F20000E4ULL,
+       0x8004051500000000ULL, 0x80040515000000E0ULL,
+       0x80040515F20000E4ULL, 0x8005051500000000ULL,
+       0x80050515000000E0ULL, 0x80050515F20000E4ULL,
        END_SIGN
 };
 
@@ -353,7 +273,7 @@ static const u64 xena_dtx_cfg[] = {
  * Constants for Fixing the MacAddress problem seen mostly on
  * Alpha machines.
  */
-static const u64 fix_mac[] = {
+static u64 fix_mac[] = {
        0x0060000000000000ULL, 0x0060600000000000ULL,
        0x0040600000000000ULL, 0x0000600000000000ULL,
        0x0020600000000000ULL, 0x0060600000000000ULL,
@@ -371,50 +291,32 @@ static const u64 fix_mac[] = {
        END_SIGN
 };
 
-MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-
 /* Module Loadable parameters. */
-S2IO_PARM_INT(tx_fifo_num, 1);
-S2IO_PARM_INT(rx_ring_num, 1);
-
-
-S2IO_PARM_INT(rx_ring_mode, 1);
-S2IO_PARM_INT(use_continuous_tx_intrs, 1);
-S2IO_PARM_INT(rmac_pause_time, 0x100);
-S2IO_PARM_INT(mc_pause_threshold_q0q3, 187);
-S2IO_PARM_INT(mc_pause_threshold_q4q7, 187);
-S2IO_PARM_INT(shared_splits, 0);
-S2IO_PARM_INT(tmac_util_period, 5);
-S2IO_PARM_INT(rmac_util_period, 5);
-S2IO_PARM_INT(bimodal, 0);
-S2IO_PARM_INT(l3l4hdr_size, 128);
-/* Frequency of Rx desc syncs expressed as power of 2 */
-S2IO_PARM_INT(rxsync_frequency, 3);
-/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
-S2IO_PARM_INT(intr_type, 0);
-/* Large receive offload feature */
-S2IO_PARM_INT(lro, 0);
-/* Max pkts to be aggregated by LRO at one time. If not specified,
- * aggregation happens until we hit max IP pkt size(64K)
- */
-S2IO_PARM_INT(lro_max_pkts, 0xFFFF);
-#ifndef CONFIG_S2IO_NAPI
-S2IO_PARM_INT(indicate_max_pkts, 0);
-#endif
-
+static unsigned int tx_fifo_num = 1;
 static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
-    {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
+    {[0 ...(MAX_TX_FIFOS - 1)] = 0 };
+static unsigned int rx_ring_num = 1;
 static unsigned int rx_ring_sz[MAX_RX_RINGS] =
-    {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
+    {[0 ...(MAX_RX_RINGS - 1)] = };
 static unsigned int rts_frm_len[MAX_RX_RINGS] =
     {[0 ...(MAX_RX_RINGS - 1)] = 0 };
-
-module_param_array(tx_fifo_len, uint, NULL, 0);
-module_param_array(rx_ring_sz, uint, NULL, 0);
-module_param_array(rts_frm_len, uint, NULL, 0);
+static unsigned int rx_ring_mode = 1;
+static unsigned int use_continuous_tx_intrs = 1;
+static unsigned int rmac_pause_time = 65535;
+static unsigned int mc_pause_threshold_q0q3 = 187;
+static unsigned int mc_pause_threshold_q4q7 = 187;
+static unsigned int shared_splits;
+static unsigned int tmac_util_period = 5;
+static unsigned int rmac_util_period = 5;
+static unsigned int bimodal = 0;
+static unsigned int l3l4hdr_size = 128;
+#ifndef CONFIG_S2IO_NAPI
+static unsigned int indicate_max_pkts;
+#endif
+/* Frequency of Rx desc syncs expressed as power of 2 */
+static unsigned int rxsync_frequency = 3;
+/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
+static unsigned int intr_type = 0;
 
 /*
  * S2IO device table.
@@ -477,9 +379,10 @@ static int init_shared_mem(struct s2io_nic *nic)
                size += config->tx_cfg[i].fifo_len;
        }
        if (size > MAX_AVAILABLE_TXDS) {
-               DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, ");
+               DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ",
+                         __FUNCTION__);
                DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
-               return -EINVAL;
+               return FAILURE;
        }
 
        lst_size = (sizeof(TxD_t) * config->max_txds);
@@ -559,7 +462,6 @@ static int init_shared_mem(struct s2io_nic *nic)
        nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL);
        if (!nic->ufo_in_band_v)
                return -ENOMEM;
-       memset(nic->ufo_in_band_v, 0, size);
 
        /* Allocation and initialization of RXDs in Rings */
        size = 0;
@@ -632,6 +534,11 @@ static int init_shared_mem(struct s2io_nic *nic)
                                        rx_blocks->block_dma_addr +
                                        (rxd_size[nic->rxd_mode] * l);
                        }
+
+                       mac_control->rings[i].rx_blocks[j].block_virt_addr =
+                               tmp_v_addr;
+                       mac_control->rings[i].rx_blocks[j].block_dma_addr =
+                               tmp_p_addr;
                }
                /* Interlinking all Rx Blocks */
                for (j = 0; j < blk_cnt; j++) {
@@ -850,21 +757,7 @@ static int s2io_verify_pci_mode(nic_t *nic)
        return mode;
 }
 
-#define NEC_VENID   0x1033
-#define NEC_DEVID   0x0125
-static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
-{
-       struct pci_dev *tdev = NULL;
-       while ((tdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
-               if ((tdev->vendor == NEC_VENID) && (tdev->device == NEC_DEVID)){
-                       if (tdev->bus == s2io_pdev->bus->parent)
-                               return 1;
-               }
-       }
-       return 0;
-}
 
-static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266};
 /**
  * s2io_print_pci_mode -
  */
@@ -881,14 +774,6 @@ static int s2io_print_pci_mode(nic_t *nic)
        if ( val64 & PCI_MODE_UNKNOWN_MODE)
                return -1;      /* Unknown PCI mode */
 
-       config->bus_speed = bus_speed[mode];
-
-       if (s2io_on_nec_bridge(nic->pdev)) {
-               DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n",
-                                                       nic->dev->name);
-               return mode;
-       }
-
        if (val64 & PCI_MODE_32_BITS) {
                DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
        } else {
@@ -898,27 +783,35 @@ static int s2io_print_pci_mode(nic_t *nic)
        switch(mode) {
                case PCI_MODE_PCI_33:
                        DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
+                       config->bus_speed = 33;
                        break;
                case PCI_MODE_PCI_66:
                        DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
+                       config->bus_speed = 133;
                        break;
                case PCI_MODE_PCIX_M1_66:
                        DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
+                       config->bus_speed = 133; /* Herc doubles the clock rate */
                        break;
                case PCI_MODE_PCIX_M1_100:
                        DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
+                       config->bus_speed = 200;
                        break;
                case PCI_MODE_PCIX_M1_133:
                        DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
+                       config->bus_speed = 266;
                        break;
                case PCI_MODE_PCIX_M2_66:
                        DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
+                       config->bus_speed = 133;
                        break;
                case PCI_MODE_PCIX_M2_100:
                        DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
+                       config->bus_speed = 200;
                        break;
                case PCI_MODE_PCIX_M2_133:
                        DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
+                       config->bus_speed = 266;
                        break;
                default:
                        return -1;      /* Unsupported bus speed */
@@ -946,7 +839,7 @@ static int init_nic(struct s2io_nic *nic)
        int i, j;
        mac_info_t *mac_control;
        struct config_param *config;
-       int dtx_cnt = 0;
+       int mdio_cnt = 0, dtx_cnt = 0;
        unsigned long long mem_share;
        int mem_size;
 
@@ -993,6 +886,20 @@ static int init_nic(struct s2io_nic *nic)
        val64 = dev->mtu;
        writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
 
+       /*
+        * Configuring the XAUI Interface of Xena.
+        * ***************************************
+        * To Configure the Xena's XAUI, one has to write a series
+        * of 64 bit values into two registers in a particular
+        * sequence. Hence a macro 'SWITCH_SIGN' has been defined
+        * which will be defined in the array of configuration values
+        * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
+        * to switch writing from one regsiter to another. We continue
+        * writing these values until we encounter the 'END_SIGN' macro.
+        * For example, After making a series of 21 writes into
+        * dtx_control register the 'SWITCH_SIGN' appears and hence we
+        * start writing into mdio_control until we encounter END_SIGN.
+        */
        if (nic->device_type & XFRAME_II_DEVICE) {
                while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
                        SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
@@ -1002,11 +909,35 @@ static int init_nic(struct s2io_nic *nic)
                        dtx_cnt++;
                }
        } else {
-               while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
-                       SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
-                                         &bar0->dtx_control, UF);
-                       val64 = readq(&bar0->dtx_control);
-                       dtx_cnt++;
+               while (1) {
+                     dtx_cfg:
+                       while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
+                               if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
+                                       dtx_cnt++;
+                                       goto mdio_cfg;
+                               }
+                               SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
+                                                 &bar0->dtx_control, UF);
+                               val64 = readq(&bar0->dtx_control);
+                               dtx_cnt++;
+                       }
+                     mdio_cfg:
+                       while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
+                               if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
+                                       mdio_cnt++;
+                                       goto dtx_cfg;
+                               }
+                               SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
+                                                 &bar0->mdio_control, UF);
+                               val64 = readq(&bar0->mdio_control);
+                               mdio_cnt++;
+                       }
+                       if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
+                           (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
+                               break;
+                       } else {
+                               goto dtx_cfg;
+                       }
                }
        }
 
@@ -1048,6 +979,11 @@ static int init_nic(struct s2io_nic *nic)
                }
        }
 
+       /* Enable Tx FIFO partition 0. */
+       val64 = readq(&bar0->tx_fifo_partition_0);
+       val64 |= BIT(0);        /* To enable the FIFO partition. */
+       writeq(val64, &bar0->tx_fifo_partition_0);
+
        /*
         * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
         * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
@@ -1226,11 +1162,6 @@ static int init_nic(struct s2io_nic *nic)
                break;
        }
 
-       /* Enable all configured Tx FIFO partitions */
-       val64 = readq(&bar0->tx_fifo_partition_0);
-       val64 |= (TX_FIFO_PARTITION_EN);
-       writeq(val64, &bar0->tx_fifo_partition_0);
-
        /* Filling the Rx round robin registers as per the
         * number of Rings and steering based on QoS.
          */
@@ -1545,19 +1476,6 @@ static int init_nic(struct s2io_nic *nic)
        writel((u32) (val64 >> 32), (add + 4));
        val64 = readq(&bar0->mac_cfg);
 
-       /* Enable FCS stripping by adapter */
-       add = &bar0->mac_cfg;
-       val64 = readq(&bar0->mac_cfg);
-       val64 |= MAC_CFG_RMAC_STRIP_FCS;
-       if (nic->device_type == XFRAME_II_DEVICE)
-               writeq(val64, &bar0->mac_cfg);
-       else {
-               writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
-               writel((u32) (val64), add);
-               writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
-               writel((u32) (val64 >> 32), (add + 4));
-       }
-
        /*
         * Set the time value to be inserted in the pause frame
         * generated by xena.
@@ -1599,26 +1517,19 @@ static int init_nic(struct s2io_nic *nic)
        val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
        writeq(val64, &bar0->pic_control);
 
-       if (nic->config.bus_speed == 266) {
-               writeq(TXREQTO_VAL(0x7f) | TXREQTO_EN, &bar0->txreqtimeout);
-               writeq(0x0, &bar0->read_retry_delay);
-               writeq(0x0, &bar0->write_retry_delay);
-       }
-
        /*
         * Programming the Herc to split every write transaction
         * that does not start on an ADB to reduce disconnects.
         */
        if (nic->device_type == XFRAME_II_DEVICE) {
-               val64 = EXT_REQ_EN | MISC_LINK_STABILITY_PRD(3);
-               writeq(val64, &bar0->misc_control);
-               val64 = readq(&bar0->pic_control2);
-               val64 &= ~(BIT(13)|BIT(14)|BIT(15));
-               writeq(val64, &bar0->pic_control2);
+               val64 = WREQ_SPLIT_MASK_SET_MASK(255);
+               writeq(val64, &bar0->wreq_split_mask);
        }
-       if (strstr(nic->product_name, "CX4")) {
-               val64 = TMAC_AVG_IPG(0x17);
-               writeq(val64, &bar0->tmac_avg_ipg);
+
+       /* Setting Link stability period to 64 ms */ 
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               val64 = MISC_LINK_STABILITY_PRD(3);
+               writeq(val64, &bar0->misc_control);
        }
 
        return SUCCESS;
@@ -1663,7 +1574,7 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
                        writeq(temp64, &bar0->general_int_mask);
                        /*
                         * If Hercules adapter enable GPIO otherwise
-                        * disable all PCIX, Flash, MDIO, IIC and GPIO
+                        * disabled all PCIX, Flash, MDIO, IIC and GPIO
                         * interrupts for now.
                         * TODO
                         */
@@ -1989,6 +1900,7 @@ static int start_nic(struct s2io_nic *nic)
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        struct net_device *dev = nic->dev;
        register u64 val64 = 0;
+       u16 interruptible;
        u16 subid, i;
        mac_info_t *mac_control;
        struct config_param *config;
@@ -2008,10 +1920,6 @@ static int start_nic(struct s2io_nic *nic)
                        val64 |= PRC_CTRL_RC_ENABLED;
                else
                        val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3;
-               if (nic->device_type == XFRAME_II_DEVICE)
-                       val64 |= PRC_CTRL_GROUP_READS;
-               val64 &= ~PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF);
-               val64 |= PRC_CTRL_RXD_BACKOFF_INTERVAL(0x1000);
                writeq(val64, &bar0->prc_ctrl_n[i]);
        }
 
@@ -2059,6 +1967,16 @@ static int start_nic(struct s2io_nic *nic)
                return FAILURE;
        }
 
+       /*  Enable select interrupts */
+       if (nic->intr_type != INTA)
+               en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
+       else {
+               interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
+               interruptible |= TX_PIC_INTR | RX_PIC_INTR;
+               interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+               en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
+       }
+
        /*
         * With some switches, link might be already up at this point.
         * Because of this weird behavior, when we enable laser,
@@ -2072,13 +1990,6 @@ static int start_nic(struct s2io_nic *nic)
        val64 |= ADAPTER_EOI_TX_ON;
        writeq(val64, &bar0->adapter_control);
 
-       if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
-               /*
-                * Dont see link state interrupts initally on some switches,
-                * so directly scheduling the link state task here.
-                */
-               schedule_work(&nic->set_link_task);
-       }
        /* SXE-002: Initialize link and activity LED */
        subid = nic->pdev->subsystem_device;
        if (((subid & 0xFF) >= 0x07) &&
@@ -2090,6 +2001,12 @@ static int start_nic(struct s2io_nic *nic)
                writeq(val64, (void __iomem *)bar0 + 0x2700);
        }
 
+       /*
+        * Don't see link state interrupts on certain switches, so
+        * directly scheduling a link state task from here.
+        */
+       schedule_work(&nic->set_link_task);
+
        return SUCCESS;
 }
 /**
@@ -2132,7 +2049,7 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in
                                       frag->size, PCI_DMA_TODEVICE);
                }
        }
-       memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds));
+       txdlp->Host_Control = 0;
        return(skb);
 }
 
@@ -2189,7 +2106,7 @@ static void stop_nic(struct s2io_nic *nic)
 {
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        register u64 val64 = 0;
-       u16 interruptible;
+       u16 interruptible, i;
        mac_info_t *mac_control;
        struct config_param *config;
 
@@ -2202,13 +2119,15 @@ static void stop_nic(struct s2io_nic *nic)
        interruptible |= TX_MAC_INTR | RX_MAC_INTR;
        en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
 
-       /* Clearing Adapter_En bit of ADAPTER_CONTROL Register */
-       val64 = readq(&bar0->adapter_control);
-       val64 &= ~(ADAPTER_CNTL_EN);
-       writeq(val64, &bar0->adapter_control);
+       /*  Disable PRCs */
+       for (i = 0; i < config->rx_ring_num; i++) {
+               val64 = readq(&bar0->prc_ctrl_n[i]);
+               val64 &= ~((u64) PRC_CTRL_RC_ENABLED);
+               writeq(val64, &bar0->prc_ctrl_n[i]);
+       }
 }
 
-static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb)
+int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb)
 {
        struct net_device *dev = nic->dev;
        struct sk_buff *frag_list;
@@ -2284,12 +2203,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
        alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
            atomic_read(&nic->rx_bufs_left[ring_no]);
 
-       block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index;
-       off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
        while (alloc_tab < alloc_cnt) {
                block_no = mac_control->rings[ring_no].rx_curr_put_info.
                    block_index;
+               block_no1 = mac_control->rings[ring_no].rx_curr_get_info.
+                   block_index;
                off = mac_control->rings[ring_no].rx_curr_put_info.offset;
+               off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
 
                rxdp = mac_control->rings[ring_no].
                                rx_blocks[block_no].rxds[off].virt_addr;
@@ -2359,9 +2279,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                        memset(rxdp, 0, sizeof(RxD1_t));
                        skb_reserve(skb, NET_IP_ALIGN);
                        ((RxD1_t*)rxdp)->Buffer0_ptr = pci_map_single
-                           (nic->pdev, skb->data, size - NET_IP_ALIGN,
-                               PCI_DMA_FROMDEVICE);
-                       rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN);
+                           (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE);
+                       rxdp->Control_2 &= (~MASK_BUFFER0_SIZE_1);
+                       rxdp->Control_2 |= SET_BUFFER0_SIZE_1(size);
 
                } else if (nic->rxd_mode >= RXD_MODE_3A) {
                        /*
@@ -2384,14 +2304,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                        skb->data = (void *) (unsigned long)tmp;
                        skb->tail = (void *) (unsigned long)tmp;
 
-                       if (!(((RxD3_t*)rxdp)->Buffer0_ptr))
-                               ((RxD3_t*)rxdp)->Buffer0_ptr =
-                                  pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
+                       ((RxD3_t*)rxdp)->Buffer0_ptr =
+                           pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
                                           PCI_DMA_FROMDEVICE);
-                       else
-                               pci_dma_sync_single_for_device(nic->pdev,
-                                   (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr,
-                                   BUF0_LEN, PCI_DMA_FROMDEVICE);
                        rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
                        if (nic->rxd_mode == RXD_MODE_3B) {
                                /* Two buffer mode */
@@ -2404,13 +2319,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                                (nic->pdev, skb->data, dev->mtu + 4,
                                                PCI_DMA_FROMDEVICE);
 
-                               /* Buffer-1 will be dummy buffer. Not used */
-                               if (!(((RxD3_t*)rxdp)->Buffer1_ptr)) {
-                                       ((RxD3_t*)rxdp)->Buffer1_ptr =
-                                               pci_map_single(nic->pdev, 
-                                               ba->ba_1, BUF1_LEN,
-                                               PCI_DMA_FROMDEVICE);
-                               }
+                               /* Buffer-1 will be dummy buffer not used */
+                               ((RxD3_t*)rxdp)->Buffer1_ptr =
+                               pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN,
+                                       PCI_DMA_FROMDEVICE);
                                rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
                                rxdp->Control_2 |= SET_BUFFER2_SIZE_3
                                                                (dev->mtu + 4);
@@ -2576,7 +2488,7 @@ static int s2io_poll(struct net_device *dev, int *budget)
        mac_info_t *mac_control;
        struct config_param *config;
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
-       u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
+       u64 val64;
        int i;
 
        atomic_inc(&nic->isr_cnt);
@@ -2588,8 +2500,8 @@ static int s2io_poll(struct net_device *dev, int *budget)
                nic->pkts_to_process = dev->quota;
        org_pkts_to_process = nic->pkts_to_process;
 
+       val64 = readq(&bar0->rx_traffic_int);
        writeq(val64, &bar0->rx_traffic_int);
-       val64 = readl(&bar0->rx_traffic_int);
 
        for (i = 0; i < config->rx_ring_num; i++) {
                rx_intr_handler(&mac_control->rings[i]);
@@ -2614,8 +2526,7 @@ static int s2io_poll(struct net_device *dev, int *budget)
                }
        }
        /* Re enable the Rx interrupts. */
-       writeq(0x0, &bar0->rx_traffic_mask);
-       val64 = readl(&bar0->rx_traffic_mask);
+       en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS);
        atomic_dec(&nic->isr_cnt);
        return 0;
 
@@ -2635,58 +2546,6 @@ no_rx:
 }
 #endif
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * s2io_netpoll - netpoll event handler entry point
- * @dev : pointer to the device structure.
- * Description:
- *     This function will be called by upper layer to check for events on the
- * interface in situations where interrupts are disabled. It is used for
- * specific in-kernel networking tasks, such as remote consoles and kernel
- * debugging over the network (example netdump in RedHat).
- */
-static void s2io_netpoll(struct net_device *dev)
-{
-       nic_t *nic = dev->priv;
-       mac_info_t *mac_control;
-       struct config_param *config;
-       XENA_dev_config_t __iomem *bar0 = nic->bar0;
-       u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
-       int i;
-
-       disable_irq(dev->irq);
-
-       atomic_inc(&nic->isr_cnt);
-       mac_control = &nic->mac_control;
-       config = &nic->config;
-
-       writeq(val64, &bar0->rx_traffic_int);
-       writeq(val64, &bar0->tx_traffic_int);
-
-       /* we need to free up the transmitted skbufs or else netpoll will 
-        * run out of skbs and will fail and eventually netpoll application such
-        * as netdump will fail.
-        */
-       for (i = 0; i < config->tx_fifo_num; i++)
-               tx_intr_handler(&mac_control->fifos[i]);
-
-       /* check for received packet and indicate up to network */
-       for (i = 0; i < config->rx_ring_num; i++)
-               rx_intr_handler(&mac_control->rings[i]);
-
-       for (i = 0; i < config->rx_ring_num; i++) {
-               if (fill_rx_buffers(nic, i) == -ENOMEM) {
-                       DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
-                       DBG_PRINT(ERR_DBG, " in Rx Netpoll!!\n");
-                       break;
-               }
-       }
-       atomic_dec(&nic->isr_cnt);
-       enable_irq(dev->irq);
-       return;
-}
-#endif
-
 /**
  *  rx_intr_handler - Rx interrupt handler
  *  @nic: device private variable.
@@ -2710,8 +2569,6 @@ static void rx_intr_handler(ring_info_t *ring_data)
 #ifndef CONFIG_S2IO_NAPI
        int pkt_cnt = 0;
 #endif
-       int i;
-
        spin_lock(&nic->rx_lock);
        if (atomic_read(&nic->card_state) == CARD_DOWN) {
                DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
@@ -2737,7 +2594,7 @@ static void rx_intr_handler(ring_info_t *ring_data)
                /* If your are next to put index then it's FIFO full condition */
                if ((get_block == put_block) &&
                    (get_info.offset + 1) == put_info.offset) {
-                       DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name);
+                       DBG_PRINT(ERR_DBG, "%s: Ring Full\n",dev->name);
                        break;
                }
                skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
@@ -2757,15 +2614,18 @@ static void rx_intr_handler(ring_info_t *ring_data)
                                 HEADER_SNAP_SIZE,
                                 PCI_DMA_FROMDEVICE);
                } else if (nic->rxd_mode == RXD_MODE_3B) {
-                       pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
+                       pci_unmap_single(nic->pdev, (dma_addr_t)
                                 ((RxD3_t*)rxdp)->Buffer0_ptr,
                                 BUF0_LEN, PCI_DMA_FROMDEVICE);
+                       pci_unmap_single(nic->pdev, (dma_addr_t)
+                                ((RxD3_t*)rxdp)->Buffer1_ptr,
+                                BUF1_LEN, PCI_DMA_FROMDEVICE);
                        pci_unmap_single(nic->pdev, (dma_addr_t)
                                 ((RxD3_t*)rxdp)->Buffer2_ptr,
                                 dev->mtu + 4,
                                 PCI_DMA_FROMDEVICE);
                } else {
-                       pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
+                       pci_unmap_single(nic->pdev, (dma_addr_t)
                                         ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN,
                                         PCI_DMA_FROMDEVICE);
                        pci_unmap_single(nic->pdev, (dma_addr_t)
@@ -2776,7 +2636,6 @@ static void rx_intr_handler(ring_info_t *ring_data)
                                         ((RxD3_t*)rxdp)->Buffer2_ptr,
                                         dev->mtu, PCI_DMA_FROMDEVICE);
                }
-               prefetch(skb->data);
                rx_osm_handler(ring_data, rxdp);
                get_info.offset++;
                ring_data->rx_curr_get_info.offset = get_info.offset;
@@ -2802,18 +2661,6 @@ static void rx_intr_handler(ring_info_t *ring_data)
                        break;
 #endif
        }
-       if (nic->lro) {
-               /* Clear all LRO sessions before exiting */
-               for (i=0; i<MAX_LRO_SESSIONS; i++) {
-                       lro_t *lro = &nic->lro0_n[i];
-                       if (lro->in_use) {
-                               update_L3L4_header(nic, lro);
-                               queue_rx_frame(lro->parent);
-                               clear_lro_session(lro);
-                       }
-               }
-       }
-
        spin_unlock(&nic->rx_lock);
 }
 
@@ -2848,10 +2695,6 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
                if (txdlp->Control_1 & TXD_T_CODE) {
                        unsigned long long err;
                        err = txdlp->Control_1 & TXD_T_CODE;
-                       if (err & 0x1) {
-                               nic->mac_control.stats_info->sw_stat.
-                                               parity_err_cnt++;
-                       }
                        if ((err >> 48) == 0xA) {
                                DBG_PRINT(TX_DBG, "TxD returned due \
 to loss of link\n");
@@ -2875,8 +2718,7 @@ to loss of link\n");
                dev_kfree_skb_irq(skb);
 
                get_info.offset++;
-               if (get_info.offset == get_info.fifo_len + 1)
-                       get_info.offset = 0;
+               get_info.offset %= get_info.fifo_len + 1;
                txdlp = (TxD_t *) fifo_data->list_info
                    [get_info.offset].list_virt_addr;
                fifo_data->tx_curr_get_info.offset =
@@ -2889,256 +2731,6 @@ to loss of link\n");
        spin_unlock(&nic->tx_lock);
 }
 
-/**
- *  s2io_mdio_write - Function to write in to MDIO registers
- *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
- *  @addr     : address value
- *  @value    : data value
- *  @dev      : pointer to net_device structure
- *  Description:
- *  This function is used to write values to the MDIO registers
- *  NONE
- */
-static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev)
-{
-       u64 val64 = 0x0;
-       nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
-
-       //address transaction
-       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-                       | MDIO_MMD_DEV_ADDR(mmd_type)
-                       | MDIO_MMS_PRT_ADDR(0x0);
-       writeq(val64, &bar0->mdio_control);
-       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
-       writeq(val64, &bar0->mdio_control);
-       udelay(100);
-
-       //Data transaction
-       val64 = 0x0;
-       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-                       | MDIO_MMD_DEV_ADDR(mmd_type)
-                       | MDIO_MMS_PRT_ADDR(0x0)
-                       | MDIO_MDIO_DATA(value)
-                       | MDIO_OP(MDIO_OP_WRITE_TRANS);
-       writeq(val64, &bar0->mdio_control);
-       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
-       writeq(val64, &bar0->mdio_control);
-       udelay(100);
-
-       val64 = 0x0;
-       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-       | MDIO_MMD_DEV_ADDR(mmd_type)
-       | MDIO_MMS_PRT_ADDR(0x0)
-       | MDIO_OP(MDIO_OP_READ_TRANS);
-       writeq(val64, &bar0->mdio_control);
-       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
-       writeq(val64, &bar0->mdio_control);
-       udelay(100);
-
-}
-
-/**
- *  s2io_mdio_read - Function to write in to MDIO registers
- *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
- *  @addr     : address value
- *  @dev      : pointer to net_device structure
- *  Description:
- *  This function is used to read values to the MDIO registers
- *  NONE
- */
-static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
-{
-       u64 val64 = 0x0;
-       u64 rval64 = 0x0;
-       nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
-
-       /* address transaction */
-       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-                       | MDIO_MMD_DEV_ADDR(mmd_type)
-                       | MDIO_MMS_PRT_ADDR(0x0);
-       writeq(val64, &bar0->mdio_control);
-       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
-       writeq(val64, &bar0->mdio_control);
-       udelay(100);
-
-       /* Data transaction */
-       val64 = 0x0;
-       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-                       | MDIO_MMD_DEV_ADDR(mmd_type)
-                       | MDIO_MMS_PRT_ADDR(0x0)
-                       | MDIO_OP(MDIO_OP_READ_TRANS);
-       writeq(val64, &bar0->mdio_control);
-       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
-       writeq(val64, &bar0->mdio_control);
-       udelay(100);
-
-       /* Read the value from regs */
-       rval64 = readq(&bar0->mdio_control);
-       rval64 = rval64 & 0xFFFF0000;
-       rval64 = rval64 >> 16;
-       return rval64;
-}
-/**
- *  s2io_chk_xpak_counter - Function to check the status of the xpak counters
- *  @counter      : couter value to be updated
- *  @flag         : flag to indicate the status
- *  @type         : counter type
- *  Description:
- *  This function is to check the status of the xpak counters value
- *  NONE
- */
-
-static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type)
-{
-       u64 mask = 0x3;
-       u64 val64;
-       int i;
-       for(i = 0; i <index; i++)
-               mask = mask << 0x2;
-
-       if(flag > 0)
-       {
-               *counter = *counter + 1;
-               val64 = *regs_stat & mask;
-               val64 = val64 >> (index * 0x2);
-               val64 = val64 + 1;
-               if(val64 == 3)
-               {
-                       switch(type)
-                       {
-                       case 1:
-                               DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
-                                         "service. Excessive temperatures may "
-                                         "result in premature transceiver "
-                                         "failure \n");
-                       break;
-                       case 2:
-                               DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
-                                         "service Excessive bias currents may "
-                                         "indicate imminent laser diode "
-                                         "failure \n");
-                       break;
-                       case 3:
-                               DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
-                                         "service Excessive laser output "
-                                         "power may saturate far-end "
-                                         "receiver\n");
-                       break;
-                       default:
-                               DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm "
-                                         "type \n");
-                       }
-                       val64 = 0x0;
-               }
-               val64 = val64 << (index * 0x2);
-               *regs_stat = (*regs_stat & (~mask)) | (val64);
-
-       } else {
-               *regs_stat = *regs_stat & (~mask);
-       }
-}
-
-/**
- *  s2io_updt_xpak_counter - Function to update the xpak counters
- *  @dev         : pointer to net_device struct
- *  Description:
- *  This function is to upate the status of the xpak counters value
- *  NONE
- */
-static void s2io_updt_xpak_counter(struct net_device *dev)
-{
-       u16 flag  = 0x0;
-       u16 type  = 0x0;
-       u16 val16 = 0x0;
-       u64 val64 = 0x0;
-       u64 addr  = 0x0;
-
-       nic_t *sp = dev->priv;
-       StatInfo_t *stat_info = sp->mac_control.stats_info;
-
-       /* Check the communication with the MDIO slave */
-       addr = 0x0000;
-       val64 = 0x0;
-       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
-       if((val64 == 0xFFFF) || (val64 == 0x0000))
-       {
-               DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - "
-                         "Returned %llx\n", (unsigned long long)val64);
-               return;
-       }
-
-       /* Check for the expecte value of 2040 at PMA address 0x0000 */
-       if(val64 != 0x2040)
-       {
-               DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - ");
-               DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n",
-                         (unsigned long long)val64);
-               return;
-       }
-
-       /* Loading the DOM register to MDIO register */
-       addr = 0xA100;
-       s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev);
-       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
-
-       /* Reading the Alarm flags */
-       addr = 0xA070;
-       val64 = 0x0;
-       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
-
-       flag = CHECKBIT(val64, 0x7);
-       type = 1;
-       s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high,
-                               &stat_info->xpak_stat.xpak_regs_stat,
-                               0x0, flag, type);
-
-       if(CHECKBIT(val64, 0x6))
-               stat_info->xpak_stat.alarm_transceiver_temp_low++;
-
-       flag = CHECKBIT(val64, 0x3);
-       type = 2;
-       s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high,
-                               &stat_info->xpak_stat.xpak_regs_stat,
-                               0x2, flag, type);
-
-       if(CHECKBIT(val64, 0x2))
-               stat_info->xpak_stat.alarm_laser_bias_current_low++;
-
-       flag = CHECKBIT(val64, 0x1);
-       type = 3;
-       s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high,
-                               &stat_info->xpak_stat.xpak_regs_stat,
-                               0x4, flag, type);
-
-       if(CHECKBIT(val64, 0x0))
-               stat_info->xpak_stat.alarm_laser_output_power_low++;
-
-       /* Reading the Warning flags */
-       addr = 0xA074;
-       val64 = 0x0;
-       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
-
-       if(CHECKBIT(val64, 0x7))
-               stat_info->xpak_stat.warn_transceiver_temp_high++;
-
-       if(CHECKBIT(val64, 0x6))
-               stat_info->xpak_stat.warn_transceiver_temp_low++;
-
-       if(CHECKBIT(val64, 0x3))
-               stat_info->xpak_stat.warn_laser_bias_current_high++;
-
-       if(CHECKBIT(val64, 0x2))
-               stat_info->xpak_stat.warn_laser_bias_current_low++;
-
-       if(CHECKBIT(val64, 0x1))
-               stat_info->xpak_stat.warn_laser_output_power_high++;
-
-       if(CHECKBIT(val64, 0x0))
-               stat_info->xpak_stat.warn_laser_output_power_low++;
-}
-
 /**
  *  alarm_intr_handler - Alarm Interrrupt handler
  *  @nic: device private variable
@@ -3156,18 +2748,6 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        struct net_device *dev = (struct net_device *) nic->dev;
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        register u64 val64 = 0, err_reg = 0;
-       u64 cnt;
-       int i;
-       nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
-       /* Handling the XPAK counters update */
-       if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
-               /* waiting for an hour */
-               nic->mac_control.stats_info->xpak_stat.xpak_timer_count++;
-       } else {
-               s2io_updt_xpak_counter(dev);
-               /* reset the count to zero */
-               nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0;
-       }
 
        /* Handling link status change error Intr */
        if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
@@ -3194,8 +2774,6 @@ static void alarm_intr_handler(struct s2io_nic *nic)
                                             MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
                                        netif_stop_queue(dev);
                                        schedule_work(&nic->rst_timer_task);
-                                       nic->mac_control.stats_info->sw_stat.
-                                                       soft_reset_cnt++;
                                }
                        }
                } else {
@@ -3207,13 +2785,11 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        /* In case of a serious error, the device will be Reset. */
        val64 = readq(&bar0->serr_source);
        if (val64 & SERR_SOURCE_ANY) {
-               nic->mac_control.stats_info->sw_stat.serious_err_cnt++;
                DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
                DBG_PRINT(ERR_DBG, "serious error %llx!!\n", 
                          (unsigned long long)val64);
                netif_stop_queue(dev);
                schedule_work(&nic->rst_timer_task);
-               nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
        }
 
        /*
@@ -3231,35 +2807,6 @@ static void alarm_intr_handler(struct s2io_nic *nic)
                ac = readq(&bar0->adapter_control);
                schedule_work(&nic->set_link_task);
        }
-       /* Check for data parity error */
-       val64 = readq(&bar0->pic_int_status);
-       if (val64 & PIC_INT_GPIO) {
-               val64 = readq(&bar0->gpio_int_reg);
-               if (val64 & GPIO_INT_REG_DP_ERR_INT) {
-                       nic->mac_control.stats_info->sw_stat.parity_err_cnt++;
-                       schedule_work(&nic->rst_timer_task);
-                       nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
-               }
-       }
-
-       /* Check for ring full counter */
-       if (nic->device_type & XFRAME_II_DEVICE) {
-               val64 = readq(&bar0->ring_bump_counter1);
-               for (i=0; i<4; i++) {
-                       cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
-                       cnt >>= 64 - ((i+1)*16);
-                       nic->mac_control.stats_info->sw_stat.ring_full_cnt
-                               += cnt;
-               }
-
-               val64 = readq(&bar0->ring_bump_counter2);
-               for (i=0; i<4; i++) {
-                       cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
-                       cnt >>= 64 - ((i+1)*16);
-                       nic->mac_control.stats_info->sw_stat.ring_full_cnt
-                               += cnt;
-               }
-       }
 
        /* Other type of interrupts are not being handled now,  TODO */
 }
@@ -3275,26 +2822,23 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(void *addr, u64 busy_bit)
+static int wait_for_cmd_complete(nic_t * sp)
 {
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
        int ret = FAILURE, cnt = 0;
        u64 val64;
 
        while (TRUE) {
-               val64 = readq(addr);
-               if (!(val64 & busy_bit)) {
+               val64 = readq(&bar0->rmac_addr_cmd_mem);
+               if (!(val64 & RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
                        ret = SUCCESS;
                        break;
                }
-
-               if(in_interrupt())
-                       mdelay(50);
-               else
-                       msleep(50);
-
+               msleep(50);
                if (cnt++ > 10)
                        break;
        }
+
        return ret;
 }
 
@@ -3308,7 +2852,7 @@ static int wait_for_cmd_complete(void *addr, u64 busy_bit)
  *  void.
  */
 
-static void s2io_reset(nic_t * sp)
+void s2io_reset(nic_t * sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64;
@@ -3333,9 +2877,6 @@ static void s2io_reset(nic_t * sp)
         * PCI write to sw_reset register is done by this time.
         */
        msleep(250);
-       if (strstr(sp->product_name, "CX4")) {
-               msleep(750);
-       }
 
        /* Restore the PCI state saved during initialization. */
        pci_restore_state(sp->pdev);
@@ -3353,7 +2894,7 @@ static void s2io_reset(nic_t * sp)
 
        /* Clear certain PCI/PCI-X fields after reset */
        if (sp->device_type == XFRAME_II_DEVICE) {
-               /* Clear "detected parity error" bit */
+               /* Clear parity err detect bit */
                pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);
 
                /* Clearing PCIX Ecc status register */
@@ -3399,7 +2940,7 @@ static void s2io_reset(nic_t * sp)
  *  SUCCESS on success and FAILURE on failure.
  */
 
-static int s2io_set_swapper(nic_t * sp)
+int s2io_set_swapper(nic_t * sp)
 {
        struct net_device *dev = sp->dev;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -3548,13 +3089,13 @@ static int wait_for_msix_trans(nic_t *nic, int i)
        return ret;
 }
 
-static void restore_xmsi_data(nic_t *nic)
+void restore_xmsi_data(nic_t *nic)
 {
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 val64;
        int i;
 
-       for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
                writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
                writeq(nic->msix_info[i].data, &bar0->xmsi_data);
                val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
@@ -3573,7 +3114,7 @@ static void store_xmsi_data(nic_t *nic)
        int i;
 
        /* Store and display */
-       for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
+       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
                val64 = (BIT(15) | vBIT(i, 26, 6));
                writeq(val64, &bar0->xmsi_access);
                if (wait_for_msix_trans(nic, i)) {
@@ -3639,7 +3180,7 @@ int s2io_enable_msi(nic_t *nic)
        return 0;
 }
 
-static int s2io_enable_msi_x(nic_t *nic)
+int s2io_enable_msi_x(nic_t *nic)
 {
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 tx_mat, rx_mat;
@@ -3701,24 +3242,15 @@ static int s2io_enable_msi_x(nic_t *nic)
                writeq(tx_mat, &bar0->tx_mat0_n[7]);
        }
 
-       nic->avail_msix_vectors = 0;
        ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
-       /* We fail init if error or we get less vectors than min required */
-       if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) {
-               nic->avail_msix_vectors = ret;
-               ret = pci_enable_msix(nic->pdev, nic->entries, ret);
-       }
        if (ret) {
                DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
                kfree(nic->entries);
                kfree(nic->s2io_entries);
                nic->entries = NULL;
                nic->s2io_entries = NULL;
-               nic->avail_msix_vectors = 0;
                return -ENOMEM;
        }
-       if (!nic->avail_msix_vectors)
-               nic->avail_msix_vectors = MAX_REQUESTED_MSI_X;
 
        /*
         * To enable MSI-X, MSI also needs to be enabled, due to a bug
@@ -3751,6 +3283,8 @@ static int s2io_open(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        int err = 0;
+       int i;
+       u16 msi_control; /* Temp variable */
 
        /*
         * Make sure you have link off by default every time
@@ -3760,23 +3294,98 @@ static int s2io_open(struct net_device *dev)
        sp->last_link_state = 0;
 
        /* Initialize H/W and enable interrupts */
-       err = s2io_card_up(sp);
-       if (err) {
+       if (s2io_card_up(sp)) {
                DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
                          dev->name);
+               err = -ENODEV;
                goto hw_init_failed;
        }
 
-       if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
+       /* Store the values of the MSIX table in the nic_t structure */
+       store_xmsi_data(sp);
+
+       /* After proper initialization of H/W, register ISR */
+       if (sp->intr_type == MSI) {
+               err = request_irq((int) sp->pdev->irq, s2io_msi_handle, 
+                       SA_SHIRQ, sp->name, dev);
+               if (err) {
+                       DBG_PRINT(ERR_DBG, "%s: MSI registration \
+failed\n", dev->name);
+                       goto isr_registration_failed;
+               }
+       }
+       if (sp->intr_type == MSI_X) {
+               for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
+                       if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
+                               sprintf(sp->desc1, "%s:MSI-X-%d-TX",
+                                       dev->name, i);
+                               err = request_irq(sp->entries[i].vector,
+                                         s2io_msix_fifo_handle, 0, sp->desc1,
+                                         sp->s2io_entries[i].arg);
+                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1, 
+                                   (unsigned long long)sp->msix_info[i].addr);
+                       } else {
+                               sprintf(sp->desc2, "%s:MSI-X-%d-RX",
+                                       dev->name, i);
+                               err = request_irq(sp->entries[i].vector,
+                                         s2io_msix_ring_handle, 0, sp->desc2,
+                                         sp->s2io_entries[i].arg);
+                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2, 
+                                    (unsigned long long)sp->msix_info[i].addr);
+                       }
+                       if (err) {
+                               DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
+failed\n", dev->name, i);
+                               DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
+                               goto isr_registration_failed;
+                       }
+                       sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
+               }
+       }
+       if (sp->intr_type == INTA) {
+               err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
+                               sp->name, dev);
+               if (err) {
+                       DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
+                                 dev->name);
+                       goto isr_registration_failed;
+               }
+       }
+
+       if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
                DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n");
-               s2io_card_down(sp);
                err = -ENODEV;
-               goto hw_init_failed;
+               goto setting_mac_address_failed;
        }
 
        netif_start_queue(dev);
        return 0;
 
+setting_mac_address_failed:
+       if (sp->intr_type != MSI_X)
+               free_irq(sp->pdev->irq, dev);
+isr_registration_failed:
+       del_timer_sync(&sp->alarm_timer);
+       if (sp->intr_type == MSI_X) {
+               if (sp->device_type == XFRAME_II_DEVICE) {
+                       for (i=1; (sp->s2io_entries[i].in_use == 
+                               MSIX_REGISTERED_SUCCESS); i++) {
+                               int vector = sp->entries[i].vector;
+                               void *arg = sp->s2io_entries[i].arg;
+
+                               free_irq(vector, arg);
+                       }
+                       pci_disable_msix(sp->pdev);
+
+                       /* Temp */
+                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+                       msi_control &= 0xFFFE; /* Disable MSI */
+                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+               }
+       }
+       else if (sp->intr_type == MSI)
+               pci_disable_msi(sp->pdev);
+       s2io_reset(sp);
 hw_init_failed:
        if (sp->intr_type == MSI_X) {
                if (sp->entries)
@@ -3803,12 +3412,35 @@ hw_init_failed:
 static int s2io_close(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
+       int i;
+       u16 msi_control;
 
        flush_scheduled_work();
        netif_stop_queue(dev);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
+       if (sp->intr_type == MSI_X) {
+               if (sp->device_type == XFRAME_II_DEVICE) {
+                       for (i=1; (sp->s2io_entries[i].in_use == 
+                                       MSIX_REGISTERED_SUCCESS); i++) {
+                               int vector = sp->entries[i].vector;
+                               void *arg = sp->s2io_entries[i].arg;
+
+                               free_irq(vector, arg);
+                       }
+                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+                       msi_control &= 0xFFFE; /* Disable MSI */
+                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+                       pci_disable_msix(sp->pdev);
+               }
+       }
+       else {
+               free_irq(sp->pdev->irq, dev);
+               if (sp->intr_type == MSI)
+                       pci_disable_msi(sp->pdev);
+       }       
        sp->device_close_flag = TRUE;   /* Device is shut down. */
        return 0;
 }
@@ -3834,11 +3466,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        TxD_t *txdp;
        TxFIFO_element_t __iomem *tx_fifo;
        unsigned long flags;
+#ifdef NETIF_F_TSO
+       int mss;
+#endif
        u16 vlan_tag = 0;
        int vlan_priority = 0;
        mac_info_t *mac_control;
        struct config_param *config;
-       int offload_type;
 
        mac_control = &sp->mac_control;
        config = &sp->config;
@@ -3869,8 +3503,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 
        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 ? 0 : (put_off+1)) == get_off) {
+       if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
                DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
                netif_stop_queue(dev);
                dev_kfree_skb(skb);
@@ -3886,11 +3519,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
 
-       offload_type = s2io_offload_type(skb);
+       txdp->Control_1 = 0;
+       txdp->Control_2 = 0;
 #ifdef NETIF_F_TSO
-       if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+       mss = skb_shinfo(skb)->tso_size;
+       if (mss) {
                txdp->Control_1 |= TXD_TCP_LSO_EN;
-               txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb));
+               txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
        }
 #endif
        if (skb->ip_summed == CHECKSUM_HW) {
@@ -3908,10 +3543,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        frg_len = skb->len - skb->data_len;
-       if (offload_type == SKB_GSO_UDP) {
+       if (skb_shinfo(skb)->ufo_size) {
                int ufo_size;
 
-               ufo_size = s2io_udp_mss(skb);
+               ufo_size = skb_shinfo(skb)->ufo_size;
                ufo_size &= ~7;
                txdp->Control_1 |= TXD_UFO_EN;
                txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
@@ -3928,13 +3563,16 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                                        sp->ufo_in_band_v,
                                        sizeof(u64), PCI_DMA_TODEVICE);
                txdp++;
+               txdp->Control_1 = 0;
+               txdp->Control_2 = 0;
        }
 
        txdp->Buffer_Pointer = pci_map_single
            (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
        txdp->Host_Control = (unsigned long) skb;
        txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
-       if (offload_type == SKB_GSO_UDP)
+
+       if (skb_shinfo(skb)->ufo_size)
                txdp->Control_1 |= TXD_UFO_EN;
 
        frg_cnt = skb_shinfo(skb)->nr_frags;
@@ -3949,12 +3587,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                    (sp->pdev, frag->page, frag->page_offset,
                     frag->size, PCI_DMA_TODEVICE);
                txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
-               if (offload_type == SKB_GSO_UDP)
+               if (skb_shinfo(skb)->ufo_size)
                        txdp->Control_1 |= TXD_UFO_EN;
        }
        txdp->Control_1 |= TXD_GATHER_CODE_LAST;
 
-       if (offload_type == SKB_GSO_UDP)
+       if (skb_shinfo(skb)->ufo_size)
                frg_cnt++; /* as Txd0 was used for inband header */
 
        tx_fifo = mac_control->tx_FIFO_start[queue];
@@ -3963,21 +3601,23 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 
        val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
                 TX_FIFO_LAST_LIST);
-       if (offload_type)
-               val64 |= TX_FIFO_SPECIAL_FUNC;
 
+#ifdef NETIF_F_TSO
+       if (mss)
+               val64 |= TX_FIFO_SPECIAL_FUNC;
+#endif
+       if (skb_shinfo(skb)->ufo_size)
+               val64 |= TX_FIFO_SPECIAL_FUNC;
        writeq(val64, &tx_fifo->List_Control);
 
        mmiowb();
 
        put_off++;
-       if (put_off == mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1)
-               put_off = 0;
+       put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
        mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
 
        /* Avoid "put" pointer going beyond "get" pointer */
-       if (((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
-               sp->mac_control.stats_info->sw_stat.fifo_full_cnt++;
+       if (((put_off + 1) % queue_len) == get_off) {
                DBG_PRINT(TX_DBG,
                          "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
                          put_off, get_off);
@@ -3999,41 +3639,13 @@ s2io_alarm_handle(unsigned long data)
        mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
 }
 
-static int s2io_chk_rx_buffers(nic_t *sp, int rng_n)
-{
-       int rxb_size, level;
-
-       if (!sp->lro) {
-               rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
-               level = rx_buffer_level(sp, rxb_size, rng_n);
-
-               if ((level == PANIC) && (!TASKLET_IN_USE)) {
-                       int ret;
-                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
-                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
-                       if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
-                               DBG_PRINT(ERR_DBG, "Out of memory in %s",
-                                         __FUNCTION__);
-                               clear_bit(0, (&sp->tasklet_status));
-                               return -1;
-                       }
-                       clear_bit(0, (&sp->tasklet_status));
-               } else if (level == LOW)
-                       tasklet_schedule(&sp->task);
-
-       } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
-                       DBG_PRINT(ERR_DBG, "%s:Out of memory", sp->dev->name);
-                       DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
-       }
-       return 0;
-}
-
 static irqreturn_t
 s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) dev_id;
        nic_t *sp = dev->priv;
        int i;
+       int ret;
        mac_info_t *mac_control;
        struct config_param *config;
 
@@ -4055,8 +3667,26 @@ s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
         * reallocate the buffers from the interrupt handler itself,
         * else schedule a tasklet to reallocate the buffers.
         */
-       for (i = 0; i < config->rx_ring_num; i++)
-               s2io_chk_rx_buffers(sp, i);
+       for (i = 0; i < config->rx_ring_num; i++) {
+               int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+               int level = rx_buffer_level(sp, rxb_size, i);
+
+               if ((level == PANIC) && (!TASKLET_IN_USE)) {
+                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
+                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
+                       if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                         dev->name);
+                               DBG_PRINT(ERR_DBG, " in ISR!!\n");
+                               clear_bit(0, (&sp->tasklet_status));
+                               atomic_dec(&sp->isr_cnt);
+                               return IRQ_HANDLED;
+                       }
+                       clear_bit(0, (&sp->tasklet_status));
+               } else if (level == LOW) {
+                       tasklet_schedule(&sp->task);
+               }
+       }
 
        atomic_dec(&sp->isr_cnt);
        return IRQ_HANDLED;
@@ -4067,13 +3697,31 @@ s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
        ring_info_t *ring = (ring_info_t *)dev_id;
        nic_t *sp = ring->nic;
+       int rxb_size, level, rng_n;
 
        atomic_inc(&sp->isr_cnt);
-
        rx_intr_handler(ring);
-       s2io_chk_rx_buffers(sp, ring->ring_no);
 
+       rng_n = ring->ring_no;
+       rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+       level = rx_buffer_level(sp, rxb_size, rng_n);
+
+       if ((level == PANIC) && (!TASKLET_IN_USE)) {
+               int ret;
+               DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+               DBG_PRINT(INTR_DBG, "PANIC levels\n");
+               if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+                       DBG_PRINT(ERR_DBG, "Out of memory in %s",
+                                 __FUNCTION__);
+                       clear_bit(0, (&sp->tasklet_status));
+                       return IRQ_HANDLED;
+               }
+               clear_bit(0, (&sp->tasklet_status));
+       } else if (level == LOW) {
+               tasklet_schedule(&sp->task);
+       }
        atomic_dec(&sp->isr_cnt);
+
        return IRQ_HANDLED;
 }
 
@@ -4088,6 +3736,7 @@ s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
        atomic_dec(&sp->isr_cnt);
        return IRQ_HANDLED;
 }
+
 static void s2io_txpic_intr_handle(nic_t *sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -4098,56 +3747,41 @@ static void s2io_txpic_intr_handle(nic_t *sp)
                val64 = readq(&bar0->gpio_int_reg);
                if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
                    (val64 & GPIO_INT_REG_LINK_UP)) {
-                       /*
-                        * This is unstable state so clear both up/down
-                        * interrupt and adapter to re-evaluate the link state.
-                        */
                        val64 |=  GPIO_INT_REG_LINK_DOWN;
                        val64 |= GPIO_INT_REG_LINK_UP;
                        writeq(val64, &bar0->gpio_int_reg);
+                       goto masking;
+               }
+
+               if (((sp->last_link_state == LINK_UP) &&
+                       (val64 & GPIO_INT_REG_LINK_DOWN)) ||
+               ((sp->last_link_state == LINK_DOWN) &&
+               (val64 & GPIO_INT_REG_LINK_UP))) {
                        val64 = readq(&bar0->gpio_int_mask);
-                       val64 &= ~(GPIO_INT_MASK_LINK_UP |
-                                  GPIO_INT_MASK_LINK_DOWN);
+                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
+                       val64 |= GPIO_INT_MASK_LINK_UP;
                        writeq(val64, &bar0->gpio_int_mask);
+                       s2io_set_link((unsigned long)sp);
                }
-               else if (val64 & GPIO_INT_REG_LINK_UP) {
-                       val64 = readq(&bar0->adapter_status);
-                       if (verify_xena_quiescence(sp, val64,
-                                                  sp->device_enabled_once)) {
-                               /* Enable Adapter */
-                               val64 = readq(&bar0->adapter_control);
-                               val64 |= ADAPTER_CNTL_EN;
-                               writeq(val64, &bar0->adapter_control);
-                               val64 |= ADAPTER_LED_ON;
-                               writeq(val64, &bar0->adapter_control);
-                               if (!sp->device_enabled_once)
-                                       sp->device_enabled_once = 1;
-
-                               s2io_link(sp, LINK_UP);
-                               /*
-                                * unmask link down interrupt and mask link-up
-                                * intr
-                                */
-                               val64 = readq(&bar0->gpio_int_mask);
-                               val64 &= ~GPIO_INT_MASK_LINK_DOWN;
-                               val64 |= GPIO_INT_MASK_LINK_UP;
-                               writeq(val64, &bar0->gpio_int_mask);
-
-                       }
-               }else if (val64 & GPIO_INT_REG_LINK_DOWN) {
-                       val64 = readq(&bar0->adapter_status);
-                       if (verify_xena_quiescence(sp, val64,
-                                                  sp->device_enabled_once)) {
-                               s2io_link(sp, LINK_DOWN);
-                               /* Link is down so unmaks link up interrupt */
-                               val64 = readq(&bar0->gpio_int_mask);
-                               val64 &= ~GPIO_INT_MASK_LINK_UP;
-                               val64 |= GPIO_INT_MASK_LINK_DOWN;
-                               writeq(val64, &bar0->gpio_int_mask);
-                       }
+masking:
+               if (sp->last_link_state == LINK_UP) {
+                       /*enable down interrupt */
+                       val64 = readq(&bar0->gpio_int_mask);
+                       /* unmasks link down intr */
+                       val64 &=  ~GPIO_INT_MASK_LINK_DOWN;
+                       /* masks link up intr */
+                       val64 |= GPIO_INT_MASK_LINK_UP;
+                       writeq(val64, &bar0->gpio_int_mask);
+               } else {
+                       /*enable UP Interrupt */
+                       val64 = readq(&bar0->gpio_int_mask);
+                       /* unmasks link up interrupt */
+                       val64 &= ~GPIO_INT_MASK_LINK_UP;
+                       /* masks link down interrupt */
+                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
+                       writeq(val64, &bar0->gpio_int_mask);
                }
        }
-       val64 = readq(&bar0->gpio_int_mask);
 }
 
 /**
@@ -4170,7 +3804,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
        nic_t *sp = dev->priv;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        int i;
-       u64 reason = 0, val64, org_mask;
+       u64 reason = 0, val64;
        mac_info_t *mac_control;
        struct config_param *config;
 
@@ -4194,41 +3828,43 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
                return IRQ_NONE;
        }
 
-       val64 = 0xFFFFFFFFFFFFFFFFULL;
-       /* Store current mask before masking all interrupts */
-       org_mask = readq(&bar0->general_int_mask);
-       writeq(val64, &bar0->general_int_mask);
-
 #ifdef CONFIG_S2IO_NAPI
        if (reason & GEN_INTR_RXTRAFFIC) {
                if (netif_rx_schedule_prep(dev)) {
-                       writeq(val64, &bar0->rx_traffic_mask);
+                       en_dis_able_nic_intrs(sp, RX_TRAFFIC_INTR,
+                                             DISABLE_INTRS);
                        __netif_rx_schedule(dev);
                }
        }
 #else
-       /*
-        * Rx handler is called by default, without checking for the
-        * cause of interrupt.
-        * rx_traffic_int reg is an R1 register, writing all 1's
-        * will ensure that the actual interrupt causing bit get's
-        * cleared and hence a read can be avoided.
-        */
-       writeq(val64, &bar0->rx_traffic_int);
-       for (i = 0; i < config->rx_ring_num; i++) {
-               rx_intr_handler(&mac_control->rings[i]);
+       /* If Intr is because of Rx Traffic */
+       if (reason & GEN_INTR_RXTRAFFIC) {
+               /*
+                * rx_traffic_int reg is an R1 register, writing all 1's
+                * will ensure that the actual interrupt causing bit get's
+                * cleared and hence a read can be avoided.
+                */
+               val64 = 0xFFFFFFFFFFFFFFFFULL;
+               writeq(val64, &bar0->rx_traffic_int);
+               for (i = 0; i < config->rx_ring_num; i++) {
+                       rx_intr_handler(&mac_control->rings[i]);
+               }
        }
 #endif
 
-       /*
-        * tx_traffic_int reg is an R1 register, writing all 1's
-        * will ensure that the actual interrupt causing bit get's
-        * cleared and hence a read can be avoided.
-        */
-       writeq(val64, &bar0->tx_traffic_int);
+       /* If Intr is because of Tx Traffic */
+       if (reason & GEN_INTR_TXTRAFFIC) {
+               /*
+                * tx_traffic_int reg is an R1 register, writing all 1's
+                * will ensure that the actual interrupt causing bit get's
+                * cleared and hence a read can be avoided.
+                */
+               val64 = 0xFFFFFFFFFFFFFFFFULL;
+               writeq(val64, &bar0->tx_traffic_int);
 
-       for (i = 0; i < config->tx_fifo_num; i++)
-               tx_intr_handler(&mac_control->fifos[i]);
+               for (i = 0; i < config->tx_fifo_num; i++)
+                       tx_intr_handler(&mac_control->fifos[i]);
+       }
 
        if (reason & GEN_INTR_TXPIC)
                s2io_txpic_intr_handle(sp);
@@ -4238,10 +3874,29 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
         * else schedule a tasklet to reallocate the buffers.
         */
 #ifndef CONFIG_S2IO_NAPI
-       for (i = 0; i < config->rx_ring_num; i++)
-               s2io_chk_rx_buffers(sp, i);
+       for (i = 0; i < config->rx_ring_num; i++) {
+               int ret;
+               int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
+               int level = rx_buffer_level(sp, rxb_size, i);
+
+               if ((level == PANIC) && (!TASKLET_IN_USE)) {
+                       DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
+                       DBG_PRINT(INTR_DBG, "PANIC levels\n");
+                       if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
+                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
+                                         dev->name);
+                               DBG_PRINT(ERR_DBG, " in ISR!!\n");
+                               clear_bit(0, (&sp->tasklet_status));
+                               atomic_dec(&sp->isr_cnt);
+                               return IRQ_HANDLED;
+                       }
+                       clear_bit(0, (&sp->tasklet_status));
+               } else if (level == LOW) {
+                       tasklet_schedule(&sp->task);
+               }
+       }
 #endif
-       writeq(org_mask, &bar0->general_int_mask);
+
        atomic_dec(&sp->isr_cnt);
        return IRQ_HANDLED;
 }
@@ -4269,8 +3924,6 @@ static void s2io_updt_stats(nic_t *sp)
                        if (cnt == 5)
                                break; /* Updt failed */
                } while(1);
-       } else {
-               memset(sp->mac_control.stats_info, 0, sizeof(StatInfo_t));
        }
 }
 
@@ -4346,8 +3999,7 @@ static void s2io_set_multicast(struct net_device *dev)
                    RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET);
                writeq(val64, &bar0->rmac_addr_cmd_mem);
                /* Wait till command completes */
-               wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
+               wait_for_cmd_complete(sp);
 
                sp->m_cast_flg = 1;
                sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
@@ -4362,8 +4014,7 @@ static void s2io_set_multicast(struct net_device *dev)
                    RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
                writeq(val64, &bar0->rmac_addr_cmd_mem);
                /* Wait till command completes */
-               wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
+               wait_for_cmd_complete(sp);
 
                sp->m_cast_flg = 0;
                sp->all_multi_pos = 0;
@@ -4428,8 +4079,7 @@ static void s2io_set_multicast(struct net_device *dev)
                        writeq(val64, &bar0->rmac_addr_cmd_mem);
 
                        /* Wait for command completes */
-                       if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+                       if (wait_for_cmd_complete(sp)) {
                                DBG_PRINT(ERR_DBG, "%s: Adding ",
                                          dev->name);
                                DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4459,8 +4109,7 @@ static void s2io_set_multicast(struct net_device *dev)
                        writeq(val64, &bar0->rmac_addr_cmd_mem);
 
                        /* Wait for command completes */
-                       if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+                       if (wait_for_cmd_complete(sp)) {
                                DBG_PRINT(ERR_DBG, "%s: Adding ",
                                          dev->name);
                                DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4480,7 +4129,7 @@ static void s2io_set_multicast(struct net_device *dev)
  *  as defined in errno.h file on failure.
  */
 
-static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
+int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
 {
        nic_t *sp = dev->priv;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -4505,8 +4154,7 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
            RMAC_ADDR_CMD_MEM_OFFSET(0);
        writeq(val64, &bar0->rmac_addr_cmd_mem);
        /* Wait till command completes */
-       if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+       if (wait_for_cmd_complete(sp)) {
                DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name);
                return FAILURE;
        }
@@ -4903,50 +4551,6 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
        }
        return ret;
 }
-static void s2io_vpd_read(nic_t *nic)
-{
-       u8 *vpd_data;
-       u8 data;
-       int i=0, cnt, fail = 0;
-       int vpd_addr = 0x80;
-
-       if (nic->device_type == XFRAME_II_DEVICE) {
-               strcpy(nic->product_name, "Xframe II 10GbE network adapter");
-               vpd_addr = 0x80;
-       }
-       else {
-               strcpy(nic->product_name, "Xframe I 10GbE network adapter");
-               vpd_addr = 0x50;
-       }
-
-       vpd_data = kmalloc(256, GFP_KERNEL);
-       if (!vpd_data)
-               return;
-
-       for (i = 0; i < 256; i +=4 ) {
-               pci_write_config_byte(nic->pdev, (vpd_addr + 2), i);
-               pci_read_config_byte(nic->pdev,  (vpd_addr + 2), &data);
-               pci_write_config_byte(nic->pdev, (vpd_addr + 3), 0);
-               for (cnt = 0; cnt <5; cnt++) {
-                       msleep(2);
-                       pci_read_config_byte(nic->pdev, (vpd_addr + 3), &data);
-                       if (data == 0x80)
-                               break;
-               }
-               if (cnt >= 5) {
-                       DBG_PRINT(ERR_DBG, "Read of VPD data failed\n");
-                       fail = 1;
-                       break;
-               }
-               pci_read_config_dword(nic->pdev,  (vpd_addr + 4),
-                                     (u32 *)&vpd_data[i]);
-       }
-       if ((!fail) && (vpd_data[1] < VPD_PRODUCT_NAME_LEN)) {
-               memset(nic->product_name, 0, vpd_data[1]);
-               memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
-       }
-       kfree(vpd_data);
-}
 
 /**
  *  s2io_ethtool_geeprom  - reads the value stored in the Eeprom.
@@ -5259,12 +4863,10 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)
        u64 val64;
 
        val64 = readq(&bar0->adapter_status);
-       if(!(LINK_IS_UP(val64)))
+       if (val64 & ADAPTER_STATUS_RMAC_LOCAL_FAULT)
                *data = 1;
-       else
-               *data = 0;
 
-       return *data;
+       return 0;
 }
 
 /**
@@ -5458,19 +5060,9 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
                (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
                le32_to_cpu(stat_info->tmac_bcst_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->tmac_ttl_octets_oflow) << 32 |
-                le32_to_cpu(stat_info->tmac_ttl_octets);
-       tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->tmac_ucst_frms_oflow) << 32 |
-                le32_to_cpu(stat_info->tmac_ucst_frms);
-       tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->tmac_nucst_frms_oflow) << 32 |
-                le32_to_cpu(stat_info->tmac_nucst_frms);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
                le32_to_cpu(stat_info->tmac_any_err_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_ttl_less_fb_octets);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
@@ -5502,27 +5094,11 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
                (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_vld_bcst_frms);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_out_rng_len_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
-       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_unsup_ctrl_frms);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_ttl_octets_oflow) << 32 |
-               le32_to_cpu(stat_info->rmac_ttl_octets);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_accepted_ucst_frms_oflow)
-               << 32 | le32_to_cpu(stat_info->rmac_accepted_ucst_frms);
-       tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_accepted_nucst_frms_oflow)
-                 << 32 | le32_to_cpu(stat_info->rmac_accepted_nucst_frms);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_discarded_frms);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_drop_events_oflow)
-                 << 32 | le32_to_cpu(stat_info->rmac_drop_events);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_less_fb_octets);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_frms);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_usized_frms);
@@ -5535,129 +5111,30 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_jabber_frms);
-       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_64_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_65_127_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_128_255_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_256_511_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_512_1023_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1024_1518_frms);
-       tmp_stats[i++] =
-               (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_ip);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
-       tmp_stats[i++] =
-               (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_drop_ip);
-       tmp_stats[i++] =
-               (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_icmp);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
-       tmp_stats[i++] =
-               (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
+       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_udp);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_err_drp_udp);
-       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_err_sym);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q0);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q1);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q2);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q3);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q4);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q5);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q6);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q7);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q0);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q1);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q2);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q3);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q4);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q5);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q6);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q7);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_pause_cnt);
-       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_data_err_cnt);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_ctrl_err_cnt);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_accepted_ip);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rd_req_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_rtry_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_rd_ack_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->wr_req_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_rtry_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->wr_disc_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_wr_ack_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->txp_wr_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->txd_rd_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->txd_wr_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rxd_rd_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rxd_wr_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->txf_rd_cnt);
-       tmp_stats[i++] = le32_to_cpu(stat_info->rxf_wr_cnt);
-       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_8192_max_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard);
-        tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt);
        tmp_stats[i++] = 0;
        tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
        tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
-       tmp_stats[i++] = stat_info->sw_stat.parity_err_cnt;
-       tmp_stats[i++] = stat_info->sw_stat.serious_err_cnt;
-       tmp_stats[i++] = stat_info->sw_stat.soft_reset_cnt;
-       tmp_stats[i++] = stat_info->sw_stat.fifo_full_cnt;
-       tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt;
-       tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_high;
-       tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_low;
-       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_high;
-       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_low;
-       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_high;
-       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_low;
-       tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_high;
-       tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_low;
-       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_high;
-       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_low;
-       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_high;
-       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_low;
-       tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt;
-       tmp_stats[i++] = stat_info->sw_stat.sending_both;
-       tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts;
-       tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts;
-       if (stat_info->sw_stat.num_aggregations) {
-               u64 tmp = stat_info->sw_stat.sum_avg_pkts_aggregated;
-               int count = 0;
-               /* 
-                * Since 64-bit divide does not work on all platforms,
-                * do repeated subtraction.
-                */
-               while (tmp >= stat_info->sw_stat.num_aggregations) {
-                       tmp -= stat_info->sw_stat.num_aggregations;
-                       count++;
-               }
-               tmp_stats[i++] = count;
-       }
-       else
-               tmp_stats[i++] = 0;
 }
 
 static int s2io_ethtool_get_regs_len(struct net_device *dev)
@@ -5722,19 +5199,6 @@ static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
        return 0;
 }
 
-static u32 s2io_ethtool_op_get_tso(struct net_device *dev)
-{
-       return (dev->features & NETIF_F_TSO) != 0;
-}
-static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data)
-{
-       if (data)
-               dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-       else
-               dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-
-       return 0;
-}
 
 static struct ethtool_ops netdev_ethtool_ops = {
        .get_settings = s2io_ethtool_gset,
@@ -5755,8 +5219,8 @@ static struct ethtool_ops netdev_ethtool_ops = {
        .get_sg = ethtool_op_get_sg,
        .set_sg = ethtool_op_set_sg,
 #ifdef NETIF_F_TSO
-       .get_tso = s2io_ethtool_op_get_tso,
-       .set_tso = s2io_ethtool_op_set_tso,
+       .get_tso = ethtool_op_get_tso,
+       .set_tso = ethtool_op_set_tso,
 #endif
        .get_ufo = ethtool_op_get_ufo,
        .set_ufo = ethtool_op_set_ufo,
@@ -5946,313 +5410,31 @@ static void s2io_set_link(unsigned long data)
        clear_bit(0, &(nic->link_state));
 }
 
-static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
-                          struct sk_buff **skb, u64 *temp0, u64 *temp1,
-                          u64 *temp2, int size)
+static void s2io_card_down(nic_t * sp)
 {
-       struct net_device *dev = sp->dev;
-       struct sk_buff *frag_list;
-
-       if ((sp->rxd_mode == RXD_MODE_1) && (rxdp->Host_Control == 0)) {
-               /* allocate skb */
-               if (*skb) {
-                       DBG_PRINT(INFO_DBG, "SKB is not NULL\n");
-                       /*
-                        * As Rx frame are not going to be processed,
-                        * using same mapped address for the Rxd
-                        * buffer pointer
-                        */
-                       ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0;
-               } else {
-                       *skb = dev_alloc_skb(size);
-                       if (!(*skb)) {
-                               DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
-                               DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
-                               return -ENOMEM ;
-                       }
-                       /* storing the mapped addr in a temp variable
-                        * such it will be used for next rxd whose
-                        * Host Control is NULL
-                        */
-                       ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0 =
-                               pci_map_single( sp->pdev, (*skb)->data,
-                                       size - NET_IP_ALIGN,
-                                       PCI_DMA_FROMDEVICE);
-                       rxdp->Host_Control = (unsigned long) (*skb);
-               }
-       } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) {
-               /* Two buffer Mode */
-               if (*skb) {
-                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
-                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0;
-                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
-               } else {
-                       *skb = dev_alloc_skb(size);
-                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
-                               pci_map_single(sp->pdev, (*skb)->data,
-                                              dev->mtu + 4,
-                                              PCI_DMA_FROMDEVICE);
-                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
-                               pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN,
-                                               PCI_DMA_FROMDEVICE);
-                       rxdp->Host_Control = (unsigned long) (*skb);
+       int cnt = 0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
+       unsigned long flags;
+       register u64 val64 = 0;
 
-                       /* Buffer-1 will be dummy buffer not used */
-                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 =
-                               pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN,
-                                              PCI_DMA_FROMDEVICE);
-               }
-       } else if ((rxdp->Host_Control == 0)) {
-               /* Three buffer mode */
-               if (*skb) {
-                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0;
-                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
-                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
-               } else {
-                       *skb = dev_alloc_skb(size);
-
-                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
-                               pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN,
-                                              PCI_DMA_FROMDEVICE);
-                       /* Buffer-1 receives L3/L4 headers */
-                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 =
-                               pci_map_single( sp->pdev, (*skb)->data,
-                                               l3l4hdr_size + 4,
-                                               PCI_DMA_FROMDEVICE);
-                       /*
-                        * skb_shinfo(skb)->frag_list will have L4
-                        * data payload
-                        */
-                       skb_shinfo(*skb)->frag_list = dev_alloc_skb(dev->mtu +
-                                                                  ALIGN_SIZE);
-                       if (skb_shinfo(*skb)->frag_list == NULL) {
-                               DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \
-                                         failed\n ", dev->name);
-                               return -ENOMEM ;
-                       }
-                       frag_list = skb_shinfo(*skb)->frag_list;
-                       frag_list->next = NULL;
-                       /*
-                        * Buffer-2 receives L4 data payload
-                        */
-                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
-                               pci_map_single( sp->pdev, frag_list->data,
-                                               dev->mtu, PCI_DMA_FROMDEVICE);
-               }
-       }
-       return 0;
-}
-static void set_rxd_buffer_size(nic_t *sp, RxD_t *rxdp, int size)
-{
-       struct net_device *dev = sp->dev;
-       if (sp->rxd_mode == RXD_MODE_1) {
-               rxdp->Control_2 = SET_BUFFER0_SIZE_1( size - NET_IP_ALIGN);
-       } else if (sp->rxd_mode == RXD_MODE_3B) {
-               rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
-               rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
-               rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4);
-       } else {
-               rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
-               rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4);
-               rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu);
+       del_timer_sync(&sp->alarm_timer);
+       /* If s2io_set_link task is executing, wait till it completes. */
+       while (test_and_set_bit(0, &(sp->link_state))) {
+               msleep(50);
        }
-}
-
-static  int rxd_owner_bit_reset(nic_t *sp)
-{
-       int i, j, k, blk_cnt = 0, size;
-       mac_info_t * mac_control = &sp->mac_control;
-       struct config_param *config = &sp->config;
-       struct net_device *dev = sp->dev;
-       RxD_t *rxdp = NULL;
-       struct sk_buff *skb = NULL;
-       buffAdd_t *ba = NULL;
-       u64 temp0_64 = 0, temp1_64 = 0, temp2_64 = 0;
-
-       /* Calculate the size based on ring mode */
-       size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
-               HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
-       if (sp->rxd_mode == RXD_MODE_1)
-               size += NET_IP_ALIGN;
-       else if (sp->rxd_mode == RXD_MODE_3B)
-               size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
-       else
-               size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4;
+       atomic_set(&sp->card_state, CARD_DOWN);
 
-       for (i = 0; i < config->rx_ring_num; i++) {
-               blk_cnt = config->rx_cfg[i].num_rxd /
-                       (rxd_count[sp->rxd_mode] +1);
+       /* disable Tx and Rx traffic on the NIC */
+       stop_nic(sp);
 
-               for (j = 0; j < blk_cnt; j++) {
-                       for (k = 0; k < rxd_count[sp->rxd_mode]; k++) {
-                               rxdp = mac_control->rings[i].
-                                       rx_blocks[j].rxds[k].virt_addr;
-                               if(sp->rxd_mode >= RXD_MODE_3A)
-                                       ba = &mac_control->rings[i].ba[j][k];
-                               set_rxd_buffer_pointer(sp, rxdp, ba,
-                                                      &skb,(u64 *)&temp0_64,
-                                                      (u64 *)&temp1_64,
-                                                      (u64 *)&temp2_64, size);
+       /* Kill tasklet. */
+       tasklet_kill(&sp->task);
 
-                               set_rxd_buffer_size(sp, rxdp, size);
-                               wmb();
-                               /* flip the Ownership bit to Hardware */
-                               rxdp->Control_1 |= RXD_OWN_XENA;
-                       }
-               }
-       }
-       return 0;
-
-}
-
-static int s2io_add_isr(nic_t * sp)
-{
-       int ret = 0;
-       struct net_device *dev = sp->dev;
-       int err = 0;
-
-       if (sp->intr_type == MSI)
-               ret = s2io_enable_msi(sp);
-       else if (sp->intr_type == MSI_X)
-               ret = s2io_enable_msi_x(sp);
-       if (ret) {
-               DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
-               sp->intr_type = INTA;
-       }
-
-       /* Store the values of the MSIX table in the nic_t structure */
-       store_xmsi_data(sp);
-
-       /* After proper initialization of H/W, register ISR */
-       if (sp->intr_type == MSI) {
-               err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
-                       IRQF_SHARED, sp->name, dev);
-               if (err) {
-                       pci_disable_msi(sp->pdev);
-                       DBG_PRINT(ERR_DBG, "%s: MSI registration failed\n",
-                                 dev->name);
-                       return -1;
-               }
-       }
-       if (sp->intr_type == MSI_X) {
-               int i;
-
-               for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
-                       if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
-                               sprintf(sp->desc[i], "%s:MSI-X-%d-TX",
-                                       dev->name, i);
-                               err = request_irq(sp->entries[i].vector,
-                                         s2io_msix_fifo_handle, 0, sp->desc[i],
-                                                 sp->s2io_entries[i].arg);
-                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
-                               (unsigned long long)sp->msix_info[i].addr);
-                       } else {
-                               sprintf(sp->desc[i], "%s:MSI-X-%d-RX",
-                                       dev->name, i);
-                               err = request_irq(sp->entries[i].vector,
-                                         s2io_msix_ring_handle, 0, sp->desc[i],
-                                                 sp->s2io_entries[i].arg);
-                               DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
-                               (unsigned long long)sp->msix_info[i].addr);
-                       }
-                       if (err) {
-                               DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
-                                         "failed\n", dev->name, i);
-                               DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
-                               return -1;
-                       }
-                       sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
-               }
-       }
-       if (sp->intr_type == INTA) {
-               err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
-                               sp->name, dev);
-               if (err) {
-                       DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
-                                 dev->name);
-                       return -1;
-               }
-       }
-       return 0;
-}
-static void s2io_rem_isr(nic_t * sp)
-{
-       int cnt = 0;
-       struct net_device *dev = sp->dev;
-
-       if (sp->intr_type == MSI_X) {
-               int i;
-               u16 msi_control;
-
-               for (i=1; (sp->s2io_entries[i].in_use ==
-                       MSIX_REGISTERED_SUCCESS); i++) {
-                       int vector = sp->entries[i].vector;
-                       void *arg = sp->s2io_entries[i].arg;
-
-                       free_irq(vector, arg);
-               }
-               pci_read_config_word(sp->pdev, 0x42, &msi_control);
-               msi_control &= 0xFFFE; /* Disable MSI */
-               pci_write_config_word(sp->pdev, 0x42, msi_control);
-
-               pci_disable_msix(sp->pdev);
-       } else {
-               free_irq(sp->pdev->irq, dev);
-               if (sp->intr_type == MSI) {
-                       u16 val;
-
-                       pci_disable_msi(sp->pdev);
-                       pci_read_config_word(sp->pdev, 0x4c, &val);
-                       val ^= 0x1;
-                       pci_write_config_word(sp->pdev, 0x4c, val);
-               }
-       }
-       /* Waiting till all Interrupt handlers are complete */
-       cnt = 0;
-       do {
-               msleep(10);
-               if (!atomic_read(&sp->isr_cnt))
-                       break;
-               cnt++;
-       } while(cnt < 5);
-}
-
-static void s2io_card_down(nic_t * sp)
-{
-       int cnt = 0;
-       XENA_dev_config_t __iomem *bar0 = sp->bar0;
-       unsigned long flags;
-       register u64 val64 = 0;
-
-       del_timer_sync(&sp->alarm_timer);
-       /* If s2io_set_link task is executing, wait till it completes. */
-       while (test_and_set_bit(0, &(sp->link_state))) {
-               msleep(50);
-       }
-       atomic_set(&sp->card_state, CARD_DOWN);
-
-       /* disable Tx and Rx traffic on the NIC */
-       stop_nic(sp);
-
-       s2io_rem_isr(sp);
-
-       /* Kill tasklet. */
-       tasklet_kill(&sp->task);
-
-       /* Check if the device is Quiescent and then Reset the NIC */
-       do {
-               /* As per the HW requirement we need to replenish the
-                * receive buffer to avoid the ring bump. Since there is
-                * no intention of processing the Rx frame at this pointwe are
-                * just settting the ownership bit of rxd in Each Rx
-                * ring to HW and set the appropriate buffer size
-                * based on the ring mode
-                */
-               rxd_owner_bit_reset(sp);
-
-               val64 = readq(&bar0->adapter_status);
-               if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {
-                       break;
+       /* Check if the device is Quiescent and then Reset the NIC */
+       do {
+               val64 = readq(&bar0->adapter_status);
+               if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {
+                       break;
                }
 
                msleep(50);
@@ -6267,6 +5449,15 @@ static void s2io_card_down(nic_t * sp)
        } while (1);
        s2io_reset(sp);
 
+       /* Waiting till all Interrupt handlers are complete */
+       cnt = 0;
+       do {
+               msleep(10);
+               if (!atomic_read(&sp->isr_cnt))
+                       break;
+               cnt++;
+       } while(cnt < 5);
+
        spin_lock_irqsave(&sp->tx_lock, flags);
        /* Free all Tx buffers */
        free_tx_buffers(sp);
@@ -6286,16 +5477,23 @@ static int s2io_card_up(nic_t * sp)
        mac_info_t *mac_control;
        struct config_param *config;
        struct net_device *dev = (struct net_device *) sp->dev;
-       u16 interruptible;
 
        /* Initialize the H/W I/O registers */
        if (init_nic(sp) != 0) {
                DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
                          dev->name);
-               s2io_reset(sp);
                return -ENODEV;
        }
 
+       if (sp->intr_type == MSI)
+               ret = s2io_enable_msi(sp);
+       else if (sp->intr_type == MSI_X)
+               ret = s2io_enable_msi_x(sp);
+       if (ret) {
+               DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
+               sp->intr_type = INTA;
+       }
+
        /*
         * Initializing the Rx buffers. For now we are considering only 1
         * Rx ring and initializing buffers into 30 Rx blocks
@@ -6318,47 +5516,21 @@ static int s2io_card_up(nic_t * sp)
        /* Setting its receive mode */
        s2io_set_multicast(dev);
 
-       if (sp->lro) {
-               /* Initialize max aggregatable pkts per session based on MTU */
-               sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu;
-               /* Check if we can use(if specified) user provided value */
-               if (lro_max_pkts < sp->lro_max_aggr_per_sess)
-                       sp->lro_max_aggr_per_sess = lro_max_pkts;
-       }
+       /* Enable tasklet for the device */
+       tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
 
        /* Enable Rx Traffic and interrupts on the NIC */
        if (start_nic(sp)) {
                DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name);
+               tasklet_kill(&sp->task);
                s2io_reset(sp);
-               free_rx_buffers(sp);
-               return -ENODEV;
-       }
-
-       /* Add interrupt service routine */
-       if (s2io_add_isr(sp) != 0) {
-               if (sp->intr_type == MSI_X)
-                       s2io_rem_isr(sp);
-               s2io_reset(sp);
+               free_irq(dev->irq, dev);
                free_rx_buffers(sp);
                return -ENODEV;
        }
 
        S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
 
-       /* Enable tasklet for the device */
-       tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
-
-       /*  Enable select interrupts */
-       if (sp->intr_type != INTA)
-               en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
-       else {
-               interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
-               interruptible |= TX_PIC_INTR | RX_PIC_INTR;
-               interruptible |= TX_MAC_INTR | RX_MAC_INTR;
-               en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS);
-       }
-
-
        atomic_set(&sp->card_state, CARD_UP);
        return 0;
 }
@@ -6408,7 +5580,6 @@ static void s2io_tx_watchdog(struct net_device *dev)
 
        if (netif_carrier_ok(dev)) {
                schedule_work(&sp->rst_timer_task);
-               sp->mac_control.stats_info->sw_stat.soft_reset_cnt++;
        }
 }
 
@@ -6420,7 +5591,7 @@ static void s2io_tx_watchdog(struct net_device *dev)
  *   @cksum : FCS checksum of the frame.
  *   @ring_no : the ring from which this RxD was extracted.
  *   Description:
- *   This function is called by the Rx interrupt serivce routine to perform
+ *   This function is called by the Tx interrupt serivce routine to perform
  *   some OS related operations on the SKB before passing it to the upper
  *   layers. It mainly checks if the checksum is OK, if so adds it to the
  *   SKBs cksum variable, increments the Rx packet count and passes the SKB
@@ -6437,33 +5608,17 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                ((unsigned long) rxdp->Host_Control);
        int ring_no = ring_data->ring_no;
        u16 l3_csum, l4_csum;
-       unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
-       lro_t *lro;
 
        skb->dev = dev;
-
-       if (err) {
-               /* Check for parity error */
-               if (err & 0x1) {
-                       sp->mac_control.stats_info->sw_stat.parity_err_cnt++;
-               }
-
-               /*
-               * Drop the packet if bad transfer code. Exception being
-               * 0x5, which could be due to unsupported IPv6 extension header.
-               * In this case, we let stack handle the packet.
-               * Note that in this case, since checksum will be incorrect,
-               * stack will validate the same.
-               */
-               if (err && ((err >> 48) != 0x5)) {
-                       DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
-                               dev->name, err);
-                       sp->stats.rx_crc_errors++;
-                       dev_kfree_skb(skb);
-                       atomic_dec(&sp->rx_bufs_left[ring_no]);
-                       rxdp->Host_Control = 0;
-                       return 0;
-               }
+       if (rxdp->Control_1 & RXD_T_CODE) {
+               unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
+               DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
+                         dev->name, err);
+               dev_kfree_skb(skb);
+               sp->stats.rx_crc_errors++;
+               atomic_dec(&sp->rx_bufs_left[ring_no]);
+               rxdp->Host_Control = 0;
+               return 0;
        }
 
        /* Updating statistics */
@@ -6501,8 +5656,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                        skb_put(skb, buf2_len);
        }
 
-       if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) ||
-           (sp->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) &&
+       if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
            (sp->rx_csum)) {
                l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
                l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
@@ -6513,57 +5667,6 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                         * a flag in the RxD.
                         */
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
-                       if (sp->lro) {
-                               u32 tcp_len;
-                               u8 *tcp;
-                               int ret = 0;
-
-                               ret = s2io_club_tcp_session(skb->data, &tcp,
-                                               &tcp_len, &lro, rxdp, sp);
-                               switch (ret) {
-                                       case 3: /* Begin anew */
-                                               lro->parent = skb;
-                                               goto aggregate;
-                                       case 1: /* Aggregate */
-                                       {
-                                               lro_append_pkt(sp, lro,
-                                                       skb, tcp_len);
-                                               goto aggregate;
-                                       }
-                                       case 4: /* Flush session */
-                                       {
-                                               lro_append_pkt(sp, lro,
-                                                       skb, tcp_len);
-                                               queue_rx_frame(lro->parent);
-                                               clear_lro_session(lro);
-                                               sp->mac_control.stats_info->
-                                                   sw_stat.flush_max_pkts++;
-                                               goto aggregate;
-                                       }
-                                       case 2: /* Flush both */
-                                               lro->parent->data_len =
-                                                       lro->frags_len;
-                                               sp->mac_control.stats_info->
-                                                    sw_stat.sending_both++;
-                                               queue_rx_frame(lro->parent);
-                                               clear_lro_session(lro);
-                                               goto send_up;
-                                       case 0: /* sessions exceeded */
-                                       case -1: /* non-TCP or not
-                                                 * L2 aggregatable
-                                                 */
-                                       case 5: /*
-                                                * First pkt in session not
-                                                * L3/L4 aggregatable
-                                                */
-                                               break;
-                                       default:
-                                               DBG_PRINT(ERR_DBG,
-                                                       "%s: Samadhana!!\n",
-                                                        __FUNCTION__);
-                                               BUG();
-                               }
-                       }
                } else {
                        /*
                         * Packet with erroneous checksum, let the
@@ -6575,31 +5678,25 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                skb->ip_summed = CHECKSUM_NONE;
        }
 
-       if (!sp->lro) {
-               skb->protocol = eth_type_trans(skb, dev);
+       skb->protocol = eth_type_trans(skb, dev);
 #ifdef CONFIG_S2IO_NAPI
-               if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
-                       /* Queueing the vlan frame to the upper layer */
-                       vlan_hwaccel_receive_skb(skb, sp->vlgrp,
-                               RXD_GET_VLAN_TAG(rxdp->Control_2));
-               } else {
-                       netif_receive_skb(skb);
-               }
+       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+               /* Queueing the vlan frame to the upper layer */
+               vlan_hwaccel_receive_skb(skb, sp->vlgrp,
+                       RXD_GET_VLAN_TAG(rxdp->Control_2));
+       } else {
+               netif_receive_skb(skb);
+       }
 #else
-               if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
-                       /* Queueing the vlan frame to the upper layer */
-                       vlan_hwaccel_rx(skb, sp->vlgrp,
-                               RXD_GET_VLAN_TAG(rxdp->Control_2));
-               } else {
-                       netif_rx(skb);
-               }
-#endif
+       if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) {
+               /* Queueing the vlan frame to the upper layer */
+               vlan_hwaccel_rx(skb, sp->vlgrp,
+                       RXD_GET_VLAN_TAG(rxdp->Control_2));
        } else {
-send_up:
-               queue_rx_frame(skb);
-       }               
+               netif_rx(skb);
+       }
+#endif
        dev->last_rx = jiffies;
-aggregate:
        atomic_dec(&sp->rx_bufs_left[ring_no]);
        return SUCCESS;
 }
@@ -6617,7 +5714,7 @@ aggregate:
  *  void.
  */
 
-static void s2io_link(nic_t * sp, int link)
+void s2io_link(nic_t * sp, int link)
 {
        struct net_device *dev = (struct net_device *) sp->dev;
 
@@ -6642,7 +5739,7 @@ static void s2io_link(nic_t * sp, int link)
  *  returns the revision ID of the device.
  */
 
-static int get_xena_rev_id(struct pci_dev *pdev)
+int get_xena_rev_id(struct pci_dev *pdev)
 {
        u8 id = 0;
        int ret;
@@ -6678,56 +5775,39 @@ static void s2io_init_pci(nic_t * sp)
        pci_write_config_word(sp->pdev, PCI_COMMAND,
                              (pci_cmd | PCI_COMMAND_PARITY));
        pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
+
+       /* Forcibly disabling relaxed ordering capability of the card. */
+       pcix_cmd &= 0xfffd;
+       pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
+                             pcix_cmd);
+       pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
+                            &(pcix_cmd));
 }
 
-static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
-{
-       if ( tx_fifo_num > 8) {
-               DBG_PRINT(ERR_DBG, "s2io: Requested number of Tx fifos not "
-                        "supported\n");
-               DBG_PRINT(ERR_DBG, "s2io: Default to 8 Tx fifos\n");
-               tx_fifo_num = 8;
-       }
-       if ( rx_ring_num > 8) {
-               DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
-                        "supported\n");
-               DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n");
-               rx_ring_num = 8;
-       }
-#ifdef CONFIG_S2IO_NAPI
-       if (*dev_intr_type != INTA) {
-               DBG_PRINT(ERR_DBG, "s2io: NAPI cannot be enabled when "
-                         "MSI/MSI-X is enabled. Defaulting to INTA\n");
-               *dev_intr_type = INTA;
-       }
-#endif
-#ifndef CONFIG_PCI_MSI
-       if (*dev_intr_type != INTA) {
-               DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
-                         "MSI/MSI-X. Defaulting to INTA\n");
-               *dev_intr_type = INTA;
-       }
-#else
-       if (*dev_intr_type > MSI_X) {
-               DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
-                         "Defaulting to INTA\n");
-               *dev_intr_type = INTA;
-       }
+MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_param(tx_fifo_num, int, 0);
+module_param(rx_ring_num, int, 0);
+module_param(rx_ring_mode, int, 0);
+module_param_array(tx_fifo_len, uint, NULL, 0);
+module_param_array(rx_ring_sz, uint, NULL, 0);
+module_param_array(rts_frm_len, uint, NULL, 0);
+module_param(use_continuous_tx_intrs, int, 1);
+module_param(rmac_pause_time, int, 0);
+module_param(mc_pause_threshold_q0q3, int, 0);
+module_param(mc_pause_threshold_q4q7, int, 0);
+module_param(shared_splits, int, 0);
+module_param(tmac_util_period, int, 0);
+module_param(rmac_util_period, int, 0);
+module_param(bimodal, bool, 0);
+module_param(l3l4hdr_size, int , 0);
+#ifndef CONFIG_S2IO_NAPI
+module_param(indicate_max_pkts, int, 0);
 #endif
-       if ((*dev_intr_type == MSI_X) &&
-                       ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
-                       (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
-               DBG_PRINT(ERR_DBG, "s2io: Xframe I does not support MSI_X. " 
-                                       "Defaulting to INTA\n");
-               *dev_intr_type = INTA;
-       }
-       if (rx_ring_mode > 3) {
-               DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n");
-               DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n");
-               rx_ring_mode = 3;
-       }
-       return SUCCESS;
-}
+module_param(rxsync_frequency, int, 0);
+module_param(intr_type, int, 0);
 
 /**
  *  s2io_init_nic - Initialization of the adapter .
@@ -6759,8 +5839,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        int mode;
        u8 dev_intr_type = intr_type;
 
-       if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
-               return ret;
+#ifdef CONFIG_S2IO_NAPI
+       if (dev_intr_type != INTA) {
+               DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
+is enabled. Defaulting to INTA\n");
+               dev_intr_type = INTA;
+       }
+       else
+               DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
+#endif
 
        if ((ret = pci_enable_device(pdev))) {
                DBG_PRINT(ERR_DBG,
@@ -6785,10 +5872,18 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                pci_disable_device(pdev);
                return -ENOMEM;
        }
+
+       if ((dev_intr_type == MSI_X) && 
+                       ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+                       (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+               DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
+Defaulting to INTA\n");
+               dev_intr_type = INTA;
+       }
        if (dev_intr_type != MSI_X) {
                if (pci_request_regions(pdev, s2io_driver_name)) {
-                       DBG_PRINT(ERR_DBG, "Request Regions failed\n");
-                       pci_disable_device(pdev);
+                       DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
+                           pci_disable_device(pdev);
                        return -ENODEV;
                }
        }
@@ -6844,7 +5939,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        else
                sp->device_type = XFRAME_I_DEVICE;
 
-       sp->lro = lro;
                
        /* Initialize some PCI/PCI-X fields of the NIC. */
        s2io_init_pci(sp);
@@ -6860,6 +5954,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        config = &sp->config;
 
        /* Tx side parameters. */
+       if (tx_fifo_len[0] == 0)
+               tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
        config->tx_fifo_num = tx_fifo_num;
        for (i = 0; i < MAX_TX_FIFOS; i++) {
                config->tx_cfg[i].fifo_len = tx_fifo_len[i];
@@ -6883,6 +5979,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        config->max_txds = MAX_SKB_FRAGS + 2;
 
        /* Rx side parameters. */
+       if (rx_ring_sz[0] == 0)
+               rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
        config->rx_ring_num = rx_ring_num;
        for (i = 0; i < MAX_RX_RINGS; i++) {
                config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
@@ -6912,7 +6010,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        /*  initialize the shared memory used by the NIC and the host */
        if (init_shared_mem(sp)) {
                DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
-                         dev->name);
+                         __FUNCTION__);
                ret = -ENOMEM;
                goto mem_alloc_failed;
        }
@@ -6966,18 +6064,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        dev->weight = 32;
 #endif
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = s2io_netpoll;
-#endif
-
        dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
        if (sp->high_dma_flag == TRUE)
                dev->features |= NETIF_F_HIGHDMA;
 #ifdef NETIF_F_TSO
        dev->features |= NETIF_F_TSO;
-#endif
-#ifdef NETIF_F_TSO6
-       dev->features |= NETIF_F_TSO6;
 #endif
        if (sp->device_type & XFRAME_II_DEVICE) {
                dev->features |= NETIF_F_UFO;
@@ -7030,8 +6121,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
            RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
        writeq(val64, &bar0->rmac_addr_cmd_mem);
-       wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
+       wait_for_cmd_complete(sp);
+
        tmp64 = readq(&bar0->rmac_addr_data0_mem);
        mac_down = (u32) tmp64;
        mac_up = (u32) (tmp64 >> 32);
@@ -7049,9 +6140,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        dev->addr_len = ETH_ALEN;
        memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
 
-       /* reset Nic and bring it to known state */
-       s2io_reset(sp);
-
        /*
         * Initialize the tasklet status and link state flags
         * and the card state parameter
@@ -7088,63 +6176,78 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                ret = -ENODEV;
                goto register_failed;
        }
-       s2io_vpd_read(sp);
-       DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n");
-       DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name,
-                 sp->product_name, get_xena_rev_id(sp->pdev));
-       DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
-                 s2io_driver_version);
-       DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
-                         "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
+
+       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), Version %s",
+                               get_xena_rev_id(sp->pdev),
+                               s2io_driver_version);
+               switch(sp->intr_type) {
+                       case INTA:
+                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
+                               break;
+                       case MSI:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
+                               break;
+                       case MSI_X:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+                               break;
+               }
+
+               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],
                          sp->def_mac_addr[0].mac_addr[2],
                          sp->def_mac_addr[0].mac_addr[3],
                          sp->def_mac_addr[0].mac_addr[4],
                          sp->def_mac_addr[0].mac_addr[5]);
-       if (sp->device_type & XFRAME_II_DEVICE) {
                mode = s2io_print_pci_mode(sp);
                if (mode < 0) {
-                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
+                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode ");
                        ret = -EBADSLT;
-                       unregister_netdev(dev);
                        goto set_swap_failed;
                }
-       }
-       switch(sp->rxd_mode) {
-               case RXD_MODE_1:
-                   DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n",
-                                               dev->name);
-                   break;
-               case RXD_MODE_3B:
-                   DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n",
-                                               dev->name);
-                   break;
-               case RXD_MODE_3A:
-                   DBG_PRINT(ERR_DBG, "%s: 3-Buffer receive mode enabled\n",
-                                               dev->name);
-                   break;
-       }
-#ifdef CONFIG_S2IO_NAPI
-       DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
-#endif
-       switch(sp->intr_type) {
-               case INTA:
-                   DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
-                   break;
-               case MSI:
-                   DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI\n", dev->name);
-                   break;
-               case MSI_X:
-                   DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
-                   break;
-       }
-       if (sp->lro)
-               DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
+       } else {
+               DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
                          dev->name);
+               DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+                                       get_xena_rev_id(sp->pdev),
+                                       s2io_driver_version);
+               switch(sp->intr_type) {
+                       case INTA:
+                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
+                               break;
+                       case MSI:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
+                               break;
+                       case MSI_X:
+                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
+                               break;
+               }
+               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],
+                         sp->def_mac_addr[0].mac_addr[2],
+                         sp->def_mac_addr[0].mac_addr[3],
+                         sp->def_mac_addr[0].mac_addr[4],
+                         sp->def_mac_addr[0].mac_addr[5]);
+       }
+       if (sp->rxd_mode == RXD_MODE_3B)
+               DBG_PRINT(ERR_DBG, "%s: 2-Buffer mode support has been "
+                         "enabled\n",dev->name);
+       if (sp->rxd_mode == RXD_MODE_3A)
+               DBG_PRINT(ERR_DBG, "%s: 3-Buffer mode support has been "
+                         "enabled\n",dev->name);
 
        /* Initialize device name */
-       sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name);
+       strcpy(sp->name, dev->name);
+       if (sp->device_type & XFRAME_II_DEVICE)
+               strcat(sp->name, ": Neterion Xframe II 10GbE adapter");
+       else
+               strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
 
        /* Initialize bimodal Interrupts */
        sp->config.bimodal = bimodal;
@@ -7241,7 +6344,7 @@ int __init s2io_starter(void)
  * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
  */
 
-static void s2io_closer(void)
+void s2io_closer(void)
 {
        pci_unregister_driver(&s2io_driver);
        DBG_PRINT(INIT_DBG, "cleanup done\n");
@@ -7249,321 +6352,3 @@ static void s2io_closer(void)
 
 module_init(s2io_starter);
 module_exit(s2io_closer);
-
-static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, 
-               struct tcphdr **tcp, RxD_t *rxdp)
-{
-       int ip_off;
-       u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len;
-
-       if (!(rxdp->Control_1 & RXD_FRAME_PROTO_TCP)) {
-               DBG_PRINT(INIT_DBG,"%s: Non-TCP frames not supported for LRO\n",
-                         __FUNCTION__);
-               return -1;
-       }
-
-       /* TODO:
-        * By default the VLAN field in the MAC is stripped by the card, if this
-        * feature is turned off in rx_pa_cfg register, then the ip_off field
-        * has to be shifted by a further 2 bytes
-        */
-       switch (l2_type) {
-               case 0: /* DIX type */
-               case 4: /* DIX type with VLAN */
-                       ip_off = HEADER_ETHERNET_II_802_3_SIZE;
-                       break;
-               /* LLC, SNAP etc are considered non-mergeable */
-               default:
-                       return -1;
-       }
-
-       *ip = (struct iphdr *)((u8 *)buffer + ip_off);
-       ip_len = (u8)((*ip)->ihl);
-       ip_len <<= 2;
-       *tcp = (struct tcphdr *)((unsigned long)*ip + ip_len);
-
-       return 0;
-}
-
-static int check_for_socket_match(lro_t *lro, struct iphdr *ip,
-                                 struct tcphdr *tcp)
-{
-       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
-       if ((lro->iph->saddr != ip->saddr) || (lro->iph->daddr != ip->daddr) ||
-          (lro->tcph->source != tcp->source) || (lro->tcph->dest != tcp->dest))
-               return -1;
-       return 0;
-}
-
-static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
-{
-       return(ntohs(ip->tot_len) - (ip->ihl << 2) - (tcp->doff << 2));
-}
-
-static void initiate_new_session(lro_t *lro, u8 *l2h,
-                    struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len)
-{
-       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
-       lro->l2h = l2h;
-       lro->iph = ip;
-       lro->tcph = tcp;
-       lro->tcp_next_seq = tcp_pyld_len + ntohl(tcp->seq);
-       lro->tcp_ack = ntohl(tcp->ack_seq);
-       lro->sg_num = 1;
-       lro->total_len = ntohs(ip->tot_len);
-       lro->frags_len = 0;
-       /* 
-        * check if we saw TCP timestamp. Other consistency checks have
-        * already been done.
-        */
-       if (tcp->doff == 8) {
-               u32 *ptr;
-               ptr = (u32 *)(tcp+1);
-               lro->saw_ts = 1;
-               lro->cur_tsval = *(ptr+1);
-               lro->cur_tsecr = *(ptr+2);
-       }
-       lro->in_use = 1;
-}
-
-static void update_L3L4_header(nic_t *sp, lro_t *lro)
-{
-       struct iphdr *ip = lro->iph;
-       struct tcphdr *tcp = lro->tcph;
-       u16 nchk;
-       StatInfo_t *statinfo = sp->mac_control.stats_info;
-       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
-
-       /* Update L3 header */
-       ip->tot_len = htons(lro->total_len);
-       ip->check = 0;
-       nchk = ip_fast_csum((u8 *)lro->iph, ip->ihl);
-       ip->check = nchk;
-
-       /* Update L4 header */
-       tcp->ack_seq = lro->tcp_ack;
-       tcp->window = lro->window;
-
-       /* Update tsecr field if this session has timestamps enabled */
-       if (lro->saw_ts) {
-               u32 *ptr = (u32 *)(tcp + 1);
-               *(ptr+2) = lro->cur_tsecr;
-       }
-
-       /* Update counters required for calculation of
-        * average no. of packets aggregated.
-        */
-       statinfo->sw_stat.sum_avg_pkts_aggregated += lro->sg_num;
-       statinfo->sw_stat.num_aggregations++;
-}
-
-static void aggregate_new_rx(lro_t *lro, struct iphdr *ip,
-               struct tcphdr *tcp, u32 l4_pyld)
-{
-       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
-       lro->total_len += l4_pyld;
-       lro->frags_len += l4_pyld;
-       lro->tcp_next_seq += l4_pyld;
-       lro->sg_num++;
-
-       /* Update ack seq no. and window ad(from this pkt) in LRO object */
-       lro->tcp_ack = tcp->ack_seq;
-       lro->window = tcp->window;
-       
-       if (lro->saw_ts) {
-               u32 *ptr;
-               /* Update tsecr and tsval from this packet */
-               ptr = (u32 *) (tcp + 1);
-               lro->cur_tsval = *(ptr + 1); 
-               lro->cur_tsecr = *(ptr + 2);
-       }
-}
-
-static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip,
-                                   struct tcphdr *tcp, u32 tcp_pyld_len)
-{
-       u8 *ptr;
-
-       DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
-
-       if (!tcp_pyld_len) {
-               /* Runt frame or a pure ack */
-               return -1;
-       }
-
-       if (ip->ihl != 5) /* IP has options */
-               return -1;
-
-       /* If we see CE codepoint in IP header, packet is not mergeable */
-       if (INET_ECN_is_ce(ipv4_get_dsfield(ip)))
-               return -1;
-
-       /* If we see ECE or CWR flags in TCP header, packet is not mergeable */
-       if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin ||
-                                   tcp->ece || tcp->cwr || !tcp->ack) {
-               /*
-                * Currently recognize only the ack control word and
-                * any other control field being set would result in
-                * flushing the LRO session
-                */
-               return -1;
-       }
-
-       /* 
-        * Allow only one TCP timestamp option. Don't aggregate if
-        * any other options are detected.
-        */
-       if (tcp->doff != 5 && tcp->doff != 8)
-               return -1;
-
-       if (tcp->doff == 8) {
-               ptr = (u8 *)(tcp + 1);  
-               while (*ptr == TCPOPT_NOP)
-                       ptr++;
-               if (*ptr != TCPOPT_TIMESTAMP || *(ptr+1) != TCPOLEN_TIMESTAMP)
-                       return -1;
-
-               /* Ensure timestamp value increases monotonically */
-               if (l_lro)
-                       if (l_lro->cur_tsval > *((u32 *)(ptr+2)))
-                               return -1;
-
-               /* timestamp echo reply should be non-zero */
-               if (*((u32 *)(ptr+6)) == 0) 
-                       return -1;
-       }
-
-       return 0;
-}
-
-static int
-s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, lro_t **lro,
-                     RxD_t *rxdp, nic_t *sp)
-{
-       struct iphdr *ip;
-       struct tcphdr *tcph;
-       int ret = 0, i;
-
-       if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
-                                        rxdp))) {
-               DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n",
-                         ip->saddr, ip->daddr);
-       } else {
-               return ret;
-       }
-
-       tcph = (struct tcphdr *)*tcp;
-       *tcp_len = get_l4_pyld_length(ip, tcph);
-       for (i=0; i<MAX_LRO_SESSIONS; i++) {
-               lro_t *l_lro = &sp->lro0_n[i];
-               if (l_lro->in_use) {
-                       if (check_for_socket_match(l_lro, ip, tcph))
-                               continue;
-                       /* Sock pair matched */
-                       *lro = l_lro;
-
-                       if ((*lro)->tcp_next_seq != ntohl(tcph->seq)) {
-                               DBG_PRINT(INFO_DBG, "%s:Out of order. expected "
-                                         "0x%x, actual 0x%x\n", __FUNCTION__,
-                                         (*lro)->tcp_next_seq,
-                                         ntohl(tcph->seq));
-
-                               sp->mac_control.stats_info->
-                                  sw_stat.outof_sequence_pkts++;
-                               ret = 2;
-                               break;
-                       }
-
-                       if (!verify_l3_l4_lro_capable(l_lro, ip, tcph,*tcp_len))
-                               ret = 1; /* Aggregate */
-                       else
-                               ret = 2; /* Flush both */
-                       break;
-               }
-       }
-
-       if (ret == 0) {
-               /* Before searching for available LRO objects,
-                * check if the pkt is L3/L4 aggregatable. If not
-                * don't create new LRO session. Just send this
-                * packet up.
-                */
-               if (verify_l3_l4_lro_capable(NULL, ip, tcph, *tcp_len)) {
-                       return 5;
-               }
-
-               for (i=0; i<MAX_LRO_SESSIONS; i++) {
-                       lro_t *l_lro = &sp->lro0_n[i];
-                       if (!(l_lro->in_use)) {
-                               *lro = l_lro;
-                               ret = 3; /* Begin anew */
-                               break;
-                       }
-               }
-       }
-
-       if (ret == 0) { /* sessions exceeded */
-               DBG_PRINT(INFO_DBG,"%s:All LRO sessions already in use\n",
-                         __FUNCTION__);
-               *lro = NULL;
-               return ret;
-       }
-
-       switch (ret) {
-               case 3:
-                       initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
-                       break;
-               case 2:
-                       update_L3L4_header(sp, *lro);
-                       break;
-               case 1:
-                       aggregate_new_rx(*lro, ip, tcph, *tcp_len);
-                       if ((*lro)->sg_num == sp->lro_max_aggr_per_sess) {
-                               update_L3L4_header(sp, *lro);
-                               ret = 4; /* Flush the LRO */
-                       }
-                       break;
-               default:
-                       DBG_PRINT(ERR_DBG,"%s:Dont know, can't say!!\n",
-                               __FUNCTION__);
-                       break;
-       }
-
-       return ret;
-}
-
-static void clear_lro_session(lro_t *lro)
-{
-       static u16 lro_struct_size = sizeof(lro_t);
-
-       memset(lro, 0, lro_struct_size);
-}
-
-static void queue_rx_frame(struct sk_buff *skb)
-{
-       struct net_device *dev = skb->dev;
-
-       skb->protocol = eth_type_trans(skb, dev);
-#ifdef CONFIG_S2IO_NAPI
-       netif_receive_skb(skb);
-#else
-       netif_rx(skb);
-#endif
-}
-
-static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb,
-                          u32 tcp_len)
-{
-       struct sk_buff *first = lro->parent;
-
-       first->len += tcp_len;
-       first->data_len = lro->frags_len;
-       skb_pull(skb, (skb->len - tcp_len));
-       if (skb_shinfo(first)->frag_list)
-               lro->last_frag->next = skb;
-       else
-               skb_shinfo(first)->frag_list = skb;
-       lro->last_frag = skb;
-       sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
-       return;
-}