Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Michal Schmidt <mschmidt@redhat.com>
Date: Wed, 25 Nov 2009 17:09:49 -0500
Subject: [net] vxge: driver update to 2.0.6
Message-id: <20091125180949.34b0f220@leela>
Patchwork-id: 21497
O-Subject: [RHEL5.5 PATCH BZ453683] vxge: driver update to 2.0.6
Bugzilla: 453683

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

This updates the vxge driver for Neterion X3100 Series 10GbE adapters.
It corresponds to the current upstream version + fixes from
net-next-2.6. It enables GRO.
The required firmware version is 1.4.4. (strongly recommended by
Neterion).

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

Testing:
Ramkrishna Vepa @Neterion ran basic tests with no problems. Neterion
will continue testing.

Upstream status:
The driver is present in 2.6.32-rc8 + 9 fixes from net-next-2.6.

--
Michal

Signed-off-by: Don Zickus <dzickus@redhat.com>

diff --git a/drivers/net/vxge/vxge-compat.h b/drivers/net/vxge/vxge-compat.h
index 24e7611..47588b4 100644
--- a/drivers/net/vxge/vxge-compat.h
+++ b/drivers/net/vxge/vxge-compat.h
@@ -3,6 +3,8 @@
 
 #include <linux/if_vlan.h>
 
+#define ETH_FCS_LEN	4	/* Octets in the FCS */
+
 static inline int vxge_pci_dma_mapping_error(struct pci_dev *pdev,
 					     dma_addr_t dma_addr)
 {
@@ -23,7 +25,7 @@ static inline void vlan_group_set_device(struct vlan_group *vg,
 }
 
 static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
-						        u16 vid)
+						       u16 vid)
 {
 	return vg ? vg->vlan_devices[vid] : NULL;
 }
@@ -33,7 +35,7 @@ static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
  */
 
 static inline struct net_device *alloc_etherdev_mq(int sizeof_priv,
-				     unsigned int queue_count)
+						   unsigned int queue_count)
 {
 	WARN_ON(queue_count != 1);
 	return alloc_etherdev(sizeof_priv);
@@ -83,8 +85,67 @@ static inline void skb_record_rx_queue(struct sk_buff *skb, u16 rx_queue)
 }
 
 /*
+ * 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 vxge_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);
+}
+
+/*
  * These are only used with TX_MULTIQ_STEERING,
- * and so should never be called in RHEL.
+ * and so should never be called in RHEL5.
  */
 
 static inline u16 skb_get_queue_mapping(const struct sk_buff *skb)
@@ -100,4 +161,57 @@ static inline int netif_subqueue_stopped(const struct net_device *dev,
 	return netif_queue_stopped(dev);
 }
 
+typedef int netdev_tx_t;
+
+/*
+ * net_device_ops copied from upstream, but only the members actually
+ * used by the vxge 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);
+	void			(*ndo_vlan_rx_add_vid)(struct net_device *dev,
+						       unsigned short vid);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	void                    (*ndo_poll_controller)(struct net_device *dev);
+#endif
+};
+
+#define eth_validate_addr NULL
+
+static inline void vxge_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;
+	ndev->vlan_rx_add_vid    = ndo->ndo_vlan_rx_add_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	ndev->poll_controller    = ndo->ndo_poll_controller;
+#endif
+}
+
 #endif /* __VXGE_COMPAT_H */
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
index 6287a4b..a8662e3 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/vxge/vxge-config.c
@@ -315,14 +315,6 @@ __vxge_hw_device_reg_addr_get(struct __vxge_hw_device *hldev)
 		hldev->kdfc = (u8 __iomem *)(hldev->bar0 +
 			VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
 		break;
-	case 2:
-		hldev->kdfc = (u8 __iomem *)(hldev->bar1 +
-			VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
-		break;
-	case 4:
-		hldev->kdfc = (u8 __iomem *)(hldev->bar2 +
-			VXGE_HW_TOC_GET_KDFC_INITIAL_OFFSET(val64));
-		break;
 	default:
 		break;
 	}
@@ -366,10 +358,8 @@ __vxge_hw_device_access_rights_get(u32 host_type, u32 func_id)
 
 	switch (host_type) {
 	case VXGE_HW_NO_MR_NO_SR_NORMAL_FUNCTION:
-		if (func_id == 0) {
-			access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
-					VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
-		}
+		access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
+				VXGE_HW_DEVICE_ACCESS_RIGHT_SRPCIM;
 		break;
 	case VXGE_HW_MR_NO_SR_VH0_BASE_FUNCTION:
 		access_rights |= VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM |
@@ -392,6 +382,22 @@ __vxge_hw_device_access_rights_get(u32 host_type, u32 func_id)
 	return access_rights;
 }
 /*
+ * __vxge_hw_device_is_privilaged
+ * This routine checks if the device function is privilaged or not
+ */
+
+enum vxge_hw_status
+__vxge_hw_device_is_privilaged(u32 host_type, u32 func_id)
+{
+	if (__vxge_hw_device_access_rights_get(host_type,
+		func_id) &
+		VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM)
+		return VXGE_HW_OK;
+	else
+		return VXGE_HW_ERR_PRIVILAGED_OPEARATION;
+}
+
+/*
  * __vxge_hw_device_host_info_get
  * This routine returns the host type assignments
  */
@@ -456,220 +462,6 @@ __vxge_hw_verify_pci_e_info(struct __vxge_hw_device *hldev)
 	return VXGE_HW_OK;
 }
 
