Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Jan 2017 03:23:22 +0000 (UTC)
From:      Sean Bruno <sbruno@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r311849 - in head: . sys/amd64/conf sys/arm64/conf sys/conf sys/dev/e1000 sys/i386/conf sys/mips/conf sys/modules sys/modules/em sys/modules/igb sys/powerpc/conf
Message-ID:  <201701100323.v0A3NMAI045868@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sbruno
Date: Tue Jan 10 03:23:22 2017
New Revision: 311849
URL: https://svnweb.freebsd.org/changeset/base/311849

Log:
  Migrate e1000 to the IFLIB framework:
  - em(4) igb(4) and lem(4)
  - deprecate the igb device from kernel configurations
  - create a symbolic link in /boot/kernel from if_em.ko to if_igb.ko
  
  Devices tested:
  - 82574L
  - I218-LM
  - 82546GB
  - 82579LM
  - I350
  - I217
  
  Please report problems to freebsd-net@freebsd.org
  
  Partial review from jhb and suggestions on how to *not* brick folks who
  originally would have lost their igbX device.
  
  Submitted by:	mmacy@nextbsd.org
  MFC after:	2 weeks
  Relnotes:	yes
  Sponsored by:	Limelight Networks and Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D8299

Added:
  head/sys/dev/e1000/em_txrx.c   (contents, props changed)
  head/sys/dev/e1000/igb_txrx.c   (contents, props changed)
Deleted:
  head/sys/dev/e1000/if_igb.c
  head/sys/dev/e1000/if_igb.h
  head/sys/dev/e1000/if_lem.c
  head/sys/dev/e1000/if_lem.h
  head/sys/modules/igb/
Modified:
  head/UPDATING
  head/sys/amd64/conf/GENERIC
  head/sys/arm64/conf/GENERIC
  head/sys/conf/NOTES
  head/sys/conf/files
  head/sys/conf/makeLINT.mk
  head/sys/dev/e1000/if_em.c
  head/sys/dev/e1000/if_em.h
  head/sys/i386/conf/GENERIC
  head/sys/mips/conf/OCTEON1
  head/sys/modules/Makefile
  head/sys/modules/em/Makefile
  head/sys/powerpc/conf/GENERIC64

Modified: head/UPDATING
==============================================================================
--- head/UPDATING	Tue Jan 10 01:36:50 2017	(r311848)
+++ head/UPDATING	Tue Jan 10 03:23:22 2017	(r311849)
@@ -51,6 +51,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12
 
 ****************************** SPECIAL WARNING: ******************************
 
+20170109:
+	The igb(4), em(4) and lem(4) ethernet drivers are now implemented via
+	IFLIB.  If you have a custom kernel configuration that excludes em(4)
+	but you use igb(4), you need to re-add em(4) to your custom configuration.
+
 20161217:
 	Clang, llvm, lldb, compiler-rt and libc++ have been upgraded to 3.9.1.
 	Please see the 20141231 entry below for information about prerequisites

Modified: head/sys/amd64/conf/GENERIC
==============================================================================
--- head/sys/amd64/conf/GENERIC	Tue Jan 10 01:36:50 2017	(r311848)
+++ head/sys/amd64/conf/GENERIC	Tue Jan 10 03:23:22 2017	(r311849)
@@ -230,7 +230,6 @@ device		puc			# Multi I/O cards and mult
 device		bxe			# Broadcom NetXtreme II BCM5771X/BCM578XX 10GbE
 device		de			# DEC/Intel DC21x4x (``Tulip'')
 device		em			# Intel PRO/1000 Gigabit Ethernet Family
-device		igb			# Intel PRO/1000 PCIE Server Gigabit Family
 device		ix			# Intel PRO/10GbE PCIE PF Ethernet
 device		ixv			# Intel PRO/10GbE PCIE VF Ethernet
 device		ixl			# Intel XL710 40Gbe PCIE Ethernet

Modified: head/sys/arm64/conf/GENERIC
==============================================================================
--- head/sys/arm64/conf/GENERIC	Tue Jan 10 01:36:50 2017	(r311848)
+++ head/sys/arm64/conf/GENERIC	Tue Jan 10 03:23:22 2017	(r311849)
@@ -120,7 +120,6 @@ device		mii
 device		miibus		# MII bus support
 device		awg		# Allwinner EMAC Gigabit Ethernet
 device		em		# Intel PRO/1000 Gigabit Ethernet Family
-device		igb		# Intel PRO/1000 PCIE Server Gigabit Family
 device		ix		# Intel 10Gb Ethernet Family
 device		msk		# Marvell/SysKonnect Yukon II Gigabit Ethernet
 device  	smc		# SMSC LAN91C111

Modified: head/sys/conf/NOTES
==============================================================================
--- head/sys/conf/NOTES	Tue Jan 10 01:36:50 2017	(r311848)
+++ head/sys/conf/NOTES	Tue Jan 10 03:23:22 2017	(r311849)
@@ -1972,7 +1972,6 @@ device		xmphy		# XaQti XMAC II
 #       KNE110TX.
 # de:   Digital Equipment DC21040
 # em:   Intel Pro/1000 Gigabit Ethernet 82542, 82543, 82544 based adapters.
