Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Ivan Vecera <ivecera@redhat.com>
Date: Fri, 11 Dec 2009 11:21:19 -0500
Subject: [net] benet: update driver to latest upstream for rhel5.5
Message-id: <1260530479-725-1-git-send-email-ivecera@redhat.com>
Patchwork-id: 21880
O-Subject: Re:[RHEL5.5 PATCH] be2net: update be2net driver to latest upstream
Bugzilla: 515269
RH-Acked-by: David S. Miller <davem@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>

BZ #515269 - Update be2net 10Gb NIC driver

Description:
This patch updates the be2net driver to current upstream. Main purpose is
the support for new devices. The original patch was provided by
ServerEngines, but it modified ethtool_ops struct and this causes kABI
problems. The upstream version uses ethtool interface to perform flashing,
for RHEL5.5 the flashing is done through sysfs.

Upstream status:
Backported from latest upstream

Test status:
Successfully tested by myself

Signed-off-by: Ivan Vecera <ivecera@redhat.com>


diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig
index c6934f1..fdb6e81 100644
--- a/drivers/net/benet/Kconfig
+++ b/drivers/net/benet/Kconfig
@@ -1,7 +1,6 @@
 config BE2NET
 	tristate "ServerEngines' 10Gbps NIC - BladeEngine 2"
 	depends on PCI && INET
-	select INET_LRO
 	help
 	This driver implements the NIC functionality for ServerEngines'
 	10Gbps network adapter - BladeEngine 2.
diff --git a/drivers/net/benet/Makefile b/drivers/net/benet/Makefile
index 8823c58..691e22f 100644
--- a/drivers/net/benet/Makefile
+++ b/drivers/net/benet/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_BE2NET) += be2net.o
 
-be2net-y :=  be_main.o be_cmds.o be_ethtool.o be_compat.o
+be2net-y :=  be_cmds.o be_compat.o be_main.o be_ethtool.o
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index 755d542..655d191 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -28,28 +28,40 @@
 #include <linux/if_vlan.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
-#include <linux/inet_lro.h>
+#include <linux/firmware.h>
+#include <linux/ethtool.h>
 #include "be_compat.h"
 
 #include "be_hw.h"
 
-#define DRV_VER			"2.0.348"
+#define DRV_VER			"2.101.331r"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
+#define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
 #define OC_NAME			"Emulex OneConnect 10Gbps NIC"
+#define OC_NAME1		"Emulex OneConnect 10Gbps NIC (be3)"
 #define DRV_DESC		BE_NAME "Driver"
 
 #define BE_VENDOR_ID 		0x19a2
 #define BE_DEVICE_ID1		0x211
+#define BE_DEVICE_ID2		0x221
 #define OC_DEVICE_ID1		0x700
 #define OC_DEVICE_ID2		0x701
+#define OC_DEVICE_ID3		0x710
 
 static inline char *nic_name(struct pci_dev *pdev)
 {
-	if (pdev->device == OC_DEVICE_ID1 || pdev->device == OC_DEVICE_ID2)
+	switch (pdev->device) {
+	case OC_DEVICE_ID1:
+	case OC_DEVICE_ID2:
 		return OC_NAME;
-	else
+	case OC_DEVICE_ID3:
+		return OC_NAME1;
+	case BE_DEVICE_ID2:
+		return BE3_NAME;
+	default:
 		return BE_NAME;
+	}
 }
 
 /* Number of bytes of an RX frame that are copied to skb->data */
@@ -58,7 +70,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE_MIN_MTU		256
 
 #define BE_NUM_VLANS_SUPPORTED	64
-#define BE_MAX_EQD		56
+#define BE_MAX_EQD		96
 #define	BE_MAX_TX_FRAG_COUNT	30
 
 #define EVNT_Q_LEN		1024
@@ -73,8 +85,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define MAX_RX_POST 		BE_NAPI_WEIGHT /* Frags posted at a time */
 #define RX_FRAGS_REFILL_WM	(RX_Q_LEN - MAX_RX_POST)
 
-#define BE_MAX_LRO_DESCRIPTORS  16
-#define BE_MAX_FRAGS_PER_FRAME  (min((u32) 16, (u32) MAX_SKB_FRAGS))
+#define FW_VER_LEN		32
 
 struct be_dma_mem {
 	void *va;
@@ -137,40 +148,14 @@ struct be_eq_obj {
 	u16 min_eqd;		/* in usecs */
 	u16 max_eqd;		/* in usecs */
 	u16 cur_eqd;		/* in usecs */
-
-	struct napi_struct napi;
 };
 
 struct be_mcc_obj {
 	struct be_queue_info q;
 	struct be_queue_info cq;
+	bool rearm_cq;
 };
 
-struct be_ctrl_info {
-	u8 __iomem *csr;
-	u8 __iomem *db;		/* Door Bell */
-	u8 __iomem *pcicfg;	/* PCI config space */
-	int pci_func;
-
-	/* Mbox used for cmd request/response */
-	spinlock_t mbox_lock;	/* For serializing mbox cmds to BE card */
-	struct be_dma_mem mbox_mem;
-	/* Mbox mem is adjusted to align to 16 bytes. The allocated addr
-	 * is stored for freeing purpose */
-	struct be_dma_mem mbox_mem_alloced;
-
-	/* MCC Rings */
-	struct be_mcc_obj mcc_obj;
-	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
-	spinlock_t mcc_cq_lock;
-
-	/* MCC Async callback */
-	void (*async_cb)(void *adapter, bool link_up);
-	void *adapter_ctxt;
-};
-
-#include "be_cmds.h"
-
 struct be_drvr_stats {
 	u32 be_num_events;	/* number of events seen */
 	u32 be_num_events_prev;
@@ -192,14 +177,13 @@ struct be_drvr_stats {
 	u32 cache_barrier[16];
 
 	u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */
-	u32 be_polls;		/* number of times NAPI called poll function */
+	u32 be_rx_polls;	/* number of times NAPI called poll function */
 	u32 be_rx_events;	/* number of ucast rx completion events  */
 	u32 be_rx_compl;	/* number of rx completion entries processed */
-	u32 be_lro_hgram_data[8];	/* histogram of LRO data packets */
-	u32 be_lro_hgram_ack[8];	/* histogram of LRO ACKs */
 	ulong be_rx_jiffies;
 	u64 be_rx_bytes;
 	u64 be_rx_bytes_prev;
+	u64 be_rx_pkts;
 	u32 be_rx_rate;
 	/* number of non ether type II frames dropped where
 	 * frame len > length field of Mac Hdr */
@@ -208,6 +192,10 @@ struct be_drvr_stats {
 	 * in frame len < length field of Mac Hdr */
 	u32 be_802_3_malformed_frames;
 	u32 be_rxcp_err;	/* Num rx completion entries w/ err set. */
+	ulong rx_fps_jiffies;	/* jiffies at last FPS calc */
+	u32 be_rx_frags;
+	u32 be_prev_rx_frags;
+	u32 be_rx_fps;		/* Rx frags per second */
 };
 
 struct be_stats_obj {
@@ -235,8 +223,6 @@ struct be_rx_obj {
 	struct be_queue_info q;
 	struct be_queue_info cq;
 	struct be_rx_page_info page_info_tbl[RX_Q_LEN];
-	struct net_lro_mgr lro_mgr;
-	struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS];
 };
 
 #define BE_NUM_MSIX_VECTORS		2	/* 1 each for Tx and Rx */
@@ -245,8 +231,19 @@ struct be_adapter {
 	struct net_device *netdev;
 	struct napi_struct napi;
 
-	/* Mbox, pci config, csr address information */
-	struct be_ctrl_info ctrl;
+	u8 __iomem *csr;
+	u8 __iomem *db;		/* Door Bell */
+	u8 __iomem *pcicfg;	/* PCI config space */
+
+	spinlock_t mbox_lock;	/* For serializing mbox cmds to BE card */
+	struct be_dma_mem mbox_mem;
+	/* Mbox mem is adjusted to align to 16 bytes. The allocated addr
+	 * is stored for freeing purpose */
+	struct be_dma_mem mbox_mem_alloced;
+
+	struct be_mcc_obj mcc_obj;
+	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
+	spinlock_t mcc_cq_lock;
 
 	struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS];
 	bool msix_enabled;
@@ -266,6 +263,7 @@ struct be_adapter {
 	struct vlan_group *vlan_grp;
 	u16 num_vlans;
 	u8 vlan_tag[VLAN_GROUP_ARRAY_LEN];
+	struct be_dma_mem mc_cmd_mem;
 
 	struct be_stats_obj stats;
 	/* Work queue used to perform periodic tasks like getting statistics */
@@ -273,7 +271,6 @@ struct be_adapter {
 
 	/* Ethtool knobs and info */
 	bool rx_csum; 		/* BE card must perform rx-checksumming */
-	u32 max_rx_coal;
 	char fw_ver[FW_VER_LEN];
 	u32 if_handle;		/* Used to configure filtering */
 	u32 pmac_id;		/* MAC addr handle used by BE card */
@@ -281,6 +278,12 @@ struct be_adapter {
 	bool link_up;
 	u32 port_num;
 	bool promiscuous;
+	bool wol;
+	u32 cap;
+	u32 rx_fc;		/* Rx flow control */
+	u32 tx_fc;		/* Tx flow control */
+	int link_speed;
+	u8 port_type;
 };
 
 extern struct ethtool_ops be_ethtool_ops;
@@ -289,6 +292,11 @@ extern struct ethtool_ops be_ethtool_ops;
 
 #define BE_SET_NETDEV_OPS(netdev, ops)	be_netdev_ops_init(netdev, ops)
 
+static inline unsigned int be_pci_func(struct be_adapter *adapter)
+{
+	return PCI_FUNC(adapter->pdev->devfn);
+}
+
 #define PAGE_SHIFT_4K		12
 #define PAGE_SIZE_4K		(1 << PAGE_SHIFT_4K)
 
@@ -377,6 +385,9 @@ static inline u8 is_udp_pkt(struct sk_buff *skb)
 	return val;
 }
 
-extern void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm,
+extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
 		u16 num_popped);
+extern void be_link_status_update(struct be_adapter *adapter, bool link_up);
+extern void netdev_stats_update(struct be_adapter *adapter);
+extern int be_load_fw(struct be_adapter *adapter, u8 *func);
 #endif				/* BE_H */
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 69c52e3..4da2597 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -16,15 +16,16 @@
  */
 
 #include "be.h"
+#include "be_cmds.h"
 
-static void be_mcc_notify(struct be_ctrl_info *ctrl)
+static void be_mcc_notify(struct be_adapter *adapter)
 {
-	struct be_queue_info *mccq = &ctrl->mcc_obj.q;
+	struct be_queue_info *mccq = &adapter->mcc_obj.q;
 	u32 val = 0;
 
 	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
 	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
-	iowrite32(val, ctrl->db + DB_MCCQ_OFFSET);
+	iowrite32(val, adapter->db + DB_MCCQ_OFFSET);
 }
 
 /* To check if valid bit is set, check the entire word as we don't know
@@ -47,7 +48,7 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
 	compl->flags = 0;
 }
 
-static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
+static int be_mcc_compl_process(struct be_adapter *adapter,
 	struct be_mcc_compl *compl)
 {
 	u16 compl_status, extd_status;
@@ -58,23 +59,30 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl,
 
 	compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
 				CQE_STATUS_COMPL_MASK;
-	if (compl_status != MCC_STATUS_SUCCESS) {
+	if (compl_status == MCC_STATUS_SUCCESS) {
+		if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) {
+			struct be_cmd_resp_get_stats *resp =
+						adapter->stats.cmd.va;
+			be_dws_le_to_cpu(&resp->hw_stats,
+						sizeof(resp->hw_stats));
+			netdev_stats_update(adapter);
+		}
+	} else if (compl_status != MCC_STATUS_NOT_SUPPORTED) {
 		extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
 				CQE_STATUS_EXTD_MASK;
-		printk(KERN_WARNING DRV_NAME
-			" error in cmd completion: status(compl/extd)=%d/%d\n",
-			compl_status, extd_status);
-		return -1;
+		dev_warn(&adapter->pdev->dev,
+		"Error in cmd completion - opcode %d, compl %d, extd %d\n",
+			compl->tag0, compl_status, extd_status);
 	}
-	return 0;
+	return compl_status;
 }
 
 /* Link state evt is a string of bytes; no need for endian swapping */
-static void be_async_link_state_process(struct be_ctrl_info *ctrl,
+static void be_async_link_state_process(struct be_adapter *adapter,
 		struct be_async_event_link_state *evt)
 {
-	ctrl->async_cb(ctrl->adapter_ctxt,
-		evt->port_link_status == ASYNC_EVENT_LINK_UP ? true : false);
+	be_link_status_update(adapter,
+		evt->port_link_status == ASYNC_EVENT_LINK_UP);
 }
 
 static inline bool is_link_state_evt(u32 trailer)
@@ -84,9 +92,9 @@ static inline bool is_link_state_evt(u32 trailer)
 				ASYNC_EVENT_CODE_LINK_STATE);
 }
 
-static struct be_mcc_compl *be_mcc_compl_get(struct be_ctrl_info *ctrl)
+static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
 {
-	struct be_queue_info *mcc_cq = &ctrl->mcc_obj.cq;
+	struct be_queue_info *mcc_cq = &adapter->mcc_obj.cq;
 	struct be_mcc_compl *compl = queue_tail_node(mcc_cq);
 
 	if (be_mcc_compl_is_new(compl)) {
@@ -96,59 +104,82 @@ static struct be_mcc_compl *be_mcc_compl_get(struct be_ctrl_info *ctrl)
 	return NULL;
 }
 
-void be_process_mcc(struct be_ctrl_info *ctrl)
+void be_async_mcc_enable(struct be_adapter *adapter)
+{
+	spin_lock_bh(&adapter->mcc_cq_lock);
+
+	be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0);
+	adapter->mcc_obj.rearm_cq = true;
+
+	spin_unlock_bh(&adapter->mcc_cq_lock);
+}
+
+void be_async_mcc_disable(struct be_adapter *adapter)
+{
+	adapter->mcc_obj.rearm_cq = false;
+}
+
+int be_process_mcc(struct be_adapter *adapter)
 {
 	struct be_mcc_compl *compl;
-	int num = 0;
+	int num = 0, status = 0;
+	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
-	spin_lock_bh(&ctrl->mcc_cq_lock);
-	while ((compl = be_mcc_compl_get(ctrl))) {
+	spin_lock_bh(&adapter->mcc_cq_lock);
+	while ((compl = be_mcc_compl_get(adapter))) {
 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
 			/* Interpret flags as an async trailer */
 			BUG_ON(!is_link_state_evt(compl->flags));
 
 			/* Interpret compl as a async link evt */
-			be_async_link_state_process(ctrl,
+			be_async_link_state_process(adapter,
 				(struct be_async_event_link_state *) compl);
-		} else {
-			be_mcc_compl_process(ctrl, compl);
-			atomic_dec(&ctrl->mcc_obj.q.used);
+		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
+				status = be_mcc_compl_process(adapter, compl);
+				atomic_dec(&mcc_obj->q.used);
 		}
 		be_mcc_compl_use(compl);
 		num++;
 	}
+
 	if (num)
-		be_cq_notify(ctrl, ctrl->mcc_obj.cq.id, true, num);
-	spin_unlock_bh(&ctrl->mcc_cq_lock);
+		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
+
+	spin_unlock_bh(&adapter->mcc_cq_lock);
+	return status;
 }
 
-#define MCC_TIMEOUT		50000 /* 5s timeout */
 /* Wait till no more pending mcc requests are present */
-static void be_mcc_wait_compl(struct be_ctrl_info *ctrl)
+static int be_mcc_wait_compl(struct be_adapter *adapter)
 {
-	int i;
-	for(i=0; i < MCC_TIMEOUT; i++) {
-		be_process_mcc(ctrl);
-		if (atomic_read(&ctrl->mcc_obj.q.used) == 0)
+#define mcc_timeout		120000 /* 12s timeout */
+	int i, status;
+	for (i = 0; i < mcc_timeout; i++) {
+		status = be_process_mcc(adapter);
+		if (status)
+			return status;
+
+		if (atomic_read(&adapter->mcc_obj.q.used) == 0)
 			break;
 		udelay(100);
 	}
-	if (i == MCC_TIMEOUT)
-		printk(KERN_WARNING DRV_NAME "mcc poll timed out\n");
+	if (i == mcc_timeout) {
+		dev_err(&adapter->pdev->dev, "mccq poll timed out\n");
+		return -1;
+	}
+	return 0;
 }
 
 /* Notify MCC requests and wait for completion */
-static void be_mcc_notify_wait(struct be_ctrl_info *ctrl)
+static int be_mcc_notify_wait(struct be_adapter *adapter)
 {
-	be_mcc_notify(ctrl);
-	be_mcc_wait_compl(ctrl);
+	be_mcc_notify(adapter);
+	return be_mcc_wait_compl(adapter);
 }
 
-#define LONG_DELAY 		2000
-static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
+static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
 {
-	void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
-	int cnt = 0, wait = 5; /* in usecs */
+	int cnt = 0, wait = 5;
 	u32 ready;
 
 	do {
@@ -156,19 +187,15 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
 		if (ready)
 			break;
 
-		if (cnt > 6000000) {
-			printk(KERN_WARNING DRV_NAME
-				": mbox_db poll timed out\n");
+		if (cnt > 4000000) {
+			dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
 			return -1;
 		}
 
-		if (cnt > 50) {
-			wait = LONG_DELAY;
-			mdelay(LONG_DELAY/1000);
-		} else {
-			udelay(wait);
-		}
+		if (cnt > 50)
+			wait = 200;
 		cnt += wait;
+		udelay(wait);
 	} while (true);
 
 	return 0;
@@ -178,111 +205,47 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
  * Insert the mailbox address into the doorbell in two steps
  * Polls on the mbox doorbell till a command completion (or a timeout) occurs
  */
-static int be_mbox_notify(struct be_ctrl_info *ctrl)
+static int be_mbox_notify_wait(struct be_adapter *adapter)
 {
 	int status;
 	u32 val = 0;
-	void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
-	struct be_dma_mem *mbox_mem = &ctrl->mbox_mem;
+	void __iomem *db = adapter->db + MPU_MAILBOX_DB_OFFSET;
+	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
 	struct be_mcc_mailbox *mbox = mbox_mem->va;
 	struct be_mcc_compl *compl = &mbox->compl;
 
-	val &= ~MPU_MAILBOX_DB_RDY_MASK;
 	val |= MPU_MAILBOX_DB_HI_MASK;
 	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
 	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
 	iowrite32(val, db);
 
 	/* wait for ready to be set */
-	status = be_mbox_db_ready_wait(ctrl);
+	status = be_mbox_db_ready_wait(adapter, db);
 	if (status != 0)
 		return status;
 
 	val = 0;
-	val &= ~MPU_MAILBOX_DB_RDY_MASK;
-	val &= ~MPU_MAILBOX_DB_HI_MASK;
 	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */
 	val |= (u32)(mbox_mem->dma >> 4) << 2;
 	iowrite32(val, db);
 
-	status = be_mbox_db_ready_wait(ctrl);
+	status = be_mbox_db_ready_wait(adapter, db);
 	if (status != 0)
 		return status;
 
 	/* A cq entry has been made now */
 	if (be_mcc_compl_is_new(compl)) {
-		status = be_mcc_compl_process(ctrl, &mbox->compl);
+		status = be_mcc_compl_process(adapter, &mbox->compl);
 		be_mcc_compl_use(compl);
 		if (status)
 			return status;
 	} else {
-		printk(KERN_WARNING DRV_NAME "invalid mailbox completion\n");
+		dev_err(&adapter->pdev->dev, "invalid mailbox completion\n");
 		return -1;
 	}
 	return 0;
 }
 
-static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage)
-{
-	u32 sem = ioread32(ctrl->csr + MPU_EP_SEMAPHORE_OFFSET);
-
-	*stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
-	if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
-		return -1;
-	else
-		return 0;
-}
-
-static int be_POST_stage_poll(struct be_ctrl_info *ctrl, u16 poll_stage)
-{
-	u16 stage, cnt, error;
-	for (cnt = 0; cnt < 5000; cnt++) {
-		error = be_POST_stage_get(ctrl, &stage);
-		if (error)
-			return -1;
-
-		if (stage == poll_stage)
-			break;
-		udelay(1000);
-	}
-	if (stage != poll_stage)
-		return -1;
-	return 0;
-}
-
-
-int be_cmd_POST(struct be_ctrl_info *ctrl)
-{
-	u16 stage, error;
-
-	error = be_POST_stage_get(ctrl, &stage);
-	if (error)
-		goto err;
-
-	if (stage == POST_STAGE_ARMFW_RDY)
-		return 0;
-
-	if (stage != POST_STAGE_AWAITING_HOST_RDY)
-		goto err;
-
-	/* On awaiting host rdy, reset and again poll on awaiting host rdy */
-	iowrite32(POST_STAGE_BE_RESET, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET);
-	error = be_POST_stage_poll(ctrl, POST_STAGE_AWAITING_HOST_RDY);
-	if (error)
-		goto err;
-
-	/* Now kickoff POST and poll on armfw ready */
-	iowrite32(POST_STAGE_HOST_RDY, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET);
-	error = be_POST_stage_poll(ctrl, POST_STAGE_ARMFW_RDY);
-	if (error)
-		goto err;
-
-	return 0;
-err:
-	printk(KERN_WARNING DRV_NAME ": ERROR, stage=%d\n", stage);
-	return -1;
-}
-
 static inline void *embedded_payload(struct be_mcc_wrb *wrb)
 {
 	return wrb->payload.embedded_payload;
@@ -295,7 +258,7 @@ static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
 
 /* Don't touch the hdr after it's prepared */
 static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
-				bool embedded, u8 sge_cnt)
+				bool embedded, u8 sge_cnt, u32 opcode)
 {
 	if (embedded)
 		wrb->embedded |= MCC_WRB_EMBEDDED_MASK;
@@ -303,7 +266,8 @@ static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
 		wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
 				MCC_WRB_SGE_CNT_SHIFT;
 	wrb->payload_length = payload_len;
-	be_dws_cpu_to_le(wrb, 8);
+	wrb->tag0 = opcode;
+	be_dws_cpu_to_le(wrb, 20);
 }
 
 /* Don't touch the hdr after it's prepared */
@@ -328,10 +292,10 @@ static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages,
 	}
 }
 
-#define MAX_INTR_RATE			651042
 /* Converts interrupt delay in microseconds to multiplier value */
 static u32 eq_delay_to_mult(u32 usec_delay)
 {
+#define MAX_INTR_RATE			651042
 	const u32 round = 10;
 	u32 multiplier;
 
@@ -353,36 +317,132 @@ static u32 eq_delay_to_mult(u32 usec_delay)
 	return multiplier;
 }
 
-static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem)
+static inline struct be_mcc_wrb *wrb_from_mbox(struct be_adapter *adapter)
 {
-	return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
+	struct be_dma_mem *mbox_mem = &adapter->mbox_mem;
+	struct be_mcc_wrb *wrb
+		= &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb;
+	memset(wrb, 0, sizeof(*wrb));
+	return wrb;
 }
 
-static inline struct be_mcc_wrb *wrb_from_mcc(struct be_queue_info *mccq)
+static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
 {
-	struct be_mcc_wrb *wrb = NULL;
-	if (atomic_read(&mccq->used) < mccq->len) {
-		wrb = queue_head_node(mccq);
-		queue_head_inc(mccq);
-		atomic_inc(&mccq->used);
-		memset(wrb, 0, sizeof(*wrb));
+	struct be_queue_info *mccq = &adapter->mcc_obj.q;
+	struct be_mcc_wrb *wrb;
+
+	if (atomic_read(&mccq->used) >= mccq->len) {
+		dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
+		return NULL;
 	}
+
+	wrb = queue_head_node(mccq);
+	queue_head_inc(mccq);
+	atomic_inc(&mccq->used);
+	memset(wrb, 0, sizeof(*wrb));
 	return wrb;
 }
 
-int be_cmd_eq_create(struct be_ctrl_info *ctrl,
+static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
+{
+	u32 sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
+
+	*stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
+	if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
+		return -1;
+	else
+		return 0;
+}
+
+int be_cmd_POST(struct be_adapter *adapter)
+{
+	u16 stage;
+	int status, timeout = 0;
+
+	do {
+		status = be_POST_stage_get(adapter, &stage);
+		if (status) {
+			dev_err(&adapter->pdev->dev,
+				"POST error; stage=0x%x.\n", stage);
+			return -1;
+		} else if (stage != POST_STAGE_ARMFW_RDY) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(2 * HZ);
+			timeout += 2;
+		} else {
+			return 0;
+		}
+	} while (timeout < 20);
+
+	dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x.\n", stage);
+	return -1;
+}
+
+/* Tell fw we're about to start firing cmds by writing a
+ * special pattern across the wrb hdr; uses mbox
+ */
+int be_cmd_fw_init(struct be_adapter *adapter)
+{
+	u8 *wrb;
+	int status;
+
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = (u8 *)wrb_from_mbox(adapter);
+	*wrb++ = 0xFF;
+	*wrb++ = 0x12;
+	*wrb++ = 0x34;
+	*wrb++ = 0xFF;
+	*wrb++ = 0xFF;
+	*wrb++ = 0x56;
+	*wrb++ = 0x78;
+	*wrb = 0xFF;
+
+	status = be_mbox_notify_wait(adapter);
+
+	spin_unlock(&adapter->mbox_lock);
+	return status;
+}
+
+/* Tell fw we're done with firing cmds by writing a
+ * special pattern across the wrb hdr; uses mbox
+ */
+int be_cmd_fw_clean(struct be_adapter *adapter)
+{
+	u8 *wrb;
+	int status;
+
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = (u8 *)wrb_from_mbox(adapter);
+	*wrb++ = 0xFF;
+	*wrb++ = 0xAA;
+	*wrb++ = 0xBB;
+	*wrb++ = 0xFF;
+	*wrb++ = 0xFF;
+	*wrb++ = 0xCC;
+	*wrb++ = 0xDD;
+	*wrb = 0xFF;
+
+	status = be_mbox_notify_wait(adapter);
+
+	spin_unlock(&adapter->mbox_lock);
+	return status;
+}
+int be_cmd_eq_create(struct be_adapter *adapter,
 		struct be_queue_info *eq, int eq_delay)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_eq_create *req = embedded_payload(wrb);
-	struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_eq_create *req;
 	struct be_dma_mem *q_mem = &eq->dma_mem;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_COMMON_EQ_CREATE);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_EQ_CREATE, sizeof(*req));
