WorkStruct: make allyesconfig
[safe/jmp/linux-2.6] / drivers / net / s2io.c
index 25d289e..250cdbe 100644 (file)
 #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.14.2"
+#define DRV_VERSION "2.0.15.2"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -370,38 +371,50 @@ 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. */
-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};
-static unsigned int rx_ring_num = 1;
-static unsigned int rx_ring_sz[MAX_RX_RINGS] =
-    {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
-static unsigned int rts_frm_len[MAX_RX_RINGS] =
-    {[0 ...(MAX_RX_RINGS - 1)] = 0 };
-static unsigned int rx_ring_mode = 1;
-static unsigned int use_continuous_tx_intrs = 1;
-static unsigned int rmac_pause_time = 0x100;
-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
+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 */
-static unsigned int rxsync_frequency = 3;
+S2IO_PARM_INT(rxsync_frequency, 3);
 /* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
-static unsigned int intr_type = 0;
+S2IO_PARM_INT(intr_type, 0);
 /* Large receive offload feature */
-static unsigned int lro = 0;
+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)
  */
-static unsigned int lro_max_pkts = 0xFFFF;
+S2IO_PARM_INT(lro_max_pkts, 0xFFFF);
+#ifndef CONFIG_S2IO_NAPI
+S2IO_PARM_INT(indicate_max_pkts, 0);
+#endif
+
+static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
+    {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
+static unsigned int rx_ring_sz[MAX_RX_RINGS] =
+    {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
+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);
 
 /*
  * S2IO device table.
@@ -464,10 +477,9 @@ 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, "%s: Requested TxDs too high, ",
-                         __FUNCTION__);
+               DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, ");
                DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
-               return FAILURE;
+               return -EINVAL;
        }
 
        lst_size = (sizeof(TxD_t) * config->max_txds);
@@ -518,9 +530,9 @@ static int init_shared_mem(struct s2io_nic *nic)
                         */
                        if (!tmp_p) {
                                mac_control->zerodma_virt_addr = tmp_v;
-                               DBG_PRINT(INIT_DBG, 
+                               DBG_PRINT(INIT_DBG,
                                "%s: Zero DMA address for TxDL. ", dev->name);
-                               DBG_PRINT(INIT_DBG, 
+                               DBG_PRINT(INIT_DBG,
                                "Virtual address %p\n", tmp_v);
                                tmp_v = pci_alloc_consistent(nic->pdev,
                                                     PAGE_SIZE, &tmp_p);
@@ -547,6 +559,7 @@ 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;
@@ -743,7 +756,7 @@ static void free_shared_mem(struct s2io_nic *nic)
                for (j = 0; j < page_num; j++) {
                        int mem_blks = (j * lst_per_page);
                        if (!mac_control->fifos[i].list_info)
-                               return; 
+                               return;
                        if (!mac_control->fifos[i].list_info[mem_blks].
                                 list_virt_addr)
                                break;
@@ -762,7 +775,7 @@ static void free_shared_mem(struct s2io_nic *nic)
                        pci_free_consistent(nic->pdev, PAGE_SIZE,
                                            mac_control->zerodma_virt_addr,
                                            (dma_addr_t)0);
-                       DBG_PRINT(INIT_DBG, 
+                       DBG_PRINT(INIT_DBG,
                                "%s: Freeing TxDL with zero DMA addr. ",
                                dev->name);
                        DBG_PRINT(INIT_DBG, "Virtual address %p\n",
@@ -842,9 +855,10 @@ static int s2io_verify_pci_mode(nic_t *nic)
 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)){
+       while ((tdev = pci_get_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)
+                               pci_dev_put(tdev);
                                return 1;
                }
        }
@@ -1213,7 +1227,7 @@ static int init_nic(struct s2io_nic *nic)
                break;
        }
 
-       /* Enable Tx FIFO partition 0. */
+       /* 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);
@@ -1263,7 +1277,7 @@ static int init_nic(struct s2io_nic *nic)
                writeq(val64, &bar0->rx_w_round_robin_1);
                val64 = 0x0200010000010203ULL;
                writeq(val64, &bar0->rx_w_round_robin_2);
-               val64 = 0x0001020001000001ULL;  
+               val64 = 0x0001020001000001ULL;
                writeq(val64, &bar0->rx_w_round_robin_3);
                val64 = 0x0203000100000000ULL;
                writeq(val64, &bar0->rx_w_round_robin_4);
@@ -1650,7 +1664,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
-                        * disabled all PCIX, Flash, MDIO, IIC and GPIO
+                        * disable all PCIX, Flash, MDIO, IIC and GPIO
                         * interrupts for now.
                         * TODO
                         */
@@ -1976,7 +1990,6 @@ 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;
@@ -2047,16 +2060,6 @@ 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,
@@ -2125,12 +2128,12 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
                        if (!txds->Buffer_Pointer)
                                break;
-                       pci_unmap_page(nic->pdev, (dma_addr_t) 
+                       pci_unmap_page(nic->pdev, (dma_addr_t)
                                        txds->Buffer_Pointer,
                                       frag->size, PCI_DMA_TODEVICE);
                }
        }
-       txdlp->Host_Control = 0;
+       memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds));
        return(skb);
 }
 
