svn commit: r252869 - in head: share/man/man4 sys/dev/oce

Xin LI delphij at FreeBSD.org
Sat Jul 6 08:30:47 UTC 2013


Author: delphij
Date: Sat Jul  6 08:30:45 2013
New Revision: 252869
URL: http://svnweb.freebsd.org/changeset/base/252869

Log:
  Update driver with recent vendor improvements, most notably support
  of Skyhawk adapters.
  
  Many thanks to Emulex for their continued support of FreeBSD.
  
  Submitted by:	"Duvvuru,Venkat Kumar" <VenkatKumar.Duvvuru Emulex.Com>
  MFC after:	1 day

Modified:
  head/share/man/man4/oce.4
  head/sys/dev/oce/oce_hw.c
  head/sys/dev/oce/oce_hw.h
  head/sys/dev/oce/oce_if.c
  head/sys/dev/oce/oce_if.h
  head/sys/dev/oce/oce_mbox.c
  head/sys/dev/oce/oce_queue.c
  head/sys/dev/oce/oce_sysctl.c
  head/sys/dev/oce/oce_util.c

Modified: head/share/man/man4/oce.4
==============================================================================
--- head/share/man/man4/oce.4	Sat Jul  6 08:16:17 2013	(r252868)
+++ head/share/man/man4/oce.4	Sat Jul  6 08:30:45 2013	(r252869)
@@ -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

Modified: head/sys/dev/oce/oce_hw.c
==============================================================================
--- head/sys/dev/oce/oce_hw.c	Sat Jul  6 08:16:17 2013	(r252868)
+++ head/sys/dev/oce/oce_hw.c	Sat Jul  6 08:30:45 2013	(r252869)
@@ -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
@@ -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);
 

Modified: head/sys/dev/oce/oce_hw.h
==============================================================================
--- head/sys/dev/oce/oce_hw.h	Sat Jul  6 08:16:17 2013	(r252868)
+++ head/sys/dev/oce/oce_hw.h	Sat Jul  6 08:30:45 2013	(r252869)
@@ -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
@@ -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
@@ -1998,6 +1997,79 @@ struct mbx_lowlevel_set_loopback_mode {
 		} rsp;
 	} 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];

Modified: head/sys/dev/oce/oce_if.c
==============================================================================
--- head/sys/dev/oce/oce_if.c	Sat Jul  6 08:16:17 2013	(r252868)
+++ head/sys/dev/oce/oce_if.c	Sat Jul  6 08:30:45 2013	(r252869)
@@ -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
@@ -96,6 +96,7 @@ static void update_queues_got(POCE_SOFTC
 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 */
@@ -147,6 +148,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
 };
 
 
@@ -190,6 +192,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;
 				}
@@ -214,7 +219,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;
@@ -229,6 +233,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);
@@ -486,17 +492,18 @@ oce_multiq_start(struct ifnet *ifp, stru
 	int queue_index = 0;
 	int status = 0;
 
+	if (!sc->link_status)
+		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;
 
 }
@@ -579,7 +586,7 @@ oce_setup_intr(POCE_SOFTC sc)
 	int rc = 0, use_intx = 0;
 	int vector = 0, req_vectors = 0;
 
-	if (sc->rss_enable)
+	if (is_rss_enabled(sc))
 		req_vectors = MAX((sc->nrqs - 1), sc->nwqs);
 	else
 		req_vectors = 1;
@@ -778,7 +785,6 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp,
 	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;
@@ -816,20 +822,14 @@ oce_tx(POCE_SOFTC sc, struct mbuf **mpp,
 		}
 	}
 
-	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_sg(wq->tag,
 				     pd->map,
 				     m, segs, &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++;
@@ -838,10 +838,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);
@@ -870,12 +871,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 =
@@ -887,7 +888,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 =
@@ -899,7 +900,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++;
 		}
 
@@ -912,7 +913,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) {
@@ -929,7 +930,7 @@ retry:
 		return rc;
 	else
 		goto free_ret;
-
+	
 	return 0;
 
 free_ret:
@@ -942,21 +943,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);
 