@@ -390,7 +450,7 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl,
 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
 
 	AMAP_SET_BITS(struct amap_eq_context, func, req->context,
-			ctrl->pci_func);
+			be_pci_func(adapter));
 	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1);
 	/* 4byte eqe*/
 	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0);
@@ -402,27 +462,32 @@ int be_cmd_eq_create(struct be_ctrl_info *ctrl,
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
+		struct be_cmd_resp_eq_create *resp = embedded_payload(wrb);
 		eq->id = le16_to_cpu(resp->eq_id);
 		eq->created = true;
 	}
-	spin_unlock(&ctrl->mbox_lock);
+
+	spin_unlock(&adapter->mbox_lock);
 	return status;
 }
 
-int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr,
+/* Uses mbox */
+int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
 			u8 type, bool permanent, u32 if_handle)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_mac_query *req = embedded_payload(wrb);
-	struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_mac_query *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_NTWK_MAC_QUERY);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req));
@@ -431,29 +496,39 @@ int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr,
 	if (permanent) {
 		req->permanent = 1;
 	} else {
-		req->if_id = cpu_to_le16((u16)if_handle);
+		req->if_id = cpu_to_le16((u16) if_handle);
 		req->permanent = 0;
 	}
 
-	status = be_mbox_notify(ctrl);
-	if (!status)
+	status = be_mbox_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_mac_query *resp = embedded_payload(wrb);
 		memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
+	}
 
-	spin_unlock(&ctrl->mbox_lock);
+	spin_unlock(&adapter->mbox_lock);
 	return status;
 }
 
-int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr,
+/* Uses synchronous MCCQ */
+int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
 		u32 if_id, u32 *pmac_id)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_pmac_add *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_pmac_add *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_NTWK_PMAC_ADD);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req));
@@ -461,26 +536,35 @@ int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr,
 	req->if_id = cpu_to_le32(if_id);
 	memcpy(req->mac_address, mac_addr, ETH_ALEN);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb);
 		*pmac_id = le32_to_cpu(resp->pmac_id);
 	}
 
-	spin_unlock(&ctrl->mbox_lock);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id)
+/* Uses synchronous MCCQ */
+int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_pmac_del *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_pmac_del *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock_bh(&adapter->mcc_lock);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_NTWK_PMAC_DEL);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req));
@@ -488,27 +572,31 @@ int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id)
 	req->if_id = cpu_to_le32(if_id);
 	req->pmac_id = cpu_to_le32(pmac_id);
 
-	status = be_mbox_notify(ctrl);
-	spin_unlock(&ctrl->mbox_lock);
+	status = be_mcc_notify_wait(adapter);
 
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-int be_cmd_cq_create(struct be_ctrl_info *ctrl,
+/* Uses Mbox */
+int be_cmd_cq_create(struct be_adapter *adapter,
 		struct be_queue_info *cq, struct be_queue_info *eq,
 		bool sol_evts, bool no_delay, int coalesce_wm)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_cq_create *req = embedded_payload(wrb);
-	struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_cq_create *req;
 	struct be_dma_mem *q_mem = &cq->dma_mem;
-	void *ctxt = &req->context;
+	void *ctxt;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
+	ctxt = &req->context;
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_COMMON_CQ_CREATE);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_CQ_CREATE, sizeof(*req));
@@ -524,17 +612,19 @@ int be_cmd_cq_create(struct be_ctrl_info *ctrl,
 	AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1);
 	AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id);
 	AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1);
-	AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func);
+	AMAP_SET_BITS(struct amap_cq_context, func, ctxt, be_pci_func(adapter));
 	be_dws_cpu_to_le(ctxt, sizeof(req->context));
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
+		struct be_cmd_resp_cq_create *resp = embedded_payload(wrb);
 		cq->id = le16_to_cpu(resp->cq_id);
 		cq->created = true;
 	}
-	spin_unlock(&ctrl->mbox_lock);
+
+	spin_unlock(&adapter->mbox_lock);
 
 	return status;
 }
@@ -547,27 +637,31 @@ static u32 be_encoded_q_len(int q_len)
 	return len_encoded;
 }
 
-int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
+int be_cmd_mccq_create(struct be_adapter *adapter,
 			struct be_queue_info *mccq,
 			struct be_queue_info *cq)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_mcc_create *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_mcc_create *req;
 	struct be_dma_mem *q_mem = &mccq->dma_mem;
-	void *ctxt = &req->context;
+	void *ctxt;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
+	ctxt = &req->context;
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_MCC_CREATE);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 			OPCODE_COMMON_MCC_CREATE, sizeof(*req));
 
 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
 
-	AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, ctrl->pci_func);
+	AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, be_pci_func(adapter));
 	AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
 	AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
 		be_encoded_q_len(mccq->len));
@@ -577,31 +671,34 @@ int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb);
 		mccq->id = le16_to_cpu(resp->id);
 		mccq->created = true;
 	}
-	spin_unlock(&ctrl->mbox_lock);
+	spin_unlock(&adapter->mbox_lock);
 
 	return status;
 }
 
-int be_cmd_txq_create(struct be_ctrl_info *ctrl,
+int be_cmd_txq_create(struct be_adapter *adapter,
 			struct be_queue_info *txq,
 			struct be_queue_info *cq)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_eth_tx_create *req;
 	struct be_dma_mem *q_mem = &txq->dma_mem;
-	void *ctxt = &req->context;
+	void *ctxt;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
+	ctxt = &req->context;
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_TX_CREATE);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE,
 		sizeof(*req));
@@ -613,7 +710,7 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl,
 	AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt,
 		be_encoded_q_len(txq->len));
 	AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt,
-			ctrl->pci_func);
+			be_pci_func(adapter));
 	AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1);
 	AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id);
 
@@ -621,30 +718,34 @@ int be_cmd_txq_create(struct be_ctrl_info *ctrl,
 
 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb);
 		txq->id = le16_to_cpu(resp->cid);
 		txq->created = true;
 	}
-	spin_unlock(&ctrl->mbox_lock);
+
+	spin_unlock(&adapter->mbox_lock);
 
 	return status;
 }
 
-int be_cmd_rxq_create(struct be_ctrl_info *ctrl,
+/* Uses mbox */
+int be_cmd_rxq_create(struct be_adapter *adapter,
 		struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
 		u16 max_frame_size, u32 if_id, u32 rss)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_eth_rx_create *req;
 	struct be_dma_mem *q_mem = &rxq->dma_mem;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_RX_CREATE);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE,
 		sizeof(*req));
@@ -657,30 +758,33 @@ int be_cmd_rxq_create(struct be_ctrl_info *ctrl,
 	req->max_frame_size = cpu_to_le16(max_frame_size);
 	req->rss_queue = cpu_to_le32(rss);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb);
 		rxq->id = le16_to_cpu(resp->id);
 		rxq->created = true;
 	}
-	spin_unlock(&ctrl->mbox_lock);
+
+	spin_unlock(&adapter->mbox_lock);
 
 	return status;
 }
 
-/* Generic destroyer function for all types of queues */
-int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
+/* Generic destroyer function for all types of queues
+ * Uses Mbox
+ */
+int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 		int queue_type)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_q_destroy *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_q_destroy *req;
 	u8 subsys = 0, opcode = 0;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
+	spin_lock(&adapter->mbox_lock);
 
-	memset(wrb, 0, sizeof(*wrb));
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
 
 	switch (queue_type) {
 	case QTYPE_EQ:
@@ -706,38 +810,47 @@ int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
 	default:
 		BUG();
 	}
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, opcode);
+
 	be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req));
 	req->id = cpu_to_le16(q->id);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
+
+	spin_unlock(&adapter->mbox_lock);
 
-	spin_unlock(&ctrl->mbox_lock);
 	return status;
 }
 
-/* Create an rx filtering policy configuration on an i/f */
-int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac,
-		bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
+/* Create an rx filtering policy configuration on an i/f
+ * Uses mbox
+ */
+int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
+		u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_if_create *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_if_create *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_NTWK_INTERFACE_CREATE);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req));
 
-	req->capability_flags = cpu_to_le32(flags);
-	req->enable_flags = cpu_to_le32(flags);
+	req->capability_flags = cpu_to_le32(cap_flags);
+	req->enable_flags = cpu_to_le32(en_flags);
 	req->pmac_invalid = pmac_invalid;
 	if (!pmac_invalid)
 		memcpy(req->mac_addr, mac, ETH_ALEN);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_if_create *resp = embedded_payload(wrb);
 		*if_handle = le32_to_cpu(resp->interface_id);
@@ -745,46 +858,61 @@ int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac,
 			*pmac_id = le32_to_cpu(resp->pmac_id);
 	}
 
-	spin_unlock(&ctrl->mbox_lock);
+	spin_unlock(&adapter->mbox_lock);
 	return status;
 }
 
-int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id)
+/* Uses mbox */
+int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_if_destroy *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_if_destroy *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_NTWK_INTERFACE_DESTROY);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req));
 
 	req->interface_id = cpu_to_le32(interface_id);
-	status = be_mbox_notify(ctrl);
 