@@ -2382,25 +2385,33 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                        skb->data = (void *) (unsigned long)tmp;
                        skb->tail = (void *) (unsigned long)tmp;
 
-                       ((RxD3_t*)rxdp)->Buffer0_ptr =
-                           pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
+                       if (!(((RxD3_t*)rxdp)->Buffer0_ptr))
+                               ((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 */
 
                                /*
-                                * Buffer2 will have L3/L4 header plus 
+                                * Buffer2 will have L3/L4 header plus
                                 * L4 payload
                                 */
                                ((RxD3_t*)rxdp)->Buffer2_ptr = pci_map_single
                                (nic->pdev, skb->data, dev->mtu + 4,
                                                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);
+                               /* 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);
+                               }
                                rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
                                rxdp->Control_2 |= SET_BUFFER2_SIZE_3
                                                                (dev->mtu + 4);
@@ -2499,7 +2510,7 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk)
                                ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN,
                                PCI_DMA_FROMDEVICE);
                        pci_unmap_single(sp->pdev, (dma_addr_t)
-                               ((RxD3_t*)rxdp)->Buffer1_ptr, 
+                               ((RxD3_t*)rxdp)->Buffer1_ptr,
                                l3l4hdr_size + 4,
                                PCI_DMA_FROMDEVICE);
                        pci_unmap_single(sp->pdev, (dma_addr_t)
@@ -2625,23 +2636,23 @@ no_rx:
 }
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
 /**
- * s2io_netpoll - Rx interrupt service handler for netpoll support
+ * s2io_netpoll - netpoll event handler entry point
  * @dev : pointer to the device structure.
  * Description:
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
+ *     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).
  */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
 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;
+       u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
        int i;
 
        disable_irq(dev->irq);
@@ -2650,9 +2661,17 @@ static void s2io_netpoll(struct net_device *dev)
        mac_control = &nic->mac_control;
        config = &nic->config;
 
-       val64 = readq(&bar0->rx_traffic_int);
        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]);
 
@@ -2719,7 +2738,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(ERR_DBG, "%s: Ring Full\n",dev->name);
+                       DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name);
                        break;
                }
                skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
@@ -2739,18 +2758,15 @@ 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_unmap_single(nic->pdev, (dma_addr_t)
+                       pci_dma_sync_single_for_cpu(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_unmap_single(nic->pdev, (dma_addr_t)
+                       pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
                                         ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN,
                                         PCI_DMA_FROMDEVICE);
                        pci_unmap_single(nic->pdev, (dma_addr_t)
@@ -2888,7 +2904,7 @@ static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device
 {
        u64 val64 = 0x0;
        nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        //address transaction
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -2937,7 +2953,7 @@ 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;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        /* address transaction */
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -3194,7 +3210,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        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", 
+               DBG_PRINT(ERR_DBG, "serious error %llx!!\n",
                          (unsigned long long)val64);
                netif_stop_queue(dev);
                schedule_work(&nic->rst_timer_task);
@@ -3260,7 +3276,7 @@ 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(void __iomem *addr, u64 busy_bit)
 {
        int ret = FAILURE, cnt = 0;
        u64 val64;
@@ -3338,7 +3354,7 @@ static void s2io_reset(nic_t * sp)
 
        /* Clear certain PCI/PCI-X fields after reset */
        if (sp->device_type == XFRAME_II_DEVICE) {
-               /* Clear parity err detect bit */
+               /* Clear "detected parity error" bit */
                pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);
 
                /* Clearing PCIX Ecc status register */
@@ -3539,7 +3555,7 @@ static void restore_xmsi_data(nic_t *nic)
        u64 val64;
        int i;
 
-       for (i=0; i< nic->avail_msix_vectors; 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));
@@ -3558,7 +3574,7 @@ static void store_xmsi_data(nic_t *nic)
        int i;
 
        /* Store and display */
-       for (i=0; i< nic->avail_msix_vectors; 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)) {
@@ -3749,101 +3765,19 @@ static int s2io_open(struct net_device *dev)
        if (err) {
                DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
                          dev->name);
-               if (err == -ENODEV)
-                       goto hw_init_failed;
-               else
-                       goto hw_enable_failed;
-       }
-
-       /* 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) {
-               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->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;
-               }
+               goto hw_init_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 setting_mac_address_failed;
+               goto hw_init_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) {
-               int i;
-               u16 msi_control; /* Temp variable */
-
-               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);
-hw_enable_failed:
-       s2io_reset(sp);
 hw_init_failed:
        if (sp->intr_type == MSI_X) {
                if (sp->entries)
@@ -3874,7 +3808,7 @@ static int s2io_close(struct net_device *dev)
        flush_scheduled_work();
        netif_stop_queue(dev);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
-       s2io_card_down(sp, 1);
+       s2io_card_down(sp);
 
        sp->device_close_flag = TRUE;   /* Device is shut down. */
        return 0;
@@ -3901,13 +3835,11 @@ 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;
@@ -3955,16 +3887,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
 
-       txdp->Control_1 = 0;
-       txdp->Control_2 = 0;
+       offload_type = s2io_offload_type(skb);
 #ifdef NETIF_F_TSO
-       mss = skb_shinfo(skb)->gso_size;
-       if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) {
+       if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
                txdp->Control_1 |= TXD_TCP_LSO_EN;
-               txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
+               txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb));
        }
 #endif