-# igb:  Intel Pro/1000 PCI Express Gigabit Ethernet: 82575 and later adapters.
 # ep:   3Com 3C509, 3C529, 3C556, 3C562D, 3C563D, 3C572, 3C574X, 3C579, 3C589
 #       and PC Card devices using these chipsets.
 # ex:   Intel EtherExpress Pro/10 and other i82595-based adapters,
@@ -2145,7 +2144,6 @@ device		cxgbe		# Chelsio T4-T6 1/10/25/4
 device		cxgbev		# Chelsio T4-T6 Virtual Functions
 device		de		# DEC/Intel DC21x4x (``Tulip'')
 device		em		# Intel Pro/1000 Gigabit Ethernet
-device		igb		# Intel Pro/1000 PCIE Gigabit Ethernet
 device		ixgb		# Intel Pro/10Gbe PCI-X Ethernet
 device		ix		# Intel Pro/10Gbe PCIE Ethernet
 device		ixv		# Intel Pro/10Gbe PCIE Ethernet VF

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Jan 10 01:36:50 2017	(r311848)
+++ head/sys/conf/files	Tue Jan 10 03:23:22 2017	(r311849)
@@ -1572,43 +1572,43 @@ dev/eisa/eisa_if.m		standard
 dev/eisa/eisaconf.c		optional eisa
 dev/e1000/if_em.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/if_lem.c		optional em \
+dev/e1000/em_txrx.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/if_igb.c		optional igb \
+dev/e1000/igb_txrx.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_80003es2lan.c	optional em | igb \
+dev/e1000/e1000_80003es2lan.c	optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_82540.c		optional em | igb \
+dev/e1000/e1000_82540.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_82541.c		optional em | igb \
+dev/e1000/e1000_82541.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_82542.c		optional em | igb \
+dev/e1000/e1000_82542.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_82543.c		optional em | igb \
+dev/e1000/e1000_82543.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_82571.c		optional em | igb \
+dev/e1000/e1000_82571.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_82575.c		optional em | igb \
+dev/e1000/e1000_82575.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_ich8lan.c	optional em | igb \
+dev/e1000/e1000_ich8lan.c	optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_i210.c		optional em | igb \
+dev/e1000/e1000_i210.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_api.c		optional em | igb \
+dev/e1000/e1000_api.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_mac.c		optional em | igb \
+dev/e1000/e1000_mac.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_manage.c	optional em | igb \
+dev/e1000/e1000_manage.c	optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_nvm.c		optional em | igb \
+dev/e1000/e1000_nvm.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_phy.c		optional em | igb \
+dev/e1000/e1000_phy.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_vf.c		optional em | igb \
+dev/e1000/e1000_vf.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_mbx.c		optional em | igb \
+dev/e1000/e1000_mbx.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
-dev/e1000/e1000_osdep.c		optional em | igb \
+dev/e1000/e1000_osdep.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/et/if_et.c			optional et
 dev/en/if_en_pci.c		optional en pci

Modified: head/sys/conf/makeLINT.mk
==============================================================================
--- head/sys/conf/makeLINT.mk	Tue Jan 10 01:36:50 2017	(r311848)
+++ head/sys/conf/makeLINT.mk	Tue Jan 10 03:23:22 2017	(r311849)
@@ -38,7 +38,6 @@ LINT: ${NOTES} ../../conf/makeLINT.sed
 	echo "nodevice bxe"		>> ${.TARGET}-NOIP
 	echo "nodevice em"		>> ${.TARGET}-NOIP
 	echo "nodevice fxp"		>> ${.TARGET}-NOIP
-	echo "nodevice igb"		>> ${.TARGET}-NOIP
 	echo "nodevice jme"		>> ${.TARGET}-NOIP
 	echo "nodevice msk"		>> ${.TARGET}-NOIP
 	echo "nodevice mxge"		>> ${.TARGET}-NOIP

