From 2d595fe20a29440c5ac4a4b3ad67be31935f4f20 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sat, 13 Jul 2013 12:09:41 +0200
Subject: [PATCH] kernel/oce: Sync oce(4) driver with FreeBSD.

An update by Emulex. Most notably, it adds support for Skyhawk adapters.

The port to DragonFly wasn't tested on a Skyhawk but looks like it should
just work[tm].

Thanks to Mihai Carabas for testing it on a BladeEngine 3 to see that I
didn't break anything which previously worked.

Taken-from: FreeBSD
---
 share/man/man4/oce.4           |   4 +-
 sys/dev/netif/oce/oce_hw.c     |  22 ++---
 sys/dev/netif/oce/oce_hw.h     |  80 ++++++++++++++-
 sys/dev/netif/oce/oce_if.c     | 148 ++++++++++++++--------------
 sys/dev/netif/oce/oce_if.h     |  96 +++++++++++++-----
 sys/dev/netif/oce/oce_mbox.c   | 218 ++++++++++++++++++++++++++++++++++++++---
 sys/dev/netif/oce/oce_queue.c  |   8 +-
 sys/dev/netif/oce/oce_sysctl.c |  12 +--
 sys/dev/netif/oce/oce_util.c   |   4 +-
 9 files changed, 452 insertions(+), 140 deletions(-)

diff --git a/share/man/man4/oce.4 b/share/man/man4/oce.4
index e4ed5bc..80e2eb4 100644
--- a/share/man/man4/oce.4
+++ b/share/man/man4/oce.4
@@ -1,4 +1,4 @@
-.\" Copyright (C) 2012 Emulex
+.\" Copyright (C) 2013 Emulex
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
 .\" 3333 Susan Street
 .\" Costa Mesa, CA 92626
 .\"
-.\" $FreeBSD: src/share/man/man4/oce.4,v 1.5 2012/11/17 01:50:46 svnexp Exp $
+.\" $FreeBSD: src/share/man/man4/oce.4,v 1.7 2013/07/07 00:30:13 svnexp Exp $
 .\"
 .Dd July 1, 2013
 .Dt OCE 4
diff --git a/sys/dev/netif/oce/oce_hw.c b/sys/dev/netif/oce/oce_hw.c
index a7ace70..c5e6fe6 100644
--- a/sys/dev/netif/oce/oce_hw.c
+++ b/sys/dev/netif/oce/oce_hw.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@
  * Costa Mesa, CA 92626
  */
 
-/* $FreeBSD: src/sys/dev/oce/oce_hw.c,v 1.7 2013/03/07 00:29:47 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_hw.c,v 1.8 2013/07/07 00:30:13 svnexp Exp $ */
 
 #include "oce_if.h"
 
@@ -53,12 +53,12 @@ oce_POST(POCE_SOFTC sc)
 	int tmo = 60000;
 
 	/* read semaphore CSR */
-	post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc));
+	post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
 
 	/* if host is ready then wait for fw ready else send POST */
 	if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) {
 		post_status.bits.stage = POST_STAGE_CHIP_RESET;
-		OCE_WRITE_REG32(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0);
+		OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc), post_status.dw0);
 	}
 
 	/* wait for FW ready */
@@ -68,7 +68,7 @@ oce_POST(POCE_SOFTC sc)
 
 		DELAY(1000);
 