-       if (skb->ip_summed == CHECKSUM_HW) {
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                txdp->Control_2 |=
                    (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN |
                     TXD_TX_CKO_UDP_EN);
@@ -3979,10 +3909,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        frg_len = skb->len - skb->data_len;
-       if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) {
+       if (offload_type == SKB_GSO_UDP) {
                int ufo_size;
 
-               ufo_size = skb_shinfo(skb)->gso_size;
+               ufo_size = s2io_udp_mss(skb);
                ufo_size &= ~7;
                txdp->Control_1 |= TXD_UFO_EN;
                txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
@@ -3999,16 +3929,13 @@ 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 (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+       if (offload_type == SKB_GSO_UDP)
                txdp->Control_1 |= TXD_UFO_EN;
 
        frg_cnt = skb_shinfo(skb)->nr_frags;
@@ -4023,12 +3950,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 (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+               if (offload_type == SKB_GSO_UDP)
                        txdp->Control_1 |= TXD_UFO_EN;
        }
        txdp->Control_1 |= TXD_GATHER_CODE_LAST;
 
-       if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+       if (offload_type == SKB_GSO_UDP)
                frg_cnt++; /* as Txd0 was used for inband header */
 
        tx_fifo = mac_control->tx_FIFO_start[queue];
@@ -4037,13 +3964,9 @@ 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);
-
-#ifdef NETIF_F_TSO
-       if (mss)
-               val64 |= TX_FIFO_SPECIAL_FUNC;
-#endif
-       if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+       if (offload_type)
                val64 |= TX_FIFO_SPECIAL_FUNC;
+
        writeq(val64, &tx_fifo->List_Control);
 
        mmiowb();
@@ -4077,13 +4000,40 @@ s2io_alarm_handle(unsigned long data)
        mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
 }
 
-static irqreturn_t
-s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
+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 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;
 
@@ -4105,83 +4055,28 @@ 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++) {
-               if (!sp->lro) {
-                       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);
-                       }
-               }
-               else if (fill_rx_buffers(sp, i) == -ENOMEM) {
-                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
-                                                       dev->name);
-                               DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
-                               break;
-               }
-       }
+       for (i = 0; i < config->rx_ring_num; i++)
+               s2io_chk_rx_buffers(sp, i);
 
        atomic_dec(&sp->isr_cnt);
        return IRQ_HANDLED;
 }
 
-static irqreturn_t
-s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
 {
        ring_info_t *ring = (ring_info_t *)dev_id;
        nic_t *sp = ring->nic;
-       struct net_device *dev = (struct net_device *) dev_id;
-       int rxb_size, level, rng_n;
 
        atomic_inc(&sp->isr_cnt);
-       rx_intr_handler(ring);
 
-       rng_n = ring->ring_no;
-       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 IRQ_HANDLED;
-                       }
-                       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", dev->name);
-                       DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
-       }
+       rx_intr_handler(ring);
+       s2io_chk_rx_buffers(sp, ring->ring_no);
 
        atomic_dec(&sp->isr_cnt);