Added: head/sys/dev/e1000/em_txrx.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/e1000/em_txrx.c	Tue Jan 10 03:23:22 2017	(r311849)
@@ -0,0 +1,720 @@
+/* $FreeBSD$ */
+#include "if_em.h"
+
+#ifdef	RSS
+#include <net/rss_config.h>
+#include <netinet/in_rss.h>
+#endif
+
+#ifdef VERBOSE_DEBUG
+#define DPRINTF device_printf
+#else
+#define DPRINTF(...)
+#endif
+
+/*********************************************************************
+ *  Local Function prototypes
+ *********************************************************************/
+static int em_tso_setup(struct adapter *adapter, if_pkt_info_t pi, u32 *txd_upper, u32 *txd_lower);
+static int em_transmit_checksum_setup(struct adapter *adapter, if_pkt_info_t pi, u32 *txd_upper, u32 *txd_lower);
+static int em_isc_txd_encap(void *arg, if_pkt_info_t pi);
+static void em_isc_txd_flush(void *arg, uint16_t txqid, uint32_t pidx);
+static int em_isc_txd_credits_update(void *arg, uint16_t txqid, uint32_t cidx_init, bool clear);
+static void em_isc_rxd_refill(void *arg, uint16_t rxqid, uint8_t flid __unused,
+			      uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs __unused, uint16_t count, uint16_t buflen __unused);
+static void em_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, uint32_t pidx);
+static int em_isc_rxd_available(void *arg, uint16_t rxqid, uint32_t idx,
+				int budget);
+static int em_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
+
+static void lem_isc_rxd_refill(void *arg, uint16_t rxqid, uint8_t flid __unused,
+			      uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs __unused, uint16_t count, uint16_t buflen __unused);
+
+static int lem_isc_rxd_available(void *arg, uint16_t rxqid, uint32_t idx,
+				int budget);
+static int lem_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
+
+static void lem_receive_checksum(int status, int errors, if_rxd_info_t ri);
+static void em_receive_checksum(uint32_t status, if_rxd_info_t ri);
+extern int em_intr(void *arg);
+
+struct if_txrx em_txrx  = {
+	em_isc_txd_encap,
+	em_isc_txd_flush,
+	em_isc_txd_credits_update,
+	em_isc_rxd_available,
+	em_isc_rxd_pkt_get,
+	em_isc_rxd_refill,
+	em_isc_rxd_flush,
+	em_intr
+};
+
+struct if_txrx lem_txrx  = {
+	em_isc_txd_encap,
+	em_isc_txd_flush,
+	em_isc_txd_credits_update,
+	lem_isc_rxd_available,
+	lem_isc_rxd_pkt_get,
+	lem_isc_rxd_refill,
+	em_isc_rxd_flush,
+	em_intr
+};
+
+extern if_shared_ctx_t em_sctx; 
+
+/**********************************************************************
+ *
+ *  Setup work for hardware segmentation offload (TSO) on
+ *  adapters using advanced tx descriptors
+ *
+ **********************************************************************/
+static int
+em_tso_setup(struct adapter *adapter, if_pkt_info_t pi, u32 *txd_upper, u32 *txd_lower)
+{
+	if_softc_ctx_t scctx = adapter->shared;
+        struct em_tx_queue *que = &adapter->tx_queues[pi->ipi_qsidx];
+        struct tx_ring *txr = &que->txr;
+	struct e1000_context_desc *TXD;
+	struct em_txbuffer  *tx_buffer;
+        int cur, hdr_len;
+
+	hdr_len = pi->ipi_ehdrlen + pi->ipi_ip_hlen + pi->ipi_tcp_hlen;
+  	*txd_lower = (E1000_TXD_CMD_DEXT |	/* Extended descr type */
+		      E1000_TXD_DTYP_D |	/* Data descr type */
+		      E1000_TXD_CMD_TSE);	/* Do TSE on this packet */
+
+	/* IP and/or TCP header checksum calculation and insertion. */
+	*txd_upper = (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
+
+	cur = pi->ipi_pidx;
+        TXD = (struct e1000_context_desc *)&txr->tx_base[cur];
+        tx_buffer = &txr->tx_buffers[cur];
+	
+	 /*
+	 * Start offset for header checksum calculation.
+	 * End offset for header checksum calculation.
+	 * Offset of place put the checksum.
+	 */
+	TXD->lower_setup.ip_fields.ipcss = pi->ipi_ehdrlen;
+	TXD->lower_setup.ip_fields.ipcse =
+	    htole16(pi->ipi_ehdrlen + pi->ipi_ip_hlen - 1);
+	TXD->lower_setup.ip_fields.ipcso = pi->ipi_ehdrlen + offsetof(struct ip, ip_sum);
+
+         /*
+	 * Start offset for payload checksum calculation.
+	 * End offset for payload checksum calculation.
+	 * Offset of place to put the checksum.
+	 */
+	TXD->upper_setup.tcp_fields.tucss = pi->ipi_ehdrlen + pi->ipi_ip_hlen;
+	TXD->upper_setup.tcp_fields.tucse = 0;
+	TXD->upper_setup.tcp_fields.tucso =
+	    pi->ipi_ehdrlen + pi->ipi_ip_hlen + offsetof(struct tcphdr, th_sum);
+	
+         /*
+	 * Payload size per packet w/o any headers.
+	 * Length of all headers up to payload.
+	 */
+	TXD->tcp_seg_setup.fields.mss = htole16(pi->ipi_tso_segsz);
+	TXD->tcp_seg_setup.fields.hdr_len = hdr_len;
+
+	TXD->cmd_and_length = htole32(adapter->txd_cmd |
+				E1000_TXD_CMD_DEXT |	/* Extended descr */
+				E1000_TXD_CMD_TSE |	/* TSE context */
+				E1000_TXD_CMD_IP |	/* Do IP csum */
+				E1000_TXD_CMD_TCP |	/* Do TCP checksum */
+				      (pi->ipi_len - hdr_len)); /* Total len */
+	tx_buffer->eop = -1;
+	txr->tx_tso = TRUE;
+
+	if (++cur == scctx->isc_ntxd[0]) {
+		cur = 0;
+	}
+	DPRINTF(iflib_get_dev(adapter->ctx), "%s: pidx: %d cur: %d\n", __FUNCTION__, pi->ipi_pidx, cur);
+	return (cur);
+}
+
+#define TSO_WORKAROUND 4
+#define DONT_FORCE_CTX 1
+
+
+/*********************************************************************
+ *  The offload context is protocol specific (TCP/UDP) and thus
+ *  only needs to be set when the protocol changes. The occasion
+ *  of a context change can be a performance detriment, and
+ *  might be better just disabled. The reason arises in the way
+ *  in which the controller supports pipelined requests from the
+ *  Tx data DMA. Up to four requests can be pipelined, and they may
+ *  belong to the same packet or to multiple packets. However all
+ *  requests for one packet are issued before a request is issued
+ *  for a subsequent packet and if a request for the next packet
+ *  requires a context change, that request will be stalled
+ *  until the previous request completes. This means setting up
+ *  a new context effectively disables pipelined Tx data DMA which
+ *  in turn greatly slow down performance to send small sized
+ *  frames. 
+ **********************************************************************/
+
+static int
+em_transmit_checksum_setup(struct adapter *adapter, if_pkt_info_t pi, u32 *txd_upper, u32 *txd_lower)
+{
+        struct e1000_context_desc   *TXD = NULL;
+	if_softc_ctx_t              scctx = adapter->shared;
+ 	struct em_tx_queue          *que = &adapter->tx_queues[pi->ipi_qsidx];
+	struct tx_ring              *txr = &que->txr;
+	struct em_txbuffer          *tx_buffer;
+	int                         csum_flags = pi->ipi_csum_flags;
+	int                         cur, hdr_len;
+	u32                         cmd;
+	
+	cur = pi->ipi_pidx;
+	hdr_len = pi->ipi_ehdrlen + pi->ipi_ip_hlen;
+	cmd = adapter->txd_cmd;
+
+	/*
+	 * The 82574L can only remember the *last* context used
+	 * regardless of queue that it was use for.  We cannot reuse
+	 * contexts on this hardware platform and must generate a new
+	 * context every time.  82574L hardware spec, section 7.2.6,
+	 * second note.
+	 */
+	if (DONT_FORCE_CTX &&
+	    adapter->tx_num_queues == 1 &&
+	    txr->csum_lhlen == pi->ipi_ehdrlen &&
+	    txr->csum_iphlen == pi->ipi_ip_hlen &&
+	    txr->csum_flags == csum_flags) {
+		/*
+		 * Same csum offload context as the previous packets;
+		 * just return.
+		 */
+		*txd_upper = txr->csum_txd_upper;
+		*txd_lower = txr->csum_txd_lower;
+		return (cur);
+	}
+
+	TXD = (struct e1000_context_desc *)&txr->tx_base[cur];
+	if (csum_flags & CSUM_IP) {
+	  	*txd_upper |= E1000_TXD_POPTS_IXSM << 8;
+		/*
+		 * Start offset for header checksum calculation.
+		 * End offset for header checksum calculation.
+		 * Offset of place to put the checksum.
+		 */
+		TXD->lower_setup.ip_fields.ipcss = pi->ipi_ehdrlen;
+		TXD->lower_setup.ip_fields.ipcse = htole16(hdr_len);
+		TXD->lower_setup.ip_fields.ipcso = pi->ipi_ehdrlen + offsetof(struct ip, ip_sum);
+		cmd |= E1000_TXD_CMD_IP;
+	}
+
+	if (csum_flags & (CSUM_TCP|CSUM_UDP)) {
+		uint8_t tucso;
+
+ 		*txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+		*txd_lower = E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
+
+		if (csum_flags & CSUM_TCP) {
+			tucso = hdr_len + offsetof(struct tcphdr, th_sum);
+			cmd |= E1000_TXD_CMD_TCP;
+		} else
+			tucso = hdr_len + offsetof(struct udphdr, uh_sum);
+ 		TXD->upper_setup.tcp_fields.tucss = hdr_len;
+ 		TXD->upper_setup.tcp_fields.tucse = htole16(0);
+ 		TXD->upper_setup.tcp_fields.tucso = tucso;
+	}
+
+	txr->csum_lhlen = pi->ipi_ehdrlen;
+	txr->csum_iphlen = pi->ipi_ip_hlen;
+	txr->csum_flags = csum_flags;
+	txr->csum_txd_upper = *txd_upper;
+	txr->csum_txd_lower = *txd_lower;
+
+	TXD->tcp_seg_setup.data = htole32(0);
+	TXD->cmd_and_length =
+		htole32(E1000_TXD_CMD_IFCS | E1000_TXD_CMD_DEXT | cmd);
+
+	tx_buffer = &txr->tx_buffers[cur];
+	tx_buffer->eop = -1;
+
+	if (++cur == scctx->isc_ntxd[0]) {
+		cur = 0;
+	}
+	DPRINTF(iflib_get_dev(adapter->ctx), "checksum_setup csum_flags=%x txd_upper=%x txd_lower=%x hdr_len=%d cmd=%x\n",
+		      csum_flags, *txd_upper, *txd_lower, hdr_len, cmd);
+	return (cur);
+}
+
+static int
+em_isc_txd_encap(void *arg, if_pkt_info_t pi)
+{
+        struct adapter *sc       = arg;
+	if_softc_ctx_t scctx     = sc->shared;
+	struct em_tx_queue *que  = &sc->tx_queues[pi->ipi_qsidx];
+	struct tx_ring *txr      = &que->txr;
+	bus_dma_segment_t *segs  = pi->ipi_segs;
+	int nsegs                = pi->ipi_nsegs;
+	int csum_flags           = pi->ipi_csum_flags;
+        int i, j, first, pidx_last; 
+	u32                     txd_upper = 0, txd_lower = 0; 
+	
+	struct em_txbuffer *tx_buffer;
+	struct e1000_tx_desc *ctxd = NULL;
+	bool do_tso, tso_desc; 
+	
+	i = first = pi->ipi_pidx;         
+	do_tso = (csum_flags & CSUM_TSO);
+	tso_desc = FALSE;
+           /*
+	 * TSO Hardware workaround, if this packet is not
+	 * TSO, and is only a single descriptor long, and
+	 * it follows a TSO burst, then we need to add a
+	 * sentinel descriptor to prevent premature writeback.
+	 */
+	if ((!do_tso) && (txr->tx_tso == TRUE)) {
+		if (nsegs == 1)
+			tso_desc = TRUE;
+		txr->tx_tso = FALSE;
+	}
+
+	/* Do hardware assists */
+	if (do_tso) {
+		i = em_tso_setup(sc, pi, &txd_upper, &txd_lower);
+		tso_desc = TRUE;
+	} else if (csum_flags & CSUM_OFFLOAD) {
+		i = em_transmit_checksum_setup(sc, pi, &txd_upper, &txd_lower);
+	}
+
+	if (pi->ipi_mflags & M_VLANTAG) {
+	  /* Set the vlan id. */
+		txd_upper |= htole16(pi->ipi_vtag) << 16;
+                /* Tell hardware to add tag */
+                txd_lower |= htole32(E1000_TXD_CMD_VLE);
+	}
+
+	DPRINTF(iflib_get_dev(sc->ctx), "encap: set up tx: nsegs=%d first=%d i=%d\n", nsegs, first, i);
+	/* XXX adapter->pcix_82544 -- lem_fill_descriptors */
+
+	/* Set up our transmit descriptors */
+	for (j = 0; j < nsegs; j++) {
+		bus_size_t seg_len;
+		bus_addr_t seg_addr;
+		uint32_t cmd;
+
+		ctxd = &txr->tx_base[i];
+		tx_buffer = &txr->tx_buffers[i];
+		seg_addr = segs[j].ds_addr;
+		seg_len = segs[j].ds_len;
+		cmd = E1000_TXD_CMD_IFCS | sc->txd_cmd;
+
+		/*
+		** TSO Workaround:
+		** If this is the last descriptor, we want to
+		** split it so we have a small final sentinel
+		*/
+		if (tso_desc && (j == (nsegs - 1)) && (seg_len > 8)) {
+			seg_len -= TSO_WORKAROUND;
+			ctxd->buffer_addr = htole64(seg_addr);
+			ctxd->lower.data = htole32(cmd | txd_lower | seg_len);
+			ctxd->upper.data = htole32(txd_upper);
+
+                        if (++i == scctx->isc_ntxd[0])
+				i = 0;
+
+			/* Now make the sentinel */
+			ctxd = &txr->tx_base[i];
+			tx_buffer = &txr->tx_buffers[i];
+			ctxd->buffer_addr = htole64(seg_addr + seg_len);
+			ctxd->lower.data = htole32(cmd | txd_lower | TSO_WORKAROUND);
+			ctxd->upper.data = htole32(txd_upper);
+			pidx_last = i;
+			if (++i == scctx->isc_ntxd[0])
+				i = 0;
+			DPRINTF(iflib_get_dev(sc->ctx), "TSO path pidx_last=%d i=%d ntxd[0]=%d\n", pidx_last, i, scctx->isc_ntxd[0]);
+		} else {
+			ctxd->buffer_addr = htole64(seg_addr);
+			ctxd->lower.data = htole32(cmd | txd_lower | seg_len);
+			ctxd->upper.data = htole32(txd_upper);
+			pidx_last = i;
+			if (++i == scctx->isc_ntxd[0])
+				i = 0;
+			DPRINTF(iflib_get_dev(sc->ctx), "pidx_last=%d i=%d ntxd[0]=%d\n", pidx_last, i, scctx->isc_ntxd[0]);
+		}
+		tx_buffer->eop = -1;
+	}
+
+	/*
+         * Last Descriptor of Packet
+	 * needs End Of Packet (EOP)
+	 * and Report Status (RS)
+         */
+        ctxd->lower.data |=
+		htole32(E1000_TXD_CMD_EOP | E1000_TXD_CMD_RS);
+
+	tx_buffer = &txr->tx_buffers[first];
+	tx_buffer->eop = pidx_last;
+	DPRINTF(iflib_get_dev(sc->ctx), "tx_buffers[%d]->eop = %d ipi_new_pidx=%d\n", first, pidx_last, i);
+	pi->ipi_new_pidx = i;
+
+	return (0); 
+}
+
+static void
+em_isc_txd_flush(void *arg, uint16_t txqid, uint32_t pidx)
+{
+	struct adapter *adapter = arg;
+	struct em_tx_queue *que = &adapter->tx_queues[txqid];
+	struct tx_ring *txr = &que->txr;
+
+	E1000_WRITE_REG(&adapter->hw, E1000_TDT(txr->me), pidx);
+}
+
+static int
+em_isc_txd_credits_update(void *arg, uint16_t txqid, uint32_t cidx_init, bool clear)
+{
+	struct adapter *adapter = arg;
+	if_softc_ctx_t scctx = adapter->shared;
+	struct em_tx_queue *que = &adapter->tx_queues[txqid];
+	struct tx_ring *txr = &que->txr;
+
+	u32 cidx, processed = 0;
+	int last, done;
+	struct em_txbuffer *buf;
+	struct e1000_tx_desc *tx_desc, *eop_desc;
+
+	cidx = cidx_init;
+	buf = &txr->tx_buffers[cidx];
+	tx_desc = &txr->tx_base[cidx];
+        last = buf->eop;
+	eop_desc = &txr->tx_base[last];
+
+	DPRINTF(iflib_get_dev(adapter->ctx), "credits_update: cidx_init=%d clear=%d last=%d\n",
+		      cidx_init, clear, last);
+	/*
+	 * What this does is get the index of the
+	 * first descriptor AFTER the EOP of the
+	 * first packet, that way we can do the
+	 * simple comparison on the inner while loop.
+	 */
+	if (++last == scctx->isc_ntxd[0])
+	     last = 0;
+	done = last;
+
+
+	while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) {
+		/* We clean the range of the packet */
+		while (cidx != done) {
+			if (clear) {
+				tx_desc->upper.data = 0;
+				tx_desc->lower.data = 0;
+				tx_desc->buffer_addr = 0;
+				buf->eop = -1;
+			}
+			tx_desc++;
+			buf++;
+			processed++;
+		  
+			/* wrap the ring ? */
+			if (++cidx == scctx->isc_ntxd[0]) {
+				cidx = 0;
+			}
+			buf = &txr->tx_buffers[cidx];
+			tx_desc = &txr->tx_base[cidx];
+		}
+		/* See if we can continue to the next packet */
+		last = buf->eop;
+		if (last == -1)
+			break;
+		eop_desc = &txr->tx_base[last];
+		/* Get new done point */
+		if (++last == scctx->isc_ntxd[0])
+			last = 0;
+		done = last;
+	}
+
+	DPRINTF(iflib_get_dev(adapter->ctx), "Processed %d credits update\n", processed);
+	return(processed);
+}
+
+static void
+lem_isc_rxd_refill(void *arg, uint16_t rxqid, uint8_t flid __unused,
+		  uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs __unused, uint16_t count, uint16_t buflen __unused)
+{
+	struct adapter *sc = arg;
+	if_softc_ctx_t scctx = sc->shared;
+	struct em_rx_queue *que = &sc->rx_queues[rxqid];
+	struct rx_ring *rxr = &que->rxr;
+	struct e1000_rx_desc *rxd;
+	int i;
+	uint32_t next_pidx;
+
+	for (i = 0, next_pidx = pidx; i < count; i++) {
+		rxd = (struct e1000_rx_desc *)&rxr->rx_base[next_pidx];
+		rxd->buffer_addr = htole64(paddrs[i]);
+		/* status bits must be cleared */
+		rxd->status = 0;
+
+		if (++next_pidx == scctx->isc_nrxd[0])
+			next_pidx = 0;
+	}
+}
+
+static void
+em_isc_rxd_refill(void *arg, uint16_t rxqid, uint8_t flid __unused,
+		  uint32_t pidx, uint64_t *paddrs, caddr_t *vaddrs __unused, uint16_t count, uint16_t buflen __unused)
+{
+	struct adapter *sc = arg;
+	if_softc_ctx_t scctx = sc->shared;
+	struct em_rx_queue *que = &sc->rx_queues[rxqid];
+	struct rx_ring *rxr = &que->rxr;
+	union e1000_rx_desc_extended *rxd;
+	int i;
+	uint32_t next_pidx;
+
+	for (i = 0, next_pidx = pidx; i < count; i++) {
+		rxd = &rxr->rx_base[next_pidx];
+		rxd->read.buffer_addr = htole64(paddrs[i]);
+		/* DD bits must be cleared */
+		rxd->wb.upper.status_error = 0; 
+	
+		if (++next_pidx == scctx->isc_nrxd[0])
+			next_pidx = 0;
+	}
+}
+
+static void
+em_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, uint32_t pidx)
+{
+    	struct adapter *sc       = arg;
+	struct em_rx_queue *que     = &sc->rx_queues[rxqid];
+	struct rx_ring *rxr      = &que->rxr;
+
+        E1000_WRITE_REG(&sc->hw, E1000_RDT(rxr->me), pidx);
+}
+
+static int
+lem_isc_rxd_available(void *arg, uint16_t rxqid, uint32_t idx, int budget)
+{
+	struct adapter *sc         = arg;
+	if_softc_ctx_t scctx = sc->shared;
+	struct em_rx_queue *que   = &sc->rx_queues[rxqid];
+	struct rx_ring *rxr        = &que->rxr;
+	struct e1000_rx_desc *rxd;
+	u32                      staterr = 0;
+	int                      cnt, i;
+
+	for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
+		rxd = (struct e1000_rx_desc *)&rxr->rx_base[i];
+		staterr = rxd->status;
+
+		if ((staterr & E1000_RXD_STAT_DD) == 0)
+			break;
+
+		if (++i == scctx->isc_nrxd[0])
+			i = 0;
+
+		if (staterr & E1000_RXD_STAT_EOP)
+			cnt++;
+	}
+	return (cnt);
+}
+
+static int
+em_isc_rxd_available(void *arg, uint16_t rxqid, uint32_t idx, int budget)
+{
+       	struct adapter *sc         = arg;
+	if_softc_ctx_t scctx = sc->shared;
+	struct em_rx_queue *que   = &sc->rx_queues[rxqid];
+	struct rx_ring *rxr        = &que->rxr;
+	union e1000_rx_desc_extended *rxd;
+	u32                      staterr = 0;
+	int                      cnt, i;
+
+	for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
+		rxd = &rxr->rx_base[i];
+		staterr = le32toh(rxd->wb.upper.status_error);
+
+		if ((staterr & E1000_RXD_STAT_DD) == 0)
+			break;
+		
+		if (++i == scctx->isc_nrxd[0]) {
+			i = 0;
+		}
+
+		if (staterr & E1000_RXD_STAT_EOP)
+			cnt++;
+
+	}
+	return (cnt);
+}
+
+static int
+lem_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
+{
+	struct adapter           *adapter = arg;
+	if_softc_ctx_t           scctx = adapter->shared;
+	struct em_rx_queue       *que = &adapter->rx_queues[ri->iri_qsidx];
+	struct rx_ring           *rxr = &que->rxr;
+	struct e1000_rx_desc *rxd;
+	u16                      len;
+	u32                      status, errors;
+	bool                     eop;
+	int                      i, cidx;
+
+	status = errors = i = 0;
+	cidx = ri->iri_cidx;
+
+	do {
+		rxd = (struct e1000_rx_desc *)&rxr->rx_base[cidx];
+		status = rxd->status;
+		errors = rxd->errors;
+
+		/* Error Checking then decrement count */
+		MPASS ((status & E1000_RXD_STAT_DD) != 0);
+
+		len = le16toh(rxd->length);
+		ri->iri_len += len;
+
+		eop = (status & E1000_RXD_STAT_EOP) != 0;
+
+		/* Make sure bad packets are discarded */
+		if (errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
+			adapter->dropped_pkts++;
+			/* XXX fixup if common */
+			return (EBADMSG);
+		}
+
+		ri->iri_frags[i].irf_flid = 0;
+		ri->iri_frags[i].irf_idx = cidx;
+		ri->iri_frags[i].irf_len = len;
+		/* Zero out the receive descriptors status. */
+		rxd->status = 0;
+
+		if (++cidx == scctx->isc_nrxd[0])
+			cidx = 0;
+		i++;
+	} while (!eop);
+
+	/* XXX add a faster way to look this up */
+	if (adapter->hw.mac.type >= e1000_82543 && !(status & E1000_RXD_STAT_IXSM))
+		lem_receive_checksum(status, errors, ri);
+
+	if (status & E1000_RXD_STAT_VP) {
+		ri->iri_vtag = le16toh(rxd->special);
+		ri->iri_flags |= M_VLANTAG;
+	}
+
+	ri->iri_nfrags = i;
+
+	return (0);
+}
+
+static int
+em_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
+{
+      	struct adapter           *adapter = arg;
+	if_softc_ctx_t           scctx = adapter->shared;
+	struct em_rx_queue       *que = &adapter->rx_queues[ri->iri_qsidx];
+	struct rx_ring           *rxr = &que->rxr;
+	union e1000_rx_desc_extended *rxd;
+
+	u16                      len; 
+	u32                      staterr = 0;
+	bool                     eop;
+	int                      i, cidx, vtag;
+
+	i = vtag = 0;
+	cidx = ri->iri_cidx;
+
+	do {
+		rxd = &rxr->rx_base[cidx];
+		staterr = le32toh(rxd->wb.upper.status_error);	
+	
+		/* Error Checking then decrement count */
+		MPASS ((staterr & E1000_RXD_STAT_DD) != 0);
+
+		len = le16toh(rxd->wb.upper.length);
+		ri->iri_len += len; 
+
+		eop = (staterr & E1000_RXD_STAT_EOP) != 0;
+
+		/* Make sure bad packets are discarded */
+		if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
+			adapter->dropped_pkts++;
+			return EBADMSG;
+		}
+
+		ri->iri_frags[i].irf_flid = 0;
+		ri->iri_frags[i].irf_idx = cidx;
+		ri->iri_frags[i].irf_len = len;
+		/* Zero out the receive descriptors status. */
+		rxd->wb.upper.status_error &= htole32(~0xFF);
+
+		if (++cidx == scctx->isc_nrxd[0])
+			cidx = 0;
+		i++;
+	} while (!eop);
+
+	/* XXX add a faster way to look this up */
+	if (adapter->hw.mac.type >= e1000_82543)
+		em_receive_checksum(staterr, ri);
+
+	if (staterr & E1000_RXD_STAT_VP) {
+		vtag = le16toh(rxd->wb.upper.vlan);
+	} 
+	
+	ri->iri_vtag = vtag;
+	ri->iri_nfrags = i;
+	if (vtag)
+		ri->iri_flags |= M_VLANTAG;
+		
+	return (0);
+}
+
+/*********************************************************************
+ *
+ *  Verify that the hardware indicated that the checksum is valid.
+ *  Inform the stack about the status of checksum so that stack
+ *  doesn't spend time verifying the checksum.
+ *
+ *********************************************************************/
+static void
+lem_receive_checksum(int status, int errors, if_rxd_info_t ri)
+{
+	/* Did it pass? */
+	if (status & E1000_RXD_STAT_IPCS && !(errors & E1000_RXD_ERR_IPE))
+		ri->iri_csum_flags = (CSUM_IP_CHECKED|CSUM_IP_VALID);
+
+	if (status & E1000_RXD_STAT_TCPCS) {
+		/* Did it pass? */
+		if (!(errors & E1000_RXD_ERR_TCPE)) {
+			ri->iri_csum_flags |=
+			(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+			ri->iri_csum_data = htons(0xffff);
+		}
+	}
+}
+
+static void
+em_receive_checksum(uint32_t status, if_rxd_info_t ri)
+{
+	ri->iri_csum_flags = 0;
+
+	/* Ignore Checksum bit is set */
+	if (status & E1000_RXD_STAT_IXSM)
+		return;
+
+	/* If the IP checksum exists and there is no IP Checksum error */
+	if ((status & (E1000_RXD_STAT_IPCS | E1000_RXDEXT_STATERR_IPE)) ==
+		E1000_RXD_STAT_IPCS) {
+		ri->iri_csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID);
+	}
+
+	/* TCP or UDP checksum */
+	if ((status & (E1000_RXD_STAT_TCPCS | E1000_RXDEXT_STATERR_TCPE)) ==
+	    E1000_RXD_STAT_TCPCS) {
+		ri->iri_csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+		ri->iri_csum_data = htons(0xffff);
+	}
+	if (status & E1000_RXD_STAT_UDPCS) {
+		ri->iri_csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+		ri->iri_csum_data = htons(0xffff);
+	}
+}

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c	Tue Jan 10 01:36:50 2017	(r311848)
+++ head/sys/dev/e1000/if_em.c	Tue Jan 10 03:23:22 2017	(r311849)
@@ -1,99 +1,10 @@
-/******************************************************************************
-
-  Copyright (c) 2001-2015, Intel Corporation 
-  All rights reserved.
-  
-  Redistribution and use in source and binary forms, with or without 
-  modification, are permitted provided that the following conditions are met:
-  
-   1. Redistributions of source code must retain the above copyright notice, 
-      this list of conditions and the following disclaimer.
-  
-   2. Redistributions in binary form must reproduce the above copyright 
-      notice, this list of conditions and the following disclaimer in the 
-      documentation and/or other materials provided with the distribution.
-  
-   3. Neither the name of the Intel Corporation nor the names of its 
-      contributors may be used to endorse or promote products derived from 
-      this software without specific prior written permission.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
-  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-  POSSIBILITY OF SUCH DAMAGE.
-
-******************************************************************************/
-/*$FreeBSD$*/
-
-#include "opt_em.h"
-#include "opt_ddb.h"
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#ifdef HAVE_KERNEL_OPTION_HEADERS
-#include "opt_device_polling.h"
-#endif
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#ifdef DDB
-#include <sys/types.h>
-#include <ddb/ddb.h>
-#endif
-#if __FreeBSD_version >= 800000
-#include <sys/buf_ring.h>
-#endif
-#include <sys/bus.h>
-#include <sys/endian.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/smp.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/taskqueue.h>
-#include <sys/eventhandler.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-
-#include <net/bpf.h>
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_var.h>
-#include <net/if_arp.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-
-#include <net/if_types.h>
-#include <net/if_vlan_var.h>
-
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-
-#include <machine/in_cksum.h>
-#include <dev/led/led.h>
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
-
-#include "e1000_api.h"
-#include "e1000_82571.h"
+/* $FreeBSD$ */
 #include "if_em.h"
