Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Aug 2014 19:54:03 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r270297 - in stable/10/sys: conf dev/cxgbe dev/cxgbe/common dev/cxgbe/tom modules/cxgbe modules/cxgbe/if_cxgbe modules/cxgbe/iw_cxgbe modules/cxgbe/t4_firmware modules/cxgbe/t5_firmware...
Message-ID:  <201408211954.s7LJs321054331@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Thu Aug 21 19:54:02 2014
New Revision: 270297
URL: http://svnweb.freebsd.org/changeset/base/270297

Log:
  MFC r266571, r266757, r268536, r269076, r269364, r269366, r269411,
  r269413, r269428, r269440, r269537, r269644, r269731, and the cxgbe
  portion of r270063.
  
  r266571:
  cxgbe(4): Remove stray if_up from the code that creates the tracing ifnet.
  
  r266757:
  cxgbe(4): netmap support for Terminator 5 (T5) based 10G/40G cards.
  Netmap gets its own hardware-assisted virtual interface and won't take
  over or disrupt the "normal" interface in any way.  You can use both
  simultaneously.
  
  For kernels with DEV_NETMAP, cxgbe(4) carves out an ncxl<N> interface
  (note the 'n' prefix) in the hardware to accompany each cxl<N>
  interface.  These two ifnet's per port share the same wire but really
  are separate interfaces in the hardware and software.  Each gets its own
  L2 MAC addresses (unicast and multicast), MTU, checksum caps, etc.  You
  should run netmap on the 'n' interfaces only, that's what they are for.
  
  With this, pkt-gen is able to transmit > 45Mpps out of a single 40G port
  of a T580 card.  2 port tx is at ~56Mpps total (28M + 28M) as of now.
  Single port receive is at 33Mpps but this is very much a work in
  progress.  I expect it to be closer to 40Mpps once done.  In any case
  the current effort can already saturate multiple 10G ports of a T5 card
  at the smallest legal packet size.  T4 gear is totally untested.
  
  trantor:~# ./pkt-gen -i ncxl0 -f tx -D 00:07:43:ab:cd:ef
  881.952141 main [1621] interface is ncxl0
  881.952250 extract_ip_range [275] range is 10.0.0.1:0 to 10.0.0.1:0
  881.952253 extract_ip_range [275] range is 10.1.0.1:0 to 10.1.0.1:0
  881.962540 main [1804] mapped 334980KB at 0x801dff000
  Sending on netmap:ncxl0: 4 queues, 1 threads and 1 cpus.
  10.0.0.1 -> 10.1.0.1 (00:00:00:00:00:00 -> 00:07:43:ab:cd:ef)
  881.962562 main [1882] Sending 512 packets every  0.000000000 s
  881.962563 main [1884] Wait 2 secs for phy reset
  884.088516 main [1886] Ready...
  884.088535 nm_open [457] overriding ifname ncxl0 ringid 0x0 flags 0x1
  884.088607 sender_body [996] start
  884.093246 sender_body [1064] drop copy
  885.090435 main_thread [1418] 45206353 pps (45289533 pkts in 1001840 usec)
  886.091600 main_thread [1418] 45322792 pps (45375593 pkts in 1001165 usec)
  887.092435 main_thread [1418] 45313992 pps (45351784 pkts in 1000834 usec)
  888.094434 main_thread [1418] 45315765 pps (45406397 pkts in 1002000 usec)
  889.095434 main_thread [1418] 45333218 pps (45378551 pkts in 1001000 usec)
  890.097434 main_thread [1418] 45315247 pps (45405877 pkts in 1002000 usec)
  891.099434 main_thread [1418] 45326515 pps (45417168 pkts in 1002000 usec)
  892.101434 main_thread [1418] 45333039 pps (45423705 pkts in 1002000 usec)
  893.103434 main_thread [1418] 45324105 pps (45414708 pkts in 1001999 usec)
  894.105434 main_thread [1418] 45318042 pps (45408723 pkts in 1002001 usec)
  895.106434 main_thread [1418] 45332430 pps (45377762 pkts in 1001000 usec)
  896.107434 main_thread [1418] 45338072 pps (45383410 pkts in 1001000 usec)
  ...
  
  r268536:
  cxgbe(4): Add an iSCSI softc to the adapter structure.
  
  r269076:
  Some hooks in cxgbe(4) for the offloaded iSCSI driver.
  
  r269364:
  Improve compliance with style.Makefile(5).
  
  r269366:
  List one file per line in the Makefiles.  This makes it easier to read
  diffs when a file is added or removed.
  
  r269411:
  cxgbe(4): minor optimizations in ingress queue processing.
  
  Reorganize struct sge_iq.  Make the iq entry size a compile time
  constant.  While here, eliminate RX_FL_ESIZE and use EQ_ESIZE directly.
  
  r269413:
  cxgbe(4):  Fix an off by one error when looking for the BAR2 doorbell
  address of an egress queue.
  
  r269428:
  cxgbe(4):  some optimizations in freelist handling.
  
  r269440:
  cxgbe(4): Remove an unused version of t4_enable_vi.
  
  r269537:
  cxgbe(4): Do not run any sleepable code in the SIOCSIFFLAGS handler when
  IFF_PROMISC or IFF_ALLMULTI is being flipped.  bpf(4) holds its global
  mutex around ifpromisc in at least the bpf_dtor path.
  
  r269644:
  cxgbe(4):  Let caller specify whether it's ok to sleep in
  t4_sched_config and t4_sched_params.
  
  r269731:
  cxgbe(4): Do not poke T4-only registers on a T5 (and vice versa).
  
  Relnotes:	Yes (native netmap support for Chelsio T4/T5 cards)

Added:
  stable/10/sys/dev/cxgbe/t4_netmap.c
     - copied, changed from r266757, head/sys/dev/cxgbe/t4_netmap.c
Modified:
  stable/10/sys/conf/files
  stable/10/sys/dev/cxgbe/adapter.h
  stable/10/sys/dev/cxgbe/common/common.h
  stable/10/sys/dev/cxgbe/common/t4_hw.c
  stable/10/sys/dev/cxgbe/offload.h
  stable/10/sys/dev/cxgbe/t4_main.c
  stable/10/sys/dev/cxgbe/t4_sge.c
  stable/10/sys/dev/cxgbe/t4_tracer.c
  stable/10/sys/dev/cxgbe/tom/t4_cpl_io.c
  stable/10/sys/dev/cxgbe/tom/t4_ddp.c
  stable/10/sys/dev/cxgbe/tom/t4_tom.h
  stable/10/sys/modules/cxgbe/Makefile
  stable/10/sys/modules/cxgbe/if_cxgbe/Makefile
  stable/10/sys/modules/cxgbe/iw_cxgbe/Makefile
  stable/10/sys/modules/cxgbe/t4_firmware/Makefile
  stable/10/sys/modules/cxgbe/t5_firmware/Makefile
  stable/10/sys/modules/cxgbe/tom/Makefile
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/conf/files
==============================================================================
--- stable/10/sys/conf/files	Thu Aug 21 19:51:07 2014	(r270296)
+++ stable/10/sys/conf/files	Thu Aug 21 19:54:02 2014	(r270297)
@@ -1128,6 +1128,8 @@ dev/cxgb/cxgb_t3fw.c		optional cxgb cxgb
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgbe/t4_main.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
+dev/cxgbe/t4_netmap.c		optional cxgbe pci \
+	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_sge.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_l2t.c		optional cxgbe pci \