-
        return IRQ_HANDLED;
 }
 
-static irqreturn_t
-s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id)
 {
        fifo_info_t *fifo = (fifo_info_t *)dev_id;
        nic_t *sp = fifo->nic;
@@ -4257,7 +4152,6 @@ static void s2io_txpic_intr_handle(nic_t *sp)
  *  s2io_isr - ISR handler of the device .
  *  @irq: the irq of the device.
  *  @dev_id: a void pointer to the dev structure of the NIC.
- *  @pt_regs: pointer to the registers pushed on the stack.
  *  Description:  This function is the ISR handler of the device. It
  *  identifies the reason for the interrupt and calls the relevant
  *  service routines. As a contongency measure, this ISR allocates the
@@ -4267,7 +4161,7 @@ static void s2io_txpic_intr_handle(nic_t *sp)
  *   IRQ_HANDLED: will be returned if IRQ was handled by this routine
  *   IRQ_NONE: will be returned if interrupt is not from our device
  */
-static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_isr(int irq, void *dev_id)
 {
        struct net_device *dev = (struct net_device *) dev_id;
        nic_t *sp = dev->priv;
@@ -4341,37 +4235,8 @@ 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++) {
-               if (!sp->lro) {
-                       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);
-                                       writeq(org_mask, &bar0->general_int_mask);
-                                       return IRQ_HANDLED;
-                               }
-                               clear_bit(0, (&sp->tasklet_status));
-                       } else if (level == LOW) {
-                               tasklet_schedule(&sp->task);
-                       }
-               }
-               else if (fill_rx_buffers(sp, i) == -ENOMEM) {
-                               DBG_PRINT(ERR_DBG, "%s:Out of memory",
-                                                       dev->name);
-                               DBG_PRINT(ERR_DBG, " in Rx intr!!\n");
-                               break;
-               }
-       }
+       for (i = 0; i < config->rx_ring_num; i++)
+               s2io_chk_rx_buffers(sp, i);
 #endif
        writeq(org_mask, &bar0->general_int_mask);
        atomic_dec(&sp->isr_cnt);
@@ -4401,6 +4266,8 @@ 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));
        }
 }
 
@@ -4432,11 +4299,11 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
        sp->stats.tx_errors =
                le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
        sp->stats.rx_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_drop_frms);
        sp->stats.multicast =
                le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
        sp->stats.rx_length_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_long_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_long_frms);
 
        return (&sp->stats);
 }
@@ -4946,7 +4813,7 @@ static int read_eeprom(nic_t * sp, int off, u64 * data)
 
        if (sp->device_type == XFRAME_II_DEVICE) {
                val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
-                       SPI_CONTROL_BYTECNT(0x3) | 
+                       SPI_CONTROL_BYTECNT(0x3) |
                        SPI_CONTROL_CMD(0x3) | SPI_CONTROL_ADDR(off);
                SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
                val64 |= SPI_CONTROL_REQ;
@@ -5013,7 +4880,7 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
                writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
 
                val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
-                       SPI_CONTROL_BYTECNT(write_cnt) | 
+                       SPI_CONTROL_BYTECNT(write_cnt) |
                        SPI_CONTROL_CMD(0x2) | SPI_CONTROL_ADDR(off);
                SPECIAL_REG_WRITE(val64, &bar0->spi_control, LF);
                val64 |= SPI_CONTROL_REQ;
@@ -5035,7 +4902,8 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
 }
 static void s2io_vpd_read(nic_t *nic)
 {
-       u8 vpd_data[256],data;
+       u8 *vpd_data;
+       u8 data;
        int i=0, cnt, fail = 0;
        int vpd_addr = 0x80;
 
@@ -5048,6 +4916,10 @@ static void s2io_vpd_read(nic_t *nic)
                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);
@@ -5070,6 +4942,7 @@ static void s2io_vpd_read(nic_t *nic)
                memset(nic->product_name, 0, vpd_data[1]);
                memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
        }
+       kfree(vpd_data);
 }
 
 /**
@@ -5388,7 +5261,7 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)
        else
                *data = 0;
 
-       return 0;
+       return *data;
 }
 
 /**
@@ -5770,7 +5643,7 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        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.
                 */
@@ -5846,8 +5719,21 @@ 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);
 