+#include <sys/sbuf.h>
+#include <machine/_inttypes.h>
+
+#define em_mac_min e1000_82547
+#define igb_mac_min e1000_82575
 
 /*********************************************************************
  *  Driver version:
@@ -110,184 +21,213 @@ char em_driver_version[] = "7.6.1-k";
  *  { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
  *********************************************************************/
 
-static em_vendor_info_t em_vendor_info_array[] =
+static pci_vendor_info_t em_vendor_info_array[] =
 {
-	/* Intel(R) PRO/1000 Network Connection */
-	{ 0x8086, E1000_DEV_ID_82571EB_COPPER,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571EB_FIBER,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571EB_SERDES,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571EB_SERDES_DUAL,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571EB_SERDES_QUAD,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571EB_QUAD_COPPER_LP,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571EB_QUAD_FIBER,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82571PT_QUAD_COPPER,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82572EI_COPPER,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82572EI_FIBER,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82572EI_SERDES,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82572EI,		PCI_ANY_ID, PCI_ANY_ID, 0},
-
-	{ 0x8086, E1000_DEV_ID_82573E,		PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82573E_IAMT,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82573L,		PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_82583V,		PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_80003ES2LAN_COPPER_SPT,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_80003ES2LAN_SERDES_SPT,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_80003ES2LAN_COPPER_DPT,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_80003ES2LAN_SERDES_DPT,
-						PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_ICH8_IGP_M_AMT,	PCI_ANY_ID, PCI_ANY_ID, 0},
-	{ 0x8086, E1000_DEV_ID_ICH8_IGP_AMT,	PCI_ANY_ID, PCI_ANY_ID, 0},

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



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