-static enum vxge_hw_status
-__vxge_hw_device_is_privilaged(struct __vxge_hw_device *hldev)
-{
-	if ((hldev->host_type == VXGE_HW_NO_MR_NO_SR_NORMAL_FUNCTION ||
-	hldev->host_type == VXGE_HW_MR_NO_SR_VH0_BASE_FUNCTION ||
-	hldev->host_type == VXGE_HW_NO_MR_SR_VH0_FUNCTION0) &&
-	(hldev->func_id == 0))
-		return VXGE_HW_OK;
-	else
-		return VXGE_HW_ERR_PRIVILAGED_OPEARATION;
-}
-
-/*
- * vxge_hw_wrr_rebalance - Rebalance the RX_WRR and KDFC_WRR calandars.
- * Rebalance the RX_WRR and KDFC_WRR calandars.
- */
-static enum
-vxge_hw_status vxge_hw_wrr_rebalance(struct __vxge_hw_device *hldev)
-{
-	u64 val64;
-	u32 wrr_states[VXGE_HW_WEIGHTED_RR_SERVICE_STATES];
-	u32 i, j, how_often = 1;
-	enum vxge_hw_status status = VXGE_HW_OK;
-
-	status = __vxge_hw_device_is_privilaged(hldev);
-	if (status != VXGE_HW_OK)
-		goto exit;
-
-	/* Reset the priorities assigned to the WRR arbitration
-	phases for the receive traffic */
-	for (i = 0; i < VXGE_HW_WRR_RING_COUNT; i++)
-		writeq(0, ((&hldev->mrpcim_reg->rx_w_round_robin_0) + i));
-
-	/* Reset the transmit FIFO servicing calendar for FIFOs */
-	for (i = 0; i < VXGE_HW_WRR_FIFO_COUNT; i++) {
-		writeq(0, ((&hldev->mrpcim_reg->kdfc_w_round_robin_0) + i));
-		writeq(0, ((&hldev->mrpcim_reg->kdfc_w_round_robin_20) + i));
-	}
-
-	/* Assign WRR priority  0 for all FIFOs */
-	for (i = 1; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-		writeq(VXGE_HW_KDFC_FIFO_0_CTRL_WRR_NUMBER(0),
-				((&hldev->mrpcim_reg->kdfc_fifo_0_ctrl)  + i));
-
-		writeq(VXGE_HW_KDFC_FIFO_17_CTRL_WRR_NUMBER(0),
-			((&hldev->mrpcim_reg->kdfc_fifo_17_ctrl) + i));
-	}
-
-	/* Reset to service non-offload doorbells */
-	writeq(0, &hldev->mrpcim_reg->kdfc_entry_type_sel_0);
-	writeq(0, &hldev->mrpcim_reg->kdfc_entry_type_sel_1);
-
-	/* Set priority 0 to all receive queues */
-	writeq(0, &hldev->mrpcim_reg->rx_queue_priority_0);
-	writeq(0, &hldev->mrpcim_reg->rx_queue_priority_1);
-	writeq(0, &hldev->mrpcim_reg->rx_queue_priority_2);
-
-	/* Initialize all the slots as unused */
-	for (i = 0; i < VXGE_HW_WEIGHTED_RR_SERVICE_STATES; i++)
-		wrr_states[i] = -1;
-
-	/* Prepare the Fifo service states */
-	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
-		if (!hldev->config.vp_config[i].min_bandwidth)
-			continue;
-
-		how_often = VXGE_HW_VPATH_BANDWIDTH_MAX /
-				hldev->config.vp_config[i].min_bandwidth;
-		if (how_often) {
-
-			for (j = 0; j < VXGE_HW_WRR_FIFO_SERVICE_STATES;) {
-				if (wrr_states[j] == -1) {
-					wrr_states[j] = i;
-					/* Make sure each fifo is serviced
-					 * atleast once */
-					if (i == j)
-						j += VXGE_HW_MAX_VIRTUAL_PATHS;
-					else
-						j += how_often;
-				} else
-					j++;
-			}
-		}
-	}
-
-	/* Fill the unused slots with 0 */
-	for (j = 0; j < VXGE_HW_WEIGHTED_RR_SERVICE_STATES; j++) {
-		if (wrr_states[j] == -1)
-			wrr_states[j] = 0;
-	}
-
-	/* Assign WRR priority number for FIFOs */
-	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-		writeq(VXGE_HW_KDFC_FIFO_0_CTRL_WRR_NUMBER(i),
-				((&hldev->mrpcim_reg->kdfc_fifo_0_ctrl) + i));
-
-		writeq(VXGE_HW_KDFC_FIFO_17_CTRL_WRR_NUMBER(i),
-			((&hldev->mrpcim_reg->kdfc_fifo_17_ctrl) + i));
-	}
-
-	/* Modify the servicing algorithm applied to the 3 types of doorbells.
-	i.e, none-offload, message and offload */
-	writeq(VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_0(0) |
-				VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_1(0) |
-				VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_2(0) |
-				VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_3(0) |
-				VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_4(1) |
-				VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_5(0) |
-				VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_6(0) |
-				VXGE_HW_KDFC_ENTRY_TYPE_SEL_0_NUMBER_7(0),
-				&hldev->mrpcim_reg->kdfc_entry_type_sel_0);
-
-	writeq(VXGE_HW_KDFC_ENTRY_TYPE_SEL_1_NUMBER_8(1),
-				&hldev->mrpcim_reg->kdfc_entry_type_sel_1);
-
-	for (i = 0, j = 0; i < VXGE_HW_WRR_FIFO_COUNT; i++) {
-
-		val64 = VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_0(wrr_states[j++]);
-		val64 |= VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_1(wrr_states[j++]);
-		val64 |= VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_2(wrr_states[j++]);
-		val64 |= VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_3(wrr_states[j++]);
-		val64 |= VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_4(wrr_states[j++]);
-		val64 |= VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_5(wrr_states[j++]);
-		val64 |= VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_6(wrr_states[j++]);
-		val64 |= VXGE_HW_KDFC_W_ROUND_ROBIN_0_NUMBER_7(wrr_states[j++]);
-
-		writeq(val64, (&hldev->mrpcim_reg->kdfc_w_round_robin_0 + i));
-		writeq(val64, (&hldev->mrpcim_reg->kdfc_w_round_robin_20 + i));
-	}
-
-	/* Set up the priorities assigned to receive queues */
-	writeq(VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_0(0) |
-			VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_1(1) |
-			VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_2(2) |
-			VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_3(3) |
-			VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_4(4) |
-			VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_5(5) |
-			VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_6(6) |
-			VXGE_HW_RX_QUEUE_PRIORITY_0_RX_Q_NUMBER_7(7),
-			&hldev->mrpcim_reg->rx_queue_priority_0);
-
-	writeq(VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_8(8) |
-			VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_9(9) |
-			VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_10(10) |
-			VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_11(11) |
-			VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_12(12) |
-			VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_13(13) |
-			VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_14(14) |
-			VXGE_HW_RX_QUEUE_PRIORITY_1_RX_Q_NUMBER_15(15),
-			&hldev->mrpcim_reg->rx_queue_priority_1);
-
-	writeq(VXGE_HW_RX_QUEUE_PRIORITY_2_RX_Q_NUMBER_16(16),
-				&hldev->mrpcim_reg->rx_queue_priority_2);
-
-	/* Initialize all the slots as unused */
-	for (i = 0; i < VXGE_HW_WEIGHTED_RR_SERVICE_STATES; i++)
-		wrr_states[i] = -1;
-
-	/* Prepare the Ring service states */
-	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
-
-		if (!hldev->config.vp_config[i].min_bandwidth)
-			continue;
-
-		how_often = VXGE_HW_VPATH_BANDWIDTH_MAX /
-				hldev->config.vp_config[i].min_bandwidth;
-
-		if (how_often) {
-			for (j = 0; j < VXGE_HW_WRR_RING_SERVICE_STATES;) {
-				if (wrr_states[j] == -1) {
-					wrr_states[j] = i;
-					/* Make sure each ring is
-					 * serviced atleast once */
-					if (i == j)
-						j += VXGE_HW_MAX_VIRTUAL_PATHS;
-					else
-						j += how_often;
-				} else
-					j++;
-			}
-		}
-	}
-
-	/* Fill the unused slots with 0 */
-	for (j = 0; j < VXGE_HW_WEIGHTED_RR_SERVICE_STATES; j++) {
-		if (wrr_states[j] == -1)
-			wrr_states[j] = 0;
-	}
-
-	for (i = 0, j = 0; i < VXGE_HW_WRR_RING_COUNT; i++) {
-		val64 =  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_0(
-				wrr_states[j++]);
-		val64 |=  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_1(
-				wrr_states[j++]);
-		val64 |=  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_2(
-				wrr_states[j++]);
-		val64 |=  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_3(
-				wrr_states[j++]);
-		val64 |=  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_4(
-				wrr_states[j++]);
-		val64 |=  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_5(
-				wrr_states[j++]);
-		val64 |=  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_6(
-				wrr_states[j++]);
-		val64 |=  VXGE_HW_RX_W_ROUND_ROBIN_0_RX_W_PRIORITY_SS_7(
-				wrr_states[j++]);
-
-		writeq(val64, ((&hldev->mrpcim_reg->rx_w_round_robin_0) + i));
-	}
-exit:
-	return status;
-}
-
 /*
  * __vxge_hw_device_initialize
  * Initialize Titan-V hardware.
@@ -678,12 +470,14 @@ enum vxge_hw_status __vxge_hw_device_initialize(struct __vxge_hw_device *hldev)
 {
 	enum vxge_hw_status status = VXGE_HW_OK;
 
-	/* Validate the pci-e link width and speed */
-	status = __vxge_hw_verify_pci_e_info(hldev);
-	if (status != VXGE_HW_OK)
-		goto exit;
+	if (VXGE_HW_OK == __vxge_hw_device_is_privilaged(hldev->host_type,
+				hldev->func_id)) {
+		/* Validate the pci-e link width and speed */
+		status = __vxge_hw_verify_pci_e_info(hldev);
+		if (status != VXGE_HW_OK)
+			goto exit;
+	}
 
-	vxge_hw_wrr_rebalance(hldev);
 exit:
 	return status;
 }
@@ -831,8 +625,6 @@ vxge_hw_device_initialize(
 		sizeof(struct vxge_hw_device_config));
 
 	hldev->bar0 = attr->bar0;
-	hldev->bar1 = attr->bar1;
-	hldev->bar2 = attr->bar2;
 	hldev->pdev = attr->pdev;
 
 	hldev->uld_callbacks.link_up = attr->uld_callbacks.link_up;
@@ -963,7 +755,8 @@ vxge_hw_mrpcim_stats_access(struct __vxge_hw_device *hldev,
 	u64 val64;
 	enum vxge_hw_status status = VXGE_HW_OK;
 
-	status = __vxge_hw_device_is_privilaged(hldev);
+	status = __vxge_hw_device_is_privilaged(hldev->host_type,
+			hldev->func_id);
 	if (status != VXGE_HW_OK)
 		goto exit;
 
@@ -1000,7 +793,8 @@ vxge_hw_device_xmac_aggr_stats_get(struct __vxge_hw_device *hldev, u32 port,
 
 	val64 = (u64 *)aggr_stats;
 
-	status = __vxge_hw_device_is_privilaged(hldev);
+	status = __vxge_hw_device_is_privilaged(hldev->host_type,
+			hldev->func_id);
 	if (status != VXGE_HW_OK)
 		goto exit;
 
@@ -1033,7 +827,8 @@ vxge_hw_device_xmac_port_stats_get(struct __vxge_hw_device *hldev, u32 port,
 	u32 offset = 0x0;
 	val64 = (u64 *) port_stats;
 
-	status = __vxge_hw_device_is_privilaged(hldev);
+	status = __vxge_hw_device_is_privilaged(hldev->host_type,
+			hldev->func_id);
 	if (status != VXGE_HW_OK)
 		goto exit;
 
@@ -1231,7 +1026,8 @@ enum vxge_hw_status vxge_hw_device_setpause_data(struct __vxge_hw_device *hldev,
 		goto exit;
 	}
 
-	status = __vxge_hw_device_is_privilaged(hldev);
+	status = __vxge_hw_device_is_privilaged(hldev->host_type,
+			hldev->func_id);
 	if (status != VXGE_HW_OK)
 		goto exit;
 
@@ -1886,17 +1682,13 @@ void __vxge_hw_mempool_destroy(struct vxge_hw_mempool *mempool)
 				mempool->memblock_size, dma_object);
 	}
 
-	if (mempool->items_arr)
-		vfree(mempool->items_arr);
+	vfree(mempool->items_arr);
 
-	if (mempool->memblocks_dma_arr)
-		vfree(mempool->memblocks_dma_arr);
+	vfree(mempool->memblocks_dma_arr);
 
-	if (mempool->memblocks_priv_arr)
-		vfree(mempool->memblocks_priv_arr);
+	vfree(mempool->memblocks_priv_arr);
 
-	if (mempool->memblocks_arr)
-		vfree(mempool->memblocks_arr);
+	vfree(mempool->memblocks_arr);
 
 	vfree(mempool);
 }