-	spin_unlock(&ctrl->mbox_lock);
+	status = be_mbox_notify_wait(adapter);
+
+	spin_unlock(&adapter->mbox_lock);
 
 	return status;
 }
 
 /* Get stats is a non embedded command: the request is not embedded inside
  * WRB but is a separate dma memory block
+ * Uses asynchronous MCC
  */
-int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd)
+int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_get_stats *req = nonemb_cmd->va;
-	struct be_sge *sge = nonembedded_sgl(wrb);
-	int status;
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_stats *req;
+	struct be_sge *sge;
+	int status = 0;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = nonemb_cmd->va;
+	sge = nonembedded_sgl(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
+			OPCODE_ETH_GET_STATISTICS);
+	wrb->tag0 = OPCODE_ETH_GET_STATISTICS;
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
 		OPCODE_ETH_GET_STATISTICS, sizeof(*req));
@@ -792,79 +920,101 @@ int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd)
 	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
 	sge->len = cpu_to_le32(nonemb_cmd->size);
 
-	status = be_mbox_notify(ctrl);
-	if (!status) {
-		struct be_cmd_resp_get_stats *resp = nonemb_cmd->va;
-		be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats));
-	}
+	be_mcc_notify(adapter);
 
-	spin_unlock(&ctrl->mbox_lock);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
-			bool *link_up)
+/* Uses synchronous mcc */
+int be_cmd_link_status_query(struct be_adapter *adapter,
+			bool *link_up, u8 *mac_speed, u16 *link_speed)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_link_status *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_link_status *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
 
 	*link_up = false;
-	memset(wrb, 0, sizeof(*wrb));
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_NTWK_LINK_STATUS_QUERY);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req));
 
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
-		if (resp->mac_speed != PHY_LINK_SPEED_ZERO)
+		if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
 			*link_up = true;
+			*link_speed = le16_to_cpu(resp->link_speed);
+			*mac_speed = resp->mac_speed;
+		}
 	}
 
-	spin_unlock(&ctrl->mbox_lock);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver)
+/* Uses Mbox */
+int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_get_fw_version *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_fw_version *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_GET_FW_VERSION);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_GET_FW_VERSION, sizeof(*req));
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
 		strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);
 	}
 
-	spin_unlock(&ctrl->mbox_lock);
+	spin_unlock(&adapter->mbox_lock);
 	return status;
 }
 
-/* set the EQ delay interval of an EQ to specified value */
-int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd)
+/* set the EQ delay interval of an EQ to specified value
+ * Uses async mcc
+ */
+int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb);
-	int status;
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_modify_eq_delay *req;
+	int status = 0;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock_bh(&adapter->mcc_lock);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_MODIFY_EQ_DELAY);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
@@ -874,23 +1024,32 @@ int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd)
 	req->delay[0].phase = 0;
 	req->delay[0].delay_multiplier = cpu_to_le32(eqd);
 
-	status = be_mbox_notify(ctrl);
+	be_mcc_notify(adapter);
 
-	spin_unlock(&ctrl->mbox_lock);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array,
+/* Uses sycnhronous mcc */
+int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
 			u32 num, bool untagged, bool promiscuous)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_vlan_config *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_vlan_config *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
-	memset(wrb, 0, sizeof(*wrb));
+	spin_lock_bh(&adapter->mcc_lock);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_NTWK_VLAN_CONFIG);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req));
@@ -904,26 +1063,32 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array,
 			req->num_vlan * sizeof(vtag_array[0]));
 	}
 
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(adapter);
 
-	spin_unlock(&ctrl->mbox_lock);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-/* Use MCC for this command as it may be called in BH context */
-int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
+/* Uses MCC for this command as it may be called in BH context
+ * Uses synchronous mcc
+ */
+int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_promiscuous_config *req;
+	int status;
 
-	spin_lock_bh(&ctrl->mcc_lock);
-
-	wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
-	BUG_ON(!wrb);
+	spin_lock_bh(&adapter->mcc_lock);
 
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
 	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_PROMISCUOUS);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
 		OPCODE_ETH_PROMISCUOUS, sizeof(*req));
@@ -933,37 +1098,47 @@ int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
 	else
 		req->port0_promiscuous = en;
 
-	be_mcc_notify_wait(ctrl);
+	status = be_mcc_notify_wait(adapter);
 
-	spin_unlock_bh(&ctrl->mcc_lock);
-	return 0;
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
 }
 
-#define BE_MAX_MC		32 /* set mcast promisc if > 32 */
 /*
- * Use MCC for this command as it may be called in BH context
+ * Uses MCC for this command as it may be called in BH context
  * (mc == NULL) => multicast promiscous
  */
-int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
-		struct dev_mc_list *mc_list, u32 mc_count)
+int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
+		struct dev_mc_list *mc_list, u32 mc_count,
+		struct be_dma_mem *mem)
 {
 	struct be_mcc_wrb *wrb;
-	struct be_cmd_req_mcast_mac_config *req;
-
-	spin_lock_bh(&ctrl->mcc_lock);
+	struct be_cmd_req_mcast_mac_config *req = mem->va;
+	struct be_sge *sge;
+	int status;
 
-	wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
-	BUG_ON(!wrb);
+	spin_lock_bh(&adapter->mcc_lock);
 
-	req = embedded_payload(wrb);
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	sge = nonembedded_sgl(wrb);
+	memset(req, 0, sizeof(*req));
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
+			OPCODE_COMMON_NTWK_MULTICAST_SET);
+	sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
+	sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
+	sge->len = cpu_to_le32(mem->size);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req));
 
 	req->interface_id = if_id;
-	if (mc_list && mc_count <= BE_MAX_MC) {
+	if (mc_list) {
 		int i;
 		struct dev_mc_list *mc;
 
@@ -975,24 +1150,31 @@ int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
 		req->promiscuous = 1;
 	}
 
-	be_mcc_notify_wait(ctrl);
+	status = be_mcc_notify_wait(adapter);
 
-	spin_unlock_bh(&ctrl->mcc_lock);
-
-	return 0;
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
 }
 
-int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc)
+/* Uses synchrounous mcc */
+int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_set_flow_control *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_set_flow_control *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
-	memset(wrb, 0, sizeof(*wrb));
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_SET_FLOW_CONTROL);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req));
@@ -1000,28 +1182,36 @@ int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc)
 	req->tx_flow_control = cpu_to_le16((u16)tx_fc);
 	req->rx_flow_control = cpu_to_le16((u16)rx_fc);
 
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(adapter);
 
-	spin_unlock(&ctrl->mbox_lock);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc)
+/* Uses sycn mcc */
+int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_get_flow_control *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_flow_control *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
-	memset(wrb, 0, sizeof(*wrb));
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_GET_FLOW_CONTROL);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req));
 
-	status = be_mbox_notify(ctrl);
+	status = be_mcc_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_get_flow_control *resp =
 						embedded_payload(wrb);
@@ -1029,31 +1219,276 @@ int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc)
 		*rx_fc = le16_to_cpu(resp->rx_flow_control);
 	}
 
-	spin_unlock(&ctrl->mbox_lock);
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
-int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num)
+/* Uses mbox */
+int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *cap)
 {
-	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-	struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb);
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_query_fw_cfg *req;
 	int status;
 
-	spin_lock(&ctrl->mbox_lock);
+	spin_lock(&adapter->mbox_lock);
 
-	memset(wrb, 0, sizeof(*wrb));
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
 
-	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_QUERY_FIRMWARE_CONFIG);
 
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req));
 
-	status = be_mbox_notify(ctrl);
+	status = be_mbox_notify_wait(adapter);
 	if (!status) {
 		struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb);
 		*port_num = le32_to_cpu(resp->phys_port);
+		*cap = le32_to_cpu(resp->function_cap);
 	}
 
-	spin_unlock(&ctrl->mbox_lock);
+	spin_unlock(&adapter->mbox_lock);
+	return status;
+}
+
+/* Uses mbox */
+int be_cmd_reset_function(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_hdr *req;
+	int status;
+
+	spin_lock(&adapter->mbox_lock);
+
+	wrb = wrb_from_mbox(adapter);
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_FUNCTION_RESET);
+
+	be_cmd_hdr_prepare(req, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
+
+	status = be_mbox_notify_wait(adapter);
+
+	spin_unlock(&adapter->mbox_lock);
+	return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num,
+			u8 bcn, u8 sts, u8 state)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_enable_disable_beacon *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_ENABLE_DISABLE_BEACON);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_ENABLE_DISABLE_BEACON, sizeof(*req));
+
+	req->port_num = port_num;
+	req->beacon_state = state;
+	req->beacon_duration = bcn;
+	req->status_duration = sts;
+
+	status = be_mcc_notify_wait(adapter);
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_beacon_state *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_GET_BEACON_STATE);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_GET_BEACON_STATE, sizeof(*req));
+
+	req->port_num = port_num;
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_get_beacon_state *resp =
+						embedded_payload(wrb);
+		*state = resp->beacon_state;
+	}
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_read_port_type(struct be_adapter *adapter, u32 port,
+				u8 *connector)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_port_type *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(struct be_cmd_resp_port_type), true, 0,
+			OPCODE_COMMON_READ_TRANSRECV_DATA);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_READ_TRANSRECV_DATA, sizeof(*req));
+
+	req->port = cpu_to_le32(port);
+	req->page_num = cpu_to_le32(TR_PAGE_A0);
+	status = be_mcc_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_port_type *resp = embedded_payload(wrb);
+			*connector = resp->data.connector;
+	}
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
+			u32 flash_type, u32 flash_opcode, u32 buf_size)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_write_flashrom *req = cmd->va;
+	struct be_sge *sge;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = cmd->va;
+	sge = nonembedded_sgl(wrb);
+
+	be_wrb_hdr_prepare(wrb, cmd->size, false, 1,
+			OPCODE_COMMON_WRITE_FLASHROM);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_WRITE_FLASHROM, cmd->size);
+	sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
+	sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
+	sge->len = cpu_to_le32(cmd->size);
+
+	req->params.op_type = cpu_to_le32(flash_type);
+	req->params.op_code = cpu_to_le32(flash_opcode);
+	req->params.data_buf_size = cpu_to_le32(buf_size);
+
+	status = be_mcc_notify_wait(adapter);
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_write_flashrom *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req)+4, true, 0,
+			OPCODE_COMMON_READ_FLASHROM);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4);
+
+	req->params.op_type = cpu_to_le32(FLASHROM_TYPE_REDBOOT);
+	req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
+	req->params.offset = 0x3FFFC;
+	req->params.data_buf_size = 0x4;
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status)
+		memcpy(flashed_crc, req->params.data_buf, 4);
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
+int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
+				struct be_dma_mem *nonemb_cmd)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_acpi_wol_magic_config *req;
+	struct be_sge *sge;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = nonemb_cmd->va;
+	sge = nonembedded_sgl(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1,
+			OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH,
+		OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, sizeof(*req));
+	memcpy(req->magic_mac, mac, ETH_ALEN);
+
+	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
+	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
+	sge->len = cpu_to_le32(nonemb_cmd->size);
+
+	status = be_mcc_notify_wait(adapter);
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 058047a..a091360 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -61,7 +61,8 @@ enum {
 /* The command is completing because the queue was getting flushed */
 	MCC_STATUS_QUEUE_FLUSHING = 0x4,
 /* The command is completing with a DMA error */
-	MCC_STATUS_DMA_FAILED = 0x5
+	MCC_STATUS_DMA_FAILED = 0x5,
+	MCC_STATUS_NOT_SUPPORTED = 66
 };
 
 #define CQE_STATUS_COMPL_MASK		0xFFFF
@@ -117,6 +118,8 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_NTWK_MULTICAST_SET		3
 #define OPCODE_COMMON_NTWK_VLAN_CONFIG  		4
 #define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY		5
+#define OPCODE_COMMON_READ_FLASHROM			6
+#define OPCODE_COMMON_WRITE_FLASHROM			7
 #define OPCODE_COMMON_CQ_CREATE				12
 #define OPCODE_COMMON_EQ_CREATE				13
 #define OPCODE_COMMON_MCC_CREATE        		21
@@ -135,6 +138,10 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG		58
 #define OPCODE_COMMON_NTWK_PMAC_ADD			59
 #define OPCODE_COMMON_NTWK_PMAC_DEL			60
+#define OPCODE_COMMON_FUNCTION_RESET			61
+#define OPCODE_COMMON_ENABLE_DISABLE_BEACON		69
+#define OPCODE_COMMON_GET_BEACON_STATE			70
+#define OPCODE_COMMON_READ_TRANSRECV_DATA		73
 
 #define OPCODE_ETH_ACPI_CONFIG				2
 #define OPCODE_ETH_PROMISCUOUS				3
@@ -143,6 +150,7 @@ struct be_mcc_mailbox {
 #define OPCODE_ETH_RX_CREATE            		8
 #define OPCODE_ETH_TX_DESTROY           		9
 #define OPCODE_ETH_RX_DESTROY           		10
+#define OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG		12
 
 struct be_cmd_req_hdr {
 	u8 opcode;		/* dword 0 */
@@ -584,6 +592,8 @@ struct be_cmd_req_promiscuous_config {
 	u16 rsvd0;
 } __packed;
 
+/******************** Multicast MAC Config *******************/
+#define BE_MAX_MC		64 /* set mcast promisc if > 64 */
 struct macaddr {
 	u8 byte[ETH_ALEN];
 };
@@ -593,7 +603,7 @@ struct be_cmd_req_mcast_mac_config {
 	u16 num_mac;
 	u8 promiscuous;
 	u8 interface_id;
-	struct macaddr mac[32];
+	struct macaddr mac[BE_MAX_MC];
 } __packed;
 
 static inline struct be_hw_stats *
@@ -630,11 +640,48 @@ struct be_cmd_resp_link_status {
 	u8 mac_fault;
 	u8 mgmt_mac_duplex;
 	u8 mgmt_mac_speed;
-	u16 rsvd0;
+	u16 link_speed;
+	u32 rsvd0;
 } __packed;
 
+/******************** Port Identification ***************************/
+/*    Identifies the type of port attached to NIC     */
+struct be_cmd_req_port_type {
+	struct be_cmd_req_hdr hdr;
+	u32 page_num;
+	u32 port;
+};
+
+enum {
+	TR_PAGE_A0 = 0xa0,
+	TR_PAGE_A2 = 0xa2
+};
+
+struct be_cmd_resp_port_type {
+	struct be_cmd_resp_hdr hdr;
+	u32 page_num;
+	u32 port;
+	struct data {
+		u8 identifier;
+		u8 identifier_ext;
+		u8 connector;
+		u8 transceiver[8];
+		u8 rsvd0[3];
+		u8 length_km;
+		u8 length_hm;
+		u8 length_om1;
+		u8 length_om2;
+		u8 length_cu;
+		u8 length_cu_m;
+		u8 vendor_name[16];
+		u8 rsvd;
+		u8 vendor_oui[3];
+		u8 vendor_pn[16];
+		u8 vendor_rev[4];
+	} data;
+};
+
 /******************** Get FW Version *******************/
-#define FW_VER_LEN			32
 struct be_cmd_req_get_fw_version {
 	struct be_cmd_req_hdr hdr;
 	u8 rsvd0[FW_VER_LEN];
@@ -693,56 +740,129 @@ struct be_cmd_resp_query_fw_cfg {
 	u32 be_config_number;
 	u32 asic_revision;
 	u32 phys_port;
-	u32 function_mode;
+	u32 function_cap;
 	u32 rsvd[26];
 };
 
-extern int be_pci_fnum_get(struct be_ctrl_info *ctrl);
-extern int be_cmd_POST(struct be_ctrl_info *ctrl);
-extern int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr,
+/******************** Port Beacon ***************************/
+
+#define BEACON_STATE_ENABLED		0x1
+#define BEACON_STATE_DISABLED		0x0
+
+struct be_cmd_req_enable_disable_beacon {
+	struct be_cmd_req_hdr hdr;
+	u8  port_num;
+	u8  beacon_state;
+	u8  beacon_duration;
+	u8  status_duration;
+} __packed;
+
+struct be_cmd_resp_enable_disable_beacon {
+	struct be_cmd_resp_hdr resp_hdr;
+	u32 rsvd0;
+} __packed;
+
+struct be_cmd_req_get_beacon_state {
+	struct be_cmd_req_hdr hdr;
+	u8  port_num;
+	u8  rsvd0;
+	u16 rsvd1;
+} __packed;
+
+struct be_cmd_resp_get_beacon_state {
+	struct be_cmd_resp_hdr resp_hdr;
+	u8 beacon_state;
+	u8 rsvd0[3];
+} __packed;
+
+/****************** Firmware Flash ******************/
+struct flashrom_params {
+	u32 op_code;
+	u32 op_type;
+	u32 data_buf_size;
+	u32 offset;
+	u8 data_buf[4];
+};
+
+struct be_cmd_write_flashrom {
+	struct be_cmd_req_hdr hdr;
+	struct flashrom_params params;
+};
+
+/************************ WOL *******************************/
+struct be_cmd_req_acpi_wol_magic_config{
+	struct be_cmd_req_hdr hdr;
+	u32 rsvd0[145];
+	u8 magic_mac[6];
+	u8 rsvd2[2];
+} __packed;
+
+extern int be_pci_fnum_get(struct be_adapter *adapter);
+extern int be_cmd_POST(struct be_adapter *adapter);
+extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
 			u8 type, bool permanent, u32 if_handle);
-extern int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr,
+extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
 			u32 if_id, u32 *pmac_id);
-extern int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id);
-extern int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 if_flags, u8 *mac,
-			bool pmac_invalid, u32 *if_handle, u32 *pmac_id);
-extern int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 if_handle);
-extern int be_cmd_eq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id);
+extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
+			u32 en_flags, u8 *mac, bool pmac_invalid,
+			u32 *if_handle, u32 *pmac_id);
+extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle);
+extern int be_cmd_eq_create(struct be_adapter *adapter,
 			struct be_queue_info *eq, int eq_delay);
