[PATCH] gianfar: Use new PHY_ID_FMT macro
[safe/jmp/linux-2.6] / drivers / net / s2io.c
index 30fbaf0..89c4678 100644 (file)
@@ -30,6 +30,8 @@
  * in the driver.
  * 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.
@@ -53,7 +55,6 @@
 #include <linux/timex.h>
 #include <linux/sched.h>
 #include <linux/ethtool.h>
-#include <linux/version.h>
 #include <linux/workqueue.h>
 #include <linux/if_vlan.h>
 
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "Version 2.0.9.1"
+#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;
 
+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)
 {
        int ret;
@@ -104,7 +108,7 @@ static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)
        mac_control = &sp->mac_control;
        if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {
                level = LOW;
-               if (rxb_size <= MAX_RXDS_PER_BLOCK) {
+               if (rxb_size <= rxd_count[sp->rxd_mode]) {
                        level = PANIC;
                }
        }
@@ -296,6 +300,7 @@ static unsigned int rx_ring_sz[MAX_RX_RINGS] =
     {[0 ...(MAX_RX_RINGS - 1)] = 0 };
 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 = 65535;
 static unsigned int mc_pause_threshold_q0q3 = 187;
@@ -304,6 +309,7 @@ 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
@@ -357,10 +363,8 @@ static int init_shared_mem(struct s2io_nic *nic)
        int i, j, blk_cnt, rx_sz, tx_sz;
        int lst_size, lst_per_page;
        struct net_device *dev = nic->dev;
-#ifdef CONFIG_2BUFF_MODE
        unsigned long tmp;
        buffAdd_t *ba;
-#endif
 
        mac_info_t *mac_control;
        struct config_param *config;
@@ -408,7 +412,7 @@ static int init_shared_mem(struct s2io_nic *nic)
                    config->tx_cfg[i].fifo_len - 1;
                mac_control->fifos[i].fifo_no = i;
                mac_control->fifos[i].nic = nic;
-               mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 1;
+               mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
 
                for (j = 0; j < page_num; j++) {
                        int k = 0;
@@ -455,10 +459,15 @@ 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;
+
        /* Allocation and initialization of RXDs in Rings */
        size = 0;
        for (i = 0; i < config->rx_ring_num; i++) {
-               if (config->rx_cfg[i].num_rxd % (MAX_RXDS_PER_BLOCK + 1)) {
+               if (config->rx_cfg[i].num_rxd %
+                   (rxd_count[nic->rxd_mode] + 1)) {
                        DBG_PRINT(ERR_DBG, "%s: RxD count of ", dev->name);
                        DBG_PRINT(ERR_DBG, "Ring%d is not a multiple of ",
                                  i);
@@ -467,11 +476,15 @@ static int init_shared_mem(struct s2io_nic *nic)
                }
                size += config->rx_cfg[i].num_rxd;
                mac_control->rings[i].block_count =
-                   config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
-               mac_control->rings[i].pkt_cnt =
-                   config->rx_cfg[i].num_rxd - mac_control->rings[i].block_count;
+                       config->rx_cfg[i].num_rxd /
+                       (rxd_count[nic->rxd_mode] + 1 );
+               mac_control->rings[i].pkt_cnt = config->rx_cfg[i].num_rxd -
+                       mac_control->rings[i].block_count;
        }
-       size = (size * (sizeof(RxD_t)));
+       if (nic->rxd_mode == RXD_MODE_1)
+               size = (size * (sizeof(RxD1_t)));
+       else
+               size = (size * (sizeof(RxD3_t)));
        rx_sz = size;
 
        for (i = 0; i < config->rx_ring_num; i++) {
@@ -486,15 +499,15 @@ static int init_shared_mem(struct s2io_nic *nic)
                mac_control->rings[i].nic = nic;
                mac_control->rings[i].ring_no = i;
 
-               blk_cnt =
-                   config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
+               blk_cnt = config->rx_cfg[i].num_rxd /
+                               (rxd_count[nic->rxd_mode] + 1);
                /*  Allocating all the Rx blocks */
                for (j = 0; j < blk_cnt; j++) {
-#ifndef CONFIG_2BUFF_MODE
-                       size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t));
-#else
-                       size = SIZE_OF_BLOCK;
-#endif
+                       rx_block_info_t *rx_blocks;
+                       int l;
+
+                       rx_blocks = &mac_control->rings[i].rx_blocks[j];
+                       size = SIZE_OF_BLOCK; //size is always page size
                        tmp_v_addr = pci_alloc_consistent(nic->pdev, size,
                                                          &tmp_p_addr);
                        if (tmp_v_addr == NULL) {
@@ -504,11 +517,24 @@ static int init_shared_mem(struct s2io_nic *nic)
                                 * memory that was alloced till the
                                 * failure happened.
                                 */
-                               mac_control->rings[i].rx_blocks[j].block_virt_addr =
-                                   tmp_v_addr;
+                               rx_blocks->block_virt_addr = tmp_v_addr;
                                return -ENOMEM;
                        }
                        memset(tmp_v_addr, 0, size);
+                       rx_blocks->block_virt_addr = tmp_v_addr;
+                       rx_blocks->block_dma_addr = tmp_p_addr;
+                       rx_blocks->rxds = kmalloc(sizeof(rxd_info_t)*
+                                                 rxd_count[nic->rxd_mode],
+                                                 GFP_KERNEL);
+                       for (l=0; l<rxd_count[nic->rxd_mode];l++) {
+                               rx_blocks->rxds[l].virt_addr =
+                                       rx_blocks->block_virt_addr +
+                                       (rxd_size[nic->rxd_mode] * l);
+                               rx_blocks->rxds[l].dma_addr =
+                                       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 =
@@ -528,62 +554,58 @@ static int init_shared_mem(struct s2io_nic *nic)
                                              blk_cnt].block_dma_addr;
 
                        pre_rxd_blk = (RxD_block_t *) tmp_v_addr;
-                       pre_rxd_blk->reserved_1 = END_OF_BLOCK; /* last RxD
-                                                                * marker.
-                                                                */
-#ifndef        CONFIG_2BUFF_MODE
                        pre_rxd_blk->reserved_2_pNext_RxD_block =
                            (unsigned long) tmp_v_addr_next;
-#endif
                        pre_rxd_blk->pNext_RxD_Blk_physical =
                            (u64) tmp_p_addr_next;
                }
        }
-
-#ifdef CONFIG_2BUFF_MODE
-       /*
-        * Allocation of Storages for buffer addresses in 2BUFF mode
-        * and the buffers as well.
-        */
-       for (i = 0; i < config->rx_ring_num; i++) {
-               blk_cnt =
-                   config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
-               mac_control->rings[i].ba = kmalloc((sizeof(buffAdd_t *) * blk_cnt),
+       if (nic->rxd_mode >= RXD_MODE_3A) {
+               /*
+                * Allocation of Storages for buffer addresses in 2BUFF mode
+                * and the buffers as well.
+                */
+               for (i = 0; i < config->rx_ring_num; i++) {
+                       blk_cnt = config->rx_cfg[i].num_rxd /
+                          (rxd_count[nic->rxd_mode]+ 1);
+                       mac_control->rings[i].ba =
+                               kmalloc((sizeof(buffAdd_t *) * blk_cnt),
                                     GFP_KERNEL);
-               if (!mac_control->rings[i].ba)
-                       return -ENOMEM;
-               for (j = 0; j < blk_cnt; j++) {
-                       int k = 0;
-                       mac_control->rings[i].ba[j] = kmalloc((sizeof(buffAdd_t) *
-                                                (MAX_RXDS_PER_BLOCK + 1)),
-                                               GFP_KERNEL);
-                       if (!mac_control->rings[i].ba[j])
+                       if (!mac_control->rings[i].ba)
                                return -ENOMEM;
-                       while (k != MAX_RXDS_PER_BLOCK) {
-                               ba = &mac_control->rings[i].ba[j][k];
-
-                               ba->ba_0_org = (void *) kmalloc
-                                   (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
-                               if (!ba->ba_0_org)
-                                       return -ENOMEM;
-                               tmp = (unsigned long) ba->ba_0_org;
-                               tmp += ALIGN_SIZE;
-                               tmp &= ~((unsigned long) ALIGN_SIZE);
-                               ba->ba_0 = (void *) tmp;
-
-                               ba->ba_1_org = (void *) kmalloc
-                                   (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
-                               if (!ba->ba_1_org)
+                       for (j = 0; j < blk_cnt; j++) {
+                               int k = 0;
+                               mac_control->rings[i].ba[j] =
+                                       kmalloc((sizeof(buffAdd_t) *
+                                               (rxd_count[nic->rxd_mode] + 1)),
+                                               GFP_KERNEL);
+                               if (!mac_control->rings[i].ba[j])
                                        return -ENOMEM;
-                               tmp = (unsigned long) ba->ba_1_org;
-                               tmp += ALIGN_SIZE;
-                               tmp &= ~((unsigned long) ALIGN_SIZE);
-                               ba->ba_1 = (void *) tmp;
-                               k++;
+                               while (k != rxd_count[nic->rxd_mode]) {
+                                       ba = &mac_control->rings[i].ba[j][k];
+
+                                       ba->ba_0_org = (void *) kmalloc
+                                           (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
+                                       if (!ba->ba_0_org)
+                                               return -ENOMEM;
+                                       tmp = (unsigned long)ba->ba_0_org;
+                                       tmp += ALIGN_SIZE;
+                                       tmp &= ~((unsigned long) ALIGN_SIZE);
+                                       ba->ba_0 = (void *) tmp;
+
+                                       ba->ba_1_org = (void *) kmalloc
+                                           (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
+                                       if (!ba->ba_1_org)
+                                               return -ENOMEM;
+                                       tmp = (unsigned long) ba->ba_1_org;
+                                       tmp += ALIGN_SIZE;
+                                       tmp &= ~((unsigned long) ALIGN_SIZE);
+                                       ba->ba_1 = (void *) tmp;
+                                       k++;
+                               }
                        }
                }
        }
-#endif
 
        /* Allocation and initialization of Statistics block */
        size = sizeof(StatInfo_t);
@@ -669,11 +691,7 @@ static void free_shared_mem(struct s2io_nic *nic)
                kfree(mac_control->fifos[i].list_info);
        }
 
-#ifndef CONFIG_2BUFF_MODE
-       size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t));
-#else
        size = SIZE_OF_BLOCK;
-#endif
        for (i = 0; i < config->rx_ring_num; i++) {
                blk_cnt = mac_control->rings[i].block_count;
                for (j = 0; j < blk_cnt; j++) {
@@ -685,30 +703,31 @@ static void free_shared_mem(struct s2io_nic *nic)
                                break;
                        pci_free_consistent(nic->pdev, size,
                                            tmp_v_addr, tmp_p_addr);
+                       kfree(mac_control->rings[i].rx_blocks[j].rxds);
                }
        }
 
-#ifdef CONFIG_2BUFF_MODE
-       /* Freeing buffer storage addresses in 2BUFF mode. */
-       for (i = 0; i < config->rx_ring_num; i++) {
-               blk_cnt =
-                   config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);
-               for (j = 0; j < blk_cnt; j++) {
-                       int k = 0;
-                       if (!mac_control->rings[i].ba[j])
-                               continue;
-                       while (k != MAX_RXDS_PER_BLOCK) {
-                               buffAdd_t *ba = &mac_control->rings[i].ba[j][k];
-                               kfree(ba->ba_0_org);
-                               kfree(ba->ba_1_org);
-                               k++;
+       if (nic->rxd_mode >= RXD_MODE_3A) {
+               /* Freeing buffer storage addresses in 2BUFF mode. */
+               for (i = 0; i < config->rx_ring_num; i++) {
+                       blk_cnt = config->rx_cfg[i].num_rxd /
+                           (rxd_count[nic->rxd_mode] + 1);
+                       for (j = 0; j < blk_cnt; j++) {
+                               int k = 0;
+                               if (!mac_control->rings[i].ba[j])
+                                       continue;
+                               while (k != rxd_count[nic->rxd_mode]) {
+                                       buffAdd_t *ba =
+                                               &mac_control->rings[i].ba[j][k];
+                                       kfree(ba->ba_0_org);
+                                       kfree(ba->ba_1_org);
+                                       k++;
+                               }
+                               kfree(mac_control->rings[i].ba[j]);
                        }
-                       kfree(mac_control->rings[i].ba[j]);
-               }
-               if (mac_control->rings[i].ba)
                        kfree(mac_control->rings[i].ba);
+               }
        }
-#endif
 
        if (mac_control->stats_mem) {
                pci_free_consistent(nic->pdev,
@@ -716,6 +735,8 @@ static void free_shared_mem(struct s2io_nic *nic)
                                    mac_control->stats_mem,
                                    mac_control->stats_mem_phy);
        }
+       if (nic->ufo_in_band_v)
+               kfree(nic->ufo_in_band_v);
 }
 
 /**
@@ -1516,7 +1537,7 @@ static int init_nic(struct s2io_nic *nic)
 #define LINK_UP_DOWN_INTERRUPT         1
 #define MAC_RMAC_ERR_TIMER             2
 
-int s2io_link_fault_indication(nic_t *nic)
+static int s2io_link_fault_indication(nic_t *nic)
 {
        if (nic->intr_type != INTA)
                return MAC_RMAC_ERR_TIMER;
@@ -1848,7 +1869,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)
  *
  */
 
-void fix_mac_address(nic_t * sp)
+static void fix_mac_address(nic_t * sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        u64 val64;
@@ -1895,20 +1916,19 @@ static int start_nic(struct s2io_nic *nic)
                val64 = readq(&bar0->prc_ctrl_n[i]);
                if (nic->config.bimodal)
                        val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
-#ifndef CONFIG_2BUFF_MODE
-               val64 |= PRC_CTRL_RC_ENABLED;
-#else
-               val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3;
-#endif
+               if (nic->rxd_mode == RXD_MODE_1)
+                       val64 |= PRC_CTRL_RC_ENABLED;
+               else
+                       val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3;
                writeq(val64, &bar0->prc_ctrl_n[i]);
        }
 
-#ifdef CONFIG_2BUFF_MODE
-       /* Enabling 2 buffer mode by writing into Rx_pa_cfg reg. */
-       val64 = readq(&bar0->rx_pa_cfg);
-       val64 |= RX_PA_CFG_IGNORE_L2_ERR;
-       writeq(val64, &bar0->rx_pa_cfg);
-#endif
+       if (nic->rxd_mode == RXD_MODE_3B) {
+               /* Enabling 2 buffer mode by writing into Rx_pa_cfg reg. */
+               val64 = readq(&bar0->rx_pa_cfg);
+               val64 |= RX_PA_CFG_IGNORE_L2_ERR;
+               writeq(val64, &bar0->rx_pa_cfg);
+       }
 
        /*
         * Enabling MC-RLDRAM. After enabling the device, we timeout
@@ -1989,6 +2009,49 @@ static int start_nic(struct s2io_nic *nic)
 
        return SUCCESS;
 }
+/**
+ * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb
+ */
+static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, int get_off)
+{
+       nic_t *nic = fifo_data->nic;
+       struct sk_buff *skb;
+       TxD_t *txds;
+       u16 j, frg_cnt;
+
+       txds = txdlp;
+       if (txds->Host_Control == (u64)(long)nic->ufo_in_band_v) {
+               pci_unmap_single(nic->pdev, (dma_addr_t)
+                       txds->Buffer_Pointer, sizeof(u64),
+                       PCI_DMA_TODEVICE);
+               txds++;
+       }
+
+       skb = (struct sk_buff *) ((unsigned long)
+                       txds->Host_Control);
+       if (!skb) {
+               memset(txdlp, 0, (sizeof(TxD_t) * fifo_data->max_txds));
+               return NULL;
+       }
+       pci_unmap_single(nic->pdev, (dma_addr_t)
+                        txds->Buffer_Pointer,
+                        skb->len - skb->data_len,
+                        PCI_DMA_TODEVICE);
+       frg_cnt = skb_shinfo(skb)->nr_frags;
+       if (frg_cnt) {
+               txds++;
+               for (j = 0; j < frg_cnt; j++, txds++) {
+                       skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
+                       if (!txds->Buffer_Pointer)
+                               break;
+                       pci_unmap_page(nic->pdev, (dma_addr_t) 
+                                       txds->Buffer_Pointer,
+                                      frag->size, PCI_DMA_TODEVICE);
+               }
+       }
+       txdlp->Host_Control = 0;
+       return(skb);
+}
 
 /**
  *  free_tx_buffers - Free all queued Tx buffers
@@ -2006,7 +2069,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
        int i, j;
        mac_info_t *mac_control;
        struct config_param *config;
-       int cnt = 0, frg_cnt;
+       int cnt = 0;
 
        mac_control = &nic->mac_control;
        config = &nic->config;
@@ -2015,38 +2078,11 @@ static void free_tx_buffers(struct s2io_nic *nic)
                for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
                        txdp = (TxD_t *) mac_control->fifos[i].list_info[j].
                            list_virt_addr;
-                       skb =
-                           (struct sk_buff *) ((unsigned long) txdp->
-                                               Host_Control);
-                       if (skb == NULL) {
-                               memset(txdp, 0, sizeof(TxD_t) *
-                                      config->max_txds);
-                               continue;
-                       }
-                       frg_cnt = skb_shinfo(skb)->nr_frags;
-                       pci_unmap_single(nic->pdev, (dma_addr_t)
-                                        txdp->Buffer_Pointer,
-                                        skb->len - skb->data_len,
-                                        PCI_DMA_TODEVICE);
-                       if (frg_cnt) {
-                               TxD_t *temp;
-                               temp = txdp;
-                               txdp++;
-                               for (j = 0; j < frg_cnt; j++, txdp++) {
-                                       skb_frag_t *frag =
-                                           &skb_shinfo(skb)->frags[j];
-                                       pci_unmap_page(nic->pdev,
-                                                      (dma_addr_t)
-                                                      txdp->
-                                                      Buffer_Pointer,
-                                                      frag->size,
-                                                      PCI_DMA_TODEVICE);
-                               }
-                               txdp = temp;
+                       skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
+                       if (skb) {
+                               dev_kfree_skb(skb);
+                               cnt++;
                        }
-                       dev_kfree_skb(skb);
-                       memset(txdp, 0, sizeof(TxD_t) * config->max_txds);
-                       cnt++;
                }
                DBG_PRINT(INTR_DBG,
                          "%s:forcibly freeing %d skbs on FIFO%d\n",
@@ -2091,6 +2127,39 @@ static void stop_nic(struct s2io_nic *nic)
        }
 }
 
+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;
+       void *tmp;
+
+       /* Buffer-1 receives L3/L4 headers */
+       ((RxD3_t*)rxdp)->Buffer1_ptr = pci_map_single
+                       (nic->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;
+       tmp = (void *)ALIGN((long)frag_list->data, ALIGN_SIZE + 1);
+       frag_list->data = tmp;
+       frag_list->tail = tmp;
+
+       /* Buffer-2 receives L4 data payload */
+       ((RxD3_t*)rxdp)->Buffer2_ptr = pci_map_single(nic->pdev,
+                               frag_list->data, dev->mtu,
+                               PCI_DMA_FROMDEVICE);
+       rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4);
+       rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu);
+
+       return SUCCESS;
+}
+
 /**
  *  fill_rx_buffers - Allocates the Rx side skbs
  *  @nic:  device private variable
@@ -2112,24 +2181,18 @@ static void stop_nic(struct s2io_nic *nic)
  *  SUCCESS on success or an appropriate -ve value on failure.
  */
 
-int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 {
        struct net_device *dev = nic->dev;
        struct sk_buff *skb;
        RxD_t *rxdp;
        int off, off1, size, block_no, block_no1;
-       int offset, offset1;
        u32 alloc_tab = 0;
        u32 alloc_cnt;
        mac_info_t *mac_control;
        struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
-       RxD_t *rxdpnext;
-       int nextblk;
        u64 tmp;
        buffAdd_t *ba;
-       dma_addr_t rxdpphys;
-#endif
 #ifndef CONFIG_S2IO_NAPI
        unsigned long flags;
 #endif
@@ -2139,8 +2202,6 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
        config = &nic->config;
        alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
            atomic_read(&nic->rx_bufs_left[ring_no]);
-       size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
-           HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
 
        while (alloc_tab < alloc_cnt) {
                block_no = mac_control->rings[ring_no].rx_curr_put_info.
@@ -2149,159 +2210,145 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                    block_index;
                off = mac_control->rings[ring_no].rx_curr_put_info.offset;
                off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
-#ifndef CONFIG_2BUFF_MODE
-               offset = block_no * (MAX_RXDS_PER_BLOCK + 1) + off;
-               offset1 = block_no1 * (MAX_RXDS_PER_BLOCK + 1) + off1;
-#else
-               offset = block_no * (MAX_RXDS_PER_BLOCK) + off;
-               offset1 = block_no1 * (MAX_RXDS_PER_BLOCK) + off1;
-#endif
 
-               rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
-                   block_virt_addr + off;
-               if ((offset == offset1) && (rxdp->Host_Control)) {
-                       DBG_PRINT(INTR_DBG, "%s: Get and Put", dev->name);
+               rxdp = mac_control->rings[ring_no].
+                               rx_blocks[block_no].rxds[off].virt_addr;
+
+               if ((block_no == block_no1) && (off == off1) &&
+                                       (rxdp->Host_Control)) {
+                       DBG_PRINT(INTR_DBG, "%s: Get and Put",
+                                 dev->name);
                        DBG_PRINT(INTR_DBG, " info equated\n");
                        goto end;
                }
-#ifndef        CONFIG_2BUFF_MODE
-               if (rxdp->Control_1 == END_OF_BLOCK) {
+               if (off && (off == rxd_count[nic->rxd_mode])) {
                        mac_control->rings[ring_no].rx_curr_put_info.
                            block_index++;
+                       if (mac_control->rings[ring_no].rx_curr_put_info.
+                           block_index == mac_control->rings[ring_no].
+                                       block_count)
+                               mac_control->rings[ring_no].rx_curr_put_info.
+                                       block_index = 0;
+                       block_no = mac_control->rings[ring_no].
+                                       rx_curr_put_info.block_index;
+                       if (off == rxd_count[nic->rxd_mode])
+                               off = 0;
                        mac_control->rings[ring_no].rx_curr_put_info.
-                           block_index %= mac_control->rings[ring_no].block_count;
-                       block_no = mac_control->rings[ring_no].rx_curr_put_info.
-                               block_index;
-                       off++;
-                       off %= (MAX_RXDS_PER_BLOCK + 1);
-                       mac_control->rings[ring_no].rx_curr_put_info.offset =
-                           off;
-                       rxdp = (RxD_t *) ((unsigned long) rxdp->Control_2);
+                               offset = off;
+                       rxdp = mac_control->rings[ring_no].
+                               rx_blocks[block_no].block_virt_addr;
                        DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
                                  dev->name, rxdp);
                }
 #ifndef CONFIG_S2IO_NAPI
                spin_lock_irqsave(&nic->put_lock, flags);
                mac_control->rings[ring_no].put_pos =
-                   (block_no * (MAX_RXDS_PER_BLOCK + 1)) + off;
+                   (block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
                spin_unlock_irqrestore(&nic->put_lock, flags);
 #endif
-#else
-               if (rxdp->Host_Control == END_OF_BLOCK) {
+               if ((rxdp->Control_1 & RXD_OWN_XENA) &&
+                       ((nic->rxd_mode >= RXD_MODE_3A) &&
+                               (rxdp->Control_2 & BIT(0)))) {
                        mac_control->rings[ring_no].rx_curr_put_info.
-                           block_index++;
-                       mac_control->rings[ring_no].rx_curr_put_info.block_index
-                           %= mac_control->rings[ring_no].block_count;
-                       block_no = mac_control->rings[ring_no].rx_curr_put_info
-                           .block_index;
-                       off = 0;
-                       DBG_PRINT(INTR_DBG, "%s: block%d at: 0x%llx\n",
-                                 dev->name, block_no,
-                                 (unsigned long long) rxdp->Control_1);
-                       mac_control->rings[ring_no].rx_curr_put_info.offset =
-                           off;
-                       rxdp = mac_control->rings[ring_no].rx_blocks[block_no].
-                           block_virt_addr;
-               }
-#ifndef CONFIG_S2IO_NAPI
-               spin_lock_irqsave(&nic->put_lock, flags);
-               mac_control->rings[ring_no].put_pos = (block_no *
-                                        (MAX_RXDS_PER_BLOCK + 1)) + off;
-               spin_unlock_irqrestore(&nic->put_lock, flags);
-#endif
-#endif
-
-#ifndef        CONFIG_2BUFF_MODE
-               if (rxdp->Control_1 & RXD_OWN_XENA)
-#else
-               if (rxdp->Control_2 & BIT(0))
-#endif
-               {
-                       mac_control->rings[ring_no].rx_curr_put_info.
-                           offset = off;
+                                       offset = off;
                        goto end;
                }
-#ifdef CONFIG_2BUFF_MODE
-               /*
-                * RxDs Spanning cache lines will be replenished only
-                * if the succeeding RxD is also owned by Host. It
-                * will always be the ((8*i)+3) and ((8*i)+6)
-                * descriptors for the 48 byte descriptor. The offending
-                * decsriptor is of-course the 3rd descriptor.
-                */
-               rxdpphys = mac_control->rings[ring_no].rx_blocks[block_no].
-                   block_dma_addr + (off * sizeof(RxD_t));
-               if (((u64) (rxdpphys)) % 128 > 80) {
-                       rxdpnext = mac_control->rings[ring_no].rx_blocks[block_no].
-                           block_virt_addr + (off + 1);
-                       if (rxdpnext->Host_Control == END_OF_BLOCK) {
-                               nextblk = (block_no + 1) %
-                                   (mac_control->rings[ring_no].block_count);
-                               rxdpnext = mac_control->rings[ring_no].rx_blocks
-                                   [nextblk].block_virt_addr;
-                       }
-                       if (rxdpnext->Control_2 & BIT(0))
-                               goto end;
-               }
-#endif
+               /* calculate size of skb based on ring mode */
+               size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
+                               HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
+               if (nic->rxd_mode == RXD_MODE_1)
+                       size += NET_IP_ALIGN;
+               else if (nic->rxd_mode == RXD_MODE_3B)
+                       size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
+               else
+                       size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4;
 
-#ifndef        CONFIG_2BUFF_MODE
-               skb = dev_alloc_skb(size + NET_IP_ALIGN);
-#else
-               skb = dev_alloc_skb(dev->mtu + ALIGN_SIZE + BUF0_LEN + 4);
-#endif
-               if (!skb) {
+               /* allocate skb */
+               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");
                        if (first_rxdp) {
                                wmb();
                                first_rxdp->Control_1 |= RXD_OWN_XENA;
                        }
-                       return -ENOMEM;
+                       return -ENOMEM ;
+               }
+               if (nic->rxd_mode == RXD_MODE_1) {
+                       /* 1 buffer mode - normal operation mode */
+                       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, 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) {
+                       /*
+                        * 2 or 3 buffer mode -
+                        * Both 2 buffer mode and 3 buffer mode provides 128
+                        * byte aligned receive buffers.
+                        *
+                        * 3 buffer mode provides header separation where in
+                        * skb->data will have L3/L4 headers where as
+                        * skb_shinfo(skb)->frag_list will have the L4 data
+                        * payload
+                        */
+
+                       memset(rxdp, 0, sizeof(RxD3_t));
+                       ba = &mac_control->rings[ring_no].ba[block_no][off];
+                       skb_reserve(skb, BUF0_LEN);
+                       tmp = (u64)(unsigned long) skb->data;
+                       tmp += ALIGN_SIZE;
+                       tmp &= ~ALIGN_SIZE;
+                       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,
+                                          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 
+                                * 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);
+                               rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
+                               rxdp->Control_2 |= SET_BUFFER2_SIZE_3
+                                                               (dev->mtu + 4);
+                       } else {
+                               /* 3 buffer mode */
+                               if (fill_rxd_3buf(nic, rxdp, skb) == -ENOMEM) {
+                                       dev_kfree_skb_irq(skb);
+                                       if (first_rxdp) {
+                                               wmb();
+                                               first_rxdp->Control_1 |=
+                                                       RXD_OWN_XENA;
+                                       }
+                                       return -ENOMEM ;
+                               }
+                       }
+                       rxdp->Control_2 |= BIT(0);
                }
-#ifndef        CONFIG_2BUFF_MODE
-               skb_reserve(skb, NET_IP_ALIGN);
-               memset(rxdp, 0, sizeof(RxD_t));
-               rxdp->Buffer0_ptr = pci_map_single
-                   (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE);
-               rxdp->Control_2 &= (~MASK_BUFFER0_SIZE);
-               rxdp->Control_2 |= SET_BUFFER0_SIZE(size);
                rxdp->Host_Control = (unsigned long) (skb);
                if (alloc_tab & ((1 << rxsync_frequency) - 1))
                        rxdp->Control_1 |= RXD_OWN_XENA;
                off++;
-               off %= (MAX_RXDS_PER_BLOCK + 1);
-               mac_control->rings[ring_no].rx_curr_put_info.offset = off;
-#else
-               ba = &mac_control->rings[ring_no].ba[block_no][off];
-               skb_reserve(skb, BUF0_LEN);
-               tmp = ((unsigned long) skb->data & ALIGN_SIZE);
-               if (tmp)
-                       skb_reserve(skb, (ALIGN_SIZE + 1) - tmp);
-
-               memset(rxdp, 0, sizeof(RxD_t));
-               rxdp->Buffer2_ptr = pci_map_single
-                   (nic->pdev, skb->data, dev->mtu + BUF0_LEN + 4,
-                    PCI_DMA_FROMDEVICE);
-               rxdp->Buffer0_ptr =
-                   pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
-                                  PCI_DMA_FROMDEVICE);
-               rxdp->Buffer1_ptr =
-                   pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN,
-                                  PCI_DMA_FROMDEVICE);
-
-               rxdp->Control_2 = SET_BUFFER2_SIZE(dev->mtu + 4);
-               rxdp->Control_2 |= SET_BUFFER0_SIZE(BUF0_LEN);
-               rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */
-               rxdp->Control_2 |= BIT(0);      /* Set Buffer_Empty bit. */
-               rxdp->Host_Control = (u64) ((unsigned long) (skb));
-               if (alloc_tab & ((1 << rxsync_frequency) - 1))
-                       rxdp->Control_1 |= RXD_OWN_XENA;
-               off++;
+               if (off == (rxd_count[nic->rxd_mode] + 1))
+                       off = 0;
                mac_control->rings[ring_no].rx_curr_put_info.offset = off;
-#endif
-               rxdp->Control_2 |= SET_RXD_MARKER;
 
+               rxdp->Control_2 |= SET_RXD_MARKER;
                if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
                        if (first_rxdp) {
                                wmb();
@@ -2326,6 +2373,67 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
        return SUCCESS;
 }
 
+static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk)
+{
+       struct net_device *dev = sp->dev;
+       int j;
+       struct sk_buff *skb;
+       RxD_t *rxdp;
+       mac_info_t *mac_control;
+       buffAdd_t *ba;
+
+       mac_control = &sp->mac_control;
+       for (j = 0 ; j < rxd_count[sp->rxd_mode]; j++) {
+               rxdp = mac_control->rings[ring_no].
+                                rx_blocks[blk].rxds[j].virt_addr;
+               skb = (struct sk_buff *)
+                       ((unsigned long) rxdp->Host_Control);
+               if (!skb) {
+                       continue;
+               }
+               if (sp->rxd_mode == RXD_MODE_1) {
+                       pci_unmap_single(sp->pdev, (dma_addr_t)
+                                ((RxD1_t*)rxdp)->Buffer0_ptr,
+                                dev->mtu +
+                                HEADER_ETHERNET_II_802_3_SIZE
+                                + HEADER_802_2_SIZE +
+                                HEADER_SNAP_SIZE,
+                                PCI_DMA_FROMDEVICE);
+                       memset(rxdp, 0, sizeof(RxD1_t));
+               } else if(sp->rxd_mode == RXD_MODE_3B) {
+                       ba = &mac_control->rings[ring_no].
+                               ba[blk][j];
+                       pci_unmap_single(sp->pdev, (dma_addr_t)
+                                ((RxD3_t*)rxdp)->Buffer0_ptr,
+                                BUF0_LEN,
+                                PCI_DMA_FROMDEVICE);
+                       pci_unmap_single(sp->pdev, (dma_addr_t)
+                                ((RxD3_t*)rxdp)->Buffer1_ptr,
+                                BUF1_LEN,
+                                PCI_DMA_FROMDEVICE);
+                       pci_unmap_single(sp->pdev, (dma_addr_t)
+                                ((RxD3_t*)rxdp)->Buffer2_ptr,
+                                dev->mtu + 4,
+                                PCI_DMA_FROMDEVICE);
+                       memset(rxdp, 0, sizeof(RxD3_t));
+               } else {
+                       pci_unmap_single(sp->pdev, (dma_addr_t)
+                               ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN,
+                               PCI_DMA_FROMDEVICE);
+                       pci_unmap_single(sp->pdev, (dma_addr_t)
+                               ((RxD3_t*)rxdp)->Buffer1_ptr, 
+                               l3l4hdr_size + 4,
+                               PCI_DMA_FROMDEVICE);
+                       pci_unmap_single(sp->pdev, (dma_addr_t)
+                               ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu,
+                               PCI_DMA_FROMDEVICE);
+                       memset(rxdp, 0, sizeof(RxD3_t));
+               }
+               dev_kfree_skb(skb);
+               atomic_dec(&sp->rx_bufs_left[ring_no]);
+       }
+}
+
 /**
  *  free_rx_buffers - Frees all Rx buffers
  *  @sp: device private variable.
@@ -2338,77 +2446,17 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 static void free_rx_buffers(struct s2io_nic *sp)
 {
        struct net_device *dev = sp->dev;
-       int i, j, blk = 0, off, buf_cnt = 0;
-       RxD_t *rxdp;
-       struct sk_buff *skb;
+       int i, blk = 0, buf_cnt = 0;
        mac_info_t *mac_control;
        struct config_param *config;
-#ifdef CONFIG_2BUFF_MODE
-       buffAdd_t *ba;
-#endif
 
        mac_control = &sp->mac_control;
        config = &sp->config;
 
        for (i = 0; i < config->rx_ring_num; i++) {
-               for (j = 0, blk = 0; j < config->rx_cfg[i].num_rxd; j++) {
-                       off = j % (MAX_RXDS_PER_BLOCK + 1);
-                       rxdp = mac_control->rings[i].rx_blocks[blk].
-                               block_virt_addr + off;
-
-#ifndef CONFIG_2BUFF_MODE
-                       if (rxdp->Control_1 == END_OF_BLOCK) {
-                               rxdp =
-                                   (RxD_t *) ((unsigned long) rxdp->
-                                              Control_2);
-                               j++;
-                               blk++;
-                       }
-#else
-                       if (rxdp->Host_Control == END_OF_BLOCK) {
-                               blk++;
-                               continue;
-                       }
-#endif
-
-                       if (!(rxdp->Control_1 & RXD_OWN_XENA)) {
-                               memset(rxdp, 0, sizeof(RxD_t));
-                               continue;
-                       }
+               for (blk = 0; blk < rx_ring_sz[i]; blk++)
+                       free_rxd_blk(sp,i,blk);
 
-                       skb =
-                           (struct sk_buff *) ((unsigned long) rxdp->
-                                               Host_Control);
-                       if (skb) {
-#ifndef CONFIG_2BUFF_MODE
-                               pci_unmap_single(sp->pdev, (dma_addr_t)
-                                                rxdp->Buffer0_ptr,
-                                                dev->mtu +
-                                                HEADER_ETHERNET_II_802_3_SIZE
-                                                + HEADER_802_2_SIZE +
-                                                HEADER_SNAP_SIZE,
-                                                PCI_DMA_FROMDEVICE);
-#else
-                               ba = &mac_control->rings[i].ba[blk][off];
-                               pci_unmap_single(sp->pdev, (dma_addr_t)
-                                                rxdp->Buffer0_ptr,
-                                                BUF0_LEN,
-                                                PCI_DMA_FROMDEVICE);
-                               pci_unmap_single(sp->pdev, (dma_addr_t)
-                                                rxdp->Buffer1_ptr,
-                                                BUF1_LEN,
-                                                PCI_DMA_FROMDEVICE);
-                               pci_unmap_single(sp->pdev, (dma_addr_t)
-                                                rxdp->Buffer2_ptr,
-                                                dev->mtu + BUF0_LEN + 4,
-                                                PCI_DMA_FROMDEVICE);
-#endif
-                               dev_kfree_skb(skb);
-                               atomic_dec(&sp->rx_bufs_left[i]);
-                               buf_cnt++;
-                       }
-                       memset(rxdp, 0, sizeof(RxD_t));
-               }
                mac_control->rings[i].rx_curr_put_info.block_index = 0;
                mac_control->rings[i].rx_curr_get_info.block_index = 0;
                mac_control->rings[i].rx_curr_put_info.offset = 0;
@@ -2514,7 +2562,7 @@ static void rx_intr_handler(ring_info_t *ring_data)
 {
        nic_t *nic = ring_data->nic;
        struct net_device *dev = (struct net_device *) nic->dev;
-       int get_block, get_offset, put_block, put_offset, ring_bufs;
+       int get_block, put_block, put_offset;
        rx_curr_get_info_t get_info, put_info;
        RxD_t *rxdp;
        struct sk_buff *skb;
@@ -2533,21 +2581,22 @@ static void rx_intr_handler(ring_info_t *ring_data)
        get_block = get_info.block_index;
        put_info = ring_data->rx_curr_put_info;
        put_block = put_info.block_index;
-       ring_bufs = get_info.ring_len+1;
-       rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
-                   get_info.offset;
-       get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-               get_info.offset;
+       rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr;
 #ifndef CONFIG_S2IO_NAPI
        spin_lock(&nic->put_lock);
        put_offset = ring_data->put_pos;
        spin_unlock(&nic->put_lock);
 #else
-       put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) +
+       put_offset = (put_block * (rxd_count[nic->rxd_mode] + 1)) +
                put_info.offset;
 #endif
-       while (RXD_IS_UP2DT(rxdp) &&
-              (((get_offset + 1) % ring_bufs) != put_offset)) {
+       while (RXD_IS_UP2DT(rxdp)) {
+               /* 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);
+                       break;
+               }
                skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
                if (skb == NULL) {
                        DBG_PRINT(ERR_DBG, "%s: The skb is ",
@@ -2556,46 +2605,52 @@ static void rx_intr_handler(ring_info_t *ring_data)
                        spin_unlock(&nic->rx_lock);
                        return;
                }
-#ifndef CONFIG_2BUFF_MODE
-               pci_unmap_single(nic->pdev, (dma_addr_t)
-                                rxdp->Buffer0_ptr,
+               if (nic->rxd_mode == RXD_MODE_1) {
+                       pci_unmap_single(nic->pdev, (dma_addr_t)
+                                ((RxD1_t*)rxdp)->Buffer0_ptr,
                                 dev->mtu +
                                 HEADER_ETHERNET_II_802_3_SIZE +
                                 HEADER_802_2_SIZE +
                                 HEADER_SNAP_SIZE,
                                 PCI_DMA_FROMDEVICE);
-#else
-               pci_unmap_single(nic->pdev, (dma_addr_t)
-                                rxdp->Buffer0_ptr,
+               } else if (nic->rxd_mode == RXD_MODE_3B) {
+                       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)
-                                rxdp->Buffer1_ptr,
+                       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)
-                                rxdp->Buffer2_ptr,
-                                dev->mtu + BUF0_LEN + 4,
+                       pci_unmap_single(nic->pdev, (dma_addr_t)
+                                ((RxD3_t*)rxdp)->Buffer2_ptr,
+                                dev->mtu + 4,
                                 PCI_DMA_FROMDEVICE);
-#endif
+               } else {
+                       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,
+                                        l3l4hdr_size + 4,
+                                        PCI_DMA_FROMDEVICE);
+                       pci_unmap_single(nic->pdev, (dma_addr_t)
+                                        ((RxD3_t*)rxdp)->Buffer2_ptr,
+                                        dev->mtu, PCI_DMA_FROMDEVICE);
+               }
                rx_osm_handler(ring_data, rxdp);
                get_info.offset++;
-               ring_data->rx_curr_get_info.offset =
-                   get_info.offset;
-               rxdp = ring_data->rx_blocks[get_block].block_virt_addr +
-                   get_info.offset;
-               if (get_info.offset &&
-                   (!(get_info.offset % MAX_RXDS_PER_BLOCK))) {
+               ring_data->rx_curr_get_info.offset = get_info.offset;
+               rxdp = ring_data->rx_blocks[get_block].
+                               rxds[get_info.offset].virt_addr;
+               if (get_info.offset == rxd_count[nic->rxd_mode]) {
                        get_info.offset = 0;
-                       ring_data->rx_curr_get_info.offset
-                           = get_info.offset;
+                       ring_data->rx_curr_get_info.offset = get_info.offset;
                        get_block++;
-                       get_block %= ring_data->block_count;
-                       ring_data->rx_curr_get_info.block_index
-                           = get_block;
+                       if (get_block == ring_data->block_count)
+                               get_block = 0;
+                       ring_data->rx_curr_get_info.block_index = get_block;
                        rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
                }
 
-               get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +
-                           get_info.offset;
 #ifdef CONFIG_S2IO_NAPI
                nic->pkts_to_process -= 1;
                if (!nic->pkts_to_process)
@@ -2628,7 +2683,6 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
        tx_curr_get_info_t get_info, put_info;
        struct sk_buff *skb;
        TxD_t *txdlp;
-       u16 j, frg_cnt;
 
        get_info = fifo_data->tx_curr_get_info;
        put_info = fifo_data->tx_curr_put_info;
@@ -2651,8 +2705,7 @@ to loss of link\n");
                        }
                }
 
-               skb = (struct sk_buff *) ((unsigned long)
-                               txdlp->Host_Control);
+               skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset);
                if (skb == NULL) {
                        DBG_PRINT(ERR_DBG, "%s: Null skb ",
                        __FUNCTION__);
@@ -2660,34 +2713,6 @@ to loss of link\n");
                        return;
                }
 
-               frg_cnt = skb_shinfo(skb)->nr_frags;
-               nic->tx_pkt_count++;
-
-               pci_unmap_single(nic->pdev, (dma_addr_t)
-                                txdlp->Buffer_Pointer,
-                                skb->len - skb->data_len,
-                                PCI_DMA_TODEVICE);
-               if (frg_cnt) {
-                       TxD_t *temp;
-                       temp = txdlp;
-                       txdlp++;
-                       for (j = 0; j < frg_cnt; j++, txdlp++) {
-                               skb_frag_t *frag =
-                                   &skb_shinfo(skb)->frags[j];
-                               if (!txdlp->Buffer_Pointer)
-                                       break;
-                               pci_unmap_page(nic->pdev,
-                                              (dma_addr_t)
-                                              txdlp->
-                                              Buffer_Pointer,
-                                              frag->size,
-                                              PCI_DMA_TODEVICE);
-                       }
-                       txdlp = temp;
-               }
-               memset(txdlp, 0,
-                      (sizeof(TxD_t) * fifo_data->max_txds));
-
                /* Updating the statistics block */
                nic->stats.tx_bytes += skb->len;
                dev_kfree_skb_irq(skb);
@@ -2797,7 +2822,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  *   SUCCESS on success and FAILURE on failure.
  */
 
-int wait_for_cmd_complete(nic_t * sp)
+static int wait_for_cmd_complete(nic_t * sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        int ret = FAILURE, cnt = 0;
@@ -2997,7 +3022,7 @@ int s2io_set_swapper(nic_t * sp)
                 SWAPPER_CTRL_RXF_W_FE |
                 SWAPPER_CTRL_XMSI_FE |
                 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
-       if (nic->intr_type == INTA)
+       if (sp->intr_type == INTA)
                val64 |= SWAPPER_CTRL_XMSI_SE;
        writeq(val64, &bar0->swapper_ctrl);
 #else
@@ -3043,9 +3068,9 @@ int s2io_set_swapper(nic_t * sp)
        return SUCCESS;
 }
 
-int wait_for_msix_trans(nic_t *nic, int i)
+static int wait_for_msix_trans(nic_t *nic, int i)
 {
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 val64;
        int ret = 0, cnt = 0;
 
@@ -3066,7 +3091,7 @@ int wait_for_msix_trans(nic_t *nic, int i)
 
 void restore_xmsi_data(nic_t *nic)
 {
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 val64;
        int i;
 
@@ -3082,9 +3107,9 @@ void restore_xmsi_data(nic_t *nic)
        }
 }
 
-void store_xmsi_data(nic_t *nic)
+static void store_xmsi_data(nic_t *nic)
 {
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 val64, addr, data;
        int i;
 
@@ -3107,7 +3132,7 @@ void store_xmsi_data(nic_t *nic)
 
 int s2io_enable_msi(nic_t *nic)
 {
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u16 msi_ctrl, msg_val;
        struct config_param *config = &nic->config;
        struct net_device *dev = nic->dev;
@@ -3157,7 +3182,7 @@ int s2io_enable_msi(nic_t *nic)
 
 int s2io_enable_msi_x(nic_t *nic)
 {
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+       XENA_dev_config_t __iomem *bar0 = nic->bar0;
        u64 tx_mat, rx_mat;
        u16 msi_control; /* Temp variable */
        int ret, i, j, msix_indx = 1;
@@ -3254,7 +3279,7 @@ int s2io_enable_msi_x(nic_t *nic)
  *   file on failure.
  */
 
-int s2io_open(struct net_device *dev)
+static int s2io_open(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        int err = 0;
@@ -3298,7 +3323,7 @@ failed\n", dev->name);
                                          s2io_msix_fifo_handle, 0, sp->desc1,
                                          sp->s2io_entries[i].arg);
                                DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1, 
-                                                       sp->msix_info[i].addr);
+                                   (unsigned long long)sp->msix_info[i].addr);
                        } else {
                                sprintf(sp->desc2, "%s:MSI-X-%d-RX",
                                        dev->name, i);
@@ -3306,7 +3331,7 @@ failed\n", dev->name);
                                          s2io_msix_ring_handle, 0, sp->desc2,
                                          sp->s2io_entries[i].arg);
                                DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2, 
-                                                       sp->msix_info[i].addr);
+                                    (unsigned long long)sp->msix_info[i].addr);
                        }
                        if (err) {
                                DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
@@ -3384,7 +3409,7 @@ hw_init_failed:
  *  file on failure.
  */
 
-int s2io_close(struct net_device *dev)
+static int s2io_close(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        int i;
@@ -3433,7 +3458,7 @@ int s2io_close(struct net_device *dev)
  *  0 on success & 1 on failure.
  */
 
-int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
@@ -3494,6 +3519,8 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
 
+       txdp->Control_1 = 0;
+       txdp->Control_2 = 0;
 #ifdef NETIF_F_TSO
        mss = skb_shinfo(skb)->tso_size;
        if (mss) {
@@ -3501,19 +3528,13 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
        }
 #endif
-
-       frg_cnt = skb_shinfo(skb)->nr_frags;
-       frg_len = skb->len - skb->data_len;
-
-       txdp->Buffer_Pointer = pci_map_single
-           (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
-       txdp->Host_Control = (unsigned long) skb;
        if (skb->ip_summed == CHECKSUM_HW) {
                txdp->Control_2 |=
                    (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN |
                     TXD_TX_CKO_UDP_EN);
        }
-
+       txdp->Control_1 |= TXD_GATHER_CODE_FIRST;
+       txdp->Control_1 |= TXD_LIST_OWN_XENA;
        txdp->Control_2 |= config->tx_intr_type;
 
        if (sp->vlgrp && vlan_tx_tag_present(skb)) {
@@ -3521,10 +3542,40 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
        }
 
-       txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) |
-                           TXD_GATHER_CODE_FIRST);
-       txdp->Control_1 |= TXD_LIST_OWN_XENA;
+       frg_len = skb->len - skb->data_len;
+       if (skb_shinfo(skb)->ufo_size) {
+               int ufo_size;
+
+               ufo_size = skb_shinfo(skb)->ufo_size;
+               ufo_size &= ~7;
+               txdp->Control_1 |= TXD_UFO_EN;
+               txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
+               txdp->Control_1 |= TXD_BUFFER0_SIZE(8);
+#ifdef __BIG_ENDIAN
+               sp->ufo_in_band_v[put_off] =
+                               (u64)skb_shinfo(skb)->ip6_frag_id;
+#else
+               sp->ufo_in_band_v[put_off] =
+                               (u64)skb_shinfo(skb)->ip6_frag_id << 32;
+#endif
+               txdp->Host_Control = (unsigned long)sp->ufo_in_band_v;
+               txdp->Buffer_Pointer = pci_map_single(sp->pdev,
+                                       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)->ufo_size)
+               txdp->Control_1 |= TXD_UFO_EN;
+
+       frg_cnt = skb_shinfo(skb)->nr_frags;
        /* For fragmented SKB. */
        for (i = 0; i < frg_cnt; i++) {
                skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -3536,9 +3587,14 @@ 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)->ufo_size)