@@ -2367,6 +2159,28 @@ exit:
 }
 
 /*
+ * vxge_hw_vpath_strip_fcs_check - Check for FCS strip.
+ */
+enum vxge_hw_status
+vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask)
+{
+	struct vxge_hw_vpmgmt_reg       __iomem *vpmgmt_reg;
+	enum vxge_hw_status status = VXGE_HW_OK;
+	int i = 0, j = 0;
+
+	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
+		if (!((vpath_mask) & vxge_mBIT(i)))
+			continue;
+		vpmgmt_reg = hldev->vpmgmt_reg[i];
+		for (j = 0; j < VXGE_HW_MAC_MAX_MAC_PORT_ID; j++) {
+			if (readq(&vpmgmt_reg->rxmac_cfg0_port_vpmgmt_clone[j])
+			& VXGE_HW_RXMAC_CFG0_PORT_VPMGMT_CLONE_STRIP_FCS)
+				return VXGE_HW_FAIL;
+		}
+	}
+	return status;
+}
+/*
  * vxge_hw_mgmt_reg_Write - Write Titan register.
  */
 enum vxge_hw_status
@@ -4070,6 +3884,30 @@ __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
 	return status;
 }
 
+void
+vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id)
+{
+	struct __vxge_hw_virtualpath *vpath;
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+	struct vxge_hw_vp_config *config;
+	u64 val64;
+
+	vpath = &hldev->virtual_paths[vp_id];
+	vp_reg = vpath->vp_reg;
+	config = vpath->vp_config;
+
+	if (config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
+		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+
+		if (config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
+			config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
+			val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
+			writeq(val64,
+			&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+		}
+	}
+	return;
+}
 /*
  * __vxge_hw_vpath_initialize
  * This routine is the final phase of init which initializes the
@@ -4112,8 +3950,6 @@ __vxge_hw_vpath_initialize(struct __vxge_hw_device *hldev, u32 vp_id)
 	if (status != VXGE_HW_OK)
 		goto exit;
 
-	writeq(0, &vp_reg->gendma_int);
-
 	val64 = readq(&vp_reg->rtdma_rd_optimization_ctrl);
 
 	/* Get MRRS value from device control */
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h
index 455566c..4d9d9a9 100644
--- a/drivers/net/vxge/vxge-config.h
+++ b/drivers/net/vxge/vxge-config.h
@@ -683,8 +683,6 @@ struct __vxge_hw_vpath_handle{
  * @major_revision: PCI Device major revision
  * @minor_revision: PCI Device minor revision
  * @bar0: BAR0 virtual address.
- * @bar1: BAR1 virtual address.
- * @bar2: BAR2 virtual address.
  * @pdev: Physical device handle
  * @config: Confguration passed by the LL driver at initialization
  * @link_state: Link state
@@ -699,8 +697,6 @@ struct __vxge_hw_device {
 	u8				major_revision;
 	u8				minor_revision;
 	void __iomem			*bar0;
-	void __iomem			*bar1;
-	void __iomem			*bar2;
 	struct pci_dev			*pdev;
 	struct net_device		*ndev;
 	struct vxge_hw_device_config	config;
@@ -789,17 +785,13 @@ struct vxge_hw_device_hw_info {
 /**
  * struct vxge_hw_device_attr - Device memory spaces.
  * @bar0: BAR0 virtual address.
- * @bar1: BAR1 virtual address.
- * @bar2: BAR2 virtual address.
  * @pdev: PCI device object.
  *
- * Device memory spaces. Includes configuration, BAR0, BAR1, etc. per device
+ * Device memory spaces. Includes configuration, BAR0 etc. per device
  * mapped memories. Also, includes a pointer to OS-specific PCI device object.
  */
 struct vxge_hw_device_attr {
 	void __iomem		*bar0;
-	void __iomem		*bar1;
-	void __iomem		*bar2;
 	struct pci_dev 		*pdev;
 	struct vxge_hw_uld_cbs	uld_callbacks;
 };
@@ -987,7 +979,9 @@ struct __vxge_hw_fifo {
 			void *txdlh,
 			enum vxge_hw_fifo_tcode t_code,
 			void *userdata,
-			void **skb_ptr);
+			struct sk_buff ***skb_ptr,
+			int nr_skb,
+			int *more);
 
 	void (*txdl_term)(
 			void *txdlh,
@@ -1548,7 +1542,7 @@ void vxge_hw_ring_rxd_1b_info_get(
 	rxd_info->l4_cksum_valid =
 		(u32)VXGE_HW_RING_RXD_L4_CKSUM_CORRECT_GET(rxdp->control_0);
 	rxd_info->l4_cksum =
-		(u32)VXGE_HW_RING_RXD_L4_CKSUM_GET(rxdp->control_0);;
+		(u32)VXGE_HW_RING_RXD_L4_CKSUM_GET(rxdp->control_0);
 	rxd_info->frame =
 		(u32)VXGE_HW_RING_RXD_ETHER_ENCAP_GET(rxdp->control_0);
 	rxd_info->proto =
@@ -1788,7 +1782,8 @@ struct vxge_hw_fifo_attr {
 			void *txdlh,
 			enum vxge_hw_fifo_tcode t_code,
 			void *userdata,
-			void **skb_ptr);
+			struct sk_buff ***skb_ptr,
+			int nr_skb, int *more);
 
 	void (*txdl_term)(
 			void *txdlh,
@@ -2207,6 +2202,8 @@ __vxge_hw_vpath_func_id_get(
 enum vxge_hw_status
 __vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath);
 
+enum vxge_hw_status
+vxge_hw_vpath_strip_fcs_check(struct __vxge_hw_device *hldev, u64 vpath_mask);
 /**
  * vxge_debug
  * @level: level of debug verbosity.
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index c3c1f80..fb5084b 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -89,22 +89,25 @@ static inline int is_vxge_card_up(struct vxgedev *vdev)
 static inline void VXGE_COMPLETE_VPATH_TX(struct vxge_fifo *fifo)
 {
 	unsigned long flags = 0;
-	struct sk_buff *skb_ptr = NULL;
-	struct sk_buff **temp, *head, *skb;
-
-	if (spin_trylock_irqsave(&fifo->tx_lock, flags)) {
-		vxge_hw_vpath_poll_tx(fifo->handle, (void **)&skb_ptr);
-		spin_unlock_irqrestore(&fifo->tx_lock, flags);
-	}
-	/* free SKBs */
-	head = skb_ptr;
-	while (head) {
-		skb = head;
-		temp = (struct sk_buff **)&skb->cb;
-		head = *temp;
-		*temp = NULL;
-		dev_kfree_skb_irq(skb);
-	}
+	struct sk_buff **skb_ptr = NULL;
+	struct sk_buff **temp;
+#define NR_SKB_COMPLETED 128
+	struct sk_buff *completed[NR_SKB_COMPLETED];
+	int more;
+
+	do {
+		more = 0;
+		skb_ptr = completed;
+
+		if (spin_trylock_irqsave(&fifo->tx_lock, flags)) {
+			vxge_hw_vpath_poll_tx(fifo->handle, &skb_ptr,
+						NR_SKB_COMPLETED, &more);
+			spin_unlock_irqrestore(&fifo->tx_lock, flags);
+		}
+		/* free SKBs */
+		for (temp = completed; temp != skb_ptr; temp++)
+			dev_kfree_skb_irq(*temp);
+	} while (more) ;
 }
 
 static inline void VXGE_COMPLETE_ALL_TX(struct vxgedev *vdev)
@@ -285,6 +288,7 @@ vxge_rx_alloc(void *dtrh, struct vxge_ring *ring, const int skb_size)
 	skb_reserve(skb, VXGE_HW_HEADER_ETHERNET_II_802_3_ALIGN);
 
 	rx_priv->skb = skb;
+	rx_priv->skb_data = NULL;
 	rx_priv->data_size = skb_size;
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s: %s:%d Exiting...", ring->ndev->name, __func__, __LINE__);
@@ -304,7 +308,8 @@ static int vxge_rx_map(void *dtrh, struct vxge_ring *ring)
 		ring->ndev->name, __func__, __LINE__);
 	rx_priv = vxge_hw_ring_rxd_private_get(dtrh);
 
-	dma_addr = pci_map_single(ring->pdev, rx_priv->skb->data,
+	rx_priv->skb_data = rx_priv->skb->data;
+	dma_addr = pci_map_single(ring->pdev, rx_priv->skb_data,
 				rx_priv->data_size, PCI_DMA_FROMDEVICE);
 
 	if (dma_addr == 0) {
@@ -374,17 +379,13 @@ vxge_rx_complete(struct vxge_ring *ring, struct sk_buff *skb, u16 vlan,
 		ring->ndev->name, __func__, __LINE__, skb->protocol);
 
 	if (ring->gro_enable) {
-#if 0 /* GRO not in RHEL */
 		if (ring->vlgrp && ext_info->vlan &&
 			(ring->vlan_tag_strip ==
 				VXGE_HW_VPATH_RPA_STRIP_VLAN_TAG_ENABLE))
-			vlan_gro_receive(&ring->napi, ring->vlgrp,
+			vlan_gro_receive(ring->napi_p, ring->vlgrp,
 					ext_info->vlan, skb);
 		else
-			napi_gro_receive(&ring->napi, skb);
-#else
-		WARN_ON(1);
-#endif
+			napi_gro_receive(ring->napi_p, skb);
 	} else {
 		if (ring->vlgrp && vlan &&
 			(ring->vlan_tag_strip ==
@@ -449,10 +450,12 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
 	vxge_hw_ring_replenish(ringh, 0);
 
 	do {
+		prefetch((char *)dtr + L1_CACHE_BYTES);
 		rx_priv = vxge_hw_ring_rxd_private_get(dtr);
 		skb = rx_priv->skb;
 		data_size = rx_priv->data_size;
 		data_dma = rx_priv->data_dma;
+		prefetch(rx_priv->skb_data);
 
 		vxge_debug_rx(VXGE_TRACE,
 			"%s: %s:%d  skb = 0x%p",
@@ -461,6 +464,8 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
 		vxge_hw_ring_rxd_1b_get(ringh, dtr, &dma_sizes);
 		pkt_length = dma_sizes;
 
+		pkt_length -= ETH_FCS_LEN;
+
 		vxge_debug_rx(VXGE_TRACE,
 			"%s: %s:%d  Packet Length = %d",
 			ring->ndev->name, __func__, __LINE__, pkt_length);
@@ -605,11 +610,10 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
 enum vxge_hw_status
 vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
 		enum vxge_hw_fifo_tcode t_code, void *userdata,
-		void **skb_ptr)
+		struct sk_buff ***skb_ptr, int nr_skb, int *more)
 {
 	struct vxge_fifo *fifo = (struct vxge_fifo *)userdata;
-	struct sk_buff *skb, *head = NULL;
-	struct sk_buff **temp;
+	struct sk_buff *skb, **done_skb = *skb_ptr;
 	int pkt_cnt = 0;
 
 	vxge_debug_entryexit(VXGE_TRACE,
@@ -662,9 +666,12 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
 		fifo->stats.tx_frms++;
 		fifo->stats.tx_bytes += skb->len;
 
-		temp = (struct sk_buff **)&skb->cb;
-		*temp = head;
-		head = skb;
+		*done_skb++ = skb;
+
+		if (--nr_skb <= 0) {
+			*more = 1;
+			break;
+		}
 
 		pkt_cnt++;
 		if (pkt_cnt > fifo->indicate_max_pkts)
@@ -673,18 +680,16 @@ vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
 	} while (vxge_hw_fifo_txdl_next_completed(fifo_hw,
 				&dtr, &t_code) == VXGE_HW_OK);
 
+	*skb_ptr = done_skb;
 	vxge_wake_tx_queue(fifo, skb);
 
-	if (skb_ptr)
-		*skb_ptr = (void *) head;
-
 	vxge_debug_entryexit(VXGE_TRACE,
 				"%s: %s:%d  Exiting...",
 				fifo->ndev->name, __func__, __LINE__);
 	return VXGE_HW_OK;
 }
 
-/* select a vpath to trasmit the packet */
+/* select a vpath to transmit the packet */
 static u32 vxge_get_vpath_no(struct vxgedev *vdev, struct sk_buff *skb,
 	int *do_lock)
 {
@@ -810,7 +815,7 @@ static int vxge_learn_mac(struct vxgedev *vdev, u8 *mac_header)
  * NOTE: when device cant queue the pkt, just the trans_start variable will
  * not be upadted.
 */
-static int
+static netdev_tx_t
 vxge_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct vxge_fifo *fifo = NULL;
@@ -824,7 +829,6 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
 	u64 dma_pointer;
 	struct vxge_tx_priv *txdl_priv = NULL;
 	struct __vxge_hw_fifo *fifo_hw;
-	u32 max_mss = 0x0;
 	int offload_type;
 	unsigned long flags = 0;
 	int vpath_no = 0;
@@ -901,6 +905,12 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto _exit2;
 	}
 
+	/* Last TXD?  Stop tx queue to avoid dropping packets.  TX
+	 * completion will resume the queue.
+	 */
+	if (avail == 1)
+		vxge_stop_tx_queue(fifo);
+
 	status = vxge_hw_fifo_txdl_reserve(fifo_hw, &dtr, &dtr_priv);
 	if (unlikely(status != VXGE_HW_OK)) {
 		vxge_debug_tx(VXGE_ERR,
@@ -976,10 +986,6 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		int mss = vxge_tcp_mss(skb);
 		if (mss) {
-			max_mss = dev->mtu + ETH_HLEN -
-				VXGE_HW_TCPIP_HEADER_MAX_SIZE;
-			if (mss > max_mss)
-				mss = max_mss;
 			vxge_debug_tx(VXGE_TRACE,
 				"%s: %s:%d mss = %d",
 				dev->name, __func__, __LINE__, mss);
@@ -1005,7 +1011,7 @@ vxge_xmit(struct sk_buff *skb, struct net_device *dev)
 	VXGE_COMPLETE_VPATH_TX(fifo);
 	vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d  Exiting...",
 		dev->name, __func__, __LINE__);
-	return 0;
+	return NETDEV_TX_OK;
 
 _exit0:
 	vxge_debug_tx(VXGE_TRACE, "%s: pci_map_page failed", dev->name);
@@ -1029,7 +1035,7 @@ _exit2:
 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
 	VXGE_COMPLETE_VPATH_TX(fifo);
 
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 /*
@@ -1054,6 +1060,7 @@ vxge_rx_term(void *dtrh, enum vxge_hw_rxd_state state, void *userdata)
 		rx_priv->data_size, PCI_DMA_FROMDEVICE);
 
 	dev_kfree_skb(rx_priv->skb);
+	rx_priv->skb_data = NULL;
 
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s: %s:%d  Exiting...",
@@ -1675,36 +1682,32 @@ int vxge_reset(struct vxgedev *vdev)
  * of packets at most in one iteration. This value is passed down by the
  * kernel as the function argument 'budget'.
  */
-static int vxge_poll_msix(struct net_device *dummy_dev, int *budget)
+static int vxge_poll_msix(struct napi_struct *napi, int budget)
 {
-	struct vxge_ring *ring = dummy_dev->priv;
-	int to_do = min(*budget, dummy_dev->quota);
-	ring->budget = to_do;
+	struct vxge_ring *ring =
+		container_of(napi, struct vxge_ring, napi);
+	int budget_org = budget;
+	ring->budget = budget;
 
 	vxge_hw_vpath_poll_rx(ring->handle);
 
-	*budget -= ring->pkts_processed;
-	dummy_dev->quota -= ring->pkts_processed;
-
-	if (ring->pkts_processed < to_do) {
-		netif_rx_complete(dummy_dev);
+	if (ring->pkts_processed < budget_org) {
+		napi_complete(napi);
 		/* Re enable the Rx interrupts for the vpath */
 		vxge_hw_channel_msix_unmask(
 				(struct __vxge_hw_channel *)ring->handle,
 				ring->rx_vector_no);
-		return 0;
 	}
 
-	return 1;
+	return ring->pkts_processed;
 }
 
-static int vxge_poll_inta(struct net_device *dummy_dev, int *pbudget)
+static int vxge_poll_inta(struct napi_struct *napi, int budget)
 {
-	struct vxgedev *vdev = dummy_dev->priv;
+	struct vxgedev *vdev = container_of(napi, struct vxgedev, napi);
 	int pkts_processed = 0;
 	int i;
-	int to_do = min(*pbudget, dummy_dev->quota);
-	int budget = to_do;
+	int budget_org = budget;
 	struct vxge_ring *ring;
 
 	struct __vxge_hw_device  *hldev = (struct __vxge_hw_device *)
@@ -1720,20 +1723,30 @@ static int vxge_poll_inta(struct net_device *dummy_dev, int *pbudget)
 			break;
 	}
 
-	*pbudget -= pkts_processed;
-	dummy_dev->quota -= pkts_processed;
-
 	VXGE_COMPLETE_ALL_TX(vdev);
 
-	if (pkts_processed < to_do) {
-		netif_rx_complete(dummy_dev);
+	if (pkts_processed < budget_org) {
+		napi_complete(napi);
 		/* Re enable the Rx interrupts for the ring */
 		vxge_hw_device_unmask_all(hldev);
 		vxge_hw_device_flush_io(hldev);
-		return 0;
 	}
 
-	return 1;
+	return pkts_processed;
+}
+
+static int vxge_poll_msix_rhel(struct net_device *dummy_dev, int *budget)
+{
+	struct vxge_ring *ring = dummy_dev->priv;
+	return rhel_napi_poll_wrapper(vxge_poll_msix, &ring->napi, dummy_dev,
+				      budget);
+}
+
+static int vxge_poll_inta_rhel(struct net_device *dummy_dev, int *budget)
+{
+	struct vxgedev *vdev = dummy_dev->priv;
+	return rhel_napi_poll_wrapper(vxge_poll_inta, &vdev->napi, dummy_dev,
+				      budget);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2150,16 +2163,16 @@ int vxge_open_vpaths(struct vxgedev *vdev)
  */
 static irqreturn_t vxge_isr_napi(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct __vxge_hw_device  *hldev = (struct __vxge_hw_device  *)dev_id;
-	struct vxgedev *vdev;
 	struct net_device *dev;
+	struct __vxge_hw_device *hldev;
 	u64 reason;
 	enum vxge_hw_status status;
+	struct vxgedev *vdev = (struct vxgedev *) dev_id;;
 
 	vxge_debug_intr(VXGE_TRACE, "%s:%d", __func__, __LINE__);
 
-	dev = hldev->ndev;
-	vdev = netdev_priv(dev);
+	dev = vdev->ndev;
+	hldev = (struct __vxge_hw_device *)pci_get_drvdata(vdev->pdev);
 
 	if (pci_channel_offline(vdev->pdev))
 		return IRQ_NONE;
@@ -2178,7 +2191,7 @@ static irqreturn_t vxge_isr_napi(int irq, void *dev_id, struct pt_regs *regs)
 			(64 - VXGE_HW_MAX_VIRTUAL_PATHS))) {
 
 			vxge_hw_device_clear_tx_rx(hldev);
-			netif_rx_schedule(vdev->dummy_dev);
+			napi_schedule(&vdev->napi);
 			vxge_debug_intr(VXGE_TRACE,
 				"%s:%d  Exiting...", __func__, __LINE__);
 			return IRQ_HANDLED;
@@ -2218,7 +2231,7 @@ vxge_rx_msix_napi_handle(int irq, void *dev_id, struct pt_regs *regs)
 	vxge_hw_channel_msix_mask((struct __vxge_hw_channel *)ring->handle,
 					ring->rx_vector_no);
 
-	netif_rx_schedule(ring->dummy_dev);
+	napi_schedule(&ring->napi);
 	return IRQ_HANDLED;
 }
 
@@ -2354,7 +2367,7 @@ static int vxge_enable_msix(struct vxgedev *vdev)
 	enum vxge_hw_status status;
 	/* 0 - Tx, 1 - Rx  */
 	int tim_msix_id[4];
-	int alarm_msix_id = 0, msix_intr_vect = 0;;
+	int alarm_msix_id = 0, msix_intr_vect = 0;
 	vdev->intr_cnt = 0;
 
 	/* allocate msix vectors */
@@ -2430,18 +2443,15 @@ static void vxge_rem_isr(struct vxgedev *vdev)
 #endif
 	if (vdev->config.intr_type == INTA) {
 			synchronize_irq(vdev->pdev->irq);
-			free_irq(vdev->pdev->irq, hldev);
+			free_irq(vdev->pdev->irq, vdev);
 	}
 }
 
 static int vxge_add_isr(struct vxgedev *vdev)
 {
 	int ret = 0;
-	struct __vxge_hw_device  *hldev =
-		(struct __vxge_hw_device  *) pci_get_drvdata(vdev->pdev);
 #ifdef CONFIG_PCI_MSI
 	int vp_idx = 0, intr_idx = 0, intr_cnt = 0, msix_idx = 0, irq_req = 0;
-	u64 function_mode = vdev->config.device_hw_info.function_mode;
 	int pci_fun = PCI_FUNC(vdev->pdev->devfn);
 
 	if (vdev->config.intr_type == MSI_X)
@@ -2450,20 +2460,9 @@ static int vxge_add_isr(struct vxgedev *vdev)
 	if (ret) {
 		vxge_debug_init(VXGE_ERR,
 			"%s: Enabling MSI-X Failed", VXGE_DRIVER_NAME);
-		if ((function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
-			test_and_set_bit(__VXGE_STATE_CARD_UP,
-				&driver_config->inta_dev_open))
-			return VXGE_HW_FAIL;
-		else {
-			vxge_debug_init(VXGE_ERR,
-				"%s: Defaulting to INTA", VXGE_DRIVER_NAME);
-			vdev->config.intr_type = INTA;
-			vxge_hw_device_set_intr_type(vdev->devh,
-				VXGE_HW_INTR_MODE_IRQLINE);
-			vxge_close_vpaths(vdev, 1);
-			vdev->no_of_vpath = 1;
-			vdev->stats.vpaths_open = 1;
-		}
+		vxge_debug_init(VXGE_ERR,
+			"%s: Defaulting to INTA", VXGE_DRIVER_NAME);
+		vdev->config.intr_type = INTA;
 	}
 
 	if (vdev->config.intr_type == MSI_X) {
@@ -2511,24 +2510,11 @@ static int vxge_add_isr(struct vxgedev *vdev)
 					"%s: MSIX - %d  Registration failed",
 					vdev->ndev->name, intr_cnt);
 				vxge_rem_msix_isr(vdev);
-				if ((function_mode ==
-					VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
-					test_and_set_bit(__VXGE_STATE_CARD_UP,
-						&driver_config->inta_dev_open))
-					return VXGE_HW_FAIL;
-				else {
-					vxge_hw_device_set_intr_type(
-						vdev->devh,
-						VXGE_HW_INTR_MODE_IRQLINE);
-						vdev->config.intr_type = INTA;
-					vxge_debug_init(VXGE_ERR,
-						"%s: Defaulting to INTA"
-						, vdev->ndev->name);
-					vxge_close_vpaths(vdev, 1);
-					vdev->no_of_vpath = 1;
-					vdev->stats.vpaths_open = 1;
+				vdev->config.intr_type = INTA;
+				vxge_debug_init(VXGE_ERR,
+					"%s: Defaulting to INTA"
+					, vdev->ndev->name);
 					goto INTA_MODE;
-				}
 			}
 
 			if (irq_req) {
@@ -2561,23 +2547,11 @@ static int vxge_add_isr(struct vxgedev *vdev)
 				"%s: MSIX - %d Registration failed",
 				vdev->ndev->name, intr_cnt);
 			vxge_rem_msix_isr(vdev);
-			if ((function_mode ==
-				VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
-				test_and_set_bit(__VXGE_STATE_CARD_UP,
-						&driver_config->inta_dev_open))
-				return VXGE_HW_FAIL;
-			else {
-				vxge_hw_device_set_intr_type(vdev->devh,
-						VXGE_HW_INTR_MODE_IRQLINE);
-				vdev->config.intr_type = INTA;
-				vxge_debug_init(VXGE_ERR,
-					"%s: Defaulting to INTA",
-					vdev->ndev->name);
-				vxge_close_vpaths(vdev, 1);
-				vdev->no_of_vpath = 1;
-				vdev->stats.vpaths_open = 1;
+			vdev->config.intr_type = INTA;
+			vxge_debug_init(VXGE_ERR,
+				"%s: Defaulting to INTA",
+				vdev->ndev->name);
 				goto INTA_MODE;
-			}
 		}
 
 		vxge_hw_vpath_msix_unmask(vdev->vpaths[vp_idx].handle,
@@ -2590,9 +2564,13 @@ INTA_MODE:
 	snprintf(vdev->desc[0], VXGE_INTR_STRLEN, "%s:vxge", vdev->ndev->name);
 
 	if (vdev->config.intr_type == INTA) {
+		vxge_hw_device_set_intr_type(vdev->devh,
+			VXGE_HW_INTR_MODE_IRQLINE);
+		vxge_hw_vpath_tti_ci_set(vdev->devh,
+			vdev->vpaths[0].device_id);
 		ret = request_irq((int) vdev->pdev->irq,
 			vxge_isr_napi,
-			IRQF_SHARED, vdev->desc[0], hldev);
+			IRQF_SHARED, vdev->desc[0], vdev);
 		if (ret) {
 			vxge_debug_init(VXGE_ERR,
 				"%s %s-%d: ISR registration failed",
@@ -2696,13 +2674,6 @@ vxge_open(struct net_device *dev)
 	 * initialized */
 	netif_carrier_off(dev);
 
-	/* Check for another device already opn with INTA */
-	if ((function_mode == VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION) &&
-		test_bit(__VXGE_STATE_CARD_UP, &driver_config->inta_dev_open)) {
-		ret = -EPERM;
-		goto out0;
-	}
-
 	/* Open VPATHs */
 	status = vxge_open_vpaths(vdev);
 	if (status != VXGE_HW_OK) {
@@ -2724,32 +2695,24 @@ vxge_open(struct net_device *dev)
 
 
 	if (vdev->config.intr_type != MSI_X) {
-		struct net_device *nd;
-		nd = alloc_netdev(0, "", ether_setup);
-		if (!nd) {
-			ret = -ENOMEM;
+		ret = vxge_netif_napi_add(vdev, &vdev->napi,
+			vxge_poll_inta_rhel, vdev->config.napi_weight);
+		if (ret)
 			goto out2;
-		}
-		nd->priv = vdev;
-		nd->weight = vdev->config.napi_weight;
-		nd->poll = vxge_poll_inta;
-		set_bit(__LINK_STATE_START, &nd->state);
-		vdev->dummy_dev = nd;
-		netif_poll_enable(vdev->dummy_dev);
+		napi_enable(&vdev->napi);
+		for (i = 0; i < vdev->no_of_vpath; i++)
+			vdev->vpaths[i].ring.napi_p = &vdev->napi;
 	} else {
 		for (i = 0; i < vdev->no_of_vpath; i++) {
-			struct net_device *nd;
-			nd = alloc_netdev(0, "", ether_setup);
-			if (!nd) {
-				ret = -ENOMEM;
+			ret = vxge_netif_napi_add(&vdev->vpaths[i].ring,
+				&vdev->vpaths[i].ring.napi,
+				vxge_poll_msix_rhel,
+				vdev->config.napi_weight);
+			if (ret)
 				goto out3;
-			}
-			nd->priv = &vdev->vpaths[i].ring;
-			nd->weight = vdev->config.napi_weight;
-			nd->poll = vxge_poll_msix;
-			set_bit(__LINK_STATE_START, &nd->state);
-			vdev->vpaths[i].ring.dummy_dev = nd;
-			netif_poll_enable(vdev->vpaths[i].ring.dummy_dev);
+			napi_enable(&vdev->vpaths[i].ring.napi);
+			vdev->vpaths[i].ring.napi_p =
+				&vdev->vpaths[i].ring.napi;
 		}
 	}
 
@@ -2867,12 +2830,13 @@ vxge_open(struct net_device *dev)
 out3:
 	/* Disable napi */
 	if (vdev->config.intr_type != MSI_X)
-		netif_poll_disable(vdev->dummy_dev);
+		napi_disable(&vdev->napi);
 	else {
-		for (i = 0; i < vdev->no_of_vpath; i++)
-			if (!vdev->vpaths[i].ring.dummy_dev)
+		for (i = 0; i < vdev->no_of_vpath; i++) {
+			if (!vdev->vpaths[i].ring.napi.dev)
 				break;
-			netif_poll_disable(vdev->vpaths[i].ring.dummy_dev);
+			napi_disable(&vdev->vpaths[i].ring.napi);
+		}
 	}
 	vxge_napi_del_all(vdev);
 out2:
@@ -2903,17 +2867,13 @@ void vxge_free_mac_add_list(struct vxge_vpath *vpath)
 static void vxge_napi_del_all(struct vxgedev *vdev)
 {
 	int i;
-	if (vdev->config.intr_type != MSI_X) {
-		if (vdev->dummy_dev) {
-			free_netdev(vdev->dummy_dev);
-			vdev->dummy_dev = NULL;
-		}
-	} else {
+	if (vdev->config.intr_type != MSI_X)
+		netif_napi_del(&vdev->napi);
+	else {
 		for (i = 0; i < vdev->no_of_vpath; i++) {
-			if (!vdev->vpaths[i].ring.dummy_dev)
+			if (!vdev->vpaths[i].ring.napi.dev)
 				break;
-			free_netdev(vdev->vpaths[i].ring.dummy_dev);
-			vdev->vpaths[i].ring.dummy_dev = NULL;
+			netif_napi_del(&vdev->vpaths[i].ring.napi);
 		}
 	}
 	return;
@@ -2932,6 +2892,9 @@ int do_vxge_close(struct net_device *dev, int do_io)
 	vdev = (struct vxgedev *)netdev_priv(dev);
 	hldev = (struct __vxge_hw_device *) pci_get_drvdata(vdev->pdev);
 
+	if (unlikely(!is_vxge_card_up(vdev)))
+		return 0;
+
 	/* If vxge_handle_crit_err task is executing,
 	 * wait till it completes. */
 	while (test_and_set_bit(__VXGE_STATE_RESET_CARD, &vdev->state))
@@ -2983,10 +2946,10 @@ int do_vxge_close(struct net_device *dev, int do_io)
 
 	/* Disable napi */
 	if (vdev->config.intr_type != MSI_X)
-		netif_poll_disable(vdev->dummy_dev);
+		napi_disable(&vdev->napi);
 	else {
 		for (i = 0; i < vdev->no_of_vpath; i++)
-			netif_poll_disable(vdev->vpaths[i].ring.dummy_dev);
+			napi_disable(&vdev->vpaths[i].ring.napi);
 	}
 
 	netif_carrier_off(vdev->ndev);
@@ -3011,7 +2974,6 @@ int do_vxge_close(struct net_device *dev, int do_io)
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s: %s:%d  Exiting...", dev->name, __func__, __LINE__);
 
-	clear_bit(__VXGE_STATE_CARD_UP, &driver_config->inta_dev_open);
 	clear_bit(__VXGE_STATE_RESET_CARD, &vdev->state);
 
 	return 0;
@@ -3240,36 +3202,26 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 	}
 }
 
-/**
- * vxge_vlan_rx_add_vid
- * @dev: net device pointer.
- * @vid: vid
- *
- * Remove the vlan id from the device's vlan id table
- */
-static void
-vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
-	struct vxgedev *vdev;
-	struct vxge_vpath *vpath;
-	int vp_id;
-
-	vxge_debug_entryexit(VXGE_TRACE, "%s:%d", __func__, __LINE__);
+static const struct net_device_ops vxge_netdev_ops = {
+	.ndo_open               = vxge_open,
+	.ndo_stop               = vxge_close,
+	.ndo_get_stats          = vxge_get_stats,
+	.ndo_start_xmit         = vxge_xmit,
+	.ndo_validate_addr      = eth_validate_addr,
+	.ndo_set_multicast_list = vxge_set_multicast,
 
-	vdev = (struct vxgedev *)netdev_priv(dev);
+	.ndo_do_ioctl           = vxge_ioctl,
 
-	vlan_group_set_device(vdev->vlgrp, vid, NULL);
+	.ndo_set_mac_address    = vxge_set_mac_addr,
+	.ndo_change_mtu         = vxge_change_mtu,
+	.ndo_vlan_rx_register   = vxge_vlan_rx_register,
+	.ndo_vlan_rx_add_vid	= vxge_vlan_rx_add_vid,
 
-	/* Delete this vlan from the vid table */
-	for (vp_id = 0; vp_id < vdev->no_of_vpath; vp_id++) {
-		vpath = &vdev->vpaths[vp_id];
-		if (!vpath->is_open)
-			continue;
-		vxge_hw_vpath_vid_delete(vpath->handle, vid);
-	}
-	vxge_debug_entryexit(VXGE_TRACE,
-		"%s:%d  Exiting...", __func__, __LINE__);
-}
+	.ndo_tx_timeout         = vxge_tx_watchdog,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller    = vxge_netpoll,
+#endif
+};
 
 int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 				   struct vxge_config *config,
@@ -3318,24 +3270,7 @@ int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 	ndev->irq = vdev->pdev->irq;
 	ndev->base_addr = (unsigned long) hldev->bar0;
 
-	ndev->open               = vxge_open;
-	ndev->stop               = vxge_close;
-	ndev->get_stats          = vxge_get_stats;
-	ndev->hard_start_xmit    = vxge_xmit;
-	ndev->set_multicast_list = vxge_set_multicast;
-
-	ndev->do_ioctl           = vxge_ioctl;
-
-	ndev->set_mac_address    = vxge_set_mac_addr;
-	ndev->change_mtu         = vxge_change_mtu;
-	ndev->vlan_rx_register   = vxge_vlan_rx_register;
-	ndev->vlan_rx_kill_vid   = vxge_vlan_rx_kill_vid;
-	ndev->vlan_rx_add_vid    = vxge_vlan_rx_add_vid;
-
-	ndev->tx_timeout         = vxge_tx_watchdog;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	ndev->poll_controller    = vxge_netpoll;
-#endif
+	vxge_set_netdev_ops(ndev, &vxge_netdev_ops);
 
 	ndev->watchdog_timeo = VXGE_LL_WATCH_DOG_TIMEOUT;
 
@@ -3366,12 +3301,10 @@ int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 
 	ndev->features |= NETIF_F_TSO | NETIF_F_TSO6;
 
-#if 0 /* GRO not in RHEL */
 	if (vdev->config.gro_enable)
 		ndev->features |= NETIF_F_GRO;
-#endif
 
-#if 0 /* MQ not in RHEL */
+#if 0 /* MQ not in RHEL5 */
 	if (vdev->config.tx_steering_type == TX_MULTIQ_STEERING)
 		ndev->real_num_tx_queues = no_of_vpath;
 #endif
@@ -3680,11 +3613,12 @@ static int __devinit vxge_config_vpaths(
 		device_config->vp_config[i].fifo.enable =
 						VXGE_HW_FIFO_ENABLE;
 		device_config->vp_config[i].fifo.max_frags =
-				MAX_SKB_FRAGS;
+				MAX_SKB_FRAGS + 1;
 		device_config->vp_config[i].fifo.memblock_size =
 			VXGE_HW_MIN_FIFO_MEMBLOCK_SIZE;
 
-		txdl_size = MAX_SKB_FRAGS * sizeof(struct vxge_hw_fifo_txd);
+		txdl_size = device_config->vp_config[i].fifo.max_frags *
+				sizeof(struct vxge_hw_fifo_txd);
 		txdl_per_memblock = VXGE_HW_MIN_FIFO_MEMBLOCK_SIZE / txdl_size;
 
 		device_config->vp_config[i].fifo.fifo_blocks =
@@ -3995,6 +3929,9 @@ static pci_ers_result_t vxge_io_error_detected(struct pci_dev *pdev,
 
 	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_vxge_close(netdev, 0);
@@ -4112,9 +4049,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		driver_config->config_dev_cnt = 0;
 		driver_config->total_dev_cnt = 0;
 		driver_config->g_no_cpus = 0;
-		driver_config->vpath_per_dev = max_config_vpath;
 	}
 
+	driver_config->vpath_per_dev = max_config_vpath;
+
 	driver_config->total_dev_cnt++;
 	if (++driver_config->config_dev_cnt > max_config_dev) {
 		ret = 0;
@@ -4132,10 +4070,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 	}
 
 	memset(&ll_config, 0, sizeof(struct vxge_config));
-#if 0 /* MQ not in RHEL */
+#if 0 /* MQ not in RHEL5 */
 	ll_config.tx_steering_type = TX_MULTIQ_STEERING;
 #else
-	ll_config.tx_steering_type = TX_PORT_STEERING; /* XXX other choice better? */
+	ll_config.tx_steering_type = TX_PORT_STEERING;
 #endif
 	ll_config.intr_type = MSI_X;
 	ll_config.napi_weight = NEW_NAPI_WEIGHT;
@@ -4197,18 +4135,6 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		attr.bar0,
 		(unsigned long long)pci_resource_start(pdev, 0));
 
-	attr.bar1 = pci_ioremap_bar(pdev, 2);
-	if (!attr.bar1) {
-		vxge_debug_init(VXGE_ERR,
-			"%s : cannot remap io memory bar2", __func__);
-		ret = -ENODEV;
-		goto _exit3;
-	}
-	vxge_debug_ll_config(VXGE_TRACE,
-		"pci ioremap bar1: %p:0x%llx",
-		attr.bar1,
-		(unsigned long long)pci_resource_start(pdev, 2));
-
 	status = vxge_hw_device_hw_info_get(attr.bar0,
 			&ll_config.device_hw_info);
 	if (status != VXGE_HW_OK) {
@@ -4216,17 +4142,17 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 			"%s: Reading of hardware info failed."
 			"Please try upgrading the firmware.", VXGE_DRIVER_NAME);
 		ret = -EINVAL;
-		goto _exit4;
+		goto _exit3;
 	}
 
 	if (ll_config.device_hw_info.fw_version.major !=
-		VXGE_DRIVER_VERSION_MAJOR) {
+		VXGE_DRIVER_FW_VERSION_MAJOR) {
 		vxge_debug_init(VXGE_ERR,
-			"FW Ver.(maj): %d not driver's expected version: %d",
-			ll_config.device_hw_info.fw_version.major,
-			VXGE_DRIVER_VERSION_MAJOR);
+			"%s: Incorrect firmware version."
+			"Please upgrade the firmware to version 1.x.x",
+			VXGE_DRIVER_NAME);
 		ret = -EINVAL;
-		goto _exit4;
+		goto _exit3;
 	}
 
 	vpath_mask = ll_config.device_hw_info.vpath_mask;
@@ -4234,7 +4160,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		vxge_debug_ll_config(VXGE_TRACE,
 			"%s: No vpaths available in device", VXGE_DRIVER_NAME);
 		ret = -EINVAL;
-		goto _exit4;
+		goto _exit3;
 	}
 
 	vxge_debug_ll_config(VXGE_TRACE,
@@ -4248,6 +4174,16 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		max_vpath_supported++;
 	}
 
+	/* Enable SRIOV mode, if firmware has SRIOV support and if it is a PF */
+	if ((VXGE_HW_FUNCTION_MODE_SRIOV ==
+		ll_config.device_hw_info.function_mode) &&
+		(max_config_dev > 1) && (pdev->is_physfn)) {
+			ret = pci_enable_sriov(pdev, max_config_dev - 1);
+			if (ret)
+				vxge_debug_ll_config(VXGE_ERR,
+					"Failed to enable SRIOV: %d \n", ret);
+	}
+
 	/*
 	 * Configure vpaths and get driver configured number of vpaths
 	 * which is less than or equal to the maximum vpaths per function.
@@ -4257,7 +4193,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		vxge_debug_ll_config(VXGE_ERR,
 			"%s: No more vpaths to configure", VXGE_DRIVER_NAME);
 		ret = 0;
-		goto _exit4;
+		goto _exit3;
 	}
 
 	/* Setting driver callbacks */
@@ -4270,7 +4206,16 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		vxge_debug_init(VXGE_ERR,
 			"Failed to initialize device (%d)", status);
 			ret = -EINVAL;
-			goto _exit4;
+			goto _exit3;
+	}
+
+	/* if FCS stripping is not disabled in MAC fail driver load */
+	if (vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask) != VXGE_HW_OK) {
+		vxge_debug_init(VXGE_ERR,
+			"%s: FCS stripping is not disabled in MAC"
+			" failing driver load", VXGE_DRIVER_NAME);
+		ret = -EINVAL;
+		goto _exit4;
 	}
 
 	vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_LL);
@@ -4278,11 +4223,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 	/* set private device info */
 	pci_set_drvdata(pdev, hldev);
 
-#if 0 /* GRO not in RHEL */
 	ll_config.gro_enable = VXGE_GRO_ALWAYS_AGGREGATE;
-#else
-	ll_config.gro_enable = VXGE_GRO_DONOT_AGGREGATE;
-#endif
 	ll_config.fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS;
 	ll_config.addr_learn_en = addr_learn_en;
 	ll_config.rth_algorithm = RTH_ALG_JENKINS;
@@ -4299,7 +4240,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 	if (vxge_device_register(hldev, &ll_config, high_dma, no_of_vpath,
 		&vdev)) {
 		ret = -EINVAL;
-		goto _exit5;
+		goto _exit4;
 	}
 
 	vxge_hw_device_debug_set(hldev, VXGE_TRACE, VXGE_COMPONENT_LL);
@@ -4310,7 +4251,6 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 	hldev->ndev = vdev->ndev;
 	vdev->mtu = VXGE_HW_DEFAULT_MTU;
 	vdev->bar0 = attr.bar0;
-	vdev->bar1 = attr.bar1;
 	vdev->max_vpath_supported = max_vpath_supported;
 	vdev->no_of_vpath = no_of_vpath;
 
@@ -4375,6 +4315,27 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		ll_config.device_hw_info.fw_version.version,
 		ll_config.device_hw_info.fw_date.date);
 
+	if (new_device) {
+		switch (ll_config.device_hw_info.function_mode) {
+		case VXGE_HW_FUNCTION_MODE_SINGLE_FUNCTION:
+			vxge_debug_init(VXGE_TRACE,
+			"%s: Single Function Mode Enabled", vdev->ndev->name);
+		break;
+		case VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION:
+			vxge_debug_init(VXGE_TRACE,
+			"%s: Multi Function Mode Enabled", vdev->ndev->name);
+		break;
+		case VXGE_HW_FUNCTION_MODE_SRIOV:
+			vxge_debug_init(VXGE_TRACE,
+			"%s: Single Root IOV Mode Enabled", vdev->ndev->name);
+		break;
+		case VXGE_HW_FUNCTION_MODE_MRIOV:
+			vxge_debug_init(VXGE_TRACE,
+			"%s: Multi Root IOV Mode Enabled", vdev->ndev->name);
+		break;
+		}
+	}
+
 	vxge_print_parm(vdev, vpath_mask);
 
 	/* Store the fw version for ethttool option */
@@ -4392,7 +4353,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 				"%s: mac_addr_list : memory allocation failed",
 				vdev->ndev->name);
 			ret = -EPERM;
-			goto _exit6;
+			goto _exit5;
 		}
 		macaddr = (u8 *)&entry->macaddr;
 		memcpy(macaddr, vdev->ndev->dev_addr, ETH_ALEN);
@@ -4400,6 +4361,28 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		vdev->vpaths[i].mac_addr_cnt = 1;
 	}
 
+	kfree(device_config);
+
+	/*
+	 * INTA is shared in multi-function mode. This is unlike the INTA
+	 * implementation in MR mode, where each VH has its own INTA message.
+	 * - INTA is masked (disabled) as long as at least one function sets
+	 * its TITAN_MASK_ALL_INT.ALARM bit.
+	 * - INTA is unmasked (enabled) when all enabled functions have cleared
+	 * their own TITAN_MASK_ALL_INT.ALARM bit.
+	 * The TITAN_MASK_ALL_INT ALARM & TRAFFIC bits are cleared on power up.
+	 * Though this driver leaves the top level interrupts unmasked while
+	 * leaving the required module interrupt bits masked on exit, there
+	 * could be a rougue driver around that does not follow this procedure
+	 * resulting in a failure to generate interrupts. The following code is
+	 * present to prevent such a failure.
+	 */
+
+	if (ll_config.device_hw_info.function_mode ==
+		VXGE_HW_FUNCTION_MODE_MULTI_FUNCTION)
+		if (vdev->config.intr_type == INTA)
+			vxge_hw_device_unmask_all(hldev);
+
 	vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d  Exiting...",
 		vdev->ndev->name, __func__, __LINE__);
 
@@ -4409,15 +4392,14 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 
 	return 0;
 
-_exit6:
+_exit5:
 	for (i = 0; i < vdev->no_of_vpath; i++)
 		vxge_free_mac_add_list(&vdev->vpaths[i]);
 
 	vxge_device_unregister(hldev);
-_exit5:
-	vxge_hw_device_terminate(hldev);
 _exit4:
-	iounmap(attr.bar1);
+	pci_disable_sriov(pdev);
+	vxge_hw_device_terminate(hldev);
 _exit3:
 	iounmap(attr.bar0);
 _exit2:
@@ -4476,7 +4458,8 @@ vxge_remove(struct pci_dev *pdev)
 	kfree(vdev->vpaths);
 
 	iounmap(vdev->bar0);
-	iounmap(vdev->bar1);
+
+	pci_disable_sriov(pdev);
 
 	/* we are safe to free it now */
 	free_netdev(dev);
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index fd11a1b..7c83ba4 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -21,7 +21,7 @@
 
 #define VXGE_DRIVER_NAME		"vxge"
 #define VXGE_DRIVER_VENDOR		"Neterion, Inc"
-#define VXGE_DRIVER_VERSION_MAJOR 0
+#define VXGE_DRIVER_FW_VERSION_MAJOR	1
 
 #define DRV_VERSION	VXGE_VERSION_MAJOR"."VXGE_VERSION_MINOR"."\
 	VXGE_VERSION_FIX"."VXGE_VERSION_BUILD"-"\
@@ -112,7 +112,6 @@ enum vxge_mac_addr_state {
 struct vxge_drv_config {
 	int config_dev_cnt;
 	int total_dev_cnt;
-	unsigned long inta_dev_open;
 	int g_no_cpus;
 	unsigned int vpath_per_dev;
 };
@@ -259,7 +258,8 @@ struct vxge_ring {
 	int budget;
 	int gro_enable;
 
-	struct net_device *dummy_dev;
+	struct napi_struct napi;
+	struct napi_struct *napi_p;
 
 #define VXGE_MAX_MAC_ADDR_COUNT		30
 
@@ -348,7 +348,7 @@ struct vxgedev {
 	int max_vpath_supported;
 	int no_of_vpath;
 
-	struct net_device *dummy_dev;
+	struct napi_struct napi;
 	/* A debug option, when enabled and if error condition occurs,
 	 * the driver will do following steps:
 	 * - mask all interrupts
@@ -363,7 +363,6 @@ struct vxgedev {
 
 	struct __vxge_hw_vpath_handle *vp_handles[VXGE_HW_MAX_VIRTUAL_PATHS];
 	void __iomem *bar0;
-	void __iomem *bar1;
 	struct vxge_sw_stats	stats;
 	int		mtu;
 	/* Below variables are used for vpath selection to transmit a packet */
@@ -378,6 +377,7 @@ struct vxgedev {
 
 struct vxge_rx_priv {
 	struct sk_buff		*skb;
+	unsigned char		*skb_data;
 	dma_addr_t		data_dma;
 	dma_addr_t		data_size;
 };
@@ -428,7 +428,8 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
 
 enum vxge_hw_status
 vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw, void *dtr,
-	enum vxge_hw_fifo_tcode t_code, void *userdata, void **skb_ptr);
+	enum vxge_hw_fifo_tcode t_code, void *userdata,
+	struct sk_buff ***skb_ptr, int nr_skbs, int *more);
 
 int vxge_close(struct net_device *dev);
 
diff --git a/drivers/net/vxge/vxge-reg.h b/drivers/net/vxge/vxge-reg.h
index 10f4da3..9a0cf8e 100644
--- a/drivers/net/vxge/vxge-reg.h
+++ b/drivers/net/vxge/vxge-reg.h
@@ -1784,7 +1784,7 @@ struct vxge_hw_mrpcim_reg {
 #define	VXGE_HW_XMAC_GEN_ERR_REG_XMACJ_XMAC_FSM_ERR	vxge_mBIT(63)
 /*0x01e18*/	u64	xmac_gen_err_mask;
 /*0x01e20*/	u64	xmac_gen_err_alarm;
-/*0x01e28*/	u64	xmac_link_err_port_reg[2];
+/*0x01e28*/	u64	xmac_link_err_port0_reg;
 #define	VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_DOWN	vxge_mBIT(3)
 #define	VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_UP	vxge_mBIT(7)
 #define	VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMACJ_PORT_WENT_DOWN	vxge_mBIT(11)
@@ -1798,8 +1798,11 @@ struct vxge_hw_mrpcim_reg {
 #define	VXGE_HW_XMAC_LINK_ERR_PORT_REG_RATEMGMT_LASI_INV	vxge_mBIT(39)
 #define	VXGE_HW_XMAC_LINK_ERR_PORT_REG_XMDIO_MDIO_MGR_ACCESS_COMPLETE \
 								vxge_mBIT(47)
-/*0x01e30*/	u64	xmac_link_err_port_mask[2];
-/*0x01e38*/	u64	xmac_link_err_port_alarm[2];
+/*0x01e30*/	u64	xmac_link_err_port0_mask;
+/*0x01e38*/	u64	xmac_link_err_port0_alarm;
+/*0x01e40*/	u64	xmac_link_err_port1_reg;
+/*0x01e48*/	u64	xmac_link_err_port1_mask;
+/*0x01e50*/	u64	xmac_link_err_port1_alarm;
 /*0x01e58*/	u64	xgxs_gen_err_reg;
 #define	VXGE_HW_XGXS_GEN_ERR_REG_XGXS_XGXS_FSM_ERR	vxge_mBIT(63)
 /*0x01e60*/	u64	xgxs_gen_err_mask;
@@ -4323,10 +4326,6 @@ struct vxge_hw_vpath_reg {
 /*0x011e0*/	u64	umq_bwr_init_byte;
 #define VXGE_HW_UMQ_BWR_INIT_BYTE_COUNT(val) vxge_vBIT(val, 0, 32)
 /*0x011e8*/	u64	gendma_int;
-#define	VXGE_HW_GENDMA_INT_IMMED_ENABLE	vxge_mBIT(6)
-#define	VXGE_HW_GENDMA_INT_EVENT_ENABLE	vxge_mBIT(7)
-#define VXGE_HW_GENDMA_INT_NUMBER(val) vxge_vBIT(val, 9, 7)
-#define VXGE_HW_GENDMA_INT_BITMAP(val) vxge_vBIT(val, 16, 16)
 /*0x011f0*/	u64	umqdmq_ir_init_notify;
 #define	VXGE_HW_UMQDMQ_IR_INIT_NOTIFY_PULSE	vxge_mBIT(3)
 /*0x011f8*/	u64	dmq_init_notify;
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index c2eeac4..61ce754 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -295,6 +295,8 @@ void vxge_hw_device_intr_enable(struct __vxge_hw_device *hldev)
 	u64 val64;
 	u32 val32;
 
+	vxge_hw_device_mask_all(hldev);
+
 	for (i = 0; i < VXGE_HW_MAX_VIRTUAL_PATHS; i++) {
 
 		if (!(hldev->vpaths_deployed & vxge_mBIT(i)))
@@ -731,6 +733,7 @@ vxge_hw_channel_dtr_try_complete(struct __vxge_hw_channel *channel, void **dtrh)
 	vxge_assert(channel->compl_index < channel->length);
 
 	*dtrh =	channel->work_arr[channel->compl_index];
+	prefetch(*dtrh);
 }
 
 /*
@@ -1070,11 +1073,11 @@ static void __vxge_hw_non_offload_db_post(struct __vxge_hw_fifo *fifo,
 		VXGE_HW_NODBW_GET_NO_SNOOP(no_snoop),
 		&fifo->nofl_db->control_0);
 
-	wmb();
+	mmiowb();
 
 	writeq(txdl_ptr, &fifo->nofl_db->txdl_ptr);
-	wmb();
 
+	mmiowb();
 }
 
 /**
@@ -1231,7 +1234,7 @@ void vxge_hw_fifo_txdl_post(struct __vxge_hw_fifo *fifo, void *txdlh)
 	vxge_hw_channel_dtr_post(&fifo->channel, txdlh);
 
 	__vxge_hw_non_offload_db_post(fifo,
-		(u64)(size_t)txdl_priv->dma_addr,
+		(u64)txdl_priv->dma_addr,
 		txdl_priv->frags - 1,
 		fifo->no_snoop_bits);
 
@@ -1923,7 +1926,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process(
 	if (vpath == NULL) {
 		alarm_event = VXGE_HW_SET_LEVEL(VXGE_HW_EVENT_UNKNOWN,
 			alarm_event);
-		goto out;
+		goto out2;
 	}
 
 	hldev = vpath->hldev;
@@ -2161,7 +2164,7 @@ enum vxge_hw_status __vxge_hw_vpath_alarm_process(
 	}
 out:
 	hldev->stats.sw_dev_err_stats.vpath_alarms++;
-
+out2:
 	if ((alarm_event == VXGE_HW_EVENT_ALARM_CLEARED) ||
 		(alarm_event == VXGE_HW_EVENT_UNKNOWN))
 		return VXGE_HW_OK;
@@ -2508,7 +2511,8 @@ enum vxge_hw_status vxge_hw_vpath_poll_rx(struct __vxge_hw_ring *ring)
  * See also: vxge_hw_vpath_poll_tx().
  */
 enum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo,
-					void **skb_ptr)
+					struct sk_buff ***skb_ptr, int nr_skb,
+					int *more)
 {
 	enum vxge_hw_fifo_tcode t_code;
 	void *first_txdlh;
@@ -2520,8 +2524,8 @@ enum vxge_hw_status vxge_hw_vpath_poll_tx(struct __vxge_hw_fifo *fifo,
 	status = vxge_hw_fifo_txdl_next_completed(fifo,
 				&first_txdlh, &t_code);
 	if (status == VXGE_HW_OK)
-		if (fifo->callback(fifo, first_txdlh,
-			t_code, channel->userdata, skb_ptr) != VXGE_HW_OK)
+		if (fifo->callback(fifo, first_txdlh, t_code,
+			channel->userdata, skb_ptr, nr_skb, more) != VXGE_HW_OK)
 			status = VXGE_HW_COMPLETIONS_REMAIN;
 
 	return status;
diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h
index 7567a11..861c853 100644
--- a/drivers/net/vxge/vxge-traffic.h
+++ b/drivers/net/vxge/vxge-traffic.h
@@ -35,8 +35,6 @@
 			VXGE_HW_HEADER_VLAN_SIZE + \
 			VXGE_HW_HEADER_SNAP_SIZE)
 
-#define VXGE_HW_TCPIP_HEADER_MAX_SIZE	(64 + 64)
-
 /* 32bit alignments */
 #define VXGE_HW_HEADER_ETHERNET_II_802_3_ALIGN		2
 #define VXGE_HW_HEADER_802_2_SNAP_ALIGN			2
@@ -2328,7 +2326,7 @@ enum vxge_hw_status vxge_hw_vpath_poll_rx(
 
 enum vxge_hw_status vxge_hw_vpath_poll_tx(
 	struct __vxge_hw_fifo *fifoh,
-	void **skb_ptr);
+	struct sk_buff ***skb_ptr, int nr_skb, int *more);
 
 enum vxge_hw_status vxge_hw_vpath_alarm_process(
 	struct __vxge_hw_vpath_handle *vpath_handle,
@@ -2391,6 +2389,8 @@ vxge_hw_channel_dtr_free(struct __vxge_hw_channel *channel, void *dtrh);
 
 int
 vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel);
+void
+vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id);
 
 /* ========================== PRIVATE API ================================= */
 
diff --git a/drivers/net/vxge/vxge-version.h b/drivers/net/vxge/vxge-version.h
index 7da02c5..77c2a75 100644
--- a/drivers/net/vxge/vxge-version.h
+++ b/drivers/net/vxge/vxge-version.h
@@ -17,7 +17,7 @@
 
 #define VXGE_VERSION_MAJOR	"2"
 #define VXGE_VERSION_MINOR	"0"
-#define VXGE_VERSION_FIX	"1"
-#define VXGE_VERSION_BUILD	"17129"
+#define VXGE_VERSION_FIX	"6"
+#define VXGE_VERSION_BUILD	"18937"
 #define VXGE_VERSION_FOR	"k"
 #endif