-extern int be_cmd_cq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_cq_create(struct be_adapter *adapter,
 			struct be_queue_info *cq, struct be_queue_info *eq,
 			bool sol_evts, bool no_delay,
 			int num_cqe_dma_coalesce);
-extern int be_cmd_mccq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_mccq_create(struct be_adapter *adapter,
 			struct be_queue_info *mccq,
 			struct be_queue_info *cq);
-extern int be_cmd_txq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_txq_create(struct be_adapter *adapter,
 			struct be_queue_info *txq,
 			struct be_queue_info *cq);
-extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl,
+extern int be_cmd_rxq_create(struct be_adapter *adapter,
 			struct be_queue_info *rxq, u16 cq_id,
 			u16 frag_size, u16 max_frame_size, u32 if_id,
 			u32 rss);
-extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q,
+extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 			int type);
-extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl,
-			bool *link_up);
-extern int be_cmd_reset(struct be_ctrl_info *ctrl);
-extern int be_cmd_get_stats(struct be_ctrl_info *ctrl,
+extern int be_cmd_link_status_query(struct be_adapter *adapter,
+			bool *link_up, u8 *mac_speed, u16 *link_speed);
+extern int be_cmd_reset(struct be_adapter *adapter);
+extern int be_cmd_get_stats(struct be_adapter *adapter,
 			struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver);
+extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver);
 
-extern int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd);
-extern int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id,
+extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd);
+extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id,
 			u16 *vtag_array, u32 num, bool untagged,
 			bool promiscuous);
-extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl,
+extern int be_cmd_promiscuous_config(struct be_adapter *adapter,
 			u8 port_num, bool en);
-extern int be_cmd_multicast_set(struct be_ctrl_info *ctrl, u32 if_id,
-			struct dev_mc_list *mc_list, u32 mc_count);
-extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl,
+extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
+			struct dev_mc_list *mc_list, u32 mc_count,
+			struct be_dma_mem *mem);
+extern int be_cmd_set_flow_control(struct be_adapter *adapter,
 			u32 tx_fc, u32 rx_fc);
-extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl,
+extern int be_cmd_get_flow_control(struct be_adapter *adapter,
 			u32 *tx_fc, u32 *rx_fc);
-extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num);
-extern void be_process_mcc(struct be_ctrl_info *ctrl);
+extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
+			u32 *port_num, u32 *cap);
+extern int be_cmd_reset_function(struct be_adapter *adapter);
+extern int be_process_mcc(struct be_adapter *adapter);
+extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
+			u8 port_num, u8 beacon, u8 status, u8 state);
+extern int be_cmd_get_beacon_state(struct be_adapter *adapter,
+			u8 port_num, u32 *state);
+extern int be_cmd_read_port_type(struct be_adapter *adapter, u32 port,
+					u8 *connector);
+extern int be_cmd_write_flashrom(struct be_adapter *adapter,
+			struct be_dma_mem *cmd, u32 flash_oper,
+			u32 flash_opcode, u32 buf_size);
+extern int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc);
+extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
+				struct be_dma_mem *nonemb_cmd);
+extern int be_cmd_fw_init(struct be_adapter *adapter);
+extern int be_cmd_fw_clean(struct be_adapter *adapter);
+extern void be_async_mcc_enable(struct be_adapter *adapter);
+extern void be_async_mcc_disable(struct be_adapter *adapter);
diff --git a/drivers/net/benet/be_compat.c b/drivers/net/benet/be_compat.c
index 442b31d..610d997 100644
--- a/drivers/net/benet/be_compat.c
+++ b/drivers/net/benet/be_compat.c
@@ -30,6 +30,9 @@ void be_netdev_ops_init(struct net_device *netdev, struct net_device_ops *ops)
 	netdev->vlan_rx_register = ops->ndo_vlan_rx_register;
 	netdev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
 	netdev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = ops->ndo_poll_controller;
+#endif
 }
 
 int eth_validate_addr(struct net_device *netdev)
@@ -51,3 +54,4 @@ int be_poll_compat(struct net_device *netdev, int *budget)
 	else
 		return 1;
 }
+
diff --git a/drivers/net/benet/be_compat.h b/drivers/net/benet/be_compat.h
index ea5c317..d7afdd0 100644
--- a/drivers/net/benet/be_compat.h
+++ b/drivers/net/benet/be_compat.h
@@ -78,6 +78,7 @@ extern void be_netdev_ops_init(struct net_device *netdev,
 			struct net_device_ops *ops);
 extern int eth_validate_addr(struct net_device *);
 
+#define dma_mapping_error(dev, map) dma_mapping_error(map)
 
 /*
  * Back port of new NAPI: simulate polling on multiple napi instances
@@ -87,15 +88,12 @@ extern int eth_validate_addr(struct net_device *);
 extern int be_poll(struct napi_struct *, int);
 extern int be_poll_compat(struct net_device *netdev, int *budget);
 
-static inline void compat_napi_schedule(struct napi_struct *napi)
+static inline void napi_schedule(struct napi_struct *napi)
 {
 	netif_rx_schedule(napi->dev);
 }
-static inline void compat_napi_complete(struct napi_struct *napi)
-{
-	netif_rx_complete(napi->dev);
-}
-static inline void compat_netif_napi_add(struct net_device *netdev,
+
+static inline void netif_napi_add(struct net_device *netdev,
 		  struct napi_struct *napi,
 		  int (*poll) (struct napi_struct *, int), int weight)
 {
@@ -105,12 +103,12 @@ static inline void compat_netif_napi_add(struct net_device *netdev,
 	napi->dev = netdev;
 }
 
-static inline void compat_napi_enable(struct napi_struct *napi)
+static inline void napi_enable(struct napi_struct *napi)
 {
 	netif_poll_enable(napi->dev);
 }
 
-static inline void compat_napi_disable(struct napi_struct *napi)
+static inline void napi_disable(struct napi_struct *napi)
 {
 	netif_poll_disable(napi->dev);
 }
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index 4465362..13e7516 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -16,6 +16,7 @@
  */
 
 #include "be.h"
+#include "be_cmds.h"
 #include <linux/ethtool.h>
 
 struct be_ethtool_stat {
@@ -54,7 +55,7 @@ static const struct be_ethtool_stat et_stats[] = {
 	{DRVSTAT_INFO(be_tx_stops)},
 	{DRVSTAT_INFO(be_fwd_reqs)},
 	{DRVSTAT_INFO(be_tx_wrbs)},
-	{DRVSTAT_INFO(be_polls)},
+	{DRVSTAT_INFO(be_rx_polls)},
 	{DRVSTAT_INFO(be_tx_events)},
 	{DRVSTAT_INFO(be_rx_events)},
 	{DRVSTAT_INFO(be_tx_compl)},
@@ -63,7 +64,6 @@ static const struct be_ethtool_stat et_stats[] = {
 	{DRVSTAT_INFO(be_802_3_dropped_frames)},
 	{DRVSTAT_INFO(be_802_3_malformed_frames)},
 	{DRVSTAT_INFO(be_tx_rate)},
-	{DRVSTAT_INFO(be_eps)},
 	{DRVSTAT_INFO(be_rx_rate)},
 	{PORTSTAT_INFO(rx_unicast_frames)},
 	{PORTSTAT_INFO(rx_multicast_frames)},
@@ -127,7 +127,6 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct be_eq_obj *be_eq = &adapter->be_eq;
 
-	coalesce->rx_max_coalesced_frames = adapter->max_rx_coal;
 
 	coalesce->rx_coalesce_usecs = be_eq->cur_eqd;
 	coalesce->rx_coalesce_usecs_high = be_eq->max_eqd;
@@ -144,22 +143,16 @@ be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 }
 
 /*
- * This routine is used to set interrup coalescing delay *as well as*
- * the number of pkts to coalesce for LRO.
+ * This routine is used to set interrup coalescing delay
  */
 static int
 be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	struct be_eq_obj *be_eq = &adapter->be_eq;
 	u32 max = 0, min = 0, cur = 0, rx, tx;
 	int status = 0;
 
-	adapter->max_rx_coal = coalesce->rx_max_coalesced_frames;
-	if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME)
-		adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME;
-
 	/* if AIC is being turned on now, start with an EQD of 0 */
 	if (be_eq->enable_aic == 0 &&
 		((coalesce->use_adaptive_rx_coalesce == 1) || 
@@ -221,7 +214,7 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 		if (cur > BE_MAX_EQD)
 			cur = BE_MAX_EQD;
 		if (be_eq->cur_eqd != cur) {
-			status = be_cmd_modify_eqd(ctrl, be_eq->q.id, cur);
+			status = be_cmd_modify_eqd(adapter, be_eq->q.id, cur);
 			if (!status)
 				be_eq->cur_eqd = cur;
 		}
@@ -312,9 +305,52 @@ static int be_get_stats_count(struct net_device *netdev)
 
 static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
-	ecmd->speed = SPEED_10000;
+	struct be_adapter *adapter = netdev_priv(netdev);
+	u8 mac_speed = 0, connector = 0;
+	u16 link_speed = 0;
+	bool link_up = false;
+
+	if (adapter->link_speed < 0) {
+		be_cmd_link_status_query(adapter, &link_up, &mac_speed,
+					 &link_speed);
+
+		/* link_speed is in units of 10 Mbps */
+		if (link_speed) {
+			ecmd->speed = link_speed*10;
+		} else {
+			switch (mac_speed) {
+			case PHY_LINK_SPEED_1GBPS:
+				ecmd->speed = SPEED_1000;
+				break;
+			case PHY_LINK_SPEED_10GBPS:
+				ecmd->speed = SPEED_10000;
+				break;
+			}
+		}
+
+		be_cmd_read_port_type(adapter, adapter->port_num, &connector);
+		switch (connector) {
+		case 7:
+			ecmd->port = PORT_FIBRE;
+			break;
+		default:
+			ecmd->port = PORT_TP;
+			break;
+		}
+
+		adapter->link_speed = ecmd->speed;
+		adapter->port_type = ecmd->port;
+	} else {
+		ecmd->speed = adapter->link_speed;
+		ecmd->port = adapter->port_type;
+	}
+
 	ecmd->duplex = DUPLEX_FULL;
 	ecmd->autoneg = AUTONEG_DISABLE;
+	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_TP);
+	ecmd->phy_address = adapter->port_num;
+	ecmd->transceiver = XCVR_INTERNAL;
+
 	return 0;
 }
 
@@ -335,8 +371,7 @@ be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 
-	be_cmd_get_flow_control(&adapter->ctrl, &ecmd->tx_pause,
-		&ecmd->rx_pause);
+	be_cmd_get_flow_control(adapter, &ecmd->tx_pause, &ecmd->rx_pause);
 	ecmd->autoneg = 0;
 }
 
@@ -348,18 +383,78 @@ be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
 
 	if (ecmd->autoneg != 0)
 		return -EINVAL;
+	adapter->tx_fc = ecmd->tx_pause;
+	adapter->rx_fc = ecmd->rx_pause;
 
-	status = be_cmd_set_flow_control(&adapter->ctrl, ecmd->tx_pause,
-			ecmd->rx_pause);
-	if (!status)
+	status = be_cmd_set_flow_control(adapter,
+					adapter->tx_fc, adapter->rx_fc);
+	if (status)
 		dev_warn(&adapter->pdev->dev, "Pause param set failed.\n");
 
 	return status;
 }
 
+static int
+be_phys_id(struct net_device *netdev, u32 data)
+{
+	struct be_adapter *adapter = netdev_priv(netdev);
+	int status;
+	u32 cur;
+
+	be_cmd_get_beacon_state(adapter, adapter->port_num, &cur);
+
+	if (cur == BEACON_STATE_ENABLED)
+		return 0;
+
+	if (data < 2)
+		data = 2;
+
+	status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0,
+			BEACON_STATE_ENABLED);
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(data*HZ);
+
+	status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0,
+			BEACON_STATE_DISABLED);
+
+	return status;
+}
+
+static void
+be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct be_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_MAGIC;
+	if (adapter->wol)
+		wol->wolopts = WAKE_MAGIC;
+	else
+		wol->wolopts = 0;
+	memset(&wol->sopass, 0, sizeof(wol->sopass));
+	return;
+}
+
+static int
+be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct be_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol = true;
+	else
+		adapter->wol = false;
+
+	return 0;
+}
+
 struct ethtool_ops be_ethtool_ops = {
 	.get_settings = be_get_settings,
 	.get_drvinfo = be_get_drvinfo,
+	.get_wol = be_get_wol,
+	.set_wol = be_set_wol,
 	.get_link = ethtool_op_get_link,
 	.get_coalesce = be_get_coalesce,
 	.set_coalesce = be_set_coalesce,
@@ -369,12 +464,13 @@ struct ethtool_ops be_ethtool_ops = {
 	.get_rx_csum = be_get_rx_csum,
 	.set_rx_csum = be_set_rx_csum,
 	.get_tx_csum = ethtool_op_get_tx_csum,
-	.set_tx_csum = ethtool_op_set_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_hw_csum,
 	.get_sg = ethtool_op_get_sg,
 	.set_sg = ethtool_op_set_sg,
 	.get_tso = ethtool_op_get_tso,
 	.set_tso = ethtool_op_set_tso,
 	.get_strings = be_get_stat_strings,
+	.phys_id = be_phys_id,
 	.get_stats_count = be_get_stats_count,
 	.get_ethtool_stats = be_get_ethtool_stats,
 };
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h
index 59e465a..8fd1ed8 100644
--- a/drivers/net/benet/be_hw.h
+++ b/drivers/net/benet/be_hw.h
@@ -51,13 +51,14 @@
  * with the OS.
  */
 #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK	(1 << 29) /* bit 29 */
-/* PCI physical function number */
-#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK  	0x7 	/* bits 26 - 28 */
-#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT	26
 
-/********* ISR0 Register Offset *************/
-#define CEV_ISR0_OFFSET			0xC18
-#define CEV_ISR_SIZE			4
+/********* Power managment (WOL) **********/
+#define PCICFG_PM_CONTROL_OFFSET		0x44
+#define PCICFG_PM_CONTROL_MASK			0x108	/* bits 3 & 8 */
+
+/********* ISR0 Register offset **********/
+#define CEV_ISR0_OFFSET 			0xC18
+#define CEV_ISR_SIZE				4
 
 /********* Event Q door bell *************/
 #define DB_EQ_OFFSET			DB_CQ_OFFSET
@@ -207,7 +208,7 @@ struct amap_eth_rx_compl {
 	u8 numfrags[3];		/* dword 1 */
 	u8 rss_flush;		/* dword 2 */
 	u8 cast_enc[2];		/* dword 2 */
-	u8 qnq;			/* dword 2 */
+	u8 vtm;			/* dword 2 */
 	u8 rss_bank;		/* dword 2 */
 	u8 rsvd1[23];		/* dword 2 */
 	u8 lro_pkt;		/* dword 2 */
@@ -219,3 +220,91 @@ struct amap_eth_rx_compl {
 struct be_eth_rx_compl {
 	u32 dw[4];
 };
+
+/* Flashrom related descriptors */
+#define IMAGE_TYPE_FIRMWARE		160
+#define IMAGE_TYPE_BOOTCODE		224
+#define IMAGE_TYPE_OPTIONROM		32
+
+#define NUM_FLASHDIR_ENTRIES		32
+
+#define FLASHROM_TYPE_ISCSI_ACTIVE	0
+#define FLASHROM_TYPE_REDBOOT		1
+#define FLASHROM_TYPE_BIOS		2
+#define FLASHROM_TYPE_PXE_BIOS		3
+#define FLASHROM_TYPE_FCOE_BIOS		8
+#define FLASHROM_TYPE_ISCSI_BACKUP	9
+#define FLASHROM_TYPE_FCOE_FW_ACTIVE	10
+#define FLASHROM_TYPE_FCOE_FW_BACKUP 	11
+
+#define FLASHROM_OPER_FLASH		1
+#define FLASHROM_OPER_SAVE		2
+#define FLASHROM_OPER_REPORT		4
+
+#define FLASH_IMAGE_MAX_SIZE            (1310720) /* Max firmware image size */
+#define FLASH_BIOS_IMAGE_MAX_SIZE       (262144)  /* Max OPTION ROM image sz */
+#define FLASH_REDBOOT_IMAGE_MAX_SIZE	(262144)  /* Max Redboot image sz    */
+
+/* Offsets for components on Flash. */
+#define FLASH_iSCSI_PRIMARY_IMAGE_START (1048576)
+#define FLASH_iSCSI_BACKUP_IMAGE_START  (2359296)
+#define FLASH_FCoE_PRIMARY_IMAGE_START  (3670016)
+#define FLASH_FCoE_BACKUP_IMAGE_START   (4980736)
+#define FLASH_iSCSI_BIOS_START          (7340032)
+#define FLASH_PXE_BIOS_START            (7864320)
+#define FLASH_FCoE_BIOS_START           (524288)
+#define FLASH_REDBOOT_START		(32768)
+#define FLASH_REDBOOT_ISM_START		(0)
+
+struct controller_id {
+	u32 vendor;
+	u32 device;
+	u32 subvendor;
+	u32 subdevice;
+};
+
+struct flash_file_hdr {
+	u8 sign[32];
+	u32 cksum;
+	u32 antidote;
+	struct controller_id cont_id;
+	u32 file_len;
+	u32 chunk_num;
+	u32 total_chunks;
+	u32 num_imgs;
+	u8 build[24];
+};
+
+struct flash_section_hdr {
+	u32 format_rev;
+	u32 cksum;
+	u32 antidote;
+	u32 build_no;
+	u8 id_string[64];
+	u32 active_entry_mask;
+	u32 valid_entry_mask;
+	u32 org_content_mask;
+	u32 rsvd0;
+	u32 rsvd1;
+	u32 rsvd2;
+	u32 rsvd3;
+	u32 rsvd4;
+};
+
+struct flash_section_entry {
+	u32 type;
+	u32 offset;
+	u32 pad_size;
+	u32 image_size;
+	u32 cksum;
+	u32 entry_point;
+	u32 rsvd0;
+	u32 rsvd1;
+	u8 ver_data[32];
+};
+
+struct flash_section_info {
+	u8 cookie[32];
+	struct flash_section_hdr fsec_hdr;
+	struct flash_section_entry fsec_entry[32];
+};
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 5c9be2b..49c91a0 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -16,6 +16,7 @@
  */
 
 #include "be.h"
+#include "be_cmds.h"
 #include <asm/div64.h>
 
 MODULE_VERSION(DRV_VER);
@@ -30,12 +31,14 @@ MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
 
 static unsigned int lro = 1;
 module_param(lro, uint, S_IRUGO);
-MODULE_PARM_DESC(lro, "Configure LRO. 1 = ON (Default), 0 = OFF");
+MODULE_PARM_DESC(lro, "Obsolete, only for backward compatibility. Don't use.");
 
 static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
 	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
+	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
 	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
+	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -64,40 +67,39 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
 	return 0;
 }
 
-static void be_intr_set(struct be_ctrl_info *ctrl, bool enable)
+static void be_intr_set(struct be_adapter *adapter, bool enable)
 {
-	u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
+	u8 __iomem *addr = adapter->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET;
 	u32 reg = ioread32(addr);
 	u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
-	if (!enabled && enable) {
+
+	if (!enabled && enable)
 		reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
-	} else if (enabled && !enable) {
+	else if (enabled && !enable)
 		reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;
-	} else {
-		printk(KERN_WARNING DRV_NAME
-			": bad value in membar_int_ctrl reg=0x%x\n", reg);
+	else
 		return;
-	}
+
 	iowrite32(reg, addr);
 }
 
-static void be_rxq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted)
+static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
 {
 	u32 val = 0;
 	val |= qid & DB_RQ_RING_ID_MASK;
 	val |= posted << DB_RQ_NUM_POSTED_SHIFT;
-	iowrite32(val, ctrl->db + DB_RQ_OFFSET);
+	iowrite32(val, adapter->db + DB_RQ_OFFSET);
 }
 
-static void be_txq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted)
+static void be_txq_notify(struct be_adapter *adapter, u16 qid, u16 posted)
 {
 	u32 val = 0;
 	val |= qid & DB_TXULP_RING_ID_MASK;
 	val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT;
-	iowrite32(val, ctrl->db + DB_TXULP1_OFFSET);
+	iowrite32(val, adapter->db + DB_TXULP1_OFFSET);
 }
 