-static struct ethtool_ops netdev_ethtool_ops = {
+       return 0;
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
        .get_settings = s2io_ethtool_gset,
        .set_settings = s2io_ethtool_sset,
        .get_drvinfo = s2io_ethtool_gdrvinfo,
@@ -5866,8 +5752,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 = ethtool_op_get_tso,
-       .set_tso = ethtool_op_set_tso,
+       .get_tso = s2io_ethtool_op_get_tso,
+       .set_tso = s2io_ethtool_op_set_tso,
 #endif
        .get_ufo = ethtool_op_get_ufo,
        .set_ufo = ethtool_op_set_ufo,
@@ -5919,7 +5805,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
 
        dev->mtu = new_mtu;
        if (netif_running(dev)) {
-               s2io_card_down(sp, 0);
+               s2io_card_down(sp);
                netif_stop_queue(dev);
                if (s2io_card_up(sp)) {
                        DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -5986,9 +5872,9 @@ static void s2io_tasklet(unsigned long dev_addr)
  * Description: Sets the link status for the adapter
  */
 
-static void s2io_set_link(unsigned long data)
+static void s2io_set_link(struct work_struct *work)
 {
-       nic_t *nic = (nic_t *) data;
+       nic_t *nic = container_of(work, nic_t, set_link_task);
        struct net_device *dev = nic->dev;
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        register u64 val64;
@@ -6099,6 +5985,11 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
                        ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
                } else {
                        *skb = dev_alloc_skb(size);
+                       if (!(*skb)) {
+                               DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n",
+                                         dev->name);
+                               return -ENOMEM;
+                       }
                        ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
                                pci_map_single(sp->pdev, (*skb)->data,
                                               dev->mtu + 4,
@@ -6121,7 +6012,11 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
                        ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
                } else {
                        *skb = dev_alloc_skb(size);
-
+                       if (!(*skb)) {
+                               DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n",
+                                         dev->name);
+                               return -ENOMEM;
+                       }
                        ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
                                pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN,
                                               PCI_DMA_FROMDEVICE);
@@ -6216,43 +6111,106 @@ static  int rxd_owner_bit_reset(nic_t *sp)
 
 }
 
-static void s2io_card_down(nic_t * sp, int flag)
+static int s2io_add_isr(nic_t * sp)
 {
-       int cnt = 0;
-       XENA_dev_config_t __iomem *bar0 = sp->bar0;
-       unsigned long flags;
-       register u64 val64 = 0;
+       int ret = 0;
        struct net_device *dev = sp->dev;
+       int err = 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);
+       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;
        }
-       atomic_set(&sp->card_state, CARD_DOWN);
 
-       /* disable Tx and Rx traffic on the NIC */
-       stop_nic(sp);
-       if (flag) {
-               if (sp->intr_type == MSI_X) {
-                       int i;
-                       u16 msi_control;
+       /* Store the values of the MSIX table in the nic_t structure */
+       store_xmsi_data(sp);
 
-                       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;
+       /* 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;
 
-                               free_irq(vector, arg);
+               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);
                        }
-                       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);
+                       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 */
@@ -6263,6 +6221,26 @@ static void s2io_card_down(nic_t * sp, int flag)
                        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);
@@ -6314,23 +6292,16 @@ 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
@@ -6354,28 +6325,46 @@ static int s2io_card_up(nic_t * sp)
        s2io_set_multicast(dev);
 
        if (sp->lro) {
-               /* Initialize max aggregatable pkts based on MTU */
+               /* 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_irq(dev->irq, dev);
+               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_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;
 }
@@ -6390,12 +6379,12 @@ static int s2io_card_up(nic_t * sp)
  * spin lock.
  */
 
-static void s2io_restart_nic(unsigned long data)
+static void s2io_restart_nic(struct work_struct *work)
 {
-       struct net_device *dev = (struct net_device *) data;
-       nic_t *sp = dev->priv;
+       nic_t *sp = container_of(work, nic_t, rst_timer_task);
+       struct net_device *dev = sp->dev;
 
-       s2io_card_down(sp, 0);
+       s2io_card_down(sp);
        if (s2io_card_up(sp)) {
                DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
                          dev->name);
@@ -6437,7 +6426,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 Tx interrupt serivce routine to perform
+ *   This function is called by the Rx 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
@@ -6614,7 +6603,7 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
        } else {
 send_up:
                queue_rx_frame(skb);
-       }               
+       }
        dev->last_rx = jiffies;
 aggregate:
        atomic_dec(&sp->rx_bufs_left[ring_no]);
@@ -6697,33 +6686,6 @@ static void s2io_init_pci(nic_t * sp)
        pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
 }
 