+                       txdp->Control_1 |= TXD_UFO_EN;
        }
        txdp->Control_1 |= TXD_GATHER_CODE_LAST;
 
+       if (skb_shinfo(skb)->ufo_size)
+               frg_cnt++; /* as Txd0 was used for inband header */
+
        tx_fifo = mac_control->tx_FIFO_start[queue];
        val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;
        writeq(val64, &tx_fifo->TxDL_Pointer);
@@ -3550,6 +3606,8 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        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();
@@ -3879,7 +3937,7 @@ static void s2io_updt_stats(nic_t *sp)
  *  pointer to the updated net_device_stats structure.
  */
 
-struct net_device_stats *s2io_get_stats(struct net_device *dev)
+static struct net_device_stats *s2io_get_stats(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        mac_info_t *mac_control;
@@ -4688,7 +4746,10 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
                fail = 1;
 
        if (ret_data != 0x012345) {
-               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
+               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. "
+                       "Data written %llx Data read %llx\n",
+                       dev->name, (unsigned long long)0x12345,
+                       (unsigned long long)ret_data);
                fail = 1;
        }
 
@@ -4707,7 +4768,10 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
                fail = 1;
 
        if (ret_data != 0x012345) {
-               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data); 
+               DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. "
+                       "Data written %llx Data read %llx\n",
+                       dev->name, (unsigned long long)0x12345,
+                       (unsigned long long)ret_data);
                fail = 1;
        }
 