-static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid,
+static void be_eq_notify(struct be_adapter *adapter, u16 qid,
 		bool arm, bool clear_int, u16 num_popped)
 {
 	u32 val = 0;
@@ -108,50 +110,45 @@ static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid,
 		val |= 1 << DB_EQ_CLR_SHIFT;
 	val |= 1 << DB_EQ_EVNT_SHIFT;
 	val |= num_popped << DB_EQ_NUM_POPPED_SHIFT;
-	iowrite32(val, ctrl->db + DB_EQ_OFFSET);
+	iowrite32(val, adapter->db + DB_EQ_OFFSET);
 }
 
-void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid,
-		bool arm, u16 num_popped)
+void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
 {
 	u32 val = 0;
 	val |= qid & DB_CQ_RING_ID_MASK;
 	if (arm)
 		val |= 1 << DB_CQ_REARM_SHIFT;
 	val |= num_popped << DB_CQ_NUM_POPPED_SHIFT;
-	iowrite32(val, ctrl->db + DB_CQ_OFFSET);
+	iowrite32(val, adapter->db + DB_CQ_OFFSET);
 }
 
-
 static int be_mac_addr_set(struct net_device *netdev, void *p)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct sockaddr *addr = p;
 	int status = 0;
 
-	if (netif_running(netdev)) {
-		status = be_cmd_pmac_del(&adapter->ctrl, adapter->if_handle,
-				adapter->pmac_id);
-		if (status)
-			return status;
-
-		status = be_cmd_pmac_add(&adapter->ctrl, (u8 *)addr->sa_data,
-				adapter->if_handle, &adapter->pmac_id);
-	}
+	status = be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id);
+	if (status)
+		return status;
 
+	status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+			adapter->if_handle, &adapter->pmac_id);
 	if (!status)
 		memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
 	return status;
 }
 
-static void netdev_stats_update(struct be_adapter *adapter)
+void netdev_stats_update(struct be_adapter *adapter)
 {
 	struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
 	struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
 	struct be_port_rxf_stats *port_stats =
 			&rxf_stats->port[adapter->port_num];
 	struct net_device_stats *dev_stats = &adapter->stats.net_stats;
+	struct be_erx_stats *erx_stats = &hw_stats->erx;
 
 	dev_stats->rx_packets = port_stats->rx_total_frames;
 	dev_stats->tx_packets = port_stats->tx_unicastframes +
@@ -165,29 +162,34 @@ static void netdev_stats_update(struct be_adapter *adapter)
 	dev_stats->rx_errors = port_stats->rx_crc_errors +
 		port_stats->rx_alignment_symbol_errors +
 		port_stats->rx_in_range_errors +
-		port_stats->rx_out_range_errors + port_stats->rx_frame_too_long;
-
-	/*  packet transmit problems */
-	dev_stats->tx_errors = 0;
-
-	/*  no space in linux buffers */
-	dev_stats->rx_dropped = 0;
-
-	/* no space available in linux */
-	dev_stats->tx_dropped = 0;
-
-	dev_stats->multicast = port_stats->tx_multicastframes;
-	dev_stats->collisions = 0;
+		port_stats->rx_out_range_errors +
+		port_stats->rx_frame_too_long +
+		port_stats->rx_dropped_too_small +
+		port_stats->rx_dropped_too_short +
+		port_stats->rx_dropped_header_too_small +
+		port_stats->rx_dropped_tcp_length +
+		port_stats->rx_dropped_runt +
+		port_stats->rx_tcp_checksum_errs +
+		port_stats->rx_ip_checksum_errs +
+		port_stats->rx_udp_checksum_errs;
+
+	/*  no space in linux buffers: best possible approximation */
+	dev_stats->rx_dropped =
+		erx_stats->rx_drops_no_fragments[adapter->rx_obj.q.id];
 
 	/* detailed rx errors */
 	dev_stats->rx_length_errors = port_stats->rx_in_range_errors +
-		port_stats->rx_out_range_errors + port_stats->rx_frame_too_long;
+		port_stats->rx_out_range_errors +
+		port_stats->rx_frame_too_long;
+
 	/* receive ring buffer overflow */
 	dev_stats->rx_over_errors = 0;
+
 	dev_stats->rx_crc_errors = port_stats->rx_crc_errors;
 
 	/* frame alignment errors */
 	dev_stats->rx_frame_errors = port_stats->rx_alignment_symbol_errors;
+
 	/* receiver fifo overrun */
 	/* drops_no_pbuf is no per i/f, it's per BE card */
 	dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow +
@@ -195,6 +197,16 @@ static void netdev_stats_update(struct be_adapter *adapter)
 					rxf_stats->rx_drops_no_pbuf;
 	/* receiver missed packetd */
 	dev_stats->rx_missed_errors = 0;
+
+	/*  packet transmit problems */
+	dev_stats->tx_errors = 0;
+
+	/* no space available in linux */
+	dev_stats->tx_dropped = 0;
+
+	dev_stats->multicast = port_stats->rx_multicast_frames;
+	dev_stats->collisions = 0;
+
 	/* detailed tx_errors */
 	dev_stats->tx_aborted_errors = 0;
 	dev_stats->tx_carrier_errors = 0;
@@ -203,13 +215,13 @@ static void netdev_stats_update(struct be_adapter *adapter)
 	dev_stats->tx_window_errors = 0;
 }
 
-void be_link_status_update(void *ctxt, bool link_up)
+void be_link_status_update(struct be_adapter *adapter, bool link_up)
 {
-	struct be_adapter *adapter = ctxt;
 	struct net_device *netdev = adapter->netdev;
 
 	/* If link came up or went down */
 	if (adapter->link_up != link_up) {
+		adapter->link_speed = -1;
 		if (link_up) {
 			netif_start_queue(netdev);
 			netif_carrier_on(netdev);
@@ -223,10 +235,9 @@ void be_link_status_update(void *ctxt, bool link_up)
 	}
 }
 
-/* Update the EQ delay in BE based on the num events / sec */
+/* Update the EQ delay n BE based on the RX frags consumed / sec */
 static void be_eqd_update(struct be_adapter *adapter)
 {
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	struct be_eq_obj *be_eq = &adapter->be_eq;
 	struct be_drvr_stats *stats = &adapter->stats.drvr_stats;
 	ulong now = jiffies;
@@ -259,7 +270,7 @@ static void be_eqd_update(struct be_adapter *adapter)
 		eqd -= 8;
 
 	if (eqd != be_eq->cur_eqd) {
-		be_cmd_modify_eqd(ctrl, be_eq->q.id, eqd);
+		be_cmd_modify_eqd(adapter, be_eq->q.id, eqd);
 		be_eq->cur_eqd = eqd;
 	}
 }
@@ -424,7 +435,9 @@ static int make_tx_wrbs(struct be_adapter *adapter,
 	return copied;
 }
 
-static int be_xmit(struct sk_buff *skb, struct net_device *netdev)
+static int be_xmit(struct sk_buff *skb,
+				 struct net_device *netdev)
+
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct be_tx_obj *tx_obj = &adapter->tx_obj;
@@ -436,23 +449,28 @@ static int be_xmit(struct sk_buff *skb, struct net_device *netdev)
 	wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb);
 
 	copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
+	if (copied) {
+		/* record the sent skb in the sent_skb table */
+		BUG_ON(tx_obj->sent_skb_list[start]);
+		tx_obj->sent_skb_list[start] = skb;
+
+		/* Ensure txq has space for the next skb; Else stop the queue
+		 * *BEFORE* ringing the tx doorbell, so that we serialze the
+		 * tx compls of the current transmit which'll wake up the queue
+		 */
+		if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=
+								txq->len) {
+			netif_stop_queue(netdev);
+			stopped = true;
+		}
 
-	/* record the sent skb in the sent_skb table */
-	BUG_ON(tx_obj->sent_skb_list[start]);
-	tx_obj->sent_skb_list[start] = skb;
+		be_txq_notify(adapter, txq->id, wrb_cnt);
 
-	/* Ensure that txq has space for the next skb; Else stop the queue
-	 * *BEFORE* ringing the tx doorbell, so that we serialze the
-	 * tx compls of the current transmit which'll wake up the queue
-	 */
-	if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= txq->len) {
-		netif_stop_queue(netdev);
-		stopped = true;
+		be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
+	} else {
+		txq->head = start;
+		dev_kfree_skb_any(skb);
 	}
-
-	be_txq_notify(&adapter->ctrl, txq->id, wrb_cnt);
-
-	be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
 	return NETDEV_TX_OK;
 }
 
@@ -477,11 +495,11 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)
  * program them in BE.  If more than BE_NUM_VLANS_SUPPORTED are configured,
  * set the BE in promiscuous VLAN mode.
  */
-static void be_vid_config(struct net_device *netdev)
+static int be_vid_config(struct be_adapter *adapter)
 {
-	struct be_adapter *adapter = netdev_priv(netdev);
 	u16 vtag[BE_NUM_VLANS_SUPPORTED];
 	u16 ntags = 0, i;
+	int status;
 
 	if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED)  {
 		/* Construct VLAN Table to give to HW */
@@ -491,23 +509,23 @@ static void be_vid_config(struct net_device *netdev)
 				ntags++;
 			}
 		}
-		be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle,
-			vtag, ntags, 1, 0);
+		status = be_cmd_vlan_config(adapter, adapter->if_handle,
+					vtag, ntags, 1, 0);
 	} else {
-		be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle,
-			NULL, 0, 1, 1);
+		status = be_cmd_vlan_config(adapter, adapter->if_handle,
+					NULL, 0, 1, 1);
 	}
+	return status;
 }
 
 static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 	struct be_eq_obj *be_eq = &adapter->be_eq;
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 
-	be_eq_notify(ctrl, be_eq->q.id, false, false, 0);
+	be_eq_notify(adapter, be_eq->q.id, false, false, 0);
 	adapter->vlan_grp = grp;
-	be_eq_notify(ctrl, be_eq->q.id, true, false, 0);
+	be_eq_notify(adapter, be_eq->q.id, true, false, 0);
 }
 
 static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
@@ -517,7 +535,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
 	adapter->num_vlans++;
 	adapter->vlan_tag[vid] = 1;
 
-	be_vid_config(netdev);
+	be_vid_config(adapter);
 }
 
 static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
@@ -528,16 +546,15 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
 	adapter->vlan_tag[vid] = 0;
 
 	vlan_group_set_device(adapter->vlan_grp, vid, NULL);
-	be_vid_config(netdev);
+	be_vid_config(adapter);
 }
 
 static void be_set_multicast_list(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 
 	if (netdev->flags & IFF_PROMISC) {
-		be_cmd_promiscuous_config(ctrl, adapter->port_num, 1);
+		be_cmd_promiscuous_config(adapter, adapter->port_num, 1);
 		adapter->promiscuous = true;
 		goto done;
 	}
@@ -545,16 +562,18 @@ static void be_set_multicast_list(struct net_device *netdev)
 	/* BE was previously in promiscous mode; disable it */
 	if (adapter->promiscuous) {
 		adapter->promiscuous = false;
-		be_cmd_promiscuous_config(ctrl, adapter->port_num, 0);
+		be_cmd_promiscuous_config(adapter, adapter->port_num, 0);
 	}
 
-	if (netdev->flags & IFF_ALLMULTI) {
-		be_cmd_multicast_set(ctrl, adapter->if_handle, NULL, 0);
+	/* Enable multicast promisc if num configured exceeds what we support */
+	if (netdev->flags & IFF_ALLMULTI || netdev->mc_count > BE_MAX_MC) {
+		be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0,
+				&adapter->mc_cmd_mem);
 		goto done;
 	}
 
-	be_cmd_multicast_set(ctrl, adapter->if_handle, netdev->mc_list,
-		netdev->mc_count);
+	be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list,
+		netdev->mc_count, &adapter->mc_cmd_mem);
 done:
 	return;
 }
@@ -587,7 +606,9 @@ static void be_rx_stats_update(struct be_adapter *adapter,
 	struct be_drvr_stats *stats = drvr_stats(adapter);
 
 	stats->be_rx_compl++;
+	stats->be_rx_frags += numfrags;
 	stats->be_rx_bytes += pktsize;
+	stats->be_rx_pkts++;
 }
 
 static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
@@ -615,9 +636,11 @@ get_rx_page_info(struct be_adapter *adapter, u16 frag_idx)
 	rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx];
 	BUG_ON(!rx_page_info->page);
 
-	if (rx_page_info->last_page_user)
+	if (rx_page_info->last_page_user) {
 		pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus),
 			adapter->big_page_size, PCI_DMA_FROMDEVICE);
+		rx_page_info->last_page_user = false;
+	}
 
 	atomic_dec(&rxq->used);
 	return rx_page_info;
@@ -652,7 +675,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
 	struct be_queue_info *rxq = &adapter->rx_obj.q;
 	struct be_rx_page_info *page_info;
 	u16 rxq_idx, i, num_rcvd, j;
-	u32 pktsize, hdr_len, curr_frag_len;
+	u32 pktsize, hdr_len, curr_frag_len, size;
 	u8 *start;
 
 	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
@@ -685,27 +708,28 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
 		skb->data_len = curr_frag_len - hdr_len;
 		skb->tail += hdr_len;
 	}
-	memset(page_info, 0, sizeof(*page_info));
+	page_info->page = NULL;
 
 	if (pktsize <= rx_frag_size) {
 		BUG_ON(num_rcvd != 1);
-		return;
+		goto done;
 	}
 
 	/* More frags present for this completion */