-		post_status.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_SEMAPHORE(sc));
+		post_status.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_SEMAPHORE(sc));
 		if (post_status.bits.error) {
 			device_printf(sc->dev,
 				  "POST failed: %x\n", post_status.dw0);
@@ -129,7 +129,7 @@ oce_hw_init(POCE_SOFTC sc)
 	if (rc)
 		goto error;
 
-	if (IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) {
+	if ((IS_BE(sc) && (sc->flags & OCE_FLAGS_BE3)) || IS_SH(sc)) {
 		rc = oce_mbox_check_native_mode(sc);
 		if (rc)
 			goto error;
@@ -258,7 +258,7 @@ oce_hw_pci_alloc(POCE_SOFTC sc)
 
 	rr = PCIR_BAR(pci_cfg_barnum);
 
-	if (IS_BE(sc))
+	if (IS_BE(sc) || IS_SH(sc))
 		sc->devcfg_res = bus_alloc_resource_any(sc->dev,
 				SYS_RES_MEMORY, &rr,
 				RF_ACTIVE|RF_SHAREABLE);
@@ -298,7 +298,7 @@ oce_hw_pci_alloc(POCE_SOFTC sc)
 		sc->flags |= OCE_FLAGS_VIRTUAL_PORT;
 
 	/* Lancer has one BAR (CFG) but BE3 has three (CFG, CSR, DB) */
-	if (IS_BE(sc)) {
+	if (IS_BE(sc) || IS_SH(sc)) {
 		/* set up CSR region */
 		rr = PCIR_BAR(OCE_PCI_CSR_BAR);
 		sc->csr_res = bus_alloc_resource_any(sc->dev,
@@ -387,7 +387,7 @@ oce_create_nw_interface(POCE_SOFTC sc)
 	}
 
 	/* enable capabilities controlled via driver startup parameters */
-	if (sc->rss_enable)
+	if (is_rss_enabled(sc))
 		capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS;
 	else {
 		capab_en_flags &= ~MBX_RX_IFACE_FLAGS_RSS;
@@ -447,9 +447,9 @@ oce_pci_soft_reset(POCE_SOFTC sc)
 	int rc;
 	mpu_ep_control_t ctrl;
 
-	ctrl.dw0 = OCE_READ_REG32(sc, csr, MPU_EP_CONTROL);
+	ctrl.dw0 = OCE_READ_CSR_MPU(sc, csr, MPU_EP_CONTROL);
 	ctrl.bits.cpu_reset = 1;
-	OCE_WRITE_REG32(sc, csr, MPU_EP_CONTROL, ctrl.dw0);
+	OCE_WRITE_CSR_MPU(sc, csr, MPU_EP_CONTROL, ctrl.dw0);
 	DELAY(50);
 	rc=oce_POST(sc);
 
diff --git a/sys/dev/netif/oce/oce_hw.h b/sys/dev/netif/oce/oce_hw.h
index 7d357e7..14319ae 100644
--- a/sys/dev/netif/oce/oce_hw.h
+++ b/sys/dev/netif/oce/oce_hw.h
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@
  * Costa Mesa, CA 92626
  */
 
-/* $FreeBSD: src/sys/dev/oce/oce_hw.h,v 1.5 2013/03/09 03:03:11 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_hw.h,v 1.6 2013/07/07 00:30:13 svnexp Exp $ */
 
 #include <sys/types.h>
 
@@ -63,8 +63,7 @@
 #define	MPU_EP_CONTROL			0
 #define	MPU_EP_SEMAPHORE_BE3		0xac
 #define	MPU_EP_SEMAPHORE_XE201		0x400
-#define MPU_EP_SEMAPHORE(sc) \
-	((IS_BE(sc)) ? MPU_EP_SEMAPHORE_BE3 : MPU_EP_SEMAPHORE_XE201)
+#define	MPU_EP_SEMAPHORE_SH		0x94
 #define	PCICFG_INTR_CTRL		0xfc
 #define	HOSTINTR_MASK			(1 << 29)
 #define	HOSTINTR_PFUNC_SHIFT		26
@@ -1999,6 +1998,79 @@ struct mbx_lowlevel_set_loopback_mode {
 	} params;
 };
 
+#define MAX_RESC_DESC				256
+#define RESC_DESC_SIZE				88
+#define ACTIVE_PROFILE				2
+#define NIC_RESC_DESC_TYPE_V0			0x41
+#define NIC_RESC_DESC_TYPE_V1			0x51
+/* OPCODE_COMMON_GET_FUNCTION_CONFIG */
+struct mbx_common_get_func_config {
+	struct mbx_hdr hdr;
+	union {
+		struct {
+			uint8_t rsvd;
+			uint8_t type;
+			uint16_t rsvd1;
+		} req;
+		struct {
+			uint32_t desc_count;
+			uint8_t resources[MAX_RESC_DESC * RESC_DESC_SIZE];
+		} rsp;
+	} params;
+};
+
+
+/* OPCODE_COMMON_GET_PROFILE_CONFIG */
+
+struct mbx_common_get_profile_config {
+	struct mbx_hdr hdr;
+	union {
+		struct {
+			uint8_t rsvd;
+			uint8_t type;
+			uint16_t rsvd1;
+		} req;
+		struct {
+			uint32_t desc_count;
+			uint8_t resources[MAX_RESC_DESC * RESC_DESC_SIZE];
+		} rsp;
+	} params;
+};
+
+struct oce_nic_resc_desc {
+	uint8_t desc_type;
+	uint8_t desc_len;
+	uint8_t rsvd1;
+	uint8_t flags;
+	uint8_t vf_num;
+	uint8_t rsvd2;
+	uint8_t pf_num;
+	uint8_t rsvd3;
+	uint16_t unicast_mac_count;
+	uint8_t rsvd4[6];
+	uint16_t mcc_count;
+	uint16_t vlan_count;
+	uint16_t mcast_mac_count;
+	uint16_t txq_count;
+	uint16_t rq_count;
+	uint16_t rssq_count;
+	uint16_t lro_count;
+	uint16_t cq_count;
+	uint16_t toe_conn_count;
+	uint16_t eq_count;
+	uint32_t rsvd5;
+	uint32_t cap_flags;
+	uint8_t link_param;
+	uint8_t rsvd6[3];
+	uint32_t bw_min;
+	uint32_t bw_max;
+	uint8_t acpi_params;
+	uint8_t wol_param;
+	uint16_t rsvd7;
+	uint32_t rsvd8[7];
+
+};
+
 struct flash_file_hdr {
 	uint8_t  sign[52];
 	uint8_t  ufi_version[4];
diff --git a/sys/dev/netif/oce/oce_if.c b/sys/dev/netif/oce/oce_if.c
index cb96081..c988297 100644
--- a/sys/dev/netif/oce/oce_if.c
+++ b/sys/dev/netif/oce/oce_if.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
  */
 
 
-/* $FreeBSD: src/sys/dev/oce/oce_if.c,v 1.13 2013/03/07 00:29:47 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_if.c,v 1.14 2013/07/07 00:30:13 svnexp Exp $ */
 
 #include "opt_inet6.h"
 #include "opt_inet.h"
@@ -102,6 +102,7 @@ static void update_queues_got(POCE_SOFTC sc);
 static void process_link_state(POCE_SOFTC sc,
 		 struct oce_async_cqe_link_state *acqe);
 static int oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m);
+static void oce_get_config(POCE_SOFTC sc);
 static struct mbuf *oce_insert_vlan_tag(POCE_SOFTC sc, struct mbuf *m, boolean_t *complete);
 
 /* IP specific */
@@ -159,6 +160,7 @@ static uint32_t supportedDevices[] =  {
 	(PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_BE3,
 	(PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201,
 	(PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201_VF,
+	(PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_SH
 };
 
 
@@ -202,6 +204,9 @@ oce_probe(device_t dev)
 				case PCI_PRODUCT_XE201_VF:
 					sc->flags |= OCE_FLAGS_XE201;
 					break;
+				case PCI_PRODUCT_SH:
+					sc->flags |= OCE_FLAGS_SH;
+					break;
 				default:
 					return ENXIO;
 				}
@@ -226,7 +231,6 @@ oce_attach(device_t dev)
 	if (rc)
 		return rc;
 
-	sc->rss_enable 	 = oce_enable_rss;
 	sc->tx_ring_size = OCE_TX_RING_SIZE;
 	sc->rx_ring_size = OCE_RX_RING_SIZE;
 	sc->rq_frag_size = OCE_RQ_BUF_SIZE;
@@ -241,6 +245,8 @@ oce_attach(device_t dev)
 	if (rc)
 		goto pci_res_free;
 
+	oce_get_config(sc);
+
 	setup_max_queues_want(sc);
 
 	rc = oce_setup_intr(sc);
@@ -512,17 +518,20 @@ oce_multiq_start(struct ifnet *ifp, struct mbuf *m)
 	int queue_index = 0;
 	int status = 0;
 
+	if (!sc->link_status) {
+		ifq_purge(&ifp->if_snd);
+		return ENXIO;
+	}
+
 	if ((m->m_flags & M_FLOWID) != 0)
 		queue_index = m->m_pkthdr.flowid % sc->nwqs;
 
 	wq = sc->wq[queue_index];
 
-	if (TRY_LOCK(&wq->tx_lock)) {
-		status = oce_multiq_transmit(ifp, m, wq);
-		UNLOCK(&wq->tx_lock);
-	} else {
-		status = drbr_enqueue(ifp, wq->br, m);
-	}
+	LOCK(&wq->tx_lock);
+	status = oce_multiq_transmit(ifp, m, wq);
+	UNLOCK(&wq->tx_lock);
+
 	return status;
 
 }
@@ -608,7 +617,7 @@ oce_setup_intr(POCE_SOFTC sc)
 #if 0 /* XXX swildner: MSI-X */
 	int req_vectors = 0;
 
-	if (sc->rss_enable)
+	if (is_rss_enabled(sc))
 		req_vectors = MAX((sc->nrqs - 1), sc->nwqs);
 	else
 		req_vectors = 1;
@@ -814,7 +823,6 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index)
 	struct mbuf *m, *m_temp;
 	struct oce_wq *wq = sc->wq[wq_index];
 	struct oce_packet_desc *pd;
-	uint32_t out;
 	struct oce_nic_hdr_wqe *nichdr;
 	struct oce_nic_frag_wqe *nicfrag;
 	int num_wqes;
@@ -852,13 +860,7 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index)
 		}
 	}
 
-	out = wq->packets_out + 1;
-	if (out == OCE_WQ_PACKET_ARRAY_SIZE)
-		out = 0;
-	if (out == wq->packets_in)
-		return EBUSY;
-
-	pd = &wq->pckts[wq->packets_out];
+	pd = &wq->pckts[wq->pkt_desc_head];
 retry:
 	rc = bus_dmamap_load_mbuf_defrag(wq->tag,
 				     pd->map,
@@ -866,7 +868,7 @@ retry:
 				     &pd->nsegs, BUS_DMA_NOWAIT);
 	if (rc == 0) {
 		num_wqes = pd->nsegs + 1;
-		if (IS_BE(sc)) {
+		if (IS_BE(sc) || IS_SH(sc)) {
 			/*Dummy required only for BE3.*/
 			if (num_wqes & 1)
 				num_wqes++;
@@ -875,10 +877,11 @@ retry:
 			bus_dmamap_unload(wq->tag, pd->map);
 			return EBUSY;
 		}
-
+		atomic_store_rel_int(&wq->pkt_desc_head,
+				     (wq->pkt_desc_head + 1) % \
+				      OCE_WQ_PACKET_ARRAY_SIZE);
 		bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_PREWRITE);
 		pd->mbuf = m;
-		wq->packets_out = out;
 
 		nichdr =
 		    RING_GET_PRODUCER_ITEM_VA(wq->ring, struct oce_nic_hdr_wqe);
@@ -909,12 +912,12 @@ retry:
 				nichdr->u0.s.lso = 1;
 				nichdr->u0.s.lso_mss  = m->m_pkthdr.tso_segsz;
 			}
-			if (!IS_BE(sc))
+			if (!IS_BE(sc) || !IS_SH(sc))
 				nichdr->u0.s.ipcs = 1;
 		}
 
 		RING_PUT(wq->ring, 1);
-		wq->ring->num_used++;
+		atomic_add_int(&wq->ring->num_used, 1);
 
 		for (i = 0; i < pd->nsegs; i++) {
 			nicfrag =
@@ -926,7 +929,7 @@ retry:
 			nicfrag->u0.s.frag_len = segs[i].ds_len;
 			pd->wqe_idx = wq->ring->pidx;
 			RING_PUT(wq->ring, 1);
-			wq->ring->num_used++;
+			atomic_add_int(&wq->ring->num_used, 1);
 		}
 		if (num_wqes > (pd->nsegs + 1)) {
 			nicfrag =
@@ -938,7 +941,7 @@ retry:
 			nicfrag->u0.dw[3] = 0;
 			pd->wqe_idx = wq->ring->pidx;
 			RING_PUT(wq->ring, 1);
-			wq->ring->num_used++;
+			atomic_add_int(&wq->ring->num_used, 1);
 			pd->nsegs++;
 		}
 
@@ -951,7 +954,7 @@ retry:
 		bus_dmamap_sync(wq->ring->dma.tag, wq->ring->dma.map,
 				BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 		reg_value = (num_wqes << 16) | wq->wq_id;
-		OCE_WRITE_REG32(sc, db, PD_TXULP_DB, reg_value);
+		OCE_WRITE_REG32(sc, db, wq->db_offset, reg_value);
 
 	} else if (rc == EFBIG)	{
 		if (retry_cnt == 0) {
@@ -981,21 +984,14 @@ free_ret:
 static void
 oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status)
 {
-	uint32_t in;
 	struct oce_packet_desc *pd;
 	POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
 	struct mbuf *m;
 
-	if (wq->packets_out == wq->packets_in)
-		device_printf(sc->dev, "WQ transmit descriptor missing\n");
-
-	in = wq->packets_in + 1;
-	if (in == OCE_WQ_PACKET_ARRAY_SIZE)
-		in = 0;
-
-	pd = &wq->pckts[wq->packets_in];
-	wq->packets_in = in;
-	wq->ring->num_used -= (pd->nsegs + 1);
+	pd = &wq->pckts[wq->pkt_desc_tail];
+	atomic_store_rel_int(&wq->pkt_desc_tail,
+			     (wq->pkt_desc_tail + 1) % OCE_WQ_PACKET_ARRAY_SIZE);
+	atomic_subtract_int(&wq->ring->num_used, pd->nsegs + 1);
 	bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
 	bus_dmamap_unload(wq->tag, pd->map);
 
@@ -1107,14 +1103,13 @@ oce_tx_task(void *arg, int npending)
 #if 0 /* XXX swildner: MULTIQUEUE */
 	int rc = 0;
 
-	if (TRY_LOCK(&wq->tx_lock)) {
-		rc = oce_multiq_transmit(ifp, NULL, wq);
-		if (rc) {
-			device_printf(sc->dev,
-			 "TX[%d] restart failed\n", wq->queue_index);
-		}
-		UNLOCK(&wq->tx_lock);
+	LOCK(&wq->tx_lock);
+	rc = oce_multiq_transmit(ifp, NULL, wq);
+	if (rc) {
+		device_printf(sc->dev,
+				"TX[%d] restart failed\n", wq->queue_index);
 	}
+	UNLOCK(&wq->tx_lock);
 #else
 	lwkt_serialize_enter(ifp->if_serializer);
 	oce_start_locked(ifp);
@@ -1180,7 +1175,6 @@ oce_wq_handler(void *arg)
 	struct oce_nic_tx_cqe *cqe;
 	int num_cqes = 0;
 
-	LOCK(&wq->tx_lock);
 	bus_dmamap_sync(cq->ring->dma.tag,
 			cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe);
@@ -1204,7 +1198,6 @@ oce_wq_handler(void *arg)
 
 	if (num_cqes)
 		oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
-	UNLOCK(&wq->tx_lock);
 
 	return 0;
 }
@@ -1280,7 +1273,7 @@ oce_rx(struct oce_rq *rq, uint32_t rqe_idx, struct oce_nic_rx_cqe *cqe)
 	}
 
 	 /* Get vlan_tag value */
-	if(IS_BE(sc))
+	if(IS_BE(sc) || IS_SH(sc))
 		vtag = BSWAP_16(cqe->u0.s.vlan_tag);
 	else
 		vtag = cqe->u0.s.vlan_tag;
@@ -1341,7 +1334,10 @@ oce_rx(struct oce_rq *rq, uint32_t rqe_idx, struct oce_nic_rx_cqe *cqe)
 
 		m->m_pkthdr.rcvif = sc->ifp;
 #if __FreeBSD_version >= 800000
-		m->m_pkthdr.flowid = rq->queue_index;
+		if (rq->queue_index)
+			m->m_pkthdr.flowid = (rq->queue_index - 1);
+		else
+			m->m_pkthdr.flowid = rq->queue_index;
 		m->m_flags |= M_FLOWID;
 #endif
 #if 0 /* XXX swildner: ETHER_VTAG */
@@ -1456,7 +1452,7 @@ oce_cqe_portid_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe)
 	struct oce_nic_rx_cqe_v1 *cqe_v1;
 	int port_id = 0;
 
-	if (sc->be3_native && IS_BE(sc)) {
+	if (sc->be3_native && (IS_BE(sc) || IS_SH(sc))) {
 		cqe_v1 = (struct oce_nic_rx_cqe_v1 *)cqe;
 		port_id =  cqe_v1->u0.s.port;
 		if (sc->port_id != port_id)
@@ -1604,8 +1600,6 @@ oce_rq_handler(void *arg)
 	struct oce_nic_rx_cqe *cqe;
 	int num_cqes = 0, rq_buffers_used = 0;
 
-
-	LOCK(&rq->rx_lock);
 	bus_dmamap_sync(cq->ring->dma.tag,
 			cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
@@ -1656,8 +1650,6 @@ oce_rq_handler(void *arg)
 			oce_alloc_rx_bufs(rq, (rq_buffers_used - 1));
 	}
 
-	UNLOCK(&rq->rx_lock);
-
 	return 0;
 
 }
@@ -1961,7 +1953,7 @@ oce_local_timer(void *arg)
 		oce_tx_restart(sc, sc->wq[i]);
 
 	/* calculate and set the eq delay for optimal interrupt rate */
-	if (IS_BE(sc))
+	if (IS_BE(sc) || IS_SH(sc))
 		oce_eqd_set_periodic(sc);
 
 	callout_reset(&sc->timer, hz, oce_local_timer, sc);
@@ -2154,38 +2146,22 @@ oce_mq_handler(void *arg)
 static void
 setup_max_queues_want(POCE_SOFTC sc)
 {
-	int max_rss = 0;
-
 	/* Check if it is FLEX machine. Is so dont use RSS */
 	if ((sc->function_mode & FNM_FLEX10_MODE) ||
 	    (sc->function_mode & FNM_UMC_MODE)    ||
 	    (sc->function_mode & FNM_VNIC_MODE)	  ||
-	    (!sc->rss_enable)			  ||
+	    (!is_rss_enabled(sc))		  ||
 	    (sc->flags & OCE_FLAGS_BE2)) {
 		sc->nrqs = 1;
 		sc->nwqs = 1;
-		sc->rss_enable = 0;
-	} else {
-		/* For multiq, our deisgn is to have TX rings equal to
-		   RSS rings. So that we can pair up one RSS ring and TX
-		   to a single intr, which improves CPU cache efficiency.
-		 */
-		if (IS_BE(sc) && (!sc->be3_native))
-			max_rss = OCE_LEGACY_MODE_RSS;
-		else
-			max_rss = OCE_MAX_RSS;
-
-		sc->nrqs = MIN(OCE_NCPUS, max_rss) + 1; /* 1 for def RX */
-		sc->nwqs = MIN(OCE_NCPUS, max_rss);
 	}
-
 }
 
 
 static void
 update_queues_got(POCE_SOFTC sc)
 {
-	if (sc->rss_enable) {
+	if (is_rss_enabled(sc)) {
 		sc->nrqs = sc->intr_count + 1;
 		sc->nwqs = sc->intr_count;
 	} else {
@@ -2274,3 +2250,31 @@ oce_tx_asic_stall_verify(POCE_SOFTC sc, struct mbuf *m)
 	}
 	return FALSE;
 }
+
+static void
+oce_get_config(POCE_SOFTC sc)
+{
+	int rc = 0;
+	uint32_t max_rss = 0;
+
+	if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
+		max_rss = OCE_LEGACY_MODE_RSS;
+	else
+		max_rss = OCE_MAX_RSS;
+
+	if (!IS_BE(sc)) {
+		rc = oce_get_func_config(sc);
+		if (rc) {
+			sc->nwqs = OCE_MAX_WQ;
+			sc->nrssqs = max_rss;
+			sc->nrqs = sc->nrssqs + 1;
+		}
+	}
+	else {
+		rc = oce_get_profile_config(sc);
+		sc->nrssqs = max_rss;
+		sc->nrqs = sc->nrssqs + 1;
+		if (rc)
+			sc->nwqs = OCE_MAX_WQ;
+	}
+}
diff --git a/sys/dev/netif/oce/oce_if.h b/sys/dev/netif/oce/oce_if.h
index 92886e9..66c28d9 100644
--- a/sys/dev/netif/oce/oce_if.h
+++ b/sys/dev/netif/oce/oce_if.h
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
  */
 
 
-/* $FreeBSD: src/sys/dev/oce/oce_if.h,v 1.5 2013/03/07 00:29:47 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_if.h,v 1.6 2013/07/07 00:30:13 svnexp Exp $ */
 
 #include <sys/param.h>
 #include <sys/endian.h>
@@ -97,11 +97,21 @@
 #define PCI_PRODUCT_BE3			0x0710	/* BE3 network adapter */
 #define PCI_PRODUCT_XE201		0xe220	/* XE201 network adapter */
 #define PCI_PRODUCT_XE201_VF		0xe228	/* XE201 with VF in Lancer */
+#define PCI_PRODUCT_SH			0x0720	/* Skyhawk network adapter */
 
 #define IS_BE(sc)	(((sc->flags & OCE_FLAGS_BE3) | \
 			 (sc->flags & OCE_FLAGS_BE2))? 1:0)
+#define IS_BE3(sc)	(sc->flags & OCE_FLAGS_BE3)
+#define IS_BE2(sc)	(sc->flags & OCE_FLAGS_BE2)
 #define IS_XE201(sc)	((sc->flags & OCE_FLAGS_XE201) ? 1:0)
 #define HAS_A0_CHIP(sc)	((sc->flags & OCE_FLAGS_HAS_A0_CHIP) ? 1:0)
+#define IS_SH(sc)	((sc->flags & OCE_FLAGS_SH) ? 1 : 0)
+
+#define is_be_mode_mc(sc)	((sc->function_mode & FNM_FLEX10_MODE) ||	\
+				(sc->function_mode & FNM_UMC_MODE)    ||	\
+				(sc->function_mode & FNM_VNIC_MODE))
+#define OCE_FUNCTION_CAPS_SUPER_NIC	0x40
+#define IS_PROFILE_SUPER_NIC(sc) (sc->function_caps & OCE_FUNCTION_CAPS_SUPER_NIC)
 
 
 /* proportion Service Level Interface queues */
@@ -112,8 +122,9 @@
 #define OCE_NCPUS			ncpus
 
 /* This should be powers of 2. Like 2,4,8 & 16 */
-#define OCE_MAX_RSS			4 /* TODO: 8*/
+#define OCE_MAX_RSS			8
 #define OCE_LEGACY_MODE_RSS		4 /* For BE3 Legacy mode*/
+#define is_rss_enabled(sc)		((sc->function_caps & FNC_RSS) && !is_be_mode_mc(sc))
 
 #define OCE_MIN_RQ			1
 #define OCE_MIN_WQ			1
@@ -148,6 +159,7 @@
 #define RSS_ENABLE_IPV6			0x4
 #define RSS_ENABLE_TCP_IPV6		0x8
 
+#define INDIRECTION_TABLE_ENTRIES	128
 
 /* flow control definitions */
 #define OCE_FC_NONE			0x00000000
@@ -193,6 +205,9 @@
 		for (i = 0, wq = sc->wq[0]; i < sc->nwqs; i++, wq = sc->wq[i])
 #define for_all_rq_queues(sc, rq, i) 	\
 		for (i = 0, rq = sc->rq[0]; i < sc->nrqs; i++, rq = sc->rq[i])
+#define for_all_rss_queues(sc, rq, i) 	\
+		for (i = 0, rq = sc->rq[i + 1]; i < (sc->nrqs - 1); \
+		     i++, rq = sc->rq[i + 1])
 #define for_all_evnt_queues(sc, eq, i) 	\
 		for (i = 0, eq = sc->eq[0]; i < sc->neqs; i++, eq = sc->eq[i])
 #define for_all_cq_queues(sc, cq, i) 	\
@@ -670,8 +685,8 @@ struct oce_wq {
 	struct oce_cq *cq;
 	bus_dma_tag_t tag;
 	struct oce_packet_desc pckts[OCE_WQ_PACKET_ARRAY_SIZE];
-	uint32_t packets_in;
-	uint32_t packets_out;
+	uint32_t pkt_desc_tail;
+	uint32_t pkt_desc_head;
 	uint32_t wqm_used;
 	boolean_t resched;
 	uint32_t wq_free;
@@ -684,6 +699,7 @@ struct oce_wq {
 	struct oce_tx_queue_stats tx_stats;
 	struct buf_ring *br;
 	struct task txtask;
+	uint32_t db_offset;
 };
 
 struct rq_config {
@@ -766,6 +782,7 @@ struct link_status {
 #define OCE_FLAGS_BE3			0x00000200
 #define OCE_FLAGS_XE201			0x00000400
 #define OCE_FLAGS_BE2			0x00000800
+#define OCE_FLAGS_SH			0x00001000
 
 #define OCE_DEV_BE2_CFG_BAR		1
 #define OCE_DEV_CFG_BAR			0
@@ -834,11 +851,11 @@ typedef struct oce_softc {
 	uint32_t ncqs;
 	uint32_t nrqs;
 	uint32_t nwqs;
+	uint32_t nrssqs;
 
 	uint32_t tx_ring_size;
 	uint32_t rx_ring_size;
 	uint32_t rq_frag_size;
-	uint32_t rss_enable;
 
 	uint32_t if_id;		/* interface ID */
 	uint32_t nifs;		/* number of adapter interfaces, 0 or 1 */
@@ -877,37 +894,47 @@ typedef struct oce_softc {
  * BE3: accesses three BAR spaces (CFG, CSR, DB)
  * Lancer: accesses one BAR space (CFG)
  **************************************************/
-#define OCE_READ_REG32(sc, space, o) \
+#define OCE_READ_CSR_MPU(sc, space, o) \
 	((IS_BE(sc)) ? (bus_space_read_4((sc)->space##_btag, \
-				      (sc)->space##_bhandle,o)) \
-		  : (bus_space_read_4((sc)->devcfg_btag, \
-				      (sc)->devcfg_bhandle,o)))
+					(sc)->space##_bhandle,o)) \
+				: (bus_space_read_4((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o)))
+#define OCE_READ_REG32(sc, space, o) \
+	((IS_BE(sc) || IS_SH(sc)) ? (bus_space_read_4((sc)->space##_btag, \
+					(sc)->space##_bhandle,o)) \
+				: (bus_space_read_4((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o)))
 #define OCE_READ_REG16(sc, space, o) \
-	((IS_BE(sc)) ? (bus_space_read_2((sc)->space##_btag, \
-				      (sc)->space##_bhandle,o)) \
-		  : (bus_space_read_2((sc)->devcfg_btag, \
-				      (sc)->devcfg_bhandle,o)))
+	((IS_BE(sc) || IS_SH(sc)) ? (bus_space_read_2((sc)->space##_btag, \
+					(sc)->space##_bhandle,o)) \
+				: (bus_space_read_2((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o)))
 #define OCE_READ_REG8(sc, space, o) \
-	((IS_BE(sc)) ? (bus_space_read_1((sc)->space##_btag, \
-				      (sc)->space##_bhandle,o)) \
-		  : (bus_space_read_1((sc)->devcfg_btag, \
-				      (sc)->devcfg_bhandle,o)))
+	((IS_BE(sc) || IS_SH(sc)) ? (bus_space_read_1((sc)->space##_btag, \
+					(sc)->space##_bhandle,o)) \
+				: (bus_space_read_1((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o)))
 
-#define OCE_WRITE_REG32(sc, space, o, v) \
+#define OCE_WRITE_CSR_MPU(sc, space, o, v) \
 	((IS_BE(sc)) ? (bus_space_write_4((sc)->space##_btag, \
 				       (sc)->space##_bhandle,o,v)) \
-		  : (bus_space_write_4((sc)->devcfg_btag, \
-				       (sc)->devcfg_bhandle,o,v)))
+				: (bus_space_write_4((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o,v)))
+#define OCE_WRITE_REG32(sc, space, o, v) \
+	((IS_BE(sc) || IS_SH(sc)) ? (bus_space_write_4((sc)->space##_btag, \
+				       (sc)->space##_bhandle,o,v)) \
+				: (bus_space_write_4((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o,v)))
 #define OCE_WRITE_REG16(sc, space, o, v) \
-	((IS_BE(sc)) ? (bus_space_write_2((sc)->space##_btag, \
+	((IS_BE(sc) || IS_SH(sc)) ? (bus_space_write_2((sc)->space##_btag, \
 				       (sc)->space##_bhandle,o,v)) \
-		  : (bus_space_write_2((sc)->devcfg_btag, \
-				       (sc)->devcfg_bhandle,o,v)))
+				: (bus_space_write_2((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o,v)))
 #define OCE_WRITE_REG8(sc, space, o, v) \
-	((IS_BE(sc)) ? (bus_space_write_1((sc)->space##_btag, \
+	((IS_BE(sc) || IS_SH(sc)) ? (bus_space_write_1((sc)->space##_btag, \
 				       (sc)->space##_bhandle,o,v)) \
-		  : (bus_space_write_1((sc)->devcfg_btag, \
-				       (sc)->devcfg_bhandle,o,v)))
+				: (bus_space_write_1((sc)->devcfg_btag, \
+					(sc)->devcfg_bhandle,o,v)))
 
 
 /***********************************************************
@@ -1028,6 +1055,8 @@ int oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce,
 int oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num);
 void oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
 					int num);
+int oce_get_profile_config(POCE_SOFTC sc);
+int oce_get_func_config(POCE_SOFTC sc);
 void mbx_common_req_hdr_init(struct mbx_hdr *hdr,
 			     uint8_t dom,
 			     uint8_t port,
@@ -1077,6 +1106,9 @@ extern uint32_t oce_max_rsp_handled;	/* max responses */
 #define LE_64(x)			htole64(x)
 #define LE_32(x)			htole32(x)
 #define LE_16(x)			htole16(x)
+#define HOST_64(x)			le64toh(x)
+#define HOST_32(x)			le32toh(x)
+#define HOST_16(x)			le16toh(x)
 #define DW_SWAP(x, l)
 #define IS_ALIGNED(x,a)			((x % a) == 0)
 #define ADDR_HI(x)			((uint32_t)((uint64_t)(x) >> 32))
@@ -1109,6 +1141,16 @@ static inline uint32_t oce_highbit(uint32_t x)
 	return 0;
 }
 
+static inline int MPU_EP_SEMAPHORE(POCE_SOFTC sc)
+{
+	if (IS_BE(sc))
+		return MPU_EP_SEMAPHORE_BE3;
+	else if (IS_SH(sc))
+		return MPU_EP_SEMAPHORE_SH;
+	else
+		return MPU_EP_SEMAPHORE_XE201;
+}
+
 #define TRANSCEIVER_DATA_NUM_ELE 64
 #define TRANSCEIVER_DATA_SIZE 256
 #define TRANSCEIVER_A0_SIZE 128
diff --git a/sys/dev/netif/oce/oce_mbox.c b/sys/dev/netif/oce/oce_mbox.c
index 0fd2b72..7af9a77 100644
--- a/sys/dev/netif/oce/oce_mbox.c
+++ b/sys/dev/netif/oce/oce_mbox.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,7 @@
 
 
 
-/* $FreeBSD: src/sys/dev/oce/oce_mbox.c,v 1.4 2013/03/07 00:29:47 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_mbox.c,v 1.5 2013/07/07 00:30:13 svnexp Exp $ */
 
 
 #include "oce_if.h"
@@ -727,12 +727,13 @@ oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
 {
 	int i = 0, j = 0, rc = 0;
 	uint8_t *tbl = fwcmd->params.req.cputable;
+	struct oce_rq *rq = NULL;
 
-
-	for (j = 0; j < sc->nrqs; j++) {
-		if (sc->rq[j]->cfg.is_rss_queue) {
-			tbl[i] = sc->rq[j]->rss_cpuid;
-			i = i + 1;
+	for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
+		for_all_rss_queues(sc, rq, i) {
+			if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
+				break;
+			tbl[j + i] = rq->rss_cpuid;
 		}
 	}
 	if (i == 0) {
@@ -766,7 +767,7 @@ oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
 
 	bzero(&mbx, sizeof(struct oce_mbx));
 
-	if (IS_XE201(sc)) {
+	if (IS_XE201(sc) || IS_SH(sc)) {
 		version = OCE_MBX_VER_V1;
 		fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
 					       RSS_ENABLE_UDP_IPV6;
@@ -1674,8 +1675,11 @@ oce_mbox_create_wq(struct oce_wq *wq)
 	if (IS_XE201(sc)) {
 		version = OCE_MBX_VER_V1;
 		fwcmd->params.req.if_id = sc->if_id;
-	} else
-		version = OCE_MBX_VER_V0;
+	} else if (IS_BE(sc))
+		IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2)
+					 : (version = OCE_MBX_VER_V0);
+	else
+		version = OCE_MBX_VER_V2;
 
 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
 				MBX_SUBSYSTEM_NIC,
@@ -1703,6 +1707,10 @@ oce_mbox_create_wq(struct oce_wq *wq)
 		goto error;
 	}
 	wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
+	if (version == OCE_MBX_VER_V2)
+		wq->db_offset = LE_32(fwcmd->params.rsp.db_offset);
+	else
+		wq->db_offset = PD_TXULP_DB;
 error:
 	return rc;
 
@@ -1743,7 +1751,7 @@ oce_mbox_create_eq(struct oce_eq *eq)
 
 	rc = oce_mbox_post(sc, &mbx, NULL);
 	if (!rc)
-                rc = fwcmd->hdr.u0.rsp.status;
+		rc = fwcmd->hdr.u0.rsp.status;
 	if (rc) {
 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
 			      __FUNCTION__, rc);
@@ -1894,6 +1902,7 @@ oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
 				TRANSCEIVER_A2_SIZE);
 	}
 error:
+	oce_dma_free(sc, &dma);
 	return rc;
 }
 
@@ -1935,8 +1944,193 @@ oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
 	rc = oce_mbox_post(sc, &mbx, NULL);
 
 	if (!rc)
-                rc = fwcmd->hdr.u0.rsp.status;
+		rc = fwcmd->hdr.u0.rsp.status;
 	if (rc)
 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
 			      __FUNCTION__, rc);
 }
+
+int
+oce_get_profile_config(POCE_SOFTC sc)
+{
+	struct oce_mbx mbx;
+	struct mbx_common_get_profile_config *fwcmd;
+	int rc = 0;
+	int version = 0;
+	struct oce_mq_sge *sgl;
+	OCE_DMA_MEM dma;
+	uint32_t desc_count = 0;
+	struct oce_nic_resc_desc *nic_desc = NULL;
+	int i;
+	boolean_t nic_desc_valid = FALSE;
+
+	if (IS_BE2(sc))
+		return -1;
+
+	/* Allocate DMA mem*/
+	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
+			  &dma, 0))
+		return ENOMEM;
+
+	/* Initialize MODIFY_EQ_DELAY ioctl header */
+	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
+	bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
+
+	if (IS_BE3(sc))
+		version = OCE_MBX_VER_V1;
+	else
+		version = OCE_MBX_VER_V0;
+
+	bzero(&mbx, sizeof(struct oce_mbx));
+	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
+				MBX_SUBSYSTEM_COMMON,
+				OPCODE_COMMON_GET_PROFILE_CONFIG,
+				MBX_TIMEOUT_SEC,
+				sizeof(struct mbx_common_get_profile_config),
+				version);
+	/* fill rest of mbx */
+	mbx.u0.s.embedded = 0;
+	mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
+	mbx.u0.s.sge_count = 1;
+	sgl = &mbx.payload.u0.u1.sgl[0];
+	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
+	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
+	sgl->length = htole32(mbx.payload_length);
+	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
+
+	fwcmd->params.req.type = ACTIVE_PROFILE;
+
+	/* command post */
+	rc = oce_mbox_post(sc, &mbx, NULL);
+	if (!rc)
+		rc = fwcmd->hdr.u0.rsp.status;
+	if (rc) {
+		device_printf(sc->dev,"%s failed - cmd status: %d\n",
+			      __FUNCTION__, rc);
+		goto error;
+	}
+
+	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
+	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
+	for (i = 0; i < desc_count; i++) {
+		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
+		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
+			nic_desc_valid = TRUE;
+			break;
+		}
+		nic_desc = (struct oce_nic_resc_desc *) \
+				((char *)nic_desc + nic_desc->desc_len);
+	}
+	if (!nic_desc_valid) {
+		rc = -1;
+		goto error;
+	}
+	else {
+		sc->nwqs = HOST_32(nic_desc->txq_count);
+		if (sc->nwqs)
+			sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
+		else
+			sc->nwqs = OCE_MAX_WQ;
+
+	}
+error:
+	oce_dma_free(sc, &dma);
+	return rc;
+
+}
+
+int
+oce_get_func_config(POCE_SOFTC sc)
+{
+	struct oce_mbx mbx;
+	struct mbx_common_get_func_config *fwcmd;
+	int rc = 0;
+	int version = 0;
+	struct oce_mq_sge *sgl;
+	OCE_DMA_MEM dma;
+	uint32_t desc_count = 0;
+	struct oce_nic_resc_desc *nic_desc = NULL;
+	int i;
+	boolean_t nic_desc_valid = FALSE;
+	uint32_t max_rss = 0;
+
+	if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
+		max_rss = OCE_LEGACY_MODE_RSS;
+	else
+		max_rss = OCE_MAX_RSS;
+
+	/* Allocate DMA mem*/
+	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
+			  &dma, 0))
+		return ENOMEM;
+
+	/* Initialize MODIFY_EQ_DELAY ioctl header */
+	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
+	bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
+
+	if (IS_SH(sc))
+		version = OCE_MBX_VER_V1;
+	else
+		version = OCE_MBX_VER_V0;
+
+	bzero(&mbx, sizeof(struct oce_mbx));
+	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
+				MBX_SUBSYSTEM_COMMON,
+				OPCODE_COMMON_GET_FUNCTION_CONFIG,
+				MBX_TIMEOUT_SEC,
+				sizeof(struct mbx_common_get_func_config),
+				version);
+	/* fill rest of mbx */
+	mbx.u0.s.embedded = 0;
+	mbx.payload_length = sizeof(struct mbx_common_get_func_config);
+	mbx.u0.s.sge_count = 1;
+	sgl = &mbx.payload.u0.u1.sgl[0];
+	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
+	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
+	sgl->length = htole32(mbx.payload_length);
+	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
+
+	/* command post */
+	rc = oce_mbox_post(sc, &mbx, NULL);
+	if (!rc)
+		rc = fwcmd->hdr.u0.rsp.status;
+	if (rc) {
+		device_printf(sc->dev,"%s failed - cmd status: %d\n",
+			      __FUNCTION__, rc);
+		goto error;
+	}
+
+	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
+	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
+	for (i = 0; i < desc_count; i++) {
+		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
+		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
+			nic_desc_valid = TRUE;
+			break;
+		}
+		nic_desc = (struct oce_nic_resc_desc *) \
+				((char *)nic_desc + nic_desc->desc_len);
+	}
+	if (!nic_desc_valid) {
+		rc = -1;
+		goto error;
+	}
+	else {
+		sc->nwqs = HOST_32(nic_desc->txq_count);
+                if (sc->nwqs)
+                        sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
+                else
+                        sc->nwqs = OCE_MAX_WQ;
+
+		sc->nrssqs = HOST_32(nic_desc->rssq_count);
+		if (sc->nrssqs)
+			sc->nrssqs = MIN(sc->nrssqs, max_rss);
+		else
+			sc->nrssqs = max_rss;
+		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */;
+	}
+error:
+	oce_dma_free(sc, &dma);
+	return rc;
+
+}
diff --git a/sys/dev/netif/oce/oce_queue.c b/sys/dev/netif/oce/oce_queue.c
index 9646f02..bcd4261 100644
--- a/sys/dev/netif/oce/oce_queue.c
+++ b/sys/dev/netif/oce/oce_queue.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,7 @@
 
 
 
-/* $FreeBSD: src/sys/dev/oce/oce_queue.c,v 1.4 2013/03/07 00:29:47 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_queue.c,v 1.5 2013/07/07 00:30:13 svnexp Exp $ */
 
 
 #include "oce_if.h"
@@ -106,7 +106,7 @@ oce_queue_init_all(POCE_SOFTC sc)
 	for_all_rq_queues(sc, rq, i) {
 		sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size,
 					OCE_MAX_JUMBO_FRAME_SIZE,
-					(i == 0) ? 0 : sc->rss_enable);
+					(i == 0) ? 0 : is_rss_enabled(sc));
 		if (!sc->rq[i])
 			goto error;
 	}
@@ -1229,7 +1229,7 @@ oce_start_rx(POCE_SOFTC sc)
 	DELAY(1);
 
 	/* RSS config */
-	if (sc->rss_enable) {
+	if (is_rss_enabled(sc)) {
 		rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE);
 		if (rc)
 			goto error;
diff --git a/sys/dev/netif/oce/oce_sysctl.c b/sys/dev/netif/oce/oce_sysctl.c
index cf94b29..3515c44 100644
--- a/sys/dev/netif/oce/oce_sysctl.c
+++ b/sys/dev/netif/oce/oce_sysctl.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@
  * Costa Mesa, CA 92626
  */
 
-/* $FreeBSD: src/sys/dev/oce/oce_sysctl.c,v 1.5 2013/03/09 03:03:11 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_sysctl.c,v 1.6 2013/07/07 00:30:13 svnexp Exp $ */
 
 
 #include "oce_if.h"
@@ -140,7 +140,7 @@ oce_add_sysctls(POCE_SOFTC sc)
 	stats_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats",
 				CTLFLAG_RD, NULL, "Ethernet Statistics");
 
-	if (IS_BE(sc))
+	if (IS_BE(sc) || IS_SH(sc))
 		oce_add_stats_sysctls_be3(sc, ctx, stats_node);
 	else
 		oce_add_stats_sysctls_xe201(sc, ctx, stats_node);
@@ -223,7 +223,7 @@ oce_sys_fwupgrade(SYSCTL_HANDLER_ARGS)
 		return ENOENT;
 	}
 
-	if (IS_BE(sc)) {
+	if (IS_BE(sc) || IS_SH(sc)) {
 		if ((sc->flags & OCE_FLAGS_BE2)) {
 			device_printf(sc->dev,
 				"Flashing not supported for BE2 yet.\n");
@@ -1270,7 +1270,7 @@ oce_stats_init(POCE_SOFTC sc)
 {
 	int rc = 0, sz;
 
-	if (IS_BE(sc)) {
+	if (IS_BE(sc) || IS_SH(sc)) {
 		if (sc->flags & OCE_FLAGS_BE2)
 			sz = sizeof(struct mbx_get_nic_stats_v0);
 		else
@@ -1298,7 +1298,7 @@ oce_refresh_nic_stats(POCE_SOFTC sc)
 {
 	int rc = 0, reset = 0;
 
-	if (IS_BE(sc)) {
+	if (IS_BE(sc) || IS_SH(sc)) {
 		if (sc->flags & OCE_FLAGS_BE2) {
 			rc = oce_mbox_get_nic_stats_v0(sc, &sc->stats_mem);
 			if (!rc)
diff --git a/sys/dev/netif/oce/oce_util.c b/sys/dev/netif/oce/oce_util.c
index d605e7f..f47bc25 100644
--- a/sys/dev/netif/oce/oce_util.c
+++ b/sys/dev/netif/oce/oce_util.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (C) 2012 Emulex
+ * Copyright (C) 2013 Emulex
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
  */
 
 
-/* $FreeBSD: src/sys/dev/oce/oce_util.c,v 1.4 2013/03/07 00:29:47 svnexp Exp $ */
+/* $FreeBSD: src/sys/dev/oce/oce_util.c,v 1.5 2013/07/07 00:30:13 svnexp Exp $ */
 
 
 #include "oce_if.h"
-- 
1.7.12.2