@@ -5072,19 +5136,20 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
 }
 
-int s2io_ethtool_get_regs_len(struct net_device *dev)
+static int s2io_ethtool_get_regs_len(struct net_device *dev)
 {
        return (XENA_REG_SPACE);
 }
 
 
-u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
+static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
 {
        nic_t *sp = dev->priv;
 
        return (sp->rx_csum);
 }
-int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+
+static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 {
        nic_t *sp = dev->priv;
 
@@ -5095,17 +5160,19 @@ int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 
        return 0;
 }
-int s2io_get_eeprom_len(struct net_device *dev)
+
+static int s2io_get_eeprom_len(struct net_device *dev)
 {
        return (XENA_EEPROM_SPACE);
 }
 
-int s2io_ethtool_self_test_count(struct net_device *dev)
+static int s2io_ethtool_self_test_count(struct net_device *dev)
 {
        return (S2IO_TEST_LEN);
 }
-void s2io_ethtool_get_strings(struct net_device *dev,
-                             u32 stringset, u8 * data)
+
+static void s2io_ethtool_get_strings(struct net_device *dev,
+                                    u32 stringset, u8 * data)
 {
        switch (stringset) {
        case ETH_SS_TEST:
@@ -5121,7 +5188,7 @@ static int s2io_ethtool_get_stats_count(struct net_device *dev)
        return (S2IO_STAT_LEN);
 }
 
-int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
+static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 {
        if (data)
                dev->features |= NETIF_F_IP_CSUM;
@@ -5154,6 +5221,8 @@ static struct ethtool_ops netdev_ethtool_ops = {
        .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,
        .self_test_count = s2io_ethtool_self_test_count,
        .self_test = s2io_ethtool_test,
        .get_strings = s2io_ethtool_get_strings,
@@ -5174,7 +5243,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
  *  function always return EOPNOTSUPPORTED
  */
 
-int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        return -EOPNOTSUPP;
 }
@@ -5190,7 +5259,7 @@ int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  *   file on failure.
  */
 
-int s2io_change_mtu(struct net_device *dev, int new_mtu)
+static int s2io_change_mtu(struct net_device *dev, int new_mtu)
 {
        nic_t *sp = dev->priv;
 
@@ -5538,16 +5607,7 @@ 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;
-#ifdef CONFIG_2BUFF_MODE
-       int buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2);
-       int buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2);
-       int get_block = ring_data->rx_curr_get_info.block_index;
-       int get_off = ring_data->rx_curr_get_info.offset;
-       buffAdd_t *ba = &ring_data->ba[get_block][get_off];
-       unsigned char *buff;
-#else
-       u16 len = (u16) ((RXD_GET_BUFFER0_SIZE(rxdp->Control_2)) >> 48);;
-#endif
+
        skb->dev = dev;
        if (rxdp->Control_1 & RXD_T_CODE) {
                unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
@@ -5564,19 +5624,36 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
        rxdp->Host_Control = 0;
        sp->rx_pkt_count++;
        sp->stats.rx_packets++;
-#ifndef CONFIG_2BUFF_MODE
-       sp->stats.rx_bytes += len;
-#else
-       sp->stats.rx_bytes += buf0_len + buf2_len;
-#endif
+       if (sp->rxd_mode == RXD_MODE_1) {
+               int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2);
 
-#ifndef CONFIG_2BUFF_MODE
-       skb_put(skb, len);
-#else
-       buff = skb_push(skb, buf0_len);
-       memcpy(buff, ba->ba_0, buf0_len);
-       skb_put(skb, buf2_len);
-#endif
+               sp->stats.rx_bytes += len;
+               skb_put(skb, len);
+
+       } else if (sp->rxd_mode >= RXD_MODE_3A) {
+               int get_block = ring_data->rx_curr_get_info.block_index;
+               int get_off = ring_data->rx_curr_get_info.offset;
+               int buf0_len = RXD_GET_BUFFER0_SIZE_3(rxdp->Control_2);
+               int buf2_len = RXD_GET_BUFFER2_SIZE_3(rxdp->Control_2);
+               unsigned char *buff = skb_push(skb, buf0_len);
+
+               buffAdd_t *ba = &ring_data->ba[get_block][get_off];
+               sp->stats.rx_bytes += buf0_len + buf2_len;
+               memcpy(buff, ba->ba_0, buf0_len);
+
+               if (sp->rxd_mode == RXD_MODE_3A) {
+                       int buf1_len = RXD_GET_BUFFER1_SIZE_3(rxdp->Control_2);
+
+                       skb_put(skb, buf1_len);
+                       skb->len += buf2_len;
+                       skb->data_len += buf2_len;
+                       skb->truesize += buf2_len;
+                       skb_put(skb_shinfo(skb)->frag_list, buf2_len);
+                       sp->stats.rx_bytes += buf1_len;
+
+               } else
+                       skb_put(skb, buf2_len);
+       }
 
        if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
            (sp->rx_csum)) {
@@ -5712,6 +5789,7 @@ 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);
@@ -5723,6 +5801,7 @@ 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
@@ -5844,6 +5923,13 @@ Defaulting to INTA\n");
        sp->pdev = pdev;
        sp->high_dma_flag = dma_flag;
        sp->device_enabled_once = FALSE;