-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
-module_param(rxsync_frequency, int, 0);
-module_param(intr_type, int, 0);
-module_param(lro, int, 0);
-module_param(lro_max_pkts, int, 0);
-
 static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
 {
        if ( tx_fifo_num > 8) {
@@ -6761,7 +6723,7 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
        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. " 
+               DBG_PRINT(ERR_DBG, "s2io: Xframe I does not support MSI_X. "
                                        "Defaulting to INTA\n");
                *dev_intr_type = INTA;
        }
@@ -6831,8 +6793,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        }
        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;
                }
        }
@@ -6889,7 +6851,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                sp->device_type = XFRAME_I_DEVICE;
 
        sp->lro = lro;
-               
+
        /* Initialize some PCI/PCI-X fields of the NIC. */
        s2io_init_pci(sp);
 
@@ -6956,7 +6918,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",
-                         __FUNCTION__);
+                         dev->name);
                ret = -ENOMEM;
                goto mem_alloc_failed;
        }
@@ -7020,6 +6982,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 #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;
                dev->features |= NETIF_F_HW_CSUM;
@@ -7027,10 +6992,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
        dev->tx_timeout = &s2io_tx_watchdog;
        dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
-       INIT_WORK(&sp->rst_timer_task,
-                 (void (*)(void *)) s2io_restart_nic, dev);
-       INIT_WORK(&sp->set_link_task,
-                 (void (*)(void *)) s2io_set_link, sp);
+       INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
+       INIT_WORK(&sp->set_link_task, s2io_set_link);
 
        pci_save_state(sp->pdev);
 
@@ -7090,6 +7053,9 @@ 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
@@ -7127,11 +7093,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
                goto register_failed;
        }
        s2io_vpd_read(sp);
-       DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name);
-       DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n",
-                               get_xena_rev_id(sp->pdev),
-                               s2io_driver_version);
        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,
                          sp->def_mac_addr[0].mac_addr[0],
@@ -7271,7 +7237,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
 
 int __init s2io_starter(void)
 {
-       return pci_module_init(&s2io_driver);
+       return pci_register_driver(&s2io_driver);
 }
 
 /**
@@ -7288,7 +7254,7 @@ static void s2io_closer(void)
 module_init(s2io_starter);
 module_exit(s2io_closer);
 
-static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip, 
+static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
                struct tcphdr **tcp, RxD_t *rxdp)
 {
        int ip_off;
@@ -7350,7 +7316,7 @@ static void initiate_new_session(lro_t *lro, u8 *l2h,
        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.
         */
@@ -7407,12 +7373,12 @@ static void aggregate_new_rx(lro_t *lro, struct iphdr *ip,
        /* 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_tsval = *(ptr + 1);
                lro->cur_tsecr = *(ptr + 2);
        }
 }
@@ -7432,8 +7398,13 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip,
        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->ack) {
+                                   tcp->ece || tcp->cwr || !tcp->ack) {
                /*
                 * Currently recognize only the ack control word and
                 * any other control field being set would result in
@@ -7442,7 +7413,7 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip,
                return -1;
        }
 
-       /* 
+       /*
         * Allow only one TCP timestamp option. Don't aggregate if
         * any other options are detected.
         */
@@ -7450,7 +7421,7 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip,
                return -1;
 
        if (tcp->doff == 8) {
-               ptr = (u8 *)(tcp + 1);  
+               ptr = (u8 *)(tcp + 1);
                while (*ptr == TCPOPT_NOP)
                        ptr++;
                if (*ptr != TCPOPT_TIMESTAMP || *(ptr+1) != TCPOLEN_TIMESTAMP)
@@ -7462,7 +7433,7 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip,
                                return -1;
 
                /* timestamp echo reply should be non-zero */
-               if (*((u32 *)(ptr+6)) == 0) 
+               if (*((u32 *)(ptr+6)) == 0)
                        return -1;
        }
 
@@ -7587,18 +7558,16 @@ static void queue_rx_frame(struct sk_buff *skb)
 static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb,
                           u32 tcp_len)
 {
-       struct sk_buff *tmp, *first = lro->parent;
+       struct sk_buff *first = lro->parent;
 
        first->len += tcp_len;
        first->data_len = lro->frags_len;
        skb_pull(skb, (skb->len - tcp_len));
-       if ((tmp = skb_shinfo(first)->frag_list)) {
-               while (tmp->next)
-                       tmp = tmp->next;
-               tmp->next = skb;
-       }
+       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;
 }