-	pktsize -= curr_frag_len; /* account for above copied frag */
+	size = pktsize;
 	for (i = 1, j = 0; i < num_rcvd; i++) {
+		size -= curr_frag_len;
 		index_inc(&rxq_idx, rxq->len);
 		page_info = get_rx_page_info(adapter, rxq_idx);
 
-		curr_frag_len = min(pktsize, rx_frag_size);
+		curr_frag_len = min(size, rx_frag_size);
 
 		/* Coalesce all frags from the same physical page in one slot */
-		if (page_info->page_offset == 0) { 
+		if (page_info->page_offset == 0) {
 			/* Fresh page */
 			j++;
 			skb_shinfo(skb)->frags[j].page = page_info->page;
-			skb_shinfo(skb)->frags[j].page_offset = 
+			skb_shinfo(skb)->frags[j].page_offset =
 							page_info->page_offset;
 			skb_shinfo(skb)->frags[j].size = 0;
 			skb_shinfo(skb)->nr_frags++;
@@ -716,24 +740,31 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
 		skb_shinfo(skb)->frags[j].size += curr_frag_len;
 		skb->len += curr_frag_len;
 		skb->data_len += curr_frag_len;
-		pktsize -= curr_frag_len;
 
-		memset(page_info, 0, sizeof(*page_info));
+		page_info->page = NULL;
 	}
 	BUG_ON(j > MAX_SKB_FRAGS);
 
+done:
 	be_rx_stats_update(adapter, pktsize, num_rcvd);
 	return;
 }
 
-/* Process the RX completion indicated by rxcp when LRO is disabled */
+/* Process the RX completion indicated by rxcp when GRO is disabled */
 static void be_rx_compl_process(struct be_adapter *adapter,
 			struct be_eth_rx_compl *rxcp)
 {
 	struct sk_buff *skb;
-	u32 vtp, vid;
+	u32 vlanf, vid;
+	u8 vtm;
+
+	vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
+	vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
 
-	vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
+	/* vlanf could be wrongly set in some cards.
+	 * ignore if vtm is not set */
+	if ((adapter->cap == 0x400) && !vtm)
+		vlanf = 0;
 
 	skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN);
 	if (!skb) {
@@ -756,7 +787,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 	skb->protocol = eth_type_trans(skb, adapter->netdev);
 	skb->dev = adapter->netdev;
 
-	if (vtp) {
+	if (vlanf) {
 		if (!adapter->vlan_grp || adapter->num_vlans == 0) {
 			kfree_skb(skb);
 			return;
@@ -769,51 +800,70 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 	}
 
 	adapter->netdev->last_rx = jiffies;
-
 	return;
 }
 
-/* Process the RX completion indicated by rxcp when LRO is enabled */
-static void be_rx_compl_process_lro(struct be_adapter *adapter,
+/* Process the RX completion indicated by rxcp when GRO is enabled */
+static void be_rx_compl_process_gro(struct be_adapter *adapter,
 			struct be_eth_rx_compl *rxcp)
 {
 	struct be_rx_page_info *page_info;
-	struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME];
+	struct sk_buff *skb = NULL;
 	struct be_queue_info *rxq = &adapter->rx_obj.q;
 	u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
 	u16 i, rxq_idx = 0, vid, j;
+	u8 vtm;
 
 	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
 	pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
 	vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
 	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
+	vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
+
+	/* vlanf could be wrongly set in some cards.
+	 * ignore if vtm is not set */
+	if ((adapter->cap == 0x400) && !vtm)
+		vlanf = 0;
+
+	skb = napi_get_frags(&adapter->napi);
+	if (!skb) {
+		be_rx_compl_discard(adapter, rxcp);
+		return;
+	}
 
 	remaining = pkt_size;
 	for (i = 0, j = -1; i < num_rcvd; i++) {
 		page_info = get_rx_page_info(adapter, rxq_idx);
+
 		curr_frag_len = min(remaining, rx_frag_size);
 
 		/* Coalesce all frags from the same physical page in one slot */
-		if (i == 0 || page_info->page_offset == 0) { 
+		if (i == 0 || page_info->page_offset == 0) {
 			/* First frag or Fresh page */
 			j++;
-			rx_frags[j].page = page_info->page;
-			rx_frags[j].page_offset = page_info->page_offset;
-			rx_frags[j].size = 0;
+			skb_shinfo(skb)->frags[j].page = page_info->page;
+			skb_shinfo(skb)->frags[j].page_offset =
+							page_info->page_offset;
+			skb_shinfo(skb)->frags[j].size = 0;
 		} else {
 			put_page(page_info->page);
 		}
+		skb_shinfo(skb)->frags[j].size += curr_frag_len;
 
-		rx_frags[j].size += curr_frag_len;
 		remaining -= curr_frag_len;
 		index_inc(&rxq_idx, rxq->len);
 		memset(page_info, 0, sizeof(*page_info));
 	}
 	BUG_ON(j > MAX_SKB_FRAGS);
 
+	skb_shinfo(skb)->nr_frags = j + 1;
+	skb->len = pkt_size;
+	skb->data_len = pkt_size;
+	skb->truesize += pkt_size;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
 	if (likely(!vlanf)) {
-		lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size,
-				pkt_size, NULL, 0);
+		napi_gro_frags(&adapter->napi);
 	} else {
 		vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
 		vid = be16_to_cpu(vid);
@@ -821,9 +871,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
 		if (!adapter->vlan_grp || adapter->num_vlans == 0)
 			return;
 
-		lro_vlan_hwaccel_receive_frags(&adapter->rx_obj.lro_mgr,
-			rx_frags, pkt_size, pkt_size, adapter->vlan_grp,
-			vid, NULL, 0);
+		vlan_gro_frags(&adapter->napi, adapter->vlan_grp, vid);
 	}
 
 	be_rx_stats_update(adapter, pkt_size, num_rcvd);
@@ -839,12 +887,19 @@ static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter)
 
 	be_dws_le_to_cpu(rxcp, sizeof(*rxcp));
 
-	rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0;
-
 	queue_tail_inc(&adapter->rx_obj.cq);
 	return rxcp;
 }
 
+/* To reset the valid bit, we need to reset the whole word as
+ * when walking the queue the valid entries are little-endian
+ * and invalid entries are host endian
+ */
+static inline void be_rx_compl_reset(struct be_eth_rx_compl *rxcp)
+{
+	rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0;
+}
+
 static inline struct page *be_alloc_pages(u32 size)
 {
 	gfp_t alloc_flags = GFP_ATOMIC;
@@ -907,7 +962,7 @@ static void be_post_rx_frags(struct be_adapter *adapter)
 
 	if (posted) {
 		atomic_add(posted, &rxq->used);
-		be_rxq_notify(&adapter->ctrl, rxq->id, posted);
+		be_rxq_notify(adapter, rxq->id, posted);
 	} else if (atomic_read(&rxq->used) == 0) {
 		/* Let be_worker replenish when memory is available */
 		adapter->rx_post_starved = true;
@@ -916,10 +971,8 @@ static void be_post_rx_frags(struct be_adapter *adapter)
 	return;
 }
 
-static struct be_eth_tx_compl *
-be_tx_compl_get(struct be_adapter *adapter)
+static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)
 {
-	struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
 	struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq);
 
 	if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0)
@@ -965,6 +1018,34 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
 	kfree_skb(sent_skb);
 }
 
+static inline struct be_eq_entry *event_get(struct be_eq_obj *eq_obj)
+{
+	struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
+
+	if (!eqe->evt)
+		return NULL;
+
+	eqe->evt = le32_to_cpu(eqe->evt);
+	queue_tail_inc(&eq_obj->q);
+	eqe->evt = 0;
+	return eqe;
+}
+
+/* Just read and notify events without processing them.
+ * Used at the time of destroying event queues */
+static void be_eq_clean(struct be_adapter *adapter,
+			struct be_eq_obj *eq_obj)
+{
+	struct be_eq_entry *eqe;
+	u16 num = 0;
+
+	while ((eqe = event_get(eq_obj)) != NULL)
+		num++;
+
+	if (num)
+		be_eq_notify(adapter, eq_obj->q.id, false, true, num);
+}
+
 static void be_rx_q_clean(struct be_adapter *adapter)
 {
 	struct be_rx_page_info *page_info;
@@ -976,12 +1057,13 @@ static void be_rx_q_clean(struct be_adapter *adapter)
 	/* First cleanup pending rx completions */
 	while ((rxcp = be_rx_compl_get(adapter)) != NULL) {
 		be_rx_compl_discard(adapter, rxcp);
-		be_cq_notify(&adapter->ctrl, rx_cq->id, true, 1);
+		be_rx_compl_reset(rxcp);
+		be_cq_notify(adapter, rx_cq->id, true, 1);
 	}
 
 	/* Then free posted rx buffer that were not used */
 	tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len;
-	for (; tail != rxq->head; index_inc(&tail, rxq->len)) {
+	for (; atomic_read(&rxq->used) > 0; index_inc(&tail, rxq->len)) {
 		page_info = get_rx_page_info(adapter, tail);
 		put_page(page_info->page);
 		memset(page_info, 0, sizeof(*page_info));
@@ -989,36 +1071,49 @@ static void be_rx_q_clean(struct be_adapter *adapter)
 	BUG_ON(atomic_read(&rxq->used));
 }
 
-static void be_tx_q_clean(struct be_adapter *adapter)
+static void be_tx_compl_clean(struct be_adapter *adapter)
 {
-	struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
-	struct sk_buff *sent_skb;
+	struct be_queue_info *tx_cq = &adapter->tx_obj.cq;
 	struct be_queue_info *txq = &adapter->tx_obj.q;
-	u16 last_index;
-	bool dummy_wrb;
-
-	while (atomic_read(&txq->used)) {
-		sent_skb = sent_skbs[txq->tail];
-		last_index = txq->tail;
-		index_adv(&last_index,
-			wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len);
-		be_tx_compl_process(adapter, last_index);
-	}
+	struct be_eth_tx_compl *txcp;
+	u16 end_idx, cmpl = 0, timeo = 0;
+
+	/* Wait for a max of 200ms for all the tx-completions to arrive. */
+	do {
+		while ((txcp = be_tx_compl_get(tx_cq))) {
+			end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
+					wrb_index, txcp);
+			be_tx_compl_process(adapter, end_idx);
+			cmpl++;
+		}
+		if (cmpl) {
+			be_cq_notify(adapter, tx_cq->id, false, cmpl);
+			cmpl = 0;
+		}
+
+		if (atomic_read(&txq->used) == 0 || ++timeo > 200)
+			break;
+
+		mdelay(1);
+	} while (true);
+
+	if (atomic_read(&txq->used))
+		dev_err(&adapter->pdev->dev, "%d pending tx-completions\n",
+			atomic_read(&txq->used));
 }
 
 static void be_mcc_queues_destroy(struct be_adapter *adapter)
 {
 	struct be_queue_info *q;
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 
-	q = &ctrl->mcc_obj.q;
+	q = &adapter->mcc_obj.q;
 	if (q->created)
-		be_cmd_q_destroy(ctrl, q, QTYPE_MCCQ);
+		be_cmd_q_destroy(adapter, q, QTYPE_MCCQ);
 	be_queue_free(adapter, q);
 
-	q = &ctrl->mcc_obj.cq;
+	q = &adapter->mcc_obj.cq;
 	if (q->created)
-		be_cmd_q_destroy(ctrl, q, QTYPE_CQ);
+		be_cmd_q_destroy(adapter, q, QTYPE_CQ);
 	be_queue_free(adapter, q);
 }
 
@@ -1026,25 +1121,24 @@ static void be_mcc_queues_destroy(struct be_adapter *adapter)
 static int be_mcc_queues_create(struct be_adapter *adapter)
 {
 	struct be_queue_info *q, *cq;
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 
 	/* Alloc MCC compl queue */
-	cq = &ctrl->mcc_obj.cq;
+	cq = &adapter->mcc_obj.cq;
 	if (be_queue_alloc(adapter, cq, MCC_CQ_LEN,
 			sizeof(struct be_mcc_compl)))
 		goto err;
 
 	/* Ask BE to create MCC compl queue; share TX's eq */
-	if (be_cmd_cq_create(ctrl, cq, &adapter->be_eq.q, false, true, 0))
+	if (be_cmd_cq_create(adapter, cq, &adapter->be_eq.q, false, true, 0))
 		goto mcc_cq_free;
 
 	/* Alloc MCC queue */
-	q = &ctrl->mcc_obj.q;
+	q = &adapter->mcc_obj.q;
 	if (be_queue_alloc(adapter, q, MCC_Q_LEN, sizeof(struct be_mcc_wrb)))
 		goto mcc_cq_destroy;
 
 	/* Ask BE to create MCC queue */
-	if (be_cmd_mccq_create(ctrl, q, cq))
+	if (be_cmd_mccq_create(adapter, q, cq))
 		goto mcc_q_free;
 
 	return 0;
@@ -1052,7 +1146,7 @@ static int be_mcc_queues_create(struct be_adapter *adapter)
 mcc_q_free:
 	be_queue_free(adapter, q);
 mcc_cq_destroy:
-	be_cmd_q_destroy(ctrl, cq, QTYPE_CQ);
+	be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
 mcc_cq_free:
 	be_queue_free(adapter, cq);
 err:
@@ -1065,17 +1159,14 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
 
 	q = &adapter->tx_obj.q;
 	if (q->created)
-		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_TXQ);
+		be_cmd_q_destroy(adapter, q, QTYPE_TXQ);
 	be_queue_free(adapter, q);
 
 	q = &adapter->tx_obj.cq;
 	if (q->created)
-		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ);
+		be_cmd_q_destroy(adapter, q, QTYPE_CQ);
 	be_queue_free(adapter, q);
 
-	/* No more tx completions can be rcvd now; clean up if there are
-	 * any pending completions or pending tx requests */
-	be_tx_q_clean(adapter);
 }
 
 static int be_tx_queues_create(struct be_adapter *adapter)
@@ -1091,7 +1182,7 @@ static int be_tx_queues_create(struct be_adapter *adapter)
 		goto queue_alloc_failed;
 
 	/* Ask BE to create Tx eth compl queue */
-	if (be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3))
+	if (be_cmd_cq_create(adapter, cq, eq, false, false, 3))
 		goto tx_cq_free;
 
 	/* Alloc TX eth queue */
@@ -1100,14 +1191,14 @@ static int be_tx_queues_create(struct be_adapter *adapter)
 		goto tx_cq_destroy;
 
 	/* Ask BE to create Tx eth queue */
-	if (be_cmd_txq_create(&adapter->ctrl, q, cq))
+	if (be_cmd_txq_create(adapter, q, cq))
 		goto tx_q_free;
 	return 0;
 
 tx_q_free:
 	be_queue_free(adapter, q);
 tx_cq_destroy:
-	be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ);
+	be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
 tx_cq_free:
 	be_queue_free(adapter, cq);
 queue_alloc_failed:
@@ -1120,19 +1211,22 @@ static void be_rx_queues_destroy(struct be_adapter *adapter)
 
 	q = &adapter->rx_obj.q;
 	if (q->created) {
-		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_RXQ);
+		be_cmd_q_destroy(adapter, q, QTYPE_RXQ);
 		be_rx_q_clean(adapter);
 	}
 	be_queue_free(adapter, q);
 
 	q = &adapter->rx_obj.cq;
 	if (q->created)
-		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ);
+		be_cmd_q_destroy(adapter, q, QTYPE_CQ);
 	be_queue_free(adapter, q);
 
+	/* Clear any residual events */
+	be_eq_clean(adapter, &adapter->be_eq);
+
 	q = &adapter->be_eq.q;
 	if (q->created)
-		be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ);
+		be_cmd_q_destroy(adapter, q, QTYPE_EQ);
 	be_queue_free(adapter, q);
 }
 
@@ -1141,7 +1235,6 @@ static int be_rx_queues_create(struct be_adapter *adapter)
 	struct be_queue_info *eq, *q, *cq;
 	int rc;
 
-	adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME;
 	adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
 	adapter->be_eq.max_eqd = BE_MAX_EQD;
 	adapter->be_eq.min_eqd = 0;
@@ -1156,7 +1249,7 @@ static int be_rx_queues_create(struct be_adapter *adapter)
 		return rc;
 
 	/* Ask BE to create Rx Event queue */
-	rc = be_cmd_eq_create(&adapter->ctrl, eq, adapter->be_eq.cur_eqd);
+	rc = be_cmd_eq_create(adapter, eq, adapter->be_eq.cur_eqd);
 	if (rc)
 		goto be_eq_free;
 
@@ -1168,7 +1261,7 @@ static int be_rx_queues_create(struct be_adapter *adapter)
 		goto be_eq_destroy;
 
 	/* Ask BE to create Rx eth compl queue */
-	rc = be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3);
+	rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
 	if (rc)
 		goto rx_cq_free;
 
@@ -1179,7 +1272,7 @@ static int be_rx_queues_create(struct be_adapter *adapter)
 		goto rx_cq_destroy;
 
 	/* Ask BE to create Rx eth queue */
-	rc = be_cmd_rxq_create(&adapter->ctrl, q, cq->id, rx_frag_size,
+	rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size,
 		BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false);
 	if (rc)
 		goto rx_q_free;
@@ -1188,45 +1281,38 @@ static int be_rx_queues_create(struct be_adapter *adapter)
 rx_q_free:
 	be_queue_free(adapter, q);
 rx_cq_destroy:
-	be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ);
+	be_cmd_q_destroy(adapter, cq, QTYPE_CQ);
 rx_cq_free:
 	be_queue_free(adapter, cq);
 be_eq_destroy:
-	be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ);
+	be_cmd_q_destroy(adapter, eq, QTYPE_EQ);
 be_eq_free:
 	be_queue_free(adapter, eq);
 	return rc;
 }
-static bool event_get(struct be_eq_obj *eq_obj, u16 *rid)
-{
-	struct be_eq_entry *entry = queue_tail_node(&eq_obj->q);
-	u32 evt = entry->evt;
 
-	if (!evt)
-		return false;
-
-	evt = le32_to_cpu(evt);
-	*rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK;
-	entry->evt = 0;
-	queue_tail_inc(&eq_obj->q);
-	return true;
+/* There are 8 evt ids per func. Retruns the evt id's bit number */
+static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id)
+{
+	return eq_id - 8 * be_pci_func(adapter);
 }
 
 static irqreturn_t be_intx(int irq, void *dev)
 {
 	struct be_adapter *adapter = dev;
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	int isr;
 
-	isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
-				PCI_FUNC(adapter->pdev->devfn) * CEV_ISR_SIZE);
-	if (unlikely(!isr))
+	isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
+			be_pci_func(adapter) * CEV_ISR_SIZE);
+	if (!isr)
 		return IRQ_NONE;
 
-	compat_napi_schedule(&adapter->napi);
+	napi_schedule(&adapter->napi);
+
 	return IRQ_HANDLED;
 }
 
+
 static irqreturn_t be_msix(int irq, void *dev)
 {
 	struct be_adapter *adapter = dev;
@@ -1234,15 +1320,17 @@ static irqreturn_t be_msix(int irq, void *dev)
 	struct be_eq_entry *entry = queue_tail_node(&eq_obj->q);
 
 	/* Clear the interrupt */
-	be_eq_notify(&adapter->ctrl, eq_obj->q.id, false, true, 0);
+	be_eq_notify(adapter, eq_obj->q.id, false, true, 0);
 
 	if (entry->evt)
-		compat_napi_schedule(&adapter->napi);
+		napi_schedule(&adapter->napi);
+	else
+		be_eq_notify(adapter, eq_obj->q.id, true, true, 0);
 
 	return IRQ_HANDLED;
 }
 