+       if (rx_ring_mode == 1)
+               sp->rxd_mode = RXD_MODE_1;
+       if (rx_ring_mode == 2)
+               sp->rxd_mode = RXD_MODE_3B;
+       if (rx_ring_mode == 3)
+               sp->rxd_mode = RXD_MODE_3A;
+
        sp->intr_type = dev_intr_type;
 
        if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
@@ -5888,7 +5974,8 @@ Defaulting to INTA\n");
                        break;
                }
        }
-       config->max_txds = MAX_SKB_FRAGS + 1;
+       /* + 2 because one Txd for skb->data and one Txd for UFO */
+       config->max_txds = MAX_SKB_FRAGS + 2;
 
        /* Rx side parameters. */
        if (rx_ring_sz[0] == 0)
@@ -5896,7 +5983,7 @@ Defaulting to INTA\n");
        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] *
-                   (MAX_RXDS_PER_BLOCK + 1);
+                   (rxd_count[sp->rxd_mode] + 1);
                config->rx_cfg[i].ring_priority = i;
        }
 
@@ -5982,6 +6069,10 @@ Defaulting to INTA\n");
 #ifdef NETIF_F_TSO
        dev->features |= NETIF_F_TSO;
 #endif
+       if (sp->device_type & XFRAME_II_DEVICE) {
+               dev->features |= NETIF_F_UFO;
+               dev->features |= NETIF_F_HW_CSUM;
+       }
 
        dev->tx_timeout = &s2io_tx_watchdog;
        dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
@@ -6091,9 +6182,6 @@ Defaulting to INTA\n");
                DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
                                get_xena_rev_id(sp->pdev),
                                s2io_driver_version);
-#ifdef CONFIG_2BUFF_MODE
-               DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
-#endif
                switch(sp->intr_type) {
                        case INTA:
                                DBG_PRINT(ERR_DBG, ", Intr type INTA");
@@ -6126,9 +6214,6 @@ Defaulting to INTA\n");
                DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
                                        get_xena_rev_id(sp->pdev),
                                        s2io_driver_version);
-#ifdef CONFIG_2BUFF_MODE
-               DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
-#endif
                switch(sp->intr_type) {
                        case INTA:
                                DBG_PRINT(ERR_DBG, ", Intr type INTA");
@@ -6149,6 +6234,12 @@ Defaulting to INTA\n");
                          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 */
        strcpy(sp->name, dev->name);