@@ -964,6 +958,7 @@ oce_tx_complete(struct oce_wq *wq, uint3
 	m_freem(m);
 	pd->mbuf = NULL;
 
+
 	if (sc->ifp->if_drv_flags & IFF_DRV_OACTIVE) {
 		if (wq->ring->num_used < (wq->ring->num_items / 2)) {
 			sc->ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE);
@@ -1066,16 +1061,15 @@ oce_tx_task(void *arg, int npending)
 	POCE_SOFTC sc = wq->parent;
 	struct ifnet *ifp = sc->ifp;
 	int rc = 0;
-	
+
 #if __FreeBSD_version >= 800000
-	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
 	oce_start(ifp);
 #endif
@@ -1134,7 +1128,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);
@@ -1158,7 +1151,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;
 }
@@ -1233,7 +1225,7 @@ oce_rx(struct oce_rq *rq, uint32_t rqe_i
 	}
 
 	 /* 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;
@@ -1294,7 +1286,10 @@ oce_rx(struct oce_rq *rq, uint32_t rqe_i
 
 		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
 		/* This deternies if vlan tag is Valid */
@@ -1401,7 +1396,7 @@ oce_cqe_portid_valid(POCE_SOFTC sc, stru
 	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)
@@ -1547,7 +1542,6 @@ oce_rq_handler(void *arg)
 	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);
@@ -1594,8 +1588,6 @@ oce_rq_handler(void *arg)
 			oce_alloc_rx_bufs(rq, (rq_buffers_used - 1));
 	}
 
-	UNLOCK(&rq->rx_lock);
-	
 	return 0;
 
 }
@@ -1889,7 +1881,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);
@@ -2080,38 +2072,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 {
@@ -2196,3 +2172,31 @@ oce_tx_asic_stall_verify(POCE_SOFTC sc, 
 	}
 	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;
+	}
+}

Modified: head/sys/dev/oce/oce_if.h
==============================================================================
--- head/sys/dev/oce/oce_if.h	Sat Jul  6 08:16:17 2013	(r252868)
+++ head/sys/dev/oce/oce_if.h	Sat Jul  6 08:30:45 2013	(r252869)
@@ -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
@@ -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 */
@@ -113,8 +123,9 @@ extern int mp_ncpus;			/* system's total
 #define OCE_NCPUS			mp_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
@@ -149,6 +160,7 @@ extern int mp_ncpus;			/* system's total
 #define RSS_ENABLE_IPV6			0x4
 #define RSS_ENABLE_TCP_IPV6		0x8
 
+#define INDIRECTION_TABLE_ENTRIES	128
 
 /* flow control definitions */
 #define OCE_FC_NONE			0x00000000
@@ -194,6 +206,9 @@ extern int mp_ncpus;			/* system's total
 		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) 	\
@@ -671,8 +686,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;
@@ -685,6 +700,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 {
@@ -765,6 +781,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
@@ -833,11 +850,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 */
@@ -873,37 +890,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)))
 
 
 /***********************************************************
@@ -1024,6 +1051,8 @@ int oce_mbox_cq_create(struct oce_cq *cq
 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,
@@ -1072,6 +1101,9 @@ extern uint32_t oce_max_rsp_handled;	/* 
 #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))
@@ -1104,6 +1136,16 @@ static inline uint32_t oce_highbit(uint3
 	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

Modified: head/sys/dev/oce/oce_mbox.c
==============================================================================
--- head/sys/dev/oce/oce_mbox.c	Sat Jul  6 08:16:17 2013	(r252868)
+++ head/sys/dev/oce/oce_mbox.c	Sat Jul  6 08:30:45 2013	(r252869)
@@ -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
@@ -727,12 +727,14 @@ oce_rss_itbl_init(POCE_SOFTC sc, struct 
 {
 	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 +768,7 @@ oce_config_nic_rss(POCE_SOFTC sc, uint32
 
 	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 +1676,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 +1708,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;
 
@@ -1874,7 +1883,7 @@ oce_mbox_read_transrecv_data(POCE_SOFTC 
 	/* command post */
 	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 +1903,7 @@ oce_mbox_read_transrecv_data(POCE_SOFTC 
 				TRANSCEIVER_A2_SIZE);
 	}
 error:
+	oce_dma_free(sc, &dma);
 	return rc;
 }
 
@@ -1935,10 +1945,193 @@ oce_mbox_eqd_modify_periodic(POCE_SOFTC 
 	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 */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list