-static inline bool do_lro(struct be_adapter *adapter,
+static inline bool do_gro(struct be_adapter *adapter,
 			struct be_eth_rx_compl *rxcp)
 {
 	int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
@@ -1251,8 +1339,7 @@ static inline bool do_lro(struct be_adapter *adapter,
 	if (err)
 		drvr_stats(adapter)->be_rxcp_err++;
 
-	return (!tcp_frame || err || (adapter->max_rx_coal <= 1) || !lro) ?
-		false : true;
+	return (tcp_frame && !err) ? true : false;
 }
 
 int be_poll_rx(struct be_adapter *adapter, int budget)
@@ -1261,31 +1348,34 @@ int be_poll_rx(struct be_adapter *adapter, int budget)
 	struct be_eth_rx_compl *rxcp;
 	u32 work;
 
+	adapter->stats.drvr_stats.be_rx_polls++;
+
 	for (work = 0; work < budget; work++) {
 		rxcp = be_rx_compl_get(adapter);
 		if (!rxcp)
 			break;
 
-		if (do_lro(adapter, rxcp))
-			be_rx_compl_process_lro(adapter, rxcp);
+		if (do_gro(adapter, rxcp))
+			be_rx_compl_process_gro(adapter, rxcp);
 		else
 			be_rx_compl_process(adapter, rxcp);
-	}
 
-	if (lro)
-		lro_flush_all(&adapter->rx_obj.lro_mgr);
+		be_rx_compl_reset(rxcp);
+	}
 
 	/* Refill the queue */
 	if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM)
 		be_post_rx_frags(adapter);
 
 	if (work)
-		be_cq_notify(&adapter->ctrl, rx_cq->id, true, work);
+		be_cq_notify(adapter, rx_cq->id, true, work);
 
 	return work;
 }
 
-/* For TX we don't honour budget; consume everything */
+/* As TX and MCC share the same EQ check for both TX and MCC completions.
+ * For TX/MCC we don't honour budget; consume everything
+ */
 int be_poll_tx(struct be_adapter *adapter, int budget)
 {
 	struct be_tx_obj *tx_obj = &adapter->tx_obj;
@@ -1295,7 +1385,7 @@ int be_poll_tx(struct be_adapter *adapter, int budget)
 	u32 num_cmpl = 0;
 	u16 end_idx;
 
-	while ((txcp = be_tx_compl_get(adapter))) {
+	while ((txcp = be_tx_compl_get(tx_cq))) {
 		end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl,
 					wrb_index, txcp);
 		be_tx_compl_process(adapter, end_idx);
@@ -1310,11 +1400,10 @@ int be_poll_tx(struct be_adapter *adapter, int budget)
 		netif_wake_queue(adapter->netdev);
 	}
 
-	drvr_stats(adapter)->be_tx_events++;
 	drvr_stats(adapter)->be_tx_compl += num_cmpl;
 
 	if (num_cmpl)
-		be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl);
+		be_cq_notify(adapter, tx_cq->id, true, num_cmpl);
 
 	return num_cmpl;
 }
@@ -1323,26 +1412,26 @@ int be_poll(struct napi_struct *napi, int budget)
 {
 	struct be_adapter *adapter =
 				container_of(napi, struct be_adapter, napi);
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	struct be_eq_obj *eq_obj = &adapter->be_eq;
-	u16 rid = 0, num = 0;
+	u16 num = 0;
 	u32 tx_work, rx_work;
 
-	while (event_get(eq_obj, &rid))
+	while (event_get(eq_obj))
 		num++;
 
 	tx_work = be_poll_tx(adapter, budget);
 	rx_work = be_poll_rx(adapter, budget);
-	be_process_mcc(&adapter->ctrl);
+	be_process_mcc(adapter);
+
+	drvr_stats(adapter)->be_num_events += num;
 
 	/* All consumed */
 	if (rx_work < budget) {
-		compat_napi_complete(napi);
-		be_eq_notify(ctrl, eq_obj->q.id, true, false, num);
+		napi_complete(napi);
+		be_eq_notify(adapter, eq_obj->q.id, true, false, num);
 	} else
-		be_eq_notify(ctrl, eq_obj->q.id, false, false, num);
+		be_eq_notify(adapter, eq_obj->q.id, false, false, num);
 
-	drvr_stats(adapter)->be_num_events += num;
 	return rx_work;
 }
 
@@ -1353,7 +1442,7 @@ static void be_worker(struct work_struct *work)
 	int status;
 
 	/* Get Stats */
-	status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd);
+	status = be_cmd_get_stats(adapter, &adapter->stats.cmd);
 	if (!status)
 		netdev_stats_update(adapter);
 
@@ -1371,6 +1460,14 @@ static void be_worker(struct work_struct *work)
 	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
 }
 
+static void be_msix_disable(struct be_adapter *adapter)
+{
+	if (adapter->msix_enabled) {
+		pci_disable_msix(adapter->pdev);
+		adapter->msix_enabled = false;
+	}
+}
+
 static void be_msix_enable(struct be_adapter *adapter)
 {
 	int i, status;
@@ -1387,27 +1484,42 @@ static void be_msix_enable(struct be_adapter *adapter)
 
 static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id)
 {
-	return adapter->msix_entries[eq_id -
-			8 * adapter->ctrl.pci_func].vector;
+	return adapter->msix_entries[
+			be_evt_bit_get(adapter, eq_id)].vector;
 }
 
-static int be_msix_register(struct be_adapter *adapter)
+static int be_request_irq(struct be_adapter *adapter,
+		struct be_eq_obj *eq_obj,
+		void *handler)
 {
 	struct net_device *netdev = adapter->netdev;
-	struct be_eq_obj *be_eq = &adapter->be_eq;
-	int status, vec;
+	int vec;
+
+	sprintf(eq_obj->desc, "%s", netdev->name);
+	vec = be_msix_vec_get(adapter, eq_obj->q.id);
+	return request_irq(vec, handler, 0, eq_obj->desc, adapter);
+}
 
-	sprintf(be_eq->desc, "%s", netdev->name);
-	vec = be_msix_vec_get(adapter, be_eq->q.id);
-	status = request_irq(vec, be_msix, 0, be_eq->desc, adapter);
+static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj)
+{
+	int vec = be_msix_vec_get(adapter, eq_obj->q.id);
+	free_irq(vec, adapter);
+}
+
+static int be_msix_register(struct be_adapter *adapter)
+{
+	int status;
+
+	status = be_request_irq(adapter, &adapter->be_eq, be_msix);
 	if (status)
 		goto err;
+
 	return 0;
+
 err:
 	dev_warn(&adapter->pdev->dev,
 		"MSIX Request IRQ failed - err %d\n", status);
-	pci_disable_msix(adapter->pdev);
-	adapter->msix_enabled = false;
+	be_msix_disable(adapter);
 	return status;
 }
 
@@ -1439,7 +1551,6 @@ done:
 static void be_irq_unregister(struct be_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	int vec;
 
 	if (!adapter->isr_registered)
 		return;
@@ -1451,8 +1562,7 @@ static void be_irq_unregister(struct be_adapter *adapter)
 	}
 
 	/* MSIx */
-	vec = be_msix_vec_get(adapter, adapter->be_eq.q.id);
-	free_irq(vec, adapter);
+	be_free_irq(adapter, &adapter->be_eq);
 done:
 	adapter->isr_registered = false;
 	return;
@@ -1461,91 +1571,140 @@ done:
 static int be_open(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	struct be_eq_obj *be_eq = &adapter->be_eq;
 	bool link_up;
 	int status;
+	u8 mac_speed;
+	u16 link_speed;
 
 	/* First time posting */
 	be_post_rx_frags(adapter);
 
-	compat_napi_enable(&adapter->napi);
+	napi_enable(&adapter->napi);
 
 	be_irq_register(adapter);
 
-	be_intr_set(ctrl, true);
+	be_intr_set(adapter, true);
+
+	/* The evt queues are created in unarmed state; arm them */
+	be_eq_notify(adapter, be_eq->q.id, true, false, 0);
 
-	/* The evt queues are created in the unarmed state; arm them */
-	be_eq_notify(ctrl, be_eq->q.id, true, false, 0);
+	/* Rx compl queue may be in unarmed state; rearm it */
+	be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0);
 
-	/* The compl queues are created in the unarmed state; arm them */
-	be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0);
-	be_cq_notify(ctrl, adapter->tx_obj.cq.id, true, 0);
+	/* Now that interrupts are on we can process async mcc */
+	be_async_mcc_enable(adapter);
 
-	status = be_cmd_link_status_query(ctrl, &link_up);
+	status = be_cmd_link_status_query(adapter, &link_up, &mac_speed,
+			&link_speed);
 	if (status)
-		return status;
+		goto ret_sts;
 	be_link_status_update(adapter, link_up);
 
+	status = be_vid_config(adapter);
+	if (status)
+		goto ret_sts;
+
+	status = be_cmd_set_flow_control(adapter,
+					adapter->tx_fc, adapter->rx_fc);
+	if (status)
+		goto ret_sts;
+
 	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
-	return 0;
+ret_sts:
+	return status;
+}
+
+static int be_setup_wol(struct be_adapter *adapter, bool enable)
+{
+	struct be_dma_mem cmd;
+	int status = 0;
+	u8 mac[ETH_ALEN];
+
+	memset(mac, 0, ETH_ALEN);
+
+	cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
+	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
+	if (cmd.va == NULL)
+		return -1;
+	memset(cmd.va, 0, cmd.size);
+
+	if (enable) {
+		status = pci_write_config_dword(adapter->pdev,
+			PCICFG_PM_CONTROL_OFFSET, PCICFG_PM_CONTROL_MASK);
+		if (status) {
+			dev_err(&adapter->pdev->dev,
+				"Could not enable Wake-on-lan \n");
+			pci_free_consistent(adapter->pdev, cmd.size, cmd.va,
+					cmd.dma);
+			return status;
+		}
+		status = be_cmd_enable_magic_wol(adapter,
+				adapter->netdev->dev_addr, &cmd);
+		pci_enable_wake(adapter->pdev, PCI_D3hot, 1);
+		pci_enable_wake(adapter->pdev, PCI_D3cold, 1);
+	} else {
+		status = be_cmd_enable_magic_wol(adapter, mac, &cmd);
+		pci_enable_wake(adapter->pdev, PCI_D3hot, 0);
+		pci_enable_wake(adapter->pdev, PCI_D3cold, 0);
+	}
+
+	pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
+	return status;
 }
 
 static int be_setup(struct be_adapter *adapter)
 {
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	struct net_device *netdev = adapter->netdev;
-	u32 if_flags;
+	u32 cap_flags, en_flags;
 	int status;
 
-	if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS |
-		BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED |
-		BE_IF_FLAGS_PASS_L3L4_ERRORS;
-	status = be_cmd_if_create(ctrl, if_flags, netdev->dev_addr,
-			false/* pmac_invalid */, &adapter->if_handle,
-			&adapter->pmac_id);
-	if (status != 0)
-		goto do_none;
-
-	be_vid_config(netdev);
+	cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+			BE_IF_FLAGS_MCAST_PROMISCUOUS |
+			BE_IF_FLAGS_PROMISCUOUS |
+			BE_IF_FLAGS_PASS_L3L4_ERRORS;
+	en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+			BE_IF_FLAGS_PASS_L3L4_ERRORS;
 
-	status = be_cmd_set_flow_control(ctrl, true, true);
+	status = be_cmd_if_create(adapter, cap_flags, en_flags,
+			netdev->dev_addr, false/* pmac_invalid */,
+			&adapter->if_handle, &adapter->pmac_id);
 	if (status != 0)
-		goto if_destroy;
+		goto do_none;
 
 	status = be_rx_queues_create(adapter);
 	if (status != 0)
-		goto if_destroy;
+		goto tx_qs_destroy;
 
 	status = be_tx_queues_create(adapter);
 	if (status != 0)
-		goto rx_qs_destroy;
+		goto if_destroy;
 
 	status = be_mcc_queues_create(adapter);
 	if (status != 0)
-		goto tx_qs_destroy;
+		goto rx_qs_destroy;
+
+	adapter->link_speed = -1;
 
 	return 0;
 
-tx_qs_destroy:
-	be_tx_queues_destroy(adapter);
 rx_qs_destroy:
 	be_rx_queues_destroy(adapter);
+tx_qs_destroy:
+	be_tx_queues_destroy(adapter);
 if_destroy:
-	be_cmd_if_destroy(ctrl, adapter->if_handle);
+	be_cmd_if_destroy(adapter, adapter->if_handle);
 do_none:
 	return status;
 }
 
 static int be_clear(struct be_adapter *adapter)
 {
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
-
 	be_mcc_queues_destroy(adapter);
-	be_tx_queues_destroy(adapter);
 	be_rx_queues_destroy(adapter);
+	be_tx_queues_destroy(adapter);
 
-	be_cmd_if_destroy(ctrl, adapter->if_handle);
+	be_cmd_if_destroy(adapter, adapter->if_handle);
 
 	return 0;
 }
@@ -1553,17 +1712,18 @@ static int be_clear(struct be_adapter *adapter)
 static int be_close(struct net_device *netdev)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	struct be_eq_obj *be_eq = &adapter->be_eq;
 	int vec;
 
 	cancel_delayed_work_sync(&adapter->work);
 
+	be_async_mcc_disable(adapter);
+
 	netif_stop_queue(netdev);
 	netif_carrier_off(netdev);
 	adapter->link_up = false;
 
-	be_intr_set(ctrl, false);
+	be_intr_set(adapter, false);
 
 	if (adapter->msix_enabled) {
 		vec = be_msix_vec_get(adapter, be_eq->q.id);
@@ -1573,60 +1733,232 @@ static int be_close(struct net_device *netdev)
 	}
 	be_irq_unregister(adapter);
 
-	compat_napi_disable(&adapter->napi);
+	napi_disable(&adapter->napi);
+
+	/* Wait for all pending tx completions to arrive so that
+	 * all tx skbs are freed.
+	 */
+	be_tx_compl_clean(adapter);
 
 	return 0;
 }
 