Modified: stable/10/sys/dev/cxgbe/adapter.h
==============================================================================
--- stable/10/sys/dev/cxgbe/adapter.h	Thu Aug 21 19:51:07 2014	(r270296)
+++ stable/10/sys/dev/cxgbe/adapter.h	Thu Aug 21 19:54:02 2014	(r270297)
@@ -48,6 +48,7 @@
 #include <netinet/tcp_lro.h>
 
 #include "offload.h"
+#include "common/t4_msg.h"
 #include "firmware/t4fw_interface.h"
 
 MALLOC_DECLARE(M_CXGBE);
@@ -118,15 +119,24 @@ struct adapter;
 typedef struct adapter adapter_t;
 
 enum {
-	FW_IQ_QSIZE = 256,
-	FW_IQ_ESIZE = 64,	/* At least 64 mandated by the firmware spec */
+	/*
+	 * All ingress queues use this entry size.  Note that the firmware event
+	 * queue and any iq expecting CPL_RX_PKT in the descriptor needs this to
+	 * be at least 64.
+	 */
+	IQ_ESIZE = 64,
 
+	/* Default queue sizes for all kinds of ingress queues */
+	FW_IQ_QSIZE = 256,
 	RX_IQ_QSIZE = 1024,
-	RX_IQ_ESIZE = 64,	/* At least 64 so CPL_RX_PKT will fit */
 
-	EQ_ESIZE = 64,		/* All egress queues use this entry size */
+	/* All egress queues use this entry size */
+	EQ_ESIZE = 64,
+
+	/* Default queue sizes for all kinds of egress queues */
+	CTRL_EQ_QSIZE = 128,
+	TX_EQ_QSIZE = 1024,
 
-	RX_FL_ESIZE = EQ_ESIZE,	/* 8 64bit addresses */
 #if MJUMPAGESIZE != MCLBYTES
 	SW_ZONE_SIZES = 4,	/* cluster, jumbop, jumbo9k, jumbo16k */
 #else
@@ -134,9 +144,7 @@ enum {
 #endif
 	CL_METADATA_SIZE = CACHE_LINE_SIZE,
 
-	CTRL_EQ_QSIZE = 128,
-
-	TX_EQ_QSIZE = 1024,
+	SGE_MAX_WR_NDESC = SGE_MAX_WR_LEN / EQ_ESIZE, /* max WR size in desc */
 	TX_SGL_SEGS = 36,
 	TX_WR_FLITS = SGE_MAX_WR_LEN / 8
 };
@@ -149,6 +157,17 @@ enum {
 };
 
 enum {
+	XGMAC_MTU	= (1 << 0),
+	XGMAC_PROMISC	= (1 << 1),
+	XGMAC_ALLMULTI	= (1 << 2),
+	XGMAC_VLANEX	= (1 << 3),
+	XGMAC_UCADDR	= (1 << 4),
+	XGMAC_MCADDRS	= (1 << 5),
+
+	XGMAC_ALL	= 0xffff
+};
+
+enum {
 	/* flags understood by begin_synchronized_op */
 	HOLD_LOCK	= (1 << 0),
 	SLEEP_OK	= (1 << 1),
@@ -162,7 +181,7 @@ enum {
 	/* adapter flags */
 	FULL_INIT_DONE	= (1 << 0),
 	FW_OK		= (1 << 1),
-	INTR_DIRECT	= (1 << 2),	/* direct interrupts for everything */
+	/* INTR_DIRECT	= (1 << 2),	No longer used. */
 	MASTER_PF	= (1 << 3),
 	ADAP_SYSCTL_CTX	= (1 << 4),
 	TOM_INIT_DONE	= (1 << 5),
@@ -175,6 +194,10 @@ enum {
 	PORT_INIT_DONE	= (1 << 1),
 	PORT_SYSCTL_CTX	= (1 << 2),
 	HAS_TRACEQ	= (1 << 3),
+	INTR_RXQ	= (1 << 4),	/* All NIC rxq's take interrupts */
+	INTR_OFLD_RXQ	= (1 << 5),	/* All TOE rxq's take interrupts */
+	INTR_NM_RXQ	= (1 << 6),	/* All netmap rxq's take interrupts */
+	INTR_ALL	= (INTR_RXQ | INTR_OFLD_RXQ | INTR_NM_RXQ),
 };
 
 #define IS_DOOMED(pi)	((pi)->flags & DOOMED)
@@ -219,6 +242,19 @@ struct port_info {
 	int nofldrxq;		/* # of offload rx queues */
 	int first_ofld_rxq;	/* index of first offload rx queue */
 #endif
+#ifdef DEV_NETMAP
+	int nnmtxq;		/* # of netmap tx queues */
+	int first_nm_txq;	/* index of first netmap tx queue */
+	int nnmrxq;		/* # of netmap rx queues */
+	int first_nm_rxq;	/* index of first netmap rx queue */
+
+	struct ifnet *nm_ifp;
+	struct ifmedia nm_media;
+	int nmif_flags;
+	uint16_t nm_viid;
+	int16_t nm_xact_addr_filt;
+	uint16_t nm_rss_size;	/* size of netmap VI's RSS table slice */
+#endif
 	int tmr_idx;
 	int pktc_idx;
 	int qsize_rxq;
@@ -281,6 +317,16 @@ struct tx_sdesc {
 	uint8_t credits;	/* NIC txq: # of frames sent out in the WR */
 };
 
+
+#define IQ_PAD (IQ_ESIZE - sizeof(struct rsp_ctrl) - sizeof(struct rss_header))
+struct iq_desc {
+	struct rss_header rss;
+	uint8_t cpl[IQ_PAD];
+	struct rsp_ctrl rsp;
+};
+#undef IQ_PAD
+CTASSERT(sizeof(struct iq_desc) == IQ_ESIZE);
+
 enum {
 	/* iq flags */
 	IQ_ALLOCATED	= (1 << 0),	/* firmware resources allocated */
@@ -298,27 +344,25 @@ enum {
  * Ingress Queue: T4 is producer, driver is consumer.
  */
 struct sge_iq {
-	bus_dma_tag_t desc_tag;
-	bus_dmamap_t desc_map;
-	bus_addr_t ba;		/* bus address of descriptor ring */
 	uint32_t flags;
-	uint16_t abs_id;	/* absolute SGE id for the iq */
-	int8_t   intr_pktc_idx;	/* packet count threshold index */
-	int8_t   pad0;
-	__be64  *desc;		/* KVA of descriptor ring */
-
 	volatile int state;
 	struct adapter *adapter;
-	const __be64 *cdesc;	/* current descriptor */
+	struct iq_desc  *desc;	/* KVA of descriptor ring */
+	int8_t   intr_pktc_idx;	/* packet count threshold index */
 	uint8_t  gen;		/* generation bit */
 	uint8_t  intr_params;	/* interrupt holdoff parameters */
 	uint8_t  intr_next;	/* XXX: holdoff for next interrupt */
-	uint8_t  esize;		/* size (bytes) of each entry in the queue */
 	uint16_t qsize;		/* size (# of entries) of the queue */
+	uint16_t sidx;		/* index of the entry with the status page */
 	uint16_t cidx;		/* consumer index */
 	uint16_t cntxt_id;	/* SGE context id for the iq */
+	uint16_t abs_id;	/* absolute SGE id for the iq */
 
 	STAILQ_ENTRY(sge_iq) link;
+
+	bus_dma_tag_t desc_tag;
+	bus_dmamap_t desc_map;
+	bus_addr_t ba;		/* bus address of descriptor ring */
 };
 
 enum {
@@ -356,7 +400,7 @@ struct sge_eq {
 	struct tx_desc *desc;	/* KVA of descriptor ring */
 	bus_addr_t ba;		/* bus address of descriptor ring */
 	struct sge_qstat *spg;	/* status page, for convenience */
-	int doorbells;
+	uint16_t doorbells;
 	volatile uint32_t *udb;	/* KVA of doorbell (lies within BAR2) */
 	u_int udb_qid;		/* relative qid within the doorbell page */
 	uint16_t cap;		/* max # of desc, for convenience */
@@ -394,43 +438,55 @@ enum {
 	FL_STARVING	= (1 << 0), /* on the adapter's list of starving fl's */
 	FL_DOOMED	= (1 << 1), /* about to be destroyed */
 	FL_BUF_PACKING	= (1 << 2), /* buffer packing enabled */
+	FL_BUF_RESUME	= (1 << 3), /* resume from the middle of the frame */
 };
 
-#define FL_RUNNING_LOW(fl)	(fl->cap - fl->needed <= fl->lowat)
-#define FL_NOT_RUNNING_LOW(fl)	(fl->cap - fl->needed >= 2 * fl->lowat)
+#define FL_RUNNING_LOW(fl) \
+    (IDXDIFF(fl->dbidx * 8, fl->cidx, fl->sidx * 8) <= fl->lowat)
+#define FL_NOT_RUNNING_LOW(fl) \
+    (IDXDIFF(fl->dbidx * 8, fl->cidx, fl->sidx * 8) >= 2 * fl->lowat)
 
 struct sge_fl {
-	bus_dma_tag_t desc_tag;
-	bus_dmamap_t desc_map;
-	struct cluster_layout cll_def;	/* default refill zone, layout */
-	struct cluster_layout cll_alt;	/* alternate refill zone, layout */
 	struct mtx fl_lock;
-	char lockname[16];
-	int flags;
-
 	__be64 *desc;		/* KVA of descriptor ring, ptr to addresses */
-	bus_addr_t ba;		/* bus address of descriptor ring */
 	struct fl_sdesc *sdesc;	/* KVA of software descriptor ring */
-	uint32_t cap;		/* max # of buffers, for convenience */
-	uint16_t qsize;		/* size (# of entries) of the queue */
-	uint16_t cntxt_id;	/* SGE context id for the freelist */
-	uint32_t cidx;		/* consumer idx (buffer idx, NOT hw desc idx) */
-	uint32_t rx_offset;	/* offset in fl buf (when buffer packing) */
-	uint32_t pidx;		/* producer idx (buffer idx, NOT hw desc idx) */
-	uint32_t needed;	/* # of buffers needed to fill up fl. */
-	uint32_t lowat;		/* # of buffers <= this means fl needs help */
-	uint32_t pending;	/* # of bufs allocated since last doorbell */
-	TAILQ_ENTRY(sge_fl) link; /* All starving freelists */
+	struct cluster_layout cll_def;	/* default refill zone, layout */
+	uint16_t lowat;		/* # of buffers <= this means fl needs help */
+	int flags;
+	uint16_t buf_boundary;
 
-	struct mbuf *m0;
-	struct mbuf **pnext;
-	u_int remaining;
+	/* The 16b idx all deal with hw descriptors */
+	uint16_t dbidx;		/* hw pidx after last doorbell */
+	uint16_t sidx;		/* index of status page */
+	volatile uint16_t hw_cidx;
+
+	/* The 32b idx are all buffer idx, not hardware descriptor idx */
+	uint32_t cidx;		/* consumer index */
+	uint32_t pidx;		/* producer index */
+
+	uint32_t dbval;
+	u_int rx_offset;	/* offset in fl buf (when buffer packing) */
+	volatile uint32_t *udb;
 
 	uint64_t mbuf_allocated;/* # of mbuf allocated from zone_mbuf */
 	uint64_t mbuf_inlined;	/* # of mbuf created within clusters */
 	uint64_t cl_allocated;	/* # of clusters allocated */
 	uint64_t cl_recycled;	/* # of clusters recycled */
 	uint64_t cl_fast_recycled; /* # of clusters recycled (fast) */
+
+	/* These 3 are valid when FL_BUF_RESUME is set, stale otherwise. */
+	struct mbuf *m0;
+	struct mbuf **pnext;
+	u_int remaining;
+
+	uint16_t qsize;		/* # of hw descriptors (status page included) */
+	uint16_t cntxt_id;	/* SGE context id for the freelist */
+	TAILQ_ENTRY(sge_fl) link; /* All starving freelists */
+	bus_dma_tag_t desc_tag;
+	bus_dmamap_t desc_map;
+	char lockname[16];
+	bus_addr_t ba;		/* bus address of descriptor ring */
+	struct cluster_layout cll_alt;	/* alternate refill zone, layout */
 };
 
 /* txq: SGE egress queue + what's needed for Ethernet NIC */
@@ -532,6 +588,64 @@ struct sge_wrq {
 	uint32_t no_desc;	/* out of hardware descriptors */
 } __aligned(CACHE_LINE_SIZE);
 
+
+#ifdef DEV_NETMAP
+struct sge_nm_rxq {
+	struct port_info *pi;
+
+	struct iq_desc *iq_desc;
+	uint16_t iq_abs_id;
+	uint16_t iq_cntxt_id;
+	uint16_t iq_cidx;
+	uint16_t iq_sidx;
+	uint8_t iq_gen;
+
+	__be64  *fl_desc;
+	uint16_t fl_cntxt_id;
+	uint32_t fl_cidx;
+	uint32_t fl_pidx;
+	uint32_t fl_sidx;
+	uint32_t fl_db_val;
+	u_int fl_hwidx:4;
+
+	u_int nid;		/* netmap ring # for this queue */
+
+	/* infrequently used items after this */
+
+	bus_dma_tag_t iq_desc_tag;
+	bus_dmamap_t iq_desc_map;
+	bus_addr_t iq_ba;
+	int intr_idx;
+
+	bus_dma_tag_t fl_desc_tag;
+	bus_dmamap_t fl_desc_map;
+	bus_addr_t fl_ba;
+} __aligned(CACHE_LINE_SIZE);
+
+struct sge_nm_txq {
+	struct tx_desc *desc;
+	uint16_t cidx;
+	uint16_t pidx;
+	uint16_t sidx;
+	uint16_t equiqidx;	/* EQUIQ last requested at this pidx */
+	uint16_t equeqidx;	/* EQUEQ last requested at this pidx */
+	uint16_t dbidx;		/* pidx of the most recent doorbell */
+	uint16_t doorbells;
+	volatile uint32_t *udb;
+	u_int udb_qid;
+	u_int cntxt_id;
+	__be32 cpl_ctrl0;	/* for convenience */
+	u_int nid;		/* netmap ring # for this queue */
+
+	/* infrequently used items after this */
+
+	bus_dma_tag_t desc_tag;
+	bus_dmamap_t desc_map;
+	bus_addr_t ba;
+	int iqidx;
+} __aligned(CACHE_LINE_SIZE);
+#endif
+
 struct sge {
 	int timer_val[SGE_NTIMERS];
 	int counter_val[SGE_NCOUNTERS];
@@ -546,6 +660,10 @@ struct sge {
 	int nofldrxq;	/* total # of TOE rx queues */
 	int nofldtxq;	/* total # of TOE tx queues */
 #endif
+#ifdef DEV_NETMAP
+	int nnmrxq;	/* total # of netmap rx queues */
+	int nnmtxq;	/* total # of netmap tx queues */
+#endif
 	int niq;	/* total # of ingress queues */
 	int neq;	/* total # of egress queues */
 
@@ -558,6 +676,10 @@ struct sge {
 	struct sge_wrq *ofld_txq;	/* TOE tx queues */
 	struct sge_ofld_rxq *ofld_rxq;	/* TOE rx queues */
 #endif
+#ifdef DEV_NETMAP
+	struct sge_nm_txq *nm_txq;	/* netmap tx queues */
+	struct sge_nm_rxq *nm_rxq;	/* netmap rx queues */
+#endif
 
 	uint16_t iq_start;
 	int eq_start;
@@ -619,11 +741,12 @@ struct adapter {
 	void *tom_softc;	/* (struct tom_data *) */
 	struct tom_tunables tt;
 	void *iwarp_softc;	/* (struct c4iw_dev *) */
+	void *iscsi_softc;
 #endif
 	struct l2t_data *l2t;	/* L2 table */
 	struct tid_info tids;
 
-	int doorbells;
+	uint16_t doorbells;
 	int open_device_map;
 #ifdef TCP_OFFLOAD
 	int offload_map;
@@ -724,6 +847,18 @@ struct adapter {
 #define for_each_ofld_rxq(pi, iter, q) \
 	for (q = &pi->adapter->sge.ofld_rxq[pi->first_ofld_rxq], iter = 0; \
 	    iter < pi->nofldrxq; ++iter, ++q)
+#define for_each_nm_txq(pi, iter, q) \
+	for (q = &pi->adapter->sge.nm_txq[pi->first_nm_txq], iter = 0; \
+	    iter < pi->nnmtxq; ++iter, ++q)
+#define for_each_nm_rxq(pi, iter, q) \
+	for (q = &pi->adapter->sge.nm_rxq[pi->first_nm_rxq], iter = 0; \
+	    iter < pi->nnmrxq; ++iter, ++q)
+
+#define IDXINCR(idx, incr, wrap) do { \
+	idx = wrap - idx > incr ? idx + incr : incr - (wrap - idx); \
+} while (0)
+#define IDXDIFF(head, tail, wrap) \
+	((head) >= (tail) ? (head) - (tail) : (wrap) - (tail) + (head))
 
 /* One for errors, one for firmware events */
 #define T4_EXTRA_INTR 2
@@ -848,6 +983,18 @@ int t4_register_fw_msg_handler(struct ad
 int t4_filter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
 int begin_synchronized_op(struct adapter *, struct port_info *, int, char *);
 void end_synchronized_op(struct adapter *, int);
+int update_mac_settings(struct ifnet *, int);
+int adapter_full_init(struct adapter *);
+int adapter_full_uninit(struct adapter *);
+int port_full_init(struct port_info *);
+int port_full_uninit(struct port_info *);
+
+#ifdef DEV_NETMAP
+/* t4_netmap.c */
+int create_netmap_ifnet(struct port_info *);
+int destroy_netmap_ifnet(struct port_info *);
+void t4_nm_intr(void *);
+#endif
 
 /* t4_sge.c */
 void t4_sge_modload(void);

Modified: stable/10/sys/dev/cxgbe/common/common.h
==============================================================================
--- stable/10/sys/dev/cxgbe/common/common.h	Thu Aug 21 19:51:07 2014	(r270296)
+++ stable/10/sys/dev/cxgbe/common/common.h	Thu Aug 21 19:54:02 2014	(r270297)
@@ -561,11 +561,11 @@ int t4_cfg_pfvf(struct adapter *adap, un
 		unsigned int exactf, unsigned int rcaps, unsigned int wxcaps);
 int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
 		     unsigned int port, unsigned int pf, unsigned int vf,
-		     unsigned int nmac, u8 *mac, unsigned int *rss_size,
+		     unsigned int nmac, u8 *mac, u16 *rss_size,
 		     unsigned int portfunc, unsigned int idstype);
 int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
 		unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
-		unsigned int *rss_size);
+		u16 *rss_size);
 int t4_free_vi(struct adapter *adap, unsigned int mbox,
 	       unsigned int pf, unsigned int vf,
 	       unsigned int viid);
@@ -614,8 +614,10 @@ int t4_sge_ctxt_rd_bd(struct adapter *ad
 int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox);
 int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
 int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox, u32 addr, u32 val);
-int t4_sched_config(struct adapter *adapter, int type, int minmaxen);
+int t4_sched_config(struct adapter *adapter, int type, int minmaxen,
+		    int sleep_ok);
 int t4_sched_params(struct adapter *adapter, int type, int level, int mode,
 		    int rateunit, int ratemode, int channel, int cl,
-		    int minrate, int maxrate, int weight, int pktsize);
+		    int minrate, int maxrate, int weight, int pktsize,
+		    int sleep_ok);
 #endif /* __CHELSIO_COMMON_H */

Modified: stable/10/sys/dev/cxgbe/common/t4_hw.c
==============================================================================
--- stable/10/sys/dev/cxgbe/common/t4_hw.c	Thu Aug 21 19:51:07 2014	(r270296)
+++ stable/10/sys/dev/cxgbe/common/t4_hw.c	Thu Aug 21 19:54:02 2014	(r270297)
@@ -2074,15 +2074,18 @@ static void pcie_intr_handler(struct ada
 
 	int fat;
 
-	fat = t4_handle_intr_status(adapter,
-				    A_PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
-				    sysbus_intr_info) +
-	      t4_handle_intr_status(adapter,
-				    A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
-				    pcie_port_intr_info) +
-	      t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
-				    is_t4(adapter) ?
-				    pcie_intr_info : t5_pcie_intr_info);
+	if (is_t4(adapter))
+		fat = t4_handle_intr_status(adapter,
+					    A_PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+					    sysbus_intr_info) +
+		      t4_handle_intr_status(adapter,
+					    A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+					    pcie_port_intr_info) +
+		      t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
+					    pcie_intr_info);
+	else
+		fat = t4_handle_intr_status(adapter, A_PCIE_INT_CAUSE,
+					    t5_pcie_intr_info);
 	if (fat)
 		t4_fatal_err(adapter);
 }
@@ -2463,9 +2466,15 @@ static void ma_intr_handler(struct adapt
 {
 	u32 v, status = t4_read_reg(adapter, A_MA_INT_CAUSE);
 
-	if (status & F_MEM_PERR_INT_CAUSE)
+	if (status & F_MEM_PERR_INT_CAUSE) {
 		CH_ALERT(adapter, "MA parity error, parity status %#x\n",
-			 t4_read_reg(adapter, A_MA_PARITY_ERROR_STATUS));
+			 t4_read_reg(adapter, A_MA_PARITY_ERROR_STATUS1));
+		if (is_t5(adapter))
+			CH_ALERT(adapter,
+				 "MA parity error, parity status %#x\n",
+				 t4_read_reg(adapter,
+				 	     A_MA_PARITY_ERROR_STATUS2));
+	}
 	if (status & F_MEM_WRAP_INT_CAUSE) {
 		v = t4_read_reg(adapter, A_MA_INT_WRAP_STATUS);
 		CH_ALERT(adapter, "MA address wrap-around error by client %u to"
@@ -2682,10 +2691,8 @@ void t4_intr_clear(struct adapter *adapt
 {
 	static const unsigned int cause_reg[] = {
 		A_SGE_INT_CAUSE1, A_SGE_INT_CAUSE2, A_SGE_INT_CAUSE3,
-		A_PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
-		A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
 		A_PCIE_NONFAT_ERR, A_PCIE_INT_CAUSE,
-		A_MA_INT_WRAP_STATUS, A_MA_PARITY_ERROR_STATUS, A_MA_INT_CAUSE,
+		A_MA_INT_WRAP_STATUS, A_MA_PARITY_ERROR_STATUS1, A_MA_INT_CAUSE,
 		A_EDC_INT_CAUSE, EDC_REG(A_EDC_INT_CAUSE, 1),
 		A_CIM_HOST_INT_CAUSE, A_CIM_HOST_UPACC_INT_CAUSE,
 		MYPF_REG(A_CIM_PF_HOST_INT_CAUSE),
@@ -2707,6 +2714,14 @@ void t4_intr_clear(struct adapter *adapt
 	t4_write_reg(adapter, is_t4(adapter) ? A_MC_INT_CAUSE :
 				A_MC_P_INT_CAUSE, 0xffffffff);
 
+	if (is_t4(adapter)) {
+		t4_write_reg(adapter, A_PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+				0xffffffff);
+		t4_write_reg(adapter, A_PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+				0xffffffff);
+	} else
+		t4_write_reg(adapter, A_MA_PARITY_ERROR_STATUS2, 0xffffffff);
+
 	t4_write_reg(adapter, A_PL_INT_CAUSE, GLBL_INTR_MASK);
 	(void) t4_read_reg(adapter, A_PL_INT_CAUSE);          /* flush */
 }
@@ -4874,7 +4889,7 @@ int t4_cfg_pfvf(struct adapter *adap, un
  */
 int t4_alloc_vi_func(struct adapter *adap, unsigned int mbox,
 		     unsigned int port, unsigned int pf, unsigned int vf,
-		     unsigned int nmac, u8 *mac, unsigned int *rss_size,
+		     unsigned int nmac, u8 *mac, u16 *rss_size,
 		     unsigned int portfunc, unsigned int idstype)
 {
 	int ret;
@@ -4929,7 +4944,7 @@ int t4_alloc_vi_func(struct adapter *ada
  */
 int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port,
 		unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac,
-		unsigned int *rss_size)
+		u16 *rss_size)
 {
 	return t4_alloc_vi_func(adap, mbox, port, pf, vf, nmac, mac, rss_size,
 				FW_VI_FUNC_ETH, 0);
@@ -5671,7 +5686,7 @@ int __devinit t4_port_init(struct port_i
 	u8 addr[6];
 	int ret, i, j;
 	struct fw_port_cmd c;
-	unsigned int rss_size;
+	u16 rss_size;
 	adapter_t *adap = p->adapter;
 
 	memset(&c, 0, sizeof(c));
@@ -5714,7 +5729,8 @@ int __devinit t4_port_init(struct port_i
 	return 0;
 }
 
-int t4_sched_config(struct adapter *adapter, int type, int minmaxen)
+int t4_sched_config(struct adapter *adapter, int type, int minmaxen,
+    		    int sleep_ok)
 {
 	struct fw_sched_cmd cmd;
 
@@ -5729,12 +5745,13 @@ int t4_sched_config(struct adapter *adap
 	cmd.u.config.minmaxen = minmaxen;
 
 	return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd),
-			       NULL, 1);
+			       NULL, sleep_ok);
 }
 
 int t4_sched_params(struct adapter *adapter, int type, int level, int mode,
 		    int rateunit, int ratemode, int channel, int cl,
-		    int minrate, int maxrate, int weight, int pktsize)
+		    int minrate, int maxrate, int weight, int pktsize,
+		    int sleep_ok)
 {
 	struct fw_sched_cmd cmd;
 
@@ -5758,5 +5775,5 @@ int t4_sched_params(struct adapter *adap
 	cmd.u.params.pktsize = cpu_to_be16(pktsize);
 
 	return t4_wr_mbox_meat(adapter,adapter->mbox, &cmd, sizeof(cmd),
-			       NULL, 1);
+			       NULL, sleep_ok);
 }

Modified: stable/10/sys/dev/cxgbe/offload.h
==============================================================================
--- stable/10/sys/dev/cxgbe/offload.h	Thu Aug 21 19:51:07 2014	(r270296)
+++ stable/10/sys/dev/cxgbe/offload.h	Thu Aug 21 19:54:02 2014	(r270297)
@@ -153,6 +153,6 @@ int t4_register_uld(struct uld_info *);
 int t4_unregister_uld(struct uld_info *);
 int t4_activate_uld(struct adapter *, int);
 int t4_deactivate_uld(struct adapter *, int);
+void t4_iscsi_init(struct ifnet *, unsigned int, const unsigned int *);
 #endif
-
 #endif

Modified: stable/10/sys/dev/cxgbe/t4_main.c
==============================================================================
--- stable/10/sys/dev/cxgbe/t4_main.c	Thu Aug 21 19:51:07 2014	(r270296)
+++ stable/10/sys/dev/cxgbe/t4_main.c	Thu Aug 21 19:54:02 2014	(r270297)
@@ -218,6 +218,24 @@ static int t4_nofldrxq1g = -1;
 TUNABLE_INT("hw.cxgbe.nofldrxq1g", &t4_nofldrxq1g);
 #endif
 
+#ifdef DEV_NETMAP
+#define NNMTXQ_10G 2
+static int t4_nnmtxq10g = -1;
+TUNABLE_INT("hw.cxgbe.nnmtxq10g", &t4_nnmtxq10g);
+
+#define NNMRXQ_10G 2
+static int t4_nnmrxq10g = -1;
+TUNABLE_INT("hw.cxgbe.nnmrxq10g", &t4_nnmrxq10g);
+
+#define NNMTXQ_1G 1
+static int t4_nnmtxq1g = -1;
+TUNABLE_INT("hw.cxgbe.nnmtxq1g", &t4_nnmtxq1g);
+
+#define NNMRXQ_1G 1
+static int t4_nnmrxq1g = -1;
+TUNABLE_INT("hw.cxgbe.nnmrxq1g", &t4_nnmrxq1g);
+#endif
+
 /*
  * Holdoff parameters for 10G and 1G ports.
  */
@@ -295,19 +313,26 @@ static int t5_write_combine = 0;
 TUNABLE_INT("hw.cxl.write_combine", &t5_write_combine);
 
 struct intrs_and_queues {
-	int intr_type;		/* INTx, MSI, or MSI-X */
-	int nirq;		/* Number of vectors */
-	int intr_flags;
-	int ntxq10g;		/* # of NIC txq's for each 10G port */
-	int nrxq10g;		/* # of NIC rxq's for each 10G port */
-	int ntxq1g;		/* # of NIC txq's for each 1G port */
-	int nrxq1g;		/* # of NIC rxq's for each 1G port */
-	int rsrv_noflowq;	/* Flag whether to reserve queue 0 */
+	uint16_t intr_type;	/* INTx, MSI, or MSI-X */
+	uint16_t nirq;		/* Total # of vectors */
+	uint16_t intr_flags_10g;/* Interrupt flags for each 10G port */
+	uint16_t intr_flags_1g;	/* Interrupt flags for each 1G port */
+	uint16_t ntxq10g;	/* # of NIC txq's for each 10G port */
+	uint16_t nrxq10g;	/* # of NIC rxq's for each 10G port */
+	uint16_t ntxq1g;	/* # of NIC txq's for each 1G port */
+	uint16_t nrxq1g;	/* # of NIC rxq's for each 1G port */
+	uint16_t rsrv_noflowq;	/* Flag whether to reserve queue 0 */
 #ifdef TCP_OFFLOAD
-	int nofldtxq10g;	/* # of TOE txq's for each 10G port */
-	int nofldrxq10g;	/* # of TOE rxq's for each 10G port */
-	int nofldtxq1g;		/* # of TOE txq's for each 1G port */
-	int nofldrxq1g;		/* # of TOE rxq's for each 1G port */
+	uint16_t nofldtxq10g;	/* # of TOE txq's for each 10G port */
+	uint16_t nofldrxq10g;	/* # of TOE rxq's for each 10G port */
+	uint16_t nofldtxq1g;	/* # of TOE txq's for each 1G port */
+	uint16_t nofldrxq1g;	/* # of TOE rxq's for each 1G port */
+#endif
+#ifdef DEV_NETMAP
+	uint16_t nnmtxq10g;	/* # of netmap txq's for each 10G port */
+	uint16_t nnmrxq10g;	/* # of netmap rxq's for each 10G port */
+	uint16_t nnmtxq1g;	/* # of netmap txq's for each 1G port */
+	uint16_t nnmrxq1g;	/* # of netmap rxq's for each 1G port */
 #endif
 };
 
@@ -321,17 +346,6 @@ struct filter_entry {
         struct t4_filter_specification fs;
 };
 
-enum {
-	XGMAC_MTU	= (1 << 0),
-	XGMAC_PROMISC	= (1 << 1),
-	XGMAC_ALLMULTI	= (1 << 2),
-	XGMAC_VLANEX	= (1 << 3),
-	XGMAC_UCADDR	= (1 << 4),
-	XGMAC_MCADDRS	= (1 << 5),
-
-	XGMAC_ALL	= 0xffff
-};
-
 static int map_bars_0_and_4(struct adapter *);
 static int map_bar_2(struct adapter *);
 static void setup_memwin(struct adapter *);
@@ -350,15 +364,10 @@ static int get_params__pre_init(struct a
 static int get_params__post_init(struct adapter *);
 static int set_params__post_init(struct adapter *);
 static void t4_set_desc(struct adapter *);
-static void build_medialist(struct port_info *);
-static int update_mac_settings(struct port_info *, int);
+static void build_medialist(struct port_info *, struct ifmedia *);
 static int cxgbe_init_synchronized(struct port_info *);
 static int cxgbe_uninit_synchronized(struct port_info *);
 static int setup_intr_handlers(struct adapter *);
-static int adapter_full_init(struct adapter *);
-static int adapter_full_uninit(struct adapter *);
-static int port_full_init(struct port_info *);
-static int port_full_uninit(struct port_info *);
 static void quiesce_eq(struct adapter *, struct sge_eq *);
 static void quiesce_iq(struct adapter *, struct sge_iq *);
 static void quiesce_fl(struct adapter *, struct sge_fl *);
@@ -556,6 +565,9 @@ t4_attach(device_t dev)
 #ifdef TCP_OFFLOAD
 	int ofld_rqidx, ofld_tqidx;
 #endif
+#ifdef DEV_NETMAP
+	int nm_rqidx, nm_tqidx;
+#endif
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
@@ -684,6 +696,13 @@ t4_attach(device_t dev)
 			sc->port[i] = NULL;
 			goto done;
 		}
+		rc = -t4_link_start(sc, sc->mbox, pi->tx_chan, &pi->link_cfg);
+		if (rc != 0) {
+			device_printf(dev, "port %d l1cfg failed: %d\n", i, rc);
+			free(pi, M_CXGBE);
+			sc->port[i] = NULL;
+			goto done;
+		}
 
 		snprintf(pi->lockname, sizeof(pi->lockname), "%sp%d",
 		    device_get_nameunit(dev), i);
@@ -725,7 +744,6 @@ t4_attach(device_t dev)
 
 	sc->intr_type = iaq.intr_type;
 	sc->intr_count = iaq.nirq;
-	sc->flags |= iaq.intr_flags;
 
 	s = &sc->sge;
 	s->nrxq = n10g * iaq.nrxq10g + n1g * iaq.nrxq1g;
@@ -733,10 +751,8 @@ t4_attach(device_t dev)
 	s->neq = s->ntxq + s->nrxq;	/* the free list in an rxq is an eq */
 	s->neq += sc->params.nports + 1;/* ctrl queues: 1 per port + 1 mgmt */
 	s->niq = s->nrxq + 1;		/* 1 extra for firmware event queue */
-
 #ifdef TCP_OFFLOAD
 	if (is_offload(sc)) {
-
 		s->nofldrxq = n10g * iaq.nofldrxq10g + n1g * iaq.nofldrxq1g;
 		s->nofldtxq = n10g * iaq.nofldtxq10g + n1g * iaq.nofldtxq1g;
 		s->neq += s->nofldtxq + s->nofldrxq;
@@ -748,6 +764,17 @@ t4_attach(device_t dev)
 		    M_CXGBE, M_ZERO | M_WAITOK);
 	}
 #endif
+#ifdef DEV_NETMAP
+	s->nnmrxq = n10g * iaq.nnmrxq10g + n1g * iaq.nnmrxq1g;
+	s->nnmtxq = n10g * iaq.nnmtxq10g + n1g * iaq.nnmtxq1g;
+	s->neq += s->nnmtxq + s->nnmrxq;
+	s->niq += s->nnmrxq;
+
+	s->nm_rxq = malloc(s->nnmrxq * sizeof(struct sge_nm_rxq),
+	    M_CXGBE, M_ZERO | M_WAITOK);
+	s->nm_txq = malloc(s->nnmtxq * sizeof(struct sge_nm_txq),
+	    M_CXGBE, M_ZERO | M_WAITOK);
+#endif
 
 	s->ctrlq = malloc(sc->params.nports * sizeof(struct sge_wrq), M_CXGBE,
 	    M_ZERO | M_WAITOK);
@@ -773,6 +800,9 @@ t4_attach(device_t dev)
 #ifdef TCP_OFFLOAD
 	ofld_rqidx = ofld_tqidx = 0;
 #endif
+#ifdef DEV_NETMAP
+	nm_rqidx = nm_tqidx = 0;
+#endif
 	for_each_port(sc, i) {
 		struct port_info *pi = sc->port[i];
 
@@ -782,9 +812,11 @@ t4_attach(device_t dev)
 		pi->first_rxq = rqidx;
 		pi->first_txq = tqidx;
 		if (is_10G_port(pi) || is_40G_port(pi)) {
+			pi->flags |= iaq.intr_flags_10g;
 			pi->nrxq = iaq.nrxq10g;
 			pi->ntxq = iaq.ntxq10g;
 		} else {
+			pi->flags |= iaq.intr_flags_1g;
 			pi->nrxq = iaq.nrxq1g;
 			pi->ntxq = iaq.ntxq1g;
 		}
@@ -796,7 +828,6 @@ t4_attach(device_t dev)
 
 		rqidx += pi->nrxq;
 		tqidx += pi->ntxq;
-
 #ifdef TCP_OFFLOAD
 		if (is_offload(sc)) {
 			pi->first_ofld_rxq = ofld_rqidx;
@@ -812,6 +843,19 @@ t4_attach(device_t dev)
 			ofld_tqidx += pi->nofldtxq;
 		}
 #endif
+#ifdef DEV_NETMAP
+		pi->first_nm_rxq = nm_rqidx;
+		pi->first_nm_txq = nm_tqidx;
+		if (is_10G_port(pi) || is_40G_port(pi)) {
+			pi->nnmrxq = iaq.nnmrxq10g;
+			pi->nnmtxq = iaq.nnmtxq10g;
+		} else {
+			pi->nnmrxq = iaq.nnmrxq1g;
+			pi->nnmtxq = iaq.nnmtxq1g;
+		}
+		nm_rqidx += pi->nnmrxq;
+		nm_tqidx += pi->nnmtxq;
+#endif
 	}
 
 	rc = setup_intr_handlers(sc);
@@ -886,7 +930,7 @@ t4_detach(device_t dev)
 	for (i = 0; i < MAX_NPORTS; i++) {
 		pi = sc->port[i];
 		if (pi) {
-			t4_free_vi(pi->adapter, sc->mbox, sc->pf, 0, pi->viid);
+			t4_free_vi(sc, sc->mbox, sc->pf, 0, pi->viid);
 			if (pi->dev)
 				device_delete_child(dev, pi->dev);
 
@@ -923,6 +967,10 @@ t4_detach(device_t dev)
 	free(sc->sge.ofld_rxq, M_CXGBE);
 	free(sc->sge.ofld_txq, M_CXGBE);
 #endif
+#ifdef DEV_NETMAP
+	free(sc->sge.nm_rxq, M_CXGBE);
+	free(sc->sge.nm_txq, M_CXGBE);
+#endif
 	free(sc->irq, M_CXGBE);
 	free(sc->sge.rxq, M_CXGBE);
 	free(sc->sge.txq, M_CXGBE);
@@ -950,7 +998,6 @@ t4_detach(device_t dev)
 	return (0);
 }
 
-
 static int
 cxgbe_probe(device_t dev)
 {
@@ -973,6 +1020,8 @@ cxgbe_attach(device_t dev)
 {
 	struct port_info *pi = device_get_softc(dev);
 	struct ifnet *ifp;
+	char *s;
+	int n, o;
 
 	/* Allocate an ifnet and set it up */
 	ifp = if_alloc(IFT_ETHER);
@@ -1005,22 +1054,39 @@ cxgbe_attach(device_t dev)
 	/* Initialize ifmedia for this port */
 	ifmedia_init(&pi->media, IFM_IMASK, cxgbe_media_change,
 	    cxgbe_media_status);
-	build_medialist(pi);
+	build_medialist(pi, &pi->media);
 
 	pi->vlan_c = EVENTHANDLER_REGISTER(vlan_config, cxgbe_vlan_config, ifp,
 	    EVENTHANDLER_PRI_ANY);
 
 	ether_ifattach(ifp, pi->hw_addr);
 
+	n = 128;
+	s = malloc(n, M_CXGBE, M_WAITOK);
+	o = snprintf(s, n, "%d txq, %d rxq (NIC)", pi->ntxq, pi->nrxq);
+	MPASS(n > o);
 #ifdef TCP_OFFLOAD
 	if (is_offload(pi->adapter)) {
-		device_printf(dev,
-		    "%d txq, %d rxq (NIC); %d txq, %d rxq (TOE)\n",
-		    pi->ntxq, pi->nrxq, pi->nofldtxq, pi->nofldrxq);
-	} else
+		o += snprintf(s + o, n - o, "; %d txq, %d rxq (TOE)",
+		    pi->nofldtxq, pi->nofldrxq);
+		MPASS(n > o);
+	}
+#endif
+#ifdef DEV_NETMAP
+	o += snprintf(s + o, n - o, "; %d txq, %d rxq (netmap)", pi->nnmtxq,
+	    pi->nnmrxq);
+	MPASS(n > o);
+#endif
+	device_printf(dev, "%s\n", s);
+	free(s, M_CXGBE);
+
+#ifdef DEV_NETMAP
+	/* nm_media handled here to keep implementation private to this file */
+	ifmedia_init(&pi->nm_media, IFM_IMASK, cxgbe_media_change,
+	    cxgbe_media_status);
+	build_medialist(pi, &pi->nm_media);
+	create_netmap_ifnet(pi);	/* logs errors it something fails */
 #endif
-		device_printf(dev, "%d txq, %d rxq\n", pi->ntxq, pi->nrxq);
-
 	cxgbe_sysctls(pi);
 
 	return (0);
@@ -1068,6 +1134,11 @@ cxgbe_detach(device_t dev)
 	ether_ifdetach(pi->ifp);
 	if_free(pi->ifp);
 
+#ifdef DEV_NETMAP
+	/* XXXNM: equivalent of cxgbe_uninit_synchronized to ifdown nm_ifp */
+	destroy_netmap_ifnet(pi);
+#endif
+
 	ADAPTER_LOCK(sc);
 	CLR_BUSY(sc);
 	wakeup(&sc->flags);
@@ -1091,7 +1162,7 @@ cxgbe_init(void *arg)
 static int
 cxgbe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
 {
-	int rc = 0, mtu, flags;
+	int rc = 0, mtu, flags, can_sleep;
 	struct port_info *pi = ifp->if_softc;
 	struct adapter *sc = pi->adapter;
 	struct ifreq *ifr = (struct ifreq *)data;
@@ -1110,13 +1181,16 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned 
 		if (pi->flags & PORT_INIT_DONE) {
 			t4_update_fl_bufsize(ifp);
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-				rc = update_mac_settings(pi, XGMAC_MTU);
+				rc = update_mac_settings(ifp, XGMAC_MTU);
 		}
 		end_synchronized_op(sc, 0);
 		break;
 
 	case SIOCSIFFLAGS:
-		rc = begin_synchronized_op(sc, pi, SLEEP_OK | INTR_OK, "t4flg");
+		can_sleep = 0;
+redo_sifflags:
+		rc = begin_synchronized_op(sc, pi,
+		    can_sleep ? (SLEEP_OK | INTR_OK) : HOLD_LOCK, "t4flg");
 		if (rc)
 			return (rc);
 
@@ -1125,24 +1199,41 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned 
 				flags = pi->if_flags;
 				if ((ifp->if_flags ^ flags) &
 				    (IFF_PROMISC | IFF_ALLMULTI)) {
-					rc = update_mac_settings(pi,
+					if (can_sleep == 1) {
+						end_synchronized_op(sc, 0);
+						can_sleep = 0;
+						goto redo_sifflags;
+					}
+					rc = update_mac_settings(ifp,
 					    XGMAC_PROMISC | XGMAC_ALLMULTI);
 				}
-			} else
+			} else {
+				if (can_sleep == 0) {
+					end_synchronized_op(sc, LOCK_HELD);
+					can_sleep = 1;
+					goto redo_sifflags;
+				}
 				rc = cxgbe_init_synchronized(pi);
+			}
 			pi->if_flags = ifp->if_flags;
-		} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		} else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+			if (can_sleep == 0) {
+				end_synchronized_op(sc, LOCK_HELD);
+				can_sleep = 1;
+				goto redo_sifflags;
+			}
 			rc = cxgbe_uninit_synchronized(pi);
-		end_synchronized_op(sc, 0);
+		}
+		end_synchronized_op(sc, can_sleep ? 0 : LOCK_HELD);
 		break;
 
-	case SIOCADDMULTI:	
+	case SIOCADDMULTI:
 	case SIOCDELMULTI: /* these two are called with a mutex held :-( */
 		rc = begin_synchronized_op(sc, pi, HOLD_LOCK, "t4multi");
 		if (rc)
 			return (rc);
 		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-			rc = update_mac_settings(pi, XGMAC_MCADDRS);
+			rc = update_mac_settings(ifp, XGMAC_MCADDRS);
 		end_synchronized_op(sc, LOCK_HELD);
 		break;
 
@@ -1231,7 +1322,7 @@ cxgbe_ioctl(struct ifnet *ifp, unsigned 
 		if (mask & IFCAP_VLAN_HWTAGGING) {
 			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-				rc = update_mac_settings(pi, XGMAC_VLANEX);
+				rc = update_mac_settings(ifp, XGMAC_VLANEX);
 		}
 		if (mask & IFCAP_VLAN_MTU) {
 			ifp->if_capenable ^= IFCAP_VLAN_MTU;
@@ -1366,13 +1457,23 @@ static void
 cxgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
 {
 	struct port_info *pi = ifp->if_softc;
-	struct ifmedia_entry *cur = pi->media.ifm_cur;
+	struct ifmedia *media = NULL;
+	struct ifmedia_entry *cur;
 	int speed = pi->link_cfg.speed;
 	int data = (pi->port_type << 8) | pi->mod_type;
 
+	if (ifp == pi->ifp)
+		media = &pi->media;
+#ifdef DEV_NETMAP
+	else if (ifp == pi->nm_ifp)
+		media = &pi->nm_media;
+#endif
+	MPASS(media != NULL);
+
+	cur = media->ifm_cur;
 	if (cur->ifm_data != data) {
-		build_medialist(pi);
-		cur = pi->media.ifm_cur;
+		build_medialist(pi, media);
+		cur = media->ifm_cur;
 	}
 
 	ifmr->ifm_status = IFM_AVALID;
@@ -1725,6 +1826,7 @@ cfg_itype_and_nqueues(struct adapter *sc
 {
 	int rc, itype, navail, nrxq10g, nrxq1g, n;
 	int nofldrxq10g = 0, nofldrxq1g = 0;
+	int nnmrxq10g = 0, nnmrxq1g = 0;
 

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408211954.s7LJs321054331>