Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 3071

kernel-2.6.18-238.el5.src.rpm

From: Michal Schmidt <mschmidt@redhat.com>
Date: Tue, 1 Dec 2009 12:38:09 -0500
Subject: [net] s2io: update driver to current upstream version
Message-id: <20091201123809.3885.19250.stgit@localhost.localdomain>
Patchwork-id: 21563
O-Subject: [RHEL5.5 PATCH] s2io: update driver to current upstream version
Bugzilla: 513942
RH-Acked-by: David S. Miller <davem@redhat.com>

https://bugzilla.redhat.com/show_bug.cgi?id=513942

This updates the s2io Neterion 10GbE driver to the current upstream version.
Includes MSI-X related fixes and using of multiple queues.

Upstream switched to using MSI-X by default. This backported driver still
defaults to INTA. Also the default number of TX queues is kept the same as in
RHEL5.4. The new 'multiq' parameter does not make sense in RHEL5, so it is not
exposed and it's always turned off.

The patch depends on the mdio module I posted in the series for bz448856:
 [RHEL5.5 PATCH 2/5] ethtool.h: add more defines for mdio to use
 [RHEL5.5 PATCH 3/5] mdio: add mdio module from upstream

Brew build:
https://brewweb.devel.redhat.com/taskinfo?taskID=2108561

Testing:
Waiting for Neterion. Testing by anyone else welcome too.

diff --git a/Documentation/networking/s2io.txt b/Documentation/networking/s2io.txt
index 2b4531b..a674c66 100644
--- a/Documentation/networking/s2io.txt
+++ b/Documentation/networking/s2io.txt
@@ -52,13 +52,10 @@ d. MSI/MSI-X. Can be enabled on platforms which support this feature
 (IA64, Xeon) resulting in noticeable performance improvement(upto 7%
 on certain platforms).
 
-e. NAPI. Compile-time option(CONFIG_S2IO_NAPI) for better Rx interrupt 
-moderation.
-
-f. Statistics. Comprehensive MAC-level and software statistics displayed
+e. Statistics. Comprehensive MAC-level and software statistics displayed
 using "ethtool -S" option.
 
-g. Multi-FIFO/Ring. Supports up to 8 transmit queues and receive rings, 
+f. Multi-FIFO/Ring. Supports up to 8 transmit queues and receive rings,
 with multiple steering options.
 
 4.  Command line parameters
@@ -126,7 +123,7 @@ However, you may want to set PCI latency timer to 248.
 #setpci -d 17d5:* LATENCY_TIMER=f8
 For detailed description of the PCI registers, please see Xframe User Guide.
 b. Use 2-buffer mode. This results in large performance boost on
-on certain platforms(eg. SGI Altix, IBM xSeries).
+certain platforms(eg. SGI Altix, IBM xSeries).
 c. Ensure Receive Checksum offload is enabled. Use "ethtool -K ethX" command to 
 set/verify this option.
 d. Enable NAPI feature(in kernel configuration Device Drivers ---> Network 
diff --git a/drivers/net/s2io-compat.h b/drivers/net/s2io-compat.h
new file mode 100644
index 0000000..749c3dc
--- /dev/null
+++ b/drivers/net/s2io-compat.h
@@ -0,0 +1,229 @@
+#ifndef __S2IO_COMPAT_H
+#define __S2IO_COMPAT_H
+
+typedef __u16 __bitwise __sum16;
+
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
+#define pr_err(fmt, ...) \
+	printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_BUF_SIZE 18
+#define DECLARE_MAC_BUF(var) char var[MAC_BUF_SIZE]
+static inline char *print_mac(char *buf, const unsigned char *addr)
+{
+	sprintf(buf, MAC_FMT,
+		addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+	return buf;
+}
+
+static inline int s2io_pci_dma_mapping_error(struct pci_dev *pdev,
+					     dma_addr_t dma_addr)
+{
+	return pci_dma_mapping_error(dma_addr);
+}
+#define pci_dma_mapping_error(pdev, dma_addr) s2io_pci_dma_mapping_error(pdev, dma_addr)
+
+/*
+ * VLAN group compat functions
+ */
+static inline void vlan_group_set_device(struct vlan_group *vg,
+					 u16 vid,
+					 struct net_device *dev)
+{
+	if (vg)
+		vg->vlan_devices[vid] = dev;
+}
+
+/*
+ * delayer work compat
+ */
+typedef void (*work_func_old_t)(void *);
+typedef void (*work_func_t)(struct work_struct *work);
+
+struct delayed_work {
+	struct work_struct work;
+};
+
+static inline void compat_INIT_WORK(struct work_struct *work, work_func_t func)
+{
+	INIT_WORK(work, (work_func_old_t)func, work);
+}
+
+static inline int compat_queue_delayed_work(struct workqueue_struct *wq,
+					    struct delayed_work *work,
+					    unsigned long delay)
+{
+	if (!delay)
+		return queue_work(wq, &work->work);
+	else
+		return queue_delayed_work(wq, &work->work, delay);
+}
+
+static inline int compat_cancel_delayed_work(struct delayed_work *work)
+{
+	return cancel_delayed_work(&work->work);
+}
+
+#undef INIT_WORK
+#define INIT_WORK(_work, _func) compat_INIT_WORK(_work, _func)
+#define INIT_DELAYED_WORK(_work,_func) INIT_WORK(&(_work)->work, _func)
+
+#define queue_delayed_work compat_queue_delayed_work
+#define cancel_delayed_work compat_cancel_delayed_work
+
+/*
+ * Multiqueue stubs and function wrappers for single-queue devices
+ */
+static inline struct net_device *alloc_etherdev_mq(int sizeof_priv,
+				     unsigned int queue_count)
+{
+	BUG_ON(queue_count != 1);
+	return alloc_etherdev(sizeof_priv);
+}
+
+static inline void netif_tx_stop_all_queues(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+}
+
+static inline void netif_tx_start_all_queues(struct net_device *dev)
+{
+	netif_start_queue(dev);
+}
+
+static inline void netif_tx_wake_all_queues(struct net_device *dev)
+{
+	netif_wake_queue(dev);
+}
+
+static inline int __netif_subqueue_stopped(struct net_device *dev,
+					   int fifo_no)
+{
+	WARN_ON(1);
+	return netif_queue_stopped(dev);
+}
+
+static void netif_wake_subqueue(struct net_device *dev, int fifo_no)
+{
+	WARN_ON(1);
+	netif_wake_queue(dev);
+}
+
+static inline void skb_record_rx_queue(struct sk_buff *skb, u16 rx_queue)
+{
+}
+
+typedef int netdev_tx_t;
+
+/*
+ * net_device_ops copied from upstream, but only the members actually
+ * used by the s2io driver.
+ */
+struct net_device_ops {
+	int			(*ndo_open)(struct net_device *dev);
+	int			(*ndo_stop)(struct net_device *dev);
+	netdev_tx_t		(*ndo_start_xmit) (struct sk_buff *skb,
+						   struct net_device *dev);
+	void			(*ndo_set_multicast_list)(struct net_device *dev);
+	int			(*ndo_set_mac_address)(struct net_device *dev,
+						       void *addr);
+	int			(*ndo_validate_addr)(struct net_device *dev);
+	int			(*ndo_do_ioctl)(struct net_device *dev,
+					        struct ifreq *ifr, int cmd);
+	int			(*ndo_change_mtu)(struct net_device *dev,
+						  int new_mtu);
+	void			(*ndo_tx_timeout) (struct net_device *dev);
+	struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);
+	void			(*ndo_vlan_rx_register)(struct net_device *dev,
+						        struct vlan_group *grp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	void                    (*ndo_poll_controller)(struct net_device *dev);
+#endif
+};
+
+#define eth_validate_addr NULL
+
+static inline void s2io_set_netdev_ops(struct net_device *ndev,
+	const struct net_device_ops *ndo)
+{
+	ndev->open               = ndo->ndo_open;
+	ndev->stop               = ndo->ndo_stop;
+	ndev->hard_start_xmit    = ndo->ndo_start_xmit;
+	ndev->set_multicast_list = ndo->ndo_set_multicast_list;
+	ndev->set_mac_address    = ndo->ndo_set_mac_address;
+	BUG_ON(ndo->ndo_validate_addr != eth_validate_addr);
+	ndev->do_ioctl           = ndo->ndo_do_ioctl;
+	ndev->change_mtu         = ndo->ndo_change_mtu;
+	ndev->tx_timeout         = ndo->ndo_tx_timeout;
+	ndev->get_stats          = ndo->ndo_get_stats;
+	ndev->vlan_rx_register   = ndo->ndo_vlan_rx_register;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	ndev->poll_controller    = ndo->ndo_poll_controller;
+#endif
+}
+
+/*
+ * Partial new NAPI to old NAPI mapping
+ * napi->dev is the dummy net_device for the old NAPI.
+ */
+
+static inline void napi_enable(struct napi_struct *napi)
+{
+	netif_poll_enable(napi->dev);
+}
+
+static inline void napi_disable(struct napi_struct *napi)
+{
+	netif_poll_disable(napi->dev);
+}
+
+static inline void napi_schedule(struct napi_struct *napi)
+{
+	netif_rx_schedule(napi->dev);
+}
+
+/* Unlike upstream netif_napi_add(), ours may fail with -ENOMEM */
+static inline int rhel_netif_napi_add(void *nd_priv,
+	struct napi_struct *napi, int (*poll)(struct net_device *, int *),
+	int weight)
+{
+	struct net_device *nd;
+
+	nd = alloc_netdev(0, "", ether_setup);
+	if (!nd)
+		return -ENOMEM;
+
+	nd->priv = nd_priv;
+	nd->weight = weight;
+	nd->poll = poll;
+	set_bit(__LINK_STATE_START, &nd->state);
+	napi->dev = nd;
+	return 0;
+}
+
+static inline void netif_napi_del(struct napi_struct *napi)
+{
+	free_netdev(napi->dev);
+	napi->dev = NULL;
+}
+
+static inline int rhel_napi_poll_wrapper(int (*poll)(struct napi_struct*, int),
+	struct napi_struct *napi, struct net_device *dummy_dev, int *budget)
+{
+	int to_do = min(*budget, dummy_dev->quota);
+	int pkts_processed;
+
+	pkts_processed = poll(napi, to_do);
+
+	*budget -= pkts_processed;
+	dummy_dev->quota -= pkts_processed;
+
+	return (pkts_processed >= to_do);
+}
+
+
+#endif /* __S2IO_COMPAT_H */
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index cfa2679..416669f 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -20,17 +20,17 @@ struct XENA_dev_config {
 
 /* General Control-Status Registers */
 	u64 general_int_status;
-#define GEN_INTR_TXPIC             BIT(0)
-#define GEN_INTR_TXDMA             BIT(1)
-#define GEN_INTR_TXMAC             BIT(2)
-#define GEN_INTR_TXXGXS            BIT(3)
-#define GEN_INTR_TXTRAFFIC         BIT(8)
-#define GEN_INTR_RXPIC             BIT(32)
-#define GEN_INTR_RXDMA             BIT(33)
-#define GEN_INTR_RXMAC             BIT(34)
-#define GEN_INTR_MC                BIT(35)
-#define GEN_INTR_RXXGXS            BIT(36)
-#define GEN_INTR_RXTRAFFIC         BIT(40)
+#define GEN_INTR_TXPIC             s2BIT(0)
+#define GEN_INTR_TXDMA             s2BIT(1)
+#define GEN_INTR_TXMAC             s2BIT(2)
+#define GEN_INTR_TXXGXS            s2BIT(3)
+#define GEN_INTR_TXTRAFFIC         s2BIT(8)
+#define GEN_INTR_RXPIC             s2BIT(32)
+#define GEN_INTR_RXDMA             s2BIT(33)
+#define GEN_INTR_RXMAC             s2BIT(34)
+#define GEN_INTR_MC                s2BIT(35)
+#define GEN_INTR_RXXGXS            s2BIT(36)
+#define GEN_INTR_RXTRAFFIC         s2BIT(40)
 #define GEN_ERROR_INTR             GEN_INTR_TXPIC | GEN_INTR_RXPIC | \
                                    GEN_INTR_TXDMA | GEN_INTR_RXDMA | \
                                    GEN_INTR_TXMAC | GEN_INTR_RXMAC | \
@@ -54,36 +54,37 @@ struct XENA_dev_config {
 
 
 	u64 adapter_status;
-#define ADAPTER_STATUS_TDMA_READY          BIT(0)
-#define ADAPTER_STATUS_RDMA_READY          BIT(1)
-#define ADAPTER_STATUS_PFC_READY           BIT(2)
-#define ADAPTER_STATUS_TMAC_BUF_EMPTY      BIT(3)
-#define ADAPTER_STATUS_PIC_QUIESCENT       BIT(5)
-#define ADAPTER_STATUS_RMAC_REMOTE_FAULT   BIT(6)
-#define ADAPTER_STATUS_RMAC_LOCAL_FAULT    BIT(7)
+#define ADAPTER_STATUS_TDMA_READY          s2BIT(0)
+#define ADAPTER_STATUS_RDMA_READY          s2BIT(1)
+#define ADAPTER_STATUS_PFC_READY           s2BIT(2)
+#define ADAPTER_STATUS_TMAC_BUF_EMPTY      s2BIT(3)
+#define ADAPTER_STATUS_PIC_QUIESCENT       s2BIT(5)
+#define ADAPTER_STATUS_RMAC_REMOTE_FAULT   s2BIT(6)
+#define ADAPTER_STATUS_RMAC_LOCAL_FAULT    s2BIT(7)
 #define ADAPTER_STATUS_RMAC_PCC_IDLE       vBIT(0xFF,8,8)
 #define ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE  vBIT(0x0F,8,8)
 #define ADAPTER_STATUS_RC_PRC_QUIESCENT    vBIT(0xFF,16,8)
-#define ADAPTER_STATUS_MC_DRAM_READY       BIT(24)
-#define ADAPTER_STATUS_MC_QUEUES_READY     BIT(25)
-#define ADAPTER_STATUS_M_PLL_LOCK          BIT(30)
-#define ADAPTER_STATUS_P_PLL_LOCK          BIT(31)
+#define ADAPTER_STATUS_MC_DRAM_READY       s2BIT(24)
+#define ADAPTER_STATUS_MC_QUEUES_READY     s2BIT(25)
+#define ADAPTER_STATUS_RIC_RUNNING         s2BIT(26)
+#define ADAPTER_STATUS_M_PLL_LOCK          s2BIT(30)
+#define ADAPTER_STATUS_P_PLL_LOCK          s2BIT(31)
 
 	u64 adapter_control;
-#define ADAPTER_CNTL_EN                    BIT(7)
-#define ADAPTER_EOI_TX_ON                  BIT(15)
-#define ADAPTER_LED_ON                     BIT(23)
+#define ADAPTER_CNTL_EN                    s2BIT(7)
+#define ADAPTER_EOI_TX_ON                  s2BIT(15)
+#define ADAPTER_LED_ON                     s2BIT(23)
 #define ADAPTER_UDPI(val)                  vBIT(val,36,4)
-#define ADAPTER_WAIT_INT                   BIT(48)
-#define ADAPTER_ECC_EN                     BIT(55)
+#define ADAPTER_WAIT_INT                   s2BIT(48)
+#define ADAPTER_ECC_EN                     s2BIT(55)
 
 	u64 serr_source;
-#define SERR_SOURCE_PIC			BIT(0)
-#define SERR_SOURCE_TXDMA		BIT(1)
-#define SERR_SOURCE_RXDMA		BIT(2)
-#define SERR_SOURCE_MAC                 BIT(3)
-#define SERR_SOURCE_MC                  BIT(4)
-#define SERR_SOURCE_XGXS                BIT(5)
+#define SERR_SOURCE_PIC			s2BIT(0)
+#define SERR_SOURCE_TXDMA		s2BIT(1)
+#define SERR_SOURCE_RXDMA		s2BIT(2)
+#define SERR_SOURCE_MAC                 s2BIT(3)
+#define SERR_SOURCE_MC                  s2BIT(4)
+#define SERR_SOURCE_XGXS                s2BIT(5)
 #define	SERR_SOURCE_ANY			(SERR_SOURCE_PIC	| \
 					SERR_SOURCE_TXDMA	| \
 					SERR_SOURCE_RXDMA	| \
@@ -101,41 +102,41 @@ struct XENA_dev_config {
 #define	PCI_MODE_PCIX_M2_66		0x5
 #define	PCI_MODE_PCIX_M2_100		0x6
 #define	PCI_MODE_PCIX_M2_133		0x7
-#define	PCI_MODE_UNSUPPORTED		BIT(0)
-#define	PCI_MODE_32_BITS		BIT(8)
-#define	PCI_MODE_UNKNOWN_MODE		BIT(9)
+#define	PCI_MODE_UNSUPPORTED		s2BIT(0)
+#define	PCI_MODE_32_BITS		s2BIT(8)
+#define	PCI_MODE_UNKNOWN_MODE		s2BIT(9)
 
 	u8 unused_0[0x800 - 0x128];
 
 /* PCI-X Controller registers */
 	u64 pic_int_status;
 	u64 pic_int_mask;
-#define PIC_INT_TX                     BIT(0)
-#define PIC_INT_FLSH                   BIT(1)
-#define PIC_INT_MDIO                   BIT(2)
-#define PIC_INT_IIC                    BIT(3)
-#define PIC_INT_GPIO                   BIT(4)
-#define PIC_INT_RX                     BIT(32)
+#define PIC_INT_TX                     s2BIT(0)
+#define PIC_INT_FLSH                   s2BIT(1)
+#define PIC_INT_MDIO                   s2BIT(2)
+#define PIC_INT_IIC                    s2BIT(3)
+#define PIC_INT_GPIO                   s2BIT(4)
+#define PIC_INT_RX                     s2BIT(32)
 
 	u64 txpic_int_reg;
 	u64 txpic_int_mask;
-#define PCIX_INT_REG_ECC_SG_ERR                BIT(0)
-#define PCIX_INT_REG_ECC_DB_ERR                BIT(1)
-#define PCIX_INT_REG_FLASHR_R_FSM_ERR          BIT(8)
-#define PCIX_INT_REG_FLASHR_W_FSM_ERR          BIT(9)
-#define PCIX_INT_REG_INI_TX_FSM_SERR           BIT(10)
-#define PCIX_INT_REG_INI_TXO_FSM_ERR           BIT(11)
-#define PCIX_INT_REG_TRT_FSM_SERR              BIT(13)
-#define PCIX_INT_REG_SRT_FSM_SERR              BIT(14)
-#define PCIX_INT_REG_PIFR_FSM_SERR             BIT(15)
-#define PCIX_INT_REG_WRC_TX_SEND_FSM_SERR      BIT(21)
-#define PCIX_INT_REG_RRC_TX_REQ_FSM_SERR       BIT(23)
-#define PCIX_INT_REG_INI_RX_FSM_SERR           BIT(48)
-#define PCIX_INT_REG_RA_RX_FSM_SERR            BIT(50)
+#define PCIX_INT_REG_ECC_SG_ERR                s2BIT(0)
+#define PCIX_INT_REG_ECC_DB_ERR                s2BIT(1)
+#define PCIX_INT_REG_FLASHR_R_FSM_ERR          s2BIT(8)
+#define PCIX_INT_REG_FLASHR_W_FSM_ERR          s2BIT(9)
+#define PCIX_INT_REG_INI_TX_FSM_SERR           s2BIT(10)
+#define PCIX_INT_REG_INI_TXO_FSM_ERR           s2BIT(11)
+#define PCIX_INT_REG_TRT_FSM_SERR              s2BIT(13)
+#define PCIX_INT_REG_SRT_FSM_SERR              s2BIT(14)
+#define PCIX_INT_REG_PIFR_FSM_SERR             s2BIT(15)
+#define PCIX_INT_REG_WRC_TX_SEND_FSM_SERR      s2BIT(21)
+#define PCIX_INT_REG_RRC_TX_REQ_FSM_SERR       s2BIT(23)
+#define PCIX_INT_REG_INI_RX_FSM_SERR           s2BIT(48)
+#define PCIX_INT_REG_RA_RX_FSM_SERR            s2BIT(50)
 /*
-#define PCIX_INT_REG_WRC_RX_SEND_FSM_SERR      BIT(52)
-#define PCIX_INT_REG_RRC_RX_REQ_FSM_SERR       BIT(54)
-#define PCIX_INT_REG_RRC_RX_SPLIT_FSM_SERR     BIT(58)
+#define PCIX_INT_REG_WRC_RX_SEND_FSM_SERR      s2BIT(52)
+#define PCIX_INT_REG_RRC_RX_REQ_FSM_SERR       s2BIT(54)
+#define PCIX_INT_REG_RRC_RX_SPLIT_FSM_SERR     s2BIT(58)
 */
 	u64 txpic_alarms;
 	u64 rxpic_int_reg;
@@ -144,92 +145,92 @@ struct XENA_dev_config {
 
 	u64 flsh_int_reg;
 	u64 flsh_int_mask;
-#define PIC_FLSH_INT_REG_CYCLE_FSM_ERR         BIT(63)
-#define PIC_FLSH_INT_REG_ERR                   BIT(62)
+#define PIC_FLSH_INT_REG_CYCLE_FSM_ERR         s2BIT(63)
+#define PIC_FLSH_INT_REG_ERR                   s2BIT(62)
 	u64 flash_alarms;
 
 	u64 mdio_int_reg;
 	u64 mdio_int_mask;
-#define MDIO_INT_REG_MDIO_BUS_ERR              BIT(0)
-#define MDIO_INT_REG_DTX_BUS_ERR               BIT(8)
-#define MDIO_INT_REG_LASI                      BIT(39)
+#define MDIO_INT_REG_MDIO_BUS_ERR              s2BIT(0)
+#define MDIO_INT_REG_DTX_BUS_ERR               s2BIT(8)
+#define MDIO_INT_REG_LASI                      s2BIT(39)
 	u64 mdio_alarms;
 
 	u64 iic_int_reg;
 	u64 iic_int_mask;
-#define IIC_INT_REG_BUS_FSM_ERR                BIT(4)
-#define IIC_INT_REG_BIT_FSM_ERR                BIT(5)
-#define IIC_INT_REG_CYCLE_FSM_ERR              BIT(6)
-#define IIC_INT_REG_REQ_FSM_ERR                BIT(7)
-#define IIC_INT_REG_ACK_ERR                    BIT(8)
+#define IIC_INT_REG_BUS_FSM_ERR                s2BIT(4)
+#define IIC_INT_REG_BIT_FSM_ERR                s2BIT(5)
+#define IIC_INT_REG_CYCLE_FSM_ERR              s2BIT(6)
+#define IIC_INT_REG_REQ_FSM_ERR                s2BIT(7)
+#define IIC_INT_REG_ACK_ERR                    s2BIT(8)
 	u64 iic_alarms;
 
 	u8 unused4[0x08];
 
 	u64 gpio_int_reg;
-#define GPIO_INT_REG_DP_ERR_INT                BIT(0)
-#define GPIO_INT_REG_LINK_DOWN                 BIT(1)
-#define GPIO_INT_REG_LINK_UP                   BIT(2)
+#define GPIO_INT_REG_DP_ERR_INT                s2BIT(0)
+#define GPIO_INT_REG_LINK_DOWN                 s2BIT(1)
+#define GPIO_INT_REG_LINK_UP                   s2BIT(2)
 	u64 gpio_int_mask;
-#define GPIO_INT_MASK_LINK_DOWN                BIT(1)
-#define GPIO_INT_MASK_LINK_UP                  BIT(2)
+#define GPIO_INT_MASK_LINK_DOWN                s2BIT(1)
+#define GPIO_INT_MASK_LINK_UP                  s2BIT(2)
 	u64 gpio_alarms;
 
 	u8 unused5[0x38];
 
 	u64 tx_traffic_int;
-#define TX_TRAFFIC_INT_n(n)                    BIT(n)
+#define TX_TRAFFIC_INT_n(n)                    s2BIT(n)
 	u64 tx_traffic_mask;
 
 	u64 rx_traffic_int;
-#define RX_TRAFFIC_INT_n(n)                    BIT(n)
+#define RX_TRAFFIC_INT_n(n)                    s2BIT(n)
 	u64 rx_traffic_mask;
 
 /* PIC Control registers */
 	u64 pic_control;
-#define PIC_CNTL_RX_ALARM_MAP_1                BIT(0)
+#define PIC_CNTL_RX_ALARM_MAP_1                s2BIT(0)
 #define PIC_CNTL_SHARED_SPLITS(n)              vBIT(n,11,5)
 
 	u64 swapper_ctrl;
-#define SWAPPER_CTRL_PIF_R_FE                  BIT(0)
-#define SWAPPER_CTRL_PIF_R_SE                  BIT(1)
-#define SWAPPER_CTRL_PIF_W_FE                  BIT(8)
-#define SWAPPER_CTRL_PIF_W_SE                  BIT(9)
-#define SWAPPER_CTRL_TXP_FE                    BIT(16)
-#define SWAPPER_CTRL_TXP_SE                    BIT(17)
-#define SWAPPER_CTRL_TXD_R_FE                  BIT(18)
-#define SWAPPER_CTRL_TXD_R_SE                  BIT(19)
-#define SWAPPER_CTRL_TXD_W_FE                  BIT(20)
-#define SWAPPER_CTRL_TXD_W_SE                  BIT(21)
-#define SWAPPER_CTRL_TXF_R_FE                  BIT(22)
-#define SWAPPER_CTRL_TXF_R_SE                  BIT(23)
-#define SWAPPER_CTRL_RXD_R_FE                  BIT(32)
-#define SWAPPER_CTRL_RXD_R_SE                  BIT(33)
-#define SWAPPER_CTRL_RXD_W_FE                  BIT(34)
-#define SWAPPER_CTRL_RXD_W_SE                  BIT(35)
-#define SWAPPER_CTRL_RXF_W_FE                  BIT(36)
-#define SWAPPER_CTRL_RXF_W_SE                  BIT(37)
-#define SWAPPER_CTRL_XMSI_FE                   BIT(40)
-#define SWAPPER_CTRL_XMSI_SE                   BIT(41)
-#define SWAPPER_CTRL_STATS_FE                  BIT(48)
-#define SWAPPER_CTRL_STATS_SE                  BIT(49)
+#define SWAPPER_CTRL_PIF_R_FE                  s2BIT(0)
+#define SWAPPER_CTRL_PIF_R_SE                  s2BIT(1)
+#define SWAPPER_CTRL_PIF_W_FE                  s2BIT(8)
+#define SWAPPER_CTRL_PIF_W_SE                  s2BIT(9)
+#define SWAPPER_CTRL_TXP_FE                    s2BIT(16)
+#define SWAPPER_CTRL_TXP_SE                    s2BIT(17)
+#define SWAPPER_CTRL_TXD_R_FE                  s2BIT(18)
+#define SWAPPER_CTRL_TXD_R_SE                  s2BIT(19)
+#define SWAPPER_CTRL_TXD_W_FE                  s2BIT(20)
+#define SWAPPER_CTRL_TXD_W_SE                  s2BIT(21)
+#define SWAPPER_CTRL_TXF_R_FE                  s2BIT(22)
+#define SWAPPER_CTRL_TXF_R_SE                  s2BIT(23)
+#define SWAPPER_CTRL_RXD_R_FE                  s2BIT(32)
+#define SWAPPER_CTRL_RXD_R_SE                  s2BIT(33)
+#define SWAPPER_CTRL_RXD_W_FE                  s2BIT(34)
+#define SWAPPER_CTRL_RXD_W_SE                  s2BIT(35)
+#define SWAPPER_CTRL_RXF_W_FE                  s2BIT(36)
+#define SWAPPER_CTRL_RXF_W_SE                  s2BIT(37)
+#define SWAPPER_CTRL_XMSI_FE                   s2BIT(40)
+#define SWAPPER_CTRL_XMSI_SE                   s2BIT(41)
+#define SWAPPER_CTRL_STATS_FE                  s2BIT(48)
+#define SWAPPER_CTRL_STATS_SE                  s2BIT(49)
 
 	u64 pif_rd_swapper_fb;
 #define IF_RD_SWAPPER_FB                            0x0123456789ABCDEF
 
 	u64 scheduled_int_ctrl;
-#define SCHED_INT_CTRL_TIMER_EN                BIT(0)
-#define SCHED_INT_CTRL_ONE_SHOT                BIT(1)
-#define SCHED_INT_CTRL_INT2MSI                 TBD
+#define SCHED_INT_CTRL_TIMER_EN                s2BIT(0)
+#define SCHED_INT_CTRL_ONE_SHOT                s2BIT(1)
+#define SCHED_INT_CTRL_INT2MSI(val)		vBIT(val,10,6)
 #define SCHED_INT_PERIOD                       TBD
 
 	u64 txreqtimeout;
 #define TXREQTO_VAL(val)						vBIT(val,0,32)
-#define TXREQTO_EN								BIT(63)
+#define TXREQTO_EN								s2BIT(63)
 
 	u64 statsreqtimeout;
 #define STATREQTO_VAL(n)                       TBD
-#define STATREQTO_EN                           BIT(63)
+#define STATREQTO_EN                           s2BIT(63)
 
 	u64 read_retry_delay;
 	u64 read_retry_acceleration;
@@ -249,16 +250,16 @@ struct XENA_dev_config {
 	u64 tx_mat0_n[0x8];
 #define TX_MAT_SET(fifo, msi)			vBIT(msi, (8 * fifo), 8)
 
-	u8 unused_1[0x8];
+	u64 xmsi_mask_reg;
 	u64 stat_byte_cnt;
 #define STAT_BC(n)                              vBIT(n,4,12)
 
 	/* Automated statistics collection */
 	u64 stat_cfg;
-#define STAT_CFG_STAT_EN           BIT(0)
-#define STAT_CFG_ONE_SHOT_EN       BIT(1)
-#define STAT_CFG_STAT_NS_EN        BIT(8)
-#define STAT_CFG_STAT_RO           BIT(9)
+#define STAT_CFG_STAT_EN           s2BIT(0)
+#define STAT_CFG_ONE_SHOT_EN       s2BIT(1)
+#define STAT_CFG_STAT_NS_EN        s2BIT(8)
+#define STAT_CFG_STAT_RO           s2BIT(9)
 #define STAT_TRSF_PER(n)           TBD
 #define	PER_SEC					   0x208d5
 #define	SET_UPDT_PERIOD(n)		   vBIT((PER_SEC*n),32,32)
@@ -270,11 +271,6 @@ struct XENA_dev_config {
 	u64 mdio_control;
 #define MDIO_MMD_INDX_ADDR(val)		vBIT(val, 0, 16)
 #define MDIO_MMD_DEV_ADDR(val)		vBIT(val, 19, 5)
-#define MDIO_MMD_PMA_DEV_ADDR		0x1
-#define MDIO_MMD_PMD_DEV_ADDR		0x1
-#define MDIO_MMD_WIS_DEV_ADDR		0x2
-#define MDIO_MMD_PCS_DEV_ADDR		0x3
-#define MDIO_MMD_PHYXS_DEV_ADDR		0x4
 #define MDIO_MMS_PRT_ADDR(val)		vBIT(val, 27, 5)
 #define MDIO_CTRL_START_TRANS(val)	vBIT(val, 56, 4)
 #define MDIO_OP(val)			vBIT(val, 60, 2)
@@ -290,18 +286,18 @@ struct XENA_dev_config {
 #define	I2C_CONTROL_DEV_ID(id)		vBIT(id,1,3)
 #define	I2C_CONTROL_ADDR(addr)		vBIT(addr,5,11)
 #define	I2C_CONTROL_BYTE_CNT(cnt)	vBIT(cnt,22,2)
-#define	I2C_CONTROL_READ			BIT(24)
-#define	I2C_CONTROL_NACK			BIT(25)
+#define	I2C_CONTROL_READ			s2BIT(24)
+#define	I2C_CONTROL_NACK			s2BIT(25)
 #define	I2C_CONTROL_CNTL_START		vBIT(0xE,28,4)
 #define	I2C_CONTROL_CNTL_END(val)	(val & vBIT(0x1,28,4))
 #define	I2C_CONTROL_GET_DATA(val)	(u32)(val & 0xFFFFFFFF)
 #define	I2C_CONTROL_SET_DATA(val)	vBIT(val,32,32)
 
 	u64 gpio_control;
-#define GPIO_CTRL_GPIO_0		BIT(8)
+#define GPIO_CTRL_GPIO_0		s2BIT(8)
 	u64 misc_control;
-#define FAULT_BEHAVIOUR			BIT(0)
-#define EXT_REQ_EN			BIT(1)
+#define FAULT_BEHAVIOUR			s2BIT(0)
+#define EXT_REQ_EN			s2BIT(1)
 #define MISC_LINK_STABILITY_PRD(val)   vBIT(val,29,3)
 
 	u8 unused7_1[0x230 - 0x208];
@@ -317,41 +313,74 @@ struct XENA_dev_config {
 /* TxDMA registers */
 	u64 txdma_int_status;
 	u64 txdma_int_mask;
-#define TXDMA_PFC_INT                  BIT(0)
-#define TXDMA_TDA_INT                  BIT(1)
-#define TXDMA_PCC_INT                  BIT(2)
-#define TXDMA_TTI_INT                  BIT(3)
-#define TXDMA_LSO_INT                  BIT(4)
-#define TXDMA_TPA_INT                  BIT(5)
-#define TXDMA_SM_INT                   BIT(6)
+#define TXDMA_PFC_INT                  s2BIT(0)
+#define TXDMA_TDA_INT                  s2BIT(1)
+#define TXDMA_PCC_INT                  s2BIT(2)
+#define TXDMA_TTI_INT                  s2BIT(3)
+#define TXDMA_LSO_INT                  s2BIT(4)
+#define TXDMA_TPA_INT                  s2BIT(5)
+#define TXDMA_SM_INT                   s2BIT(6)
 	u64 pfc_err_reg;
+#define PFC_ECC_SG_ERR			s2BIT(7)
+#define PFC_ECC_DB_ERR			s2BIT(15)
+#define PFC_SM_ERR_ALARM		s2BIT(23)
+#define PFC_MISC_0_ERR			s2BIT(31)
+#define PFC_MISC_1_ERR			s2BIT(32)
+#define PFC_PCIX_ERR			s2BIT(39)
 	u64 pfc_err_mask;
 	u64 pfc_err_alarm;
 
 	u64 tda_err_reg;
+#define TDA_Fn_ECC_SG_ERR		vBIT(0xff,0,8)
+#define TDA_Fn_ECC_DB_ERR		vBIT(0xff,8,8)
+#define TDA_SM0_ERR_ALARM		s2BIT(22)
+#define TDA_SM1_ERR_ALARM		s2BIT(23)
+#define TDA_PCIX_ERR			s2BIT(39)
 	u64 tda_err_mask;
 	u64 tda_err_alarm;
 
 	u64 pcc_err_reg;
-#define PCC_FB_ECC_DB_ERR		vBIT(0xFF, 16, 8)
+#define PCC_FB_ECC_SG_ERR		vBIT(0xFF,0,8)
+#define PCC_TXB_ECC_SG_ERR		vBIT(0xFF,8,8)
+#define PCC_FB_ECC_DB_ERR		vBIT(0xFF,16, 8)
+#define PCC_TXB_ECC_DB_ERR		vBIT(0xff,24,8)
+#define PCC_SM_ERR_ALARM		vBIT(0xff,32,8)
+#define PCC_WR_ERR_ALARM		vBIT(0xff,40,8)
+#define PCC_N_SERR			vBIT(0xff,48,8)
+#define PCC_6_COF_OV_ERR		s2BIT(56)
+#define PCC_7_COF_OV_ERR		s2BIT(57)
+#define PCC_6_LSO_OV_ERR		s2BIT(58)
+#define PCC_7_LSO_OV_ERR		s2BIT(59)
 #define PCC_ENABLE_FOUR			vBIT(0x0F,0,8)
-
 	u64 pcc_err_mask;
 	u64 pcc_err_alarm;
 
 	u64 tti_err_reg;
+#define TTI_ECC_SG_ERR			s2BIT(7)
+#define TTI_ECC_DB_ERR			s2BIT(15)
+#define TTI_SM_ERR_ALARM		s2BIT(23)
 	u64 tti_err_mask;
 	u64 tti_err_alarm;
 
 	u64 lso_err_reg;
+#define LSO6_SEND_OFLOW			s2BIT(12)
+#define LSO7_SEND_OFLOW			s2BIT(13)
+#define LSO6_ABORT			s2BIT(14)
+#define LSO7_ABORT			s2BIT(15)
+#define LSO6_SM_ERR_ALARM		s2BIT(22)
+#define LSO7_SM_ERR_ALARM		s2BIT(23)
 	u64 lso_err_mask;
 	u64 lso_err_alarm;
 
 	u64 tpa_err_reg;
+#define TPA_TX_FRM_DROP			s2BIT(7)
+#define TPA_SM_ERR_ALARM		s2BIT(23)
+
 	u64 tpa_err_mask;
 	u64 tpa_err_alarm;
 
 	u64 sm_err_reg;
+#define SM_SM_ERR_ALARM			s2BIT(15)
 	u64 sm_err_mask;
 	u64 sm_err_alarm;
 
@@ -364,7 +393,7 @@ struct XENA_dev_config {
 #define X_MAX_FIFOS                        8
 #define X_FIFO_MAX_LEN                     0x1FFF	/*8191 */
 	u64 tx_fifo_partition_0;
-#define TX_FIFO_PARTITION_EN               BIT(0)
+#define TX_FIFO_PARTITION_EN               s2BIT(0)
 #define TX_FIFO_PARTITION_0_PRI(val)       vBIT(val,5,3)
 #define TX_FIFO_PARTITION_0_LEN(val)       vBIT(val,19,13)
 #define TX_FIFO_PARTITION_1_PRI(val)       vBIT(val,37,3)
@@ -404,16 +433,16 @@ struct XENA_dev_config {
 	u64 tx_w_round_robin_4;
 
 	u64 tti_command_mem;
-#define TTI_CMD_MEM_WE                     BIT(7)
-#define TTI_CMD_MEM_STROBE_NEW_CMD         BIT(15)
-#define TTI_CMD_MEM_STROBE_BEING_EXECUTED  BIT(15)
+#define TTI_CMD_MEM_WE                     s2BIT(7)
+#define TTI_CMD_MEM_STROBE_NEW_CMD         s2BIT(15)
+#define TTI_CMD_MEM_STROBE_BEING_EXECUTED  s2BIT(15)
 #define TTI_CMD_MEM_OFFSET(n)              vBIT(n,26,6)
 
 	u64 tti_data1_mem;
 #define TTI_DATA1_MEM_TX_TIMER_VAL(n)      vBIT(n,6,26)
 #define TTI_DATA1_MEM_TX_TIMER_AC_CI(n)    vBIT(n,38,2)
-#define TTI_DATA1_MEM_TX_TIMER_AC_EN       BIT(38)
-#define TTI_DATA1_MEM_TX_TIMER_CI_EN       BIT(39)
+#define TTI_DATA1_MEM_TX_TIMER_AC_EN       s2BIT(38)
+#define TTI_DATA1_MEM_TX_TIMER_CI_EN       s2BIT(39)
 #define TTI_DATA1_MEM_TX_URNG_A(n)         vBIT(n,41,7)
 #define TTI_DATA1_MEM_TX_URNG_B(n)         vBIT(n,49,7)
 #define TTI_DATA1_MEM_TX_URNG_C(n)         vBIT(n,57,7)
@@ -426,11 +455,11 @@ struct XENA_dev_config {
 
 /* Tx Protocol assist */
 	u64 tx_pa_cfg;
-#define TX_PA_CFG_IGNORE_FRM_ERR           BIT(1)
-#define TX_PA_CFG_IGNORE_SNAP_OUI          BIT(2)
-#define TX_PA_CFG_IGNORE_LLC_CTRL          BIT(3)
-#define	TX_PA_CFG_IGNORE_L2_ERR			   BIT(6)
-#define RX_PA_CFG_STRIP_VLAN_TAG		BIT(15)
+#define TX_PA_CFG_IGNORE_FRM_ERR           s2BIT(1)
+#define TX_PA_CFG_IGNORE_SNAP_OUI          s2BIT(2)
+#define TX_PA_CFG_IGNORE_LLC_CTRL          s2BIT(3)
+#define	TX_PA_CFG_IGNORE_L2_ERR			   s2BIT(6)
+#define RX_PA_CFG_STRIP_VLAN_TAG		s2BIT(15)
 
 /* Recent add, used only debug purposes. */
 	u64 pcc_enable;
@@ -444,28 +473,58 @@ struct XENA_dev_config {
 /* RxDMA Registers */
 	u64 rxdma_int_status;
 	u64 rxdma_int_mask;
-#define RXDMA_INT_RC_INT_M             BIT(0)
-#define RXDMA_INT_RPA_INT_M            BIT(1)
-#define RXDMA_INT_RDA_INT_M            BIT(2)
-#define RXDMA_INT_RTI_INT_M            BIT(3)
+#define RXDMA_INT_RC_INT_M             s2BIT(0)
+#define RXDMA_INT_RPA_INT_M            s2BIT(1)
+#define RXDMA_INT_RDA_INT_M            s2BIT(2)
+#define RXDMA_INT_RTI_INT_M            s2BIT(3)
 
 	u64 rda_err_reg;
+#define RDA_RXDn_ECC_SG_ERR		vBIT(0xFF,0,8)
+#define RDA_RXDn_ECC_DB_ERR		vBIT(0xFF,8,8)
+#define RDA_FRM_ECC_SG_ERR		s2BIT(23)
+#define RDA_FRM_ECC_DB_N_AERR		s2BIT(31)
+#define RDA_SM1_ERR_ALARM		s2BIT(38)
+#define RDA_SM0_ERR_ALARM		s2BIT(39)
+#define RDA_MISC_ERR			s2BIT(47)
+#define RDA_PCIX_ERR			s2BIT(55)
+#define RDA_RXD_ECC_DB_SERR		s2BIT(63)
 	u64 rda_err_mask;
 	u64 rda_err_alarm;
 
 	u64 rc_err_reg;
+#define RC_PRCn_ECC_SG_ERR		vBIT(0xFF,0,8)
+#define RC_PRCn_ECC_DB_ERR		vBIT(0xFF,8,8)
+#define RC_FTC_ECC_SG_ERR		s2BIT(23)
+#define RC_FTC_ECC_DB_ERR		s2BIT(31)
+#define RC_PRCn_SM_ERR_ALARM		vBIT(0xFF,32,8)
+#define RC_FTC_SM_ERR_ALARM		s2BIT(47)
+#define RC_RDA_FAIL_WR_Rn		vBIT(0xFF,48,8)
 	u64 rc_err_mask;
 	u64 rc_err_alarm;
 
 	u64 prc_pcix_err_reg;
+#define PRC_PCI_AB_RD_Rn		vBIT(0xFF,0,8)
+#define PRC_PCI_DP_RD_Rn		vBIT(0xFF,8,8)
+#define PRC_PCI_AB_WR_Rn		vBIT(0xFF,16,8)
+#define PRC_PCI_DP_WR_Rn		vBIT(0xFF,24,8)
+#define PRC_PCI_AB_F_WR_Rn		vBIT(0xFF,32,8)
+#define PRC_PCI_DP_F_WR_Rn		vBIT(0xFF,40,8)
 	u64 prc_pcix_err_mask;
 	u64 prc_pcix_err_alarm;
 
 	u64 rpa_err_reg;
+#define RPA_ECC_SG_ERR			s2BIT(7)
+#define RPA_ECC_DB_ERR			s2BIT(15)
+#define RPA_FLUSH_REQUEST		s2BIT(22)
+#define RPA_SM_ERR_ALARM		s2BIT(23)
+#define RPA_CREDIT_ERR			s2BIT(31)
 	u64 rpa_err_mask;
 	u64 rpa_err_alarm;
 
 	u64 rti_err_reg;
+#define RTI_ECC_SG_ERR			s2BIT(7)
+#define RTI_ECC_DB_ERR			s2BIT(15)
+#define RTI_SM_ERR_ALARM		s2BIT(23)
 	u64 rti_err_mask;
 	u64 rti_err_alarm;
 
@@ -505,49 +564,49 @@ struct XENA_dev_config {
 #endif
 	u64 prc_rxd0_n[RX_MAX_RINGS];
 	u64 prc_ctrl_n[RX_MAX_RINGS];
-#define PRC_CTRL_RC_ENABLED                    BIT(7)
-#define PRC_CTRL_RING_MODE                     (BIT(14)|BIT(15))
+#define PRC_CTRL_RC_ENABLED                    s2BIT(7)
+#define PRC_CTRL_RING_MODE                     (s2BIT(14)|s2BIT(15))
 #define PRC_CTRL_RING_MODE_1                   vBIT(0,14,2)
 #define PRC_CTRL_RING_MODE_3                   vBIT(1,14,2)
 #define PRC_CTRL_RING_MODE_5                   vBIT(2,14,2)
 #define PRC_CTRL_RING_MODE_x                   vBIT(3,14,2)
-#define PRC_CTRL_NO_SNOOP                      (BIT(22)|BIT(23))
-#define PRC_CTRL_NO_SNOOP_DESC                 BIT(22)
-#define PRC_CTRL_NO_SNOOP_BUFF                 BIT(23)
-#define PRC_CTRL_BIMODAL_INTERRUPT             BIT(37)
-#define PRC_CTRL_GROUP_READS                   BIT(38)
+#define PRC_CTRL_NO_SNOOP                      (s2BIT(22)|s2BIT(23))
+#define PRC_CTRL_NO_SNOOP_DESC                 s2BIT(22)
+#define PRC_CTRL_NO_SNOOP_BUFF                 s2BIT(23)
+#define PRC_CTRL_BIMODAL_INTERRUPT             s2BIT(37)
+#define PRC_CTRL_GROUP_READS                   s2BIT(38)
 #define PRC_CTRL_RXD_BACKOFF_INTERVAL(val)     vBIT(val,40,24)
 
 	u64 prc_alarm_action;
-#define PRC_ALARM_ACTION_RR_R0_STOP            BIT(3)
-#define PRC_ALARM_ACTION_RW_R0_STOP            BIT(7)
-#define PRC_ALARM_ACTION_RR_R1_STOP            BIT(11)
-#define PRC_ALARM_ACTION_RW_R1_STOP            BIT(15)
-#define PRC_ALARM_ACTION_RR_R2_STOP            BIT(19)
-#define PRC_ALARM_ACTION_RW_R2_STOP            BIT(23)
-#define PRC_ALARM_ACTION_RR_R3_STOP            BIT(27)
-#define PRC_ALARM_ACTION_RW_R3_STOP            BIT(31)
-#define PRC_ALARM_ACTION_RR_R4_STOP            BIT(35)
-#define PRC_ALARM_ACTION_RW_R4_STOP            BIT(39)
-#define PRC_ALARM_ACTION_RR_R5_STOP            BIT(43)
-#define PRC_ALARM_ACTION_RW_R5_STOP            BIT(47)
-#define PRC_ALARM_ACTION_RR_R6_STOP            BIT(51)
-#define PRC_ALARM_ACTION_RW_R6_STOP            BIT(55)
-#define PRC_ALARM_ACTION_RR_R7_STOP            BIT(59)
-#define PRC_ALARM_ACTION_RW_R7_STOP            BIT(63)
+#define PRC_ALARM_ACTION_RR_R0_STOP            s2BIT(3)
+#define PRC_ALARM_ACTION_RW_R0_STOP            s2BIT(7)
+#define PRC_ALARM_ACTION_RR_R1_STOP            s2BIT(11)
+#define PRC_ALARM_ACTION_RW_R1_STOP            s2BIT(15)
+#define PRC_ALARM_ACTION_RR_R2_STOP            s2BIT(19)
+#define PRC_ALARM_ACTION_RW_R2_STOP            s2BIT(23)
+#define PRC_ALARM_ACTION_RR_R3_STOP            s2BIT(27)
+#define PRC_ALARM_ACTION_RW_R3_STOP            s2BIT(31)
+#define PRC_ALARM_ACTION_RR_R4_STOP            s2BIT(35)
+#define PRC_ALARM_ACTION_RW_R4_STOP            s2BIT(39)
+#define PRC_ALARM_ACTION_RR_R5_STOP            s2BIT(43)
+#define PRC_ALARM_ACTION_RW_R5_STOP            s2BIT(47)
+#define PRC_ALARM_ACTION_RR_R6_STOP            s2BIT(51)
+#define PRC_ALARM_ACTION_RW_R6_STOP            s2BIT(55)
+#define PRC_ALARM_ACTION_RR_R7_STOP            s2BIT(59)
+#define PRC_ALARM_ACTION_RW_R7_STOP            s2BIT(63)
 
 /* Receive traffic interrupts */
 	u64 rti_command_mem;
-#define RTI_CMD_MEM_WE                          BIT(7)
-#define RTI_CMD_MEM_STROBE                      BIT(15)
-#define RTI_CMD_MEM_STROBE_NEW_CMD              BIT(15)
-#define RTI_CMD_MEM_STROBE_CMD_BEING_EXECUTED   BIT(15)
+#define RTI_CMD_MEM_WE                          s2BIT(7)
+#define RTI_CMD_MEM_STROBE                      s2BIT(15)
+#define RTI_CMD_MEM_STROBE_NEW_CMD              s2BIT(15)
+#define RTI_CMD_MEM_STROBE_CMD_BEING_EXECUTED   s2BIT(15)
 #define RTI_CMD_MEM_OFFSET(n)                   vBIT(n,29,3)
 
 	u64 rti_data1_mem;
 #define RTI_DATA1_MEM_RX_TIMER_VAL(n)      vBIT(n,3,29)
-#define RTI_DATA1_MEM_RX_TIMER_AC_EN       BIT(38)
-#define RTI_DATA1_MEM_RX_TIMER_CI_EN       BIT(39)
+#define RTI_DATA1_MEM_RX_TIMER_AC_EN       s2BIT(38)
+#define RTI_DATA1_MEM_RX_TIMER_CI_EN       s2BIT(39)
 #define RTI_DATA1_MEM_RX_URNG_A(n)         vBIT(n,41,7)
 #define RTI_DATA1_MEM_RX_URNG_B(n)         vBIT(n,49,7)
 #define RTI_DATA1_MEM_RX_URNG_C(n)         vBIT(n,57,7)
@@ -559,10 +618,10 @@ struct XENA_dev_config {
 #define RTI_DATA2_MEM_RX_UFC_D(n)          vBIT(n,48,16)
 
 	u64 rx_pa_cfg;
-#define RX_PA_CFG_IGNORE_FRM_ERR           BIT(1)
-#define RX_PA_CFG_IGNORE_SNAP_OUI          BIT(2)
-#define RX_PA_CFG_IGNORE_LLC_CTRL          BIT(3)
-#define RX_PA_CFG_IGNORE_L2_ERR            BIT(6)
+#define RX_PA_CFG_IGNORE_FRM_ERR           s2BIT(1)
+#define RX_PA_CFG_IGNORE_SNAP_OUI          s2BIT(2)
+#define RX_PA_CFG_IGNORE_LLC_CTRL          s2BIT(3)
+#define RX_PA_CFG_IGNORE_L2_ERR            s2BIT(6)
 
 	u64 unused_11_1;
 
@@ -578,38 +637,64 @@ struct XENA_dev_config {
 /* Media Access Controller Register */
 	u64 mac_int_status;
 	u64 mac_int_mask;
-#define MAC_INT_STATUS_TMAC_INT            BIT(0)
-#define MAC_INT_STATUS_RMAC_INT            BIT(1)
+#define MAC_INT_STATUS_TMAC_INT            s2BIT(0)
+#define MAC_INT_STATUS_RMAC_INT            s2BIT(1)
 
 	u64 mac_tmac_err_reg;
-#define TMAC_ERR_REG_TMAC_ECC_DB_ERR       BIT(15)
-#define TMAC_ERR_REG_TMAC_TX_BUF_OVRN      BIT(23)
-#define TMAC_ERR_REG_TMAC_TX_CRI_ERR       BIT(31)
+#define TMAC_ECC_SG_ERR				s2BIT(7)
+#define TMAC_ECC_DB_ERR				s2BIT(15)
+#define TMAC_TX_BUF_OVRN			s2BIT(23)
+#define TMAC_TX_CRI_ERR				s2BIT(31)
+#define TMAC_TX_SM_ERR				s2BIT(39)
+#define TMAC_DESC_ECC_SG_ERR			s2BIT(47)
+#define TMAC_DESC_ECC_DB_ERR			s2BIT(55)
+
 	u64 mac_tmac_err_mask;
 	u64 mac_tmac_err_alarm;
 
 	u64 mac_rmac_err_reg;
-#define RMAC_ERR_REG_RX_BUFF_OVRN          BIT(0)
-#define RMAC_ERR_REG_RTS_ECC_DB_ERR        BIT(14)
-#define RMAC_ERR_REG_ECC_DB_ERR            BIT(15)
-#define RMAC_LINK_STATE_CHANGE_INT         BIT(31)
+#define RMAC_RX_BUFF_OVRN			s2BIT(0)
+#define RMAC_FRM_RCVD_INT			s2BIT(1)
+#define RMAC_UNUSED_INT				s2BIT(2)
+#define RMAC_RTS_PNUM_ECC_SG_ERR		s2BIT(5)
+#define RMAC_RTS_DS_ECC_SG_ERR			s2BIT(6)
+#define RMAC_RD_BUF_ECC_SG_ERR			s2BIT(7)
+#define RMAC_RTH_MAP_ECC_SG_ERR			s2BIT(8)
+#define RMAC_RTH_SPDM_ECC_SG_ERR		s2BIT(9)
+#define RMAC_RTS_VID_ECC_SG_ERR			s2BIT(10)
+#define RMAC_DA_SHADOW_ECC_SG_ERR		s2BIT(11)
+#define RMAC_RTS_PNUM_ECC_DB_ERR		s2BIT(13)
+#define RMAC_RTS_DS_ECC_DB_ERR			s2BIT(14)
+#define RMAC_RD_BUF_ECC_DB_ERR			s2BIT(15)
+#define RMAC_RTH_MAP_ECC_DB_ERR			s2BIT(16)
+#define RMAC_RTH_SPDM_ECC_DB_ERR		s2BIT(17)
+#define RMAC_RTS_VID_ECC_DB_ERR			s2BIT(18)
+#define RMAC_DA_SHADOW_ECC_DB_ERR		s2BIT(19)
+#define RMAC_LINK_STATE_CHANGE_INT		s2BIT(31)
+#define RMAC_RX_SM_ERR				s2BIT(39)
+#define RMAC_SINGLE_ECC_ERR			(s2BIT(5) | s2BIT(6) | s2BIT(7) |\
+						s2BIT(8)  | s2BIT(9) | s2BIT(10)|\
+						s2BIT(11))
+#define RMAC_DOUBLE_ECC_ERR			(s2BIT(13) | s2BIT(14) | s2BIT(15) |\
+						s2BIT(16)  | s2BIT(17) | s2BIT(18)|\
+						s2BIT(19))
 	u64 mac_rmac_err_mask;
 	u64 mac_rmac_err_alarm;
 
 	u8 unused14[0x100 - 0x40];
 
 	u64 mac_cfg;
-#define MAC_CFG_TMAC_ENABLE             BIT(0)
-#define MAC_CFG_RMAC_ENABLE             BIT(1)
-#define MAC_CFG_LAN_NOT_WAN             BIT(2)
-#define MAC_CFG_TMAC_LOOPBACK           BIT(3)
-#define MAC_CFG_TMAC_APPEND_PAD         BIT(4)
-#define MAC_CFG_RMAC_STRIP_FCS          BIT(5)
-#define MAC_CFG_RMAC_STRIP_PAD          BIT(6)
-#define MAC_CFG_RMAC_PROM_ENABLE        BIT(7)
-#define MAC_RMAC_DISCARD_PFRM           BIT(8)
-#define MAC_RMAC_BCAST_ENABLE           BIT(9)
-#define MAC_RMAC_ALL_ADDR_ENABLE        BIT(10)
+#define MAC_CFG_TMAC_ENABLE             s2BIT(0)
+#define MAC_CFG_RMAC_ENABLE             s2BIT(1)
+#define MAC_CFG_LAN_NOT_WAN             s2BIT(2)
+#define MAC_CFG_TMAC_LOOPBACK           s2BIT(3)
+#define MAC_CFG_TMAC_APPEND_PAD         s2BIT(4)
+#define MAC_CFG_RMAC_STRIP_FCS          s2BIT(5)
+#define MAC_CFG_RMAC_STRIP_PAD          s2BIT(6)
+#define MAC_CFG_RMAC_PROM_ENABLE        s2BIT(7)
+#define MAC_RMAC_DISCARD_PFRM           s2BIT(8)
+#define MAC_RMAC_BCAST_ENABLE           s2BIT(9)
+#define MAC_RMAC_ALL_ADDR_ENABLE        s2BIT(10)
 #define MAC_RMAC_INVLD_IPG_THR(val)     vBIT(val,16,8)
 
 	u64 tmac_avg_ipg;
@@ -621,33 +706,39 @@ struct XENA_dev_config {
 #define RMAC_MAX_PYLD_LEN_JUMBO_DEF vBIT(9600,2,14)
 
 	u64 rmac_err_cfg;
-#define RMAC_ERR_FCS                    BIT(0)
-#define RMAC_ERR_FCS_ACCEPT             BIT(1)
-#define RMAC_ERR_TOO_LONG               BIT(1)
-#define RMAC_ERR_TOO_LONG_ACCEPT        BIT(1)
-#define RMAC_ERR_RUNT                   BIT(2)
-#define RMAC_ERR_RUNT_ACCEPT            BIT(2)
-#define RMAC_ERR_LEN_MISMATCH           BIT(3)
-#define RMAC_ERR_LEN_MISMATCH_ACCEPT    BIT(3)
+#define RMAC_ERR_FCS                    s2BIT(0)
+#define RMAC_ERR_FCS_ACCEPT             s2BIT(1)
+#define RMAC_ERR_TOO_LONG               s2BIT(1)
+#define RMAC_ERR_TOO_LONG_ACCEPT        s2BIT(1)
+#define RMAC_ERR_RUNT                   s2BIT(2)
+#define RMAC_ERR_RUNT_ACCEPT            s2BIT(2)
+#define RMAC_ERR_LEN_MISMATCH           s2BIT(3)
+#define RMAC_ERR_LEN_MISMATCH_ACCEPT    s2BIT(3)
 
 	u64 rmac_cfg_key;
 #define RMAC_CFG_KEY(val)               vBIT(val,0,16)
 
-#define MAX_MAC_ADDRESSES           16
-#define MAX_MC_ADDRESSES            32	/* Multicast addresses */
-#define MAC_MAC_ADDR_START_OFFSET   0
-#define MAC_MC_ADDR_START_OFFSET    16
-#define MAC_MC_ALL_MC_ADDR_OFFSET   63	/* enables all multicast pkts */
+#define S2IO_MAC_ADDR_START_OFFSET	0
+
+#define S2IO_XENA_MAX_MC_ADDRESSES	64	/* multicast addresses */
+#define S2IO_HERC_MAX_MC_ADDRESSES	256
+
+#define S2IO_XENA_MAX_MAC_ADDRESSES	16
+#define S2IO_HERC_MAX_MAC_ADDRESSES	64
+
+#define S2IO_XENA_MC_ADDR_START_OFFSET	16
+#define S2IO_HERC_MC_ADDR_START_OFFSET	64
+
 	u64 rmac_addr_cmd_mem;
-#define RMAC_ADDR_CMD_MEM_WE                    BIT(7)
+#define RMAC_ADDR_CMD_MEM_WE                    s2BIT(7)
 #define RMAC_ADDR_CMD_MEM_RD                    0
-#define RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD        BIT(15)
-#define RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING  BIT(15)
+#define RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD        s2BIT(15)
+#define RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING  s2BIT(15)
 #define RMAC_ADDR_CMD_MEM_OFFSET(n)             vBIT(n,26,6)
 
 	u64 rmac_addr_data0_mem;
 #define RMAC_ADDR_DATA0_MEM_ADDR(n)    vBIT(n,0,48)
-#define RMAC_ADDR_DATA0_MEM_USER       BIT(48)
+#define RMAC_ADDR_DATA0_MEM_USER       s2BIT(48)
 
 	u64 rmac_addr_data1_mem;
 #define RMAC_ADDR_DATA1_MEM_MASK(n)    vBIT(n,0,48)
@@ -664,10 +755,10 @@ struct XENA_dev_config {
 	u64 tmac_ipg_cfg;
 
 	u64 rmac_pause_cfg;
-#define RMAC_PAUSE_GEN             BIT(0)
-#define RMAC_PAUSE_GEN_ENABLE      BIT(0)
-#define RMAC_PAUSE_RX              BIT(1)
-#define RMAC_PAUSE_RX_ENABLE       BIT(1)
+#define RMAC_PAUSE_GEN             s2BIT(0)
+#define RMAC_PAUSE_GEN_ENABLE      s2BIT(0)
+#define RMAC_PAUSE_RX              s2BIT(1)
+#define RMAC_PAUSE_RX_ENABLE       s2BIT(1)
 #define RMAC_PAUSE_HG_PTIME_DEF    vBIT(0xFFFF,16,16)
 #define RMAC_PAUSE_HG_PTIME(val)    vBIT(val,16,16)
 
@@ -698,29 +789,29 @@ struct XENA_dev_config {
 #define MAX_DIX_MAP                         4
 	u64 rts_dix_map_n[MAX_DIX_MAP];
 #define RTS_DIX_MAP_ETYPE(val)             vBIT(val,0,16)
-#define RTS_DIX_MAP_SCW(val)               BIT(val,21)
+#define RTS_DIX_MAP_SCW(val)               s2BIT(val,21)
 
 	u64 rts_q_alternates;
 	u64 rts_default_q;
 
 	u64 rts_ctrl;
-#define RTS_CTRL_IGNORE_SNAP_OUI           BIT(2)
-#define RTS_CTRL_IGNORE_LLC_CTRL           BIT(3)
+#define RTS_CTRL_IGNORE_SNAP_OUI           s2BIT(2)
+#define RTS_CTRL_IGNORE_LLC_CTRL           s2BIT(3)
 
 	u64 rts_pn_cam_ctrl;
-#define RTS_PN_CAM_CTRL_WE                 BIT(7)
-#define RTS_PN_CAM_CTRL_STROBE_NEW_CMD     BIT(15)
-#define RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED   BIT(15)
+#define RTS_PN_CAM_CTRL_WE                 s2BIT(7)
+#define RTS_PN_CAM_CTRL_STROBE_NEW_CMD     s2BIT(15)
+#define RTS_PN_CAM_CTRL_STROBE_BEING_EXECUTED   s2BIT(15)
 #define RTS_PN_CAM_CTRL_OFFSET(n)          vBIT(n,24,8)
 	u64 rts_pn_cam_data;
-#define RTS_PN_CAM_DATA_TCP_SELECT         BIT(7)
+#define RTS_PN_CAM_DATA_TCP_SELECT         s2BIT(7)
 #define RTS_PN_CAM_DATA_PORT(val)          vBIT(val,8,16)
 #define RTS_PN_CAM_DATA_SCW(val)           vBIT(val,24,8)
 
 	u64 rts_ds_mem_ctrl;
-#define RTS_DS_MEM_CTRL_WE                 BIT(7)
-#define RTS_DS_MEM_CTRL_STROBE_NEW_CMD     BIT(15)
-#define RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED   BIT(15)
+#define RTS_DS_MEM_CTRL_WE                 s2BIT(7)
+#define RTS_DS_MEM_CTRL_STROBE_NEW_CMD     s2BIT(15)
+#define RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED   s2BIT(15)
 #define RTS_DS_MEM_CTRL_OFFSET(n)          vBIT(n,26,6)
 	u64 rts_ds_mem_data;
 #define RTS_DS_MEM_DATA(n)                 vBIT(n,0,8)
@@ -734,22 +825,23 @@ struct XENA_dev_config {
 
 /* memory controller registers */
 	u64 mc_int_status;
-#define MC_INT_STATUS_MC_INT               BIT(0)
+#define MC_INT_STATUS_MC_INT               s2BIT(0)
 	u64 mc_int_mask;
-#define MC_INT_MASK_MC_INT                 BIT(0)
+#define MC_INT_MASK_MC_INT                 s2BIT(0)
 
 	u64 mc_err_reg;
-#define MC_ERR_REG_ECC_DB_ERR_L            BIT(14)
-#define MC_ERR_REG_ECC_DB_ERR_U            BIT(15)
-#define MC_ERR_REG_MIRI_ECC_DB_ERR_0       BIT(18)
-#define MC_ERR_REG_MIRI_ECC_DB_ERR_1       BIT(20)
-#define MC_ERR_REG_MIRI_CRI_ERR_0          BIT(22)
-#define MC_ERR_REG_MIRI_CRI_ERR_1          BIT(23)
-#define MC_ERR_REG_SM_ERR                  BIT(31)
-#define MC_ERR_REG_ECC_ALL_SNG		   (BIT(2) | BIT(3) | BIT(4) | BIT(5) |\
-					BIT(17) | BIT(19))
-#define MC_ERR_REG_ECC_ALL_DBL		   (BIT(10) | BIT(11) | BIT(12) |\
-					BIT(13) | BIT(18) | BIT(20))
+#define MC_ERR_REG_ECC_DB_ERR_L            s2BIT(14)
+#define MC_ERR_REG_ECC_DB_ERR_U            s2BIT(15)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_0       s2BIT(18)
+#define MC_ERR_REG_MIRI_ECC_DB_ERR_1       s2BIT(20)
+#define MC_ERR_REG_MIRI_CRI_ERR_0          s2BIT(22)
+#define MC_ERR_REG_MIRI_CRI_ERR_1          s2BIT(23)
+#define MC_ERR_REG_SM_ERR                  s2BIT(31)
+#define MC_ERR_REG_ECC_ALL_SNG		   (s2BIT(2) | s2BIT(3) | s2BIT(4) | s2BIT(5) |\
+					s2BIT(17) | s2BIT(19))
+#define MC_ERR_REG_ECC_ALL_DBL		   (s2BIT(10) | s2BIT(11) | s2BIT(12) |\
+					s2BIT(13) | s2BIT(18) | s2BIT(20))
+#define PLL_LOCK_N			s2BIT(39)
 	u64 mc_err_mask;
 	u64 mc_err_alarm;
 
@@ -767,8 +859,8 @@ struct XENA_dev_config {
 #define RX_QUEUE_CFG_Q7_SZ(n)              vBIT(n,56,8)
 
 	u64 mc_rldram_mrs;
-#define	MC_RLDRAM_QUEUE_SIZE_ENABLE			BIT(39)
-#define	MC_RLDRAM_MRS_ENABLE				BIT(47)
+#define	MC_RLDRAM_QUEUE_SIZE_ENABLE			s2BIT(39)
+#define	MC_RLDRAM_MRS_ENABLE				s2BIT(47)
 
 	u64 mc_rldram_interleave;
 
@@ -781,11 +873,11 @@ struct XENA_dev_config {
 	u64 mc_rldram_ref_per;
 	u8 unused20[0x220 - 0x208];
 	u64 mc_rldram_test_ctrl;
-#define MC_RLDRAM_TEST_MODE		BIT(47)
-#define MC_RLDRAM_TEST_WRITE	BIT(7)
-#define MC_RLDRAM_TEST_GO		BIT(15)
-#define MC_RLDRAM_TEST_DONE		BIT(23)
-#define MC_RLDRAM_TEST_PASS		BIT(31)
+#define MC_RLDRAM_TEST_MODE		s2BIT(47)
+#define MC_RLDRAM_TEST_WRITE	s2BIT(7)
+#define MC_RLDRAM_TEST_GO		s2BIT(15)
+#define MC_RLDRAM_TEST_DONE		s2BIT(23)
+#define MC_RLDRAM_TEST_PASS		s2BIT(31)
 
 	u8 unused21[0x240 - 0x228];
 	u64 mc_rldram_test_add;
@@ -798,7 +890,7 @@ struct XENA_dev_config {
 
 	u8 unused24_1[0x360 - 0x308];
 	u64 mc_rldram_ctrl;
-#define	MC_RLDRAM_ENABLE_ODT		BIT(7)
+#define	MC_RLDRAM_ENABLE_ODT		s2BIT(7)
 
 	u8 unused24_2[0x640 - 0x368];
 	u64 mc_rldram_ref_per_herc;
@@ -816,18 +908,24 @@ struct XENA_dev_config {
 	/* XGXS control registers */
 
 	u64 xgxs_int_status;
-#define XGXS_INT_STATUS_TXGXS              BIT(0)
-#define XGXS_INT_STATUS_RXGXS              BIT(1)
+#define XGXS_INT_STATUS_TXGXS              s2BIT(0)
+#define XGXS_INT_STATUS_RXGXS              s2BIT(1)
 	u64 xgxs_int_mask;
-#define XGXS_INT_MASK_TXGXS                BIT(0)
-#define XGXS_INT_MASK_RXGXS                BIT(1)
+#define XGXS_INT_MASK_TXGXS                s2BIT(0)
+#define XGXS_INT_MASK_RXGXS                s2BIT(1)
 
 	u64 xgxs_txgxs_err_reg;
-#define TXGXS_ECC_DB_ERR                   BIT(15)
+#define TXGXS_ECC_SG_ERR		s2BIT(7)
+#define TXGXS_ECC_DB_ERR		s2BIT(15)
+#define TXGXS_ESTORE_UFLOW		s2BIT(31)
+#define TXGXS_TX_SM_ERR			s2BIT(39)
+
 	u64 xgxs_txgxs_err_mask;
 	u64 xgxs_txgxs_err_alarm;
 
 	u64 xgxs_rxgxs_err_reg;
+#define RXGXS_ESTORE_OFLOW		s2BIT(7)
+#define RXGXS_RX_SM_ERR			s2BIT(39)
 	u64 xgxs_rxgxs_err_mask;
 	u64 xgxs_rxgxs_err_alarm;
 
@@ -846,10 +944,10 @@ struct XENA_dev_config {
 #define SPI_CONTROL_BYTECNT(cnt)	vBIT(cnt,29,3)
 #define SPI_CONTROL_CMD(cmd)		vBIT(cmd,32,8)
 #define SPI_CONTROL_ADDR(addr)		vBIT(addr,40,24)
-#define SPI_CONTROL_SEL1		BIT(4)
-#define SPI_CONTROL_REQ			BIT(7)
-#define SPI_CONTROL_NACK		BIT(5)
-#define SPI_CONTROL_DONE		BIT(6)
+#define SPI_CONTROL_SEL1		s2BIT(4)
+#define SPI_CONTROL_REQ			s2BIT(7)
+#define SPI_CONTROL_NACK		s2BIT(5)
+#define SPI_CONTROL_DONE		s2BIT(6)
 	u64 spi_data;
 #define SPI_DATA_WRITE(data,len)	vBIT(data,0,len)
 };
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index cba6289..cd89a70 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1,7 +1,7 @@
 /************************************************************************
  * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
  * Copyright(c) 2002-2007 Neterion Inc.
-
+ *
  * This software may be used and distributed according to the terms of
  * the GNU General Public License (GPL), incorporated herein by reference.
  * Drivers based on or derived from this code fall under the GPL and must
@@ -25,7 +25,7 @@
  * Christopher Hellwig	: Some more 2.6 specific issues in the driver.
  *
  * The module loadable parameters that are supported by the driver and a brief
- * explaination of all the variables.
+ * explanation of all the variables.
  *
  * rx_ring_num : This can be used to program the number of receive rings used
  * in the driver.
@@ -38,7 +38,7 @@
  * Tx descriptors that can be associated with each corresponding FIFO.
  * intr_type: This defines the type of interrupt. The values can be 0(INTA),
  *     2(MSI_X). Default value is '0(INTA)'
- * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
+ * lro_enable: Specifies whether to enable Large Receive Offload (LRO) or not.
  *     Possible values '1' for enable '0' for disable. Default is '0'
  * lro_max_pkts: This parameter defines maximum number of packets can be
  *     aggregated as a single large packet
@@ -52,6 +52,8 @@
  *                 and enable in non-promiscuous mode.
  ************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -61,6 +63,7 @@
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/mdio.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -72,36 +75,34 @@
 #include <linux/if_vlan.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 #include <net/tcp.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
 #include <asm/div64.h>
 #include <asm/irq.h>
 
 /* local include */
 #include "s2io.h"
 #include "s2io-regs.h"
+#include "s2io-compat.h"
 
-#define DRV_VERSION "2.0.25.1"
+#define DRV_VERSION "2.0.26.25"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
 static char s2io_driver_version[] = DRV_VERSION;
 
-static int rxd_size[2] = {32,48};
-static int rxd_count[2] = {127,85};
-
-/* RHEL5 compat */
-typedef __u16 __bitwise __sum16;
+static int rxd_size[2] = {32, 48};
+static int rxd_count[2] = {127, 85};
 
 static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
 {
 	int ret;
 
 	ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
-		(GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK));
+	       (GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK));
 
 	return ret;
 }
@@ -111,30 +112,21 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
  * problem, 600B, 600C, 600D, 640B, 640C and 640D.
  * macro below identifies these cards given the subsystem_id.
  */
-#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid) \
-	(dev_type == XFRAME_I_DEVICE) ?			\
-		((((subid >= 0x600B) && (subid <= 0x600D)) || \
-		 ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0
+#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid)		\
+	(dev_type == XFRAME_I_DEVICE) ?					\
+	((((subid >= 0x600B) && (subid <= 0x600D)) ||			\
+	  ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0
 
 #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
 				      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
-#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))
-#define PANIC	1
-#define LOW	2
-static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring)
-{
-	struct mac_info *mac_control;
 
-	mac_control = &sp->mac_control;
-	if (rxb_size <= rxd_count[sp->rxd_mode])
-		return PANIC;
-	else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
-		return  LOW;
-	return 0;
+static inline int is_s2io_card_up(const struct s2io_nic *sp)
+{
+	return test_bit(__S2IO_STATE_CARD_UP, &sp->state);
 }
 
 /* Ethtool related variables and Macros. */
-static char s2io_gstrings[][ETH_GSTRING_LEN] = {
+static const char s2io_gstrings[][ETH_GSTRING_LEN] = {
 	"Register test\t(offline)",
 	"Eeprom test\t(offline)",
 	"Link test\t(online)",
@@ -142,7 +134,7 @@ static char s2io_gstrings[][ETH_GSTRING_LEN] = {
 	"BIST Test\t(offline)"
 };
 
-static char ethtool_xena_stats_keys[][ETH_GSTRING_LEN] = {
+static const char ethtool_xena_stats_keys[][ETH_GSTRING_LEN] = {
 	{"tmac_frms"},
 	{"tmac_data_octets"},
 	{"tmac_drop_frms"},
@@ -239,7 +231,7 @@ static char ethtool_xena_stats_keys[][ETH_GSTRING_LEN] = {
 	{"rxf_wr_cnt"}
 };
 
-static char ethtool_enhanced_stats_keys[][ETH_GSTRING_LEN] = {
+static const char ethtool_enhanced_stats_keys[][ETH_GSTRING_LEN] = {
 	{"rmac_ttl_1519_4095_frms"},
 	{"rmac_ttl_4096_8191_frms"},
 	{"rmac_ttl_8192_max_frms"},
@@ -258,7 +250,7 @@ static char ethtool_enhanced_stats_keys[][ETH_GSTRING_LEN] = {
 	{"link_fault_cnt"}
 };
 
-static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
+static const char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
 	{"\n DRIVER STATISTICS"},
 	{"single_bit_ecc_errs"},
 	{"double_bit_ecc_errs"},
@@ -266,83 +258,127 @@ static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
 	{"serious_err_cnt"},
 	{"soft_reset_cnt"},
 	{"fifo_full_cnt"},
-	{"ring_full_cnt"},
-	("alarm_transceiver_temp_high"),
-	("alarm_transceiver_temp_low"),
-	("alarm_laser_bias_current_high"),
-	("alarm_laser_bias_current_low"),
-	("alarm_laser_output_power_high"),
-	("alarm_laser_output_power_low"),
-	("warn_transceiver_temp_high"),
-	("warn_transceiver_temp_low"),
-	("warn_laser_bias_current_high"),
-	("warn_laser_bias_current_low"),
-	("warn_laser_output_power_high"),
-	("warn_laser_output_power_low"),
-	("lro_aggregated_pkts"),
-	("lro_flush_both_count"),
-	("lro_out_of_sequence_pkts"),
-	("lro_flush_due_to_max_pkts"),
-	("lro_avg_aggr_pkts"),
-	("mem_alloc_fail_cnt"),
-	("pci_map_fail_cnt"),
-	("watchdog_timer_cnt"),
-	("mem_allocated"),
-	("mem_freed"),
-	("link_up_cnt"),
-	("link_down_cnt"),
-	("link_up_time"),
-	("link_down_time"),
-	("tx_tcode_buf_abort_cnt"),
-	("tx_tcode_desc_abort_cnt"),
-	("tx_tcode_parity_err_cnt"),
-	("tx_tcode_link_loss_cnt"),
-	("tx_tcode_list_proc_err_cnt"),
-	("rx_tcode_parity_err_cnt"),
-	("rx_tcode_abort_cnt"),
-	("rx_tcode_parity_abort_cnt"),
-	("rx_tcode_rda_fail_cnt"),
-	("rx_tcode_unkn_prot_cnt"),
-	("rx_tcode_fcs_err_cnt"),
-	("rx_tcode_buf_size_err_cnt"),
-	("rx_tcode_rxd_corrupt_cnt"),
-	("rx_tcode_unkn_err_cnt")
+	{"ring_0_full_cnt"},
+	{"ring_1_full_cnt"},
+	{"ring_2_full_cnt"},
+	{"ring_3_full_cnt"},
+	{"ring_4_full_cnt"},
+	{"ring_5_full_cnt"},
+	{"ring_6_full_cnt"},
+	{"ring_7_full_cnt"},
+	{"alarm_transceiver_temp_high"},
+	{"alarm_transceiver_temp_low"},
+	{"alarm_laser_bias_current_high"},
+	{"alarm_laser_bias_current_low"},
+	{"alarm_laser_output_power_high"},
+	{"alarm_laser_output_power_low"},
+	{"warn_transceiver_temp_high"},
+	{"warn_transceiver_temp_low"},
+	{"warn_laser_bias_current_high"},
+	{"warn_laser_bias_current_low"},
+	{"warn_laser_output_power_high"},
+	{"warn_laser_output_power_low"},
+	{"lro_aggregated_pkts"},
+	{"lro_flush_both_count"},
+	{"lro_out_of_sequence_pkts"},
+	{"lro_flush_due_to_max_pkts"},
+	{"lro_avg_aggr_pkts"},
+	{"mem_alloc_fail_cnt"},
+	{"pci_map_fail_cnt"},
+	{"watchdog_timer_cnt"},
+	{"mem_allocated"},
+	{"mem_freed"},
+	{"link_up_cnt"},
+	{"link_down_cnt"},
+	{"link_up_time"},
+	{"link_down_time"},
+	{"tx_tcode_buf_abort_cnt"},
+	{"tx_tcode_desc_abort_cnt"},
+	{"tx_tcode_parity_err_cnt"},
+	{"tx_tcode_link_loss_cnt"},
+	{"tx_tcode_list_proc_err_cnt"},
+	{"rx_tcode_parity_err_cnt"},
+	{"rx_tcode_abort_cnt"},
+	{"rx_tcode_parity_abort_cnt"},
+	{"rx_tcode_rda_fail_cnt"},
+	{"rx_tcode_unkn_prot_cnt"},
+	{"rx_tcode_fcs_err_cnt"},
+	{"rx_tcode_buf_size_err_cnt"},
+	{"rx_tcode_rxd_corrupt_cnt"},
+	{"rx_tcode_unkn_err_cnt"},
+	{"tda_err_cnt"},
+	{"pfc_err_cnt"},
+	{"pcc_err_cnt"},
+	{"tti_err_cnt"},
+	{"tpa_err_cnt"},
+	{"sm_err_cnt"},
+	{"lso_err_cnt"},
+	{"mac_tmac_err_cnt"},
+	{"mac_rmac_err_cnt"},
+	{"xgxs_txgxs_err_cnt"},
+	{"xgxs_rxgxs_err_cnt"},
+	{"rc_err_cnt"},
+	{"prc_pcix_err_cnt"},
+	{"rpa_err_cnt"},
+	{"rda_err_cnt"},
+	{"rti_err_cnt"},
+	{"mc_err_cnt"}
 };
 
-#define S2IO_XENA_STAT_LEN sizeof(ethtool_xena_stats_keys)/ ETH_GSTRING_LEN
-#define S2IO_ENHANCED_STAT_LEN sizeof(ethtool_enhanced_stats_keys)/ \
-					ETH_GSTRING_LEN
-#define S2IO_DRIVER_STAT_LEN sizeof(ethtool_driver_stats_keys)/ ETH_GSTRING_LEN
+#define S2IO_XENA_STAT_LEN     ARRAY_SIZE(ethtool_xena_stats_keys)
+#define S2IO_ENHANCED_STAT_LEN ARRAY_SIZE(ethtool_enhanced_stats_keys)
+#define S2IO_DRIVER_STAT_LEN   ARRAY_SIZE(ethtool_driver_stats_keys)
 
-#define XFRAME_I_STAT_LEN (S2IO_XENA_STAT_LEN + S2IO_DRIVER_STAT_LEN )
-#define XFRAME_II_STAT_LEN (XFRAME_I_STAT_LEN + S2IO_ENHANCED_STAT_LEN )
+#define XFRAME_I_STAT_LEN (S2IO_XENA_STAT_LEN + S2IO_DRIVER_STAT_LEN)
+#define XFRAME_II_STAT_LEN (XFRAME_I_STAT_LEN + S2IO_ENHANCED_STAT_LEN)
 
-#define XFRAME_I_STAT_STRINGS_LEN ( XFRAME_I_STAT_LEN * ETH_GSTRING_LEN )
-#define XFRAME_II_STAT_STRINGS_LEN ( XFRAME_II_STAT_LEN * ETH_GSTRING_LEN )
+#define XFRAME_I_STAT_STRINGS_LEN (XFRAME_I_STAT_LEN * ETH_GSTRING_LEN)
+#define XFRAME_II_STAT_STRINGS_LEN (XFRAME_II_STAT_LEN * ETH_GSTRING_LEN)
 
-#define S2IO_TEST_LEN	sizeof(s2io_gstrings) / ETH_GSTRING_LEN
-#define S2IO_STRINGS_LEN	S2IO_TEST_LEN * ETH_GSTRING_LEN
+#define S2IO_TEST_LEN  ARRAY_SIZE(s2io_gstrings)
+#define S2IO_STRINGS_LEN       (S2IO_TEST_LEN * ETH_GSTRING_LEN)
 
-#define S2IO_TIMER_CONF(timer, handle, arg, exp)		\
-			init_timer(&timer);			\
-			timer.function = handle;		\
-			timer.data = (unsigned long) arg;	\
-			mod_timer(&timer, (jiffies + exp))	\
+#define S2IO_TIMER_CONF(timer, handle, arg, exp)	\
+	init_timer(&timer);				\
+	timer.function = handle;			\
+	timer.data = (unsigned long)arg;		\
+	mod_timer(&timer, (jiffies + exp))		\
+
+/* copy mac addr to def_mac_addr array */
+static void do_s2io_copy_mac_addr(struct s2io_nic *sp, int offset, u64 mac_addr)
+{
+	sp->def_mac_addr[offset].mac_addr[5] = (u8) (mac_addr);
+	sp->def_mac_addr[offset].mac_addr[4] = (u8) (mac_addr >> 8);
+	sp->def_mac_addr[offset].mac_addr[3] = (u8) (mac_addr >> 16);
+	sp->def_mac_addr[offset].mac_addr[2] = (u8) (mac_addr >> 24);
+	sp->def_mac_addr[offset].mac_addr[1] = (u8) (mac_addr >> 32);
+	sp->def_mac_addr[offset].mac_addr[0] = (u8) (mac_addr >> 40);
+}
 
 /* Add the vlan */
 static void s2io_vlan_rx_register(struct net_device *dev,
-					struct vlan_group *grp)
+				  struct vlan_group *grp)
 {
-	struct s2io_nic *nic = dev->priv;
-	unsigned long flags;
+	int i;
+	struct s2io_nic *nic = netdev_priv(dev);
+	unsigned long flags[MAX_TX_FIFOS];
+	struct config_param *config = &nic->config;
+	struct mac_info *mac_control = &nic->mac_control;
+
+	for (i = 0; i < config->tx_fifo_num; i++) {
+		struct fifo_info *fifo = &mac_control->fifos[i];
+
+		spin_lock_irqsave(&fifo->tx_lock, flags[i]);
+	}
 
-	spin_lock_irqsave(&nic->tx_lock, flags);
 	nic->vlgrp = grp;
-	spin_unlock_irqrestore(&nic->tx_lock, flags);
-}
 
-/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
-int vlan_strip_flag;
+	for (i = config->tx_fifo_num - 1; i >= 0; i--) {
+		struct fifo_info *fifo = &mac_control->fifos[i];
+
+		spin_unlock_irqrestore(&fifo->tx_lock, flags[i]);
+	}
+}
 
 /*
  * Constants to be programmed into the Xena's registers, to configure
@@ -414,10 +450,13 @@ MODULE_VERSION(DRV_VERSION);
 
 
 /* Module Loadable parameters. */
-S2IO_PARM_INT(tx_fifo_num, 1);
+S2IO_PARM_INT(tx_fifo_num, FIFO_DEFAULT_NUM);
 S2IO_PARM_INT(rx_ring_num, 1);
-
-
+#if 0 /* don't do multiqueue TX in RHEL5 */
+S2IO_PARM_INT(multiq, 0);
+#else
+static int multiq = 0;
+#endif
 S2IO_PARM_INT(rx_ring_mode, 1);
 S2IO_PARM_INT(use_continuous_tx_intrs, 1);
 S2IO_PARM_INT(rmac_pause_time, 0x100);
@@ -426,14 +465,18 @@ 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(bimodal, 0); /* unused */
 S2IO_PARM_INT(l3l4hdr_size, 128);
+/* 0 is no steering, 1 is Priority steering, 2 is Default steering */
+S2IO_PARM_INT(tx_steering_type, TX_DEFAULT_STEERING);
 /* Frequency of Rx desc syncs expressed as power of 2 */
 S2IO_PARM_INT(rxsync_frequency, 3);
 /* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
 S2IO_PARM_INT(intr_type, 0);
 /* Large receive offload feature */
-S2IO_PARM_INT(lro, 0);
+static unsigned int lro_enable;
+module_param_named(lro, lro_enable, uint, 0);
+
 /* Max pkts to be aggregated by LRO at one time. If not specified,
  * aggregation happens until we hit max IP pkt size(64K)
  */
@@ -445,11 +488,11 @@ S2IO_PARM_INT(ufo, 0);
 S2IO_PARM_INT(vlan_tag_strip, NO_STRIP_IN_PROMISC);
 
 static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
-    {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
+{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};
+{[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
 static unsigned int rts_frm_len[MAX_RX_RINGS] =
-    {[0 ...(MAX_RX_RINGS - 1)] = 0 };
+{[0 ...(MAX_RX_RINGS - 1)] = 0 };
 
 module_param_array(tx_fifo_len, uint, NULL, 0);
 module_param_array(rx_ring_sz, uint, NULL, 0);
@@ -465,9 +508,9 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
 	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
 	 PCI_ANY_ID, PCI_ANY_ID},
 	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN,
-         PCI_ANY_ID, PCI_ANY_ID},
-        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
-         PCI_ANY_ID, PCI_ANY_ID},
+	 PCI_ANY_ID, PCI_ANY_ID},
+	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
+	 PCI_ANY_ID, PCI_ANY_ID},
 	{0,}
 };
 
@@ -480,16 +523,83 @@ static struct pci_error_handlers s2io_err_handler = {
 };
 
 static struct pci_driver s2io_driver = {
-      .name = "S2IO",
-      .id_table = s2io_tbl,
-      .probe = s2io_init_nic,
-      .remove = __devexit_p(s2io_rem_nic),
-      .err_handler = &s2io_err_handler,
+	.name = "S2IO",
+	.id_table = s2io_tbl,
+	.probe = s2io_init_nic,
+	.remove = __devexit_p(s2io_rem_nic),
+	.err_handler = &s2io_err_handler,
 };
 
 /* A simplifier macro used both by init and free shared_mem Fns(). */
 #define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each)
 
+/* netqueue manipulation helper functions */
+static inline void s2io_stop_all_tx_queue(struct s2io_nic *sp)
+{
+	if (!sp->config.multiq) {
+		int i;
+
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_STOP;
+	}
+	netif_tx_stop_all_queues(sp->dev);
+}
+
+static inline void s2io_stop_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+	if (!sp->config.multiq)
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_STOP;
+
+	netif_tx_stop_all_queues(sp->dev);
+}
+
+static inline void s2io_start_all_tx_queue(struct s2io_nic *sp)
+{
+	if (!sp->config.multiq) {
+		int i;
+
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+	}
+	netif_tx_start_all_queues(sp->dev);
+}
+
+static inline void s2io_start_tx_queue(struct s2io_nic *sp, int fifo_no)
+{
+	if (!sp->config.multiq)
+		sp->mac_control.fifos[fifo_no].queue_state =
+			FIFO_QUEUE_START;
+
+	netif_tx_start_all_queues(sp->dev);
+}
+
+static inline void s2io_wake_all_tx_queue(struct s2io_nic *sp)
+{
+	if (!sp->config.multiq) {
+		int i;
+
+		for (i = 0; i < sp->config.tx_fifo_num; i++)
+			sp->mac_control.fifos[i].queue_state = FIFO_QUEUE_START;
+	}
+	netif_tx_wake_all_queues(sp->dev);
+}
+
+static inline void s2io_wake_tx_queue(
+	struct fifo_info *fifo, int cnt, u8 multiq)
+{
+
+	if (multiq) {
+		if (cnt && __netif_subqueue_stopped(fifo->dev, fifo->fifo_no))
+			netif_wake_subqueue(fifo->dev, fifo->fifo_no);
+	} else if (cnt && (fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(fifo->dev)) {
+			fifo->queue_state = FIFO_QUEUE_START;
+			netif_wake_queue(fifo->dev);
+		}
+	}
+}
+
 /**
  * init_shared_mem - Allocation and Initialization of Memory
  * @nic: Device private variable.
@@ -509,54 +619,70 @@ static int init_shared_mem(struct s2io_nic *nic)
 	struct net_device *dev = nic->dev;
 	unsigned long tmp;
 	struct buffAdd *ba;
-
-	struct mac_info *mac_control;
-	struct config_param *config;
+	struct config_param *config = &nic->config;
+	struct mac_info *mac_control = &nic->mac_control;
 	unsigned long long mem_allocated = 0;
 
-	mac_control = &nic->mac_control;
-	config = &nic->config;
-
-
-	/* Allocation and initialization of TXDLs in FIOFs */
+	/* Allocation and initialization of TXDLs in FIFOs */
 	size = 0;
 	for (i = 0; i < config->tx_fifo_num; i++) {
-		size += config->tx_cfg[i].fifo_len;
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		size += tx_cfg->fifo_len;
 	}
 	if (size > MAX_AVAILABLE_TXDS) {
-		DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, ");
-		DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
+		DBG_PRINT(ERR_DBG,
+			  "Too many TxDs requested: %d, max supported: %d\n",
+			  size, MAX_AVAILABLE_TXDS);
 		return -EINVAL;
 	}
 
+	size = 0;
+	for (i = 0; i < config->tx_fifo_num; i++) {
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		size = tx_cfg->fifo_len;
+		/*
+		 * Legal values are from 2 to 8192
+		 */
+		if (size < 2) {
+			DBG_PRINT(ERR_DBG, "Fifo %d: Invalid length (%d) - "
+				  "Valid lengths are 2 through 8192\n",
+				  i, size);
+			return -EINVAL;
+		}
+	}
+
 	lst_size = (sizeof(struct TxD) * config->max_txds);
 	lst_per_page = PAGE_SIZE / lst_size;
 
 	for (i = 0; i < config->tx_fifo_num; i++) {
-		int fifo_len = config->tx_cfg[i].fifo_len;
+		struct fifo_info *fifo = &mac_control->fifos[i];
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+		int fifo_len = tx_cfg->fifo_len;
 		int list_holder_size = fifo_len * sizeof(struct list_info_hold);
-		mac_control->fifos[i].list_info = kmalloc(list_holder_size,
-							  GFP_KERNEL);
-		if (!mac_control->fifos[i].list_info) {
-			DBG_PRINT(INFO_DBG,
-				  "Malloc failed for list_info\n");
+
+		fifo->list_info = kzalloc(list_holder_size, GFP_KERNEL);
+		if (!fifo->list_info) {
+			DBG_PRINT(INFO_DBG, "Malloc failed for list_info\n");
 			return -ENOMEM;
 		}
 		mem_allocated += list_holder_size;
-		memset(mac_control->fifos[i].list_info, 0, list_holder_size);
 	}
 	for (i = 0; i < config->tx_fifo_num; i++) {
 		int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
 						lst_per_page);
-		mac_control->fifos[i].tx_curr_put_info.offset = 0;
-		mac_control->fifos[i].tx_curr_put_info.fifo_len =
-		    config->tx_cfg[i].fifo_len - 1;
-		mac_control->fifos[i].tx_curr_get_info.offset = 0;
-		mac_control->fifos[i].tx_curr_get_info.fifo_len =
-		    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 + 2;
+		struct fifo_info *fifo = &mac_control->fifos[i];
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		fifo->tx_curr_put_info.offset = 0;
+		fifo->tx_curr_put_info.fifo_len = tx_cfg->fifo_len - 1;
+		fifo->tx_curr_get_info.offset = 0;
+		fifo->tx_curr_get_info.fifo_len = tx_cfg->fifo_len - 1;
+		fifo->fifo_no = i;
+		fifo->nic = nic;
+		fifo->max_txds = MAX_SKB_FRAGS + 2;
+		fifo->dev = dev;
 
 		for (j = 0; j < page_num; j++) {
 			int k = 0;
@@ -566,8 +692,7 @@ static int init_shared_mem(struct s2io_nic *nic)
 						     PAGE_SIZE, &tmp_p);
 			if (!tmp_v) {
 				DBG_PRINT(INFO_DBG,
-					  "pci_alloc_consistent ");
-				DBG_PRINT(INFO_DBG, "failed for TxDL\n");
+					  "pci_alloc_consistent failed for TxDL\n");
 				return -ENOMEM;
 			}
 			/* If we got a zero DMA address(can happen on
@@ -578,54 +703,58 @@ static int init_shared_mem(struct s2io_nic *nic)
 			if (!tmp_p) {
 				mac_control->zerodma_virt_addr = tmp_v;
 				DBG_PRINT(INIT_DBG,
-				"%s: Zero DMA address for TxDL. ", dev->name);
-				DBG_PRINT(INIT_DBG,
-				"Virtual address %p\n", tmp_v);
+					  "%s: Zero DMA address for TxDL. "
+					  "Virtual address %p\n",
+					  dev->name, tmp_v);
 				tmp_v = pci_alloc_consistent(nic->pdev,
-						     PAGE_SIZE, &tmp_p);
+							     PAGE_SIZE, &tmp_p);
 				if (!tmp_v) {
 					DBG_PRINT(INFO_DBG,
-					  "pci_alloc_consistent ");
-					DBG_PRINT(INFO_DBG, "failed for TxDL\n");
+						  "pci_alloc_consistent failed for TxDL\n");
 					return -ENOMEM;
 				}
 				mem_allocated += PAGE_SIZE;
 			}
 			while (k < lst_per_page) {
 				int l = (j * lst_per_page) + k;
-				if (l == config->tx_cfg[i].fifo_len)
+				if (l == tx_cfg->fifo_len)
 					break;
-				mac_control->fifos[i].list_info[l].list_virt_addr =
-				    tmp_v + (k * lst_size);
-				mac_control->fifos[i].list_info[l].list_phy_addr =
-				    tmp_p + (k * lst_size);
+				fifo->list_info[l].list_virt_addr =
+					tmp_v + (k * lst_size);
+				fifo->list_info[l].list_phy_addr =
+					tmp_p + (k * lst_size);
 				k++;
 			}
 		}
 	}
 
-	nic->ufo_in_band_v = kcalloc(size, sizeof(u64), GFP_KERNEL);
-	if (!nic->ufo_in_band_v)
-		return -ENOMEM;
-	 mem_allocated += (size * sizeof(u64));
+	for (i = 0; i < config->tx_fifo_num; i++) {
+		struct fifo_info *fifo = &mac_control->fifos[i];
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		size = tx_cfg->fifo_len;
+		fifo->ufo_in_band_v = kcalloc(size, sizeof(u64), GFP_KERNEL);
+		if (!fifo->ufo_in_band_v)
+			return -ENOMEM;
+		mem_allocated += (size * sizeof(u64));
+	}
 
 	/* 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 %
-		    (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);
-			DBG_PRINT(ERR_DBG, "RxDs per Block");
+		struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+		struct ring_info *ring = &mac_control->rings[i];
+
+		if (rx_cfg->num_rxd % (rxd_count[nic->rxd_mode] + 1)) {
+			DBG_PRINT(ERR_DBG, "%s: Ring%d RxD count is not a "
+				  "multiple of RxDs per Block\n",
+				  dev->name, i);
 			return FAILURE;
 		}
-		size += 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 += rx_cfg->num_rxd;
+		ring->block_count = rx_cfg->num_rxd /
+			(rxd_count[nic->rxd_mode] + 1);
+		ring->pkt_cnt = rx_cfg->num_rxd - ring->block_count;
 	}
 	if (nic->rxd_mode == RXD_MODE_1)
 		size = (size * (sizeof(struct RxD1)));
@@ -633,26 +762,27 @@ static int init_shared_mem(struct s2io_nic *nic)
 		size = (size * (sizeof(struct RxD3)));
 
 	for (i = 0; i < config->rx_ring_num; i++) {
-		mac_control->rings[i].rx_curr_get_info.block_index = 0;
-		mac_control->rings[i].rx_curr_get_info.offset = 0;
-		mac_control->rings[i].rx_curr_get_info.ring_len =
-		    config->rx_cfg[i].num_rxd - 1;
-		mac_control->rings[i].rx_curr_put_info.block_index = 0;
-		mac_control->rings[i].rx_curr_put_info.offset = 0;
-		mac_control->rings[i].rx_curr_put_info.ring_len =
-		    config->rx_cfg[i].num_rxd - 1;
-		mac_control->rings[i].nic = nic;
-		mac_control->rings[i].ring_no = i;
-
-		blk_cnt = config->rx_cfg[i].num_rxd /
-				(rxd_count[nic->rxd_mode] + 1);
+		struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+		struct ring_info *ring = &mac_control->rings[i];
+
+		ring->rx_curr_get_info.block_index = 0;
+		ring->rx_curr_get_info.offset = 0;
+		ring->rx_curr_get_info.ring_len = rx_cfg->num_rxd - 1;
+		ring->rx_curr_put_info.block_index = 0;
+		ring->rx_curr_put_info.offset = 0;
+		ring->rx_curr_put_info.ring_len = rx_cfg->num_rxd - 1;
+		ring->nic = nic;
+		ring->ring_no = i;
+		ring->lro = lro_enable;
+
+		blk_cnt = rx_cfg->num_rxd / (rxd_count[nic->rxd_mode] + 1);
 		/*  Allocating all the Rx blocks */
 		for (j = 0; j < blk_cnt; j++) {
 			struct rx_block_info *rx_blocks;
 			int l;
 
-			rx_blocks = &mac_control->rings[i].rx_blocks[j];
-			size = SIZE_OF_BLOCK; //size is always page size
+			rx_blocks = &ring->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) {
@@ -667,16 +797,16 @@ static int init_shared_mem(struct s2io_nic *nic)
 			}
 			mem_allocated += size;
 			memset(tmp_v_addr, 0, size);
+
+			size = sizeof(struct rxd_info) *
+				rxd_count[nic->rxd_mode];
 			rx_blocks->block_virt_addr = tmp_v_addr;
 			rx_blocks->block_dma_addr = tmp_p_addr;
-			rx_blocks->rxds = kmalloc(sizeof(struct rxd_info)*
-						  rxd_count[nic->rxd_mode],
-						  GFP_KERNEL);
+			rx_blocks->rxds = kmalloc(size,  GFP_KERNEL);
 			if (!rx_blocks->rxds)
 				return -ENOMEM;
-			mem_allocated += 
-			(sizeof(struct rxd_info)* rxd_count[nic->rxd_mode]);
-			for (l=0; l<rxd_count[nic->rxd_mode];l++) {
+			mem_allocated += size;
+			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);
@@ -687,22 +817,17 @@ static int init_shared_mem(struct s2io_nic *nic)
 		}
 		/* Interlinking all Rx Blocks */
 		for (j = 0; j < blk_cnt; j++) {
-			tmp_v_addr =
-				mac_control->rings[i].rx_blocks[j].block_virt_addr;
-			tmp_v_addr_next =
-				mac_control->rings[i].rx_blocks[(j + 1) %
-					      blk_cnt].block_virt_addr;
-			tmp_p_addr =
-				mac_control->rings[i].rx_blocks[j].block_dma_addr;
-			tmp_p_addr_next =
-				mac_control->rings[i].rx_blocks[(j + 1) %
-					      blk_cnt].block_dma_addr;
-
-			pre_rxd_blk = (struct RxD_block *) tmp_v_addr;
+			int next = (j + 1) % blk_cnt;
+			tmp_v_addr = ring->rx_blocks[j].block_virt_addr;
+			tmp_v_addr_next = ring->rx_blocks[next].block_virt_addr;
+			tmp_p_addr = ring->rx_blocks[j].block_dma_addr;
+			tmp_p_addr_next = ring->rx_blocks[next].block_dma_addr;
+
+			pre_rxd_blk = (struct RxD_block *)tmp_v_addr;
 			pre_rxd_blk->reserved_2_pNext_RxD_block =
-			    (unsigned long) tmp_v_addr_next;
+				(unsigned long)tmp_v_addr_next;
 			pre_rxd_blk->pNext_RxD_Blk_physical =
-			    (u64) tmp_p_addr_next;
+				(u64)tmp_p_addr_next;
 		}
 	}
 	if (nic->rxd_mode == RXD_MODE_3B) {
@@ -711,48 +836,46 @@ static int init_shared_mem(struct s2io_nic *nic)
 		 * 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(struct buffAdd *) * blk_cnt),
-				     GFP_KERNEL);
-			if (!mac_control->rings[i].ba)
+			struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+			struct ring_info *ring = &mac_control->rings[i];
+
+			blk_cnt = rx_cfg->num_rxd /
+				(rxd_count[nic->rxd_mode] + 1);
+			size = sizeof(struct buffAdd *) * blk_cnt;
+			ring->ba = kmalloc(size, GFP_KERNEL);
+			if (!ring->ba)
 				return -ENOMEM;
-			mem_allocated +=(sizeof(struct buffAdd *) * blk_cnt);
+			mem_allocated += size;
 			for (j = 0; j < blk_cnt; j++) {
 				int k = 0;
-				mac_control->rings[i].ba[j] =
-					kmalloc((sizeof(struct buffAdd) *
-						(rxd_count[nic->rxd_mode] + 1)),
-						GFP_KERNEL);
-				if (!mac_control->rings[i].ba[j])
+
+				size = sizeof(struct buffAdd) *
+					(rxd_count[nic->rxd_mode] + 1);
+				ring->ba[j] = kmalloc(size, GFP_KERNEL);
+				if (!ring->ba[j])
 					return -ENOMEM;
-				mem_allocated += (sizeof(struct buffAdd) *  \
-					(rxd_count[nic->rxd_mode] + 1));
+				mem_allocated += size;
 				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);
+					ba = &ring->ba[j][k];
+					size = BUF0_LEN + ALIGN_SIZE;
+					ba->ba_0_org = kmalloc(size, GFP_KERNEL);
 					if (!ba->ba_0_org)
 						return -ENOMEM;
-					mem_allocated += 
-						(BUF0_LEN + ALIGN_SIZE);
+					mem_allocated += size;
 					tmp = (unsigned long)ba->ba_0_org;
 					tmp += ALIGN_SIZE;
-					tmp &= ~((unsigned long) ALIGN_SIZE);
-					ba->ba_0 = (void *) tmp;
+					tmp &= ~((unsigned long)ALIGN_SIZE);
+					ba->ba_0 = (void *)tmp;
 
-					ba->ba_1_org = (void *) kmalloc
-					    (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
+					size = BUF1_LEN + ALIGN_SIZE;
+					ba->ba_1_org = kmalloc(size, GFP_KERNEL);
 					if (!ba->ba_1_org)
 						return -ENOMEM;
-					mem_allocated 
-						+= (BUF1_LEN + ALIGN_SIZE);
-					tmp = (unsigned long) ba->ba_1_org;
+					mem_allocated += size;
+					tmp = (unsigned long)ba->ba_1_org;
 					tmp += ALIGN_SIZE;
-					tmp &= ~((unsigned long) ALIGN_SIZE);
-					ba->ba_1 = (void *) tmp;
+					tmp &= ~((unsigned long)ALIGN_SIZE);
+					ba->ba_1 = (void *)tmp;
 					k++;
 				}
 			}
@@ -761,8 +884,9 @@ static int init_shared_mem(struct s2io_nic *nic)
 
 	/* Allocation and initialization of Statistics block */
 	size = sizeof(struct stat_block);
-	mac_control->stats_mem = pci_alloc_consistent
-	    (nic->pdev, size, &mac_control->stats_mem_phy);
+	mac_control->stats_mem =
+		pci_alloc_consistent(nic->pdev, size,
+				     &mac_control->stats_mem_phy);
 
 	if (!mac_control->stats_mem) {
 		/*
@@ -776,10 +900,10 @@ static int init_shared_mem(struct s2io_nic *nic)
 	mac_control->stats_mem_sz = size;
 
 	tmp_v_addr = mac_control->stats_mem;
-	mac_control->stats_info = (struct stat_block *) tmp_v_addr;
+	mac_control->stats_info = (struct stat_block *)tmp_v_addr;
 	memset(tmp_v_addr, 0, size);
-	DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name,
-		  (unsigned long long) tmp_p_addr);
+	DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n", dev->name,
+		  (unsigned long long)tmp_p_addr);
 	mac_control->stats_info->sw_stat.mem_allocated += mem_allocated;
 	return SUCCESS;
 }
@@ -794,46 +918,48 @@ static int init_shared_mem(struct s2io_nic *nic)
 static void free_shared_mem(struct s2io_nic *nic)
 {
 	int i, j, blk_cnt, size;
-	u32 ufo_size = 0;
 	void *tmp_v_addr;
 	dma_addr_t tmp_p_addr;
-	struct mac_info *mac_control;
-	struct config_param *config;
 	int lst_size, lst_per_page;
 	struct net_device *dev;
 	int page_num = 0;
+	struct config_param *config;
+	struct mac_info *mac_control;
+	struct stat_block *stats;
+	struct swStat *swstats;
 
 	if (!nic)
 		return;
 
 	dev = nic->dev;
 
-	mac_control = &nic->mac_control;
 	config = &nic->config;
+	mac_control = &nic->mac_control;
+	stats = mac_control->stats_info;
+	swstats = &stats->sw_stat;
 
-	lst_size = (sizeof(struct TxD) * config->max_txds);
+	lst_size = sizeof(struct TxD) * config->max_txds;
 	lst_per_page = PAGE_SIZE / lst_size;
 
 	for (i = 0; i < config->tx_fifo_num; i++) {
-		ufo_size += config->tx_cfg[i].fifo_len;
-		page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
-							lst_per_page);
+		struct fifo_info *fifo = &mac_control->fifos[i];
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		page_num = TXD_MEM_PAGE_CNT(tx_cfg->fifo_len, lst_per_page);
 		for (j = 0; j < page_num; j++) {
 			int mem_blks = (j * lst_per_page);
-			if (!mac_control->fifos[i].list_info)
+			struct list_info_hold *fli;
+
+			if (!fifo->list_info)
 				return;
-			if (!mac_control->fifos[i].list_info[mem_blks].
-				 list_virt_addr)
+
+			fli = &fifo->list_info[mem_blks];
+			if (!fli->list_virt_addr)
 				break;
 			pci_free_consistent(nic->pdev, PAGE_SIZE,
-					    mac_control->fifos[i].
-					    list_info[mem_blks].
-					    list_virt_addr,
-					    mac_control->fifos[i].
-					    list_info[mem_blks].
-					    list_phy_addr);
-			nic->mac_control.stats_info->sw_stat.mem_freed 
-						+= PAGE_SIZE;
+					    fli->list_virt_addr,
+					    fli->list_phy_addr);
+			swstats->mem_freed += PAGE_SIZE;
 		}
 		/* If we got a zero DMA address during allocation,
 		 * free the page now
@@ -843,79 +969,84 @@ static void free_shared_mem(struct s2io_nic *nic)
 					    mac_control->zerodma_virt_addr,
 					    (dma_addr_t)0);
 			DBG_PRINT(INIT_DBG,
-			  	"%s: Freeing TxDL with zero DMA addr. ",
-				dev->name);
-			DBG_PRINT(INIT_DBG, "Virtual address %p\n",
-				mac_control->zerodma_virt_addr);
-			nic->mac_control.stats_info->sw_stat.mem_freed 
-						+= PAGE_SIZE;
+				  "%s: Freeing TxDL with zero DMA address. "
+				  "Virtual address %p\n",
+				  dev->name, mac_control->zerodma_virt_addr);
+			swstats->mem_freed += PAGE_SIZE;
 		}
-		kfree(mac_control->fifos[i].list_info);
-		nic->mac_control.stats_info->sw_stat.mem_freed += 
-		(nic->config.tx_cfg[i].fifo_len *sizeof(struct list_info_hold));
+		kfree(fifo->list_info);
+		swstats->mem_freed += tx_cfg->fifo_len *
+			sizeof(struct list_info_hold);
 	}
 
 	size = SIZE_OF_BLOCK;
 	for (i = 0; i < config->rx_ring_num; i++) {
-		blk_cnt = mac_control->rings[i].block_count;
+		struct ring_info *ring = &mac_control->rings[i];
+
+		blk_cnt = ring->block_count;
 		for (j = 0; j < blk_cnt; j++) {
-			tmp_v_addr = mac_control->rings[i].rx_blocks[j].
-				block_virt_addr;
-			tmp_p_addr = mac_control->rings[i].rx_blocks[j].
-				block_dma_addr;
+			tmp_v_addr = ring->rx_blocks[j].block_virt_addr;
+			tmp_p_addr = ring->rx_blocks[j].block_dma_addr;
 			if (tmp_v_addr == NULL)
 				break;
 			pci_free_consistent(nic->pdev, size,
 					    tmp_v_addr, tmp_p_addr);
-			nic->mac_control.stats_info->sw_stat.mem_freed += size;
-			kfree(mac_control->rings[i].rx_blocks[j].rxds);
-			nic->mac_control.stats_info->sw_stat.mem_freed += 
-			( sizeof(struct rxd_info)* rxd_count[nic->rxd_mode]);
+			swstats->mem_freed += size;
+			kfree(ring->rx_blocks[j].rxds);
+			swstats->mem_freed += sizeof(struct rxd_info) *
+				rxd_count[nic->rxd_mode];
 		}
 	}
 
 	if (nic->rxd_mode == RXD_MODE_3B) {
 		/* 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);
+			struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+			struct ring_info *ring = &mac_control->rings[i];
+
+			blk_cnt = rx_cfg->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])
+				if (!ring->ba[j])
 					continue;
 				while (k != rxd_count[nic->rxd_mode]) {
-					struct buffAdd *ba =
-						&mac_control->rings[i].ba[j][k];
+					struct buffAdd *ba = &ring->ba[j][k];
 					kfree(ba->ba_0_org);
-					nic->mac_control.stats_info->sw_stat.\
-					mem_freed += (BUF0_LEN + ALIGN_SIZE);
+					swstats->mem_freed +=
+						BUF0_LEN + ALIGN_SIZE;
 					kfree(ba->ba_1_org);
-					nic->mac_control.stats_info->sw_stat.\
-					mem_freed += (BUF1_LEN + ALIGN_SIZE);
+					swstats->mem_freed +=
+						BUF1_LEN + ALIGN_SIZE;
 					k++;
 				}
-				kfree(mac_control->rings[i].ba[j]);
-				nic->mac_control.stats_info->sw_stat.mem_freed 				+= (sizeof(struct buffAdd) * 
-				(rxd_count[nic->rxd_mode] + 1));
+				kfree(ring->ba[j]);
+				swstats->mem_freed += sizeof(struct buffAdd) *
+					(rxd_count[nic->rxd_mode] + 1);
 			}
-			kfree(mac_control->rings[i].ba);
-			nic->mac_control.stats_info->sw_stat.mem_freed += 
-			(sizeof(struct buffAdd *) * blk_cnt);
+			kfree(ring->ba);
+			swstats->mem_freed += sizeof(struct buffAdd *) *
+				blk_cnt;
+		}
+	}
+
+	for (i = 0; i < nic->config.tx_fifo_num; i++) {
+		struct fifo_info *fifo = &mac_control->fifos[i];
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		if (fifo->ufo_in_band_v) {
+			swstats->mem_freed += tx_cfg->fifo_len *
+				sizeof(u64);
+			kfree(fifo->ufo_in_band_v);
 		}
 	}
 
 	if (mac_control->stats_mem) {
+		swstats->mem_freed += mac_control->stats_mem_sz;
 		pci_free_consistent(nic->pdev,
 				    mac_control->stats_mem_sz,
 				    mac_control->stats_mem,
 				    mac_control->stats_mem_phy);
-		nic->mac_control.stats_info->sw_stat.mem_freed += 
-			mac_control->stats_mem_sz;
-	}
-	if (nic->ufo_in_band_v) {
-		kfree(nic->ufo_in_band_v);
-		nic->mac_control.stats_info->sw_stat.mem_freed 
-			+= (ufo_size * sizeof(u64));
 	}
 }
 
@@ -932,7 +1063,7 @@ static int s2io_verify_pci_mode(struct s2io_nic *nic)
 	val64 = readq(&bar0->pci_mode);
 	mode = (u8)GET_PCI_MODE(val64);
 
-	if ( val64 & PCI_MODE_UNKNOWN_MODE)
+	if (val64 & PCI_MODE_UNKNOWN_MODE)
 		return -1;      /* Unknown PCI mode */
 	return mode;
 }
@@ -944,9 +1075,10 @@ static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
 	struct pci_dev *tdev = NULL;
 	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)
+			if (tdev->bus == s2io_pdev->bus->parent) {
 				pci_dev_put(tdev);
 				return 1;
+			}
 		}
 	}
 	return 0;
@@ -962,62 +1094,138 @@ static int s2io_print_pci_mode(struct s2io_nic *nic)
 	register u64 val64 = 0;
 	int	mode;
 	struct config_param *config = &nic->config;
+	const char *pcimode;
 
 	val64 = readq(&bar0->pci_mode);
 	mode = (u8)GET_PCI_MODE(val64);
 
-	if ( val64 & PCI_MODE_UNKNOWN_MODE)
+	if (val64 & PCI_MODE_UNKNOWN_MODE)
 		return -1;	/* Unknown PCI mode */
 
 	config->bus_speed = bus_speed[mode];
 
 	if (s2io_on_nec_bridge(nic->pdev)) {
 		DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n",
-							nic->dev->name);
+			  nic->dev->name);
 		return mode;
 	}
 
-	if (val64 & PCI_MODE_32_BITS) {
-		DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
-	} else {
-		DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name);
+	switch (mode) {
+	case PCI_MODE_PCI_33:
+		pcimode = "33MHz PCI bus";
+		break;
+	case PCI_MODE_PCI_66:
+		pcimode = "66MHz PCI bus";
+		break;
+	case PCI_MODE_PCIX_M1_66:
+		pcimode = "66MHz PCIX(M1) bus";
+		break;
+	case PCI_MODE_PCIX_M1_100:
+		pcimode = "100MHz PCIX(M1) bus";
+		break;
+	case PCI_MODE_PCIX_M1_133:
+		pcimode = "133MHz PCIX(M1) bus";
+		break;
+	case PCI_MODE_PCIX_M2_66:
+		pcimode = "133MHz PCIX(M2) bus";
+		break;
+	case PCI_MODE_PCIX_M2_100:
+		pcimode = "200MHz PCIX(M2) bus";
+		break;
+	case PCI_MODE_PCIX_M2_133:
+		pcimode = "266MHz PCIX(M2) bus";
+		break;
+	default:
+		pcimode = "unsupported bus!";
+		mode = -1;
 	}
 
-	switch(mode) {
-		case PCI_MODE_PCI_33:
-			DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
-			break;
-		case PCI_MODE_PCI_66:
-			DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
-			break;
-		case PCI_MODE_PCIX_M1_66:
-			DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
-			break;
-		case PCI_MODE_PCIX_M1_100:
-			DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
-			break;
-		case PCI_MODE_PCIX_M1_133:
-			DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
-			break;
-		case PCI_MODE_PCIX_M2_66:
-			DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
-			break;
-		case PCI_MODE_PCIX_M2_100:
-			DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
-			break;
-		case PCI_MODE_PCIX_M2_133:
-			DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
-			break;
-		default:
-			return -1;	/* Unsupported bus speed */
-	}
+	DBG_PRINT(ERR_DBG, "%s: Device is on %d bit %s\n",
+		  nic->dev->name, val64 & PCI_MODE_32_BITS ? 32 : 64, pcimode);
 
 	return mode;
 }
 
 /**
+ *  init_tti - Initialization transmit traffic interrupt scheme
+ *  @nic: device private variable
+ *  @link: link status (UP/DOWN) used to enable/disable continuous
+ *  transmit interrupts
+ *  Description: The function configures transmit traffic interrupts
+ *  Return Value:  SUCCESS on success and
+ *  '-1' on failure
+ */
+
+static int init_tti(struct s2io_nic *nic, int link)
+{
+	struct XENA_dev_config __iomem *bar0 = nic->bar0;
+	register u64 val64 = 0;
+	int i;
+	struct config_param *config = &nic->config;
+
+	for (i = 0; i < config->tx_fifo_num; i++) {
+		/*
+		 * TTI Initialization. Default Tx timer gets us about
+		 * 250 interrupts per sec. Continuous interrupts are enabled
+		 * by default.
+		 */
+		if (nic->device_type == XFRAME_II_DEVICE) {
+			int count = (nic->config.bus_speed * 125)/2;
+			val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
+		} else
+			val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
+
+		val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
+			TTI_DATA1_MEM_TX_URNG_B(0x10) |
+			TTI_DATA1_MEM_TX_URNG_C(0x30) |
+			TTI_DATA1_MEM_TX_TIMER_AC_EN;
+		if (i == 0)
+			if (use_continuous_tx_intrs && (link == LINK_UP))
+				val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
+		writeq(val64, &bar0->tti_data1_mem);
+
+		if (nic->config.intr_type == MSI_X) {
+			val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
+				TTI_DATA2_MEM_TX_UFC_B(0x100) |
+				TTI_DATA2_MEM_TX_UFC_C(0x200) |
+				TTI_DATA2_MEM_TX_UFC_D(0x300);
+		} else {
+			if ((nic->config.tx_steering_type ==
+			     TX_DEFAULT_STEERING) &&
+			    (config->tx_fifo_num > 1) &&
+			    (i >= nic->udp_fifo_idx) &&
+			    (i < (nic->udp_fifo_idx +
+				  nic->total_udp_fifos)))
+				val64 = TTI_DATA2_MEM_TX_UFC_A(0x50) |
+					TTI_DATA2_MEM_TX_UFC_B(0x80) |
+					TTI_DATA2_MEM_TX_UFC_C(0x100) |
+					TTI_DATA2_MEM_TX_UFC_D(0x120);
+			else
+				val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
+					TTI_DATA2_MEM_TX_UFC_B(0x20) |
+					TTI_DATA2_MEM_TX_UFC_C(0x40) |
+					TTI_DATA2_MEM_TX_UFC_D(0x80);
+		}
+
+		writeq(val64, &bar0->tti_data2_mem);
+
+		val64 = TTI_CMD_MEM_WE |
+			TTI_CMD_MEM_STROBE_NEW_CMD |
+			TTI_CMD_MEM_OFFSET(i);
+		writeq(val64, &bar0->tti_command_mem);
+
+		if (wait_for_cmd_complete(&bar0->tti_command_mem,
+					  TTI_CMD_MEM_STROBE_NEW_CMD,
+					  S2IO_BIT_RESET) != SUCCESS)
+			return FAILURE;
+	}
+
+	return SUCCESS;
+}
+
+/**
  *  init_nic - Initialization of hardware
- *  @nic: device peivate variable
+ *  @nic: device private variable
  *  Description: The function sequentially configures every block
  *  of the H/W from their reset values.
  *  Return Value:  SUCCESS on success and
@@ -1032,19 +1240,16 @@ static int init_nic(struct s2io_nic *nic)
 	void __iomem *add;
 	u32 time;
 	int i, j;
-	struct mac_info *mac_control;
-	struct config_param *config;
 	int dtx_cnt = 0;
 	unsigned long long mem_share;
 	int mem_size;
-
-	mac_control = &nic->mac_control;
-	config = &nic->config;
+	struct config_param *config = &nic->config;
+	struct mac_info *mac_control = &nic->mac_control;
 
 	/* to set the swapper controle on the card */
-	if(s2io_set_swapper(nic)) {
-		DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
-		return -1;
+	if (s2io_set_swapper(nic)) {
+		DBG_PRINT(ERR_DBG, "ERROR: Setting Swapper failed\n");
+		return -EIO;
 	}
 
 	/*
@@ -1063,12 +1268,26 @@ static int init_nic(struct s2io_nic *nic)
 	msleep(500);
 	val64 = readq(&bar0->sw_reset);
 
+	/* Ensure that it's safe to access registers by checking
+	 * RIC_RUNNING bit is reset. Check is valid only for XframeII.
+	 */
+	if (nic->device_type == XFRAME_II_DEVICE) {
+		for (i = 0; i < 50; i++) {
+			val64 = readq(&bar0->adapter_status);
+			if (!(val64 & ADAPTER_STATUS_RIC_RUNNING))
+				break;
+			msleep(10);
+		}
+		if (i == 50)
+			return -ENODEV;
+	}
+
 	/*  Enable Receiving broadcasts */
 	add = &bar0->mac_cfg;
 	val64 = readq(&bar0->mac_cfg);
 	val64 |= MAC_RMAC_BCAST_ENABLE;
 	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
-	writel((u32) val64, add);
+	writel((u32)val64, add);
 	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
 	writel((u32) (val64 >> 32), (add + 4));
 
@@ -1105,12 +1324,11 @@ static int init_nic(struct s2io_nic *nic)
 	writeq(val64, &bar0->tx_fifo_partition_2);
 	writeq(val64, &bar0->tx_fifo_partition_3);
 
-
 	for (i = 0, j = 0; i < config->tx_fifo_num; i++) {
-		val64 |=
-		    vBIT(config->tx_cfg[i].fifo_len - 1, ((i * 32) + 19),
-			 13) | vBIT(config->tx_cfg[i].fifo_priority,
-				    ((i * 32) + 5), 3);
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		val64 |= vBIT(tx_cfg->fifo_len - 1, ((j * 32) + 19), 13) |
+			vBIT(tx_cfg->fifo_priority, ((j * 32) + 5), 3);
 
 		if (i == (config->tx_fifo_num - 1)) {
 			if (i % 2 == 0)
@@ -1121,17 +1339,25 @@ static int init_nic(struct s2io_nic *nic)
 		case 1:
 			writeq(val64, &bar0->tx_fifo_partition_0);
 			val64 = 0;
+			j = 0;
 			break;
 		case 3:
 			writeq(val64, &bar0->tx_fifo_partition_1);
 			val64 = 0;
+			j = 0;
 			break;
 		case 5:
 			writeq(val64, &bar0->tx_fifo_partition_2);
 			val64 = 0;
+			j = 0;
 			break;
 		case 7:
 			writeq(val64, &bar0->tx_fifo_partition_3);
+			val64 = 0;
+			j = 0;
+			break;
+		default:
+			j++;
 			break;
 		}
 	}
@@ -1140,29 +1366,30 @@ static int init_nic(struct s2io_nic *nic)
 	 * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
 	 * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
 	 */
-	if ((nic->device_type == XFRAME_I_DEVICE) &&
-		(get_xena_rev_id(nic->pdev) < 4))
+	if ((nic->device_type == XFRAME_I_DEVICE) && (nic->pdev->revision < 4))
 		writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
 
 	val64 = readq(&bar0->tx_fifo_partition_0);
 	DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",
-		  &bar0->tx_fifo_partition_0, (unsigned long long) val64);
+		  &bar0->tx_fifo_partition_0, (unsigned long long)val64);
 
 	/*
 	 * Initialization of Tx_PA_CONFIG register to ignore packet
 	 * integrity checking.
 	 */
 	val64 = readq(&bar0->tx_pa_cfg);
-	val64 |= TX_PA_CFG_IGNORE_FRM_ERR | TX_PA_CFG_IGNORE_SNAP_OUI |
-	    TX_PA_CFG_IGNORE_LLC_CTRL | TX_PA_CFG_IGNORE_L2_ERR;
+	val64 |= TX_PA_CFG_IGNORE_FRM_ERR |
+		TX_PA_CFG_IGNORE_SNAP_OUI |
+		TX_PA_CFG_IGNORE_LLC_CTRL |
+		TX_PA_CFG_IGNORE_L2_ERR;
 	writeq(val64, &bar0->tx_pa_cfg);
 
 	/* Rx DMA intialization. */
 	val64 = 0;
 	for (i = 0; i < config->rx_ring_num; i++) {
-		val64 |=
-		    vBIT(config->rx_cfg[i].ring_priority, (5 + (i * 8)),
-			 3);
+		struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+
+		val64 |= vBIT(rx_cfg->ring_priority, (5 + (i * 8)), 3);
 	}
 	writeq(val64, &bar0->rx_queue_priority);
 
@@ -1217,11 +1444,11 @@ static int init_nic(struct s2io_nic *nic)
 
 	/*
 	 * Filling Tx round robin registers
-	 * as per the number of FIFOs
+	 * as per the number of FIFOs for equal scheduling priority
 	 */
 	switch (config->tx_fifo_num) {
 	case 1:
-		val64 = 0x0000000000000000ULL;
+		val64 = 0x0;
 		writeq(val64, &bar0->tx_w_round_robin_0);
 		writeq(val64, &bar0->tx_w_round_robin_1);
 		writeq(val64, &bar0->tx_w_round_robin_2);
@@ -1229,87 +1456,78 @@ static int init_nic(struct s2io_nic *nic)
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	case 2:
-		val64 = 0x0000010000010000ULL;
+		val64 = 0x0001000100010001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_0);
-		val64 = 0x0100000100000100ULL;
 		writeq(val64, &bar0->tx_w_round_robin_1);
-		val64 = 0x0001000001000001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_2);
-		val64 = 0x0000010000010000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_3);
-		val64 = 0x0100000000000000ULL;
+		val64 = 0x0001000100000000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	case 3:
-		val64 = 0x0001000102000001ULL;
+		val64 = 0x0001020001020001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_0);
-		val64 = 0x0001020000010001ULL;
+		val64 = 0x0200010200010200ULL;
 		writeq(val64, &bar0->tx_w_round_robin_1);
-		val64 = 0x0200000100010200ULL;
+		val64 = 0x0102000102000102ULL;
 		writeq(val64, &bar0->tx_w_round_robin_2);
-		val64 = 0x0001000102000001ULL;
+		val64 = 0x0001020001020001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_3);
-		val64 = 0x0001020000000000ULL;
+		val64 = 0x0200010200000000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	case 4:
-		val64 = 0x0001020300010200ULL;
+		val64 = 0x0001020300010203ULL;
 		writeq(val64, &bar0->tx_w_round_robin_0);
-		val64 = 0x0100000102030001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_1);
-		val64 = 0x0200010000010203ULL;
 		writeq(val64, &bar0->tx_w_round_robin_2);
-		val64 = 0x0001020001000001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_3);
-		val64 = 0x0203000100000000ULL;
+		val64 = 0x0001020300000000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	case 5:
-		val64 = 0x0001000203000102ULL;
+		val64 = 0x0001020304000102ULL;
 		writeq(val64, &bar0->tx_w_round_robin_0);
-		val64 = 0x0001020001030004ULL;
+		val64 = 0x0304000102030400ULL;
 		writeq(val64, &bar0->tx_w_round_robin_1);
-		val64 = 0x0001000203000102ULL;
+		val64 = 0x0102030400010203ULL;
 		writeq(val64, &bar0->tx_w_round_robin_2);
-		val64 = 0x0001020001030004ULL;
+		val64 = 0x0400010203040001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_3);
-		val64 = 0x0001000000000000ULL;
+		val64 = 0x0203040000000000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	case 6:
-		val64 = 0x0001020304000102ULL;
+		val64 = 0x0001020304050001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_0);
-		val64 = 0x0304050001020001ULL;
+		val64 = 0x0203040500010203ULL;
 		writeq(val64, &bar0->tx_w_round_robin_1);
-		val64 = 0x0203000100000102ULL;
+		val64 = 0x0405000102030405ULL;
 		writeq(val64, &bar0->tx_w_round_robin_2);
-		val64 = 0x0304000102030405ULL;
+		val64 = 0x0001020304050001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_3);
-		val64 = 0x0001000200000000ULL;
+		val64 = 0x0203040500000000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	case 7:
-		val64 = 0x0001020001020300ULL;
+		val64 = 0x0001020304050600ULL;
 		writeq(val64, &bar0->tx_w_round_robin_0);
-		val64 = 0x0102030400010203ULL;
+		val64 = 0x0102030405060001ULL;
 		writeq(val64, &bar0->tx_w_round_robin_1);
-		val64 = 0x0405060001020001ULL;
+		val64 = 0x0203040506000102ULL;
 		writeq(val64, &bar0->tx_w_round_robin_2);
-		val64 = 0x0304050000010200ULL;
+		val64 = 0x0304050600010203ULL;
 		writeq(val64, &bar0->tx_w_round_robin_3);
-		val64 = 0x0102030000000000ULL;
+		val64 = 0x0405060000000000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	case 8:
-		val64 = 0x0001020300040105ULL;
+		val64 = 0x0001020304050607ULL;
 		writeq(val64, &bar0->tx_w_round_robin_0);
-		val64 = 0x0200030106000204ULL;
 		writeq(val64, &bar0->tx_w_round_robin_1);
-		val64 = 0x0103000502010007ULL;
 		writeq(val64, &bar0->tx_w_round_robin_2);
-		val64 = 0x0304010002060500ULL;
 		writeq(val64, &bar0->tx_w_round_robin_3);
-		val64 = 0x0103020400000000ULL;
+		val64 = 0x0001020300000000ULL;
 		writeq(val64, &bar0->tx_w_round_robin_4);
 		break;
 	}
@@ -1320,113 +1538,112 @@ static int init_nic(struct s2io_nic *nic)
 	writeq(val64, &bar0->tx_fifo_partition_0);
 
 	/* Filling the Rx round robin registers as per the
-	 * number of Rings and steering based on QoS.
-         */
+	 * number of Rings and steering based on QoS with
+	 * equal priority.
+	 */
 	switch (config->rx_ring_num) {
 	case 1:
+		val64 = 0x0;
+		writeq(val64, &bar0->rx_w_round_robin_0);
+		writeq(val64, &bar0->rx_w_round_robin_1);
+		writeq(val64, &bar0->rx_w_round_robin_2);
+		writeq(val64, &bar0->rx_w_round_robin_3);
+		writeq(val64, &bar0->rx_w_round_robin_4);
+
 		val64 = 0x8080808080808080ULL;
 		writeq(val64, &bar0->rts_qos_steering);
 		break;
 	case 2:
-		val64 = 0x0000010000010000ULL;
+		val64 = 0x0001000100010001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_0);
-		val64 = 0x0100000100000100ULL;
 		writeq(val64, &bar0->rx_w_round_robin_1);
-		val64 = 0x0001000001000001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_2);
-		val64 = 0x0000010000010000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_3);
-		val64 = 0x0100000000000000ULL;
+		val64 = 0x0001000100000000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_4);
 
 		val64 = 0x8080808040404040ULL;
 		writeq(val64, &bar0->rts_qos_steering);
 		break;
 	case 3:
-		val64 = 0x0001000102000001ULL;
+		val64 = 0x0001020001020001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_0);
-		val64 = 0x0001020000010001ULL;
+		val64 = 0x0200010200010200ULL;
 		writeq(val64, &bar0->rx_w_round_robin_1);
-		val64 = 0x0200000100010200ULL;
+		val64 = 0x0102000102000102ULL;
 		writeq(val64, &bar0->rx_w_round_robin_2);
-		val64 = 0x0001000102000001ULL;
+		val64 = 0x0001020001020001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_3);
-		val64 = 0x0001020000000000ULL;
+		val64 = 0x0200010200000000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_4);
 
 		val64 = 0x8080804040402020ULL;
 		writeq(val64, &bar0->rts_qos_steering);
 		break;
 	case 4:
-		val64 = 0x0001020300010200ULL;
+		val64 = 0x0001020300010203ULL;
 		writeq(val64, &bar0->rx_w_round_robin_0);
-		val64 = 0x0100000102030001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_1);
-		val64 = 0x0200010000010203ULL;
 		writeq(val64, &bar0->rx_w_round_robin_2);
-		val64 = 0x0001020001000001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_3);
-		val64 = 0x0203000100000000ULL;
+		val64 = 0x0001020300000000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_4);
 
 		val64 = 0x8080404020201010ULL;
 		writeq(val64, &bar0->rts_qos_steering);
 		break;
 	case 5:
-		val64 = 0x0001000203000102ULL;
+		val64 = 0x0001020304000102ULL;
 		writeq(val64, &bar0->rx_w_round_robin_0);
-		val64 = 0x0001020001030004ULL;
+		val64 = 0x0304000102030400ULL;
 		writeq(val64, &bar0->rx_w_round_robin_1);
-		val64 = 0x0001000203000102ULL;
+		val64 = 0x0102030400010203ULL;
 		writeq(val64, &bar0->rx_w_round_robin_2);
-		val64 = 0x0001020001030004ULL;
+		val64 = 0x0400010203040001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_3);
-		val64 = 0x0001000000000000ULL;
+		val64 = 0x0203040000000000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_4);
 
 		val64 = 0x8080404020201008ULL;
 		writeq(val64, &bar0->rts_qos_steering);
 		break;
 	case 6:
-		val64 = 0x0001020304000102ULL;
+		val64 = 0x0001020304050001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_0);
-		val64 = 0x0304050001020001ULL;
+		val64 = 0x0203040500010203ULL;
 		writeq(val64, &bar0->rx_w_round_robin_1);
-		val64 = 0x0203000100000102ULL;
+		val64 = 0x0405000102030405ULL;
 		writeq(val64, &bar0->rx_w_round_robin_2);
-		val64 = 0x0304000102030405ULL;
+		val64 = 0x0001020304050001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_3);
-		val64 = 0x0001000200000000ULL;
+		val64 = 0x0203040500000000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_4);
 
 		val64 = 0x8080404020100804ULL;
 		writeq(val64, &bar0->rts_qos_steering);
 		break;
 	case 7:
-		val64 = 0x0001020001020300ULL;
+		val64 = 0x0001020304050600ULL;
 		writeq(val64, &bar0->rx_w_round_robin_0);
-		val64 = 0x0102030400010203ULL;
+		val64 = 0x0102030405060001ULL;
 		writeq(val64, &bar0->rx_w_round_robin_1);
-		val64 = 0x0405060001020001ULL;
+		val64 = 0x0203040506000102ULL;
 		writeq(val64, &bar0->rx_w_round_robin_2);
-		val64 = 0x0304050000010200ULL;
+		val64 = 0x0304050600010203ULL;
 		writeq(val64, &bar0->rx_w_round_robin_3);
-		val64 = 0x0102030000000000ULL;
+		val64 = 0x0405060000000000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_4);
 
 		val64 = 0x8080402010080402ULL;
 		writeq(val64, &bar0->rts_qos_steering);
 		break;
 	case 8:
-		val64 = 0x0001020300040105ULL;
+		val64 = 0x0001020304050607ULL;
 		writeq(val64, &bar0->rx_w_round_robin_0);
-		val64 = 0x0200030106000204ULL;
 		writeq(val64, &bar0->rx_w_round_robin_1);
-		val64 = 0x0103000502010007ULL;
 		writeq(val64, &bar0->rx_w_round_robin_2);
-		val64 = 0x0304010002060500ULL;
 		writeq(val64, &bar0->rx_w_round_robin_3);
-		val64 = 0x0103020400000000ULL;
+		val64 = 0x0001020300000000ULL;
 		writeq(val64, &bar0->rx_w_round_robin_4);
 
 		val64 = 0x8040201008040201ULL;
@@ -1456,17 +1673,17 @@ static int init_nic(struct s2io_nic *nic)
 		 */
 		if (rts_frm_len[i] != 0) {
 			writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]),
-				&bar0->rts_frm_len_n[i]);
+			       &bar0->rts_frm_len_n[i]);
 		}
 	}
-	
+
 	/* Disable differentiated services steering logic */
 	for (i = 0; i < 64; i++) {
 		if (rts_ds_steer(nic, i, 0) == FAILURE) {
-			DBG_PRINT(ERR_DBG, "%s: failed rts ds steering",
-				dev->name);
-			DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i);
-			return FAILURE;
+			DBG_PRINT(ERR_DBG,
+				  "%s: rts_ds_steer failed on codepoint %d\n",
+				  dev->name, i);
+			return -ENODEV;
 		}
 	}
 
@@ -1483,146 +1700,71 @@ static int init_nic(struct s2io_nic *nic)
 	 * bandwidth utilization.
 	 */
 	val64 = MAC_TX_LINK_UTIL_VAL(tmac_util_period) |
-	    MAC_RX_LINK_UTIL_VAL(rmac_util_period);
+		MAC_RX_LINK_UTIL_VAL(rmac_util_period);
 	writeq(val64, &bar0->mac_link_util);
 
-
 	/*
 	 * Initializing the Transmit and Receive Traffic Interrupt
 	 * Scheme.
 	 */
-	/*
-	 * TTI Initialization. Default Tx timer gets us about
-	 * 250 interrupts per sec. Continuous interrupts are enabled
-	 * by default.
-	 */
-	if (nic->device_type == XFRAME_II_DEVICE) {
-		int count = (nic->config.bus_speed * 125)/2;
-		val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
-	} else {
-
-		val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
-	}
-	val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
-	    TTI_DATA1_MEM_TX_URNG_B(0x10) |
-	    TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
-		if (use_continuous_tx_intrs)
-			val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
-	writeq(val64, &bar0->tti_data1_mem);
-
-	val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
-	    TTI_DATA2_MEM_TX_UFC_B(0x20) |
-	    TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
-	writeq(val64, &bar0->tti_data2_mem);
-
-	val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
-	writeq(val64, &bar0->tti_command_mem);
-
-	/*
-	 * Once the operation completes, the Strobe bit of the command
-	 * register will be reset. We poll for this particular condition
-	 * We wait for a maximum of 500ms for the operation to complete,
-	 * if it's not complete by then we return error.
-	 */
-	time = 0;
-	while (TRUE) {
-		val64 = readq(&bar0->tti_command_mem);
-		if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
-			break;
-		}
-		if (time > 10) {
-			DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n",
-				  dev->name);
-			return -1;
-		}
-		msleep(50);
-		time++;
-	}
 
-	if (nic->config.bimodal) {
-		int k = 0;
-		for (k = 0; k < config->rx_ring_num; k++) {
-			val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
-			val64 |= TTI_CMD_MEM_OFFSET(0x38+k);
-			writeq(val64, &bar0->tti_command_mem);
+	/* Initialize TTI */
+	if (SUCCESS != init_tti(nic, nic->last_link_state))
+		return -ENODEV;
 
+	/* RTI Initialization */
+	if (nic->device_type == XFRAME_II_DEVICE) {
 		/*
-		 * Once the operation completes, the Strobe bit of the command
-		 * register will be reset. We poll for this particular condition
-		 * We wait for a maximum of 500ms for the operation to complete,
-		 * if it's not complete by then we return error.
-		*/
-			time = 0;
-			while (TRUE) {
-				val64 = readq(&bar0->tti_command_mem);
-				if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
-					break;
-				}
-				if (time > 10) {
-					DBG_PRINT(ERR_DBG,
-						"%s: TTI init Failed\n",
-					dev->name);
-					return -1;
-				}
-				time++;
-				msleep(50);
-			}
-		}
-	} else {
-
-		/* RTI Initialization */
-		if (nic->device_type == XFRAME_II_DEVICE) {
-			/*
-			 * Programmed to generate Apprx 500 Intrs per
-			 * second
-			 */
-			int count = (nic->config.bus_speed * 125)/4;
-			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
-		} else {
-			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
-		}
-		val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
-		    RTI_DATA1_MEM_RX_URNG_B(0x10) |
-		    RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;
-
-		writeq(val64, &bar0->rti_data1_mem);
+		 * Programmed to generate Apprx 500 Intrs per
+		 * second
+		 */
+		int count = (nic->config.bus_speed * 125)/4;
+		val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
+	} else
+		val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
+	val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
+		RTI_DATA1_MEM_RX_URNG_B(0x10) |
+		RTI_DATA1_MEM_RX_URNG_C(0x30) |
+		RTI_DATA1_MEM_RX_TIMER_AC_EN;
+
+	writeq(val64, &bar0->rti_data1_mem);
+
+	val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
+		RTI_DATA2_MEM_RX_UFC_B(0x2) ;
+	if (nic->config.intr_type == MSI_X)
+		val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) |
+			  RTI_DATA2_MEM_RX_UFC_D(0x40));
+	else
+		val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) |
+			  RTI_DATA2_MEM_RX_UFC_D(0x80));
+	writeq(val64, &bar0->rti_data2_mem);
 
-		val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
-		    RTI_DATA2_MEM_RX_UFC_B(0x2) ;
-		if (nic->intr_type == MSI_X)
-		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
-				RTI_DATA2_MEM_RX_UFC_D(0x40));
-		else
-		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
-				RTI_DATA2_MEM_RX_UFC_D(0x80));
-		writeq(val64, &bar0->rti_data2_mem);
+	for (i = 0; i < config->rx_ring_num; i++) {
+		val64 = RTI_CMD_MEM_WE |
+			RTI_CMD_MEM_STROBE_NEW_CMD |
+			RTI_CMD_MEM_OFFSET(i);
+		writeq(val64, &bar0->rti_command_mem);
 
-		for (i = 0; i < config->rx_ring_num; i++) {
-			val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
-					| RTI_CMD_MEM_OFFSET(i);
-			writeq(val64, &bar0->rti_command_mem);
+		/*
+		 * Once the operation completes, the Strobe bit of the
+		 * command register will be reset. We poll for this
+		 * particular condition. We wait for a maximum of 500ms
+		 * for the operation to complete, if it's not complete
+		 * by then we return error.
+		 */
+		time = 0;
+		while (true) {
+			val64 = readq(&bar0->rti_command_mem);
+			if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD))
+				break;
 
-			/*
-			 * Once the operation completes, the Strobe bit of the
-			 * command register will be reset. We poll for this
-			 * particular condition. We wait for a maximum of 500ms
-			 * for the operation to complete, if it's not complete
-			 * by then we return error.
-			 */
-			time = 0;
-			while (TRUE) {
-				val64 = readq(&bar0->rti_command_mem);
-				if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
-					break;
-				}
-				if (time > 10) {
-					DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
-						  dev->name);
-					return -1;
-				}
-				time++;
-				msleep(50);
+			if (time > 10) {
+				DBG_PRINT(ERR_DBG, "%s: RTI init failed\n",
+					  dev->name);
+				return -ENODEV;
 			}
+			time++;
+			msleep(50);
 		}
 	}
 
@@ -1673,19 +1815,17 @@ static int init_nic(struct s2io_nic *nic)
 	 */
 	val64 = 0;
 	for (i = 0; i < 4; i++) {
-		val64 |=
-		    (((u64) 0xFF00 | nic->mac_control.
-		      mc_pause_threshold_q0q3)
-		     << (i * 2 * 8));
+		val64 |= (((u64)0xFF00 |
+			   nic->mac_control.mc_pause_threshold_q0q3)
+			  << (i * 2 * 8));
 	}
 	writeq(val64, &bar0->mc_pause_thresh_q0q3);
 
 	val64 = 0;
 	for (i = 0; i < 4; i++) {
-		val64 |=
-		    (((u64) 0xFF00 | nic->mac_control.
-		      mc_pause_threshold_q4q7)
-		     << (i * 2 * 8));
+		val64 |= (((u64)0xFF00 |
+			   nic->mac_control.mc_pause_threshold_q4q7)
+			  << (i * 2 * 8));
 	}
 	writeq(val64, &bar0->mc_pause_thresh_q4q7);
 
@@ -1712,7 +1852,7 @@ static int init_nic(struct s2io_nic *nic)
 			MISC_LINK_STABILITY_PRD(3);
 		writeq(val64, &bar0->misc_control);
 		val64 = readq(&bar0->pic_control2);
-		val64 &= ~(BIT(13)|BIT(14)|BIT(15));
+		val64 &= ~(s2BIT(13)|s2BIT(14)|s2BIT(15));
 		writeq(val64, &bar0->pic_control2);
 	}
 	if (strstr(nic->product_name, "CX4")) {
@@ -1727,8 +1867,6 @@ static int init_nic(struct s2io_nic *nic)
 
 static int s2io_link_fault_indication(struct s2io_nic *nic)
 {
-	if (nic->intr_type != INTA)
-		return MAC_RMAC_ERR_TIMER;
 	if (nic->device_type == XFRAME_II_DEVICE)
 		return LINK_UP_DOWN_INTERRUPT;
 	else
@@ -1736,6 +1874,155 @@ static int s2io_link_fault_indication(struct s2io_nic *nic)
 }
 
 /**
+ *  do_s2io_write_bits -  update alarm bits in alarm register
+ *  @value: alarm bits
+ *  @flag: interrupt status
+ *  @addr: address value
+ *  Description: update alarm bits in alarm register
+ *  Return Value:
+ *  NONE.
+ */
+static void do_s2io_write_bits(u64 value, int flag, void __iomem *addr)
+{
+	u64 temp64;
+
+	temp64 = readq(addr);
+
+	if (flag == ENABLE_INTRS)
+		temp64 &= ~((u64)value);
+	else
+		temp64 |= ((u64)value);
+	writeq(temp64, addr);
+}
+
+static void en_dis_err_alarms(struct s2io_nic *nic, u16 mask, int flag)
+{
+	struct XENA_dev_config __iomem *bar0 = nic->bar0;
+	register u64 gen_int_mask = 0;
+	u64 interruptible;
+
+	writeq(DISABLE_ALL_INTRS, &bar0->general_int_mask);
+	if (mask & TX_DMA_INTR) {
+		gen_int_mask |= TXDMA_INT_M;
+
+		do_s2io_write_bits(TXDMA_TDA_INT | TXDMA_PFC_INT |
+				   TXDMA_PCC_INT | TXDMA_TTI_INT |
+				   TXDMA_LSO_INT | TXDMA_TPA_INT |
+				   TXDMA_SM_INT, flag, &bar0->txdma_int_mask);
+
+		do_s2io_write_bits(PFC_ECC_DB_ERR | PFC_SM_ERR_ALARM |
+				   PFC_MISC_0_ERR | PFC_MISC_1_ERR |
+				   PFC_PCIX_ERR | PFC_ECC_SG_ERR, flag,
+				   &bar0->pfc_err_mask);
+
+		do_s2io_write_bits(TDA_Fn_ECC_DB_ERR | TDA_SM0_ERR_ALARM |
+				   TDA_SM1_ERR_ALARM | TDA_Fn_ECC_SG_ERR |
+				   TDA_PCIX_ERR, flag, &bar0->tda_err_mask);
+
+		do_s2io_write_bits(PCC_FB_ECC_DB_ERR | PCC_TXB_ECC_DB_ERR |
+				   PCC_SM_ERR_ALARM | PCC_WR_ERR_ALARM |
+				   PCC_N_SERR | PCC_6_COF_OV_ERR |
+				   PCC_7_COF_OV_ERR | PCC_6_LSO_OV_ERR |
+				   PCC_7_LSO_OV_ERR | PCC_FB_ECC_SG_ERR |
+				   PCC_TXB_ECC_SG_ERR,
+				   flag, &bar0->pcc_err_mask);
+
+		do_s2io_write_bits(TTI_SM_ERR_ALARM | TTI_ECC_SG_ERR |
+				   TTI_ECC_DB_ERR, flag, &bar0->tti_err_mask);
+
+		do_s2io_write_bits(LSO6_ABORT | LSO7_ABORT |
+				   LSO6_SM_ERR_ALARM | LSO7_SM_ERR_ALARM |
+				   LSO6_SEND_OFLOW | LSO7_SEND_OFLOW,
+				   flag, &bar0->lso_err_mask);
+
+		do_s2io_write_bits(TPA_SM_ERR_ALARM | TPA_TX_FRM_DROP,
+				   flag, &bar0->tpa_err_mask);
+
+		do_s2io_write_bits(SM_SM_ERR_ALARM, flag, &bar0->sm_err_mask);
+	}
+
+	if (mask & TX_MAC_INTR) {
+		gen_int_mask |= TXMAC_INT_M;
+		do_s2io_write_bits(MAC_INT_STATUS_TMAC_INT, flag,
+				   &bar0->mac_int_mask);
+		do_s2io_write_bits(TMAC_TX_BUF_OVRN | TMAC_TX_SM_ERR |
+				   TMAC_ECC_SG_ERR | TMAC_ECC_DB_ERR |
+				   TMAC_DESC_ECC_SG_ERR | TMAC_DESC_ECC_DB_ERR,
+				   flag, &bar0->mac_tmac_err_mask);
+	}
+
+	if (mask & TX_XGXS_INTR) {
+		gen_int_mask |= TXXGXS_INT_M;
+		do_s2io_write_bits(XGXS_INT_STATUS_TXGXS, flag,
+				   &bar0->xgxs_int_mask);
+		do_s2io_write_bits(TXGXS_ESTORE_UFLOW | TXGXS_TX_SM_ERR |
+				   TXGXS_ECC_SG_ERR | TXGXS_ECC_DB_ERR,
+				   flag, &bar0->xgxs_txgxs_err_mask);
+	}
+
+	if (mask & RX_DMA_INTR) {
+		gen_int_mask |= RXDMA_INT_M;
+		do_s2io_write_bits(RXDMA_INT_RC_INT_M | RXDMA_INT_RPA_INT_M |
+				   RXDMA_INT_RDA_INT_M | RXDMA_INT_RTI_INT_M,
+				   flag, &bar0->rxdma_int_mask);
+		do_s2io_write_bits(RC_PRCn_ECC_DB_ERR | RC_FTC_ECC_DB_ERR |
+				   RC_PRCn_SM_ERR_ALARM | RC_FTC_SM_ERR_ALARM |
+				   RC_PRCn_ECC_SG_ERR | RC_FTC_ECC_SG_ERR |
+				   RC_RDA_FAIL_WR_Rn, flag, &bar0->rc_err_mask);
+		do_s2io_write_bits(PRC_PCI_AB_RD_Rn | PRC_PCI_AB_WR_Rn |
+				   PRC_PCI_AB_F_WR_Rn | PRC_PCI_DP_RD_Rn |
+				   PRC_PCI_DP_WR_Rn | PRC_PCI_DP_F_WR_Rn, flag,
+				   &bar0->prc_pcix_err_mask);
+		do_s2io_write_bits(RPA_SM_ERR_ALARM | RPA_CREDIT_ERR |
+				   RPA_ECC_SG_ERR | RPA_ECC_DB_ERR, flag,
+				   &bar0->rpa_err_mask);
+		do_s2io_write_bits(RDA_RXDn_ECC_DB_ERR | RDA_FRM_ECC_DB_N_AERR |
+				   RDA_SM1_ERR_ALARM | RDA_SM0_ERR_ALARM |
+				   RDA_RXD_ECC_DB_SERR | RDA_RXDn_ECC_SG_ERR |
+				   RDA_FRM_ECC_SG_ERR |
+				   RDA_MISC_ERR|RDA_PCIX_ERR,
+				   flag, &bar0->rda_err_mask);
+		do_s2io_write_bits(RTI_SM_ERR_ALARM |
+				   RTI_ECC_SG_ERR | RTI_ECC_DB_ERR,
+				   flag, &bar0->rti_err_mask);
+	}
+
+	if (mask & RX_MAC_INTR) {
+		gen_int_mask |= RXMAC_INT_M;
+		do_s2io_write_bits(MAC_INT_STATUS_RMAC_INT, flag,
+				   &bar0->mac_int_mask);
+		interruptible = (RMAC_RX_BUFF_OVRN | RMAC_RX_SM_ERR |
+				 RMAC_UNUSED_INT | RMAC_SINGLE_ECC_ERR |
+				 RMAC_DOUBLE_ECC_ERR);
+		if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER)
+			interruptible |= RMAC_LINK_STATE_CHANGE_INT;
+		do_s2io_write_bits(interruptible,
+				   flag, &bar0->mac_rmac_err_mask);
+	}
+
+	if (mask & RX_XGXS_INTR) {
+		gen_int_mask |= RXXGXS_INT_M;
+		do_s2io_write_bits(XGXS_INT_STATUS_RXGXS, flag,
+				   &bar0->xgxs_int_mask);
+		do_s2io_write_bits(RXGXS_ESTORE_OFLOW | RXGXS_RX_SM_ERR, flag,
+				   &bar0->xgxs_rxgxs_err_mask);
+	}
+
+	if (mask & MC_INTR) {
+		gen_int_mask |= MC_INT_M;
+		do_s2io_write_bits(MC_INT_MASK_MC_INT,
+				   flag, &bar0->mc_int_mask);
+		do_s2io_write_bits(MC_ERR_REG_SM_ERR | MC_ERR_REG_ECC_ALL_SNG |
+				   MC_ERR_REG_ECC_ALL_DBL | PLL_LOCK_N, flag,
+				   &bar0->mc_err_mask);
+	}
+	nic->general_int_mask = gen_int_mask;
+
+	/* Remove this line when alarm interrupts are enabled */
+	nic->general_int_mask = 0;
+}
+
+/**
  *  en_dis_able_nic_intrs - Enable or Disable the interrupts
  *  @nic: device private variable,
  *  @mask: A mask indicating which Intr block must be modified and,
@@ -1749,17 +2036,16 @@ static int s2io_link_fault_indication(struct s2io_nic *nic)
 static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
 {
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
-	register u64 val64 = 0, temp64 = 0;
+	register u64 temp64 = 0, intr_mask = 0;
+
+	intr_mask = nic->general_int_mask;
 
 	/*  Top level interrupt classification */
 	/*  PIC Interrupts */
-	if ((mask & (TX_PIC_INTR | RX_PIC_INTR))) {
+	if (mask & TX_PIC_INTR) {
 		/*  Enable PIC Intrs in the general intr mask register */
-		val64 = TXPIC_INT_M;
+		intr_mask |= TXPIC_INT_M;
 		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
 			/*
 			 * If Hercules adapter enable GPIO otherwise
 			 * disable all PCIX, Flash, MDIO, IIC and GPIO
@@ -1767,65 +2053,26 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
 			 * TODO
 			 */
 			if (s2io_link_fault_indication(nic) ==
-					LINK_UP_DOWN_INTERRUPT ) {
-				temp64 = readq(&bar0->pic_int_mask);
-				temp64 &= ~((u64) PIC_INT_GPIO);
-				writeq(temp64, &bar0->pic_int_mask);
-				temp64 = readq(&bar0->gpio_int_mask);
-				temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
-				writeq(temp64, &bar0->gpio_int_mask);
-			} else {
+			    LINK_UP_DOWN_INTERRUPT) {
+				do_s2io_write_bits(PIC_INT_GPIO, flag,
+						   &bar0->pic_int_mask);
+				do_s2io_write_bits(GPIO_INT_MASK_LINK_UP, flag,
+						   &bar0->gpio_int_mask);
+			} else
 				writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
-			}
-			/*
-			 * No MSI Support is available presently, so TTI and
-			 * RTI interrupts are also disabled.
-			 */
 		} else if (flag == DISABLE_INTRS) {
 			/*
 			 * Disable PIC Intrs in the general
 			 * intr mask register
 			 */
 			writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
-		}
-	}
-
-	/*  MAC Interrupts */
-	/*  Enabling/Disabling MAC interrupts */
-	if (mask & (TX_MAC_INTR | RX_MAC_INTR)) {
-		val64 = TXMAC_INT_M | RXMAC_INT_M;
-		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
-			/*
-			 * All MAC block error interrupts are disabled for now
-			 * TODO
-			 */
-		} else if (flag == DISABLE_INTRS) {
-			/*
-			 * Disable MAC Intrs in the general intr mask register
-			 */
-			writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask);
-			writeq(DISABLE_ALL_INTRS,
-			       &bar0->mac_rmac_err_mask);
-
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
 		}
 	}
 
 	/*  Tx traffic interrupts */
 	if (mask & TX_TRAFFIC_INTR) {
-		val64 = TXTRAFFIC_INT_M;
+		intr_mask |= TXTRAFFIC_INT_M;
 		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
 			/*
 			 * Enable all the Tx side interrupts
 			 * writing 0 Enables all 64 TX interrupt levels
@@ -1837,19 +2084,13 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
 			 * register.
 			 */
 			writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask);
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
 		}
 	}
 
 	/*  Rx traffic interrupts */
 	if (mask & RX_TRAFFIC_INTR) {
-		val64 = RXTRAFFIC_INT_M;
+		intr_mask |= RXTRAFFIC_INT_M;
 		if (flag == ENABLE_INTRS) {
-			temp64 = readq(&bar0->general_int_mask);
-			temp64 &= ~((u64) val64);
-			writeq(temp64, &bar0->general_int_mask);
 			/* writing 0 Enables all 8 RX interrupt levels */
 			writeq(0x0, &bar0->rx_traffic_mask);
 		} else if (flag == DISABLE_INTRS) {
@@ -1858,11 +2099,17 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
 			 * register.
 			 */
 			writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask);
-			temp64 = readq(&bar0->general_int_mask);
-			val64 |= temp64;
-			writeq(val64, &bar0->general_int_mask);
 		}
 	}
+
+	temp64 = readq(&bar0->general_int_mask);
+	if (flag == ENABLE_INTRS)
+		temp64 &= ~((u64)intr_mask);
+	else
+		temp64 = DISABLE_ALL_INTRS;
+	writeq(temp64, &bar0->general_int_mask);
+
+	nic->general_int_mask = readq(&bar0->general_int_mask);
 }
 
 /**
@@ -1875,11 +2122,11 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag)
 	int ret = 0, herc;
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64 = readq(&bar0->adapter_status);
-	
+
 	herc = (sp->device_type == XFRAME_II_DEVICE);
 
-	if (flag == FALSE) {
-		if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+	if (flag == false) {
+		if ((!herc && (sp->pdev->revision >= 4)) || herc) {
 			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
 				ret = 1;
 		} else {
@@ -1887,7 +2134,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag)
 				ret = 1;
 		}
 	} else {
-		if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+		if ((!herc && (sp->pdev->revision >= 4)) || herc) {
 			if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
 			     ADAPTER_STATUS_RMAC_PCC_IDLE))
 				ret = 1;
@@ -1918,35 +2165,35 @@ static int verify_xena_quiescence(struct s2io_nic *sp)
 	mode = s2io_verify_pci_mode(sp);
 
 	if (!(val64 & ADAPTER_STATUS_TDMA_READY)) {
-		DBG_PRINT(ERR_DBG, "%s", "TDMA is not ready!");
+		DBG_PRINT(ERR_DBG, "TDMA is not ready!\n");
 		return 0;
 	}
 	if (!(val64 & ADAPTER_STATUS_RDMA_READY)) {
-	DBG_PRINT(ERR_DBG, "%s", "RDMA is not ready!");
+		DBG_PRINT(ERR_DBG, "RDMA is not ready!\n");
 		return 0;
 	}
 	if (!(val64 & ADAPTER_STATUS_PFC_READY)) {
-		DBG_PRINT(ERR_DBG, "%s", "PFC is not ready!");
+		DBG_PRINT(ERR_DBG, "PFC is not ready!\n");
 		return 0;
 	}
 	if (!(val64 & ADAPTER_STATUS_TMAC_BUF_EMPTY)) {
-		DBG_PRINT(ERR_DBG, "%s", "TMAC BUF is not empty!");
+		DBG_PRINT(ERR_DBG, "TMAC BUF is not empty!\n");
 		return 0;
 	}
 	if (!(val64 & ADAPTER_STATUS_PIC_QUIESCENT)) {
-		DBG_PRINT(ERR_DBG, "%s", "PIC is not QUIESCENT!");
+		DBG_PRINT(ERR_DBG, "PIC is not QUIESCENT!\n");
 		return 0;
 	}
 	if (!(val64 & ADAPTER_STATUS_MC_DRAM_READY)) {
-		DBG_PRINT(ERR_DBG, "%s", "MC_DRAM is not ready!");
+		DBG_PRINT(ERR_DBG, "MC_DRAM is not ready!\n");
 		return 0;
 	}
 	if (!(val64 & ADAPTER_STATUS_MC_QUEUES_READY)) {
-		DBG_PRINT(ERR_DBG, "%s", "MC_QUEUES is not ready!");
+		DBG_PRINT(ERR_DBG, "MC_QUEUES is not ready!\n");
 		return 0;
 	}
 	if (!(val64 & ADAPTER_STATUS_M_PLL_LOCK)) {
-		DBG_PRINT(ERR_DBG, "%s", "M_PLL is not locked!");
+		DBG_PRINT(ERR_DBG, "M_PLL is not locked!\n");
 		return 0;
 	}
 
@@ -1956,14 +2203,14 @@ static int verify_xena_quiescence(struct s2io_nic *sp)
 	 * not be asserted.
 	 */
 	if (!(val64 & ADAPTER_STATUS_P_PLL_LOCK) &&
-		sp->device_type == XFRAME_II_DEVICE && mode !=
-		PCI_MODE_PCI_33) {
-		DBG_PRINT(ERR_DBG, "%s", "P_PLL is not locked!");
+	    sp->device_type == XFRAME_II_DEVICE &&
+	    mode != PCI_MODE_PCI_33) {
+		DBG_PRINT(ERR_DBG, "P_PLL is not locked!\n");
 		return 0;
 	}
 	if (!((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
-			ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
-		DBG_PRINT(ERR_DBG, "%s", "RC_PRC is not QUIESCENT!");
+	      ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
+		DBG_PRINT(ERR_DBG, "RC_PRC is not QUIESCENT!\n");
 		return 0;
 	}
 	return 1;
@@ -1977,7 +2224,7 @@ static int verify_xena_quiescence(struct s2io_nic *sp)
  *
  */
 
-static void fix_mac_address(struct s2io_nic * sp)
+static void fix_mac_address(struct s2io_nic *sp)
 {
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64;
@@ -2009,20 +2256,17 @@ static int start_nic(struct s2io_nic *nic)
 	struct net_device *dev = nic->dev;
 	register u64 val64 = 0;
 	u16 subid, i;
-	struct mac_info *mac_control;
-	struct config_param *config;
-
-	mac_control = &nic->mac_control;
-	config = &nic->config;
+	struct config_param *config = &nic->config;
+	struct mac_info *mac_control = &nic->mac_control;
 
 	/*  PRC Initialization and configuration */
 	for (i = 0; i < config->rx_ring_num; i++) {
-		writeq((u64) mac_control->rings[i].rx_blocks[0].block_dma_addr,
+		struct ring_info *ring = &mac_control->rings[i];
+
+		writeq((u64)ring->rx_blocks[0].block_dma_addr,
 		       &bar0->prc_rxd0_n[i]);
 
 		val64 = readq(&bar0->prc_ctrl_n[i]);
-		if (nic->config.bimodal)
-			val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
 		if (nic->rxd_mode == RXD_MODE_1)
 			val64 |= PRC_CTRL_RC_ENABLED;
 		else
@@ -2045,12 +2289,12 @@ static int start_nic(struct s2io_nic *nic)
 		val64 = readq(&bar0->rx_pa_cfg);
 		val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
 		writeq(val64, &bar0->rx_pa_cfg);
-		vlan_strip_flag = 0;
+		nic->vlan_strip_flag = 0;
 	} else {
 		val64 = readq(&bar0->rx_pa_cfg);
 		val64 |= RX_PA_CFG_STRIP_VLAN_TAG;
 		writeq(val64, &bar0->rx_pa_cfg);
-		vlan_strip_flag = 1;
+		nic->vlan_strip_flag = 1;
 	}
 
 	/*
@@ -2071,22 +2315,14 @@ static int start_nic(struct s2io_nic *nic)
 	writeq(val64, &bar0->adapter_control);
 
 	/*
-	 * Clearing any possible Link state change interrupts that
-	 * could have popped up just before Enabling the card.
-	 */
-	val64 = readq(&bar0->mac_rmac_err_reg);
-	if (val64)
-		writeq(val64, &bar0->mac_rmac_err_reg);
-
-	/*
 	 * Verify if the device is ready to be enabled, if so enable
 	 * it.
 	 */
 	val64 = readq(&bar0->adapter_status);
 	if (!verify_xena_quiescence(nic)) {
-		DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name);
-		DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n",
-			  (unsigned long long) val64);
+		DBG_PRINT(ERR_DBG, "%s: device is not ready, "
+			  "Adapter status reads: 0x%llx\n",
+			  dev->name, (unsigned long long)val64);
 		return FAILURE;
 	}
 
@@ -2126,8 +2362,8 @@ static int start_nic(struct s2io_nic *nic)
 /**
  * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb
  */
-static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \
-					TxD *txdlp, int get_off)
+static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data,
+					struct TxD *txdlp, int get_off)
 {
 	struct s2io_nic *nic = fifo_data->nic;
 	struct sk_buff *skb;
@@ -2135,23 +2371,19 @@ static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \
 	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);
+	if (txds->Host_Control == (u64)(long)fifo_data->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);
+	skb = (struct sk_buff *)((unsigned long)txds->Host_Control);
 	if (!skb) {
 		memset(txdlp, 0, (sizeof(struct TxD) * 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);
+	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++;
@@ -2159,13 +2391,13 @@ static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \
 			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,
+			pci_unmap_page(nic->pdev,
+				       (dma_addr_t)txds->Buffer_Pointer,
 				       frag->size, PCI_DMA_TODEVICE);
 		}
 	}
-	memset(txdlp,0, (sizeof(struct TxD) * fifo_data->max_txds));
-	return(skb);
+	memset(txdlp, 0, (sizeof(struct TxD) * fifo_data->max_txds));
+	return skb;
 }
 
 /**
@@ -2174,7 +2406,7 @@ static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \
  *  Description:
  *  Free all queued Tx buffers.
  *  Return Value: void
-*/
+ */
 
 static void free_tx_buffers(struct s2io_nic *nic)
 {
@@ -2182,30 +2414,33 @@ static void free_tx_buffers(struct s2io_nic *nic)
 	struct sk_buff *skb;
 	struct TxD *txdp;
 	int i, j;
-	struct mac_info *mac_control;
-	struct config_param *config;
 	int cnt = 0;
-
-	mac_control = &nic->mac_control;
-	config = &nic->config;
+	struct config_param *config = &nic->config;
+	struct mac_info *mac_control = &nic->mac_control;
+	struct stat_block *stats = mac_control->stats_info;
+	struct swStat *swstats = &stats->sw_stat;
 
 	for (i = 0; i < config->tx_fifo_num; i++) {
-		for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
-			txdp = (struct TxD *) \
-			mac_control->fifos[i].list_info[j].list_virt_addr;
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+		struct fifo_info *fifo = &mac_control->fifos[i];
+		unsigned long flags;
+
+		spin_lock_irqsave(&fifo->tx_lock, flags);
+		for (j = 0; j < tx_cfg->fifo_len; j++) {
+			txdp = (struct TxD *)fifo->list_info[j].list_virt_addr;
 			skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
 			if (skb) {
-				nic->mac_control.stats_info->sw_stat.mem_freed 
-					+= skb->truesize;
+				swstats->mem_freed += skb->truesize;
 				dev_kfree_skb(skb);
 				cnt++;
 			}
 		}
 		DBG_PRINT(INTR_DBG,
-			  "%s:forcibly freeing %d skbs on FIFO%d\n",
+			  "%s: forcibly freeing %d skbs on FIFO%d\n",
 			  dev->name, cnt, i);
-		mac_control->fifos[i].tx_curr_get_info.offset = 0;
-		mac_control->fifos[i].tx_curr_put_info.offset = 0;
+		fifo->tx_curr_get_info.offset = 0;
+		fifo->tx_curr_put_info.offset = 0;
+		spin_unlock_irqrestore(&fifo->tx_lock, flags);
 	}
 }
 
@@ -2224,16 +2459,11 @@ static void stop_nic(struct s2io_nic *nic)
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
 	register u64 val64 = 0;
 	u16 interruptible;
-	struct mac_info *mac_control;
-	struct config_param *config;
-
-	mac_control = &nic->mac_control;
-	config = &nic->config;
 
 	/*  Disable all interrupts */
+	en_dis_err_alarms(nic, ENA_ALL_INTRS, DISABLE_INTRS);
 	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
-	interruptible |= TX_PIC_INTR | RX_PIC_INTR;
-	interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+	interruptible |= TX_PIC_INTR;
 	en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
 
 	/* Clearing Adapter_En bit of ADAPTER_CONTROL Register */
@@ -2244,8 +2474,10 @@ static void stop_nic(struct s2io_nic *nic)
 
 /**
  *  fill_rx_buffers - Allocates the Rx side skbs
- *  @nic:  device private variable
- *  @ring_no: ring number
+ *  @ring_info: per ring structure
+ *  @from_card_up: If this is true, we will map the buffer to get
+ *     the dma address for buf0 and buf1 to give it to the card.
+ *     Else we will sync the already mapped buffer to give it to the card.
  *  Description:
  *  The function allocates Rx side skbs and puts the physical
  *  address of these buffers into the RxD buffer pointers, so that the NIC
@@ -2262,130 +2494,112 @@ static void stop_nic(struct s2io_nic *nic)
  *   Return Value:
  *  SUCCESS on success or an appropriate -ve value on failure.
  */
-
-static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+static int fill_rx_buffers(struct s2io_nic *nic, struct ring_info *ring,
+			   int from_card_up)
 {
-	struct net_device *dev = nic->dev;
 	struct sk_buff *skb;
 	struct RxD_t *rxdp;
-	int off, off1, size, block_no, block_no1;
+	int off, size, block_no, block_no1;
 	u32 alloc_tab = 0;
 	u32 alloc_cnt;
-	struct mac_info *mac_control;
-	struct config_param *config;
 	u64 tmp;
 	struct buffAdd *ba;
-	unsigned long flags;
 	struct RxD_t *first_rxdp = NULL;
 	u64 Buffer0_ptr = 0, Buffer1_ptr = 0;
+	int rxd_index = 0;
 	struct RxD1 *rxdp1;
 	struct RxD3 *rxdp3;
-	struct swStat *stats = &nic->mac_control.stats_info->sw_stat;
+	struct swStat *swstats = &ring->nic->mac_control.stats_info->sw_stat;
 
-	mac_control = &nic->mac_control;
-	config = &nic->config;
-	alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
-	    atomic_read(&nic->rx_bufs_left[ring_no]);
+	alloc_cnt = ring->pkt_cnt - ring->rx_bufs_left;
 
-	block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index;
-	off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
+	block_no1 = ring->rx_curr_get_info.block_index;
 	while (alloc_tab < alloc_cnt) {
-		block_no = mac_control->rings[ring_no].rx_curr_put_info.
-		    block_index;
-		off = mac_control->rings[ring_no].rx_curr_put_info.offset;
+		block_no = ring->rx_curr_put_info.block_index;
 
-		rxdp = mac_control->rings[ring_no].
-				rx_blocks[block_no].rxds[off].virt_addr;
+		off = ring->rx_curr_put_info.offset;
 
-		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");
+		rxdp = ring->rx_blocks[block_no].rxds[off].virt_addr;
+
+		rxd_index = off + 1;
+		if (block_no)
+			rxd_index += (block_no * ring->rxd_count);
+
+		if ((block_no == block_no1) &&
+		    (off == ring->rx_curr_get_info.offset) &&
+		    (rxdp->Host_Control)) {
+			DBG_PRINT(INTR_DBG, "%s: Get and Put info equated\n",
+				  ring->dev->name);
 			goto end;
 		}
-		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.
-				offset = off;
-			rxdp = mac_control->rings[ring_no].
-				rx_blocks[block_no].block_virt_addr;
+		if (off && (off == ring->rxd_count)) {
+			ring->rx_curr_put_info.block_index++;
+			if (ring->rx_curr_put_info.block_index ==
+			    ring->block_count)
+				ring->rx_curr_put_info.block_index = 0;
+			block_no = ring->rx_curr_put_info.block_index;
+			off = 0;
+			ring->rx_curr_put_info.offset = off;
+			rxdp = ring->rx_blocks[block_no].block_virt_addr;
 			DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
-				  dev->name, rxdp);
-		}
-		if(!napi) {
-			spin_lock_irqsave(&nic->put_lock, flags);
-			mac_control->rings[ring_no].put_pos =
-			(block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
-			spin_unlock_irqrestore(&nic->put_lock, flags);
-		} else {
-			mac_control->rings[ring_no].put_pos =
-			(block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
+				  ring->dev->name, rxdp);
+
 		}
+
 		if ((rxdp->Control_1 & RXD_OWN_XENA) &&
-			((nic->rxd_mode == RXD_MODE_3B) &&
-				(rxdp->Control_2 & BIT(0)))) {
-			mac_control->rings[ring_no].rx_curr_put_info.
-					offset = off;
+		    ((ring->rxd_mode == RXD_MODE_3B) &&
+		     (rxdp->Control_2 & s2BIT(0)))) {
+			ring->rx_curr_put_info.offset = off;
 			goto end;
 		}
 		/* 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 = ring->mtu +
+			HEADER_ETHERNET_II_802_3_SIZE +
+			HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
+		if (ring->rxd_mode == RXD_MODE_1)
 			size += NET_IP_ALIGN;
 		else
-			size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
+			size = ring->mtu + ALIGN_SIZE + BUF0_LEN + 4;
 
 		/* allocate skb */
 		skb = dev_alloc_skb(size);
-		if(!skb) {
-			DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name);
-			DBG_PRINT(INFO_DBG, "memory to allocate SKBs\n");
+		if (!skb) {
+			DBG_PRINT(INFO_DBG, "%s: Could not allocate skb\n",
+				  ring->dev->name);
 			if (first_rxdp) {
 				wmb();
 				first_rxdp->Control_1 |= RXD_OWN_XENA;
 			}
-			nic->mac_control.stats_info->sw_stat. \
-				mem_alloc_fail_cnt++;
+			swstats->mem_alloc_fail_cnt++;
+
 			return -ENOMEM ;
 		}
-		nic->mac_control.stats_info->sw_stat.mem_allocated 
-			+= skb->truesize;
-		if (nic->rxd_mode == RXD_MODE_1) {
+		swstats->mem_allocated += skb->truesize;
+
+		if (ring->rxd_mode == RXD_MODE_1) {
 			/* 1 buffer mode - normal operation mode */
-			rxdp1 = (struct RxD1*)rxdp;
+			rxdp1 = (struct RxD1 *)rxdp;
 			memset(rxdp, 0, sizeof(struct RxD1));
 			skb_reserve(skb, NET_IP_ALIGN);
-			rxdp1->Buffer0_ptr = pci_map_single
-			    (nic->pdev, skb->data, size - NET_IP_ALIGN,
-				PCI_DMA_FROMDEVICE);
-			if( (rxdp1->Buffer0_ptr == 0) ||
-				(rxdp1->Buffer0_ptr ==
-				DMA_ERROR_CODE))
+			rxdp1->Buffer0_ptr =
+				pci_map_single(ring->pdev, skb->data,
+					       size - NET_IP_ALIGN,
+					       PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(nic->pdev,
+						  rxdp1->Buffer0_ptr))
 				goto pci_map_failed;
 
-			rxdp->Control_2 = 
+			rxdp->Control_2 =
 				SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN);
-
-		} else if (nic->rxd_mode == RXD_MODE_3B) {
+			rxdp->Host_Control = (unsigned long)skb;
+		} else if (ring->rxd_mode == RXD_MODE_3B) {
 			/*
 			 * 2 buffer mode -
 			 * 2 buffer mode provides 128
 			 * byte aligned receive buffers.
 			 */
 
-			rxdp3 = (struct RxD3*)rxdp;
+			rxdp3 = (struct RxD3 *)rxdp;
 			/* save buffer pointers to avoid frequent dma mapping */
 			Buffer0_ptr = rxdp3->Buffer0_ptr;
 			Buffer1_ptr = rxdp3->Buffer1_ptr;
@@ -2394,68 +2608,75 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 			rxdp3->Buffer0_ptr = Buffer0_ptr;
 			rxdp3->Buffer1_ptr = Buffer1_ptr;
 
-			ba = &mac_control->rings[ring_no].ba[block_no][off];
+			ba = &ring->ba[block_no][off];
 			skb_reserve(skb, BUF0_LEN);
-			tmp = (u64)(unsigned long) skb->data;
+			tmp = (u64)(unsigned long)skb->data;
 			tmp += ALIGN_SIZE;
 			tmp &= ~ALIGN_SIZE;
 			skb->data = (void *) (unsigned long)tmp;
-			skb->tail = (void *) (unsigned long)tmp;
+			skb_reset_tail_pointer(skb);
 
-			if (!(rxdp3->Buffer0_ptr))
+			if (from_card_up) {
 				rxdp3->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) rxdp3->Buffer0_ptr,
-				    BUF0_LEN, PCI_DMA_FROMDEVICE);
-			if( (rxdp3->Buffer0_ptr == 0) ||
-				(rxdp3->Buffer0_ptr == DMA_ERROR_CODE))
-				goto pci_map_failed;
+					pci_map_single(ring->pdev, ba->ba_0,
+						       BUF0_LEN,
+						       PCI_DMA_FROMDEVICE);
+				if (pci_dma_mapping_error(nic->pdev,
+							  rxdp3->Buffer0_ptr))
+					goto pci_map_failed;
+			} else
+				pci_dma_sync_single_for_device(ring->pdev,
+							       (dma_addr_t)rxdp3->Buffer0_ptr,
+							       BUF0_LEN,
+							       PCI_DMA_FROMDEVICE);
 
 			rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
-			if (nic->rxd_mode == RXD_MODE_3B) {
+			if (ring->rxd_mode == RXD_MODE_3B) {
 				/* Two buffer mode */
 
 				/*
 				 * Buffer2 will have L3/L4 header plus
 				 * L4 payload
 				 */
-				rxdp3->Buffer2_ptr = pci_map_single
-				(nic->pdev, skb->data, dev->mtu + 4,
-						PCI_DMA_FROMDEVICE);
+				rxdp3->Buffer2_ptr = pci_map_single(ring->pdev,
+								    skb->data,
+								    ring->mtu + 4,
+								    PCI_DMA_FROMDEVICE);
 
-				if( (rxdp3->Buffer2_ptr == 0) ||
-					(rxdp3->Buffer2_ptr == DMA_ERROR_CODE))
+				if (pci_dma_mapping_error(nic->pdev,
+							  rxdp3->Buffer2_ptr))
 					goto pci_map_failed;
 
-				rxdp3->Buffer1_ptr =
-						pci_map_single(nic->pdev,
-						ba->ba_1, BUF1_LEN,
-						PCI_DMA_FROMDEVICE);
-				if( (rxdp3->Buffer1_ptr == 0) ||
-					(rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) {
-					pci_unmap_single
-						(nic->pdev,
-						(dma_addr_t)rxdp3->Buffer2_ptr,
-						dev->mtu + 4,
-						PCI_DMA_FROMDEVICE);
-					goto pci_map_failed;
+				if (from_card_up) {
+					rxdp3->Buffer1_ptr =
+						pci_map_single(ring->pdev,
+							       ba->ba_1,
+							       BUF1_LEN,
+							       PCI_DMA_FROMDEVICE);
+
+					if (pci_dma_mapping_error(nic->pdev,
+								  rxdp3->Buffer1_ptr)) {
+						pci_unmap_single(ring->pdev,
+								 (dma_addr_t)(unsigned long)
+								 skb->data,
+								 ring->mtu + 4,
+								 PCI_DMA_FROMDEVICE);
+						goto pci_map_failed;
+					}
 				}
 				rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
 				rxdp->Control_2 |= SET_BUFFER2_SIZE_3
-								(dev->mtu + 4);
+					(ring->mtu + 4);
 			}
-			rxdp->Control_2 |= BIT(0);
+			rxdp->Control_2 |= s2BIT(0);
+			rxdp->Host_Control = (unsigned long) (skb);
 		}
-		rxdp->Host_Control = (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))
+		if (off == (ring->rxd_count + 1))
 			off = 0;
-		mac_control->rings[ring_no].rx_curr_put_info.offset = off;
+		ring->rx_curr_put_info.offset = off;
 
 		rxdp->Control_2 |= SET_RXD_MARKER;
 		if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
@@ -2465,11 +2686,11 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 			}
 			first_rxdp = rxdp;
 		}
-		atomic_inc(&nic->rx_bufs_left[ring_no]);
+		ring->rx_bufs_left += 1;
 		alloc_tab++;
 	}
 
-      end:
+end:
 	/* Transfer ownership of first descriptor to adapter just before
 	 * exiting. Before that, use memory barrier so that ownership
 	 * and other fields are seen by adapter correctly.
@@ -2480,9 +2701,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 	}
 
 	return SUCCESS;
+
 pci_map_failed:
-	stats->pci_map_fail_cnt++;
-	stats->mem_freed += skb->truesize;
+	swstats->pci_map_fail_cnt++;
+	swstats->mem_freed += skb->truesize;
 	dev_kfree_skb_irq(skb);
 	return -ENOMEM;
 }
@@ -2493,51 +2715,48 @@ static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk)
 	int j;
 	struct sk_buff *skb;
 	struct RxD_t *rxdp;
-	struct mac_info *mac_control;
 	struct buffAdd *ba;
 	struct RxD1 *rxdp1;
 	struct RxD3 *rxdp3;
+	struct mac_info *mac_control = &sp->mac_control;
+	struct stat_block *stats = mac_control->stats_info;
+	struct swStat *swstats = &stats->sw_stat;
 
-	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) {
+			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) {
-			rxdp1 = (struct RxD1*)rxdp;
-			pci_unmap_single(sp->pdev, (dma_addr_t)
-				rxdp1->Buffer0_ptr,
-				dev->mtu +
-				HEADER_ETHERNET_II_802_3_SIZE
-				+ HEADER_802_2_SIZE +
-				HEADER_SNAP_SIZE,
-				PCI_DMA_FROMDEVICE);
+			rxdp1 = (struct RxD1 *)rxdp;
+			pci_unmap_single(sp->pdev,
+					 (dma_addr_t)rxdp1->Buffer0_ptr,
+					 dev->mtu +
+					 HEADER_ETHERNET_II_802_3_SIZE +
+					 HEADER_802_2_SIZE + HEADER_SNAP_SIZE,
+					 PCI_DMA_FROMDEVICE);
 			memset(rxdp, 0, sizeof(struct RxD1));
-		} else if(sp->rxd_mode == RXD_MODE_3B) {
-			rxdp3 = (struct RxD3*)rxdp;
-			ba = &mac_control->rings[ring_no].
-				ba[blk][j];
-			pci_unmap_single(sp->pdev, (dma_addr_t)
-				rxdp3->Buffer0_ptr,
-				BUF0_LEN,
-				PCI_DMA_FROMDEVICE);
-			pci_unmap_single(sp->pdev, (dma_addr_t)
-				rxdp3->Buffer1_ptr,
-				BUF1_LEN,
-				PCI_DMA_FROMDEVICE);
-			pci_unmap_single(sp->pdev, (dma_addr_t)
-				rxdp3->Buffer2_ptr,
-				dev->mtu + 4,
-				PCI_DMA_FROMDEVICE);
+		} else if (sp->rxd_mode == RXD_MODE_3B) {
+			rxdp3 = (struct RxD3 *)rxdp;
+			ba = &mac_control->rings[ring_no].ba[blk][j];
+			pci_unmap_single(sp->pdev,
+					 (dma_addr_t)rxdp3->Buffer0_ptr,
+					 BUF0_LEN,
+					 PCI_DMA_FROMDEVICE);
+			pci_unmap_single(sp->pdev,
+					 (dma_addr_t)rxdp3->Buffer1_ptr,
+					 BUF1_LEN,
+					 PCI_DMA_FROMDEVICE);
+			pci_unmap_single(sp->pdev,
+					 (dma_addr_t)rxdp3->Buffer2_ptr,
+					 dev->mtu + 4,
+					 PCI_DMA_FROMDEVICE);
 			memset(rxdp, 0, sizeof(struct RxD3));
 		}
-		sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
+		swstats->mem_freed += skb->truesize;
 		dev_kfree_skb(skb);
-		atomic_dec(&sp->rx_bufs_left[ring_no]);
+		mac_control->rings[ring_no].rx_bufs_left -= 1;
 	}
 }
 
@@ -2554,29 +2773,37 @@ static void free_rx_buffers(struct s2io_nic *sp)
 {
 	struct net_device *dev = sp->dev;
 	int i, blk = 0, buf_cnt = 0;
-	struct mac_info *mac_control;
-	struct config_param *config;
-
-	mac_control = &sp->mac_control;
-	config = &sp->config;
+	struct config_param *config = &sp->config;
+	struct mac_info *mac_control = &sp->mac_control;
 
 	for (i = 0; i < config->rx_ring_num; i++) {
+		struct ring_info *ring = &mac_control->rings[i];
+
 		for (blk = 0; blk < rx_ring_sz[i]; blk++)
-			free_rxd_blk(sp,i,blk);
-
-		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;
-		mac_control->rings[i].rx_curr_get_info.offset = 0;
-		atomic_set(&sp->rx_bufs_left[i], 0);
-		DBG_PRINT(INIT_DBG, "%s:Freed 0x%x Rx Buffers on ring%d\n",
+			free_rxd_blk(sp, i, blk);
+
+		ring->rx_curr_put_info.block_index = 0;
+		ring->rx_curr_get_info.block_index = 0;
+		ring->rx_curr_put_info.offset = 0;
+		ring->rx_curr_get_info.offset = 0;
+		ring->rx_bufs_left = 0;
+		DBG_PRINT(INIT_DBG, "%s: Freed 0x%x Rx Buffers on ring%d\n",
 			  dev->name, buf_cnt, i);
 	}
 }
 
+static int s2io_chk_rx_buffers(struct s2io_nic *nic, struct ring_info *ring)
+{
+	if (fill_rx_buffers(nic, ring, 0) == -ENOMEM) {
+		DBG_PRINT(INFO_DBG, "%s: Out of memory in Rx Intr!!\n",
+			  ring->dev->name);
+	}
+	return 0;
+}
+
 /**
  * s2io_poll - Rx interrupt handler for NAPI support
- * @dev : pointer to the device structure.
+ * @napi : pointer to the napi structure.
  * @budget : The number of packets that were budgeted to be processed
  * during  one pass through the 'Poll" function.
  * Description:
@@ -2587,68 +2814,79 @@ static void free_rx_buffers(struct s2io_nic *sp)
  * 0 on success and 1 if there are No Rx packets to be processed.
  */
 
-static int s2io_poll(struct net_device *dev, int *budget)
+static int s2io_poll_msix(struct napi_struct *napi, int budget)
 {
-	struct s2io_nic *nic = dev->priv;
-	int pkt_cnt = 0, org_pkts_to_process;
-	struct mac_info *mac_control;
-	struct config_param *config;
+	struct ring_info *ring = container_of(napi, struct ring_info, napi);
+	struct net_device *dev = ring->dev;
+	int pkts_processed = 0;
+	u8 __iomem *addr = NULL;
+	u8 val8 = 0;
+	struct s2io_nic *nic = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
-	int i;
-
-	atomic_inc(&nic->isr_cnt);
-	mac_control = &nic->mac_control;
-	config = &nic->config;
+	int budget_org = budget;
 
-	nic->pkts_to_process = *budget;
-	if (nic->pkts_to_process > dev->quota)
-		nic->pkts_to_process = dev->quota;
-	org_pkts_to_process = nic->pkts_to_process;
+	if (unlikely(!is_s2io_card_up(nic)))
+		return 0;
 
-	writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
-	readl(&bar0->rx_traffic_int);
+	pkts_processed = rx_intr_handler(ring, budget);
+	s2io_chk_rx_buffers(nic, ring);
 
-	for (i = 0; i < config->rx_ring_num; i++) {
-		rx_intr_handler(&mac_control->rings[i]);
-		pkt_cnt = org_pkts_to_process - nic->pkts_to_process;
-		if (!nic->pkts_to_process) {
-			/* Quota for the current iteration has been met */
-			goto no_rx;
-		}
+	if (pkts_processed < budget_org) {
+		napi_complete(napi);
+		/*Re Enable MSI-Rx Vector*/
+		addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
+		addr += 7 - ring->ring_no;
+		val8 = (ring->ring_no == 0) ? 0x3f : 0xbf;
+		writeb(val8, addr);
+		val8 = readb(addr);
 	}
-	if (!pkt_cnt)
-		pkt_cnt = 1;
+	return pkts_processed;
+}
 
-	dev->quota -= pkt_cnt;
-	*budget -= pkt_cnt;
-	netif_rx_complete(dev);
+static int s2io_poll_inta(struct napi_struct *napi, int budget)
+{
+	struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi);
+	int pkts_processed = 0;
+	int ring_pkts_processed, i;
+	struct XENA_dev_config __iomem *bar0 = nic->bar0;
+	int budget_org = budget;
+	struct config_param *config = &nic->config;
+	struct mac_info *mac_control = &nic->mac_control;
+
+	if (unlikely(!is_s2io_card_up(nic)))
+		return 0;
 
 	for (i = 0; i < config->rx_ring_num; i++) {
-		if (fill_rx_buffers(nic, i) == -ENOMEM) {
-			DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
-			DBG_PRINT(INFO_DBG, " in Rx Poll!!\n");
+		struct ring_info *ring = &mac_control->rings[i];
+		ring_pkts_processed = rx_intr_handler(ring, budget);
+		s2io_chk_rx_buffers(nic, ring);
+		pkts_processed += ring_pkts_processed;
+		budget -= ring_pkts_processed;
+		if (budget <= 0)
 			break;
-		}
 	}
-	/* Re enable the Rx interrupts. */
-	writeq(0x0, &bar0->rx_traffic_mask);
-	readl(&bar0->rx_traffic_mask);
-	atomic_dec(&nic->isr_cnt);
-	return 0;
+	if (pkts_processed < budget_org) {
+		napi_complete(napi);
+		/* Re enable the Rx interrupts for the ring */
+		writeq(0, &bar0->rx_traffic_mask);
+		readl(&bar0->rx_traffic_mask);
+	}
+	return pkts_processed;
+}
 
-no_rx:
-	dev->quota -= pkt_cnt;
-	*budget -= pkt_cnt;
+static int rhel_s2io_poll_msix(struct net_device *dummy_dev, int *budget)
+{
+	struct ring_info *ring = dummy_dev->priv;
+	return rhel_napi_poll_wrapper(s2io_poll_msix, &ring->napi, dummy_dev,
+				      budget);
+}
+
+static int rhel_s2io_poll_inta(struct net_device *dummy_dev, int *budget)
+{
+	struct s2io_nic *nic = dummy_dev->priv;
+	return rhel_napi_poll_wrapper(s2io_poll_inta, &nic->napi, dummy_dev,
+				      budget);
 
-	for (i = 0; i < config->rx_ring_num; i++) {
-		if (fill_rx_buffers(nic, i) == -ENOMEM) {
-			DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
-			DBG_PRINT(INFO_DBG, " in Rx Poll!!\n");
-			break;
-		}
-	}
-	atomic_dec(&nic->isr_cnt);
-	return 1;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2663,23 +2901,18 @@ no_rx:
  */
 static void s2io_netpoll(struct net_device *dev)
 {
-	struct s2io_nic *nic = dev->priv;
-	struct mac_info *mac_control;
-	struct config_param *config;
+	struct s2io_nic *nic = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
 	u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
 	int i;
+	struct config_param *config = &nic->config;
+	struct mac_info *mac_control = &nic->mac_control;
 
-	if ((nic->pdev->error_state != pci_channel_io_normal) &&
-	    (nic->pdev->error_state != 0))
+	if (pci_channel_offline(nic->pdev) && nic->pdev->error_state != 0)
 		return;
 
 	disable_irq(dev->irq);
 
-	atomic_inc(&nic->isr_cnt);
-	mac_control = &nic->mac_control;
-	config = &nic->config;
-
 	writeq(val64, &bar0->rx_traffic_int);
 	writeq(val64, &bar0->tx_traffic_int);
 
@@ -2691,17 +2924,22 @@ static void s2io_netpoll(struct net_device *dev)
 		tx_intr_handler(&mac_control->fifos[i]);
 
 	/* check for received packet and indicate up to network */
-	for (i = 0; i < config->rx_ring_num; i++)
-		rx_intr_handler(&mac_control->rings[i]);
+	for (i = 0; i < config->rx_ring_num; i++) {
+		struct ring_info *ring = &mac_control->rings[i];
+
+		rx_intr_handler(ring, 0);
+	}
 
 	for (i = 0; i < config->rx_ring_num; i++) {
-		if (fill_rx_buffers(nic, i) == -ENOMEM) {
-			DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
-			DBG_PRINT(INFO_DBG, " in Rx Netpoll!!\n");
+		struct ring_info *ring = &mac_control->rings[i];
+
+		if (fill_rx_buffers(nic, ring, 0) == -ENOMEM) {
+			DBG_PRINT(INFO_DBG,
+				  "%s: Out of memory in Rx Netpoll!!\n",
+				  dev->name);
 			break;
 		}
 	}
-	atomic_dec(&nic->isr_cnt);
 	enable_irq(dev->irq);
 	return;
 }
@@ -2709,7 +2947,8 @@ static void s2io_netpoll(struct net_device *dev)
 
 /**
  *  rx_intr_handler - Rx interrupt handler
- *  @nic: device private variable.
+ *  @ring_info: per ring structure.
+ *  @budget: budget for napi processing.
  *  Description:
  *  If the interrupt is because of a received frame or if the
  *  receive ring contains fresh as yet un-processed frames,this function is
@@ -2717,40 +2956,24 @@ static void s2io_netpoll(struct net_device *dev)
  *  stopped and sends the skb to the OSM's Rx handler and then increments
  *  the offset.
  *  Return Value:
- *  NONE.
+ *  No. of napi packets processed.
  */
-static void rx_intr_handler(struct ring_info *ring_data)
+static int rx_intr_handler(struct ring_info *ring_data, int budget)
 {
-	struct s2io_nic *nic = ring_data->nic;
-	struct net_device *dev = (struct net_device *) nic->dev;
-	int get_block, put_block, put_offset;
+	int get_block, put_block;
 	struct rx_curr_get_info get_info, put_info;
 	struct RxD_t *rxdp;
 	struct sk_buff *skb;
-	int pkt_cnt = 0;
+	int pkt_cnt = 0, napi_pkts = 0;
 	int i;
-	struct RxD1* rxdp1;
-	struct RxD3* rxdp3;
-
-	spin_lock(&nic->rx_lock);
-	if (atomic_read(&nic->card_state) == CARD_DOWN) {
-		DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
-			  __FUNCTION__, dev->name);
-		spin_unlock(&nic->rx_lock);
-		return;
-	}
+	struct RxD1 *rxdp1;
+	struct RxD3 *rxdp3;
 
 	get_info = ring_data->rx_curr_get_info;
 	get_block = get_info.block_index;
 	memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info));
 	put_block = put_info.block_index;
 	rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr;
-	if (!napi) {
-		spin_lock(&nic->put_lock);
-		put_offset = ring_data->put_pos;
-		spin_unlock(&nic->put_lock);
-	} else
-		put_offset = ring_data->put_pos;
 
 	while (RXD_IS_UP2DT(rxdp)) {
 		/*
@@ -2759,43 +2982,43 @@ static void rx_intr_handler(struct ring_info *ring_data)
 		 */
 		if ((get_block == put_block) &&
 		    (get_info.offset + 1) == put_info.offset) {
-			DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name);
+			DBG_PRINT(INTR_DBG, "%s: Ring Full\n",
+				  ring_data->dev->name);
 			break;
 		}
-		skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
+		skb = (struct sk_buff *)((unsigned long)rxdp->Host_Control);
 		if (skb == NULL) {
-			DBG_PRINT(ERR_DBG, "%s: The skb is ",
-				  dev->name);
-			DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
-			spin_unlock(&nic->rx_lock);
-			return;
+			DBG_PRINT(ERR_DBG, "%s: NULL skb in Rx Intr\n",
+				  ring_data->dev->name);
+			return 0;
 		}
-		if (nic->rxd_mode == RXD_MODE_1) {
-			rxdp1 = (struct RxD1*)rxdp;
-			pci_unmap_single(nic->pdev, (dma_addr_t)
-				rxdp1->Buffer0_ptr,
-				dev->mtu +
-				HEADER_ETHERNET_II_802_3_SIZE +
-				HEADER_802_2_SIZE +
-				HEADER_SNAP_SIZE,
-				PCI_DMA_FROMDEVICE);
-		} else if (nic->rxd_mode == RXD_MODE_3B) {
-			rxdp3 = (struct RxD3*)rxdp;
-			pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
-				rxdp3->Buffer0_ptr,
-				BUF0_LEN, PCI_DMA_FROMDEVICE);
-			pci_unmap_single(nic->pdev, (dma_addr_t)
-				rxdp3->Buffer2_ptr,
-				dev->mtu + 4,
-				PCI_DMA_FROMDEVICE);
+		if (ring_data->rxd_mode == RXD_MODE_1) {
+			rxdp1 = (struct RxD1 *)rxdp;
+			pci_unmap_single(ring_data->pdev, (dma_addr_t)
+					 rxdp1->Buffer0_ptr,
+					 ring_data->mtu +
+					 HEADER_ETHERNET_II_802_3_SIZE +
+					 HEADER_802_2_SIZE +
+					 HEADER_SNAP_SIZE,
+					 PCI_DMA_FROMDEVICE);
+		} else if (ring_data->rxd_mode == RXD_MODE_3B) {
+			rxdp3 = (struct RxD3 *)rxdp;
+			pci_dma_sync_single_for_cpu(ring_data->pdev,
+						    (dma_addr_t)rxdp3->Buffer0_ptr,
+						    BUF0_LEN,
+						    PCI_DMA_FROMDEVICE);
+			pci_unmap_single(ring_data->pdev,
+					 (dma_addr_t)rxdp3->Buffer2_ptr,
+					 ring_data->mtu + 4,
+					 PCI_DMA_FROMDEVICE);
 		}
 		prefetch(skb->data);
 		rx_osm_handler(ring_data, rxdp);
 		get_info.offset++;
 		ring_data->rx_curr_get_info.offset = get_info.offset;
 		rxdp = ring_data->rx_blocks[get_block].
-				rxds[get_info.offset].virt_addr;
-		if (get_info.offset == rxd_count[nic->rxd_mode]) {
+			rxds[get_info.offset].virt_addr;
+		if (get_info.offset == rxd_count[ring_data->rxd_mode]) {
 			get_info.offset = 0;
 			ring_data->rx_curr_get_info.offset = get_info.offset;
 			get_block++;
@@ -2805,26 +3028,28 @@ static void rx_intr_handler(struct ring_info *ring_data)
 			rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
 		}
 
-		nic->pkts_to_process -= 1;
-		if ((napi) && (!nic->pkts_to_process))
-			break;
+		if (ring_data->nic->config.napi) {
+			budget--;
+			napi_pkts++;
+			if (!budget)
+				break;
+		}
 		pkt_cnt++;
 		if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))
 			break;
 	}
-	if (nic->lro) {
+	if (ring_data->lro) {
 		/* Clear all LRO sessions before exiting */
-		for (i=0; i<MAX_LRO_SESSIONS; i++) {
-			struct lro *lro = &nic->lro0_n[i];
+		for (i = 0; i < MAX_LRO_SESSIONS; i++) {
+			struct lro *lro = &ring_data->lro0_n[i];
 			if (lro->in_use) {
-				update_L3L4_header(nic, lro);
-				queue_rx_frame(lro->parent);
+				update_L3L4_header(ring_data->nic, lro);
+				queue_rx_frame(lro->parent, lro->vlan_tag);
 				clear_lro_session(lro);
 			}
 		}
 	}
-
-	spin_unlock(&nic->rx_lock);
+	return napi_pkts;
 }
 
 /**
@@ -2842,16 +3067,22 @@ static void rx_intr_handler(struct ring_info *ring_data)
 static void tx_intr_handler(struct fifo_info *fifo_data)
 {
 	struct s2io_nic *nic = fifo_data->nic;
-	struct net_device *dev = (struct net_device *) nic->dev;
 	struct tx_curr_get_info get_info, put_info;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct TxD *txdlp;
+	int pkt_cnt = 0;
+	unsigned long flags = 0;
 	u8 err_mask;
+	struct stat_block *stats = nic->mac_control.stats_info;
+	struct swStat *swstats = &stats->sw_stat;
+
+	if (!spin_trylock_irqsave(&fifo_data->tx_lock, flags))
+		return;
 
 	get_info = fifo_data->tx_curr_get_info;
 	memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info));
-	txdlp = (struct TxD *) fifo_data->list_info[get_info.offset].
-	    list_virt_addr;
+	txdlp = (struct TxD *)
+		fifo_data->list_info[get_info.offset].list_virt_addr;
 	while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
 	       (get_info.offset != put_info.offset) &&
 	       (txdlp->Host_Control)) {
@@ -2860,66 +3091,59 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
 			unsigned long long err;
 			err = txdlp->Control_1 & TXD_T_CODE;
 			if (err & 0x1) {
-				nic->mac_control.stats_info->sw_stat.
-						parity_err_cnt++;
+				swstats->parity_err_cnt++;
 			}
 
 			/* update t_code statistics */
 			err_mask = err >> 48;
-			switch(err_mask) {
-				case 2:
-					nic->mac_control.stats_info->sw_stat.
-							tx_buf_abort_cnt++;
+			switch (err_mask) {
+			case 2:
+				swstats->tx_buf_abort_cnt++;
 				break;
 
-				case 3:
-					nic->mac_control.stats_info->sw_stat.
-							tx_desc_abort_cnt++;
+			case 3:
+				swstats->tx_desc_abort_cnt++;
 				break;
 
-				case 7:
-					nic->mac_control.stats_info->sw_stat.
-							tx_parity_err_cnt++;
+			case 7:
+				swstats->tx_parity_err_cnt++;
 				break;
 
-				case 10:
-					nic->mac_control.stats_info->sw_stat.
-							tx_link_loss_cnt++;
+			case 10:
+				swstats->tx_link_loss_cnt++;
 				break;
 
-				case 15:
-					nic->mac_control.stats_info->sw_stat.
-							tx_list_proc_err_cnt++;
+			case 15:
+				swstats->tx_list_proc_err_cnt++;
 				break;
-                        }
+			}
 		}
 
 		skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset);
 		if (skb == NULL) {
-			DBG_PRINT(ERR_DBG, "%s: Null skb ",
-			__FUNCTION__);
-			DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
+			spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
+			DBG_PRINT(ERR_DBG, "%s: NULL skb in Tx Free Intr\n",
+				  __func__);
 			return;
 		}
+		pkt_cnt++;
 
 		/* Updating the statistics block */
-		nic->stats.tx_bytes += skb->len;
-		nic->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
+		nic->dev_stats.tx_bytes += skb->len;
+		swstats->mem_freed += skb->truesize;
 		dev_kfree_skb_irq(skb);
 
 		get_info.offset++;
 		if (get_info.offset == get_info.fifo_len + 1)
 			get_info.offset = 0;
-		txdlp = (struct TxD *) fifo_data->list_info
-		    [get_info.offset].list_virt_addr;
-		fifo_data->tx_curr_get_info.offset =
-		    get_info.offset;
+		txdlp = (struct TxD *)
+			fifo_data->list_info[get_info.offset].list_virt_addr;
+		fifo_data->tx_curr_get_info.offset = get_info.offset;
 	}
 
-	spin_lock(&nic->tx_lock);
-	if (netif_queue_stopped(dev))
-		netif_wake_queue(dev);
-	spin_unlock(&nic->tx_lock);
+	s2io_wake_tx_queue(fifo_data, pkt_cnt, nic->config.multiq);
+
+	spin_unlock_irqrestore(&fifo_data->tx_lock, flags);
 }
 
 /**
@@ -2932,43 +3156,41 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
  *  This function is used to write values to the MDIO registers
  *  NONE
  */
-static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev)
+static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value,
+			    struct net_device *dev)
 {
-	u64 val64 = 0x0;
-	struct s2io_nic *sp = dev->priv;
+	u64 val64;
+	struct s2io_nic *sp = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
-	//address transaction
-	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-			| MDIO_MMD_DEV_ADDR(mmd_type)
-			| MDIO_MMS_PRT_ADDR(0x0);
+	/* address transaction */
+	val64 = MDIO_MMD_INDX_ADDR(addr) |
+		MDIO_MMD_DEV_ADDR(mmd_type) |
+		MDIO_MMS_PRT_ADDR(0x0);
 	writeq(val64, &bar0->mdio_control);
 	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
 	writeq(val64, &bar0->mdio_control);
 	udelay(100);
 
-	//Data transaction
-	val64 = 0x0;
-	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-			| MDIO_MMD_DEV_ADDR(mmd_type)
-			| MDIO_MMS_PRT_ADDR(0x0)
-			| MDIO_MDIO_DATA(value)
-			| MDIO_OP(MDIO_OP_WRITE_TRANS);
+	/* Data transaction */
+	val64 = MDIO_MMD_INDX_ADDR(addr) |
+		MDIO_MMD_DEV_ADDR(mmd_type) |
+		MDIO_MMS_PRT_ADDR(0x0) |
+		MDIO_MDIO_DATA(value) |
+		MDIO_OP(MDIO_OP_WRITE_TRANS);
 	writeq(val64, &bar0->mdio_control);
 	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
 	writeq(val64, &bar0->mdio_control);
 	udelay(100);
 
-	val64 = 0x0;
-	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-	| MDIO_MMD_DEV_ADDR(mmd_type)
-	| MDIO_MMS_PRT_ADDR(0x0)
-	| MDIO_OP(MDIO_OP_READ_TRANS);
+	val64 = MDIO_MMD_INDX_ADDR(addr) |
+		MDIO_MMD_DEV_ADDR(mmd_type) |
+		MDIO_MMS_PRT_ADDR(0x0) |
+		MDIO_OP(MDIO_OP_READ_TRANS);
 	writeq(val64, &bar0->mdio_control);
 	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
 	writeq(val64, &bar0->mdio_control);
 	udelay(100);
-
 }
 
 /**
@@ -2984,24 +3206,23 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
 {
 	u64 val64 = 0x0;
 	u64 rval64 = 0x0;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
 	/* address transaction */
-	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-			| MDIO_MMD_DEV_ADDR(mmd_type)
-			| MDIO_MMS_PRT_ADDR(0x0);
+	val64 = val64 | (MDIO_MMD_INDX_ADDR(addr)
+			 | MDIO_MMD_DEV_ADDR(mmd_type)
+			 | MDIO_MMS_PRT_ADDR(0x0));
 	writeq(val64, &bar0->mdio_control);
 	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
 	writeq(val64, &bar0->mdio_control);
 	udelay(100);
 
 	/* Data transaction */
-	val64 = 0x0;
-	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
-			| MDIO_MMD_DEV_ADDR(mmd_type)
-			| MDIO_MMS_PRT_ADDR(0x0)
-			| MDIO_OP(MDIO_OP_READ_TRANS);
+	val64 = MDIO_MMD_INDX_ADDR(addr) |
+		MDIO_MMD_DEV_ADDR(mmd_type) |
+		MDIO_MMS_PRT_ADDR(0x0) |
+		MDIO_OP(MDIO_OP_READ_TRANS);
 	writeq(val64, &bar0->mdio_control);
 	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
 	writeq(val64, &bar0->mdio_control);
@@ -3013,6 +3234,7 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
 	rval64 = rval64 >> 16;
 	return rval64;
 }
+
 /**
  *  s2io_chk_xpak_counter - Function to check the status of the xpak counters
  *  @counter      : couter value to be updated
@@ -3023,45 +3245,43 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
  *  NONE
  */
 
-static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type)
+static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index,
+				  u16 flag, u16 type)
 {
 	u64 mask = 0x3;
 	u64 val64;
 	int i;
-	for(i = 0; i <index; i++)
+	for (i = 0; i < index; i++)
 		mask = mask << 0x2;
 
-	if(flag > 0)
-	{
+	if (flag > 0) {
 		*counter = *counter + 1;
 		val64 = *regs_stat & mask;
 		val64 = val64 >> (index * 0x2);
 		val64 = val64 + 1;
-		if(val64 == 3)
-		{
-			switch(type)
-			{
+		if (val64 == 3) {
+			switch (type) {
 			case 1:
-				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
-					  "service. Excessive temperatures may "
-					  "result in premature transceiver "
-					  "failure \n");
-			break;
+				DBG_PRINT(ERR_DBG,
+					  "Take Xframe NIC out of service.\n");
+				DBG_PRINT(ERR_DBG,
+"Excessive temperatures may result in premature transceiver failure.\n");
+				break;
 			case 2:
-				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
-					  "service Excessive bias currents may "
-					  "indicate imminent laser diode "
-					  "failure \n");
-			break;
+				DBG_PRINT(ERR_DBG,
+					  "Take Xframe NIC out of service.\n");
+				DBG_PRINT(ERR_DBG,
+"Excessive bias currents may indicate imminent laser diode failure.\n");
+				break;
 			case 3:
-				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
-					  "service Excessive laser output "
-					  "power may saturate far-end "
-					  "receiver\n");
-			break;
+				DBG_PRINT(ERR_DBG,
+					  "Take Xframe NIC out of service.\n");
+				DBG_PRINT(ERR_DBG,
+"Excessive laser output power may saturate far-end receiver.\n");
+				break;
 			default:
-				DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm "
-					  "type \n");
+				DBG_PRINT(ERR_DBG,
+					  "Incorrect XPAK Alarm type\n");
 			}
 			val64 = 0x0;
 		}
@@ -3088,218 +3308,88 @@ static void s2io_updt_xpak_counter(struct net_device *dev)
 	u64 val64 = 0x0;
 	u64 addr  = 0x0;
 
-	struct s2io_nic *sp = dev->priv;
-	struct stat_block *stat_info = sp->mac_control.stats_info;
+	struct s2io_nic *sp = netdev_priv(dev);
+	struct stat_block *stats = sp->mac_control.stats_info;
+	struct xpakStat *xstats = &stats->xpak_stat;
 
 	/* Check the communication with the MDIO slave */
-	addr = 0x0000;
+	addr = MDIO_CTRL1;
 	val64 = 0x0;
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
-	if((val64 == 0xFFFF) || (val64 == 0x0000))
-	{
-		DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - "
-			  "Returned %llx\n", (unsigned long long)val64);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
+	if ((val64 == 0xFFFF) || (val64 == 0x0000)) {
+		DBG_PRINT(ERR_DBG,
+			  "ERR: MDIO slave access failed - Returned %llx\n",
+			  (unsigned long long)val64);
 		return;
 	}
 
-	/* Check for the expecte value of 2040 at PMA address 0x0000 */
-	if(val64 != 0x2040)
-	{
-		DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - ");
-		DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n",
-			  (unsigned long long)val64);
+	/* Check for the expected value of control reg 1 */
+	if (val64 != MDIO_CTRL1_SPEED10G) {
+		DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - "
+			  "Returned: %llx- Expected: 0x%x\n",
+			  (unsigned long long)val64, MDIO_CTRL1_SPEED10G);
 		return;
 	}
 
 	/* Loading the DOM register to MDIO register */
 	addr = 0xA100;
-	s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev);
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	s2io_mdio_write(MDIO_MMD_PMAPMD, addr, val16, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
 
 	/* Reading the Alarm flags */
 	addr = 0xA070;
 	val64 = 0x0;
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
 
 	flag = CHECKBIT(val64, 0x7);
 	type = 1;
-	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high,
-				&stat_info->xpak_stat.xpak_regs_stat,
-				0x0, flag, type);
+	s2io_chk_xpak_counter(&xstats->alarm_transceiver_temp_high,
+			      &xstats->xpak_regs_stat,
+			      0x0, flag, type);
 
-	if(CHECKBIT(val64, 0x6))
-		stat_info->xpak_stat.alarm_transceiver_temp_low++;
+	if (CHECKBIT(val64, 0x6))
+		xstats->alarm_transceiver_temp_low++;
 
 	flag = CHECKBIT(val64, 0x3);
 	type = 2;
-	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high,
-				&stat_info->xpak_stat.xpak_regs_stat,
-				0x2, flag, type);
+	s2io_chk_xpak_counter(&xstats->alarm_laser_bias_current_high,
+			      &xstats->xpak_regs_stat,
+			      0x2, flag, type);
 
-	if(CHECKBIT(val64, 0x2))
-		stat_info->xpak_stat.alarm_laser_bias_current_low++;
+	if (CHECKBIT(val64, 0x2))
+		xstats->alarm_laser_bias_current_low++;
 
 	flag = CHECKBIT(val64, 0x1);
 	type = 3;
-	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high,
-				&stat_info->xpak_stat.xpak_regs_stat,
-				0x4, flag, type);
+	s2io_chk_xpak_counter(&xstats->alarm_laser_output_power_high,
+			      &xstats->xpak_regs_stat,
+			      0x4, flag, type);
 
-	if(CHECKBIT(val64, 0x0))
-		stat_info->xpak_stat.alarm_laser_output_power_low++;
+	if (CHECKBIT(val64, 0x0))
+		xstats->alarm_laser_output_power_low++;
 
 	/* Reading the Warning flags */
 	addr = 0xA074;
 	val64 = 0x0;
-	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMAPMD, addr, dev);
 
-	if(CHECKBIT(val64, 0x7))
-		stat_info->xpak_stat.warn_transceiver_temp_high++;
+	if (CHECKBIT(val64, 0x7))
+		xstats->warn_transceiver_temp_high++;
 
-	if(CHECKBIT(val64, 0x6))
-		stat_info->xpak_stat.warn_transceiver_temp_low++;
+	if (CHECKBIT(val64, 0x6))
+		xstats->warn_transceiver_temp_low++;
 
-	if(CHECKBIT(val64, 0x3))
-		stat_info->xpak_stat.warn_laser_bias_current_high++;
+	if (CHECKBIT(val64, 0x3))
+		xstats->warn_laser_bias_current_high++;
 
-	if(CHECKBIT(val64, 0x2))
-		stat_info->xpak_stat.warn_laser_bias_current_low++;
+	if (CHECKBIT(val64, 0x2))
+		xstats->warn_laser_bias_current_low++;
 
-	if(CHECKBIT(val64, 0x1))
-		stat_info->xpak_stat.warn_laser_output_power_high++;
+	if (CHECKBIT(val64, 0x1))
+		xstats->warn_laser_output_power_high++;
 
-	if(CHECKBIT(val64, 0x0))
-		stat_info->xpak_stat.warn_laser_output_power_low++;
-}
-
-/**
- *  alarm_intr_handler - Alarm Interrrupt handler
- *  @nic: device private variable
- *  Description: If the interrupt was neither because of Rx packet or Tx
- *  complete, this function is called. If the interrupt was to indicate
- *  a loss of link, the OSM link status handler is invoked for any other
- *  alarm interrupt the block that raised the interrupt is displayed
- *  and a H/W reset is issued.
- *  Return Value:
- *  NONE
-*/
-
-static void alarm_intr_handler(struct s2io_nic *nic)
-{
-	struct net_device *dev = (struct net_device *) nic->dev;
-	struct XENA_dev_config __iomem *bar0 = nic->bar0;
-	register u64 val64 = 0, err_reg = 0;
-	u64 cnt;
-	int i;
-	if (atomic_read(&nic->card_state) == CARD_DOWN)
-		return;
-	if ((nic->pdev->error_state != pci_channel_io_normal) &&
-	    (nic->pdev->error_state != 0))
-		return;
-	nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
-	/* Handling the XPAK counters update */
-	if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
-		/* waiting for an hour */
-		nic->mac_control.stats_info->xpak_stat.xpak_timer_count++;
-	} else {
-		s2io_updt_xpak_counter(dev);
-		/* reset the count to zero */
-		nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0;
-	}
-
-	/* Handling link status change error Intr */
-	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
-		err_reg = readq(&bar0->mac_rmac_err_reg);
-		writeq(err_reg, &bar0->mac_rmac_err_reg);
-		if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
-			schedule_work(&nic->set_link_task);
-		}
-	}
-
-	/* Handling Ecc errors */
-	val64 = readq(&bar0->mc_err_reg);
-	writeq(val64, &bar0->mc_err_reg);
-	if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
-		if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
-			nic->mac_control.stats_info->sw_stat.
-				double_ecc_errs++;
-			DBG_PRINT(INIT_DBG, "%s: Device indicates ",
-				  dev->name);
-			DBG_PRINT(INIT_DBG, "double ECC error!!\n");
-			if (nic->device_type != XFRAME_II_DEVICE) {
-				/* Reset XframeI only if critical error */
-				if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
-					     MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
-					netif_stop_queue(dev);
-					schedule_work(&nic->rst_timer_task);
-					nic->mac_control.stats_info->sw_stat.
-							soft_reset_cnt++;
-				}
-			}
-		} else {
-			nic->mac_control.stats_info->sw_stat.
-				single_ecc_errs++;
-		}
-	}
-
-	/* In case of a serious error, the device will be Reset. */
-	val64 = readq(&bar0->serr_source);
-	if (val64 & SERR_SOURCE_ANY) {
-		nic->mac_control.stats_info->sw_stat.serious_err_cnt++;
-		DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
-		DBG_PRINT(ERR_DBG, "serious error %llx!!\n",
-			  (unsigned long long)val64);
-		netif_stop_queue(dev);
-		schedule_work(&nic->rst_timer_task);
-		nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
-	}
-
-	/*
-	 * Also as mentioned in the latest Errata sheets if the PCC_FB_ECC
-	 * Error occurs, the adapter will be recycled by disabling the
-	 * adapter enable bit and enabling it again after the device
-	 * becomes Quiescent.
-	 */
-	val64 = readq(&bar0->pcc_err_reg);
-	writeq(val64, &bar0->pcc_err_reg);
-	if (val64 & PCC_FB_ECC_DB_ERR) {
-		u64 ac = readq(&bar0->adapter_control);
-		ac &= ~(ADAPTER_CNTL_EN);
-		writeq(ac, &bar0->adapter_control);
-		ac = readq(&bar0->adapter_control);
-		schedule_work(&nic->set_link_task);
-	}
-	/* Check for data parity error */
-	val64 = readq(&bar0->pic_int_status);
-	if (val64 & PIC_INT_GPIO) {
-		val64 = readq(&bar0->gpio_int_reg);
-		if (val64 & GPIO_INT_REG_DP_ERR_INT) {
-			nic->mac_control.stats_info->sw_stat.parity_err_cnt++;
-			schedule_work(&nic->rst_timer_task);
-			nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
-		}
-	}
-
-	/* Check for ring full counter */
-	if (nic->device_type & XFRAME_II_DEVICE) {
-		val64 = readq(&bar0->ring_bump_counter1);
-		for (i=0; i<4; i++) {
-			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
-			cnt >>= 64 - ((i+1)*16);
-			nic->mac_control.stats_info->sw_stat.ring_full_cnt
-				+= cnt;
-		}
-
-		val64 = readq(&bar0->ring_bump_counter2);
-		for (i=0; i<4; i++) {
-			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
-			cnt >>= 64 - ((i+1)*16);
-			nic->mac_control.stats_info->sw_stat.ring_full_cnt
-				+= cnt;
-		}
-	}
-
-	/* Other type of interrupts are not being handled now,  TODO */
+	if (CHECKBIT(val64, 0x0))
+		xstats->warn_laser_output_power_low++;
 }
 
 /**
@@ -3314,7 +3404,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  */
 
 static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
-				int bit_state)
+				 int bit_state)
 {
 	int ret = FAILURE, cnt = 0, delay = 1;
 	u64 val64;
@@ -3336,7 +3426,7 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
 			}
 		}
 
-		if(in_interrupt())
+		if (in_interrupt())
 			mdelay(delay);
 		else
 			msleep(delay);
@@ -3376,7 +3466,7 @@ static u16 check_pci_device_id(u16 id)
  *  void.
  */
 
-static void s2io_reset(struct s2io_nic * sp)
+static void s2io_reset(struct s2io_nic *sp)
 {
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64;
@@ -3385,32 +3475,33 @@ static void s2io_reset(struct s2io_nic * sp)
 	u16 val16;
 	unsigned long long up_cnt, down_cnt, up_time, down_time, reset_cnt;
 	unsigned long long mem_alloc_cnt, mem_free_cnt, watchdog_cnt;
+	struct stat_block *stats;
+	struct swStat *swstats;
 
-	DBG_PRINT(INIT_DBG,"%s - Resetting XFrame card %s\n",
-			__FUNCTION__, sp->dev->name);
+	DBG_PRINT(INIT_DBG, "%s: Resetting XFrame card %s\n",
+		  __func__, sp->dev->name);
 
 	/* Back up  the PCI-X CMD reg, dont want to lose MMRBC, OST settings */
 	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));
 
 	val64 = SW_RESET_ALL;
 	writeq(val64, &bar0->sw_reset);
-	if (strstr(sp->product_name, "CX4")) {
+	if (strstr(sp->product_name, "CX4"))
 		msleep(750);
-	}
 	msleep(250);
 	for (i = 0; i < S2IO_MAX_PCI_CONFIG_SPACE_REINIT; i++) {
 
 		/* Restore the PCI state saved during initialization. */
 		pci_restore_state(sp->pdev);
+		pci_save_state(sp->pdev);
 		pci_read_config_word(sp->pdev, 0x2, &val16);
 		if (check_pci_device_id(val16) != (u16)PCI_ANY_ID)
 			break;
 		msleep(200);
 	}
 
-	if (check_pci_device_id(val16) == (u16)PCI_ANY_ID) {
-		DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __FUNCTION__);
-	}
+	if (check_pci_device_id(val16) == (u16)PCI_ANY_ID)
+		DBG_PRINT(ERR_DBG, "%s SW_Reset failed!\n", __func__);
 
 	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, pci_cmd);
 
@@ -3419,6 +3510,9 @@ static void s2io_reset(struct s2io_nic * sp)
 	/* Set swapper to enable I/O register access */
 	s2io_set_swapper(sp);
 
+	/* restore mac_addr entries */
+	do_s2io_restore_unicast_mc(sp);
+
 	/* Restore the MSIX table entries from local variables */
 	restore_xmsi_data(sp);
 
@@ -3431,31 +3525,36 @@ static void s2io_reset(struct s2io_nic * sp)
 		pci_write_config_dword(sp->pdev, 0x68, 0x7C);
 
 		/* Clearing PCI_STATUS error reflected here */
-		writeq(BIT(62), &bar0->txpic_int_reg);
+		writeq(s2BIT(62), &bar0->txpic_int_reg);
 	}
 
-	/* Reset device statistics buffer */
-	memset(&sp->stats_buffer, 0, sizeof (struct s2io_stats_buffer));
+	/* Reset device statistics */
+	memset(&sp->stats_buffer, 0, sizeof(struct s2io_stats_buffer));
+
+	stats = sp->mac_control.stats_info;
+	swstats = &stats->sw_stat;
 
-	up_cnt = sp->mac_control.stats_info->sw_stat.link_up_cnt;
-	down_cnt = sp->mac_control.stats_info->sw_stat.link_down_cnt;
-	up_time = sp->mac_control.stats_info->sw_stat.link_up_time;
-	down_time = sp->mac_control.stats_info->sw_stat.link_down_time;
-	reset_cnt = sp->mac_control.stats_info->sw_stat.soft_reset_cnt;
-	mem_alloc_cnt = sp->mac_control.stats_info->sw_stat.mem_allocated;
-	mem_free_cnt = sp->mac_control.stats_info->sw_stat.mem_freed;
-	watchdog_cnt = sp->mac_control.stats_info->sw_stat.watchdog_timer_cnt;
 	/* save link up/down time/cnt, reset/memory/watchdog cnt */
-	memset(sp->mac_control.stats_info, 0, sizeof(struct stat_block));
+	up_cnt = swstats->link_up_cnt;
+	down_cnt = swstats->link_down_cnt;
+	up_time = swstats->link_up_time;
+	down_time = swstats->link_down_time;
+	reset_cnt = swstats->soft_reset_cnt;
+	mem_alloc_cnt = swstats->mem_allocated;
+	mem_free_cnt = swstats->mem_freed;
+	watchdog_cnt = swstats->watchdog_timer_cnt;
+
+	memset(stats, 0, sizeof(struct stat_block));
+
 	/* restore link up/down time/cnt, reset/memory/watchdog cnt */
-	sp->mac_control.stats_info->sw_stat.link_up_cnt = up_cnt;
-	sp->mac_control.stats_info->sw_stat.link_down_cnt = down_cnt;
-	sp->mac_control.stats_info->sw_stat.link_up_time = up_time;
-	sp->mac_control.stats_info->sw_stat.link_down_time = down_time;
-	sp->mac_control.stats_info->sw_stat.soft_reset_cnt = reset_cnt;
-	sp->mac_control.stats_info->sw_stat.mem_allocated = mem_alloc_cnt;
-	sp->mac_control.stats_info->sw_stat.mem_freed = mem_free_cnt;
-	sp->mac_control.stats_info->sw_stat.watchdog_timer_cnt = watchdog_cnt;
+	swstats->link_up_cnt = up_cnt;
+	swstats->link_down_cnt = down_cnt;
+	swstats->link_up_time = up_time;
+	swstats->link_down_time = down_time;
+	swstats->soft_reset_cnt = reset_cnt;
+	swstats->mem_allocated = mem_alloc_cnt;
+	swstats->mem_freed = mem_free_cnt;
+	swstats->watchdog_timer_cnt = watchdog_cnt;
 
 	/* SXE-002: Configure link and activity LED to turn it off */
 	subid = sp->pdev->subsystem_device;
@@ -3477,10 +3576,7 @@ static void s2io_reset(struct s2io_nic * sp)
 		writeq(val64, &bar0->pcc_err_reg);
 	}
 
-	/* restore the previously assigned mac address */
-	s2io_set_mac_addr(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr);
-
-	sp->device_enabled_once = FALSE;
+	sp->device_enabled_once = false;
 }
 
 /**
@@ -3493,7 +3589,7 @@ static void s2io_reset(struct s2io_nic * sp)
  *  SUCCESS on success and FAILURE on failure.
  */
 
-static int s2io_set_swapper(struct s2io_nic * sp)
+static int s2io_set_swapper(struct s2io_nic *sp)
 {
 	struct net_device *dev = sp->dev;
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -3512,7 +3608,7 @@ static int s2io_set_swapper(struct s2io_nic * sp)
 				0x4200004242000042ULL,  /* FE=0, SE=1 */
 				0};                     /* FE=0, SE=0 */
 
-		while(i<4) {
+		while (i < 4) {
 			writeq(value[i], &bar0->swapper_ctrl);
 			val64 = readq(&bar0->pif_rd_swapper_fb);
 			if (val64 == 0x0123456789ABCDEFULL)
@@ -3520,10 +3616,9 @@ static int s2io_set_swapper(struct s2io_nic * sp)
 			i++;
 		}
 		if (i == 4) {
-			DBG_PRINT(ERR_DBG, "%s: Endian settings are wrong, ",
-				dev->name);
-			DBG_PRINT(ERR_DBG, "feedback read %llx\n",
-				(unsigned long long) val64);
+			DBG_PRINT(ERR_DBG, "%s: Endian settings are wrong, "
+				  "feedback read %llx\n",
+				  dev->name, (unsigned long long)val64);
 			return FAILURE;
 		}
 		valr = value[i];
@@ -3535,47 +3630,48 @@ static int s2io_set_swapper(struct s2io_nic * sp)
 	writeq(valt, &bar0->xmsi_address);
 	val64 = readq(&bar0->xmsi_address);
 
-	if(val64 != valt) {
+	if (val64 != valt) {
 		int i = 0;
 		u64 value[] = { 0x00C3C30000C3C300ULL,  /* FE=1, SE=1 */
 				0x0081810000818100ULL,  /* FE=1, SE=0 */
 				0x0042420000424200ULL,  /* FE=0, SE=1 */
 				0};                     /* FE=0, SE=0 */
 
-		while(i<4) {
+		while (i < 4) {
 			writeq((value[i] | valr), &bar0->swapper_ctrl);
 			writeq(valt, &bar0->xmsi_address);
 			val64 = readq(&bar0->xmsi_address);
-			if(val64 == valt)
+			if (val64 == valt)
 				break;
 			i++;
 		}
-		if(i == 4) {
+		if (i == 4) {
 			unsigned long long x = val64;
-			DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr ");
-			DBG_PRINT(ERR_DBG, "reads:0x%llx\n", x);
+			DBG_PRINT(ERR_DBG,
+				  "Write failed, Xmsi_addr reads:0x%llx\n", x);
 			return FAILURE;
 		}
 	}
 	val64 = readq(&bar0->swapper_ctrl);
 	val64 &= 0xFFFF000000000000ULL;
 
-#ifdef  __BIG_ENDIAN
+#ifdef __BIG_ENDIAN
 	/*
 	 * The device by default set to a big endian format, so a
 	 * big endian driver need not set anything.
 	 */
 	val64 |= (SWAPPER_CTRL_TXP_FE |
-		 SWAPPER_CTRL_TXP_SE |
-		 SWAPPER_CTRL_TXD_R_FE |
-		 SWAPPER_CTRL_TXD_W_FE |
-		 SWAPPER_CTRL_TXF_R_FE |
-		 SWAPPER_CTRL_RXD_R_FE |
-		 SWAPPER_CTRL_RXD_W_FE |
-		 SWAPPER_CTRL_RXF_W_FE |
-		 SWAPPER_CTRL_XMSI_FE |
-		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
-	if (sp->intr_type == INTA)
+		  SWAPPER_CTRL_TXP_SE |
+		  SWAPPER_CTRL_TXD_R_FE |
+		  SWAPPER_CTRL_TXD_W_FE |
+		  SWAPPER_CTRL_TXF_R_FE |
+		  SWAPPER_CTRL_RXD_R_FE |
+		  SWAPPER_CTRL_RXD_W_FE |
+		  SWAPPER_CTRL_RXF_W_FE |
+		  SWAPPER_CTRL_XMSI_FE |
+		  SWAPPER_CTRL_STATS_FE |
+		  SWAPPER_CTRL_STATS_SE);
+	if (sp->config.intr_type == INTA)
 		val64 |= SWAPPER_CTRL_XMSI_SE;
 	writeq(val64, &bar0->swapper_ctrl);
 #else
@@ -3585,20 +3681,21 @@ static int s2io_set_swapper(struct s2io_nic * sp)
 	 * we want to set.
 	 */
 	val64 |= (SWAPPER_CTRL_TXP_FE |
-		 SWAPPER_CTRL_TXP_SE |
-		 SWAPPER_CTRL_TXD_R_FE |
-		 SWAPPER_CTRL_TXD_R_SE |
-		 SWAPPER_CTRL_TXD_W_FE |
-		 SWAPPER_CTRL_TXD_W_SE |
-		 SWAPPER_CTRL_TXF_R_FE |
-		 SWAPPER_CTRL_RXD_R_FE |
-		 SWAPPER_CTRL_RXD_R_SE |
-		 SWAPPER_CTRL_RXD_W_FE |
-		 SWAPPER_CTRL_RXD_W_SE |
-		 SWAPPER_CTRL_RXF_W_FE |
-		 SWAPPER_CTRL_XMSI_FE |
-		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
-	if (sp->intr_type == INTA)
+		  SWAPPER_CTRL_TXP_SE |
+		  SWAPPER_CTRL_TXD_R_FE |
+		  SWAPPER_CTRL_TXD_R_SE |
+		  SWAPPER_CTRL_TXD_W_FE |
+		  SWAPPER_CTRL_TXD_W_SE |
+		  SWAPPER_CTRL_TXF_R_FE |
+		  SWAPPER_CTRL_RXD_R_FE |
+		  SWAPPER_CTRL_RXD_R_SE |
+		  SWAPPER_CTRL_RXD_W_FE |
+		  SWAPPER_CTRL_RXD_W_SE |
+		  SWAPPER_CTRL_RXF_W_FE |
+		  SWAPPER_CTRL_XMSI_FE |
+		  SWAPPER_CTRL_STATS_FE |
+		  SWAPPER_CTRL_STATS_SE);
+	if (sp->config.intr_type == INTA)
 		val64 |= SWAPPER_CTRL_XMSI_SE;
 	writeq(val64, &bar0->swapper_ctrl);
 #endif
@@ -3611,10 +3708,9 @@ static int s2io_set_swapper(struct s2io_nic * sp)
 	val64 = readq(&bar0->pif_rd_swapper_fb);
 	if (val64 != 0x0123456789ABCDEFULL) {
 		/* Endian settings are incorrect, calls for another dekko. */
-		DBG_PRINT(ERR_DBG, "%s: Endian settings are wrong, ",
-			  dev->name);
-		DBG_PRINT(ERR_DBG, "feedback read %llx\n",
-			  (unsigned long long) val64);
+		DBG_PRINT(ERR_DBG,
+			  "%s: Endian settings are wrong, feedback read %llx\n",
+			  dev->name, (unsigned long long)val64);
 		return FAILURE;
 	}
 
@@ -3629,11 +3725,11 @@ static int wait_for_msix_trans(struct s2io_nic *nic, int i)
 
 	do {
 		val64 = readq(&bar0->xmsi_access);
-		if (!(val64 & BIT(15)))
+		if (!(val64 & s2BIT(15)))
 			break;
 		mdelay(1);
 		cnt++;
-	} while(cnt < 5);
+	} while (cnt < 5);
 	if (cnt == 5) {
 		DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
 		ret = 1;
@@ -3646,15 +3742,20 @@ static void restore_xmsi_data(struct s2io_nic *nic)
 {
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
 	u64 val64;
-	int i;
+	int i, msix_index;
+
+	if (nic->device_type == XFRAME_I_DEVICE)
+		return;
 
-	for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
+	for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+		msix_index = (i) ? ((i-1) * 8 + 1) : 0;
 		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));
+		val64 = (s2BIT(7) | s2BIT(15) | vBIT(msix_index, 26, 6));
 		writeq(val64, &bar0->xmsi_access);
-		if (wait_for_msix_trans(nic, i)) {
-			DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+		if (wait_for_msix_trans(nic, msix_index)) {
+			DBG_PRINT(ERR_DBG, "%s: index: %d failed\n",
+				  __func__, msix_index);
 			continue;
 		}
 	}
@@ -3664,14 +3765,19 @@ static void store_xmsi_data(struct s2io_nic *nic)
 {
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
 	u64 val64, addr, data;
-	int i;
+	int i, msix_index;
+
+	if (nic->device_type == XFRAME_I_DEVICE)
+		return;
 
 	/* Store and display */
-	for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
-		val64 = (BIT(15) | vBIT(i, 26, 6));
+	for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+		msix_index = (i) ? ((i-1) * 8 + 1) : 0;
+		val64 = (s2BIT(15) | vBIT(msix_index, 26, 6));
 		writeq(val64, &bar0->xmsi_access);
-		if (wait_for_msix_trans(nic, i)) {
-			DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
+		if (wait_for_msix_trans(nic, msix_index)) {
+			DBG_PRINT(ERR_DBG, "%s: index: %d failed\n",
+				  __func__, msix_index);
 			continue;
 		}
 		addr = readq(&bar0->xmsi_address);
@@ -3686,99 +3792,74 @@ static void store_xmsi_data(struct s2io_nic *nic)
 static int s2io_enable_msi_x(struct s2io_nic *nic)
 {
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
-	u64 tx_mat, rx_mat;
+	u64 rx_mat;
 	u16 msi_control; /* Temp variable */
 	int ret, i, j, msix_indx = 1;
-
-	nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
-			       GFP_KERNEL);
-	if (nic->entries == NULL) {
-		DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \
-			__FUNCTION__);
-		nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
+	int size;
+	struct stat_block *stats = nic->mac_control.stats_info;
+	struct swStat *swstats = &stats->sw_stat;
+
+	size = nic->num_entries * sizeof(struct msix_entry);
+	nic->entries = kzalloc(size, GFP_KERNEL);
+	if (!nic->entries) {
+		DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n",
+			  __func__);
+		swstats->mem_alloc_fail_cnt++;
 		return -ENOMEM;
 	}
-	nic->mac_control.stats_info->sw_stat.mem_allocated 
-		+= (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
-	memset(nic->entries, 0,MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
-
-	nic->s2io_entries =
-		kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
-				   GFP_KERNEL);
-	if (nic->s2io_entries == NULL) {
-		DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", 
-			__FUNCTION__);
-		nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
+	swstats->mem_allocated += size;
+
+	size = nic->num_entries * sizeof(struct s2io_msix_entry);
+	nic->s2io_entries = kzalloc(size, GFP_KERNEL);
+	if (!nic->s2io_entries) {
+		DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n",
+			  __func__);
+		swstats->mem_alloc_fail_cnt++;
 		kfree(nic->entries);
-		nic->mac_control.stats_info->sw_stat.mem_freed 
-			+= (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+		swstats->mem_freed
+			+= (nic->num_entries * sizeof(struct msix_entry));
 		return -ENOMEM;
 	}
-	 nic->mac_control.stats_info->sw_stat.mem_allocated 
-		+= (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
-	memset(nic->s2io_entries, 0,
-	       MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+	swstats->mem_allocated += size;
+
+	nic->entries[0].entry = 0;
+	nic->s2io_entries[0].entry = 0;
+	nic->s2io_entries[0].in_use = MSIX_FLG;
+	nic->s2io_entries[0].type = MSIX_ALARM_TYPE;
+	nic->s2io_entries[0].arg = &nic->mac_control.fifos;
 
-	for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
-		nic->entries[i].entry = i;
-		nic->s2io_entries[i].entry = i;
+	for (i = 1; i < nic->num_entries; i++) {
+		nic->entries[i].entry = ((i - 1) * 8) + 1;
+		nic->s2io_entries[i].entry = ((i - 1) * 8) + 1;
 		nic->s2io_entries[i].arg = NULL;
 		nic->s2io_entries[i].in_use = 0;
 	}
 
-	tx_mat = readq(&bar0->tx_mat0_n[0]);
-	for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
-		tx_mat |= TX_MAT_SET(i, msix_indx);
-		nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
-		nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
-		nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
-	}
-	writeq(tx_mat, &bar0->tx_mat0_n[0]);
-
-	if (!nic->config.bimodal) {
-		rx_mat = readq(&bar0->rx_mat);
-		for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
-			rx_mat |= RX_MAT_SET(j, msix_indx);
-			nic->s2io_entries[msix_indx].arg 
-				= &nic->mac_control.rings[j];
-			nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
-			nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
-		}
-		writeq(rx_mat, &bar0->rx_mat);
-	} else {
-		tx_mat = readq(&bar0->tx_mat0_n[7]);
-		for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
-			tx_mat |= TX_MAT_SET(i, msix_indx);
-			nic->s2io_entries[msix_indx].arg 
-				= &nic->mac_control.rings[j];
-			nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
-			nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
-		}
-		writeq(tx_mat, &bar0->tx_mat0_n[7]);
+	rx_mat = readq(&bar0->rx_mat);
+	for (j = 0; j < nic->config.rx_ring_num; j++) {
+		rx_mat |= RX_MAT_SET(j, msix_indx);
+		nic->s2io_entries[j+1].arg = &nic->mac_control.rings[j];
+		nic->s2io_entries[j+1].type = MSIX_RING_TYPE;
+		nic->s2io_entries[j+1].in_use = MSIX_FLG;
+		msix_indx += 8;
 	}
+	writeq(rx_mat, &bar0->rx_mat);
+	readq(&bar0->rx_mat);
 
-	nic->avail_msix_vectors = 0;
-	ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+	ret = pci_enable_msix(nic->pdev, nic->entries, nic->num_entries);
 	/* We fail init if error or we get less vectors than min required */
-	if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) {
-		nic->avail_msix_vectors = ret;
-		ret = pci_enable_msix(nic->pdev, nic->entries, ret);
-	}
 	if (ret) {
-		DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
+		DBG_PRINT(ERR_DBG, "Enabling MSI-X failed\n");
 		kfree(nic->entries);
-		nic->mac_control.stats_info->sw_stat.mem_freed 
-			+= (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+		swstats->mem_freed += nic->num_entries *
+			sizeof(struct msix_entry);
 		kfree(nic->s2io_entries);
-		nic->mac_control.stats_info->sw_stat.mem_freed 
-		+= (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+		swstats->mem_freed += nic->num_entries *
+			sizeof(struct s2io_msix_entry);
 		nic->entries = NULL;
 		nic->s2io_entries = NULL;
-		nic->avail_msix_vectors = 0;
 		return -ENOMEM;
 	}
-	if (!nic->avail_msix_vectors)
-		nic->avail_msix_vectors = MAX_REQUESTED_MSI_X;
 
 	/*
 	 * To enable MSI-X, MSI also needs to be enabled, due to a bug
@@ -3791,6 +3872,92 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
 	return 0;
 }
 
+/* Handle software interrupt used during MSI(X) test */
+static irqreturn_t s2io_test_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct s2io_nic *sp = dev_id;
+
+	sp->msi_detected = 1;
+	wake_up(&sp->msi_wait);
+
+	return IRQ_HANDLED;
+}
+
+/* Test interrupt path by forcing a a software IRQ */
+static int s2io_test_msi(struct s2io_nic *sp)
+{
+	struct pci_dev *pdev = sp->pdev;
+	struct XENA_dev_config __iomem *bar0 = sp->bar0;
+	int err;
+	u64 val64, saved64;
+
+	err = request_irq(sp->entries[1].vector, s2io_test_intr, 0,
+			  sp->name, sp);
+	if (err) {
+		DBG_PRINT(ERR_DBG, "%s: PCI %s: cannot assign irq %d\n",
+			  sp->dev->name, pci_name(pdev), pdev->irq);
+		return err;
+	}
+
+	init_waitqueue_head(&sp->msi_wait);
+	sp->msi_detected = 0;
+
+	saved64 = val64 = readq(&bar0->scheduled_int_ctrl);
+	val64 |= SCHED_INT_CTRL_ONE_SHOT;
+	val64 |= SCHED_INT_CTRL_TIMER_EN;
+	val64 |= SCHED_INT_CTRL_INT2MSI(1);
+	writeq(val64, &bar0->scheduled_int_ctrl);
+
+	wait_event_timeout(sp->msi_wait, sp->msi_detected, HZ/10);
+
+	if (!sp->msi_detected) {
+		/* MSI(X) test failed, go back to INTx mode */
+		DBG_PRINT(ERR_DBG, "%s: PCI %s: No interrupt was generated "
+			  "using MSI(X) during test\n",
+			  sp->dev->name, pci_name(pdev));
+
+		err = -EOPNOTSUPP;
+	}
+
+	free_irq(sp->entries[1].vector, sp);
+
+	writeq(saved64, &bar0->scheduled_int_ctrl);
+
+	return err;
+}
+
+static void remove_msix_isr(struct s2io_nic *sp)
+{
+	int i;
+	u16 msi_control;
+
+	for (i = 0; i < sp->num_entries; i++) {
+		if (sp->s2io_entries[i].in_use == MSIX_REGISTERED_SUCCESS) {
+			int vector = sp->entries[i].vector;
+			void *arg = sp->s2io_entries[i].arg;
+			free_irq(vector, arg);
+		}
+	}
+
+	kfree(sp->entries);
+	kfree(sp->s2io_entries);
+	sp->entries = NULL;
+	sp->s2io_entries = NULL;
+
+	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);
+}
+
+static void remove_inta_isr(struct s2io_nic *sp)
+{
+	struct net_device *dev = sp->dev;
+
+	free_irq(sp->pdev->irq, dev);
+}
+
 /* ********************************************************* *
  * Functions defined below concern the OS part of the driver *
  * ********************************************************* */
@@ -3809,7 +3976,8 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
 
 static int s2io_open(struct net_device *dev)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
+	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 	int err = 0;
 
 	/*
@@ -3827,27 +3995,26 @@ static int s2io_open(struct net_device *dev)
 		goto hw_init_failed;
 	}
 
-	if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
+	if (do_s2io_prog_unicast(dev, dev->dev_addr) == FAILURE) {
 		DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n");
 		s2io_card_down(sp);
 		err = -ENODEV;
 		goto hw_init_failed;
 	}
-
-	netif_start_queue(dev);
+	s2io_start_all_tx_queue(sp);
 	return 0;
 
 hw_init_failed:
-	if (sp->intr_type == MSI_X) {
+	if (sp->config.intr_type == MSI_X) {
 		if (sp->entries) {
 			kfree(sp->entries);
-			sp->mac_control.stats_info->sw_stat.mem_freed 
-			+= (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
+			swstats->mem_freed += sp->num_entries *
+				sizeof(struct msix_entry);
 		}
 		if (sp->s2io_entries) {
 			kfree(sp->s2io_entries);
-			sp->mac_control.stats_info->sw_stat.mem_freed 
-			+= (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
+			swstats->mem_freed += sp->num_entries *
+				sizeof(struct s2io_msix_entry);
 		}
 	}
 	return err;
@@ -3868,10 +4035,25 @@ hw_init_failed:
 
 static int s2io_close(struct net_device *dev)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
+	struct config_param *config = &sp->config;
+	u64 tmp64;
+	int offset;
+
+	/* Return if the device is already closed               *
+	 *  Can happen when s2io_card_up failed in change_mtu    *
+	 */
+	if (!is_s2io_card_up(sp))
+		return 0;
+
+	s2io_stop_all_tx_queue(sp);
+	/* delete all populated mac entries */
+	for (offset = 1; offset < config->max_mc_addr; offset++) {
+		tmp64 = do_s2io_read_unicast_mc(sp, offset);
+		if (tmp64 != S2IO_DISABLE_MAC_ENTRY)
+			do_s2io_delete_unicast_mc(sp, tmp64);
+	}
 
-	netif_stop_queue(dev);
-	/* Reset card, kill tasklet and free Tx and Rx buffers. */
 	s2io_card_down(sp);
 
 	return 0;
@@ -3890,82 +4072,130 @@ static int s2io_close(struct net_device *dev)
  *  0 on success & 1 on failure.
  */
 
-static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
 	register u64 val64;
 	struct TxD *txdp;
 	struct TxFIFO_element __iomem *tx_fifo;
-	unsigned long flags;
+	unsigned long flags = 0;
 	u16 vlan_tag = 0;
-	int vlan_priority = 0;
-	struct mac_info *mac_control;
-	struct config_param *config;
+	struct fifo_info *fifo = NULL;
+	int do_spin_lock = 1;
 	int offload_type;
-	struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
-
-	mac_control = &sp->mac_control;
-	config = &sp->config;
+	int enable_per_list_interrupt = 0;
+	struct config_param *config = &sp->config;
+	struct mac_info *mac_control = &sp->mac_control;
+	struct stat_block *stats = mac_control->stats_info;
+	struct swStat *swstats = &stats->sw_stat;
 
 	DBG_PRINT(TX_DBG, "%s: In Neterion Tx routine\n", dev->name);
 
 	if (unlikely(skb->len <= 0)) {
-		DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name);
+		DBG_PRINT(TX_DBG, "%s: Buffer has no data..\n", dev->name);
 		dev_kfree_skb_any(skb);
-		return 0;
-}
+		return NETDEV_TX_OK;
+	}
 
-	spin_lock_irqsave(&sp->tx_lock, flags);
-	if (atomic_read(&sp->card_state) == CARD_DOWN) {
+	if (!is_s2io_card_up(sp)) {
 		DBG_PRINT(TX_DBG, "%s: Card going down for reset\n",
 			  dev->name);
-		spin_unlock_irqrestore(&sp->tx_lock, flags);
 		dev_kfree_skb(skb);
-		return 0;
+		return NETDEV_TX_OK;
 	}
 
 	queue = 0;
-	/* Get Fifo number to Transmit based on vlan priority */
-	if (sp->vlgrp && vlan_tx_tag_present(skb)) {
+	if (sp->vlgrp && vlan_tx_tag_present(skb))
 		vlan_tag = vlan_tx_tag_get(skb);
-		vlan_priority = vlan_tag >> 13;
-		queue = config->fifo_mapping[vlan_priority];
+	if (sp->config.tx_steering_type == TX_DEFAULT_STEERING) {
+		if (skb->protocol == htons(ETH_P_IP)) {
+			struct iphdr *ip;
+			struct tcphdr *th;
+			ip = ip_hdr(skb);
+
+			if ((ip->frag_off & htons(IP_OFFSET|IP_MF)) == 0) {
+				th = (struct tcphdr *)(((unsigned char *)ip) +
+						       ip->ihl*4);
+
+				if (ip->protocol == IPPROTO_TCP) {
+					queue_len = sp->total_tcp_fifos;
+					queue = (ntohs(th->source) +
+						 ntohs(th->dest)) &
+						sp->fifo_selector[queue_len - 1];
+					if (queue >= queue_len)
+						queue = queue_len - 1;
+				} else if (ip->protocol == IPPROTO_UDP) {
+					queue_len = sp->total_udp_fifos;
+					queue = (ntohs(th->source) +
+						 ntohs(th->dest)) &
+						sp->fifo_selector[queue_len - 1];
+					if (queue >= queue_len)
+						queue = queue_len - 1;
+					queue += sp->udp_fifo_idx;
+					if (skb->len > 1024)
+						enable_per_list_interrupt = 1;
+					do_spin_lock = 0;
+				}
+			}
+		}
+	} else if (sp->config.tx_steering_type == TX_PRIORITY_STEERING)
+		/* get fifo number based on skb->priority value */
+		queue = config->fifo_mapping
+			[skb->priority & (MAX_TX_FIFOS - 1)];
+	fifo = &mac_control->fifos[queue];
+
+	if (do_spin_lock)
+		spin_lock_irqsave(&fifo->tx_lock, flags);
+	else {
+		if (unlikely(!spin_trylock_irqsave(&fifo->tx_lock, flags)))
+			return NETDEV_TX_LOCKED;
 	}
 
-	put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset;
-	get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset;
-	txdp = (struct TxD *) mac_control->fifos[queue].list_info[put_off].
-		list_virt_addr;
+	if (sp->config.multiq) {
+		if (__netif_subqueue_stopped(dev, fifo->fifo_no)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	} else if (unlikely(fifo->queue_state == FIFO_QUEUE_STOP)) {
+		if (netif_queue_stopped(dev)) {
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+	}
 
-	queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
+	put_off = (u16)fifo->tx_curr_put_info.offset;
+	get_off = (u16)fifo->tx_curr_get_info.offset;
+	txdp = (struct TxD *)fifo->list_info[put_off].list_virt_addr;
+
+	queue_len = fifo->tx_curr_put_info.fifo_len + 1;
 	/* Avoid "put" pointer going beyond "get" pointer */
 	if (txdp->Host_Control ||
-		   ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
+	    ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
 		DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 		dev_kfree_skb(skb);
-		spin_unlock_irqrestore(&sp->tx_lock, flags);
-		return 0;
+		spin_unlock_irqrestore(&fifo->tx_lock, flags);
+		return NETDEV_TX_OK;
 	}
 
 	offload_type = s2io_offload_type(skb);
-
 	if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
 		txdp->Control_1 |= TXD_TCP_LSO_EN;
 		txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(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);
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		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)) {
+	txdp->Control_2 |= TXD_INT_NUMBER(fifo->fifo_no);
+	if (enable_per_list_interrupt)
+		if (put_off & (queue_len >> 5))
+			txdp->Control_2 |= TXD_INT_TYPE_PER_LIST;
+	if (vlan_tag) {
 		txdp->Control_2 |= TXD_VLAN_ENABLE;
 		txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag);
 	}
@@ -3980,29 +4210,29 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 		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;
+		/* both variants do cpu_to_be64(be32_to_cpu(...)) */
+		fifo->ufo_in_band_v[put_off] =
+			(__force u64)skb_shinfo(skb)->ip6_frag_id;
 #else
-		sp->ufo_in_band_v[put_off] =
-				(u64)skb_shinfo(skb)->ip6_frag_id << 32;
+		fifo->ufo_in_band_v[put_off] =
+			(__force u64)skb_shinfo(skb)->ip6_frag_id << 32;
 #endif
-		txdp->Host_Control = (unsigned long)sp->ufo_in_band_v;
+		txdp->Host_Control = (unsigned long)fifo->ufo_in_band_v;
 		txdp->Buffer_Pointer = pci_map_single(sp->pdev,
-					sp->ufo_in_band_v,
-					sizeof(u64), PCI_DMA_TODEVICE);
-		if((txdp->Buffer_Pointer == 0) ||
-			(txdp->Buffer_Pointer == DMA_ERROR_CODE))
+						      fifo->ufo_in_band_v,
+						      sizeof(u64),
+						      PCI_DMA_TODEVICE);
+		if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer))
 			goto pci_map_failed;
 		txdp++;
 	}
 
-	txdp->Buffer_Pointer = pci_map_single
-	    (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
-	if((txdp->Buffer_Pointer == 0) ||
-		(txdp->Buffer_Pointer == DMA_ERROR_CODE))
+	txdp->Buffer_Pointer = pci_map_single(sp->pdev, skb->data,
+					      frg_len, PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(sp->pdev, txdp->Buffer_Pointer))
 		goto pci_map_failed;
 
-	txdp->Host_Control = (unsigned long) skb;
+	txdp->Host_Control = (unsigned long)skb;
 	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
 	if (offload_type == SKB_GSO_UDP)
 		txdp->Control_1 |= TXD_UFO_EN;
@@ -4015,9 +4245,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 		if (!frag->size)
 			continue;
 		txdp++;
-		txdp->Buffer_Pointer = (u64) pci_map_page
-		    (sp->pdev, frag->page, frag->page_offset,
-		     frag->size, PCI_DMA_TODEVICE);
+		txdp->Buffer_Pointer = (u64)pci_map_page(sp->pdev, frag->page,
+							 frag->page_offset,
+							 frag->size,
+							 PCI_DMA_TODEVICE);
 		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
 		if (offload_type == SKB_GSO_UDP)
 			txdp->Control_1 |= TXD_UFO_EN;
@@ -4028,7 +4259,7 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 		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;
+	val64 = fifo->list_info[put_off].list_phy_addr;
 	writeq(val64, &tx_fifo->TxDL_Pointer);
 
 	val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
@@ -4041,96 +4272,112 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 	mmiowb();
 
 	put_off++;
-	if (put_off == mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1)
+	if (put_off == fifo->tx_curr_put_info.fifo_len + 1)
 		put_off = 0;
-	mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
+	fifo->tx_curr_put_info.offset = put_off;
 
 	/* Avoid "put" pointer going beyond "get" pointer */
 	if (((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
-		sp->mac_control.stats_info->sw_stat.fifo_full_cnt++;
+		swstats->fifo_full_cnt++;
 		DBG_PRINT(TX_DBG,
 			  "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
 			  put_off, get_off);
-		netif_stop_queue(dev);
+		s2io_stop_tx_queue(sp, fifo->fifo_no);
 	}
-	mac_control->stats_info->sw_stat.mem_allocated += skb->truesize;
 	dev->trans_start = jiffies;
-	spin_unlock_irqrestore(&sp->tx_lock, flags);
+	swstats->mem_allocated += skb->truesize;
+	spin_unlock_irqrestore(&fifo->tx_lock, flags);
+
+	if (sp->config.intr_type == MSI_X)
+		tx_intr_handler(fifo);
+
+	return NETDEV_TX_OK;
 
-	return 0;
 pci_map_failed:
-	stats->pci_map_fail_cnt++;
-	netif_stop_queue(dev);
-	stats->mem_freed += skb->truesize;
+	swstats->pci_map_fail_cnt++;
+	s2io_stop_tx_queue(sp, fifo->fifo_no);
+	swstats->mem_freed += skb->truesize;
 	dev_kfree_skb(skb);
-	spin_unlock_irqrestore(&sp->tx_lock, flags);
-	return 0;
+	spin_unlock_irqrestore(&fifo->tx_lock, flags);
+	return NETDEV_TX_OK;
 }
 
 static void
 s2io_alarm_handle(unsigned long data)
 {
 	struct s2io_nic *sp = (struct s2io_nic *)data;
+	struct net_device *dev = sp->dev;
 
-	alarm_intr_handler(sp);
+	s2io_handle_errors(dev);
 	mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
 }
 
-static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n)
+static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id,
+					 struct pt_regs *regs)
 {
-	int rxb_size, level;
+	struct ring_info *ring = (struct ring_info *)dev_id;
+	struct s2io_nic *sp = ring->nic;
+	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
-	if (!sp->lro) {
-		rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
-		level = rx_buffer_level(sp, rxb_size, rng_n);
+	if (unlikely(!is_s2io_card_up(sp)))
+		return IRQ_HANDLED;
 
-		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(INFO_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);
+	if (sp->config.napi) {
+		u8 __iomem *addr = NULL;
+		u8 val8 = 0;
 
-	} else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
-			DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name);
-			DBG_PRINT(INFO_DBG, " in Rx Intr!!\n");
+		addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
+		addr += (7 - ring->ring_no);
+		val8 = (ring->ring_no == 0) ? 0x7f : 0xff;
+		writeb(val8, addr);
+		val8 = readb(addr);
+		napi_schedule(&ring->napi);
+	} else {
+		rx_intr_handler(ring, 0);
+		s2io_chk_rx_buffers(sp, ring);
 	}
-	return 0;
+
+	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id,
+					 struct pt_regs *regs)
 {
-	struct ring_info *ring = (struct ring_info *)dev_id;
-	struct s2io_nic *sp = ring->nic;
+	int i;
+	struct fifo_info *fifos = (struct fifo_info *)dev_id;
+	struct s2io_nic *sp = fifos->nic;
+	struct XENA_dev_config __iomem *bar0 = sp->bar0;
+	struct config_param *config  = &sp->config;
+	u64 reason;
 
-	atomic_inc(&sp->isr_cnt);
+	if (unlikely(!is_s2io_card_up(sp)))
+		return IRQ_NONE;
 
-	rx_intr_handler(ring);
-	s2io_chk_rx_buffers(sp, ring->ring_no);
+	reason = readq(&bar0->general_int_status);
+	if (unlikely(reason == S2IO_MINUS_ONE))
+		/* Nothing much can be done. Get out */
+		return IRQ_HANDLED;
 
-	atomic_dec(&sp->isr_cnt);
-	return IRQ_HANDLED;
-}
+	if (reason & (GEN_INTR_TXPIC | GEN_INTR_TXTRAFFIC)) {
+		writeq(S2IO_MINUS_ONE, &bar0->general_int_mask);
 
-static irqreturn_t
-s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct fifo_info *fifo = (struct fifo_info *)dev_id;
-	struct s2io_nic *sp = fifo->nic;
+		if (reason & GEN_INTR_TXPIC)
+			s2io_txpic_intr_handle(sp);
 
-	atomic_inc(&sp->isr_cnt);
-	tx_intr_handler(fifo);
-	atomic_dec(&sp->isr_cnt);
-	return IRQ_HANDLED;
+		if (reason & GEN_INTR_TXTRAFFIC)
+			writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
+
+		for (i = 0; i < config->tx_fifo_num; i++)
+			tx_intr_handler(&fifos[i]);
+
+		writeq(sp->general_int_mask, &bar0->general_int_mask);
+		readl(&bar0->general_int_status);
+		return IRQ_HANDLED;
+	}
+	/* The interrupt was not raised by us */
+	return IRQ_NONE;
 }
+
 static void s2io_txpic_intr_handle(struct s2io_nic *sp)
 {
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -4145,17 +4392,16 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp)
 			 * This is unstable state so clear both up/down
 			 * interrupt and adapter to re-evaluate the link state.
 			 */
-			val64 |=  GPIO_INT_REG_LINK_DOWN;
+			val64 |= GPIO_INT_REG_LINK_DOWN;
 			val64 |= GPIO_INT_REG_LINK_UP;
 			writeq(val64, &bar0->gpio_int_reg);
 			val64 = readq(&bar0->gpio_int_mask);
 			val64 &= ~(GPIO_INT_MASK_LINK_UP |
 				   GPIO_INT_MASK_LINK_DOWN);
 			writeq(val64, &bar0->gpio_int_mask);
-		}
-		else if (val64 & GPIO_INT_REG_LINK_UP) {
+		} else if (val64 & GPIO_INT_REG_LINK_UP) {
 			val64 = readq(&bar0->adapter_status);
-				/* Enable Adapter */
+			/* Enable Adapter */
 			val64 = readq(&bar0->adapter_control);
 			val64 |= ADAPTER_CNTL_EN;
 			writeq(val64, &bar0->adapter_control);
@@ -4174,7 +4420,7 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp)
 			val64 |= GPIO_INT_MASK_LINK_UP;
 			writeq(val64, &bar0->gpio_int_mask);
 
-		}else if (val64 & GPIO_INT_REG_LINK_DOWN) {
+		} else if (val64 & GPIO_INT_REG_LINK_DOWN) {
 			val64 = readq(&bar0->adapter_status);
 			s2io_link(sp, LINK_DOWN);
 			/* Link is down so unmaks link up interrupt */
@@ -4185,7 +4431,7 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp)
 
 			/* turn off LED */
 			val64 = readq(&bar0->adapter_control);
-			val64 = val64 &(~ADAPTER_LED_ON);
+			val64 = val64 & (~ADAPTER_LED_ON);
 			writeq(val64, &bar0->adapter_control);
 		}
 	}
@@ -4193,10 +4439,331 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp)
 }
 
 /**
+ *  do_s2io_chk_alarm_bit - Check for alarm and incrment the counter
+ *  @value: alarm bits
+ *  @addr: address value
+ *  @cnt: counter variable
+ *  Description: Check for alarm and increment the counter
+ *  Return Value:
+ *  1 - if alarm bit set
+ *  0 - if alarm bit is not set
+ */
+static int do_s2io_chk_alarm_bit(u64 value, void __iomem *addr,
+				 unsigned long long *cnt)
+{
+	u64 val64;
+	val64 = readq(addr);
+	if (val64 & value) {
+		writeq(val64, addr);
+		(*cnt)++;
+		return 1;
+	}
+	return 0;
+
+}
+
+/**
+ *  s2io_handle_errors - Xframe error indication handler
+ *  @nic: device private variable
+ *  Description: Handle alarms such as loss of link, single or
+ *  double ECC errors, critical and serious errors.
+ *  Return Value:
+ *  NONE
+ */
+static void s2io_handle_errors(void *dev_id)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct s2io_nic *sp = netdev_priv(dev);
+	struct XENA_dev_config __iomem *bar0 = sp->bar0;
+	u64 temp64 = 0, val64 = 0;
+	int i = 0;
+
+	struct swStat *sw_stat = &sp->mac_control.stats_info->sw_stat;
+	struct xpakStat *stats = &sp->mac_control.stats_info->xpak_stat;
+
+	if (!is_s2io_card_up(sp))
+		return;
+
+	if (pci_channel_offline(sp->pdev) && sp->pdev->error_state != 0)
+		return;
+
+	memset(&sw_stat->ring_full_cnt, 0,
+	       sizeof(sw_stat->ring_full_cnt));
+
+	/* Handling the XPAK counters update */
+	if (stats->xpak_timer_count < 72000) {
+		/* waiting for an hour */
+		stats->xpak_timer_count++;
+	} else {
+		s2io_updt_xpak_counter(dev);
+		/* reset the count to zero */
+		stats->xpak_timer_count = 0;
+	}
+
+	/* Handling link status change error Intr */
+	if (s2io_link_fault_indication(sp) == MAC_RMAC_ERR_TIMER) {
+		val64 = readq(&bar0->mac_rmac_err_reg);
+		writeq(val64, &bar0->mac_rmac_err_reg);
+		if (val64 & RMAC_LINK_STATE_CHANGE_INT)
+			schedule_work(&sp->set_link_task);
+	}
+
+	/* In case of a serious error, the device will be Reset. */
+	if (do_s2io_chk_alarm_bit(SERR_SOURCE_ANY, &bar0->serr_source,
+				  &sw_stat->serious_err_cnt))
+		goto reset;
+
+	/* Check for data parity error */
+	if (do_s2io_chk_alarm_bit(GPIO_INT_REG_DP_ERR_INT, &bar0->gpio_int_reg,
+				  &sw_stat->parity_err_cnt))
+		goto reset;
+
+	/* Check for ring full counter */
+	if (sp->device_type == XFRAME_II_DEVICE) {
+		val64 = readq(&bar0->ring_bump_counter1);
+		for (i = 0; i < 4; i++) {
+			temp64 = (val64 & vBIT(0xFFFF, (i*16), 16));
+			temp64 >>= 64 - ((i+1)*16);
+			sw_stat->ring_full_cnt[i] += temp64;
+		}
+
+		val64 = readq(&bar0->ring_bump_counter2);
+		for (i = 0; i < 4; i++) {
+			temp64 = (val64 & vBIT(0xFFFF, (i*16), 16));
+			temp64 >>= 64 - ((i+1)*16);
+			sw_stat->ring_full_cnt[i+4] += temp64;
+		}
+	}
+
+	val64 = readq(&bar0->txdma_int_status);
+	/*check for pfc_err*/
+	if (val64 & TXDMA_PFC_INT) {
+		if (do_s2io_chk_alarm_bit(PFC_ECC_DB_ERR | PFC_SM_ERR_ALARM |
+					  PFC_MISC_0_ERR | PFC_MISC_1_ERR |
+					  PFC_PCIX_ERR,
+					  &bar0->pfc_err_reg,
+					  &sw_stat->pfc_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(PFC_ECC_SG_ERR,
+				      &bar0->pfc_err_reg,
+				      &sw_stat->pfc_err_cnt);
+	}
+
+	/*check for tda_err*/
+	if (val64 & TXDMA_TDA_INT) {
+		if (do_s2io_chk_alarm_bit(TDA_Fn_ECC_DB_ERR |
+					  TDA_SM0_ERR_ALARM |
+					  TDA_SM1_ERR_ALARM,
+					  &bar0->tda_err_reg,
+					  &sw_stat->tda_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(TDA_Fn_ECC_SG_ERR | TDA_PCIX_ERR,
+				      &bar0->tda_err_reg,
+				      &sw_stat->tda_err_cnt);
+	}
+	/*check for pcc_err*/
+	if (val64 & TXDMA_PCC_INT) {
+		if (do_s2io_chk_alarm_bit(PCC_SM_ERR_ALARM | PCC_WR_ERR_ALARM |
+					  PCC_N_SERR | PCC_6_COF_OV_ERR |
+					  PCC_7_COF_OV_ERR | PCC_6_LSO_OV_ERR |
+					  PCC_7_LSO_OV_ERR | PCC_FB_ECC_DB_ERR |
+					  PCC_TXB_ECC_DB_ERR,
+					  &bar0->pcc_err_reg,
+					  &sw_stat->pcc_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(PCC_FB_ECC_SG_ERR | PCC_TXB_ECC_SG_ERR,
+				      &bar0->pcc_err_reg,
+				      &sw_stat->pcc_err_cnt);
+	}
+
+	/*check for tti_err*/
+	if (val64 & TXDMA_TTI_INT) {
+		if (do_s2io_chk_alarm_bit(TTI_SM_ERR_ALARM,
+					  &bar0->tti_err_reg,
+					  &sw_stat->tti_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(TTI_ECC_SG_ERR | TTI_ECC_DB_ERR,
+				      &bar0->tti_err_reg,
+				      &sw_stat->tti_err_cnt);
+	}
+
+	/*check for lso_err*/
+	if (val64 & TXDMA_LSO_INT) {
+		if (do_s2io_chk_alarm_bit(LSO6_ABORT | LSO7_ABORT |
+					  LSO6_SM_ERR_ALARM | LSO7_SM_ERR_ALARM,
+					  &bar0->lso_err_reg,
+					  &sw_stat->lso_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(LSO6_SEND_OFLOW | LSO7_SEND_OFLOW,
+				      &bar0->lso_err_reg,
+				      &sw_stat->lso_err_cnt);
+	}
+
+	/*check for tpa_err*/
+	if (val64 & TXDMA_TPA_INT) {
+		if (do_s2io_chk_alarm_bit(TPA_SM_ERR_ALARM,
+					  &bar0->tpa_err_reg,
+					  &sw_stat->tpa_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(TPA_TX_FRM_DROP,
+				      &bar0->tpa_err_reg,
+				      &sw_stat->tpa_err_cnt);
+	}
+
+	/*check for sm_err*/
+	if (val64 & TXDMA_SM_INT) {
+		if (do_s2io_chk_alarm_bit(SM_SM_ERR_ALARM,
+					  &bar0->sm_err_reg,
+					  &sw_stat->sm_err_cnt))
+			goto reset;
+	}
+
+	val64 = readq(&bar0->mac_int_status);
+	if (val64 & MAC_INT_STATUS_TMAC_INT) {
+		if (do_s2io_chk_alarm_bit(TMAC_TX_BUF_OVRN | TMAC_TX_SM_ERR,
+					  &bar0->mac_tmac_err_reg,
+					  &sw_stat->mac_tmac_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(TMAC_ECC_SG_ERR | TMAC_ECC_DB_ERR |
+				      TMAC_DESC_ECC_SG_ERR |
+				      TMAC_DESC_ECC_DB_ERR,
+				      &bar0->mac_tmac_err_reg,
+				      &sw_stat->mac_tmac_err_cnt);
+	}
+
+	val64 = readq(&bar0->xgxs_int_status);
+	if (val64 & XGXS_INT_STATUS_TXGXS) {
+		if (do_s2io_chk_alarm_bit(TXGXS_ESTORE_UFLOW | TXGXS_TX_SM_ERR,
+					  &bar0->xgxs_txgxs_err_reg,
+					  &sw_stat->xgxs_txgxs_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(TXGXS_ECC_SG_ERR | TXGXS_ECC_DB_ERR,
+				      &bar0->xgxs_txgxs_err_reg,
+				      &sw_stat->xgxs_txgxs_err_cnt);
+	}
+
+	val64 = readq(&bar0->rxdma_int_status);
+	if (val64 & RXDMA_INT_RC_INT_M) {
+		if (do_s2io_chk_alarm_bit(RC_PRCn_ECC_DB_ERR |
+					  RC_FTC_ECC_DB_ERR |
+					  RC_PRCn_SM_ERR_ALARM |
+					  RC_FTC_SM_ERR_ALARM,
+					  &bar0->rc_err_reg,
+					  &sw_stat->rc_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(RC_PRCn_ECC_SG_ERR |
+				      RC_FTC_ECC_SG_ERR |
+				      RC_RDA_FAIL_WR_Rn, &bar0->rc_err_reg,
+				      &sw_stat->rc_err_cnt);
+		if (do_s2io_chk_alarm_bit(PRC_PCI_AB_RD_Rn |
+					  PRC_PCI_AB_WR_Rn |
+					  PRC_PCI_AB_F_WR_Rn,
+					  &bar0->prc_pcix_err_reg,
+					  &sw_stat->prc_pcix_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(PRC_PCI_DP_RD_Rn |
+				      PRC_PCI_DP_WR_Rn |
+				      PRC_PCI_DP_F_WR_Rn,
+				      &bar0->prc_pcix_err_reg,
+				      &sw_stat->prc_pcix_err_cnt);
+	}
+
+	if (val64 & RXDMA_INT_RPA_INT_M) {
+		if (do_s2io_chk_alarm_bit(RPA_SM_ERR_ALARM | RPA_CREDIT_ERR,
+					  &bar0->rpa_err_reg,
+					  &sw_stat->rpa_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(RPA_ECC_SG_ERR | RPA_ECC_DB_ERR,
+				      &bar0->rpa_err_reg,
+				      &sw_stat->rpa_err_cnt);
+	}
+
+	if (val64 & RXDMA_INT_RDA_INT_M) {
+		if (do_s2io_chk_alarm_bit(RDA_RXDn_ECC_DB_ERR |
+					  RDA_FRM_ECC_DB_N_AERR |
+					  RDA_SM1_ERR_ALARM |
+					  RDA_SM0_ERR_ALARM |
+					  RDA_RXD_ECC_DB_SERR,
+					  &bar0->rda_err_reg,
+					  &sw_stat->rda_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(RDA_RXDn_ECC_SG_ERR |
+				      RDA_FRM_ECC_SG_ERR |
+				      RDA_MISC_ERR |
+				      RDA_PCIX_ERR,
+				      &bar0->rda_err_reg,
+				      &sw_stat->rda_err_cnt);
+	}
+
+	if (val64 & RXDMA_INT_RTI_INT_M) {
+		if (do_s2io_chk_alarm_bit(RTI_SM_ERR_ALARM,
+					  &bar0->rti_err_reg,
+					  &sw_stat->rti_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(RTI_ECC_SG_ERR | RTI_ECC_DB_ERR,
+				      &bar0->rti_err_reg,
+				      &sw_stat->rti_err_cnt);
+	}
+
+	val64 = readq(&bar0->mac_int_status);
+	if (val64 & MAC_INT_STATUS_RMAC_INT) {
+		if (do_s2io_chk_alarm_bit(RMAC_RX_BUFF_OVRN | RMAC_RX_SM_ERR,
+					  &bar0->mac_rmac_err_reg,
+					  &sw_stat->mac_rmac_err_cnt))
+			goto reset;
+		do_s2io_chk_alarm_bit(RMAC_UNUSED_INT |
+				      RMAC_SINGLE_ECC_ERR |
+				      RMAC_DOUBLE_ECC_ERR,
+				      &bar0->mac_rmac_err_reg,
+				      &sw_stat->mac_rmac_err_cnt);
+	}
+
+	val64 = readq(&bar0->xgxs_int_status);
+	if (val64 & XGXS_INT_STATUS_RXGXS) {
+		if (do_s2io_chk_alarm_bit(RXGXS_ESTORE_OFLOW | RXGXS_RX_SM_ERR,
+					  &bar0->xgxs_rxgxs_err_reg,
+					  &sw_stat->xgxs_rxgxs_err_cnt))
+			goto reset;
+	}
+
+	val64 = readq(&bar0->mc_int_status);
+	if (val64 & MC_INT_STATUS_MC_INT) {
+		if (do_s2io_chk_alarm_bit(MC_ERR_REG_SM_ERR,
+					  &bar0->mc_err_reg,
+					  &sw_stat->mc_err_cnt))
+			goto reset;
+
+		/* Handling Ecc errors */
+		if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
+			writeq(val64, &bar0->mc_err_reg);
+			if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
+				sw_stat->double_ecc_errs++;
+				if (sp->device_type != XFRAME_II_DEVICE) {
+					/*
+					 * Reset XframeI only if critical error
+					 */
+					if (val64 &
+					    (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
+					     MC_ERR_REG_MIRI_ECC_DB_ERR_1))
+						goto reset;
+				}
+			} else
+				sw_stat->single_ecc_errs++;
+		}
+	}
+	return;
+
+reset:
+	s2io_stop_all_tx_queue(sp);
+	schedule_work(&sp->rst_timer_task);
+	sw_stat->soft_reset_cnt++;
+	return;
+}
+
+/**
  *  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
@@ -4208,8 +4775,8 @@ static void s2io_txpic_intr_handle(struct s2io_nic *sp)
  */
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct s2io_nic *sp = dev->priv;
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct s2io_nic *sp = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	int i;
 	u64 reason = 0;
@@ -4217,13 +4784,14 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
 	struct config_param *config;
 
 	/* Pretend we handled any irq's from a disconnected card */
-	if ((sp->pdev->error_state != pci_channel_io_normal) &&
-	    (sp->pdev->error_state != 0))
+	if (pci_channel_offline(sp->pdev) && sp->pdev->error_state != 0)
+		return IRQ_NONE;
+
+	if (!is_s2io_card_up(sp))
 		return IRQ_NONE;
 
-	atomic_inc(&sp->isr_cnt);
-	mac_control = &sp->mac_control;
 	config = &sp->config;
+	mac_control = &sp->mac_control;
 
 	/*
 	 * Identify the cause for interrupt and call the appropriate
@@ -4231,73 +4799,73 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
 	 * 1. Rx of packet.
 	 * 2. Tx complete.
 	 * 3. Link down.
-	 * 4. Error in any functional blocks of the NIC.
 	 */
 	reason = readq(&bar0->general_int_status);
 
-	if (!reason) {
-		/* The interrupt was not raised by us. */
-		atomic_dec(&sp->isr_cnt);
-		return IRQ_NONE;
-	}
-	else if (unlikely(reason == S2IO_MINUS_ONE) ) {
-		/* Disable device and get out */
-		atomic_dec(&sp->isr_cnt);
-		return IRQ_NONE;
-	}
+	if (unlikely(reason == S2IO_MINUS_ONE))
+		return IRQ_HANDLED;	/* Nothing much can be done. Get out */
 
-	if (napi) {
-		if (reason & GEN_INTR_RXTRAFFIC) {
-			if ( likely ( netif_rx_schedule_prep(dev)) ) {
-				__netif_rx_schedule(dev);
+	if (reason &
+	    (GEN_INTR_RXTRAFFIC | GEN_INTR_TXTRAFFIC | GEN_INTR_TXPIC)) {
+		writeq(S2IO_MINUS_ONE, &bar0->general_int_mask);
+
+		if (config->napi) {
+			if (reason & GEN_INTR_RXTRAFFIC) {
+				napi_schedule(&sp->napi);
 				writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
+				writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+				readl(&bar0->rx_traffic_int);
 			}
-			else
+		} else {
+			/*
+			 * rx_traffic_int reg is an R1 register, writing all 1's
+			 * will ensure that the actual interrupt causing bit
+			 * get's cleared and hence a read can be avoided.
+			 */
+			if (reason & GEN_INTR_RXTRAFFIC)
 				writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+
+			for (i = 0; i < config->rx_ring_num; i++) {
+				struct ring_info *ring = &mac_control->rings[i];
+
+				rx_intr_handler(ring, 0);
+			}
 		}
-	} else {
+
 		/*
-		 * Rx handler is called by default, without checking for the
-		 * cause of interrupt.
-		 * rx_traffic_int reg is an R1 register, writing all 1's
+		 * tx_traffic_int reg is an R1 register, writing all 1's
 		 * will ensure that the actual interrupt causing bit get's
 		 * cleared and hence a read can be avoided.
 		 */
-		if (reason & GEN_INTR_RXTRAFFIC)
-			writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
+		if (reason & GEN_INTR_TXTRAFFIC)
+			writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
 
-		for (i = 0; i < config->rx_ring_num; i++) {
-			rx_intr_handler(&mac_control->rings[i]);
-		}
-	}
+		for (i = 0; i < config->tx_fifo_num; i++)
+			tx_intr_handler(&mac_control->fifos[i]);
 
-	/*
-	 * tx_traffic_int reg is an R1 register, writing all 1's
-	 * will ensure that the actual interrupt causing bit get's
-	 * cleared and hence a read can be avoided.
-	 */
-	if (reason & GEN_INTR_TXTRAFFIC)
-		writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int);
+		if (reason & GEN_INTR_TXPIC)
+			s2io_txpic_intr_handle(sp);
 
-	for (i = 0; i < config->tx_fifo_num; i++)
-		tx_intr_handler(&mac_control->fifos[i]);
+		/*
+		 * Reallocate the buffers from the interrupt handler itself.
+		 */
+		if (!config->napi) {
+			for (i = 0; i < config->rx_ring_num; i++) {
+				struct ring_info *ring = &mac_control->rings[i];
 
-	if (reason & GEN_INTR_TXPIC)
-		s2io_txpic_intr_handle(sp);
-	/*
-	 * If the Rx buffer count is below the panic threshold then
-	 * reallocate the buffers from the interrupt handler itself,
-	 * else schedule a tasklet to reallocate the buffers.
-	 */
-	if (!napi) {
-		for (i = 0; i < config->rx_ring_num; i++)
-			s2io_chk_rx_buffers(sp, i);
-	}
+				s2io_chk_rx_buffers(sp, ring);
+			}
+		}
+		writeq(sp->general_int_mask, &bar0->general_int_mask);
+		readl(&bar0->general_int_status);
 
-	writeq(0, &bar0->general_int_mask);
-	readl(&bar0->general_int_status);
+		return IRQ_HANDLED;
+
+	} else if (!reason) {
+		/* The interrupt was not raised by us */
+		return IRQ_NONE;
+	}
 
-	atomic_dec(&sp->isr_cnt);
 	return IRQ_HANDLED;
 }
 
@@ -4310,7 +4878,7 @@ static void s2io_updt_stats(struct s2io_nic *sp)
 	u64 val64;
 	int cnt = 0;
 
-	if (atomic_read(&sp->card_state) == CARD_UP) {
+	if (is_s2io_card_up(sp)) {
 		/* Apprx 30us on a 133 MHz bus */
 		val64 = SET_UPDT_CLICKS(10) |
 			STAT_CFG_ONE_SHOT_EN | STAT_CFG_STAT_EN;
@@ -4318,13 +4886,13 @@ static void s2io_updt_stats(struct s2io_nic *sp)
 		do {
 			udelay(100);
 			val64 = readq(&bar0->stat_cfg);
-			if (!(val64 & BIT(0)))
+			if (!(val64 & s2BIT(0)))
 				break;
 			cnt++;
 			if (cnt == 5)
 				break; /* Updt failed */
-		} while(1);
-	} 
+		} while (1);
+	}
 }
 
 /**
@@ -4339,38 +4907,39 @@ static void s2io_updt_stats(struct s2io_nic *sp)
 
 static struct net_device_stats *s2io_get_stats(struct net_device *dev)
 {
-	struct s2io_nic *sp = dev->priv;
-	struct mac_info *mac_control;
-	struct config_param *config;
-
-	mac_control = &sp->mac_control;
-	config = &sp->config;
+	struct s2io_nic *sp = netdev_priv(dev);
+	struct config_param *config = &sp->config;
+	struct mac_info *mac_control = &sp->mac_control;
+	struct stat_block *stats = mac_control->stats_info;
+	int i;
 
 	/* Configure Stats for immediate updt */
 	s2io_updt_stats(sp);
 
-	/* Calculate the changes in the device statistics since the last call, 
+	/* Calculate the changes in the device statistics since the last call,
 	 * and add them to the statistics maintained by the OS.
 	 *
-	 * The amount of changes to be added equals to the distance between the 
-	 * s2io statistics buffer (which holds the device statistics when 
+	 * The amount of changes to be added equals to the distance between the
+	 * s2io statistics buffer (which holds the device statistics when
 	 * this function was previously called) towards the current values of the
 	 * device statistics.
 	 *
-	 * Normally the current device statistics are always greater or equal to 
-	 * the old statistics stored in the buffer, unless the 32bit device 
-	 * registers cycle back to zero due to overflow. This fact is taken into 
-	 * account for calculating the correct amount of increment to be added to 
+	 * Normally the current device statistics are always greater or equal to
+	 * the old statistics stored in the buffer, unless the 32bit device
+	 * registers cycle back to zero due to overflow. This fact is taken into
+	 * account for calculating the correct amount of increment to be added to
 	 * the OS statistics.
 	 */
 
 #define UPDATE_STATS(FIELD, DEVFIELD) \
 { \
-	u32 dev_stat = le32_to_cpu(mac_control->stats_info->DEVFIELD); \
+	u32 dev_stat = le32_to_cpu(stats->DEVFIELD); \
 	if (dev_stat >= sp->stats_buffer.FIELD) \
-		sp->stats.FIELD += dev_stat - sp->stats_buffer.FIELD; \
+		sp->dev_stats.FIELD += \
+			dev_stat - sp->stats_buffer.FIELD; \
 	else \
-		sp->stats.FIELD += ((u32) -1) - sp->stats_buffer.FIELD + dev_stat; \
+		sp->dev_stats.FIELD += \
+			((u32) -1) - sp->stats_buffer.FIELD + dev_stat; \
 	sp->stats_buffer.FIELD = dev_stat; \
 }
 
@@ -4382,7 +4951,16 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
 
 #undef UPDATE_STATS
 
-	return (&sp->stats);
+	/* collect per-ring rx_packets and rx_bytes */
+	sp->dev_stats.rx_packets = sp->dev_stats.rx_bytes = 0;
+	for (i = 0; i < config->rx_ring_num; i++) {
+		struct ring_info *ring = &mac_control->rings[i];
+
+		sp->dev_stats.rx_packets += ring->rx_packets;
+		sp->dev_stats.rx_bytes += ring->rx_bytes;
+	}
+
+	return &sp->dev_stats;
 }
 
 /**
@@ -4402,12 +4980,13 @@ static void s2io_set_multicast(struct net_device *dev)
 {
 	int i, j, prev_cnt;
 	struct dev_mc_list *mclist;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64 = 0, multi_mac = 0x010203040506ULL, mask =
-	    0xfeffffffffffULL;
-	u64 dis_addr = 0xffffffffffffULL, mac_addr = 0;
+		0xfeffffffffffULL;
+	u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, mac_addr = 0;
 	void __iomem *add;
+	struct config_param *config = &sp->config;
 
 	if ((dev->flags & IFF_ALLMULTI) && (!sp->m_cast_flg)) {
 		/*  Enable all Multicast addresses */
@@ -4416,16 +4995,16 @@ static void s2io_set_multicast(struct net_device *dev)
 		writeq(RMAC_ADDR_DATA1_MEM_MASK(mask),
 		       &bar0->rmac_addr_data1_mem);
 		val64 = RMAC_ADDR_CMD_MEM_WE |
-		    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-		    RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET);
+			RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+			RMAC_ADDR_CMD_MEM_OFFSET(config->max_mc_addr - 1);
 		writeq(val64, &bar0->rmac_addr_cmd_mem);
 		/* Wait till command completes */
 		wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-					RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
-					S2IO_BIT_RESET);
+				      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+				      S2IO_BIT_RESET);
 
 		sp->m_cast_flg = 1;
-		sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
+		sp->all_multi_pos = config->max_mc_addr - 1;
 	} else if ((dev->flags & IFF_ALLMULTI) && (sp->m_cast_flg)) {
 		/*  Disable all Multicast addresses */
 		writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
@@ -4433,13 +5012,13 @@ static void s2io_set_multicast(struct net_device *dev)
 		writeq(RMAC_ADDR_DATA1_MEM_MASK(0x0),
 		       &bar0->rmac_addr_data1_mem);
 		val64 = RMAC_ADDR_CMD_MEM_WE |
-		    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-		    RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
+			RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+			RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
 		writeq(val64, &bar0->rmac_addr_cmd_mem);
 		/* Wait till command completes */
 		wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-					RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
-					S2IO_BIT_RESET);
+				      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+				      S2IO_BIT_RESET);
 
 		sp->m_cast_flg = 0;
 		sp->all_multi_pos = 0;
@@ -4452,7 +5031,7 @@ static void s2io_set_multicast(struct net_device *dev)
 		val64 |= MAC_CFG_RMAC_PROM_ENABLE;
 
 		writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
-		writel((u32) val64, add);
+		writel((u32)val64, add);
 		writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
 		writel((u32) (val64 >> 32), (add + 4));
 
@@ -4460,7 +5039,7 @@ static void s2io_set_multicast(struct net_device *dev)
 			val64 = readq(&bar0->rx_pa_cfg);
 			val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
 			writeq(val64, &bar0->rx_pa_cfg);
-			vlan_strip_flag = 0;
+			sp->vlan_strip_flag = 0;
 		}
 
 		val64 = readq(&bar0->mac_cfg);
@@ -4474,7 +5053,7 @@ static void s2io_set_multicast(struct net_device *dev)
 		val64 &= ~MAC_CFG_RMAC_PROM_ENABLE;
 
 		writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
-		writel((u32) val64, add);
+		writel((u32)val64, add);
 		writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
 		writel((u32) (val64 >> 32), (add + 4));
 
@@ -4482,23 +5061,22 @@ static void s2io_set_multicast(struct net_device *dev)
 			val64 = readq(&bar0->rx_pa_cfg);
 			val64 |= RX_PA_CFG_STRIP_VLAN_TAG;
 			writeq(val64, &bar0->rx_pa_cfg);
-			vlan_strip_flag = 1;
+			sp->vlan_strip_flag = 1;
 		}
 
 		val64 = readq(&bar0->mac_cfg);
 		sp->promisc_flg = 0;
-		DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n",
-			  dev->name);
+		DBG_PRINT(INFO_DBG, "%s: left promiscuous mode\n", dev->name);
 	}
 
 	/*  Update individual M_CAST address list */
 	if ((!sp->m_cast_flg) && dev->mc_count) {
 		if (dev->mc_count >
-		    (MAX_ADDRS_SUPPORTED - MAC_MC_ADDR_START_OFFSET - 1)) {
-			DBG_PRINT(ERR_DBG, "%s: No more Rx filters ",
+		    (config->max_mc_addr - config->max_mac_addr)) {
+			DBG_PRINT(ERR_DBG,
+				  "%s: No more Rx filters can be added - "
+				  "please enable ALL_MULTI instead\n",
 				  dev->name);
-			DBG_PRINT(ERR_DBG, "can be added, please enable ");
-			DBG_PRINT(ERR_DBG, "ALL_MULTI instead\n");
 			return;
 		}
 
@@ -4510,20 +5088,20 @@ static void s2io_set_multicast(struct net_device *dev)
 			writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
 			       &bar0->rmac_addr_data0_mem);
 			writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
-				&bar0->rmac_addr_data1_mem);
+			       &bar0->rmac_addr_data1_mem);
 			val64 = RMAC_ADDR_CMD_MEM_WE |
-			    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-			    RMAC_ADDR_CMD_MEM_OFFSET
-			    (MAC_MC_ADDR_START_OFFSET + i);
+				RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+				RMAC_ADDR_CMD_MEM_OFFSET
+				(config->mc_start_offset + i);
 			writeq(val64, &bar0->rmac_addr_cmd_mem);
 
 			/* Wait for command completes */
 			if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-					RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
-					S2IO_BIT_RESET)) {
-				DBG_PRINT(ERR_DBG, "%s: Adding ",
+						  RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+						  S2IO_BIT_RESET)) {
+				DBG_PRINT(ERR_DBG,
+					  "%s: Adding Multicasts failed\n",
 					  dev->name);
-				DBG_PRINT(ERR_DBG, "Multicasts failed\n");
 				return;
 			}
 		}
@@ -4542,28 +5120,183 @@ static void s2io_set_multicast(struct net_device *dev)
 			writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr),
 			       &bar0->rmac_addr_data0_mem);
 			writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL),
-				&bar0->rmac_addr_data1_mem);
+			       &bar0->rmac_addr_data1_mem);
 			val64 = RMAC_ADDR_CMD_MEM_WE |
-			    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-			    RMAC_ADDR_CMD_MEM_OFFSET
-			    (i + MAC_MC_ADDR_START_OFFSET);
+				RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+				RMAC_ADDR_CMD_MEM_OFFSET
+				(i + config->mc_start_offset);
 			writeq(val64, &bar0->rmac_addr_cmd_mem);
 
 			/* Wait for command completes */
 			if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-					RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
-					S2IO_BIT_RESET)) {
-				DBG_PRINT(ERR_DBG, "%s: Adding ",
+						  RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+						  S2IO_BIT_RESET)) {
+				DBG_PRINT(ERR_DBG,
+					  "%s: Adding Multicasts failed\n",
 					  dev->name);
-				DBG_PRINT(ERR_DBG, "Multicasts failed\n");
 				return;
 			}
 		}
 	}
 }
 
+/* read from CAM unicast & multicast addresses and store it in
+ * def_mac_addr structure
+ */
+static void do_s2io_store_unicast_mc(struct s2io_nic *sp)
+{
+	int offset;
+	u64 mac_addr = 0x0;
+	struct config_param *config = &sp->config;
+
+	/* store unicast & multicast mac addresses */
+	for (offset = 0; offset < config->max_mc_addr; offset++) {
+		mac_addr = do_s2io_read_unicast_mc(sp, offset);
+		/* if read fails disable the entry */
+		if (mac_addr == FAILURE)
+			mac_addr = S2IO_DISABLE_MAC_ENTRY;
+		do_s2io_copy_mac_addr(sp, offset, mac_addr);
+	}
+}
+
+/* restore unicast & multicast MAC to CAM from def_mac_addr structure */
+static void do_s2io_restore_unicast_mc(struct s2io_nic *sp)
+{
+	int offset;
+	struct config_param *config = &sp->config;
+	/* restore unicast mac address */
+	for (offset = 0; offset < config->max_mac_addr; offset++)
+		do_s2io_prog_unicast(sp->dev,
+				     sp->def_mac_addr[offset].mac_addr);
+
+	/* restore multicast mac address */
+	for (offset = config->mc_start_offset;
+	     offset < config->max_mc_addr; offset++)
+		do_s2io_add_mc(sp, sp->def_mac_addr[offset].mac_addr);
+}
+
+/* add a multicast MAC address to CAM */
+static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr)
+{
+	int i;
+	u64 mac_addr = 0;
+	struct config_param *config = &sp->config;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		mac_addr <<= 8;
+		mac_addr |= addr[i];
+	}
+	if ((0ULL == mac_addr) || (mac_addr == S2IO_DISABLE_MAC_ENTRY))
+		return SUCCESS;
+
+	/* check if the multicast mac already preset in CAM */
+	for (i = config->mc_start_offset; i < config->max_mc_addr; i++) {
+		u64 tmp64;
+		tmp64 = do_s2io_read_unicast_mc(sp, i);
+		if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
+			break;
+
+		if (tmp64 == mac_addr)
+			return SUCCESS;
+	}
+	if (i == config->max_mc_addr) {
+		DBG_PRINT(ERR_DBG,
+			  "CAM full no space left for multicast MAC\n");
+		return FAILURE;
+	}
+	/* Update the internal structure with this new mac address */
+	do_s2io_copy_mac_addr(sp, i, mac_addr);
+
+	return do_s2io_add_mac(sp, mac_addr, i);
+}
+
+/* add MAC address to CAM */
+static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int off)
+{
+	u64 val64;
+	struct XENA_dev_config __iomem *bar0 = sp->bar0;
+
+	writeq(RMAC_ADDR_DATA0_MEM_ADDR(addr),
+	       &bar0->rmac_addr_data0_mem);
+
+	val64 =	RMAC_ADDR_CMD_MEM_WE | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+		RMAC_ADDR_CMD_MEM_OFFSET(off);
+	writeq(val64, &bar0->rmac_addr_cmd_mem);
+
+	/* Wait till command completes */
+	if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+				  RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+				  S2IO_BIT_RESET)) {
+		DBG_PRINT(INFO_DBG, "do_s2io_add_mac failed\n");
+		return FAILURE;
+	}
+	return SUCCESS;
+}
+/* deletes a specified unicast/multicast mac entry from CAM */
+static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr)
+{
+	int offset;
+	u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, tmp64;
+	struct config_param *config = &sp->config;
+
+	for (offset = 1;
+	     offset < config->max_mc_addr; offset++) {
+		tmp64 = do_s2io_read_unicast_mc(sp, offset);
+		if (tmp64 == addr) {
+			/* disable the entry by writing  0xffffffffffffULL */
+			if (do_s2io_add_mac(sp, dis_addr, offset) ==  FAILURE)
+				return FAILURE;
+			/* store the new mac list from CAM */
+			do_s2io_store_unicast_mc(sp);
+			return SUCCESS;
+		}
+	}
+	DBG_PRINT(ERR_DBG, "MAC address 0x%llx not found in CAM\n",
+		  (unsigned long long)addr);
+	return FAILURE;
+}
+
+/* read mac entries from CAM */
+static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset)
+{
+	u64 tmp64 = 0xffffffffffff0000ULL, val64;
+	struct XENA_dev_config __iomem *bar0 = sp->bar0;
+
+	/* read mac addr */
+	val64 =	RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+		RMAC_ADDR_CMD_MEM_OFFSET(offset);
+	writeq(val64, &bar0->rmac_addr_cmd_mem);
+
+	/* Wait till command completes */
+	if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+				  RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+				  S2IO_BIT_RESET)) {
+		DBG_PRINT(INFO_DBG, "do_s2io_read_unicast_mc failed\n");
+		return FAILURE;
+	}
+	tmp64 = readq(&bar0->rmac_addr_data0_mem);
+
+	return tmp64 >> 16;
+}
+
+/**
+ * s2io_set_mac_addr driver entry point
+ */
+
+static int s2io_set_mac_addr(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EINVAL;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	/* store the MAC address in CAM */
+	return do_s2io_prog_unicast(dev, dev->dev_addr);
+}
 /**
- *  s2io_set_mac_addr - Programs the Xframe mac address
+ *  do_s2io_prog_unicast - Programs the Xframe mac address
  *  @dev : pointer to the device structure.
  *  @addr: a uchar pointer to the new mac address which is to be set.
  *  Description : This procedure will program the Xframe to receive
@@ -4572,13 +5305,13 @@ static void s2io_set_multicast(struct net_device *dev)
  *  as defined in errno.h file on failure.
  */
 
-static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
+static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr)
 {
-	struct s2io_nic *sp = dev->priv;
-	struct XENA_dev_config __iomem *bar0 = sp->bar0;
-	register u64 val64, mac_addr = 0;
+	struct s2io_nic *sp = netdev_priv(dev);
+	register u64 mac_addr = 0, perm_addr = 0;
 	int i;
-	u64 old_mac_addr = 0;
+	u64 tmp64;
+	struct config_param *config = &sp->config;
 
 	/*
 	 * Set the new MAC address as the new unicast filter and reflect this
@@ -4588,39 +5321,35 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
 	for (i = 0; i < ETH_ALEN; i++) {
 		mac_addr <<= 8;
 		mac_addr |= addr[i];
-		old_mac_addr <<= 8;
-		old_mac_addr |= sp->def_mac_addr[0].mac_addr[i];
+		perm_addr <<= 8;
+		perm_addr |= sp->def_mac_addr[0].mac_addr[i];
 	}
 
-	if(0 == mac_addr)
+	/* check if the dev_addr is different than perm_addr */
+	if (mac_addr == perm_addr)
 		return SUCCESS;
 
-	/* Update the internal structure with this new mac address */
-	if(mac_addr != old_mac_addr) {
-		memset(sp->def_mac_addr[0].mac_addr, 0, sizeof(ETH_ALEN));
-		sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_addr);
-		sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_addr >> 8);
-		sp->def_mac_addr[0].mac_addr[3] = (u8) (mac_addr >> 16);
-		sp->def_mac_addr[0].mac_addr[2] = (u8) (mac_addr >> 24);
-		sp->def_mac_addr[0].mac_addr[1] = (u8) (mac_addr >> 32);
-		sp->def_mac_addr[0].mac_addr[0] = (u8) (mac_addr >> 40);
-	}
-
-	writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr),
-	       &bar0->rmac_addr_data0_mem);
+	/* check if the mac already preset in CAM */
+	for (i = 1; i < config->max_mac_addr; i++) {
+		tmp64 = do_s2io_read_unicast_mc(sp, i);
+		if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
+			break;
 
-	val64 =
-	    RMAC_ADDR_CMD_MEM_WE | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-	    RMAC_ADDR_CMD_MEM_OFFSET(0);
-	writeq(val64, &bar0->rmac_addr_cmd_mem);
-	/* Wait till command completes */
-	if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-		      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET)) {
-		DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name);
+		if (tmp64 == mac_addr) {
+			DBG_PRINT(INFO_DBG,
+				  "MAC addr:0x%llx already present in CAM\n",
+				  (unsigned long long)mac_addr);
+			return SUCCESS;
+		}
+	}
+	if (i == config->max_mac_addr) {
+		DBG_PRINT(ERR_DBG, "CAM full no space left for Unicast MAC\n");
 		return FAILURE;
 	}
+	/* Update the internal structure with this new mac address */
+	do_s2io_copy_mac_addr(sp, i, mac_addr);
 
-	return SUCCESS;
+	return do_s2io_add_mac(sp, mac_addr, i);
 }
 
 /**
@@ -4633,14 +5362,15 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
  * the NIC.
  * Return value:
  * 0 on success.
-*/
+ */
 
 static int s2io_ethtool_sset(struct net_device *dev,
 			     struct ethtool_cmd *info)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	if ((info->autoneg == AUTONEG_ENABLE) ||
-	    (info->speed != SPEED_10000) || (info->duplex != DUPLEX_FULL))
+	    (info->speed != SPEED_10000) ||
+	    (info->duplex != DUPLEX_FULL))
 		return -EINVAL;
 	else {
 		s2io_close(sp->dev);
@@ -4664,11 +5394,13 @@ static int s2io_ethtool_sset(struct net_device *dev,
 
 static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	info->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
 	info->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
 	info->port = PORT_FIBRE;
-	/* info->transceiver?? TODO */
+
+	/* info->transceiver */
+	info->transceiver = XCVR_EXTERNAL;
 
 	if (netif_carrier_ok(sp->dev)) {
 		info->speed = 10000;
@@ -4697,7 +5429,7 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
 static void s2io_ethtool_gdrvinfo(struct net_device *dev,
 				  struct ethtool_drvinfo *info)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 
 	strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
 	strncpy(info->version, s2io_driver_version, sizeof(info->version));
@@ -4705,12 +5437,6 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
 	strncpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
 	info->regdump_len = XENA_REG_SPACE;
 	info->eedump_len = XENA_EEPROM_SPACE;
-	info->testinfo_len = S2IO_TEST_LEN;
-
-	if (sp->device_type == XFRAME_I_DEVICE)
-		info->n_stats = XFRAME_I_STAT_LEN;
-	else
-		info->n_stats = XFRAME_II_STAT_LEN;
 }
 
 /**
@@ -4725,15 +5451,15 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
  *  buffer area.
  * Return value :
  * void .
-*/
+ */
 
 static void s2io_ethtool_gregs(struct net_device *dev,
 			       struct ethtool_regs *regs, void *space)
 {
 	int i;
 	u64 reg;
-	u8 *reg_space = (u8 *) space;
-	struct s2io_nic *sp = dev->priv;
+	u8 *reg_space = (u8 *)space;
+	struct s2io_nic *sp = netdev_priv(dev);
 
 	regs->len = XENA_REG_SPACE;
 	regs->version = sp->pdev->subsystem_device;
@@ -4752,17 +5478,17 @@ static void s2io_ethtool_gregs(struct net_device *dev,
  * adapter LED bit of the adapter control bit to set/reset every time on
  * invocation. The timer is set for 1/2 a second, hence tha NIC blinks
  *  once every second.
-*/
+ */
 static void s2io_phy_id(unsigned long data)
 {
-	struct s2io_nic *sp = (struct s2io_nic *) data;
+	struct s2io_nic *sp = (struct s2io_nic *)data;
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64 = 0;
 	u16 subid;
 
 	subid = sp->pdev->subsystem_device;
 	if ((sp->device_type == XFRAME_II_DEVICE) ||
-		   ((subid & 0xFF) >= 0x07)) {
+	    ((subid & 0xFF) >= 0x07)) {
 		val64 = readq(&bar0->gpio_control);
 		val64 ^= GPIO_CTRL_GPIO_0;
 		writeq(val64, &bar0->gpio_control);
@@ -4793,25 +5519,23 @@ static void s2io_phy_id(unsigned long data)
 static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
 {
 	u64 val64 = 0, last_gpio_ctrl_val;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u16 subid;
 
 	subid = sp->pdev->subsystem_device;
 	last_gpio_ctrl_val = readq(&bar0->gpio_control);
-	if ((sp->device_type == XFRAME_I_DEVICE) &&
-		((subid & 0xFF) < 0x07)) {
+	if ((sp->device_type == XFRAME_I_DEVICE) && ((subid & 0xFF) < 0x07)) {
 		val64 = readq(&bar0->adapter_control);
 		if (!(val64 & ADAPTER_CNTL_EN)) {
-			printk(KERN_ERR
-			       "Adapter Link down, cannot blink LED\n");
+			pr_err("Adapter Link down, cannot blink LED\n");
 			return -EFAULT;
 		}
 	}
 	if (sp->id_timer.function == NULL) {
 		init_timer(&sp->id_timer);
 		sp->id_timer.function = s2io_phy_id;
-		sp->id_timer.data = (unsigned long) sp;
+		sp->id_timer.data = (unsigned long)sp;
 	}
 	mod_timer(&sp->id_timer, jiffies);
 	if (data)
@@ -4829,10 +5553,10 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
 }
 
 static void s2io_ethtool_gringparam(struct net_device *dev,
-                                    struct ethtool_ringparam *ering)
+				    struct ethtool_ringparam *ering)
 {
-	struct s2io_nic *sp = dev->priv;
-	int i,tx_desc_count=0,rx_desc_count=0;
+	struct s2io_nic *sp = netdev_priv(dev);
+	int i, tx_desc_count = 0, rx_desc_count = 0;
 
 	if (sp->rxd_mode == RXD_MODE_1)
 		ering->rx_max_pending = MAX_RX_DESC_1;
@@ -4840,20 +5564,20 @@ static void s2io_ethtool_gringparam(struct net_device *dev,
 		ering->rx_max_pending = MAX_RX_DESC_2;
 
 	ering->tx_max_pending = MAX_TX_DESC;
-	for (i = 0 ; i < sp->config.tx_fifo_num ; i++) 
+	for (i = 0 ; i < sp->config.tx_fifo_num ; i++)
 		tx_desc_count += sp->config.tx_cfg[i].fifo_len;
-	
-	DBG_PRINT(INFO_DBG,"\nmax txds : %d\n",sp->config.max_txds);
+
+	DBG_PRINT(INFO_DBG, "max txds: %d\n", sp->config.max_txds);
 	ering->tx_pending = tx_desc_count;
 	rx_desc_count = 0;
-	for (i = 0 ; i < sp->config.rx_ring_num ; i++) 
+	for (i = 0 ; i < sp->config.rx_ring_num ; i++)
 		rx_desc_count += sp->config.rx_cfg[i].num_rxd;
 
 	ering->rx_pending = rx_desc_count;
 
 	ering->rx_mini_max_pending = 0;
 	ering->rx_mini_pending = 0;
-	if(sp->rxd_mode == RXD_MODE_1)
+	if (sp->rxd_mode == RXD_MODE_1)
 		ering->rx_jumbo_max_pending = MAX_RX_DESC_1;
 	else if (sp->rxd_mode == RXD_MODE_3B)
 		ering->rx_jumbo_max_pending = MAX_RX_DESC_2;
@@ -4874,15 +5598,15 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
 				       struct ethtool_pauseparam *ep)
 {
 	u64 val64;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
 	val64 = readq(&bar0->rmac_pause_cfg);
 	if (val64 & RMAC_PAUSE_GEN_ENABLE)
-		ep->tx_pause = TRUE;
+		ep->tx_pause = true;
 	if (val64 & RMAC_PAUSE_RX_ENABLE)
-		ep->rx_pause = TRUE;
-	ep->autoneg = FALSE;
+		ep->rx_pause = true;
+	ep->autoneg = false;
 }
 
 /**
@@ -4898,10 +5622,10 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
  */
 
 static int s2io_ethtool_setpause_data(struct net_device *dev,
-			       struct ethtool_pauseparam *ep)
+				      struct ethtool_pauseparam *ep)
 {
 	u64 val64;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
 	val64 = readq(&bar0->rmac_pause_cfg);
@@ -4934,7 +5658,7 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
  */
 
 #define S2IO_DEV_ID		5
-static int read_eeprom(struct s2io_nic * sp, int off, u64 * data)
+static int read_eeprom(struct s2io_nic *sp, int off, u64 *data)
 {
 	int ret = -1;
 	u32 exit_cnt = 0;
@@ -4942,9 +5666,11 @@ static int read_eeprom(struct s2io_nic * sp, int off, u64 * data)
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
 	if (sp->device_type == XFRAME_I_DEVICE) {
-		val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-		    I2C_CONTROL_BYTE_CNT(0x3) | I2C_CONTROL_READ |
-		    I2C_CONTROL_CNTL_START;
+		val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) |
+			I2C_CONTROL_ADDR(off) |
+			I2C_CONTROL_BYTE_CNT(0x3) |
+			I2C_CONTROL_READ |
+			I2C_CONTROL_CNTL_START;
 		SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
 
 		while (exit_cnt < 5) {
@@ -4999,16 +5725,18 @@ static int read_eeprom(struct s2io_nic * sp, int off, u64 * data)
  *  0 on success, -1 on failure.
  */
 
-static int write_eeprom(struct s2io_nic * sp, int off, u64 data, int cnt)
+static int write_eeprom(struct s2io_nic *sp, int off, u64 data, int cnt)
 {
 	int exit_cnt = 0, ret = -1;
 	u64 val64;
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 
 	if (sp->device_type == XFRAME_I_DEVICE) {
-		val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) | I2C_CONTROL_ADDR(off) |
-		    I2C_CONTROL_BYTE_CNT(cnt) | I2C_CONTROL_SET_DATA((u32)data) |
-		    I2C_CONTROL_CNTL_START;
+		val64 = I2C_CONTROL_DEV_ID(S2IO_DEV_ID) |
+			I2C_CONTROL_ADDR(off) |
+			I2C_CONTROL_BYTE_CNT(cnt) |
+			I2C_CONTROL_SET_DATA((u32)data) |
+			I2C_CONTROL_CNTL_START;
 		SPECIAL_REG_WRITE(val64, &bar0->i2c_control, LF);
 
 		while (exit_cnt < 5) {
@@ -5025,7 +5753,7 @@ static int write_eeprom(struct s2io_nic * sp, int off, u64 data, int cnt)
 
 	if (sp->device_type == XFRAME_II_DEVICE) {
 		int write_cnt = (cnt == 8) ? 0 : cnt;
-		writeq(SPI_DATA_WRITE(data,(cnt<<3)), &bar0->spi_data);
+		writeq(SPI_DATA_WRITE(data, (cnt << 3)), &bar0->spi_data);
 
 		val64 = SPI_CONTROL_KEY(0x9) | SPI_CONTROL_SEL1 |
 			SPI_CONTROL_BYTECNT(write_cnt) |
@@ -5052,14 +5780,14 @@ static void s2io_vpd_read(struct s2io_nic *nic)
 {
 	u8 *vpd_data;
 	u8 data;
-	int i=0, cnt, fail = 0;
+	int i = 0, cnt, fail = 0;
 	int vpd_addr = 0x80;
+	struct swStat *swstats = &nic->mac_control.stats_info->sw_stat;
 
 	if (nic->device_type == XFRAME_II_DEVICE) {
 		strcpy(nic->product_name, "Xframe II 10GbE network adapter");
 		vpd_addr = 0x80;
-	}
-	else {
+	} else {
 		strcpy(nic->product_name, "Xframe I 10GbE network adapter");
 		vpd_addr = 0x50;
 	}
@@ -5067,16 +5795,16 @@ static void s2io_vpd_read(struct s2io_nic *nic)
 
 	vpd_data = kmalloc(256, GFP_KERNEL);
 	if (!vpd_data) {
-		nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++;
+		swstats->mem_alloc_fail_cnt++;
 		return;
 	}
-	nic->mac_control.stats_info->sw_stat.mem_allocated += 256;
+	swstats->mem_allocated += 256;
 
-	for (i = 0; i < 256; i +=4 ) {
+	for (i = 0; i < 256; i += 4) {
 		pci_write_config_byte(nic->pdev, (vpd_addr + 2), i);
 		pci_read_config_byte(nic->pdev,  (vpd_addr + 2), &data);
 		pci_write_config_byte(nic->pdev, (vpd_addr + 3), 0);
-		for (cnt = 0; cnt <5; cnt++) {
+		for (cnt = 0; cnt < 5; cnt++) {
 			msleep(2);
 			pci_read_config_byte(nic->pdev, (vpd_addr + 3), &data);
 			if (data == 0x80)
@@ -5091,15 +5819,15 @@ static void s2io_vpd_read(struct s2io_nic *nic)
 				      (u32 *)&vpd_data[i]);
 	}
 
-	if(!fail) {
+	if (!fail) {
 		/* read serial number of adapter */
 		for (cnt = 0; cnt < 256; cnt++) {
-		if ((vpd_data[cnt] == 'S') &&
-			(vpd_data[cnt+1] == 'N') &&
-			(vpd_data[cnt+2] < VPD_STRING_LEN)) {
+			if ((vpd_data[cnt] == 'S') &&
+			    (vpd_data[cnt+1] == 'N') &&
+			    (vpd_data[cnt+2] < VPD_STRING_LEN)) {
 				memset(nic->serial_num, 0, VPD_STRING_LEN);
 				memcpy(nic->serial_num, &vpd_data[cnt + 3],
-					vpd_data[cnt+2]);
+				       vpd_data[cnt+2]);
 				break;
 			}
 		}
@@ -5110,7 +5838,7 @@ static void s2io_vpd_read(struct s2io_nic *nic)
 		memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
 	}
 	kfree(vpd_data);
-	nic->mac_control.stats_info->sw_stat.mem_freed += 256;
+	swstats->mem_freed += 256;
 }
 
 /**
@@ -5127,11 +5855,11 @@ static void s2io_vpd_read(struct s2io_nic *nic)
  */
 
 static int s2io_ethtool_geeprom(struct net_device *dev,
-			 struct ethtool_eeprom *eeprom, u8 * data_buf)
+				struct ethtool_eeprom *eeprom, u8 * data_buf)
 {
 	u32 i, valid;
 	u64 data;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 
 	eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
 
@@ -5165,32 +5893,32 @@ static int s2io_ethtool_geeprom(struct net_device *dev,
 
 static int s2io_ethtool_seeprom(struct net_device *dev,
 				struct ethtool_eeprom *eeprom,
-				u8 * data_buf)
+				u8 *data_buf)
 {
 	int len = eeprom->len, cnt = 0;
 	u64 valid = 0, data;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 
 	if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
 		DBG_PRINT(ERR_DBG,
-			  "ETHTOOL_WRITE_EEPROM Err: Magic value ");
-		DBG_PRINT(ERR_DBG, "is wrong, Its not 0x%x\n",
+			  "ETHTOOL_WRITE_EEPROM Err: "
+			  "Magic value is wrong, it is 0x%x should be 0x%x\n",
+			  (sp->pdev->vendor | (sp->pdev->device << 16)),
 			  eeprom->magic);
 		return -EFAULT;
 	}
 
 	while (len) {
-		data = (u32) data_buf[cnt] & 0x000000FF;
-		if (data) {
-			valid = (u32) (data << 24);
-		} else
+		data = (u32)data_buf[cnt] & 0x000000FF;
+		if (data)
+			valid = (u32)(data << 24);
+		else
 			valid = data;
 
 		if (write_eeprom(sp, (eeprom->offset + cnt), valid, 0)) {
 			DBG_PRINT(ERR_DBG,
-				  "ETHTOOL_WRITE_EEPROM Err: Cannot ");
-			DBG_PRINT(ERR_DBG,
-				  "write into the specified offset\n");
+				  "ETHTOOL_WRITE_EEPROM Err: "
+				  "Cannot write into the specified offset\n");
 			return -EFAULT;
 		}
 		cnt++;
@@ -5213,7 +5941,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
  * 0 on success.
  */
 
-static int s2io_register_test(struct s2io_nic * sp, uint64_t * data)
+static int s2io_register_test(struct s2io_nic *sp, uint64_t *data)
 {
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64 = 0, exp_val;
@@ -5222,13 +5950,13 @@ static int s2io_register_test(struct s2io_nic * sp, uint64_t * data)
 	val64 = readq(&bar0->pif_rd_swapper_fb);
 	if (val64 != 0x123456789abcdefULL) {
 		fail = 1;
-		DBG_PRINT(INFO_DBG, "Read Test level 1 fails\n");
+		DBG_PRINT(INFO_DBG, "Read Test level %d fails\n", 1);
 	}
 
 	val64 = readq(&bar0->rmac_pause_cfg);
 	if (val64 != 0xc000ffff00000000ULL) {
 		fail = 1;
-		DBG_PRINT(INFO_DBG, "Read Test level 2 fails\n");
+		DBG_PRINT(INFO_DBG, "Read Test level %d fails\n", 2);
 	}
 
 	val64 = readq(&bar0->rx_queue_cfg);
@@ -5238,13 +5966,13 @@ static int s2io_register_test(struct s2io_nic * sp, uint64_t * data)
 		exp_val = 0x0808080808080808ULL;
 	if (val64 != exp_val) {
 		fail = 1;
-		DBG_PRINT(INFO_DBG, "Read Test level 3 fails\n");
+		DBG_PRINT(INFO_DBG, "Read Test level %d fails\n", 3);
 	}
 
 	val64 = readq(&bar0->xgxs_efifo_cfg);
 	if (val64 != 0x000000001923141EULL) {
 		fail = 1;
-		DBG_PRINT(INFO_DBG, "Read Test level 4 fails\n");
+		DBG_PRINT(INFO_DBG, "Read Test level %d fails\n", 4);
 	}
 
 	val64 = 0x5A5A5A5A5A5A5A5AULL;
@@ -5252,7 +5980,7 @@ static int s2io_register_test(struct s2io_nic * sp, uint64_t * data)
 	val64 = readq(&bar0->xmsi_data);
 	if (val64 != 0x5A5A5A5A5A5A5A5AULL) {
 		fail = 1;
-		DBG_PRINT(ERR_DBG, "Write Test level 1 fails\n");
+		DBG_PRINT(ERR_DBG, "Write Test level %d fails\n", 1);
 	}
 
 	val64 = 0xA5A5A5A5A5A5A5A5ULL;
@@ -5260,7 +5988,7 @@ static int s2io_register_test(struct s2io_nic * sp, uint64_t * data)
 	val64 = readq(&bar0->xmsi_data);
 	if (val64 != 0xA5A5A5A5A5A5A5A5ULL) {
 		fail = 1;
-		DBG_PRINT(ERR_DBG, "Write Test level 2 fails\n");
+		DBG_PRINT(ERR_DBG, "Write Test level %d fails\n", 2);
 	}
 
 	*data = fail;
@@ -5280,7 +6008,7 @@ static int s2io_register_test(struct s2io_nic * sp, uint64_t * data)
  * 0 on success.
  */
 
-static int s2io_eeprom_test(struct s2io_nic * sp, uint64_t * data)
+static int s2io_eeprom_test(struct s2io_nic *sp, uint64_t *data)
 {
 	int fail = 0;
 	u64 ret_data, org_4F0, org_7F0;
@@ -5309,9 +6037,9 @@ static int s2io_eeprom_test(struct s2io_nic * sp, uint64_t * data)
 
 	if (ret_data != 0x012345) {
 		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);
+			  "Data written %llx Data read %llx\n",
+			  dev->name, (unsigned long long)0x12345,
+			  (unsigned long long)ret_data);
 		fail = 1;
 	}
 
@@ -5331,9 +6059,9 @@ static int s2io_eeprom_test(struct s2io_nic * sp, uint64_t * data)
 
 	if (ret_data != 0x012345) {
 		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);
+			  "Data written %llx Data read %llx\n",
+			  dev->name, (unsigned long long)0x12345,
+			  (unsigned long long)ret_data);
 		fail = 1;
 	}
 
@@ -5382,7 +6110,7 @@ static int s2io_eeprom_test(struct s2io_nic * sp, uint64_t * data)
  * 0 on success and -1 on failure.
  */
 
-static int s2io_bist_test(struct s2io_nic * sp, uint64_t * data)
+static int s2io_bist_test(struct s2io_nic *sp, uint64_t *data)
 {
 	u8 bist = 0;
 	int cnt = 0, ret = -1;
@@ -5418,13 +6146,13 @@ static int s2io_bist_test(struct s2io_nic * sp, uint64_t * data)
  * 0 on success.
  */
 
-static int s2io_link_test(struct s2io_nic * sp, uint64_t * data)
+static int s2io_link_test(struct s2io_nic *sp, uint64_t *data)
 {
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64;
 
 	val64 = readq(&bar0->adapter_status);
-	if(!(LINK_IS_UP(val64)))
+	if (!(LINK_IS_UP(val64)))
 		*data = 1;
 	else
 		*data = 0;
@@ -5445,7 +6173,7 @@ static int s2io_link_test(struct s2io_nic * sp, uint64_t * data)
  *  0 on success.
  */
 
-static int s2io_rldram_test(struct s2io_nic * sp, uint64_t * data)
+static int s2io_rldram_test(struct s2io_nic *sp, uint64_t *data)
 {
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
 	u64 val64;
@@ -5468,28 +6196,26 @@ static int s2io_rldram_test(struct s2io_nic * sp, uint64_t * data)
 
 	while (iteration < 2) {
 		val64 = 0x55555555aaaa0000ULL;
-		if (iteration == 1) {
+		if (iteration == 1)
 			val64 ^= 0xFFFFFFFFFFFF0000ULL;
-		}
 		writeq(val64, &bar0->mc_rldram_test_d0);
 
 		val64 = 0xaaaa5a5555550000ULL;
-		if (iteration == 1) {
+		if (iteration == 1)
 			val64 ^= 0xFFFFFFFFFFFF0000ULL;
-		}
 		writeq(val64, &bar0->mc_rldram_test_d1);
 
 		val64 = 0x55aaaaaaaa5a0000ULL;
-		if (iteration == 1) {
+		if (iteration == 1)
 			val64 ^= 0xFFFFFFFFFFFF0000ULL;
-		}
 		writeq(val64, &bar0->mc_rldram_test_d2);
 
 		val64 = (u64) (0x0000003ffffe0100ULL);
 		writeq(val64, &bar0->mc_rldram_test_add);
 
-		val64 = MC_RLDRAM_TEST_MODE | MC_RLDRAM_TEST_WRITE |
-		    	MC_RLDRAM_TEST_GO;
+		val64 = MC_RLDRAM_TEST_MODE |
+			MC_RLDRAM_TEST_WRITE |
+			MC_RLDRAM_TEST_GO;
 		SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_test_ctrl, LF);
 
 		for (cnt = 0; cnt < 5; cnt++) {
@@ -5547,9 +6273,9 @@ static int s2io_rldram_test(struct s2io_nic * sp, uint64_t * data)
 
 static void s2io_ethtool_test(struct net_device *dev,
 			      struct ethtool_test *ethtest,
-			      uint64_t * data)
+			      uint64_t *data)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 	int orig_state = netif_running(sp->dev);
 
 	if (ethtest->flags == ETH_TEST_FL_OFFLINE) {
@@ -5580,8 +6306,7 @@ static void s2io_ethtool_test(struct net_device *dev,
 	} else {
 		/* Online Tests. */
 		if (!orig_state) {
-			DBG_PRINT(ERR_DBG,
-				  "%s: is not up, cannot run test\n",
+			DBG_PRINT(ERR_DBG, "%s: is not up, cannot run test\n",
 				  dev->name);
 			data[0] = -1;
 			data[1] = -1;
@@ -5602,278 +6327,297 @@ static void s2io_ethtool_test(struct net_device *dev,
 
 static void s2io_get_ethtool_stats(struct net_device *dev,
 				   struct ethtool_stats *estats,
-				   u64 * tmp_stats)
+				   u64 *tmp_stats)
 {
-	int i = 0;
-	struct s2io_nic *sp = dev->priv;
-	struct stat_block *stat_info = sp->mac_control.stats_info;
+	int i = 0, k;
+	struct s2io_nic *sp = netdev_priv(dev);
+	struct stat_block *stats = sp->mac_control.stats_info;
+	struct swStat *swstats = &stats->sw_stat;
+	struct xpakStat *xstats = &stats->xpak_stat;
 
 	s2io_updt_stats(sp);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_frms_oflow) << 32  |
-		le32_to_cpu(stat_info->tmac_frms);
+		(u64)le32_to_cpu(stats->tmac_frms_oflow) << 32  |
+		le32_to_cpu(stats->tmac_frms);
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stats->tmac_data_octets_oflow) << 32 |
+		le32_to_cpu(stats->tmac_data_octets);
+	tmp_stats[i++] = le64_to_cpu(stats->tmac_drop_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_data_octets_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_data_octets);
-	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms);
+		(u64)le32_to_cpu(stats->tmac_mcst_frms_oflow) << 32 |
+		le32_to_cpu(stats->tmac_mcst_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_mcst_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_mcst_frms);
+		(u64)le32_to_cpu(stats->tmac_bcst_frms_oflow) << 32 |
+		le32_to_cpu(stats->tmac_bcst_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->tmac_pause_ctrl_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_bcst_frms);
-	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->tmac_ttl_octets_oflow) << 32 |
-                le32_to_cpu(stat_info->tmac_ttl_octets);
+		(u64)le32_to_cpu(stats->tmac_ttl_octets_oflow) << 32 |
+		le32_to_cpu(stats->tmac_ttl_octets);
 	tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->tmac_ucst_frms_oflow) << 32 |
-                le32_to_cpu(stat_info->tmac_ucst_frms);
+		(u64)le32_to_cpu(stats->tmac_ucst_frms_oflow) << 32 |
+		le32_to_cpu(stats->tmac_ucst_frms);
 	tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->tmac_nucst_frms_oflow) << 32 |
-                le32_to_cpu(stat_info->tmac_nucst_frms);
+		(u64)le32_to_cpu(stats->tmac_nucst_frms_oflow) << 32 |
+		le32_to_cpu(stats->tmac_nucst_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_any_err_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_ttl_less_fb_octets);
-	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
+		(u64)le32_to_cpu(stats->tmac_any_err_frms_oflow) << 32 |
+		le32_to_cpu(stats->tmac_any_err_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->tmac_ttl_less_fb_octets);
+	tmp_stats[i++] = le64_to_cpu(stats->tmac_vld_ip_octets);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_vld_ip);
+		(u64)le32_to_cpu(stats->tmac_vld_ip_oflow) << 32 |
+		le32_to_cpu(stats->tmac_vld_ip);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_drop_ip_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_drop_ip);
+		(u64)le32_to_cpu(stats->tmac_drop_ip_oflow) << 32 |
+		le32_to_cpu(stats->tmac_drop_ip);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_icmp_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_icmp);
+		(u64)le32_to_cpu(stats->tmac_icmp_oflow) << 32 |
+		le32_to_cpu(stats->tmac_icmp);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->tmac_rst_tcp_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_rst_tcp);
-	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp);
-	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_udp_oflow) << 32 |
-		le32_to_cpu(stat_info->tmac_udp);
+		(u64)le32_to_cpu(stats->tmac_rst_tcp_oflow) << 32 |
+		le32_to_cpu(stats->tmac_rst_tcp);
+	tmp_stats[i++] = le64_to_cpu(stats->tmac_tcp);
+	tmp_stats[i++] = (u64)le32_to_cpu(stats->tmac_udp_oflow) << 32 |
+		le32_to_cpu(stats->tmac_udp);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_vld_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_vld_frms);
+		(u64)le32_to_cpu(stats->rmac_vld_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_vld_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_data_octets_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_data_octets);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms);
+		(u64)le32_to_cpu(stats->rmac_data_octets_oflow) << 32 |
+		le32_to_cpu(stats->rmac_data_octets);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_fcs_err_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_drop_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_vld_mcst_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_vld_mcst_frms);
+		(u64)le32_to_cpu(stats->rmac_vld_mcst_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_vld_mcst_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_vld_bcst_frms);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_out_rng_len_err_frms);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_unsup_ctrl_frms);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_ttl_octets_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_ttl_octets);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_accepted_ucst_frms_oflow)
-		<< 32 | le32_to_cpu(stat_info->rmac_accepted_ucst_frms);
+		(u64)le32_to_cpu(stats->rmac_vld_bcst_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_vld_bcst_frms);
+	tmp_stats[i++] = le32_to_cpu(stats->rmac_in_rng_len_err_frms);
+	tmp_stats[i++] = le32_to_cpu(stats->rmac_out_rng_len_err_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_long_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_pause_ctrl_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_unsup_ctrl_frms);
 	tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_accepted_nucst_frms_oflow)
-                 << 32 | le32_to_cpu(stat_info->rmac_accepted_nucst_frms);
+		(u64)le32_to_cpu(stats->rmac_ttl_octets_oflow) << 32 |
+		le32_to_cpu(stats->rmac_ttl_octets);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_discarded_frms);
-        tmp_stats[i++] =
-                (u64)le32_to_cpu(stat_info->rmac_drop_events_oflow)
-                 << 32 | le32_to_cpu(stat_info->rmac_drop_events);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_less_fb_octets);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_frms);
+		(u64)le32_to_cpu(stats->rmac_accepted_ucst_frms_oflow) << 32
+		| le32_to_cpu(stats->rmac_accepted_ucst_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_usized_frms);
+		(u64)le32_to_cpu(stats->rmac_accepted_nucst_frms_oflow)
+		<< 32 | le32_to_cpu(stats->rmac_accepted_nucst_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_osized_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_osized_frms);
+		(u64)le32_to_cpu(stats->rmac_discarded_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_discarded_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_frag_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_frag_frms);
+		(u64)le32_to_cpu(stats->rmac_drop_events_oflow)
+		<< 32 | le32_to_cpu(stats->rmac_drop_events);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_less_fb_octets);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_jabber_frms);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_64_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_65_127_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_128_255_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_256_511_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_512_1023_frms);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1024_1518_frms);
+		(u64)le32_to_cpu(stats->rmac_usized_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_usized_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_ip);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
+		(u64)le32_to_cpu(stats->rmac_osized_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_osized_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_drop_ip);
+		(u64)le32_to_cpu(stats->rmac_frag_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_frag_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_icmp);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
+		(u64)le32_to_cpu(stats->rmac_jabber_frms_oflow) << 32 |
+		le32_to_cpu(stats->rmac_jabber_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_64_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_65_127_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_128_255_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_256_511_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_512_1023_frms);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_1024_1518_frms);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_udp);
+		(u64)le32_to_cpu(stats->rmac_ip_oflow) << 32 |
+		le32_to_cpu(stats->rmac_ip);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_ip_octets);
+	tmp_stats[i++] = le32_to_cpu(stats->rmac_hdr_err_ip);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_err_drp_udp);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_err_sym);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q0);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q1);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q2);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q3);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q4);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q5);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q6);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q7);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q0);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q1);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q2);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q3);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q4);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q5);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q6);
-        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q7);
+		(u64)le32_to_cpu(stats->rmac_drop_ip_oflow) << 32 |
+		le32_to_cpu(stats->rmac_drop_ip);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_pause_cnt);
-	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_data_err_cnt);
-        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_ctrl_err_cnt);
+		(u64)le32_to_cpu(stats->rmac_icmp_oflow) << 32 |
+		le32_to_cpu(stats->rmac_icmp);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_tcp);
 	tmp_stats[i++] =
-		(u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
-		le32_to_cpu(stat_info->rmac_accepted_ip);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rd_req_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_rtry_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_rd_ack_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->wr_req_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_rtry_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->wr_disc_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_wr_ack_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->txp_wr_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->txd_rd_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->txd_wr_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rxd_rd_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rxd_wr_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->txf_rd_cnt);
-	tmp_stats[i++] = le32_to_cpu(stat_info->rxf_wr_cnt);
+		(u64)le32_to_cpu(stats->rmac_udp_oflow) << 32 |
+		le32_to_cpu(stats->rmac_udp);
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stats->rmac_err_drp_udp_oflow) << 32 |
+		le32_to_cpu(stats->rmac_err_drp_udp);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_xgmii_err_sym);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q0);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q1);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q2);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q3);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q4);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q5);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q6);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_frms_q7);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q0);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q1);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q2);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q3);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q4);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q5);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q6);
+	tmp_stats[i++] = le16_to_cpu(stats->rmac_full_q7);
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stats->rmac_pause_cnt_oflow) << 32 |
+		le32_to_cpu(stats->rmac_pause_cnt);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_xgmii_data_err_cnt);
+	tmp_stats[i++] = le64_to_cpu(stats->rmac_xgmii_ctrl_err_cnt);
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stats->rmac_accepted_ip_oflow) << 32 |
+		le32_to_cpu(stats->rmac_accepted_ip);
+	tmp_stats[i++] = le32_to_cpu(stats->rmac_err_tcp);
+	tmp_stats[i++] = le32_to_cpu(stats->rd_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->new_rd_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->new_rd_req_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->rd_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->wr_rtry_rd_ack_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->wr_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->new_wr_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->new_wr_req_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->wr_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->wr_disc_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->rd_rtry_wr_ack_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->txp_wr_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->txd_rd_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->txd_wr_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->rxd_rd_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->rxd_wr_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->txf_rd_cnt);
+	tmp_stats[i++] = le32_to_cpu(stats->rxf_wr_cnt);
 
 	/* Enhanced statistics exist only for Hercules */
-	if(sp->device_type == XFRAME_II_DEVICE) {
+	if (sp->device_type == XFRAME_II_DEVICE) {
 		tmp_stats[i++] =
-				le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms);
+			le64_to_cpu(stats->rmac_ttl_1519_4095_frms);
 		tmp_stats[i++] =
-				le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms);
+			le64_to_cpu(stats->rmac_ttl_4096_8191_frms);
 		tmp_stats[i++] =
-				le64_to_cpu(stat_info->rmac_ttl_8192_max_frms);
-		tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms);
-		tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms);
-		tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms);
-		tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms);
-		tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms);
-		tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard);
-		tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard);
-		tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard);
-		tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard);
-		tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard);
-		tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard);
-		tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard);
-		tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt);
+			le64_to_cpu(stats->rmac_ttl_8192_max_frms);
+		tmp_stats[i++] = le64_to_cpu(stats->rmac_ttl_gt_max_frms);
+		tmp_stats[i++] = le64_to_cpu(stats->rmac_osized_alt_frms);
+		tmp_stats[i++] = le64_to_cpu(stats->rmac_jabber_alt_frms);
+		tmp_stats[i++] = le64_to_cpu(stats->rmac_gt_max_alt_frms);
+		tmp_stats[i++] = le64_to_cpu(stats->rmac_vlan_frms);
+		tmp_stats[i++] = le32_to_cpu(stats->rmac_len_discard);
+		tmp_stats[i++] = le32_to_cpu(stats->rmac_fcs_discard);
+		tmp_stats[i++] = le32_to_cpu(stats->rmac_pf_discard);
+		tmp_stats[i++] = le32_to_cpu(stats->rmac_da_discard);
+		tmp_stats[i++] = le32_to_cpu(stats->rmac_red_discard);
+		tmp_stats[i++] = le32_to_cpu(stats->rmac_rts_discard);
+		tmp_stats[i++] = le32_to_cpu(stats->rmac_ingm_full_discard);
+		tmp_stats[i++] = le32_to_cpu(stats->link_fault_cnt);
 	}
 
 	tmp_stats[i++] = 0;
-	tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
-	tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
-	tmp_stats[i++] = stat_info->sw_stat.parity_err_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.serious_err_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.soft_reset_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.fifo_full_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt;
-	tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_high;
-	tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_low;
-	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_high;
-	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_low;
-	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_high;
-	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_low;
-	tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_high;
-	tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_low;
-	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_high;
-	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_low;
-	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_high;
-	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_low;
-	tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.sending_both;
-	tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts;
-	tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts;
-	if (stat_info->sw_stat.num_aggregations) {
-		u64 tmp = stat_info->sw_stat.sum_avg_pkts_aggregated;
+	tmp_stats[i++] = swstats->single_ecc_errs;
+	tmp_stats[i++] = swstats->double_ecc_errs;
+	tmp_stats[i++] = swstats->parity_err_cnt;
+	tmp_stats[i++] = swstats->serious_err_cnt;
+	tmp_stats[i++] = swstats->soft_reset_cnt;
+	tmp_stats[i++] = swstats->fifo_full_cnt;
+	for (k = 0; k < MAX_RX_RINGS; k++)
+		tmp_stats[i++] = swstats->ring_full_cnt[k];
+	tmp_stats[i++] = xstats->alarm_transceiver_temp_high;
+	tmp_stats[i++] = xstats->alarm_transceiver_temp_low;
+	tmp_stats[i++] = xstats->alarm_laser_bias_current_high;
+	tmp_stats[i++] = xstats->alarm_laser_bias_current_low;
+	tmp_stats[i++] = xstats->alarm_laser_output_power_high;
+	tmp_stats[i++] = xstats->alarm_laser_output_power_low;
+	tmp_stats[i++] = xstats->warn_transceiver_temp_high;
+	tmp_stats[i++] = xstats->warn_transceiver_temp_low;
+	tmp_stats[i++] = xstats->warn_laser_bias_current_high;
+	tmp_stats[i++] = xstats->warn_laser_bias_current_low;
+	tmp_stats[i++] = xstats->warn_laser_output_power_high;
+	tmp_stats[i++] = xstats->warn_laser_output_power_low;
+	tmp_stats[i++] = swstats->clubbed_frms_cnt;
+	tmp_stats[i++] = swstats->sending_both;
+	tmp_stats[i++] = swstats->outof_sequence_pkts;
+	tmp_stats[i++] = swstats->flush_max_pkts;
+	if (swstats->num_aggregations) {
+		u64 tmp = swstats->sum_avg_pkts_aggregated;
 		int count = 0;
 		/*
 		 * Since 64-bit divide does not work on all platforms,
 		 * do repeated subtraction.
 		 */
-		while (tmp >= stat_info->sw_stat.num_aggregations) {
-			tmp -= stat_info->sw_stat.num_aggregations;
+		while (tmp >= swstats->num_aggregations) {
+			tmp -= swstats->num_aggregations;
 			count++;
 		}
 		tmp_stats[i++] = count;
-	}
-	else
+	} else
 		tmp_stats[i++] = 0;
-	tmp_stats[i++] = stat_info->sw_stat.mem_alloc_fail_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.pci_map_fail_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.watchdog_timer_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.mem_allocated;
-	tmp_stats[i++] = stat_info->sw_stat.mem_freed;
-	tmp_stats[i++] = stat_info->sw_stat.link_up_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.link_down_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.link_up_time;
-	tmp_stats[i++] = stat_info->sw_stat.link_down_time;
-
-	tmp_stats[i++] = stat_info->sw_stat.tx_buf_abort_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.tx_desc_abort_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.tx_parity_err_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.tx_link_loss_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.tx_list_proc_err_cnt;
-
-	tmp_stats[i++] = stat_info->sw_stat.rx_parity_err_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_abort_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_parity_abort_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_rda_fail_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_unkn_prot_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_fcs_err_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_buf_size_err_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_rxd_corrupt_cnt;
-	tmp_stats[i++] = stat_info->sw_stat.rx_unkn_err_cnt;
+	tmp_stats[i++] = swstats->mem_alloc_fail_cnt;
+	tmp_stats[i++] = swstats->pci_map_fail_cnt;
+	tmp_stats[i++] = swstats->watchdog_timer_cnt;
+	tmp_stats[i++] = swstats->mem_allocated;
+	tmp_stats[i++] = swstats->mem_freed;
+	tmp_stats[i++] = swstats->link_up_cnt;
+	tmp_stats[i++] = swstats->link_down_cnt;
+	tmp_stats[i++] = swstats->link_up_time;
+	tmp_stats[i++] = swstats->link_down_time;
+
+	tmp_stats[i++] = swstats->tx_buf_abort_cnt;
+	tmp_stats[i++] = swstats->tx_desc_abort_cnt;
+	tmp_stats[i++] = swstats->tx_parity_err_cnt;
+	tmp_stats[i++] = swstats->tx_link_loss_cnt;
+	tmp_stats[i++] = swstats->tx_list_proc_err_cnt;
+
+	tmp_stats[i++] = swstats->rx_parity_err_cnt;
+	tmp_stats[i++] = swstats->rx_abort_cnt;
+	tmp_stats[i++] = swstats->rx_parity_abort_cnt;
+	tmp_stats[i++] = swstats->rx_rda_fail_cnt;
+	tmp_stats[i++] = swstats->rx_unkn_prot_cnt;
+	tmp_stats[i++] = swstats->rx_fcs_err_cnt;
+	tmp_stats[i++] = swstats->rx_buf_size_err_cnt;
+	tmp_stats[i++] = swstats->rx_rxd_corrupt_cnt;
+	tmp_stats[i++] = swstats->rx_unkn_err_cnt;
+	tmp_stats[i++] = swstats->tda_err_cnt;
+	tmp_stats[i++] = swstats->pfc_err_cnt;
+	tmp_stats[i++] = swstats->pcc_err_cnt;
+	tmp_stats[i++] = swstats->tti_err_cnt;
+	tmp_stats[i++] = swstats->tpa_err_cnt;
+	tmp_stats[i++] = swstats->sm_err_cnt;
+	tmp_stats[i++] = swstats->lso_err_cnt;
+	tmp_stats[i++] = swstats->mac_tmac_err_cnt;
+	tmp_stats[i++] = swstats->mac_rmac_err_cnt;
+	tmp_stats[i++] = swstats->xgxs_txgxs_err_cnt;
+	tmp_stats[i++] = swstats->xgxs_rxgxs_err_cnt;
+	tmp_stats[i++] = swstats->rc_err_cnt;
+	tmp_stats[i++] = swstats->prc_pcix_err_cnt;
+	tmp_stats[i++] = swstats->rpa_err_cnt;
+	tmp_stats[i++] = swstats->rda_err_cnt;
+	tmp_stats[i++] = swstats->rti_err_cnt;
+	tmp_stats[i++] = swstats->mc_err_cnt;
 }
 
 static int s2io_ethtool_get_regs_len(struct net_device *dev)
 {
-	return (XENA_REG_SPACE);
+	return XENA_REG_SPACE;
 }
 
 
-static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
+static u32 s2io_ethtool_get_rx_csum(struct net_device *dev)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 
-	return (sp->rx_csum);
+	return sp->rx_csum;
 }
 
 static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 
 	if (data)
 		sp->rx_csum = 1;
@@ -5885,19 +6629,46 @@ static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 
 static int s2io_get_eeprom_len(struct net_device *dev)
 {
-	return (XENA_EEPROM_SPACE);
+	return XENA_EEPROM_SPACE;
 }
 
-static int s2io_ethtool_self_test_count(struct net_device *dev)
+static int s2io_get_sset_count(struct net_device *dev, int sset)
 {
-	return (S2IO_TEST_LEN);
+	struct s2io_nic *sp = netdev_priv(dev);
+
+	switch (sset) {
+	case ETH_SS_TEST:
+		return S2IO_TEST_LEN;
+	case ETH_SS_STATS:
+		switch (sp->device_type) {
+		case XFRAME_I_DEVICE:
+			return XFRAME_I_STAT_LEN;
+		case XFRAME_II_DEVICE:
+			return XFRAME_II_STAT_LEN;
+		default:
+			return 0;
+		}
+	default:
+		return -EOPNOTSUPP;
+	}
 }
 
+static int s2io_ethtool_self_test_count(struct net_device *net_dev)
+{
+	return s2io_get_sset_count(net_dev, ETH_SS_TEST);
+}
+
+static int s2io_ethtool_get_stats_count(struct net_device *net_dev)
+{
+	return s2io_get_sset_count(net_dev, ETH_SS_STATS);
+}
+
+
 static void s2io_ethtool_get_strings(struct net_device *dev,
-				     u32 stringset, u8 * data)
+				     u32 stringset, u8 *data)
 {
 	int stat_size = 0;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
 
 	switch (stringset) {
 	case ETH_SS_TEST:
@@ -5905,34 +6676,18 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
 		break;
 	case ETH_SS_STATS:
 		stat_size = sizeof(ethtool_xena_stats_keys);
-		memcpy(data, &ethtool_xena_stats_keys,stat_size);
-		if(sp->device_type == XFRAME_II_DEVICE) {
+		memcpy(data, &ethtool_xena_stats_keys, stat_size);
+		if (sp->device_type == XFRAME_II_DEVICE) {
 			memcpy(data + stat_size,
-				&ethtool_enhanced_stats_keys,
-				sizeof(ethtool_enhanced_stats_keys));
+			       &ethtool_enhanced_stats_keys,
+			       sizeof(ethtool_enhanced_stats_keys));
 			stat_size += sizeof(ethtool_enhanced_stats_keys);
 		}
 
 		memcpy(data + stat_size, &ethtool_driver_stats_keys,
-			sizeof(ethtool_driver_stats_keys));
+		       sizeof(ethtool_driver_stats_keys));
 	}
 }
-static int s2io_ethtool_get_stats_count(struct net_device *dev)
-{
-	struct s2io_nic *sp = dev->priv;
-	int stat_count = 0;
-	switch(sp->device_type) {
-	case XFRAME_I_DEVICE:
-		stat_count = XFRAME_I_STAT_LEN;
-	break;
-
-	case XFRAME_II_DEVICE:
-		stat_count = XFRAME_II_STAT_LEN;
-	break;
-	}
-
-	return stat_count;
-}
 
 static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 {
@@ -6019,24 +6774,25 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
 static int s2io_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
+	int ret = 0;
 
 	if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
-		DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n",
-			  dev->name);
+		DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", dev->name);
 		return -EPERM;
 	}
 
 	dev->mtu = new_mtu;
 	if (netif_running(dev)) {
+		s2io_stop_all_tx_queue(sp);
 		s2io_card_down(sp);
-		netif_stop_queue(dev);
-		if (s2io_card_up(sp)) {
+		ret = s2io_card_up(sp);
+		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
-				  __FUNCTION__);
+				  __func__);
+			return ret;
 		}
-		if (netif_queue_stopped(dev))
-			netif_wake_queue(dev);
+		s2io_wake_all_tx_queue(sp);
 	} else { /* Device is down */
 		struct XENA_dev_config __iomem *bar0 = sp->bar0;
 		u64 val64 = new_mtu;
@@ -6044,50 +6800,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
 		writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
 	}
 
-	return 0;
-}
-
-/**
- *  s2io_tasklet - Bottom half of the ISR.
- *  @dev_adr : address of the device structure in dma_addr_t format.
- *  Description:
- *  This is the tasklet or the bottom half of the ISR. This is
- *  an extension of the ISR which is scheduled by the scheduler to be run
- *  when the load on the CPU is low. All low priority tasks of the ISR can
- *  be pushed into the tasklet. For now the tasklet is used only to
- *  replenish the Rx buffers in the Rx buffer descriptors.
- *  Return value:
- *  void.
- */
-
-static void s2io_tasklet(unsigned long dev_addr)
-{
-	struct net_device *dev = (struct net_device *) dev_addr;
-	struct s2io_nic *sp = dev->priv;
-	int i, ret;
-	struct mac_info *mac_control;
-	struct config_param *config;
-
-	mac_control = &sp->mac_control;
-	config = &sp->config;
-
-	if (!TASKLET_IN_USE) {
-		for (i = 0; i < config->rx_ring_num; i++) {
-			ret = fill_rx_buffers(sp, i);
-			if (ret == -ENOMEM) {
-				DBG_PRINT(INFO_DBG, "%s: Out of ",
-					  dev->name);
-				DBG_PRINT(INFO_DBG, "memory in tasklet\n");
-				break;
-			} else if (ret == -EFILL) {
-				DBG_PRINT(INFO_DBG,
-					  "%s: Rx Ring %d is full\n",
-					  dev->name, i);
-				break;
-			}
-		}
-		clear_bit(0, (&sp->tasklet_status));
-	}
+	return ret;
 }
 
 /**
@@ -6096,9 +6809,10 @@ 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)
 {
-	struct s2io_nic *nic = (struct s2io_nic *) data;
+	struct s2io_nic *nic = container_of(work, struct s2io_nic,
+					    set_link_task);
 	struct net_device *dev = nic->dev;
 	struct XENA_dev_config __iomem *bar0 = nic->bar0;
 	register u64 val64;
@@ -6109,7 +6823,7 @@ static void s2io_set_link(unsigned long data)
 	if (!netif_running(dev))
 		goto out_unlock;
 
-	if (test_and_set_bit(0, &(nic->link_state))) {
+	if (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(nic->state))) {
 		/* The card is being reset, no point doing anything */
 		goto out_unlock;
 	}
@@ -6131,7 +6845,7 @@ static void s2io_set_link(unsigned long data)
 				val64 |= ADAPTER_CNTL_EN;
 				writeq(val64, &bar0->adapter_control);
 				if (CARDS_WITH_FAULTY_LINK_INDICATORS(
-					nic->device_type, subid)) {
+					    nic->device_type, subid)) {
 					val64 = readq(&bar0->gpio_control);
 					val64 |= GPIO_CTRL_GPIO_0;
 					writeq(val64, &bar0->gpio_control);
@@ -6140,20 +6854,18 @@ static void s2io_set_link(unsigned long data)
 					val64 |= ADAPTER_LED_ON;
 					writeq(val64, &bar0->adapter_control);
 				}
-				nic->device_enabled_once = TRUE;
+				nic->device_enabled_once = true;
 			} else {
-				DBG_PRINT(ERR_DBG, "%s: Error: ", dev->name);
-				DBG_PRINT(ERR_DBG, "device is not Quiescent\n");
-				netif_stop_queue(dev);
+				DBG_PRINT(ERR_DBG,
+					  "%s: Error: device is not Quiescent\n",
+					  dev->name);
+				s2io_stop_all_tx_queue(nic);
 			}
 		}
-		val64 = readq(&bar0->adapter_status);
-		if (!LINK_IS_UP(val64)) {
-			DBG_PRINT(ERR_DBG, "%s:", dev->name);
-			DBG_PRINT(ERR_DBG, " Link down after enabling ");
-			DBG_PRINT(ERR_DBG, "device \n");
-		} else
-			s2io_link(nic, LINK_UP);
+		val64 = readq(&bar0->adapter_control);
+		val64 |= ADAPTER_LED_ON;
+		writeq(val64, &bar0->adapter_control);
+		s2io_link(nic, LINK_UP);
 	} else {
 		if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type,
 						      subid)) {
@@ -6162,18 +6874,22 @@ static void s2io_set_link(unsigned long data)
 			writeq(val64, &bar0->gpio_control);
 			val64 = readq(&bar0->gpio_control);
 		}
+		/* turn off LED */
+		val64 = readq(&bar0->adapter_control);
+		val64 = val64 & (~ADAPTER_LED_ON);
+		writeq(val64, &bar0->adapter_control);
 		s2io_link(nic, LINK_DOWN);
 	}
-	clear_bit(0, &(nic->link_state));
+	clear_bit(__S2IO_STATE_LINK_TASK, &(nic->state));
 
 out_unlock:
 	rtnl_unlock();
 }
 
 static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
-				struct buffAdd *ba,
-				struct sk_buff **skb, u64 *temp0, u64 *temp1,
-				u64 *temp2, int size)
+				  struct buffAdd *ba,
+				  struct sk_buff **skb, u64 *temp0, u64 *temp1,
+				  u64 *temp2, int size)
 {
 	struct net_device *dev = sp->dev;
 	struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
@@ -6192,27 +6908,23 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
 		} else {
 			*skb = dev_alloc_skb(size);
 			if (!(*skb)) {
-				DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name);
-				DBG_PRINT(INFO_DBG, "memory to allocate ");
-				DBG_PRINT(INFO_DBG, "1 buf mode SKBs\n");
-				sp->mac_control.stats_info->sw_stat. \
-					mem_alloc_fail_cnt++;
+				DBG_PRINT(INFO_DBG,
+					  "%s: Out of memory to allocate %s\n",
+					  dev->name, "1 buf mode SKBs");
+				stats->mem_alloc_fail_cnt++;
 				return -ENOMEM ;
 			}
-			sp->mac_control.stats_info->sw_stat.mem_allocated 
-				+= (*skb)->truesize;
+			stats->mem_allocated += (*skb)->truesize;
 			/* storing the mapped addr in a temp variable
 			 * such it will be used for next rxd whose
 			 * Host Control is NULL
 			 */
 			rxdp1->Buffer0_ptr = *temp0 =
-				pci_map_single( sp->pdev, (*skb)->data,
-					size - NET_IP_ALIGN,
-					PCI_DMA_FROMDEVICE);
-			if( (rxdp1->Buffer0_ptr == 0) ||
-				(rxdp1->Buffer0_ptr == DMA_ERROR_CODE)) {
+				pci_map_single(sp->pdev, (*skb)->data,
+					       size - NET_IP_ALIGN,
+					       PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(sp->pdev, rxdp1->Buffer0_ptr))
 				goto memalloc_failed;
-			}
 			rxdp->Host_Control = (unsigned long) (*skb);
 		}
 	} else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) {
@@ -6225,31 +6937,29 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
 		} else {
 			*skb = dev_alloc_skb(size);
 			if (!(*skb)) {
-				DBG_PRINT(INFO_DBG, "%s: Out of ", dev->name);
-				DBG_PRINT(INFO_DBG, "memory to allocate ");
-				DBG_PRINT(INFO_DBG, "2 buf mode SKBs\n");
-				sp->mac_control.stats_info->sw_stat. \
-					mem_alloc_fail_cnt++;
+				DBG_PRINT(INFO_DBG,
+					  "%s: Out of memory to allocate %s\n",
+					  dev->name,
+					  "2 buf mode SKBs");
+				stats->mem_alloc_fail_cnt++;
 				return -ENOMEM;
 			}
-			sp->mac_control.stats_info->sw_stat.mem_allocated 
-				+= (*skb)->truesize;
+			stats->mem_allocated += (*skb)->truesize;
 			rxdp3->Buffer2_ptr = *temp2 =
 				pci_map_single(sp->pdev, (*skb)->data,
 					       dev->mtu + 4,
 					       PCI_DMA_FROMDEVICE);
-			if( (rxdp3->Buffer2_ptr == 0) ||
-				(rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) {
+			if (pci_dma_mapping_error(sp->pdev, rxdp3->Buffer2_ptr))
 				goto memalloc_failed;
-			}
 			rxdp3->Buffer0_ptr = *temp0 =
-				pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN,
-						PCI_DMA_FROMDEVICE);
-			if( (rxdp3->Buffer0_ptr == 0) ||
-				(rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) {
-				pci_unmap_single (sp->pdev,
-					(dma_addr_t)rxdp3->Buffer2_ptr,
-					dev->mtu + 4, PCI_DMA_FROMDEVICE);
+				pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN,
+					       PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(sp->pdev,
+						  rxdp3->Buffer0_ptr)) {
+				pci_unmap_single(sp->pdev,
+						 (dma_addr_t)rxdp3->Buffer2_ptr,
+						 dev->mtu + 4,
+						 PCI_DMA_FROMDEVICE);
 				goto memalloc_failed;
 			}
 			rxdp->Host_Control = (unsigned long) (*skb);
@@ -6257,25 +6967,27 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
 			/* Buffer-1 will be dummy buffer not used */
 			rxdp3->Buffer1_ptr = *temp1 =
 				pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN,
-						PCI_DMA_FROMDEVICE);
-			if( (rxdp3->Buffer1_ptr == 0) ||
-				(rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) {
-				pci_unmap_single (sp->pdev,
-					(dma_addr_t)rxdp3->Buffer0_ptr,
-					BUF0_LEN, PCI_DMA_FROMDEVICE);
-				pci_unmap_single (sp->pdev,
-					(dma_addr_t)rxdp3->Buffer2_ptr,
-					dev->mtu + 4, PCI_DMA_FROMDEVICE);
+					       PCI_DMA_FROMDEVICE);
+			if (pci_dma_mapping_error(sp->pdev,
+						  rxdp3->Buffer1_ptr)) {
+				pci_unmap_single(sp->pdev,
+						 (dma_addr_t)rxdp3->Buffer0_ptr,
+						 BUF0_LEN, PCI_DMA_FROMDEVICE);
+				pci_unmap_single(sp->pdev,
+						 (dma_addr_t)rxdp3->Buffer2_ptr,
+						 dev->mtu + 4,
+						 PCI_DMA_FROMDEVICE);
 				goto memalloc_failed;
 			}
 		}
 	}
 	return 0;
-	memalloc_failed:
-		stats->pci_map_fail_cnt++;
-		stats->mem_freed += (*skb)->truesize;
-		dev_kfree_skb(*skb);
-		return -ENOMEM;
+
+memalloc_failed:
+	stats->pci_map_fail_cnt++;
+	stats->mem_freed += (*skb)->truesize;
+	dev_kfree_skb(*skb);
+	return -ENOMEM;
 }
 
 static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp,
@@ -6283,19 +6995,19 @@ static void set_rxd_buffer_size(struct s2io_nic *sp, struct RxD_t *rxdp,
 {
 	struct net_device *dev = sp->dev;
 	if (sp->rxd_mode == RXD_MODE_1) {
-		rxdp->Control_2 = SET_BUFFER0_SIZE_1( size - NET_IP_ALIGN);
+		rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN);
 	} else if (sp->rxd_mode == RXD_MODE_3B) {
 		rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
 		rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
-		rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4);
+		rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu + 4);
 	}
 }
 
 static  int rxd_owner_bit_reset(struct s2io_nic *sp)
 {
 	int i, j, k, blk_cnt = 0, size;
-	struct mac_info * mac_control = &sp->mac_control;
 	struct config_param *config = &sp->config;
+	struct mac_info *mac_control = &sp->mac_control;
 	struct net_device *dev = sp->dev;
 	struct RxD_t *rxdp = NULL;
 	struct sk_buff *skb = NULL;
@@ -6311,20 +7023,21 @@ static  int rxd_owner_bit_reset(struct s2io_nic *sp)
 		size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
 
 	for (i = 0; i < config->rx_ring_num; i++) {
-		blk_cnt = config->rx_cfg[i].num_rxd /
-			(rxd_count[sp->rxd_mode] +1);
+		struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+		struct ring_info *ring = &mac_control->rings[i];
+
+		blk_cnt = rx_cfg->num_rxd / (rxd_count[sp->rxd_mode] + 1);
 
 		for (j = 0; j < blk_cnt; j++) {
 			for (k = 0; k < rxd_count[sp->rxd_mode]; k++) {
-				rxdp = mac_control->rings[i].
-					rx_blocks[j].rxds[k].virt_addr;
-				if(sp->rxd_mode == RXD_MODE_3B)
-					ba = &mac_control->rings[i].ba[j][k];
-				if (set_rxd_buffer_pointer(sp, rxdp, ba,
-						       &skb,(u64 *)&temp0_64,
-						       (u64 *)&temp1_64,
-						       (u64 *)&temp2_64,
-							size) == ENOMEM) {
+				rxdp = ring->rx_blocks[j].rxds[k].virt_addr;
+				if (sp->rxd_mode == RXD_MODE_3B)
+					ba = &ring->ba[j][k];
+				if (set_rxd_buffer_pointer(sp, rxdp, ba, &skb,
+							   (u64 *)&temp0_64,
+							   (u64 *)&temp1_64,
+							   (u64 *)&temp2_64,
+							   size) == -ENOMEM) {
 					return 0;
 				}
 
@@ -6339,78 +7052,89 @@ static  int rxd_owner_bit_reset(struct s2io_nic *sp)
 
 }
 
-static int s2io_add_isr(struct s2io_nic * sp)
+static int s2io_add_isr(struct s2io_nic *sp)
 {
 	int ret = 0;
 	struct net_device *dev = sp->dev;
 	int err = 0;
 
-	if (sp->intr_type == MSI_X)
+	if (sp->config.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;
+		sp->config.intr_type = INTA;
 	}
 
-	/* Store the values of the MSIX table in the struct s2io_nic structure */
+	/*
+	 * Store the values of the MSIX table in
+	 * the struct s2io_nic structure
+	 */
 	store_xmsi_data(sp);
 
 	/* After proper initialization of H/W, register ISR */
-	if (sp->intr_type == MSI_X) {
-		int i, msix_tx_cnt=0,msix_rx_cnt=0;
-
-		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);
-				/* If either data or addr is zero print it */
-				if(!(sp->msix_info[i].addr &&
-					sp->msix_info[i].data)) {
-					DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx"
-						"Data:0x%lx\n",sp->desc[i],
-						(unsigned long long)
-						sp->msix_info[i].addr,
-						(unsigned long)
-						ntohl(sp->msix_info[i].data));
-				} else {
-					msix_tx_cnt++;
+	if (sp->config.intr_type == MSI_X) {
+		int i, msix_rx_cnt = 0;
+
+		for (i = 0; i < sp->num_entries; i++) {
+			if (sp->s2io_entries[i].in_use == MSIX_FLG) {
+				if (sp->s2io_entries[i].type ==
+				    MSIX_RING_TYPE) {
+					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);
+				} else if (sp->s2io_entries[i].type ==
+					   MSIX_ALARM_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);
+
 				}
-			} 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);
-				/* If either data or addr is zero print it */
-				if(!(sp->msix_info[i].addr &&
-					sp->msix_info[i].data)) {
-					DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx"
-						"Data:0x%lx\n",sp->desc[i],
-						(unsigned long long)
-						sp->msix_info[i].addr,
-						(unsigned long)
-						ntohl(sp->msix_info[i].data));
-				} else {
+				/* if either data or addr is zero print it. */
+				if (!(sp->msix_info[i].addr &&
+				      sp->msix_info[i].data)) {
+					DBG_PRINT(ERR_DBG,
+						  "%s @Addr:0x%llx Data:0x%llx\n",
+						  sp->desc[i],
+						  (unsigned long long)
+						  sp->msix_info[i].addr,
+						  (unsigned long long)
+						  ntohl(sp->msix_info[i].data));
+				} else
 					msix_rx_cnt++;
+				if (err) {
+					remove_msix_isr(sp);
+
+					DBG_PRINT(ERR_DBG,
+						  "%s:MSI-X-%d registration "
+						  "failed\n", dev->name, i);
+
+					DBG_PRINT(ERR_DBG,
+						  "%s: Defaulting to INTA\n",
+						  dev->name);
+					sp->config.intr_type = INTA;
+					break;
 				}
+				sp->s2io_entries[i].in_use =
+					MSIX_REGISTERED_SUCCESS;
 			}
-			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;
 		}
-		printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
-		printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
+		if (!err) {
+			pr_info("MSI-X-RX %d entries enabled\n", --msix_rx_cnt);
+			DBG_PRINT(INFO_DBG,
+				  "MSI-X-TX entries enabled through alarm vector\n");
+		}
 	}
-	if (sp->intr_type == INTA) {
-		err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
-				sp->name, dev);
+	if (sp->config.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);
@@ -6419,53 +7143,42 @@ static int s2io_add_isr(struct s2io_nic * sp)
 	}
 	return 0;
 }
-static void s2io_rem_isr(struct s2io_nic * 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);
-	}
-	/* Waiting till all Interrupt handlers are complete */
-	cnt = 0;
-	do {
-		msleep(10);
-		if (!atomic_read(&sp->isr_cnt))
-			break;
-		cnt++;
-	} while(cnt < 5);
+static void s2io_rem_isr(struct s2io_nic *sp)
+{
+	if (sp->config.intr_type == MSI_X)
+		remove_msix_isr(sp);
+	else
+		remove_inta_isr(sp);
 }
 
-static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
+static void do_s2io_card_down(struct s2io_nic *sp, int do_io)
 {
 	int cnt = 0;
 	struct XENA_dev_config __iomem *bar0 = sp->bar0;
-	unsigned long flags;
 	register u64 val64 = 0;
+	struct config_param *config;
+	config = &sp->config;
+
+	if (!is_s2io_card_up(sp))
+		return;
 
 	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))) {
+	while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state)))
 		msleep(50);
+	clear_bit(__S2IO_STATE_CARD_UP, &sp->state);
+
+	/* Disable napi */
+	if (sp->config.napi) {
+		int off = 0;
+		if (config->intr_type ==  MSI_X) {
+			for (; off < sp->config.rx_ring_num; off++)
+				napi_disable(&sp->mac_control.rings[off].napi);
+		}
+		else
+			napi_disable(&sp->napi);
 	}
-	atomic_set(&sp->card_state, CARD_DOWN);
 
 	/* disable Tx and Rx traffic on the NIC */
 	if (do_io)
@@ -6473,11 +7186,11 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 
 	s2io_rem_isr(sp);
 
-	/* Kill tasklet. */
-	tasklet_kill(&sp->task);
+	/* stop the tx queue, indicate link down */
+	s2io_link(sp, LINK_DOWN);
 
 	/* Check if the device is Quiescent and then Reset the NIC */
-	while(do_io) {
+	while (do_io) {
 		/* As per the HW requirement we need to replenish the
 		 * receive buffer to avoid the ring bump. Since there is
 		 * no intention of processing the Rx frame at this pointwe are
@@ -6489,66 +7202,67 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
 
 		val64 = readq(&bar0->adapter_status);
 		if (verify_xena_quiescence(sp)) {
-			if(verify_pcc_quiescent(sp, sp->device_enabled_once))
-			break;
+			if (verify_pcc_quiescent(sp, sp->device_enabled_once))
+				break;
 		}
 
 		msleep(50);
 		cnt++;
 		if (cnt == 10) {
-			DBG_PRINT(ERR_DBG,
-				  "s2io_close:Device not Quiescent ");
-			DBG_PRINT(ERR_DBG, "adaper status reads 0x%llx\n",
-				  (unsigned long long) val64);
+			DBG_PRINT(ERR_DBG, "Device not Quiescent - "
+				  "adapter status reads 0x%llx\n",
+				  (unsigned long long)val64);
 			break;
 		}
 	}
 	if (do_io)
 		s2io_reset(sp);
 
-	spin_lock_irqsave(&sp->tx_lock, flags);
 	/* Free all Tx buffers */
 	free_tx_buffers(sp);
-	spin_unlock_irqrestore(&sp->tx_lock, flags);
 
 	/* Free all Rx buffers */
-	spin_lock_irqsave(&sp->rx_lock, flags);
 	free_rx_buffers(sp);
-	spin_unlock_irqrestore(&sp->rx_lock, flags);
 
-	clear_bit(0, &(sp->link_state));
+	clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state));
 }
 
-static void s2io_card_down(struct s2io_nic * sp)
+static void s2io_card_down(struct s2io_nic *sp)
 {
 	do_s2io_card_down(sp, 1);
 }
 
-static int s2io_card_up(struct s2io_nic * sp)
+static int s2io_card_up(struct s2io_nic *sp)
 {
 	int i, ret = 0;
-	struct mac_info *mac_control;
 	struct config_param *config;
-	struct net_device *dev = (struct net_device *) sp->dev;
+	struct mac_info *mac_control;
+	struct net_device *dev = (struct net_device *)sp->dev;
 	u16 interruptible;
 
 	/* Initialize the H/W I/O registers */
-	if (init_nic(sp) != 0) {
+	ret = init_nic(sp);
+	if (ret != 0) {
 		DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
 			  dev->name);
-		s2io_reset(sp);
-		return -ENODEV;
+		if (ret != -EIO)
+			s2io_reset(sp);
+		return ret;
 	}
 
 	/*
 	 * Initializing the Rx buffers. For now we are considering only 1
 	 * Rx ring and initializing buffers into 30 Rx blocks
 	 */
-	mac_control = &sp->mac_control;
 	config = &sp->config;
+	mac_control = &sp->mac_control;
 
 	for (i = 0; i < config->rx_ring_num; i++) {
-		if ((ret = fill_rx_buffers(sp, i))) {
+		struct ring_info *ring = &mac_control->rings[i];
+
+		ring->mtu = dev->mtu;
+		ret = fill_rx_buffers(sp, ring, 1);
+		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
 				  dev->name);
 			s2io_reset(sp);
@@ -6556,14 +7270,25 @@ static int s2io_card_up(struct s2io_nic * sp)
 			return -ENOMEM;
 		}
 		DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i,
-			  atomic_read(&sp->rx_bufs_left[i]));
+			  ring->rx_bufs_left);
 	}
+
+	/* Initialise napi */
+	if (config->napi) {
+		if (config->intr_type ==  MSI_X) {
+			for (i = 0; i < sp->config.rx_ring_num; i++)
+				napi_enable(&sp->mac_control.rings[i].napi);
+		} else {
+			napi_enable(&sp->napi);
+		}
+	}
+
 	/* Maintain the state prior to the open */
 	if (sp->promisc_flg)
 		sp->promisc_flg = 0;
 	if (sp->m_cast_flg) {
 		sp->m_cast_flg = 0;
-		sp->all_multi_pos= 0;
+		sp->all_multi_pos = 0;
 	}
 
 	/* Setting its receive mode */
@@ -6572,7 +7297,7 @@ static int s2io_card_up(struct s2io_nic * sp)
 	if (sp->lro) {
 		/* Initialize max aggregatable pkts per session based on MTU */
 		sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu;
-		/* Check if we can use(if specified) user provided value */
+		/* 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;
 	}
@@ -6587,7 +7312,7 @@ static int s2io_card_up(struct s2io_nic * sp)
 
 	/* Add interrupt service routine */
 	if (s2io_add_isr(sp) != 0) {
-		if (sp->intr_type == MSI_X)
+		if (sp->config.intr_type == MSI_X)
 			s2io_rem_isr(sp);
 		s2io_reset(sp);
 		free_rx_buffers(sp);
@@ -6596,21 +7321,19 @@ static int s2io_card_up(struct s2io_nic * sp)
 
 	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);
+	set_bit(__S2IO_STATE_CARD_UP, &sp->state);
 
 	/*  Enable select interrupts */
-	if (sp->intr_type != INTA)
-		en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
-	else {
+	en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS);
+	if (sp->config.intr_type != INTA) {
+		interruptible = TX_TRAFFIC_INTR | TX_PIC_INTR;
+		en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS);
+	} else {
 		interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
-		interruptible |= TX_PIC_INTR | RX_PIC_INTR;
-		interruptible |= TX_MAC_INTR | RX_MAC_INTR;
+		interruptible |= TX_PIC_INTR;
 		en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS);
 	}
 
-
-	atomic_set(&sp->card_state, CARD_UP);
 	return 0;
 }
 
@@ -6624,10 +7347,10 @@ static int s2io_card_up(struct s2io_nic * 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;
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = container_of(work, struct s2io_nic, rst_timer_task);
+	struct net_device *dev = sp->dev;
 
 	rtnl_lock();
 
@@ -6636,12 +7359,10 @@ static void s2io_restart_nic(unsigned long data)
 
 	s2io_card_down(sp);
 	if (s2io_card_up(sp)) {
-		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
-			  dev->name);
+		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", dev->name);
 	}
-	netif_wake_queue(dev);
-	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",
-		  dev->name);
+	s2io_wake_all_tx_queue(sp);
+	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n", dev->name);
 out_unlock:
 	rtnl_unlock();
 }
@@ -6661,12 +7382,13 @@ out_unlock:
 
 static void s2io_tx_watchdog(struct net_device *dev)
 {
-	struct s2io_nic *sp = dev->priv;
+	struct s2io_nic *sp = netdev_priv(dev);
+	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
 	if (netif_carrier_ok(dev)) {
-		sp->mac_control.stats_info->sw_stat.watchdog_timer_cnt++;
+		swstats->watchdog_timer_cnt++;
 		schedule_work(&sp->rst_timer_task);
-		sp->mac_control.stats_info->sw_stat.soft_reset_cnt++;
+		swstats->soft_reset_cnt++;
 	}
 }
 
@@ -6690,96 +7412,88 @@ static void s2io_tx_watchdog(struct net_device *dev)
 static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
 {
 	struct s2io_nic *sp = ring_data->nic;
-	struct net_device *dev = (struct net_device *) sp->dev;
+	struct net_device *dev = (struct net_device *)ring_data->dev;
 	struct sk_buff *skb = (struct sk_buff *)
-		((unsigned long) rxdp->Host_Control);
+		((unsigned long)rxdp->Host_Control);
 	int ring_no = ring_data->ring_no;
 	u16 l3_csum, l4_csum;
 	unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
-	struct lro *lro;
+	struct lro *uninitialized_var(lro);
 	u8 err_mask;
+	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
 	skb->dev = dev;
 
 	if (err) {
 		/* Check for parity error */
-		if (err & 0x1) {
-			sp->mac_control.stats_info->sw_stat.parity_err_cnt++;
-		}
+		if (err & 0x1)
+			swstats->parity_err_cnt++;
+
 		err_mask = err >> 48;
-		switch(err_mask) {
-			case 1:
-				sp->mac_control.stats_info->sw_stat.
-				rx_parity_err_cnt++;
+		switch (err_mask) {
+		case 1:
+			swstats->rx_parity_err_cnt++;
 			break;
 
-			case 2:
-				sp->mac_control.stats_info->sw_stat.
-				rx_abort_cnt++;
+		case 2:
+			swstats->rx_abort_cnt++;
 			break;
 
-			case 3:
-				sp->mac_control.stats_info->sw_stat.
-				rx_parity_abort_cnt++;
+		case 3:
+			swstats->rx_parity_abort_cnt++;
 			break;
 
-			case 4:
-				sp->mac_control.stats_info->sw_stat.
-				rx_rda_fail_cnt++;
+		case 4:
+			swstats->rx_rda_fail_cnt++;
 			break;
 
-			case 5:
-				sp->mac_control.stats_info->sw_stat.
-				rx_unkn_prot_cnt++;
+		case 5:
+			swstats->rx_unkn_prot_cnt++;
 			break;
 
-			case 6:
-				sp->mac_control.stats_info->sw_stat.
-				rx_fcs_err_cnt++;
+		case 6:
+			swstats->rx_fcs_err_cnt++;
 			break;
 
-			case 7:
-				sp->mac_control.stats_info->sw_stat.
-				rx_buf_size_err_cnt++;
+		case 7:
+			swstats->rx_buf_size_err_cnt++;
 			break;
 
-			case 8:
-				sp->mac_control.stats_info->sw_stat.
-				rx_rxd_corrupt_cnt++;
+		case 8:
+			swstats->rx_rxd_corrupt_cnt++;
 			break;
 
-			case 15:
-				sp->mac_control.stats_info->sw_stat.
-				rx_unkn_err_cnt++;
+		case 15:
+			swstats->rx_unkn_err_cnt++;
 			break;
 		}
 		/*
-		* Drop the packet if bad transfer code. Exception being
-		* 0x5, which could be due to unsupported IPv6 extension header.
-		* In this case, we let stack handle the packet.
-		* Note that in this case, since checksum will be incorrect,
-		* stack will validate the same.
-		*/
+		 * Drop the packet if bad transfer code. Exception being
+		 * 0x5, which could be due to unsupported IPv6 extension header.
+		 * In this case, we let stack handle the packet.
+		 * Note that in this case, since checksum will be incorrect,
+		 * stack will validate the same.
+		 */
 		if (err_mask != 0x5) {
 			DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%x\n",
-				dev->name, err_mask);
-			sp->stats.rx_crc_errors++;
-			sp->mac_control.stats_info->sw_stat.mem_freed 
+				  dev->name, err_mask);
+			sp->dev_stats.rx_crc_errors++;
+			swstats->mem_freed
 				+= skb->truesize;
 			dev_kfree_skb(skb);
-			atomic_dec(&sp->rx_bufs_left[ring_no]);
+			ring_data->rx_bufs_left -= 1;
 			rxdp->Host_Control = 0;
 			return 0;
 		}
 	}
 
 	/* Updating statistics */
-	sp->stats.rx_packets++;
+	ring_data->rx_packets++;
 	rxdp->Host_Control = 0;
 	if (sp->rxd_mode == RXD_MODE_1) {
 		int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2);
 
-		sp->stats.rx_bytes += len;
+		ring_data->rx_bytes += len;
 		skb_put(skb, len);
 
 	} else if (sp->rxd_mode == RXD_MODE_3B) {
@@ -6790,13 +7504,14 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
 		unsigned char *buff = skb_push(skb, buf0_len);
 
 		struct buffAdd *ba = &ring_data->ba[get_block][get_off];
-		sp->stats.rx_bytes += buf0_len + buf2_len;
+		ring_data->rx_bytes += buf0_len + buf2_len;
 		memcpy(buff, ba->ba_0, buf0_len);
 		skb_put(skb, buf2_len);
 	}
 
-	if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && ((!sp->lro) ||
-	    (sp->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) &&
+	if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) &&
+	    ((!ring_data->lro) ||
+	     (ring_data->lro && (!(rxdp->Control_1 & RXD_FRAME_IP_FRAG)))) &&
 	    (sp->rx_csum)) {
 		l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);
 		l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);
@@ -6807,55 +7522,48 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
 			 * a flag in the RxD.
 			 */
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
-			if (sp->lro) {
+			if (ring_data->lro) {
 				u32 tcp_len;
 				u8 *tcp;
 				int ret = 0;
 
-				ret = s2io_club_tcp_session(skb->data, &tcp,
-						&tcp_len, &lro, rxdp, sp);
+				ret = s2io_club_tcp_session(ring_data,
+							    skb->data, &tcp,
+							    &tcp_len, &lro,
+							    rxdp, sp);
 				switch (ret) {
-					case 3: /* Begin anew */
-						lro->parent = skb;
-						goto aggregate;
-					case 1: /* Aggregate */
-					{
-						lro_append_pkt(sp, lro,
-							skb, tcp_len);
-						goto aggregate;
-					}
-					case 4: /* Flush session */
-					{
-						lro_append_pkt(sp, lro,
-							skb, tcp_len);
-						queue_rx_frame(lro->parent);
-						clear_lro_session(lro);
-						sp->mac_control.stats_info->
-						    sw_stat.flush_max_pkts++;
-						goto aggregate;
-					}
-					case 2: /* Flush both */
-						lro->parent->data_len =
-							lro->frags_len;
-						sp->mac_control.stats_info->
-						     sw_stat.sending_both++;
-						queue_rx_frame(lro->parent);
-						clear_lro_session(lro);
-						goto send_up;
-					case 0: /* sessions exceeded */
-					case -1: /* non-TCP or not
-						  * L2 aggregatable
-						  */
-					case 5: /*
-						 * First pkt in session not
-						 * L3/L4 aggregatable
-						 */
-						break;
-					default:
-						DBG_PRINT(ERR_DBG,
-							"%s: Samadhana!!\n",
-							 __FUNCTION__);
-						BUG();
+				case 3: /* Begin anew */
+					lro->parent = skb;
+					goto aggregate;
+				case 1: /* Aggregate */
+					lro_append_pkt(sp, lro, skb, tcp_len);
+					goto aggregate;
+				case 4: /* Flush session */
+					lro_append_pkt(sp, lro, skb, tcp_len);
+					queue_rx_frame(lro->parent,
+						       lro->vlan_tag);
+					clear_lro_session(lro);
+					swstats->flush_max_pkts++;
+					goto aggregate;
+				case 2: /* Flush both */
+					lro->parent->data_len = lro->frags_len;
+					swstats->sending_both++;
+					queue_rx_frame(lro->parent,
+						       lro->vlan_tag);
+					clear_lro_session(lro);
+					goto send_up;
+				case 0: /* sessions exceeded */
+				case -1: /* non-TCP or not L2 aggregatable */
+				case 5: /*
+					 * First pkt in session not
+					 * L3/L4 aggregatable
+					 */
+					break;
+				default:
+					DBG_PRINT(ERR_DBG,
+						  "%s: Samadhana!!\n",
+						  __func__);
+					BUG();
 				}
 			}
 		} else {
@@ -6865,34 +7573,16 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
 			 */
 			skb->ip_summed = CHECKSUM_NONE;
 		}
-	} else {
+	} else
 		skb->ip_summed = CHECKSUM_NONE;
-	}
-	sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
-	if (!sp->lro) {
-		skb->protocol = eth_type_trans(skb, dev);
-		if ((sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2) &&
-			vlan_strip_flag)) {
-			/* Queueing the vlan frame to the upper layer */
-			if (napi)
-				vlan_hwaccel_receive_skb(skb, sp->vlgrp,
-					RXD_GET_VLAN_TAG(rxdp->Control_2));
-			else
-				vlan_hwaccel_rx(skb, sp->vlgrp,
-					RXD_GET_VLAN_TAG(rxdp->Control_2));
-		} else {
-			if (napi)
-				netif_receive_skb(skb);
-			else
-				netif_rx(skb);
-		}
-	} else {
+
+	swstats->mem_freed += skb->truesize;
 send_up:
-		queue_rx_frame(skb);
-	}
+	skb_record_rx_queue(skb, ring_no);
+	queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2));
 	dev->last_rx = jiffies;
 aggregate:
-	atomic_dec(&sp->rx_bufs_left[ring_no]);
+	sp->mac_control.rings[ring_no].rx_bufs_left -= 1;
 	return SUCCESS;
 }
 
@@ -6909,25 +7599,29 @@ aggregate:
  *  void.
  */
 
-static void s2io_link(struct s2io_nic * sp, int link)
+static void s2io_link(struct s2io_nic *sp, int link)
 {
-	struct net_device *dev = (struct net_device *) sp->dev;
+	struct net_device *dev = (struct net_device *)sp->dev;
+	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
 	if (link != sp->last_link_state) {
+		init_tti(sp, link);
 		if (link == LINK_DOWN) {
 			DBG_PRINT(ERR_DBG, "%s: Link down\n", dev->name);
+			s2io_stop_all_tx_queue(sp);
 			netif_carrier_off(dev);
-			if(sp->mac_control.stats_info->sw_stat.link_up_cnt)
-			sp->mac_control.stats_info->sw_stat.link_up_time = 
-				jiffies - sp->start_time;
-			sp->mac_control.stats_info->sw_stat.link_down_cnt++;
+			if (swstats->link_up_cnt)
+				swstats->link_up_time =
+					jiffies - sp->start_time;
+			swstats->link_down_cnt++;
 		} else {
 			DBG_PRINT(ERR_DBG, "%s: Link Up\n", dev->name);
-			if (sp->mac_control.stats_info->sw_stat.link_down_cnt)
-			sp->mac_control.stats_info->sw_stat.link_down_time = 
-				jiffies - sp->start_time;
-			sp->mac_control.stats_info->sw_stat.link_up_cnt++;
+			if (swstats->link_down_cnt)
+				swstats->link_down_time =
+					jiffies - sp->start_time;
+			swstats->link_up_cnt++;
 			netif_carrier_on(dev);
+			s2io_wake_all_tx_queue(sp);
 		}
 	}
 	sp->last_link_state = link;
@@ -6935,23 +7629,6 @@ static void s2io_link(struct s2io_nic * sp, int link)
 }
 
 /**
- *  get_xena_rev_id - to identify revision ID of xena.
- *  @pdev : PCI Dev structure
- *  Description:
- *  Function to identify the Revision ID of xena.
- *  Return value:
- *  returns the revision ID of the device.
- */
-
-static int get_xena_rev_id(struct pci_dev *pdev)
-{
-	u8 id = 0;
-	int ret;
-	ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
-	return id;
-}
-
-/**
  *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
  *  @sp : private member of the device structure, which is a pointer to the
  *  s2io_nic structure.
@@ -6962,7 +7639,7 @@ static int get_xena_rev_id(struct pci_dev *pdev)
  *  void
  */
 
-static void s2io_init_pci(struct s2io_nic * sp)
+static void s2io_init_pci(struct s2io_nic *sp)
 {
 	u16 pci_cmd = 0, pcix_cmd = 0;
 
@@ -6981,47 +7658,65 @@ static void s2io_init_pci(struct s2io_nic * sp)
 	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
 }
 
-static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
+static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type,
+			    u8 *dev_multiq)
 {
-	if ( tx_fifo_num > 8) {
-		DBG_PRINT(ERR_DBG, "s2io: Requested number of Tx fifos not "
-			 "supported\n");
-		DBG_PRINT(ERR_DBG, "s2io: Default to 8 Tx fifos\n");
-		tx_fifo_num = 8;
+	if ((tx_fifo_num > MAX_TX_FIFOS) || (tx_fifo_num < 1)) {
+		DBG_PRINT(ERR_DBG, "Requested number of tx fifos "
+			  "(%d) not supported\n", tx_fifo_num);
+
+		if (tx_fifo_num < 1)
+			tx_fifo_num = 1;
+		else
+			tx_fifo_num = MAX_TX_FIFOS;
+
+		DBG_PRINT(ERR_DBG, "Default to %d tx fifos\n", tx_fifo_num);
 	}
-	if ( rx_ring_num > 8) {
-		DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
-			 "supported\n");
-		DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n");
-		rx_ring_num = 8;
+
+	if (multiq)
+		*dev_multiq = multiq;
+
+	if (tx_steering_type && (1 == tx_fifo_num)) {
+		if (tx_steering_type != TX_DEFAULT_STEERING)
+			DBG_PRINT(ERR_DBG,
+				  "Tx steering is not supported with "
+				  "one fifo. Disabling Tx steering.\n");
+		tx_steering_type = NO_STEERING;
 	}
-	if (*dev_intr_type != INTA)
-		napi = 0;
 
-#ifndef CONFIG_PCI_MSI
-	if (*dev_intr_type != INTA) {
-		DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
-			  "MSI/MSI-X. Defaulting to INTA\n");
-		*dev_intr_type = INTA;
+	if ((tx_steering_type < NO_STEERING) ||
+	    (tx_steering_type > TX_DEFAULT_STEERING)) {
+		DBG_PRINT(ERR_DBG,
+			  "Requested transmit steering not supported\n");
+		DBG_PRINT(ERR_DBG, "Disabling transmit steering\n");
+		tx_steering_type = NO_STEERING;
 	}
-#else
+
+	if (rx_ring_num > MAX_RX_RINGS) {
+		DBG_PRINT(ERR_DBG,
+			  "Requested number of rx rings not supported\n");
+		DBG_PRINT(ERR_DBG, "Default to %d rx rings\n",
+			  MAX_RX_RINGS);
+		rx_ring_num = MAX_RX_RINGS;
+	}
+
 	if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) {
-		DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
+		DBG_PRINT(ERR_DBG, "Wrong intr_type requested. "
 			  "Defaulting to INTA\n");
 		*dev_intr_type = INTA;
 	}
-#endif
+
 	if ((*dev_intr_type == MSI_X) &&
-			((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
-			(pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
-		DBG_PRINT(ERR_DBG, "s2io: Xframe I does not support MSI_X. "
-					"Defaulting to INTA\n");
+	    ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+	     (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+		DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. "
+			  "Defaulting to INTA\n");
 		*dev_intr_type = INTA;
 	}
 
 	if ((rx_ring_mode != 1) && (rx_ring_mode != 2)) {
-		DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n");
-		DBG_PRINT(ERR_DBG, "s2io: Defaulting to 1-buffer mode\n");
+		DBG_PRINT(ERR_DBG, "Requested ring mode not supported\n");
+		DBG_PRINT(ERR_DBG, "Defaulting to 1-buffer mode\n");
 		rx_ring_mode = 1;
 	}
 	return SUCCESS;
@@ -7030,7 +7725,7 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
 /**
  * rts_ds_steer - Receive traffic steering based on IPv4 or IPv6 TOS
  * or Traffic class respectively.
- * @nic: device peivate variable
+ * @nic: device private variable
  * Description: The function configures the receive steering to
  * desired receive ring.
  * Return Value:  SUCCESS on success and
@@ -7054,8 +7749,38 @@ static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring)
 	writeq(val64, &bar0->rts_ds_mem_ctrl);
 
 	return wait_for_cmd_complete(&bar0->rts_ds_mem_ctrl,
-				RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED,
-				S2IO_BIT_RESET);
+				     RTS_DS_MEM_CTRL_STROBE_CMD_BEING_EXECUTED,
+				     S2IO_BIT_RESET);
+}
+
+static const struct net_device_ops s2io_netdev_ops = {
+	.ndo_open	        = s2io_open,
+	.ndo_stop	        = s2io_close,
+	.ndo_get_stats	        = s2io_get_stats,
+	.ndo_start_xmit    	= s2io_xmit,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_multicast_list = s2io_set_multicast,
+	.ndo_do_ioctl	   	= s2io_ioctl,
+	.ndo_set_mac_address    = s2io_set_mac_addr,
+	.ndo_change_mtu	   	= s2io_change_mtu,
+	.ndo_vlan_rx_register   = s2io_vlan_rx_register,
+	.ndo_tx_timeout	   	= s2io_tx_watchdog,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller    = s2io_netpoll,
+#endif
+};
+
+static void s2io_napi_del_all_rings(struct s2io_nic *sp)
+{
+	struct ring_info *ring;
+	int i;
+
+	for (i = 0; i < sp->config.rx_ring_num; i++) {
+		ring = &sp->mac_control.rings[i];
+		if (!ring->napi.dev)
+			break;
+		netif_napi_del(&ring->napi);
+	}
 }
 
 /**
@@ -7078,49 +7803,56 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	struct s2io_nic *sp;
 	struct net_device *dev;
 	int i, j, ret;
-	int dma_flag = FALSE;
+	int dma_flag = false;
 	u32 mac_up, mac_down;
 	u64 val64 = 0, tmp64 = 0;
 	struct XENA_dev_config __iomem *bar0 = NULL;
 	u16 subid;
-	struct mac_info *mac_control;
 	struct config_param *config;
+	struct mac_info *mac_control;
 	int mode;
 	u8 dev_intr_type = intr_type;
+	u8 dev_multiq = 0;
+	DECLARE_MAC_BUF(mac);
 
-	if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
+	ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
+	if (ret)
 		return ret;
 
-	if ((ret = pci_enable_device(pdev))) {
+	ret = pci_enable_device(pdev);
+	if (ret) {
 		DBG_PRINT(ERR_DBG,
-			  "s2io_init_nic: pci_enable_device failed\n");
+			  "%s: pci_enable_device failed\n", __func__);
 		return ret;
 	}
 
-	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-		DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n");
-		dma_flag = TRUE;
-		if (pci_set_consistent_dma_mask
-		    (pdev, DMA_64BIT_MASK)) {
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		DBG_PRINT(INIT_DBG, "%s: Using 64bit DMA\n", __func__);
+		dma_flag = true;
+		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
 			DBG_PRINT(ERR_DBG,
-				  "Unable to obtain 64bit DMA for \
-					consistent allocations\n");
+				  "Unable to obtain 64bit DMA "
+				  "for consistent allocations\n");
 			pci_disable_device(pdev);
 			return -ENOMEM;
 		}
-	} else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
-		DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 32bit DMA\n");
+	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		DBG_PRINT(INIT_DBG, "%s: Using 32bit DMA\n", __func__);
 	} else {
 		pci_disable_device(pdev);
 		return -ENOMEM;
 	}
-	if ((ret = pci_request_regions(pdev, s2io_driver_name))) {
-		DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x \n", __FUNCTION__, ret);
+	ret = pci_request_regions(pdev, s2io_driver_name);
+	if (ret) {
+		DBG_PRINT(ERR_DBG, "%s: Request Regions failed - %x\n",
+			  __func__, ret);
 		pci_disable_device(pdev);
 		return -ENODEV;
 	}
-
-	dev = alloc_etherdev(sizeof(struct s2io_nic));
+	if (dev_multiq)
+		dev = alloc_etherdev_mq(sizeof(struct s2io_nic), tx_fifo_num);
+	else
+		dev = alloc_etherdev(sizeof(struct s2io_nic));
 	if (dev == NULL) {
 		DBG_PRINT(ERR_DBG, "Device allocation failed\n");
 		pci_disable_device(pdev);
@@ -7130,30 +7862,29 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
 	pci_set_master(pdev);
 	pci_set_drvdata(pdev, dev);
-	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	/*  Private member variable initialized to s2io NIC structure */
-	sp = dev->priv;
+	sp = netdev_priv(dev);
 	memset(sp, 0, sizeof(struct s2io_nic));
 	sp->dev = dev;
 	sp->pdev = pdev;
 	sp->high_dma_flag = dma_flag;
-	sp->device_enabled_once = FALSE;
+	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;
 
-	sp->intr_type = dev_intr_type;
+	sp->config.intr_type = dev_intr_type;
 
 	if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
-		(pdev->device == PCI_DEVICE_ID_HERC_UNI))
+	    (pdev->device == PCI_DEVICE_ID_HERC_UNI))
 		sp->device_type = XFRAME_II_DEVICE;
 	else
 		sp->device_type = XFRAME_I_DEVICE;
 
-	sp->lro = lro;
+	sp->lro = lro_enable;
 
 	/* Initialize some PCI/PCI-X fields of the NIC. */
 	s2io_init_pci(sp);
@@ -7165,25 +7896,58 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	 * these parameters are not not specified during load time, they
 	 * are initialized with default values.
 	 */
-	mac_control = &sp->mac_control;
 	config = &sp->config;
+	mac_control = &sp->mac_control;
+
+	config->napi = napi;
+	config->tx_steering_type = tx_steering_type;
 
 	/* Tx side parameters. */
-	config->tx_fifo_num = tx_fifo_num;
-	for (i = 0; i < MAX_TX_FIFOS; i++) {
-		config->tx_cfg[i].fifo_len = tx_fifo_len[i];
-		config->tx_cfg[i].fifo_priority = i;
+	if (config->tx_steering_type == TX_PRIORITY_STEERING)
+		config->tx_fifo_num = MAX_TX_FIFOS;
+	else
+		config->tx_fifo_num = tx_fifo_num;
+
+	/* Initialize the fifos used for tx steering */
+	if (config->tx_fifo_num < 5) {
+		if (config->tx_fifo_num  == 1)
+			sp->total_tcp_fifos = 1;
+		else
+			sp->total_tcp_fifos = config->tx_fifo_num - 1;
+		sp->udp_fifo_idx = config->tx_fifo_num - 1;
+		sp->total_udp_fifos = 1;
+		sp->other_fifo_idx = sp->total_tcp_fifos - 1;
+	} else {
+		sp->total_tcp_fifos = (tx_fifo_num - FIFO_UDP_MAX_NUM -
+				       FIFO_OTHER_MAX_NUM);
+		sp->udp_fifo_idx = sp->total_tcp_fifos;
+		sp->total_udp_fifos = FIFO_UDP_MAX_NUM;
+		sp->other_fifo_idx = sp->udp_fifo_idx + FIFO_UDP_MAX_NUM;
+	}
+
+	config->multiq = dev_multiq;
+	for (i = 0; i < config->tx_fifo_num; i++) {
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		tx_cfg->fifo_len = tx_fifo_len[i];
+		tx_cfg->fifo_priority = i;
 	}
 
 	/* mapping the QoS priority to the configured fifos */
 	for (i = 0; i < MAX_TX_FIFOS; i++)
-		config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i];
+		config->fifo_mapping[i] = fifo_map[config->tx_fifo_num - 1][i];
+
+	/* map the hashing selector table to the configured fifos */
+	for (i = 0; i < config->tx_fifo_num; i++)
+		sp->fifo_selector[i] = fifo_selector[i];
+
 
 	config->tx_intr_type = TXD_INT_TYPE_UTILZ;
 	for (i = 0; i < config->tx_fifo_num; i++) {
-		config->tx_cfg[i].f_no_snoop =
-		    (NO_SNOOP_TXD | NO_SNOOP_TXD_BUFFER);
-		if (config->tx_cfg[i].fifo_len < 65) {
+		struct tx_fifo_config *tx_cfg = &config->tx_cfg[i];
+
+		tx_cfg->f_no_snoop = (NO_SNOOP_TXD | NO_SNOOP_TXD_BUFFER);
+		if (tx_cfg->fifo_len < 65) {
 			config->tx_intr_type = TXD_INT_TYPE_PER_LIST;
 			break;
 		}
@@ -7193,16 +7957,24 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
 	/* Rx side parameters. */
 	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] *
-		    (rxd_count[sp->rxd_mode] + 1);
-		config->rx_cfg[i].ring_priority = i;
+	for (i = 0; i < config->rx_ring_num; i++) {
+		struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+		struct ring_info *ring = &mac_control->rings[i];
+
+		rx_cfg->num_rxd = rx_ring_sz[i] * (rxd_count[sp->rxd_mode] + 1);
+		rx_cfg->ring_priority = i;
+		ring->rx_bufs_left = 0;
+		ring->rxd_mode = sp->rxd_mode;
+		ring->rxd_count = rxd_count[sp->rxd_mode];
+		ring->pdev = sp->pdev;
+		ring->dev = sp->dev;
 	}
 
 	for (i = 0; i < rx_ring_num; i++) {
-		config->rx_cfg[i].ring_org = RING_ORG_BUFF1;
-		config->rx_cfg[i].f_no_snoop =
-		    (NO_SNOOP_RXD | NO_SNOOP_RXD_BUFFER);
+		struct rx_ring_config *rx_cfg = &config->rx_cfg[i];
+
+		rx_cfg->ring_org = RING_ORG_BUFF1;
+		rx_cfg->f_no_snoop = (NO_SNOOP_RXD | NO_SNOOP_RXD_BUFFER);
 	}
 
 	/*  Setting Mac Control parameters */
@@ -7211,23 +7983,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	mac_control->mc_pause_threshold_q4q7 = mc_pause_threshold_q4q7;
 
 
-	/* Initialize Ring buffer parameters. */
-	for (i = 0; i < config->rx_ring_num; i++)
-		atomic_set(&sp->rx_bufs_left[i], 0);
-
-	/* Initialize the number of ISRs currently running */
-	atomic_set(&sp->isr_cnt, 0);
-
 	/*  initialize the shared memory used by the NIC and the host */
 	if (init_shared_mem(sp)) {
-		DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
-			  dev->name);
+		DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", dev->name);
 		ret = -ENOMEM;
 		goto mem_alloc_failed;
 	}
 
-	sp->bar0 = ioremap(pci_resource_start(pdev, 0),
-				     pci_resource_len(pdev, 0));
+	sp->bar0 = pci_ioremap_bar(pdev, 0);
 	if (!sp->bar0) {
 		DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem1\n",
 			  dev->name);
@@ -7235,8 +7998,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 		goto bar0_remap_failed;
 	}
 
-	sp->bar1 = ioremap(pci_resource_start(pdev, 2),
-				     pci_resource_len(pdev, 2));
+	sp->bar1 = pci_ioremap_bar(pdev, 2);
 	if (!sp->bar1) {
 		DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem2\n",
 			  dev->name);
@@ -7249,35 +8011,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
 	/* Initializing the BAR1 address as the start of the FIFO pointer. */
 	for (j = 0; j < MAX_TX_FIFOS; j++) {
-		mac_control->tx_FIFO_start[j] = (struct TxFIFO_element __iomem *)
-		    (sp->bar1 + (j * 0x00020000));
+		mac_control->tx_FIFO_start[j] =
+			(struct TxFIFO_element __iomem *)
+			(sp->bar1 + (j * 0x00020000));
 	}
 
 	/*  Driver entry points */
-	dev->open = &s2io_open;
-	dev->stop = &s2io_close;
-	dev->hard_start_xmit = &s2io_xmit;
-	dev->get_stats = &s2io_get_stats;
-	dev->set_multicast_list = &s2io_set_multicast;
-	dev->do_ioctl = &s2io_ioctl;
-	dev->change_mtu = &s2io_change_mtu;
+	s2io_set_netdev_ops(dev, &s2io_netdev_ops);
 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-	dev->vlan_rx_register = s2io_vlan_rx_register;
-
-	/*
-	 * will use eth_mac_addr() for  dev->set_mac_address
-	 * mac address will be set every time dev->open() is called
-	 */
-	dev->poll = s2io_poll;
-	dev->weight = 32;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	dev->poll_controller = s2io_netpoll;
-#endif
 
 	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-	if (sp->high_dma_flag == TRUE)
+	if (sp->high_dma_flag == true)
 		dev->features |= NETIF_F_HIGHDMA;
 	dev->features |= NETIF_F_TSO;
 	dev->features |= NETIF_F_TSO6;
@@ -7285,19 +8029,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 		dev->features |= NETIF_F_UFO;
 		dev->features |= NETIF_F_HW_CSUM;
 	}
-
-	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);
 
 	/* Setting swapper control on the NIC, for proper reset operation */
 	if (s2io_set_swapper(sp)) {
-		DBG_PRINT(ERR_DBG, "%s:swapper settings are wrong\n",
+		DBG_PRINT(ERR_DBG, "%s: swapper settings are wrong\n",
 			  dev->name);
 		ret = -EAGAIN;
 		goto set_swap_failed;
@@ -7307,13 +8047,48 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	if (sp->device_type & XFRAME_II_DEVICE) {
 		mode = s2io_verify_pci_mode(sp);
 		if (mode < 0) {
-			DBG_PRINT(ERR_DBG, "%s: ", __FUNCTION__);
-			DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
+			DBG_PRINT(ERR_DBG, "%s: Unsupported PCI bus mode\n",
+				  __func__);
 			ret = -EBADSLT;
 			goto set_swap_failed;
 		}
 	}
 
+	if (sp->config.intr_type == MSI_X) {
+		sp->num_entries = config->rx_ring_num + 1;
+		ret = s2io_enable_msi_x(sp);
+
+		if (!ret) {
+			ret = s2io_test_msi(sp);
+			/* rollback MSI-X, will re-enable during add_isr() */
+			remove_msix_isr(sp);
+		}
+		if (ret) {
+
+			DBG_PRINT(ERR_DBG,
+				  "MSI-X requested but failed to enable\n");
+			sp->config.intr_type = INTA;
+		}
+	}
+
+	if (config->intr_type ==  MSI_X) {
+		for (i = 0; i < config->rx_ring_num ; i++) {
+			struct ring_info *ring = &mac_control->rings[i];
+
+			ret = rhel_netif_napi_add(ring, &ring->napi,
+						  rhel_s2io_poll_msix, 64);
+			if (ret) {
+				s2io_napi_del_all_rings(sp);
+				goto napi_add_failed;
+			}
+		}
+	} else {
+		ret = rhel_netif_napi_add(sp, &sp->napi,
+					  rhel_s2io_poll_inta, 64);
+		if (ret)
+			goto napi_add_failed;
+	}
+
 	/* Not needed for Herc */
 	if (sp->device_type & XFRAME_I_DEVICE) {
 		/*
@@ -7330,12 +8105,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	 */
 	bar0 = sp->bar0;
 	val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-	    RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
+		RMAC_ADDR_CMD_MEM_OFFSET(0 + S2IO_MAC_ADDR_START_OFFSET);
 	writeq(val64, &bar0->rmac_addr_cmd_mem);
 	wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
-		      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET);
+			      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+			      S2IO_BIT_RESET);
 	tmp64 = readq(&bar0->rmac_addr_data0_mem);
-	mac_down = (u32) tmp64;
+	mac_down = (u32)tmp64;
 	mac_up = (u32) (tmp64 >> 32);
 
 	sp->def_mac_addr[0].mac_addr[3] = (u8) (mac_up);
@@ -7348,24 +8124,44 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	/*  Set the factory defined MAC address initially   */
 	dev->addr_len = ETH_ALEN;
 	memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
+	memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
+
+	/* initialize number of multicast & unicast MAC entries variables */
+	if (sp->device_type == XFRAME_I_DEVICE) {
+		config->max_mc_addr = S2IO_XENA_MAX_MC_ADDRESSES;
+		config->max_mac_addr = S2IO_XENA_MAX_MAC_ADDRESSES;
+		config->mc_start_offset = S2IO_XENA_MC_ADDR_START_OFFSET;
+	} else if (sp->device_type == XFRAME_II_DEVICE) {
+		config->max_mc_addr = S2IO_HERC_MAX_MC_ADDRESSES;
+		config->max_mac_addr = S2IO_HERC_MAX_MAC_ADDRESSES;
+		config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET;
+	}
+
+	/* store mac addresses from CAM to s2io_nic structure */
+	do_s2io_store_unicast_mc(sp);
 
+	/* Configure MSIX vector for number of rings configured plus one */
+	if ((sp->device_type == XFRAME_II_DEVICE) &&
+	    (config->intr_type == MSI_X))
+		sp->num_entries = config->rx_ring_num + 1;
+
+	/* Store the values of the MSIX table in the s2io_nic structure */
+	store_xmsi_data(sp);
 	/* reset Nic and bring it to known state */
 	s2io_reset(sp);
 
 	/*
-	 * Initialize the tasklet status and link state flags
+	 * Initialize link state flags
 	 * and the card state parameter
 	 */
-	atomic_set(&(sp->card_state), 0);
-	sp->tasklet_status = 0;
-	sp->link_state = 0;
+	sp->state = 0;
 
 	/* Initialize spinlocks */
-	spin_lock_init(&sp->tx_lock);
+	for (i = 0; i < sp->config.tx_fifo_num; i++) {
+		struct fifo_info *fifo = &mac_control->fifos[i];
 
-	if (!napi)
-		spin_lock_init(&sp->put_lock);
-	spin_lock_init(&sp->rx_lock);
+		spin_lock_init(&fifo->tx_lock);
+	}
 
 	/*
 	 * SXE-002: Configure link and activity LED to init state
@@ -7377,7 +8173,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 		val64 |= 0x0000800000000000ULL;
 		writeq(val64, &bar0->gpio_control);
 		val64 = 0x0411040400000000ULL;
-		writeq(val64, (void __iomem *) bar0 + 0x2700);
+		writeq(val64, (void __iomem *)bar0 + 0x2700);
 		val64 = readq(&bar0->gpio_control);
 	}
 
@@ -7390,65 +8186,97 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 	}
 	s2io_vpd_read(sp);
 	DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2007 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: Neterion %s (rev %d)\n", dev->name,
+		  sp->product_name, pdev->revision);
 	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", dev->name,
-			  sp->def_mac_addr[0].mac_addr[0],
-			  sp->def_mac_addr[0].mac_addr[1],
-			  sp->def_mac_addr[0].mac_addr[2],
-			  sp->def_mac_addr[0].mac_addr[3],
-			  sp->def_mac_addr[0].mac_addr[4],
-			  sp->def_mac_addr[0].mac_addr[5]);
-	DBG_PRINT(ERR_DBG, "SERIAL NUMBER: %s\n", sp->serial_num);
+	DBG_PRINT(ERR_DBG, "%s: MAC Address: %s\n",
+		  dev->name, print_mac(mac, dev->dev_addr));
+	DBG_PRINT(ERR_DBG, "Serial number: %s\n", sp->serial_num);
 	if (sp->device_type & XFRAME_II_DEVICE) {
 		mode = s2io_print_pci_mode(sp);
 		if (mode < 0) {
-			DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
 			ret = -EBADSLT;
 			unregister_netdev(dev);
 			goto set_swap_failed;
 		}
 	}
-	switch(sp->rxd_mode) {
-		case RXD_MODE_1:
-		    DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n",
-						dev->name);
-		    break;
-		case RXD_MODE_3B:
-		    DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n",
-						dev->name);
-		    break;
+	switch (sp->rxd_mode) {
+	case RXD_MODE_1:
+		DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n",
+			  dev->name);
+		break;
+	case RXD_MODE_3B:
+		DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n",
+			  dev->name);
+		break;
 	}
 
-	if (napi)
+	switch (sp->config.napi) {
+	case 0:
+		DBG_PRINT(ERR_DBG, "%s: NAPI disabled\n", dev->name);
+		break;
+	case 1:
 		DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
-	switch(sp->intr_type) {
-		case INTA:
-		    DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
-		    break;
-		case MSI_X:
-		    DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
-		    break;
+		break;
 	}
+
+	DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name,
+		  sp->config.tx_fifo_num);
+
+	DBG_PRINT(ERR_DBG, "%s: Using %d Rx ring(s)\n", dev->name,
+		  sp->config.rx_ring_num);
+
+	switch (sp->config.intr_type) {
+	case INTA:
+		DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
+		break;
+	case MSI_X:
+		DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
+		break;
+	}
+	if (sp->config.multiq) {
+		for (i = 0; i < sp->config.tx_fifo_num; i++) {
+			struct fifo_info *fifo = &mac_control->fifos[i];
+
+			fifo->multiq = config->multiq;
+		}
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support enabled\n",
+			  dev->name);
+	} else
+		DBG_PRINT(ERR_DBG, "%s: Multiqueue support disabled\n",
+			  dev->name);
+
+	switch (sp->config.tx_steering_type) {
+	case NO_STEERING:
+		DBG_PRINT(ERR_DBG, "%s: No steering enabled for transmit\n",
+			  dev->name);
+		break;
+	case TX_PRIORITY_STEERING:
+		DBG_PRINT(ERR_DBG,
+			  "%s: Priority steering enabled for transmit\n",
+			  dev->name);
+		break;
+	case TX_DEFAULT_STEERING:
+		DBG_PRINT(ERR_DBG,
+			  "%s: Default steering enabled for transmit\n",
+			  dev->name);
+	}
+
 	if (sp->lro)
 		DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
 			  dev->name);
 	if (ufo)
-		DBG_PRINT(ERR_DBG, "%s: UDP Fragmentation Offload(UFO)"
-					" enabled\n", dev->name);
+		DBG_PRINT(ERR_DBG,
+			  "%s: UDP Fragmentation Offload(UFO) enabled\n",
+			  dev->name);
 	/* Initialize device name */
 	sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name);
 
-	/* Initialize bimodal Interrupts */
-	sp->config.bimodal = bimodal;
-	if (!(sp->device_type & XFRAME_II_DEVICE) && bimodal) {
-		sp->config.bimodal = 0;
-		DBG_PRINT(ERR_DBG,"%s:Bimodal intr not supported by Xframe I\n",
-			dev->name);
-	}
+	if (vlan_tag_strip)
+		sp->vlan_strip_flag = 1;
+	else
+		sp->vlan_strip_flag = 0;
 
 	/*
 	 * Make Link state as off at this point, when the Link change
@@ -7459,13 +8287,18 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 
 	return 0;
 
-      register_failed:
-      set_swap_failed:
+register_failed:
+set_swap_failed:
+	if (config->intr_type == MSI_X)
+		s2io_napi_del_all_rings(sp);
+	else
+		netif_napi_del(&sp->napi);
+napi_add_failed:
 	iounmap(sp->bar1);
-      bar1_remap_failed:
+bar1_remap_failed:
 	iounmap(sp->bar0);
-      bar0_remap_failed:
-      mem_alloc_failed:
+bar0_remap_failed:
+mem_alloc_failed:
 	free_shared_mem(sp);
 	pci_disable_device(pdev);
 	pci_release_regions(pdev);
@@ -7487,7 +8320,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 static void __devexit s2io_rem_nic(struct pci_dev *pdev)
 {
 	struct net_device *dev =
-	    (struct net_device *) pci_get_drvdata(pdev);
+		(struct net_device *)pci_get_drvdata(pdev);
 	struct s2io_nic *sp;
 
 	if (dev == NULL) {
@@ -7497,8 +8330,12 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
 
 	flush_scheduled_work();
 
-	sp = dev->priv;
+	sp = netdev_priv(dev);
 	unregister_netdev(dev);
+	if (sp->config.intr_type == MSI_X)
+		s2io_napi_del_all_rings(sp);
+	else
+		netif_napi_del(&sp->napi);
 
 	free_shared_mem(sp);
 	iounmap(sp->bar0);
@@ -7515,7 +8352,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
  * the module loadable parameters and initializes PCI configuration space.
  */
 
-int __init s2io_starter(void)
+static int __init s2io_starter(void)
 {
 	return pci_register_driver(&s2io_driver);
 }
@@ -7535,30 +8372,32 @@ module_init(s2io_starter);
 module_exit(s2io_closer);
 
 static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
-		struct tcphdr **tcp, struct RxD_t *rxdp)
+				struct tcphdr **tcp, struct RxD_t *rxdp,
+				struct s2io_nic *sp)
 {
 	int ip_off;
 	u8 l2_type = (u8)((rxdp->Control_1 >> 37) & 0x7), ip_len;
 
 	if (!(rxdp->Control_1 & RXD_FRAME_PROTO_TCP)) {
-		DBG_PRINT(INIT_DBG,"%s: Non-TCP frames not supported for LRO\n",
-			  __FUNCTION__);
+		DBG_PRINT(INIT_DBG,
+			  "%s: Non-TCP frames not supported for LRO\n",
+			  __func__);
 		return -1;
 	}
 
-	/* TODO:
-	 * By default the VLAN field in the MAC is stripped by the card, if this
-	 * feature is turned off in rx_pa_cfg register, then the ip_off field
-	 * has to be shifted by a further 2 bytes
-	 */
-	switch (l2_type) {
-		case 0: /* DIX type */
-		case 4: /* DIX type with VLAN */
-			ip_off = HEADER_ETHERNET_II_802_3_SIZE;
-			break;
+	/* Checking for DIX type or DIX type with VLAN */
+	if ((l2_type == 0) || (l2_type == 4)) {
+		ip_off = HEADER_ETHERNET_II_802_3_SIZE;
+		/*
+		 * If vlan stripping is disabled and the frame is VLAN tagged,
+		 * shift the offset by the VLAN header size bytes.
+		 */
+		if ((!sp->vlan_strip_flag) &&
+		    (rxdp->Control_1 & RXD_FRAME_VLAN_TAG))
+			ip_off += HEADER_VLAN_SIZE;
+	} else {
 		/* LLC, SNAP etc are considered non-mergeable */
-		default:
-			return -1;
+		return -1;
 	}
 
 	*ip = (struct iphdr *)((u8 *)buffer + ip_off);
@@ -7572,39 +8411,43 @@ static int check_L2_lro_capable(u8 *buffer, struct iphdr **ip,
 static int check_for_socket_match(struct lro *lro, struct iphdr *ip,
 				  struct tcphdr *tcp)
 {
-	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
-	if ((lro->iph->saddr != ip->saddr) || (lro->iph->daddr != ip->daddr) ||
-	   (lro->tcph->source != tcp->source) || (lro->tcph->dest != tcp->dest))
+	DBG_PRINT(INFO_DBG, "%s: Been here...\n", __func__);
+	if ((lro->iph->saddr != ip->saddr) ||
+	    (lro->iph->daddr != ip->daddr) ||
+	    (lro->tcph->source != tcp->source) ||
+	    (lro->tcph->dest != tcp->dest))
 		return -1;
 	return 0;
 }
 
 static inline int get_l4_pyld_length(struct iphdr *ip, struct tcphdr *tcp)
 {
-	return(ntohs(ip->tot_len) - (ip->ihl << 2) - (tcp->doff << 2));
+	return ntohs(ip->tot_len) - (ip->ihl << 2) - (tcp->doff << 2);
 }
 
 static void initiate_new_session(struct lro *lro, u8 *l2h,
-		     struct iphdr *ip, struct tcphdr *tcp, u32 tcp_pyld_len)
+				 struct iphdr *ip, struct tcphdr *tcp,
+				 u32 tcp_pyld_len, u16 vlan_tag)
 {
-	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+	DBG_PRINT(INFO_DBG, "%s: Been here...\n", __func__);
 	lro->l2h = l2h;
 	lro->iph = ip;
 	lro->tcph = tcp;
 	lro->tcp_next_seq = tcp_pyld_len + ntohl(tcp->seq);
-	lro->tcp_ack = ntohl(tcp->ack_seq);
+	lro->tcp_ack = tcp->ack_seq;
 	lro->sg_num = 1;
 	lro->total_len = ntohs(ip->tot_len);
 	lro->frags_len = 0;
+	lro->vlan_tag = vlan_tag;
 	/*
-	 * check if we saw TCP timestamp. Other consistency checks have
-	 * already been done.
- 	 */
+	 * Check if we saw TCP timestamp.
+	 * Other consistency checks have already been done.
+	 */
 	if (tcp->doff == 8) {
-		u32 *ptr;
-		ptr = (u32 *)(tcp+1);
+		__be32 *ptr;
+		ptr = (__be32 *)(tcp+1);
 		lro->saw_ts = 1;
-		lro->cur_tsval = *(ptr+1);
+		lro->cur_tsval = ntohl(*(ptr+1));
 		lro->cur_tsecr = *(ptr+2);
 	}
 	lro->in_use = 1;
@@ -7615,8 +8458,9 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
 	struct iphdr *ip = lro->iph;
 	struct tcphdr *tcp = lro->tcph;
 	__sum16 nchk;
-	struct stat_block *statinfo = sp->mac_control.stats_info;
-	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
+
+	DBG_PRINT(INFO_DBG, "%s: Been here...\n", __func__);
 
 	/* Update L3 header */
 	ip->tot_len = htons(lro->total_len);
@@ -7630,21 +8474,21 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
 
 	/* Update tsecr field if this session has timestamps enabled */
 	if (lro->saw_ts) {
-		u32 *ptr = (u32 *)(tcp + 1);
+		__be32 *ptr = (__be32 *)(tcp + 1);
 		*(ptr+2) = lro->cur_tsecr;
 	}
 
 	/* Update counters required for calculation of
 	 * average no. of packets aggregated.
 	 */
-	statinfo->sw_stat.sum_avg_pkts_aggregated += lro->sg_num;
-	statinfo->sw_stat.num_aggregations++;
+	swstats->sum_avg_pkts_aggregated += lro->sg_num;
+	swstats->num_aggregations++;
 }
 
 static void aggregate_new_rx(struct lro *lro, struct iphdr *ip,
-		struct tcphdr *tcp, u32 l4_pyld)
+			     struct tcphdr *tcp, u32 l4_pyld)
 {
-	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+	DBG_PRINT(INFO_DBG, "%s: Been here...\n", __func__);
 	lro->total_len += l4_pyld;
 	lro->frags_len += l4_pyld;
 	lro->tcp_next_seq += l4_pyld;
@@ -7655,10 +8499,10 @@ static void aggregate_new_rx(struct lro *lro, struct iphdr *ip,
 	lro->window = tcp->window;
 
 	if (lro->saw_ts) {
-		u32 *ptr;
+		__be32 *ptr;
 		/* Update tsecr and tsval from this packet */
-		ptr = (u32 *) (tcp + 1);
-		lro->cur_tsval = *(ptr + 1);
+		ptr = (__be32 *)(tcp+1);
+		lro->cur_tsval = ntohl(*(ptr+1));
 		lro->cur_tsecr = *(ptr + 2);
 	}
 }
@@ -7668,7 +8512,7 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip,
 {
 	u8 *ptr;
 
-	DBG_PRINT(INFO_DBG,"%s: Been here...\n", __FUNCTION__);
+	DBG_PRINT(INFO_DBG, "%s: Been here...\n", __func__);
 
 	if (!tcp_pyld_len) {
 		/* Runt frame or a pure ack */
@@ -7683,8 +8527,9 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip,
 		return -1;
 
 	/* If we see ECE or CWR flags in TCP header, packet is not mergeable */
-	if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin ||
-				    tcp->ece || tcp->cwr || !tcp->ack) {
+	if (tcp->urg || tcp->psh || tcp->rst ||
+	    tcp->syn || tcp->fin ||
+	    tcp->ece || tcp->cwr || !tcp->ack) {
 		/*
 		 * Currently recognize only the ack control word and
 		 * any other control field being set would result in
@@ -7709,37 +8554,39 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip,
 
 		/* Ensure timestamp value increases monotonically */
 		if (l_lro)
-			if (l_lro->cur_tsval > *((u32 *)(ptr+2)))
+			if (l_lro->cur_tsval > ntohl(*((__be32 *)(ptr+2))))
 				return -1;
 
 		/* timestamp echo reply should be non-zero */
-		if (*((u32 *)(ptr+6)) == 0)
+		if (*((__be32 *)(ptr+6)) == 0)
 			return -1;
 	}
 
 	return 0;
 }
 
-static int
-s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
-		      struct RxD_t *rxdp, struct s2io_nic *sp)
+static int s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer,
+				 u8 **tcp, u32 *tcp_len, struct lro **lro,
+				 struct RxD_t *rxdp, struct s2io_nic *sp)
 {
 	struct iphdr *ip;
 	struct tcphdr *tcph;
 	int ret = 0, i;
+	u16 vlan_tag = 0;
+	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
-	if (!(ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
-					 rxdp))) {
-		DBG_PRINT(INFO_DBG,"IP Saddr: %x Daddr: %x\n",
-			  ip->saddr, ip->daddr);
-	} else {
+	ret = check_L2_lro_capable(buffer, &ip, (struct tcphdr **)tcp,
+				   rxdp, sp);
+	if (ret)
 		return ret;
-	}
 
+	DBG_PRINT(INFO_DBG, "IP Saddr: %x Daddr: %x\n", ip->saddr, ip->daddr);
+
+	vlan_tag = RXD_GET_VLAN_TAG(rxdp->Control_2);
 	tcph = (struct tcphdr *)*tcp;
 	*tcp_len = get_l4_pyld_length(ip, tcph);
-	for (i=0; i<MAX_LRO_SESSIONS; i++) {
-		struct lro *l_lro = &sp->lro0_n[i];
+	for (i = 0; i < MAX_LRO_SESSIONS; i++) {
+		struct lro *l_lro = &ring_data->lro0_n[i];
 		if (l_lro->in_use) {
 			if (check_for_socket_match(l_lro, ip, tcph))
 				continue;
@@ -7747,18 +8594,19 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
 			*lro = l_lro;
 
 			if ((*lro)->tcp_next_seq != ntohl(tcph->seq)) {
-				DBG_PRINT(INFO_DBG, "%s:Out of order. expected "
-					  "0x%x, actual 0x%x\n", __FUNCTION__,
+				DBG_PRINT(INFO_DBG, "%s: Out of sequence. "
+					  "expected 0x%x, actual 0x%x\n",
+					  __func__,
 					  (*lro)->tcp_next_seq,
 					  ntohl(tcph->seq));
 
-				sp->mac_control.stats_info->
-				   sw_stat.outof_sequence_pkts++;
+				swstats->outof_sequence_pkts++;
 				ret = 2;
 				break;
 			}
 
-			if (!verify_l3_l4_lro_capable(l_lro, ip, tcph,*tcp_len))
+			if (!verify_l3_l4_lro_capable(l_lro, ip, tcph,
+						      *tcp_len))
 				ret = 1; /* Aggregate */
 			else
 				ret = 2; /* Flush both */
@@ -7772,12 +8620,11 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
 		 * don't create new LRO session. Just send this
 		 * packet up.
 		 */
-		if (verify_l3_l4_lro_capable(NULL, ip, tcph, *tcp_len)) {
+		if (verify_l3_l4_lro_capable(NULL, ip, tcph, *tcp_len))
 			return 5;
-		}
 
-		for (i=0; i<MAX_LRO_SESSIONS; i++) {
-			struct lro *l_lro = &sp->lro0_n[i];
+		for (i = 0; i < MAX_LRO_SESSIONS; i++) {
+			struct lro *l_lro = &ring_data->lro0_n[i];
 			if (!(l_lro->in_use)) {
 				*lro = l_lro;
 				ret = 3; /* Begin anew */
@@ -7787,30 +8634,30 @@ s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
 	}
 
 	if (ret == 0) { /* sessions exceeded */
-		DBG_PRINT(INFO_DBG,"%s:All LRO sessions already in use\n",
-			  __FUNCTION__);
+		DBG_PRINT(INFO_DBG, "%s: All LRO sessions already in use\n",
+			  __func__);
 		*lro = NULL;
 		return ret;
 	}
 
 	switch (ret) {
-		case 3:
-			initiate_new_session(*lro, buffer, ip, tcph, *tcp_len);
-			break;
-		case 2:
+	case 3:
+		initiate_new_session(*lro, buffer, ip, tcph, *tcp_len,
+				     vlan_tag);
+		break;
+	case 2:
+		update_L3L4_header(sp, *lro);
+		break;
+	case 1:
+		aggregate_new_rx(*lro, ip, tcph, *tcp_len);
+		if ((*lro)->sg_num == sp->lro_max_aggr_per_sess) {
 			update_L3L4_header(sp, *lro);
-			break;
-		case 1:
-			aggregate_new_rx(*lro, ip, tcph, *tcp_len);
-			if ((*lro)->sg_num == sp->lro_max_aggr_per_sess) {
-				update_L3L4_header(sp, *lro);
-				ret = 4; /* Flush the LRO */
-			}
-			break;
-		default:
-			DBG_PRINT(ERR_DBG,"%s:Dont know, can't say!!\n",
-				__FUNCTION__);
-			break;
+			ret = 4; /* Flush the LRO */
+		}
+		break;
+	default:
+		DBG_PRINT(ERR_DBG, "%s: Don't know, can't say!!\n", __func__);
+		break;
 	}
 
 	return ret;
@@ -7823,22 +8670,31 @@ static void clear_lro_session(struct lro *lro)
 	memset(lro, 0, lro_struct_size);
 }
 
-static void queue_rx_frame(struct sk_buff *skb)
+static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
 {
 	struct net_device *dev = skb->dev;
+	struct s2io_nic *sp = netdev_priv(dev);
 
 	skb->protocol = eth_type_trans(skb, dev);
-	if (napi)
-		netif_receive_skb(skb);
-	else
-		netif_rx(skb);
+	if (sp->vlgrp && vlan_tag && (sp->vlan_strip_flag)) {
+		/* Queueing the vlan frame to the upper layer */
+		if (sp->config.napi)
+			vlan_hwaccel_receive_skb(skb, sp->vlgrp, vlan_tag);
+		else
+			vlan_hwaccel_rx(skb, sp->vlgrp, vlan_tag);
+	} else {
+		if (sp->config.napi)
+			netif_receive_skb(skb);
+		else
+			netif_rx(skb);
+	}
 }
 
 static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
-			   struct sk_buff *skb,
-			   u32 tcp_len)
+			   struct sk_buff *skb, u32 tcp_len)
 {
 	struct sk_buff *first = lro->parent;
+	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
 	first->len += tcp_len;
 	first->data_len = lro->frags_len;
@@ -7849,26 +8705,29 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
 		skb_shinfo(first)->frag_list = skb;
 	first->truesize += skb->truesize;
 	lro->last_frag = skb;
-	sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
+	swstats->clubbed_frms_cnt++;
 	return;
 }
 
 /**
  * s2io_io_error_detected - called when PCI error is detected
  * @pdev: Pointer to PCI device
- * @state: The current pci conneection state
+ * @state: The current pci connection state
  *
  * This function is called after a PCI bus error affecting
  * this device has been detected.
  */
 static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
-                                               pci_channel_state_t state)
+					       pci_channel_state_t state)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct s2io_nic *sp = netdev->priv;
+	struct s2io_nic *sp = netdev_priv(netdev);
 
 	netif_device_detach(netdev);
 
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
 	if (netif_running(netdev)) {
 		/* Bring down the card, while avoiding PCI I/O */
 		do_s2io_card_down(sp, 0);
@@ -7890,11 +8749,10 @@ static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
 static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct s2io_nic *sp = netdev->priv;
+	struct s2io_nic *sp = netdev_priv(netdev);
 
 	if (pci_enable_device(pdev)) {
-		printk(KERN_ERR "s2io: "
-		       "Cannot re-enable PCI device after reset.\n");
+		pr_err("Cannot re-enable PCI device after reset.\n");
 		return PCI_ERS_RESULT_DISCONNECT;
 	}
 
@@ -7914,23 +8772,21 @@ static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
 static void s2io_io_resume(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct s2io_nic *sp = netdev->priv;
+	struct s2io_nic *sp = netdev_priv(netdev);
 
 	if (netif_running(netdev)) {
 		if (s2io_card_up(sp)) {
-			printk(KERN_ERR "s2io: "
-			       "Can't bring device back up after reset.\n");
+			pr_err("Can't bring device back up after reset.\n");
 			return;
 		}
 
 		if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
 			s2io_card_down(sp);
-			printk(KERN_ERR "s2io: "
-			       "Can't resetore mac addr after reset.\n");
+			pr_err("Can't restore mac addr after reset.\n");
 			return;
 		}
 	}
 
 	netif_device_attach(netdev);
-	netif_wake_queue(netdev);
+	netif_tx_wake_all_queues(netdev);
 }
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 6436e28..71b9853 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -14,23 +14,15 @@
 #define _S2IO_H
 
 #define TBD 0
-#define BIT(loc)		(0x8000000000000000ULL >> (loc))
+#define s2BIT(loc)		(0x8000000000000000ULL >> (loc))
 #define vBIT(val, loc, sz)	(((u64)val) << (64-loc-sz))
 #define INV(d)  ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff)
 
-#ifndef BOOL
-#define BOOL    int
-#endif
-
-#ifndef TRUE
-#define TRUE    1
-#define FALSE   0
-#endif
-
 #undef SUCCESS
 #define SUCCESS 0
 #define FAILURE -1
 #define S2IO_MINUS_ONE 0xFFFFFFFFFFFFFFFFULL
+#define S2IO_DISABLE_MAC_ENTRY 0xFFFFFFFFFFFFULL
 #define S2IO_MAX_PCI_CONFIG_SPACE_REINIT 100
 #define S2IO_BIT_RESET 1
 #define S2IO_BIT_SET 2
@@ -72,11 +64,10 @@ enum {
 static int debug_level = ERR_DBG;
 
 /* DEBUG message print. */
-#define DBG_PRINT(dbg_level, args...)  if(!(debug_level<dbg_level)) printk(args)
-
-#ifndef DMA_ERROR_CODE
-#define DMA_ERROR_CODE          (~(dma_addr_t)0x0)
-#endif
+#define DBG_PRINT(dbg_level, fmt, args...) do {			\
+	if (dbg_level >= debug_level)				\
+		pr_info(fmt, ##args);				\
+	} while (0)
 
 /* Protocol assist features of the NIC */
 #define L3_CKSUM_OK 0xFFFF
@@ -91,7 +82,7 @@ struct swStat {
 	unsigned long long serious_err_cnt;
 	unsigned long long soft_reset_cnt;
 	unsigned long long fifo_full_cnt;
-	unsigned long long ring_full_cnt;
+	unsigned long long ring_full_cnt[8];
 	/* LRO statistics */
 	unsigned long long clubbed_frms_cnt;
 	unsigned long long sending_both;
@@ -126,6 +117,26 @@ struct swStat {
 	unsigned long long rx_buf_size_err_cnt;
 	unsigned long long rx_rxd_corrupt_cnt;
 	unsigned long long rx_unkn_err_cnt;
+
+	/* Error/alarm statistics*/
+	unsigned long long tda_err_cnt;
+	unsigned long long pfc_err_cnt;
+	unsigned long long pcc_err_cnt;
+	unsigned long long tti_err_cnt;
+	unsigned long long lso_err_cnt;
+	unsigned long long tpa_err_cnt;
+	unsigned long long sm_err_cnt;
+	unsigned long long mac_tmac_err_cnt;
+	unsigned long long mac_rmac_err_cnt;
+	unsigned long long xgxs_txgxs_err_cnt;
+	unsigned long long xgxs_rxgxs_err_cnt;
+	unsigned long long rc_err_cnt;
+	unsigned long long prc_pcix_err_cnt;
+	unsigned long long rpa_err_cnt;
+	unsigned long long rda_err_cnt;
+	unsigned long long rti_err_cnt;
+	unsigned long long mc_err_cnt;
+
 };
 
 /* Xpak releated alarm and warnings */
@@ -339,6 +350,11 @@ struct stat_block {
 #define MAX_TX_FIFOS 8
 #define MAX_RX_RINGS 8
 
+#define FIFO_DEFAULT_NUM	1
+#define FIFO_UDP_MAX_NUM			2 /* 0 - even, 1 -odd ports */
+#define FIFO_OTHER_MAX_NUM			1
+
+
 #define MAX_RX_DESC_1  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 127 )
 #define MAX_RX_DESC_2  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
 #define MAX_RX_DESC_3  (MAX_RX_RINGS * MAX_RX_BLOCKS_PER_RING * 85 )
@@ -356,6 +372,8 @@ static int fifo_map[][MAX_TX_FIFOS] = {
 	{0, 1, 2, 3, 4, 5, 6, 7},
 };
 
+static u16 fifo_selector[MAX_TX_FIFOS] = {0, 1, 3, 3, 7, 7, 7, 7};
+
 /* Maintains Per FIFO related information. */
 struct tx_fifo_config {
 #define	MAX_AVAILABLE_TXDS	8192
@@ -408,10 +426,21 @@ struct config_param {
 /* Tx Side */
 	u32 tx_fifo_num;	/*Number of Tx FIFOs */
 
+	/* 0-No steering, 1-Priority steering, 2-Default fifo map */
+#define	NO_STEERING				0
+#define	TX_PRIORITY_STEERING			0x1
+#define TX_DEFAULT_STEERING 			0x2
+	u8 tx_steering_type;
+
 	u8 fifo_mapping[MAX_TX_FIFOS];
 	struct tx_fifo_config tx_cfg[MAX_TX_FIFOS];	/*Per-Tx FIFO config */
 	u32 max_txds;		/*Max no. of Tx buffer descriptor per TxDL */
 	u64 tx_intr_type;
+#define INTA	0
+#define MSI_X	2
+	u8 intr_type;
+	u8 napi;
+
 	/* Specifies if Tx Intr is UTILZ or PER_LIST type. */
 
 /* Rx Side */
@@ -419,7 +448,6 @@ struct config_param {
 #define MAX_RX_BLOCKS_PER_RING  150
 
 	struct rx_ring_config rx_cfg[MAX_RX_RINGS];	/*Per-Rx Ring config */
-	u8 bimodal;		/*Flag for setting bimodal interrupts*/
 
 #define HEADER_ETHERNET_II_802_3_SIZE 14
 #define HEADER_802_2_SIZE              3
@@ -434,6 +462,10 @@ struct config_param {
 #define MAX_MTU_JUMBO               (MAX_PYLD_JUMBO+18)
 #define MAX_MTU_JUMBO_VLAN          (MAX_PYLD_JUMBO+22)
 	u16 bus_speed;
+	int max_mc_addr;	/* xena=64 herc=256 */
+	int max_mac_addr;	/* xena=16 herc=64 */
+	int mc_start_offset;	/* xena=16 herc=64 */
+	u8 multiq;
 };
 
 /* Structure representing MAC Addrs */
@@ -449,42 +481,42 @@ struct TxFIFO_element {
 
 	u64 List_Control;
 #define TX_FIFO_LAST_TXD_NUM( val)     vBIT(val,0,8)
-#define TX_FIFO_FIRST_LIST             BIT(14)
-#define TX_FIFO_LAST_LIST              BIT(15)
+#define TX_FIFO_FIRST_LIST             s2BIT(14)
+#define TX_FIFO_LAST_LIST              s2BIT(15)
 #define TX_FIFO_FIRSTNLAST_LIST        vBIT(3,14,2)
-#define TX_FIFO_SPECIAL_FUNC           BIT(23)
-#define TX_FIFO_DS_NO_SNOOP            BIT(31)
-#define TX_FIFO_BUFF_NO_SNOOP          BIT(30)
+#define TX_FIFO_SPECIAL_FUNC           s2BIT(23)
+#define TX_FIFO_DS_NO_SNOOP            s2BIT(31)
+#define TX_FIFO_BUFF_NO_SNOOP          s2BIT(30)
 };
 
 /* Tx descriptor structure */
 struct TxD {
 	u64 Control_1;
 /* bit mask */
-#define TXD_LIST_OWN_XENA       BIT(7)
-#define TXD_T_CODE              (BIT(12)|BIT(13)|BIT(14)|BIT(15))
+#define TXD_LIST_OWN_XENA       s2BIT(7)
+#define TXD_T_CODE              (s2BIT(12)|s2BIT(13)|s2BIT(14)|s2BIT(15))
 #define TXD_T_CODE_OK(val)      (|(val & TXD_T_CODE))
 #define GET_TXD_T_CODE(val)     ((val & TXD_T_CODE)<<12)
-#define TXD_GATHER_CODE         (BIT(22) | BIT(23))
-#define TXD_GATHER_CODE_FIRST   BIT(22)
-#define TXD_GATHER_CODE_LAST    BIT(23)
-#define TXD_TCP_LSO_EN          BIT(30)
-#define TXD_UDP_COF_EN          BIT(31)
-#define TXD_UFO_EN		BIT(31) | BIT(30)
+#define TXD_GATHER_CODE         (s2BIT(22) | s2BIT(23))
+#define TXD_GATHER_CODE_FIRST   s2BIT(22)
+#define TXD_GATHER_CODE_LAST    s2BIT(23)
+#define TXD_TCP_LSO_EN          s2BIT(30)
+#define TXD_UDP_COF_EN          s2BIT(31)
+#define TXD_UFO_EN		s2BIT(31) | s2BIT(30)
 #define TXD_TCP_LSO_MSS(val)    vBIT(val,34,14)
 #define TXD_UFO_MSS(val)	vBIT(val,34,14)
 #define TXD_BUFFER0_SIZE(val)   vBIT(val,48,16)
 
 	u64 Control_2;
-#define TXD_TX_CKO_CONTROL      (BIT(5)|BIT(6)|BIT(7))
-#define TXD_TX_CKO_IPV4_EN      BIT(5)
-#define TXD_TX_CKO_TCP_EN       BIT(6)
-#define TXD_TX_CKO_UDP_EN       BIT(7)
-#define TXD_VLAN_ENABLE         BIT(15)
+#define TXD_TX_CKO_CONTROL      (s2BIT(5)|s2BIT(6)|s2BIT(7))
+#define TXD_TX_CKO_IPV4_EN      s2BIT(5)
+#define TXD_TX_CKO_TCP_EN       s2BIT(6)
+#define TXD_TX_CKO_UDP_EN       s2BIT(7)
+#define TXD_VLAN_ENABLE         s2BIT(15)
 #define TXD_VLAN_TAG(val)       vBIT(val,16,16)
 #define TXD_INT_NUMBER(val)     vBIT(val,34,6)
-#define TXD_INT_TYPE_PER_LIST   BIT(47)
-#define TXD_INT_TYPE_UTILZ      BIT(46)
+#define TXD_INT_TYPE_PER_LIST   s2BIT(47)
+#define TXD_INT_TYPE_UTILZ      s2BIT(46)
 #define TXD_SET_MARKER         vBIT(0x6,0,4)
 
 	u64 Buffer_Pointer;
@@ -501,14 +533,15 @@ struct list_info_hold {
 struct RxD_t {
 	u64 Host_Control;	/* reserved for host */
 	u64 Control_1;
-#define RXD_OWN_XENA            BIT(7)
-#define RXD_T_CODE              (BIT(12)|BIT(13)|BIT(14)|BIT(15))
+#define RXD_OWN_XENA            s2BIT(7)
+#define RXD_T_CODE              (s2BIT(12)|s2BIT(13)|s2BIT(14)|s2BIT(15))
 #define RXD_FRAME_PROTO         vBIT(0xFFFF,24,8)
-#define RXD_FRAME_PROTO_IPV4    BIT(27)
-#define RXD_FRAME_PROTO_IPV6    BIT(28)
-#define RXD_FRAME_IP_FRAG	BIT(29)
-#define RXD_FRAME_PROTO_TCP     BIT(30)
-#define RXD_FRAME_PROTO_UDP     BIT(31)
+#define RXD_FRAME_VLAN_TAG      s2BIT(24)
+#define RXD_FRAME_PROTO_IPV4    s2BIT(27)
+#define RXD_FRAME_PROTO_IPV6    s2BIT(28)
+#define RXD_FRAME_IP_FRAG	s2BIT(29)
+#define RXD_FRAME_PROTO_TCP     s2BIT(30)
+#define RXD_FRAME_PROTO_UDP     s2BIT(31)
 #define TCP_OR_UDP_FRAME        (RXD_FRAME_PROTO_TCP | RXD_FRAME_PROTO_UDP)
 #define RXD_GET_L3_CKSUM(val)   ((u16)(val>> 16) & 0xFFFF)
 #define RXD_GET_L4_CKSUM(val)   ((u16)(val) & 0xFFFF)
@@ -635,11 +668,58 @@ struct rx_block_info {
 	struct rxd_info *rxds;
 };
 
+/* Data structure to represent a LRO session */
+struct lro {
+	struct sk_buff	*parent;
+	struct sk_buff  *last_frag;
+	u8		*l2h;
+	struct iphdr	*iph;
+	struct tcphdr	*tcph;
+	u32		tcp_next_seq;
+	__be32		tcp_ack;
+	int		total_len;
+	int		frags_len;
+	int		sg_num;
+	int		in_use;
+	__be16		window;
+	u16             vlan_tag;
+	u32		cur_tsval;
+	__be32		cur_tsecr;
+	u8		saw_ts;
+} ____cacheline_aligned;
+
 /* Ring specific structure */
 struct ring_info {
 	/* The ring number */
 	int ring_no;
 
+	/* per-ring buffer counter */
+	u32 rx_bufs_left;
+
+#define MAX_LRO_SESSIONS       32
+	struct lro lro0_n[MAX_LRO_SESSIONS];
+	u8		lro;
+
+	/* copy of sp->rxd_mode flag */
+	int rxd_mode;
+
+	/* Number of rxds per block for the rxd_mode */
+	int rxd_count;
+
+	/* copy of sp pointer */
+	struct s2io_nic *nic;
+
+	/* copy of sp->dev pointer */
+	struct net_device *dev;
+
+	/* copy of sp->pdev pointer */
+	struct pci_dev *pdev;
+
+	/* Per ring napi struct */
+	struct napi_struct napi;
+
+	unsigned long interrupt_count;
+
 	/*
 	 *  Place holders for the virtual and physical addresses of
 	 *  all the Rx Blocks
@@ -660,13 +740,16 @@ struct ring_info {
 	 */
 	struct rx_curr_get_info rx_curr_get_info;
 
-	/* Index to the absolute position of the put pointer of Rx ring */
-	int put_pos;
+	/* interface MTU value */
+        unsigned mtu;
 
 	/* Buffer Address store. */
 	struct buffAdd **ba;
-	struct s2io_nic *nic;
-};
+
+	/* per-Ring statistics */
+	unsigned long rx_packets;
+	unsigned long rx_bytes;
+} ____cacheline_aligned;
 
 /* Fifo specific structure */
 struct fifo_info {
@@ -690,9 +773,24 @@ struct fifo_info {
 	 * the buffers
 	 */
 	struct tx_curr_get_info tx_curr_get_info;
+#define FIFO_QUEUE_START 0
+#define FIFO_QUEUE_STOP 1
+	int queue_state;
+
+	/* copy of sp->dev pointer */
+	struct net_device *dev;
+
+	/* copy of multiq status */
+	u8 multiq;
+
+	/* Per fifo lock */
+	spinlock_t tx_lock;
+
+	/* Per fifo UFO in band structure */
+	u64 *ufo_in_band_v;
 
 	struct s2io_nic *nic;
-};
+} ____cacheline_aligned;
 
 /* Information related to the Tx and Rx FIFOs and Rings of Xena
  * is maintained in this structure.
@@ -738,7 +836,7 @@ struct usr_addr {
  * Structure to keep track of the MSI-X vectors and the corresponding
  * argument registered against each vector
  */
-#define MAX_REQUESTED_MSI_X	17
+#define MAX_REQUESTED_MSI_X	9
 struct s2io_msix_entry
 {
 	u16 vector;
@@ -746,8 +844,8 @@ struct s2io_msix_entry
 	void *arg;
 
 	u8 type;
-#define	MSIX_FIFO_TYPE	1
-#define	MSIX_RING_TYPE	2
+#define        MSIX_ALARM_TYPE         1
+#define        MSIX_RING_TYPE          2
 
 	u8 in_use;
 #define MSIX_REGISTERED_SUCCESS	0xAA
@@ -758,34 +856,20 @@ struct msix_info_st {
 	u64 data;
 };
 
-/* Data structure to represent a LRO session */
-struct lro {
-	struct sk_buff	*parent;
-	struct sk_buff  *last_frag;
-	u8		*l2h;
-	struct iphdr	*iph;
-	struct tcphdr	*tcph;
-	u32		tcp_next_seq;
-	__be32		tcp_ack;
-	int		total_len;
-	int		frags_len;
-	int		sg_num;
-	int		in_use;
-	__be16		window;
-	u32		cur_tsval;
-	u32		cur_tsecr;
-	u8		saw_ts;
+/* These flags represent the devices temporary state */
+enum s2io_device_state_t
+{
+	__S2IO_STATE_LINK_TASK=0,
+	__S2IO_STATE_CARD_UP
 };
 
 /* Network private statistics. */
 struct s2io_stats_buffer {
-
-	unsigned long   tx_packets;             /* packets transmitted    */
-	unsigned long   rx_errors;              /* bad packets received         */
-	unsigned long   tx_errors;              /* packet transmit problems     */
-	unsigned long   multicast;              /* multicast packets received   */
+	unsigned long   tx_packets;           /* packets transmitted        */
+	unsigned long   rx_errors;            /* bad packets received       */
+	unsigned long   tx_errors;            /* packet transmit problems   */
+	unsigned long   multicast;            /* multicast packets received */
 	unsigned long   rx_length_errors;
-
 };
 
 /* Structure representing one instance of the NIC */
@@ -797,7 +881,7 @@ struct s2io_nic {
 	 */
 	int pkts_to_process;
 	struct net_device *dev;
-	struct s2io_stats_buffer stats_buffer;
+	struct net_device_stats dev_stats;
 	struct mac_info mac_control;
 	struct config_param config;
 	struct pci_dev *pdev;
@@ -806,15 +890,13 @@ struct s2io_nic {
 #define MAX_MAC_SUPPORTED   16
 #define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED
 
-	struct mac_addr def_mac_addr[MAX_MAC_SUPPORTED];
+	struct mac_addr def_mac_addr[256];
 
-	struct net_device_stats stats;
+	struct s2io_stats_buffer stats_buffer;
 	int high_dma_flag;
 	int device_enabled_once;
 
 	char name[60];
-	struct tasklet_struct task;
-	volatile unsigned long tasklet_status;
 
 	/* Timer that handles I/O errors/exceptions */
 	struct timer_list alarm_timer;
@@ -822,18 +904,13 @@ struct s2io_nic {
 	/* Space to back up the PCI config space */
 	u32 config_space[256 / sizeof(u32)];
 
-	atomic_t rx_bufs_left[MAX_RX_RINGS];
-
-	spinlock_t tx_lock;
-	spinlock_t put_lock;
-
 #define PROMISC     1
 #define ALL_MULTI   2
 
 #define MAX_ADDRS_SUPPORTED 64
 	u16 usr_addr_count;
 	u16 mc_addr_count;
-	struct usr_addr usr_addrs[MAX_ADDRS_SUPPORTED];
+	struct usr_addr usr_addrs[256];
 
 	u16 m_cast_flg;
 	u16 all_multi_pos;
@@ -854,6 +931,28 @@ struct s2io_nic {
 	 */
 	int rx_csum;
 
+	/* Below variables are used for fifo selection to transmit a packet */
+	u16 fifo_selector[MAX_TX_FIFOS];
+
+	/* Total fifos for tcp packets */
+	u8 total_tcp_fifos;
+
+	/*
+	* Beginning index of udp for udp packets
+	* Value will be equal to
+	* (tx_fifo_num - FIFO_UDP_MAX_NUM - FIFO_OTHER_MAX_NUM)
+	*/
+	u8 udp_fifo_idx;
+
+	u8 total_udp_fifos;
+
+	/*
+	 * Beginning index of fifo for all other packets
+	 * Value will be equal to (tx_fifo_num - FIFO_OTHER_MAX_NUM)
+	*/
+	u8 other_fifo_idx;
+
+	struct napi_struct napi;
 	/*  after blink, the adapter must be restored with original
 	 *  values.
 	 */
@@ -866,13 +965,13 @@ struct s2io_nic {
 
 	int task_flag;
 	unsigned long long start_time;
-#define CARD_DOWN 1
-#define CARD_UP 2
-	atomic_t card_state;
-	volatile unsigned long link_state;
 	struct vlan_group *vlgrp;
+	int vlan_strip_flag;
 #define MSIX_FLG                0xA5
+	int num_entries;
 	struct msix_entry *entries;
+	int msi_detected;
+	wait_queue_head_t msi_wait;
 	struct s2io_msix_entry *s2io_entries;
 	char desc[MAX_REQUESTED_MSI_X][25];
 
@@ -884,20 +983,13 @@ struct s2io_nic {
 #define XFRAME_II_DEVICE	2
 	u8 device_type;
 
-#define MAX_LRO_SESSIONS	32
-	struct lro lro0_n[MAX_LRO_SESSIONS];
 	unsigned long	clubbed_frms_cnt;
 	unsigned long	sending_both;
 	u8		lro;
 	u16		lro_max_aggr_per_sess;
+	volatile unsigned long state;
+	u64		general_int_mask;
 
-#define INTA	0
-#define MSI_X	2
-	u8 intr_type;
-
-	spinlock_t	rx_lock;
-	atomic_t	isr_cnt;
-	u64 *ufo_in_band_v;
 #define VPD_STRING_LEN 80
 	u8  product_name[VPD_STRING_LEN];
 	u8  serial_num[VPD_STRING_LEN];
@@ -984,26 +1076,26 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
 /*  Interrupt masks for the general interrupt mask register */
 #define DISABLE_ALL_INTRS   0xFFFFFFFFFFFFFFFFULL
 
-#define TXPIC_INT_M         BIT(0)
-#define TXDMA_INT_M         BIT(1)
-#define TXMAC_INT_M         BIT(2)
-#define TXXGXS_INT_M        BIT(3)
-#define TXTRAFFIC_INT_M     BIT(8)
-#define PIC_RX_INT_M        BIT(32)
-#define RXDMA_INT_M         BIT(33)
-#define RXMAC_INT_M         BIT(34)
-#define MC_INT_M            BIT(35)
-#define RXXGXS_INT_M        BIT(36)
-#define RXTRAFFIC_INT_M     BIT(40)
+#define TXPIC_INT_M         s2BIT(0)
+#define TXDMA_INT_M         s2BIT(1)
+#define TXMAC_INT_M         s2BIT(2)
+#define TXXGXS_INT_M        s2BIT(3)
+#define TXTRAFFIC_INT_M     s2BIT(8)
+#define PIC_RX_INT_M        s2BIT(32)
+#define RXDMA_INT_M         s2BIT(33)
+#define RXMAC_INT_M         s2BIT(34)
+#define MC_INT_M            s2BIT(35)
+#define RXXGXS_INT_M        s2BIT(36)
+#define RXTRAFFIC_INT_M     s2BIT(40)
 
 /*  PIC level Interrupts TODO*/
 
 /*  DMA level Inressupts */
-#define TXDMA_PFC_INT_M     BIT(0)
-#define TXDMA_PCC_INT_M     BIT(2)
+#define TXDMA_PFC_INT_M     s2BIT(0)
+#define TXDMA_PCC_INT_M     s2BIT(2)
 
 /*  PFC block interrupts */
-#define PFC_MISC_ERR_1      BIT(0)	/* Interrupt to indicate FIFO full */
+#define PFC_MISC_ERR_1      s2BIT(0)	/* Interrupt to indicate FIFO full */
 
 /* PCC block interrupts. */
 #define	PCC_FB_ECC_ERR	   vBIT(0xff, 16, 8)	/* Interrupt to indicate
@@ -1019,21 +1111,22 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev);
 static int init_shared_mem(struct s2io_nic *sp);
 static void free_shared_mem(struct s2io_nic *sp);
 static int init_nic(struct s2io_nic *nic);
-static void rx_intr_handler(struct ring_info *ring_data);
+static int rx_intr_handler(struct ring_info *ring_data, int budget);
+static void s2io_txpic_intr_handle(struct s2io_nic *sp);
 static void tx_intr_handler(struct fifo_info *fifo_data);
-static void alarm_intr_handler(struct s2io_nic *sp);
+static void s2io_handle_errors(void * dev_id);
 
 static int s2io_starter(void);
 static void s2io_closer(void);
 static void s2io_tx_watchdog(struct net_device *dev);
-static void s2io_tasklet(unsigned long dev_addr);
 static void s2io_set_multicast(struct net_device *dev);
 static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp);
 static void s2io_link(struct s2io_nic * sp, int link);
 static void s2io_reset(struct s2io_nic * sp);
-static int s2io_poll(struct net_device *dev, int *budget);
+static int s2io_poll_msix(struct napi_struct *napi, int budget);
+static int s2io_poll_inta(struct napi_struct *napi, int budget);
 static void s2io_init_pci(struct s2io_nic * sp);
-static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr);
 static void s2io_alarm_handle(unsigned long data);
 static irqreturn_t
 s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
@@ -1042,23 +1135,31 @@ s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
 static int verify_xena_quiescence(struct s2io_nic *sp);
 static struct ethtool_ops netdev_ethtool_ops;
-static void s2io_set_link(unsigned long data);
+static void s2io_set_link(struct work_struct *work);
 static int s2io_set_swapper(struct s2io_nic * sp);
 static void s2io_card_down(struct s2io_nic *nic);
 static int s2io_card_up(struct s2io_nic *nic);
-static int get_xena_rev_id(struct pci_dev *pdev);
 static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
 					int bit_state);
 static int s2io_add_isr(struct s2io_nic * sp);
 static void s2io_rem_isr(struct s2io_nic * sp);
 
 static void restore_xmsi_data(struct s2io_nic *nic);
-
-static int s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro, struct RxD_t *rxdp, struct s2io_nic *sp);
+static void do_s2io_store_unicast_mc(struct s2io_nic *sp);
+static void do_s2io_restore_unicast_mc(struct s2io_nic *sp);
+static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset);
+static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr);
+static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int offset);
+static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr);
+
+static int s2io_club_tcp_session(struct ring_info *ring_data, u8 *buffer,
+	u8 **tcp, u32 *tcp_len, struct lro **lro, struct RxD_t *rxdp,
+	struct s2io_nic *sp);
 static void clear_lro_session(struct lro *lro);
-static void queue_rx_frame(struct sk_buff *skb);
+static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag);
 static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro);
-static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro, struct sk_buff *skb, u32 tcp_len);
+static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
+			   struct sk_buff *skb, u32 tcp_len);
 static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
 
 static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,