-static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
-				void **ip_hdr, void **tcpudp_hdr,
-				u64 *hdr_flags, void *priv)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void be_netpoll(struct net_device *netdev)
 {
-	struct ethhdr *eh;
-	struct vlan_ethhdr *veh;
-	struct iphdr *iph;
-	u8 *va = page_address(frag->page) + frag->page_offset;
-	unsigned long ll_hlen;
+	struct be_adapter *adapter = netdev_priv(netdev);
+	struct be_eq_obj *eq_obj = &adapter->be_eq;
+	struct be_eq_entry *entry = queue_tail_node(&eq_obj->q);
 
-	prefetch(va);
-	eh = (struct ethhdr *)va;
-	*mac_hdr = eh;
-	ll_hlen = ETH_HLEN;
-	if (eh->h_proto != htons(ETH_P_IP)) {
-		if (eh->h_proto == htons(ETH_P_8021Q)) {
-			veh = (struct vlan_ethhdr *)va;
-			if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
-				return -1;
+	/* Clear the interrupt */
+	be_eq_notify(adapter, eq_obj->q.id, false, true, 0);
 
-			ll_hlen += VLAN_HLEN;
-		} else {
+	if (entry->evt)
+		napi_schedule(&adapter->napi);
+	else
+		be_eq_notify(adapter, eq_obj->q.id, true, true, 0);
+
+	return;
+}
+#endif
+
+#define FW_FILE_HDR_SIGN 	"ServerEngines Corp. "
+char flash_cookie[2][16] =	{"*** SE FLAS",
+				"H DIRECTORY *** "};
+
+static bool be_flash_redboot(struct be_adapter *adapter,
+			const u8 *p)
+{
+	u32 crc_offset;
+	u8 flashed_crc[4];
+	int status;
+	crc_offset = FLASH_REDBOOT_START + FLASH_REDBOOT_IMAGE_MAX_SIZE - 4
+			+ sizeof(struct flash_file_hdr) - 32*1024;
+	p += crc_offset;
+	status = be_cmd_get_flash_crc(adapter, flashed_crc);
+	if (status) {
+		dev_err(&adapter->pdev->dev,
+		"could not get crc from flash, not flashing redboot\n");
+		return false;
+	}
+
+	/*update redboot only if crc does not match*/
+	if (!memcmp(flashed_crc, p, 4))
+		return false;
+	else
+		return true;
+}
+
+static int be_flash_image(struct be_adapter *adapter,
+			const struct firmware *fw,
+			struct be_dma_mem *flash_cmd, u32 flash_type)
+{
+	int status;
+	u32 flash_op, image_offset = 0, total_bytes, image_size = 0;
+	int num_bytes;
+	const u8 *p = fw->data;
+	struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+	switch (flash_type) {
+	case FLASHROM_TYPE_ISCSI_ACTIVE:
+		image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START;
+		image_size = FLASH_IMAGE_MAX_SIZE;
+		break;
+	case FLASHROM_TYPE_ISCSI_BACKUP:
+		image_offset = FLASH_iSCSI_BACKUP_IMAGE_START;
+		image_size = FLASH_IMAGE_MAX_SIZE;
+		break;
+	case FLASHROM_TYPE_FCOE_FW_ACTIVE:
+		image_offset = FLASH_FCoE_PRIMARY_IMAGE_START;
+		image_size = FLASH_IMAGE_MAX_SIZE;
+		break;
+	case FLASHROM_TYPE_FCOE_FW_BACKUP:
+		image_offset = FLASH_FCoE_BACKUP_IMAGE_START;
+		image_size = FLASH_IMAGE_MAX_SIZE;
+		break;
+	case FLASHROM_TYPE_BIOS:
+		image_offset = FLASH_iSCSI_BIOS_START;
+		image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+		break;
+	case FLASHROM_TYPE_FCOE_BIOS:
+		image_offset = FLASH_FCoE_BIOS_START;
+		image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+		break;
+	case FLASHROM_TYPE_PXE_BIOS:
+		image_offset = FLASH_PXE_BIOS_START;
+		image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+		break;
+	case FLASHROM_TYPE_REDBOOT:
+		if (!be_flash_redboot(adapter, fw->data))
+			return 0;
+		image_offset = FLASH_REDBOOT_ISM_START;
+		image_size = FLASH_REDBOOT_IMAGE_MAX_SIZE;
+		break;
+	default:
+		return 0;
+	}
+
+	p += sizeof(struct flash_file_hdr) + image_offset;
+	if (p + image_size > fw->data + fw->size)
+		return -1;
+
+	total_bytes = image_size;
+
+	while (total_bytes) {
+		if (total_bytes > 32*1024)
+			num_bytes = 32*1024;
+		else
+			num_bytes = total_bytes;
+		total_bytes -= num_bytes;
+
+		if (!total_bytes)
+			flash_op = FLASHROM_OPER_FLASH;
+		else
+			flash_op = FLASHROM_OPER_SAVE;
+		memcpy(req->params.data_buf, p, num_bytes);
+		p += num_bytes;
+		status = be_cmd_write_flashrom(adapter, flash_cmd,
+				flash_type, flash_op, num_bytes);
+		if (status) {
+			dev_err(&adapter->pdev->dev,
+			"cmd to write to flash rom failed. type/op %d/%d\n",
+			flash_type, flash_op);
 			return -1;
 		}
+		yield();
 	}
-	*hdr_flags = LRO_IPV4;
-	iph = (struct iphdr *)(va + ll_hlen);
-	*ip_hdr = iph;
-	if (iph->protocol != IPPROTO_TCP)
-		return -1;
-	*hdr_flags |= LRO_TCP;
-	*tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
 
 	return 0;
 }
 
-static void be_lro_init(struct be_adapter *adapter, struct net_device *netdev)
+#define ETHTOOL_FLASH_MAX_FILENAME 128
+
+int be_load_fw(struct be_adapter *adapter, u8 *func)
 {
-	struct net_lro_mgr *lro_mgr;
+	char fw_file[ETHTOOL_FLASH_MAX_FILENAME];
+	const struct firmware *fw;
+	struct flash_file_hdr *fhdr;
+	struct flash_section_info *fsec = NULL;
+	struct be_dma_mem flash_cmd;
+	int status;
+	const u8 *p;
+	bool entry_found = false;
+	int flash_type;
+	char fw_ver[FW_VER_LEN];
+	char fw_cfg;
+
+	status = be_cmd_get_fw_ver(adapter, fw_ver);
+	if (status)
+		return status;
+
+	fw_cfg = *(fw_ver + 2);
+	if (fw_cfg == '0')
+		fw_cfg = '1';
+	strcpy(fw_file, func);
+
+	status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
+	if (status)
+		goto fw_exit;
+
+	p = fw->data;
+	fhdr = (struct flash_file_hdr *) p;
+	if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) {
+		dev_err(&adapter->pdev->dev,
+			"Firmware(%s) load error (signature did not match)\n",
+				fw_file);
+		status = -1;
+		goto fw_exit;
+	}
+
+	dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
+
+	p += sizeof(struct flash_file_hdr);
+	while (p < (fw->data + fw->size)) {
+		fsec = (struct flash_section_info *)p;
+		if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) {
+			entry_found = true;
+			break;
+		}
+		p += 32;
+	}
+
+	if (!entry_found) {
+		status = -1;
+		dev_err(&adapter->pdev->dev,
+			"Flash cookie not found in firmware image\n");
+		goto fw_exit;
+	}
+
+	flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+	flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size,
+					&flash_cmd.dma);
+	if (!flash_cmd.va) {
+		status = -ENOMEM;
+		dev_err(&adapter->pdev->dev,
+			"Memory allocation failure while flashing\n");
+		goto fw_exit;
+	}
+
+	for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE;
+		flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) {
+		status = be_flash_image(adapter, fw, &flash_cmd,
+				flash_type);
+		if (status)
+			break;
+	}
+
+	pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va,
+				flash_cmd.dma);
+	if (status) {
+		dev_err(&adapter->pdev->dev, "Firmware load error\n");
+		goto fw_exit;
+	}
 
-	lro_mgr = &adapter->rx_obj.lro_mgr;
-	lro_mgr->dev = netdev;
-	lro_mgr->features = LRO_F_NAPI;
-	lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
-	lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
-	lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS;
-	lro_mgr->lro_arr = adapter->rx_obj.lro_desc;
-	lro_mgr->get_frag_header = be_get_frag_header;
-	lro_mgr->max_aggr = BE_MAX_FRAGS_PER_FRAME;
+	dev_info(&adapter->pdev->dev, "Firmware flashed succesfully\n");
+
+fw_exit:
+	release_firmware(fw);
+	return status;
 }
 
 static struct net_device_ops be_netdev_ops = {
@@ -1641,6 +1973,9 @@ static struct net_device_ops be_netdev_ops = {
 	.ndo_vlan_rx_register	= be_vlan_register,
 	.ndo_vlan_rx_add_vid	= be_vlan_add_vid,
 	.ndo_vlan_rx_kill_vid	= be_vlan_rem_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= be_netpoll,
+#endif
 };
 
 static void be_netdev_init(struct net_device *netdev)
@@ -1648,21 +1983,22 @@ static void be_netdev_init(struct net_device *netdev)
 	struct be_adapter *adapter = netdev_priv(netdev);
 
 	netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
-		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM |
-		NETIF_F_IPV6_CSUM;
+		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
+		NETIF_F_GRO;
 
 	netdev->flags |= IFF_MULTICAST;
 
 	adapter->rx_csum = true;
 
+	/* Default settings for Rx and Tx flow control */
+	adapter->rx_fc = true;
+	adapter->tx_fc = true;
+
 	BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
 
 	SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
 
-	if (lro)
-		be_lro_init(adapter, netdev);
-
-	compat_netif_napi_add(netdev, &adapter->napi, be_poll,
+	netif_napi_add(netdev, &adapter->napi, be_poll,
 		BE_NAPI_WEIGHT);
 
 	netif_carrier_off(netdev);
@@ -1671,13 +2007,12 @@ static void be_netdev_init(struct net_device *netdev)
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
 {
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
-	if (ctrl->csr)
-		iounmap(ctrl->csr);
-	if (ctrl->db)
-		iounmap(ctrl->db);
-	if (ctrl->pcicfg)
-		iounmap(ctrl->pcicfg);
+	if (adapter->csr)
+		iounmap(adapter->csr);
+	if (adapter->db)
+		iounmap(adapter->db);
+	if (adapter->pcicfg)
+		iounmap(adapter->pcicfg);
 }
 
 static int be_map_pci_bars(struct be_adapter *adapter)
@@ -1688,19 +2023,19 @@ static int be_map_pci_bars(struct be_adapter *adapter)
 			pci_resource_len(adapter->pdev, 2));
 	if (addr == NULL)
 		return -ENOMEM;
-	adapter->ctrl.csr = addr;
+	adapter->csr = addr;
 
 	addr = ioremap_nocache(pci_resource_start(adapter->pdev, 4),
 			128 * 1024);
 	if (addr == NULL)
 		goto pci_map_err;
-	adapter->ctrl.db = addr;
+	adapter->db = addr;
 
 	addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1),
 			pci_resource_len(adapter->pdev, 1));
 	if (addr == NULL)
 		goto pci_map_err;
-	adapter->ctrl.pcicfg = addr;
+	adapter->pcicfg = addr;
 
 	return 0;
 pci_map_err:
@@ -1711,50 +2046,68 @@ pci_map_err:
 
 static void be_ctrl_cleanup(struct be_adapter *adapter)
 {
-	struct be_dma_mem *mem = &adapter->ctrl.mbox_mem_alloced;
+	struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
 
 	be_unmap_pci_bars(adapter);
 
 	if (mem->va)
 		pci_free_consistent(adapter->pdev, mem->size,
 			mem->va, mem->dma);
+
+	mem = &adapter->mc_cmd_mem;
+	if (mem->va)
+		pci_free_consistent(adapter->pdev, mem->size,
+			mem->va, mem->dma);
 }
 
-/* Initialize the mbox required to send cmds to BE */
 static int be_ctrl_init(struct be_adapter *adapter)
 {
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
-	struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced;
-	struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem;
+	struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
+	struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
+	struct be_dma_mem *mc_cmd_mem = &adapter->mc_cmd_mem;
 	int status;
-	u32 val;
 
 	status = be_map_pci_bars(adapter);
 	if (status)
-		return status;
+		goto done;
 
 	mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
 	mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev,
 				mbox_mem_alloc->size, &mbox_mem_alloc->dma);
 	if (!mbox_mem_alloc->va) {
-		be_unmap_pci_bars(adapter);
-		return -1;
+		status = -ENOMEM;
+		goto unmap_pci_bars;
 	}
+
 	mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
 	mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
 	mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
 	memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
-	spin_lock_init(&ctrl->mbox_lock);
-	spin_lock_init(&ctrl->mcc_lock);
-	spin_lock_init(&ctrl->mcc_cq_lock);
 
-	ctrl->async_cb = be_link_status_update;
-	ctrl->adapter_ctxt = adapter;
+	mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config);
+	mc_cmd_mem->va = pci_alloc_consistent(adapter->pdev, mc_cmd_mem->size,
+			&mc_cmd_mem->dma);
+	if (mc_cmd_mem->va == NULL) {
+		status = -ENOMEM;
+		goto free_mbox;
+	}
+	memset(mc_cmd_mem->va, 0, mc_cmd_mem->size);
+
+	spin_lock_init(&adapter->mbox_lock);
+	spin_lock_init(&adapter->mcc_lock);
+	spin_lock_init(&adapter->mcc_cq_lock);
 
-	val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);
-	ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) &
-					MEMBAR_CTRL_INT_CTRL_PFUNC_MASK;
 	return 0;
+
+free_mbox:
+	pci_free_consistent(adapter->pdev, mbox_mem_alloc->size,
+		mbox_mem_alloc->va, mbox_mem_alloc->dma);
+
+unmap_pci_bars:
+	be_unmap_pci_bars(adapter);
+
+done:
+	return status;
 }
 
 static void be_stats_cleanup(struct be_adapter *adapter)
@@ -1779,12 +2132,44 @@ static int be_stats_init(struct be_adapter *adapter)
 	return 0;
 }
 
+static ssize_t flash_fw_store(struct class_device *cdev, const char *buf,
+			      size_t len)
+{
+	struct be_adapter *adapter =
+		netdev_priv(container_of(cdev, struct net_device, class_dev));
+	char file_name[ETHTOOL_FLASH_MAX_FILENAME];
+	int status;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0;
+	strncpy(file_name, buf, (ETHTOOL_FLASH_MAX_FILENAME - 1));
+
+	status = be_load_fw(adapter, file_name);
+	if (!status)
+		return len;
+	else
+		return status;
+}
+
+static CLASS_DEVICE_ATTR(flash_fw, S_IWUSR, NULL, flash_fw_store);
+
+static struct attribute *benet_attrs[] = {
+	&class_device_attr_flash_fw.attr,
+	NULL,
+};
+
+static struct attribute_group benet_attr_group = {.attrs = benet_attrs };
+
 static void __devexit be_remove(struct pci_dev *pdev)
 {
 	struct be_adapter *adapter = pci_get_drvdata(pdev);
 	if (!adapter)
 		return;
 
+	sysfs_remove_group(&adapter->netdev->class_dev.kobj, &benet_attr_group);
+
 	unregister_netdev(adapter->netdev);
 
 	be_clear(adapter);
@@ -1793,10 +2178,7 @@ static void __devexit be_remove(struct pci_dev *pdev)
 
 	be_ctrl_cleanup(adapter);
 
-	if (adapter->msix_enabled) {
-		pci_disable_msix(adapter->pdev);
-		adapter->msix_enabled = false;
-	}
+	be_msix_disable(adapter);
 
 	pci_set_drvdata(pdev, NULL);
 	pci_release_regions(pdev);
@@ -1805,21 +2187,28 @@ static void __devexit be_remove(struct pci_dev *pdev)
 	free_netdev(adapter->netdev);
 }
 
-static int be_hw_up(struct be_adapter *adapter)
+static int be_get_config(struct be_adapter *adapter)
 {
-	struct be_ctrl_info *ctrl = &adapter->ctrl;
 	int status;
+	u8 mac[ETH_ALEN];
 
-	status = be_cmd_POST(ctrl);
+	status = be_cmd_get_fw_ver(adapter, adapter->fw_ver);
 	if (status)
 		return status;
 
-	status = be_cmd_get_fw_ver(ctrl, adapter->fw_ver);
+	memset(mac, 0, ETH_ALEN);
+	status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
+			&adapter->cap);
 	if (status)
 		return status;
 
-	status = be_cmd_query_fw_cfg(ctrl, &adapter->port_num);
-	return status;
+	status = be_cmd_mac_addr_query(adapter, mac,
+			MAC_ADDRESS_TYPE_NETWORK, true /*permanent */, 0);
+	if (status)
+		return status;
+	memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
+
+	return 0;
 }
 
 static int __devinit be_probe(struct pci_dev *pdev,
@@ -1828,8 +2217,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	int status = 0;
 	struct be_adapter *adapter;
 	struct net_device *netdev;
-	struct be_ctrl_info *ctrl;
-	u8 mac[ETH_ALEN];
 
 	status = pci_enable_device(pdev);
 	if (status)
@@ -1849,6 +2236,8 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	adapter->pdev = pdev;
 	pci_set_drvdata(pdev, adapter);
 	adapter->netdev = netdev;
+	be_netdev_init(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
 
 	be_msix_enable(adapter);
 
@@ -1863,28 +2252,33 @@ static int __devinit be_probe(struct pci_dev *pdev,
 		}
 	}
 
-	ctrl = &adapter->ctrl;
 	status = be_ctrl_init(adapter);
 	if (status)
 		goto free_netdev;
 
-	status = be_stats_init(adapter);
+	/* sync up with fw's ready state */
+	status = be_cmd_POST(adapter);
 	if (status)
 		goto ctrl_clean;
 
-	status = be_hw_up(adapter);
+	/* tell fw we're ready to fire cmds */
+	status = be_cmd_fw_init(adapter);
 	if (status)
-		goto stats_clean;
+		goto ctrl_clean;
 
-	status = be_cmd_mac_addr_query(ctrl, mac, MAC_ADDRESS_TYPE_NETWORK,
-			true /* permanent */, 0);
+	status = be_cmd_reset_function(adapter);
+	if (status)
+		goto ctrl_clean;
+
+	status = be_stats_init(adapter);
+	if (status)
+		goto ctrl_clean;
+
+	status = be_get_config(adapter);
 	if (status)
 		goto stats_clean;
-	memcpy(netdev->dev_addr, mac, ETH_ALEN);
 
 	INIT_DELAYED_WORK(&adapter->work, be_worker);
-	be_netdev_init(netdev);
-	SET_NETDEV_DEV(netdev, &adapter->pdev->dev);
 
 	status = be_setup(adapter);
 	if (status)
@@ -1894,7 +2288,11 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	if (status != 0)
 		goto unsetup;
 
-	dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
+	if (sysfs_create_group(&adapter->netdev->class_dev.kobj,
+			       &benet_attr_group))
+		dev_err(&pdev->dev, "Could not create sysfs group\n");
+
+	dev_info(&pdev->dev, "%s - %s\n", netdev->name, nic_name(pdev));
 	return 0;
 
 unsetup:
@@ -1904,7 +2302,9 @@ stats_clean:
 ctrl_clean:
 	be_ctrl_cleanup(adapter);
 free_netdev:
+	be_msix_disable(adapter);
 	free_netdev(adapter->netdev);
+	pci_set_drvdata(pdev, NULL);
 rel_reg:
 	pci_release_regions(pdev);
 disable_dev:
@@ -1919,13 +2319,17 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
 	struct be_adapter *adapter = pci_get_drvdata(pdev);
 	struct net_device *netdev =  adapter->netdev;
 
+	if (adapter->wol)
+		be_setup_wol(adapter, true);
+
 	netif_device_detach(netdev);
 	if (netif_running(netdev)) {
 		rtnl_lock();
 		be_close(netdev);
-		be_clear(adapter);
 		rtnl_unlock();
 	}
+	be_cmd_get_flow_control(adapter, &adapter->tx_fc, &adapter->rx_fc);
+	be_clear(adapter);
 
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
@@ -1948,13 +2352,22 @@ static int be_resume(struct pci_dev *pdev)
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
 
+	/* tell fw we're ready to fire cmds */
+	status = be_cmd_fw_init(adapter);
+	if (status)
+		return status;
+
+	be_setup(adapter);
+
 	if (netif_running(netdev)) {
 		rtnl_lock();
-		be_setup(adapter);
 		be_open(netdev);
 		rtnl_unlock();
 	}
 	netif_device_attach(netdev);
+
+	if (adapter->wol)
+		be_setup_wol(adapter, false);
 	return 0;
 }
 
@@ -1969,6 +2382,12 @@ static struct pci_driver be_driver = {
 
 static int __init be_init_module(void)
 {
+	if (lro != 1) {
+		printk(KERN_WARNING DRV_NAME
+		       "The driver doesn't support LRO anymore. "
+		       "Don't use this parameter!\n");
+	}
+
 	if (rx_frag_size != 8192 && rx_frag_size != 4096
 		&& rx_frag_size != 2048) {
 		printk(KERN_WARNING DRV_NAME
@@ -1976,12 +2395,6 @@ static int __init be_init_module(void)
 			" Using 2048\n");
 		rx_frag_size = 2048;
 	}
-	/* Ensure rx_frag_size is aligned to chache line */
-	if (SKB_DATA_ALIGN(rx_frag_size) != rx_frag_size) {
-		printk(KERN_WARNING DRV_NAME
-			" : Bad module param rx_frag_size. Using 2048\n");
-		rx_frag_size = 2048;
-	}
 
 	return pci_register_driver(&be_driver);
 }