Module Name:    src
Committed By:   msaitoh
Date:           Fri Dec  2 10:42:04 UTC 2016

Modified Files:
        src/sys/dev/pci/ixgbe: ix_txrx.c ixgbe.c ixgbe.h ixgbe_82598.c
            ixgbe_82599.c ixgbe_api.c ixgbe_api.h ixgbe_common.c ixgbe_dcb.c
            ixgbe_mbx.h ixgbe_osdep.h ixgbe_phy.c ixgbe_phy.h ixgbe_type.h
            ixgbe_vf.c ixgbe_x540.c ixgbe_x550.c ixgbe_x550.h ixv.c
Added Files:
        src/sys/dev/pci/ixgbe: ixgbe_osdep.c
Removed Files:
        src/sys/dev/pci/ixgbe: LICENSE README

Log Message:
Update ixg(4) and ixv(4) up to FreeBSD r292674:
- Add X552 SFP+ and X550T single port.
- Bug fixes.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r0 src/sys/dev/pci/ixgbe/LICENSE
cvs rdiff -u -r1.2 -r0 src/sys/dev/pci/ixgbe/README
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/pci/ixgbe/ix_txrx.c \
    src/sys/dev/pci/ixgbe/ixgbe_82598.c src/sys/dev/pci/ixgbe/ixgbe_phy.h
cvs rdiff -u -r1.47 -r1.48 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/pci/ixgbe/ixgbe.h \
    src/sys/dev/pci/ixgbe/ixgbe_type.h
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/pci/ixgbe/ixgbe_82599.c \
    src/sys/dev/pci/ixgbe/ixgbe_api.c src/sys/dev/pci/ixgbe/ixgbe_osdep.h
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/pci/ixgbe/ixgbe_api.h \
    src/sys/dev/pci/ixgbe/ixgbe_phy.c
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/pci/ixgbe/ixgbe_common.c \
    src/sys/dev/pci/ixgbe/ixgbe_mbx.h
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/ixgbe/ixgbe_dcb.c
cvs rdiff -u -r0 -r1.1 src/sys/dev/pci/ixgbe/ixgbe_osdep.c
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/pci/ixgbe/ixgbe_vf.c
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/pci/ixgbe/ixgbe_x540.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/pci/ixgbe/ixgbe_x550.c \
    src/sys/dev/pci/ixgbe/ixgbe_x550.h
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/pci/ixgbe/ixv.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ixgbe/ix_txrx.c
diff -u src/sys/dev/pci/ixgbe/ix_txrx.c:1.7 src/sys/dev/pci/ixgbe/ix_txrx.c:1.8
--- src/sys/dev/pci/ixgbe/ix_txrx.c:1.7	Fri Dec  2 10:34:23 2016
+++ src/sys/dev/pci/ixgbe/ix_txrx.c	Fri Dec  2 10:42:04 2016
@@ -58,8 +58,11 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-/*$FreeBSD: head/sys/dev/ixgbe/ix_txrx.c 289238 2015-10-13 17:34:18Z sbruno $*/
-/*$NetBSD: ix_txrx.c,v 1.7 2016/12/02 10:34:23 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ix_txrx.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ix_txrx.c,v 1.8 2016/12/02 10:42:04 msaitoh Exp $*/
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
 
 #include "ixgbe.h"
 
@@ -98,48 +101,6 @@ static bool ixgbe_rsc_enable = FALSE;
 static int atr_sample_rate = 20;
 #endif
 
-/* Shared PCI config read/write */
-u16
-ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg)
-{
-	switch (reg % 4) {
-	case 0:
-		return pci_conf_read(hw->back->pc, hw->back->tag, reg) &
-		    __BITS(15, 0);
-	case 2:
-		return __SHIFTOUT(pci_conf_read(hw->back->pc, hw->back->tag,
-		    reg - 2), __BITS(31, 16));
-	default:
-		panic("%s: invalid register (%" PRIx32, __func__, reg); 
-		break;
-	}
-}
-
-void
-ixgbe_write_pci_cfg(struct ixgbe_hw *hw, u32 reg, u16 value)
-{
-	pcireg_t old;
-
-	switch (reg % 4) {
-	case 0:
-		old = pci_conf_read(hw->back->pc, hw->back->tag, reg) &
-		    __BITS(31, 16);
-		pci_conf_write(hw->back->pc, hw->back->tag, reg, value | old);
-		break;
-	case 2:
-		old = pci_conf_read(hw->back->pc, hw->back->tag, reg - 2) &
-		    __BITS(15, 0);
-		pci_conf_write(hw->back->pc, hw->back->tag, reg - 2,
-		    __SHIFTIN(value, __BITS(31, 16)) | old);
-		break;
-	default:
-		panic("%s: invalid register (%" PRIx32, __func__, reg); 
-		break;
-	}
-
-	return;
-}
-
 /*********************************************************************
  *  Local Function prototypes
  *********************************************************************/
@@ -246,8 +207,8 @@ ixgbe_start(struct ifnet *ifp)
 #else /* ! IXGBE_LEGACY_TX */
 
 /*
-** Multiqueue Transmit driver
-**
+** Multiqueue Transmit Entry Point
+** (if_transmit function)
 */
 int
 ixgbe_mq_start(struct ifnet *ifp, struct mbuf *m)
@@ -267,13 +228,22 @@ ixgbe_mq_start(struct ifnet *ifp, struct
 	 * If everything is setup correctly, it should be the
 	 * same bucket that the current CPU we're on is.
 	 */
+#if __FreeBSD_version < 1100054
+	if (m->m_flags & M_FLOWID) {
+#else
 	if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
+#endif
 #ifdef	RSS
 		if (rss_hash2bucket(m->m_pkthdr.flowid,
-		    M_HASHTYPE_GET(m), &bucket_id) == 0)
+		    M_HASHTYPE_GET(m), &bucket_id) == 0) {
 			/* TODO: spit out something if bucket_id > num_queues? */
 			i = bucket_id % adapter->num_queues;
-		else
+#ifdef IXGBE_DEBUG
+			if (bucket_id > adapter->num_queues)
+				if_printf(ifp, "bucket_id (%d) > num_queues "
+				    "(%d)\n", bucket_id, adapter->num_queues);
+#endif
+		} else
 #endif
 			i = m->m_pkthdr.flowid % adapter->num_queues;
 	} else
@@ -489,6 +459,7 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 	}
 #endif
 
+	olinfo_status |= IXGBE_ADVTXD_CC;
 	i = txr->next_avail_desc;
 	for (j = 0; j < map->dm_nsegs; j++) {
 		bus_size_t seglen;
@@ -777,15 +748,21 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
 	struct m_tag *mtag;
 	struct ixgbe_adv_tx_context_desc *TXD;
 	struct ether_vlan_header *eh;
-	struct ip ip;
-	struct ip6_hdr ip6;
+#ifdef INET
+	struct ip *ip;
+#endif
+#ifdef INET6
+	struct ip6_hdr *ip6;
+#endif
 	u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
 	int	ehdrlen, ip_hlen = 0;
 	u16	etype;
-	u8	ipproto __diagused = 0;
+	u8	ipproto = 0;
 	int	offload = TRUE;
 	int	ctxd = txr->next_avail_desc;
 	u16	vtag = 0;
+	char	*l3d;
+
 
 	/* First check if TSO is to be used */
 	if (mp->m_pkthdr.csum_flags & (M_CSUM_TSOv4|M_CSUM_TSOv6))
@@ -833,25 +810,29 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
 	if (offload == FALSE)
 		goto no_offloads;
 
+	/*
+	 * If the first mbuf only includes the ethernet header, jump to the next one
+	 * XXX: This assumes the stack splits mbufs containing headers on header boundaries
+	 * XXX: And assumes the entire IP header is contained in one mbuf
+	 */
+	if (mp->m_len == ehdrlen && mp->m_next)
+		l3d = mtod(mp->m_next, char *);
+	else
+		l3d = mtod(mp, char *) + ehdrlen;
+
 	switch (etype) {
 	case ETHERTYPE_IP:
-		m_copydata(mp, ehdrlen, sizeof(ip), &ip);
-		ip_hlen = ip.ip_hl << 2;
-		ipproto = ip.ip_p;
-#if 0
-		ip.ip_sum = 0;
-		m_copyback(mp, ehdrlen, sizeof(ip), &ip);
-#else
-		KASSERT((mp->m_pkthdr.csum_flags & M_CSUM_IPv4) == 0 ||
-		    ip.ip_sum == 0);
-#endif
+		ip = (struct ip *)(l3d);
+		ip_hlen = ip->ip_hl << 2;
+		ipproto = ip->ip_p;
 		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
+		KASSERT((mp->m_pkthdr.csum_flags & M_CSUM_IPv4) == 0 ||
+		    ip->ip_sum == 0);
 		break;
 	case ETHERTYPE_IPV6:
-		m_copydata(mp, ehdrlen, sizeof(ip6), &ip6);
-		ip_hlen = sizeof(ip6);
-		/* XXX-BZ this will go badly in case of ext hdrs. */
-		ipproto = ip6.ip6_nxt;
+		ip6 = (struct ip6_hdr *)(l3d);
+		ip_hlen = sizeof(struct ip6_hdr);
+		ipproto = ip6->ip6_nxt;
 		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
 		break;
 	default:
@@ -863,16 +844,26 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
 
 	vlan_macip_lens |= ip_hlen;
 
-	if (mp->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_TCPv6)) {
-		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
-		*olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-		KASSERT(ipproto == IPPROTO_TCP);
-	} else if (mp->m_pkthdr.csum_flags & (M_CSUM_UDPv4|M_CSUM_UDPv6)) {
-		type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
-		*olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-		KASSERT(ipproto == IPPROTO_UDP);
+	/* No support for offloads for non-L4 next headers */
+ 	switch (ipproto) {
+ 		case IPPROTO_TCP:
+			if (mp->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_TCPv6))
+
+				type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+			else
+				offload = false;
+			break;
+		case IPPROTO_UDP:
+			if (mp->m_pkthdr.csum_flags & (M_CSUM_UDPv4|M_CSUM_UDPv6))
+				type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
+			else
+				offload = false;
+			break;
 	}
 
+	if (offload) /* Insert L4 checksum into data descriptors */
+		*olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
+
 no_offloads:
 	type_tucmd_mlhl |= IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT;
 
@@ -918,7 +909,6 @@ ixgbe_tso_setup(struct tx_ring *txr, str
 #endif
 	struct tcphdr *th;
 
-
 	/*
 	 * Determine where frame payload starts.
 	 * Jump over vlan headers if already present
@@ -1072,8 +1062,9 @@ ixgbe_txeof(struct tx_ring *txr)
 	work -= txr->num_desc; /* The distance to ring end */
         ixgbe_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
 	    BUS_DMASYNC_POSTREAD);
+
 	do {
-		union ixgbe_adv_tx_desc *eop= buf->eop;
+		union ixgbe_adv_tx_desc *eop = buf->eop;
 		if (eop == NULL) /* No work */
 			break;
 
@@ -1318,6 +1309,7 @@ ixgbe_setup_hw_rsc(struct rx_ring *rxr)
 
 	rxr->hw_rsc = TRUE;
 }
+
 /*********************************************************************
  *
  *  Refresh mbuf buffers for RX descriptor rings
@@ -1449,7 +1441,6 @@ fail:
 	return (error);
 }
 
-
 static void     
 ixgbe_free_receive_ring(struct rx_ring *rxr)
 { 
@@ -1470,7 +1461,6 @@ ixgbe_free_receive_ring(struct rx_ring *
 	}
 }
 
-
 /*********************************************************************
  *
  *  Initialize a receive ring and its buffers.
@@ -1981,6 +1971,7 @@ ixgbe_rxeof(struct ix_queue *que)
 				ixgbe_rx_checksum(staterr, sendmp, ptype,
 				   &adapter->stats.pf);
 			}
+
 #if 0 /* FreeBSD */
                         /*
                          * In case of multiqueue, we have RXCSUM.PCSD bit set
@@ -2037,7 +2028,7 @@ ixgbe_rxeof(struct ix_queue *que)
                                 sendmp->m_pkthdr.flowid = que->msix;
 				M_HASHTYPE_SET(sendmp, M_HASHTYPE_OPAQUE);
 			}
-#endif /* FreeBSD_version */
+#endif
 		}
 next_desc:
 		ixgbe_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
@@ -2103,24 +2094,25 @@ ixgbe_rx_checksum(u32 staterr, struct mb
 	u16	status = (u16) staterr;
 	u8	errors = (u8) (staterr >> 24);
 #if 0
-	bool	sctp = FALSE;
+	bool	sctp = false;
 
 	if ((ptype & IXGBE_RXDADV_PKTTYPE_ETQF) == 0 &&
 	    (ptype & IXGBE_RXDADV_PKTTYPE_SCTP) != 0)
-		sctp = TRUE;
+		sctp = true;
 #endif
 
+	/* IPv4 checksum */
 	if (status & IXGBE_RXD_STAT_IPCS) {
 		stats->ipcs.ev_count++;
 		if (!(errors & IXGBE_RXD_ERR_IPE)) {
 			/* IP Checksum Good */
 			mp->m_pkthdr.csum_flags = M_CSUM_IPv4;
-
 		} else {
 			stats->ipcs_bad.ev_count++;
 			mp->m_pkthdr.csum_flags = M_CSUM_IPv4|M_CSUM_IPv4_BAD;
 		}
 	}
+	/* TCP/UDP/SCTP checksum */
 	if (status & IXGBE_RXD_STAT_L4CS) {
 		stats->l4cs.ev_count++;
 		int type = M_CSUM_TCPv4|M_CSUM_TCPv6|M_CSUM_UDPv4|M_CSUM_UDPv6;
@@ -2131,7 +2123,6 @@ ixgbe_rx_checksum(u32 staterr, struct mb
 			mp->m_pkthdr.csum_flags |= type | M_CSUM_TCP_UDP_BAD;
 		}
 	}
-	return;
 }
 
 
Index: src/sys/dev/pci/ixgbe/ixgbe_82598.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.7 src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.8
--- src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.7	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_82598.c	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82598.c 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_82598.c,v 1.7 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82598.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_82598.c,v 1.8 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #include "ixgbe_type.h"
 #include "ixgbe_82598.h"
@@ -661,7 +661,7 @@ static s32 ixgbe_check_mac_link_82598(st
 		hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
 				     &adapt_comp_reg);
 		if (link_up_wait_to_complete) {
-			for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+			for (i = 0; i < hw->mac.max_link_up_time; i++) {
 				if ((link_reg & 1) &&
 				    ((adapt_comp_reg & 1) == 0)) {
 					*link_up = TRUE;
@@ -690,7 +690,7 @@ static s32 ixgbe_check_mac_link_82598(st
 
 	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
 	if (link_up_wait_to_complete) {
-		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+		for (i = 0; i < hw->mac.max_link_up_time; i++) {
 			if (links_reg & IXGBE_LINKS_UP) {
 				*link_up = TRUE;
 				break;
Index: src/sys/dev/pci/ixgbe/ixgbe_phy.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_phy.h:1.7 src/sys/dev/pci/ixgbe/ixgbe_phy.h:1.8
--- src/sys/dev/pci/ixgbe/ixgbe_phy.h:1.7	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_phy.h	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_phy.h 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_phy.h,v 1.7 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_phy.h 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_phy.h,v 1.8 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #ifndef _IXGBE_PHY_H_
 #define _IXGBE_PHY_H_
@@ -93,16 +93,23 @@
 #define IXGBE_CS4227_GLOBAL_ID_LSB	0
 #define IXGBE_CS4227_SCRATCH		2
 #define IXGBE_CS4227_GLOBAL_ID_VALUE	0x03E5
-#define IXGBE_CS4227_SCRATCH_VALUE	0x5aa5
-#define IXGBE_CS4227_RETRIES		5
+#define IXGBE_CS4227_RESET_PENDING	0x1357
+#define IXGBE_CS4227_RESET_COMPLETE	0x5AA5
+#define IXGBE_CS4227_RETRIES		15
+#define IXGBE_CS4227_EFUSE_STATUS	0x0181
 #define IXGBE_CS4227_LINE_SPARE22_MSB	0x12AD	/* Reg to program speed */
 #define IXGBE_CS4227_LINE_SPARE24_LSB	0x12B0	/* Reg to program EDC */
 #define IXGBE_CS4227_HOST_SPARE22_MSB	0x1AAD	/* Reg to program speed */
 #define IXGBE_CS4227_HOST_SPARE24_LSB	0x1AB0	/* Reg to program EDC */
+#define IXGBE_CS4227_EEPROM_STATUS	0x5001
+#define IXGBE_CS4227_EEPROM_LOAD_OK	0x0001
+#define IXGBE_CS4227_SPEED_1G		0x8000
+#define IXGBE_CS4227_SPEED_10G		0
 #define IXGBE_CS4227_EDC_MODE_CX1	0x0002
 #define IXGBE_CS4227_EDC_MODE_SR	0x0004
+#define IXGBE_CS4227_EDC_MODE_DIAG	0x0008
 #define IXGBE_CS4227_RESET_HOLD		500	/* microseconds */
-#define IXGBE_CS4227_RESET_DELAY	500	/* milliseconds */
+#define IXGBE_CS4227_RESET_DELAY	450	/* milliseconds */
 #define IXGBE_CS4227_CHECK_DELAY	30	/* milliseconds */
 #define IXGBE_PE			0xE0	/* Port expander address */
 #define IXGBE_PE_OUTPUT			1	/* Output register offset */

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.47 src/sys/dev/pci/ixgbe/ixgbe.c:1.48
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.47	Fri Dec  2 10:34:23 2016
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Fri Dec  2 10:42:04 2016
@@ -58,8 +58,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-/*$FreeBSD: head/sys/dev/ixgbe/if_ix.c 289238 2015-10-13 17:34:18Z sbruno $*/
-/*$NetBSD: ixgbe.c,v 1.47 2016/12/02 10:34:23 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/if_ix.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe.c,v 1.48 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -70,14 +70,10 @@
 #include <sys/cprng.h>
 
 /*********************************************************************
- *  Set this to one to display debug statistics
- *********************************************************************/
-int             ixgbe_display_debug_stats = 0;
-
-/*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixgbe_driver_version[] = "3.1.0";
+char ixgbe_driver_version[] = "3.1.13-k";
+
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -118,9 +114,11 @@ static ixgbe_vendor_info_t ixgbe_vendor_
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550T1, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
 	/* required last entry */
 	{0, 0, 0, 0, 0}
 };
@@ -155,7 +153,7 @@ static int      ixgbe_media_change(struc
 static void     ixgbe_identify_hardware(struct adapter *);
 static int      ixgbe_allocate_pci_resources(struct adapter *,
 		    const struct pci_attach_args *);
-static void	ixgbe_get_slot_info(struct ixgbe_hw *);
+static void	ixgbe_get_slot_info(struct adapter *);
 static int      ixgbe_allocate_msix(struct adapter *,
 		    const struct pci_attach_args *);
 static int      ixgbe_allocate_legacy(struct adapter *,
@@ -168,7 +166,6 @@ static void	ixgbe_config_gpie(struct ada
 static void	ixgbe_config_dmac(struct adapter *);
 static void	ixgbe_config_delay_values(struct adapter *);
 static void	ixgbe_config_link(struct adapter *);
-static void	ixgbe_check_eee_support(struct adapter *);
 static void	ixgbe_check_wol_support(struct adapter *);
 static int	ixgbe_setup_low_power_mode(struct adapter *);
 static void	ixgbe_rearm_queues(struct adapter *, u64);
@@ -177,6 +174,7 @@ static void     ixgbe_initialize_transmi
 static void     ixgbe_initialize_receive_units(struct adapter *);
 static void	ixgbe_enable_rx_drop(struct adapter *);
 static void	ixgbe_disable_rx_drop(struct adapter *);
+static void	ixgbe_initialize_rss_mapping(struct adapter *);
 
 static void     ixgbe_enable_intr(struct adapter *);
 static void     ixgbe_disable_intr(struct adapter *);
@@ -199,19 +197,24 @@ static void     ixgbe_add_hw_stats(struc
 
 /* Sysctl handlers */
 static void	ixgbe_set_sysctl_value(struct adapter *, const char *,
-		    const char *, int *, int);
+		     const char *, int *, int);
 static int	ixgbe_set_flowcntl(SYSCTLFN_PROTO);
 static int	ixgbe_set_advertise(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_thermal_test(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_dmac(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_phy_temp(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_phy_overtemp_occurred(SYSCTLFN_PROTO);
+#ifdef IXGBE_DEBUG
+static int	ixgbe_sysctl_power_state(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_print_rss_config(SYSCTLFN_PROTO);
+#endif
 static int	ixgbe_sysctl_wol_enable(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_wufc(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_eee_enable(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_eee_negotiated(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_eee_rx_lpi_status(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_eee_tx_lpi_status(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_eee_tx_lpi_delay(SYSCTLFN_PROTO);
 
 /* Support for pluggable optic modules */
 static bool	ixgbe_sfp_probe(struct adapter *);
@@ -264,9 +267,6 @@ DRIVER_MODULE(ix, pci, ix_driver, ix_dev
 
 MODULE_DEPEND(ix, pci, 1, 1, 1);
 MODULE_DEPEND(ix, ether, 1, 1, 1);
-#ifdef DEV_NETMAP
-MODULE_DEPEND(ix, netmap, 1, 1, 1);
-#endif /* DEV_NETMAP */
 #endif
 
 /*
@@ -437,7 +437,7 @@ ixgbe_attach(device_t parent, device_t d
 
 	/* Allocate, clear, and link in our adapter structure */
 	adapter = device_private(dev);
-	adapter->dev = adapter->osdep.dev = dev;
+	adapter->dev = dev;
 	hw = &adapter->hw;
 	adapter->osdep.pc = pa->pa_pc;
 	adapter->osdep.tag = pa->pa_tag;
@@ -538,18 +538,18 @@ ixgbe_attach(device_t parent, device_t d
 		adapter->sfp_probe = TRUE;
 		error = 0;
 	} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-		aprint_error_dev(dev,"Unsupported SFP+ module detected!\n");
+		aprint_error_dev(dev, "Unsupported SFP+ module detected!\n");
 		error = EIO;
 		goto err_late;
 	} else if (error) {
-		aprint_error_dev(dev,"Unable to initialize the shared code\n");
+		aprint_error_dev(dev, "Unable to initialize the shared code\n");
 		error = EIO;
 		goto err_late;
 	}
 
 	/* Make sure we have a good EEPROM before we read from it */
 	if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) {
-		aprint_error_dev(dev,"The EEPROM Checksum Is Not Valid\n");
+		aprint_error_dev(dev, "The EEPROM Checksum Is Not Valid\n");
 		error = EIO;
 		goto err_late;
 	}
@@ -559,25 +559,22 @@ ixgbe_attach(device_t parent, device_t d
 	case IXGBE_ERR_EEPROM_VERSION:
 		aprint_error_dev(dev, "This device is a pre-production adapter/"
 		    "LOM.  Please be aware there may be issues associated "
-		    "with your hardware.\n If you are experiencing problems "
+		    "with your hardware.\nIf you are experiencing problems "
 		    "please contact your Intel or hardware representative "
 		    "who provided you with this hardware.\n");
 		break;
 	case IXGBE_ERR_SFP_NOT_SUPPORTED:
-		aprint_error_dev(dev,"Unsupported SFP+ Module\n");
+		aprint_error_dev(dev, "Unsupported SFP+ Module\n");
 		error = EIO;
-		aprint_error_dev(dev,"Hardware Initialization Failure\n");
+		aprint_error_dev(dev, "Hardware Initialization Failure\n");
 		goto err_late;
 	case IXGBE_ERR_SFP_NOT_PRESENT:
-		device_printf(dev,"No SFP+ Module found\n");
+		aprint_error_dev(dev, "No SFP+ Module found\n");
 		/* falls thru */
 	default:
 		break;
 	}
 
-	/* Detect and set physical type */
-	ixgbe_setup_optics(adapter);
-
 	error = -1;
 	if ((adapter->msix > 1) && (ixgbe_enable_msix))
 		error = ixgbe_allocate_msix(adapter, pa);
@@ -594,11 +591,12 @@ ixgbe_attach(device_t parent, device_t d
 	ixgbe_update_stats_counters(adapter);
 
         /* Check PCIE slot type/speed/width */
-	ixgbe_get_slot_info(hw);
+	ixgbe_get_slot_info(adapter);
 
-
-	/* Set an initial default flow control value */
+	/* Set an initial default flow control & dmac value */
 	adapter->fc = ixgbe_fc_full;
+	adapter->dmac = 0;
+	adapter->eee_enabled = 0;
 
 #ifdef PCI_IOV
 	if ((hw->mac.type != ixgbe_mac_82598EB) && (adapter->msix > 1)) {
@@ -624,7 +622,6 @@ ixgbe_attach(device_t parent, device_t d
 
 	/* Check for certain supported features */
 	ixgbe_check_wol_support(adapter);
-	ixgbe_check_eee_support(adapter);
 
 	/* Add sysctls */
 	ixgbe_add_device_sysctls(adapter);
@@ -703,8 +700,7 @@ ixgbe_detach(device_t dev, int flags)
 	}
 #endif /* PCI_IOV */
 
-	pmf_device_deregister(dev);
-
+	ether_ifdetach(adapter->ifp);
 	/* Stop the adapter */
 	IXGBE_CORE_LOCK(adapter);
 	ixgbe_setup_low_power_mode(adapter);
@@ -734,7 +730,6 @@ ixgbe_detach(device_t dev, int flags)
 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
 
-	ether_ifdetach(adapter->ifp);
 	callout_halt(&adapter->timer, NULL);
 #ifdef DEV_NETMAP
 	netmap_detach(adapter->ifp);
@@ -893,12 +888,6 @@ ixgbe_suspend(device_t dev, const pmf_qu
 
 	error = ixgbe_setup_low_power_mode(adapter);
 
-#if 0 /* XXX */
-	/* Save state and power down */
-	pci_save_state(dev);
-	pci_set_powerstate(dev, PCI_POWERSTATE_D3);
-#endif
-
 	IXGBE_CORE_UNLOCK(adapter);
 
 	return (error);
@@ -916,11 +905,6 @@ ixgbe_resume(device_t dev, const pmf_qua
 
 	IXGBE_CORE_LOCK(adapter);
 
-#if 0 /* XXX */
-	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
-	pci_restore_state(dev);
-#endif
-
 	/* Read & clear WUS register */
 	wus = IXGBE_READ_REG(hw, IXGBE_WUS);
 	if (wus)
@@ -939,7 +923,6 @@ ixgbe_resume(device_t dev, const pmf_qua
 
 	IXGBE_CORE_UNLOCK(adapter);
 
-	INIT_DEBUGOUT("ixgbe_resume: end");
 	return true;
 }
 
@@ -1078,6 +1061,19 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 	return error;
 }
 
+/*
+ * Set the various hardware offload abilities.
+ *
+ * This takes the ifnet's if_capenable flags (e.g. set by the user using
+ * ifconfig) and indicates to the OS via the ifnet's if_hwassist field what
+ * mbuf offload flags the driver will understand.
+ */
+static void
+ixgbe_set_if_hwassist(struct adapter *adapter)
+{
+	/* XXX */
+}
+
 /*********************************************************************
  *  Init entry point
  *
@@ -1100,6 +1096,7 @@ ixgbe_init_locked(struct adapter *adapte
 	struct rx_ring  *rxr;
 	u32		txdctl, mhadd;
 	u32		rxdctl, rxctrl;
+	int err = 0;
 #ifdef PCI_IOV
 	enum ixgbe_iov_mode mode;
 #endif
@@ -1135,6 +1132,9 @@ ixgbe_init_locked(struct adapter *adapte
 	ixgbe_set_rar(hw, 0, hw->mac.addr, adapter->pool, 1);
 	hw->addr_ctrl.rar_used_count = 1;
 
+	/* Set hardware offload abilities from ifnet flags */
+	ixgbe_set_if_hwassist(adapter);
+
 	/* Prepare transmit descriptors and buffers */
 	if (ixgbe_setup_transmit_structures(adapter)) {
 		device_printf(dev, "Could not setup transmit structures\n");
@@ -1151,10 +1151,7 @@ ixgbe_init_locked(struct adapter *adapte
 	/* Setup Multicast table */
 	ixgbe_set_multi(adapter);
 
-	/*
-	** Determine the correct mbuf pool
-	** for doing jumbo frames
-	*/
+	/* Determine the correct mbuf pool, based on frame size */
 	if (adapter->max_frame_size <= MCLBYTES)
 		adapter->rx_mbuf_sz = MCLBYTES;
 	else
@@ -1290,7 +1287,7 @@ ixgbe_init_locked(struct adapter *adapte
 	 * need to be kick-started
 	 */
 	if (hw->phy.type == ixgbe_phy_none) {
-		int err = hw->phy.ops.identify(hw);
+		err = hw->phy.ops.identify(hw);
 		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
                 	device_printf(dev,
 			    "Unsupported SFP+ module type was detected.\n");
@@ -1302,7 +1299,11 @@ ixgbe_init_locked(struct adapter *adapte
 	IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
 
 	/* Configure Energy Efficient Ethernet for supported devices */
-	ixgbe_setup_eee(hw, adapter->eee_enabled);
+	if (hw->mac.ops.setup_eee) {
+		err = hw->mac.ops.setup_eee(hw, adapter->eee_enabled);
+		if (err)
+			device_printf(dev, "Error setting up EEE: %d\n", err);
+	}
 
 	/* Config/Enable Link */
 	ixgbe_config_link(adapter);
@@ -1372,7 +1373,7 @@ ixgbe_config_gpie(struct adapter *adapte
 
 	/*
 	 * Thermal Failure Detection (X540)
-	 * Link Detection (X557)
+	 * Link Detection (X552 SFP+, X552/X557-AT)
 	 */
 	if (hw->mac.type == ixgbe_mac_X540 ||
 	    hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
@@ -1701,6 +1702,9 @@ ixgbe_msix_link(void *arg)
 
 	++adapter->link_irq.ev_count;
 
+	/* Pause other interrupts */
+	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
+
 	/* First get the cause */
 	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
 	/* Be sure the queue bits are not cleared */
@@ -1709,8 +1713,10 @@ ixgbe_msix_link(void *arg)
 	IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
 
 	/* Link status change */
-	if (reg_eicr & IXGBE_EICR_LSC)
+	if (reg_eicr & IXGBE_EICR_LSC) {
+		IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
 		softint_schedule(adapter->link_si);
+	}
 
 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
 #ifdef IXGBE_FDIR
@@ -1724,14 +1730,14 @@ ixgbe_msix_link(void *arg)
 		} else
 #endif
 		if (reg_eicr & IXGBE_EICR_ECC) {
-                	device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! "
+			device_printf(adapter->dev, "CRITICAL: ECC ERROR!! "
 			    "Please Reboot!!\n");
 			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
 		}
 
 		/* Check for over temp condition */
 		if (reg_eicr & IXGBE_EICR_TS) {
-			device_printf(adapter->dev, "\nCRITICAL: OVER TEMP!! "
+			device_printf(adapter->dev, "CRITICAL: OVER TEMP!! "
 			    "PHY IS SHUT DOWN!!\n");
 			device_printf(adapter->dev, "System shutdown required!\n");
 			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS);
@@ -1773,6 +1779,7 @@ ixgbe_msix_link(void *arg)
 		softint_schedule(adapter->phy_si);
  	}
 
+	/* Re-enable other interrupts */
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
 	return 1;
 }
@@ -1866,6 +1873,7 @@ ixgbe_media_status(struct ifnet * ifp, s
 	** XXX: These need to use the proper media types once
 	** they're added.
 	*/
+#ifndef IFM_ETH_XTYPE
 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
 		switch (adapter->link_speed) {
 		case IXGBE_LINK_SPEED_10GB_FULL:
@@ -1891,6 +1899,33 @@ ixgbe_media_status(struct ifnet * ifp, s
 			ifmr->ifm_active |= IFM_1000_CX | IFM_FDX;
 			break;
 		}
+#else
+	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
+		switch (adapter->link_speed) {
+		case IXGBE_LINK_SPEED_10GB_FULL:
+			ifmr->ifm_active |= IFM_10G_KR | IFM_FDX;
+			break;
+		case IXGBE_LINK_SPEED_2_5GB_FULL:
+			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
+			break;
+		case IXGBE_LINK_SPEED_1GB_FULL:
+			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
+			break;
+		}
+	else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4
+	    || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
+		switch (adapter->link_speed) {
+		case IXGBE_LINK_SPEED_10GB_FULL:
+			ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX;
+			break;
+		case IXGBE_LINK_SPEED_2_5GB_FULL:
+			ifmr->ifm_active |= IFM_2500_KX | IFM_FDX;
+			break;
+		case IXGBE_LINK_SPEED_1GB_FULL:
+			ifmr->ifm_active |= IFM_1000_KX | IFM_FDX;
+			break;
+		}
+#endif
 	
 	/* If nothing is recognized... */
 #if 0
@@ -1933,13 +1968,14 @@ ixgbe_media_change(struct ifnet * ifp)
 		return (EINVAL);
 
 	if (hw->phy.media_type == ixgbe_media_type_backplane)
-		return (EPERM);
+		return (ENODEV);
 
 	/*
 	** We don't actually need to check against the supported
 	** media types of the adapter; ifmedia will take care of
 	** that for us.
 	*/
+#ifndef IFM_ETH_XTYPE
 	switch (IFM_SUBTYPE(ifm->ifm_media)) {
 		case IFM_AUTO:
 		case IFM_10G_T:
@@ -1965,6 +2001,33 @@ ixgbe_media_change(struct ifnet * ifp)
 		default:
 			goto invalid;
 	}
+#else
+	switch (IFM_SUBTYPE(ifm->ifm_media)) {
+		case IFM_AUTO:
+		case IFM_10G_T:
+			speed |= IXGBE_LINK_SPEED_100_FULL;
+		case IFM_10G_LRM:
+		case IFM_10G_KR:
+		case IFM_10G_LR:
+		case IFM_10G_KX4:
+			speed |= IXGBE_LINK_SPEED_1GB_FULL;
+		case IFM_10G_TWINAX:
+			speed |= IXGBE_LINK_SPEED_10GB_FULL;
+			break;
+		case IFM_1000_T:
+			speed |= IXGBE_LINK_SPEED_100_FULL;
+		case IFM_1000_LX:
+		case IFM_1000_SX:
+		case IFM_1000_KX:
+			speed |= IXGBE_LINK_SPEED_1GB_FULL;
+			break;
+		case IFM_100_TX:
+			speed |= IXGBE_LINK_SPEED_100_FULL;
+			break;
+		default:
+			goto invalid;
+	}
+#endif
 
 	hw->mac.autotry_restart = TRUE;
 	hw->mac.ops.setup_link(hw, speed, TRUE);
@@ -2688,7 +2751,7 @@ ixgbe_setup_msix(struct adapter *adapter
 	adapter->msix_mem = (void *)1; /* XXX */
 
 	/* Figure out a reasonable auto config value */
-	queues = (ncpu > (msgs-1)) ? (msgs-1) : ncpu;
+	queues = (ncpu > (msgs - 1)) ? (msgs - 1) : ncpu;
 
 #ifdef	RSS
 	/* If we're doing RSS, clamp at the number of RSS buckets */
@@ -2698,6 +2761,9 @@ ixgbe_setup_msix(struct adapter *adapter
 
 	if (ixgbe_num_queues != 0)
 		queues = ixgbe_num_queues;
+	/* Set max queues to 8 when autoconfiguring */
+	else if ((ixgbe_num_queues == 0) && (queues > 8))
+		queues = 8;
 
 	/* reflect correct sysctl value */
 	ixgbe_num_queues = queues;
@@ -2729,7 +2795,7 @@ msi:
        	msgs = pci_msi_count(adapter->osdep.pc, adapter->osdep.tag);
 	adapter->msix_mem = NULL; /* XXX */
        	msgs = 1;
-	aprint_normal_dev(dev,"Using an MSI interrupt\n");
+	aprint_normal_dev(dev, "Using an MSI interrupt\n");
 	return (msgs);
 }
 
@@ -2768,13 +2834,13 @@ map_err:
 		aprint_error_dev(dev, "unexpected type on BAR0\n");
 		return ENXIO;
 	}
+	adapter->hw.back = adapter;
 
-	/* Legacy defaults */
+	/* Default to 1 queue if MSI-X setup fails */
 	adapter->num_queues = 1;
-	adapter->hw.back = &adapter->osdep;
 
 	/*
-	** Now setup MSI or MSI/X, should
+	** Now setup MSI or MSI-X, should
 	** return us the number of supported
 	** vectors. (Will be 1 for MSI)
 	*/
@@ -2874,14 +2940,20 @@ ixgbe_setup_interface(device_t dev, stru
 	 */
 	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
 
-	ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSOv4 | IFCAP_TSOv6;
+	/* Set capability flags */
+	ifp->if_capabilities |= IFCAP_RXCSUM
+			     |  IFCAP_TXCSUM
+			     |  IFCAP_TSOv4
+			     |  IFCAP_TSOv6
+			     |  IFCAP_LRO;
 	ifp->if_capenable = 0;
 
-	ec->ec_capabilities |= ETHERCAP_VLAN_HWCSUM;
-	ec->ec_capabilities |= ETHERCAP_JUMBO_MTU;
-	ifp->if_capabilities |= IFCAP_LRO;
 	ec->ec_capabilities |= ETHERCAP_VLAN_HWTAGGING
-	    		    | ETHERCAP_VLAN_MTU;
+	    		    |  ETHERCAP_VLAN_HWCSUM
+	    		    |  ETHERCAP_JUMBO_MTU
+	    		    |  ETHERCAP_VLAN_MTU;
+
+	/* Enable the above capabilities by default */
 	ec->ec_capenable = ec->ec_capabilities;
 
 	/*
@@ -2901,9 +2973,10 @@ ixgbe_setup_interface(device_t dev, stru
 	ifmedia_init(&adapter->media, IFM_IMASK, ixgbe_media_change,
 		    ixgbe_media_status);
 
+	adapter->phy_layer = ixgbe_get_supported_physical_layer(&adapter->hw);
 	ixgbe_add_media_types(adapter);
 
-	/* Autoselect media by default */
+	/* Set autoselect media by default */
 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
 
 	return (0);
@@ -2916,7 +2989,7 @@ ixgbe_add_media_types(struct adapter *ad
 	device_t dev = adapter->dev;
 	int layer;
 
-	layer = adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
+	layer = adapter->phy_layer;
 
 	/* Media types with matching NetBSD media defines */
 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T)
@@ -2930,20 +3003,28 @@ ixgbe_add_media_types(struct adapter *ad
 	    layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA)
 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
 
-	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR)
+	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) {
 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
-	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR)
+		if (hw->phy.multispeed_fiber)
+			ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_LX, 0, NULL);
+	}
+	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) {
 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+		if (hw->phy.multispeed_fiber)
+			ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
+	} else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
+		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4)
 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_CX4, 0, NULL);
-	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX)
-		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_SX, 0, NULL);
 
-	/*
-	** Other (no matching NetBSD media type):
-	** To workaround this, we'll assign these completely
-	** inappropriate media types.
-	*/
+#ifdef IFM_ETH_XTYPE
+	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR)
+		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KR, 0, NULL);
+	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4)
+		ifmedia_add(&adapter->media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
+	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX)
+		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_KX, 0, NULL);
+#else
 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) {
 		device_printf(dev, "Media supported: 10GbaseKR\n");
 		device_printf(dev, "10GbaseKR mapped to 10GbaseSR\n");
@@ -2959,10 +3040,9 @@ ixgbe_add_media_types(struct adapter *ad
 		device_printf(dev, "1000baseKX mapped to 1000baseCX\n");
 		ifmedia_add(&adapter->media, IFM_ETHER | IFM_1000_CX, 0, NULL);
 	}
-	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) {
-		/* Someday, someone will care about you... */
+#endif
+	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
 		device_printf(dev, "Media supported: 1000baseBX\n");
-	}
 	
 	if (hw->device_id == IXGBE_DEV_ID_82598AT) {
 		ifmedia_add(&adapter->media,
@@ -3032,7 +3112,6 @@ ixgbe_initialize_transmit_units(struct a
 	struct ixgbe_hw	*hw = &adapter->hw;
 
 	/* Setup the Base and Length of the Tx Descriptor Ring */
-
 	for (int i = 0; i < adapter->num_queues; i++, txr++) {
 		u64	tdba = txr->txdma.dma_paddr;
 		u32	txctrl = 0;
@@ -3052,12 +3131,15 @@ ixgbe_initialize_transmit_units(struct a
 		txr->tail = IXGBE_TDT(j);
 
 		/* Disable Head Writeback */
+		/*
+		 * Note: for X550 series devices, these registers are actually
+		 * prefixed with TPH_ isntead of DCA_, but the addresses and
+		 * fields remain the same.
+		 */
 		switch (hw->mac.type) {
 		case ixgbe_mac_82598EB:
 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(j));
 			break;
-		case ixgbe_mac_82599EB:
-		case ixgbe_mac_X540:
 		default:
 			txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(j));
 			break;
@@ -3067,8 +3149,6 @@ ixgbe_initialize_transmit_units(struct a
 		case ixgbe_mac_82598EB:
 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(j), txctrl);
 			break;
-		case ixgbe_mac_82599EB:
-		case ixgbe_mac_X540:
 		default:
 			IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(j), txctrl);
 			break;
@@ -3101,7 +3181,7 @@ ixgbe_initialize_transmit_units(struct a
 }
 
 static void
-ixgbe_initialise_rss_mapping(struct adapter *adapter)
+ixgbe_initialize_rss_mapping(struct adapter *adapter)
 {
 	struct ixgbe_hw	*hw = &adapter->hw;
 	u32 reta = 0, mrqc, rss_key[10];
@@ -3237,7 +3317,6 @@ ixgbe_initialize_receive_units(struct ad
 	u32		bufsz, fctrl, srrctl, rxcsum;
 	u32		hlreg;
 
-
 	/*
 	 * Make sure receives are disabled while
 	 * setting up the descriptor ring
@@ -3322,7 +3401,7 @@ ixgbe_initialize_receive_units(struct ad
 
 	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
 
-	ixgbe_initialise_rss_mapping(adapter);
+	ixgbe_initialize_rss_mapping(adapter);
 
 	if (adapter->num_queues > 1) {
 		/* RSS and RX IPP Checksum are mutually exclusive */
@@ -3332,6 +3411,7 @@ ixgbe_initialize_receive_units(struct ad
 	if (ifp->if_capenable & IFCAP_RXCSUM)
 		rxcsum |= IXGBE_RXCSUM_PCSD;
 
+	/* This is useful for calculating UDP/IP fragment checksums */
 	if (!(rxcsum & IXGBE_RXCSUM_PCSD))
 		rxcsum |= IXGBE_RXCSUM_IPPCSE;
 
@@ -3553,9 +3633,10 @@ ixgbe_disable_intr(struct adapter *adapt
 ** the slot this adapter is plugged into.
 */
 static void
-ixgbe_get_slot_info(struct ixgbe_hw *hw)
+ixgbe_get_slot_info(struct adapter *adapter)
 {
-	device_t		dev = ((struct ixgbe_osdep *)hw->back)->dev;
+	device_t		dev = adapter->dev;
+	struct ixgbe_hw		*hw = &adapter->hw;
 	struct ixgbe_mac_info	*mac = &hw->mac;
 	u16			link;
 
@@ -3765,7 +3846,7 @@ ixgbe_sfp_probe(struct adapter *adapter)
 			adapter->sfp_probe = FALSE;
                         goto out;
 		} else
-			device_printf(dev,"SFP+ module detected!\n");
+			device_printf(dev, "SFP+ module detected!\n");
 		/* We now have supported optics */
 		adapter->sfp_probe = FALSE;
 		/* Set the optics type so system reports correctly */
@@ -3784,10 +3865,14 @@ static void
 ixgbe_handle_link(void *context)
 {
 	struct adapter  *adapter = context;
+	struct ixgbe_hw *hw = &adapter->hw;
 
-	ixgbe_check_link(&adapter->hw,
+	ixgbe_check_link(hw,
 	    &adapter->link_speed, &adapter->link_up, 0);
 	ixgbe_update_link_status(adapter);
+
+	/* Re-enable link interrupts */
+	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_LSC);
 }
 
 /*
@@ -3829,13 +3914,9 @@ ixgbe_handle_msf(void *context)
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 autoneg;
 	bool negotiate;
-	int err;
 
-	err = hw->phy.ops.identify_sfp(hw);
-	if (!err) {
-		ixgbe_setup_optics(adapter);
-		INIT_DEBUGOUT1("ixgbe_sfp_probe: flags: %X\n", adapter->optics);
-	}
+	/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
+	adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
 
 	autoneg = hw->phy.autoneg_advertised;
 	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
@@ -3845,6 +3926,7 @@ ixgbe_handle_msf(void *context)
 	if (hw->mac.ops.setup_link)
 		hw->mac.ops.setup_link(hw, autoneg, TRUE);
 
+	/* Adjust media types shown in ifconfig */
 	ifmedia_removeall(&adapter->media);
 	ixgbe_add_media_types(adapter);
 	return;
@@ -3924,18 +4006,6 @@ ixgbe_config_dmac(struct adapter *adapte
 }
 
 /*
- * Checks whether the adapter supports Energy Efficient Ethernet
- * or not, based on device ID.
- */
-static void
-ixgbe_check_eee_support(struct adapter *adapter)
-{
-	struct ixgbe_hw *hw = &adapter->hw;
-
-	adapter->eee_enabled = !!(hw->mac.ops.setup_eee);
-}
-
-/*
  * Checks whether the adapter's ports are capable of
  * Wake On LAN by reading the adapter's NVM.
  *
@@ -3953,8 +4023,8 @@ ixgbe_check_wol_support(struct adapter *
 	ixgbe_get_device_caps(hw, &dev_caps);
 	if ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0_1) ||
 	    ((dev_caps & IXGBE_DEVICE_CAPS_WOL_PORT0) &&
-	        hw->bus.func == 0))
-	    adapter->wol_support = hw->wol_enabled = 1;
+	      hw->bus.func == 0))
+		adapter->wol_support = hw->wol_enabled = 1;
 
 	/* Save initial wake up filter configuration */
 	adapter->wufc = IXGBE_READ_REG(hw, IXGBE_WUFC);
@@ -4314,7 +4384,21 @@ ixgbe_add_device_sysctls(struct adapter 
 	    ixgbe_sysctl_thermal_test, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
 		aprint_error_dev(dev, "could not create sysctl\n");
 
-	/* for X550 devices */
+#ifdef IXGBE_DEBUG
+	/* testing sysctls (for all devices) */
+	if (sysctl_createv(log, 0, &rnode, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_INT,
+	    "power_state", SYSCTL_DESCR("PCI Power State"),
+	    ixgbe_sysctl_power_state, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
+		aprint_error_dev(dev, "could not create sysctl\n");
+
+	if (sysctl_createv(log, 0, &rnode, &cnode,
+	    CTLFLAG_READONLY, CTLTYPE_STRING,
+	    "print_rss_config", SYSCTL_DESCR("Prints RSS Configuration"),
+	    ixgbe_sysctl_print_rss_config, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
+		aprint_error_dev(dev, "could not create sysctl\n");
+#endif
+	/* for X550 series devices */
 	if (hw->mac.type >= ixgbe_mac_X550)
 		if (sysctl_createv(log, 0, &rnode, &cnode,
 		    CTLFLAG_READWRITE, CTLTYPE_INT,
@@ -4322,8 +4406,8 @@ ixgbe_add_device_sysctls(struct adapter 
 		    ixgbe_sysctl_dmac, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
 			aprint_error_dev(dev, "could not create sysctl\n");
 
-	/* for X550T and X550EM backplane devices */
-	if (hw->mac.ops.setup_eee) {
+	/* for X552 backplane devices */
+	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
 		const struct sysctlnode *eee_node;
 
 		if (sysctl_createv(log, 0, &rnode, &eee_node,
@@ -4358,11 +4442,15 @@ ixgbe_add_device_sysctls(struct adapter 
 		    ixgbe_sysctl_eee_rx_lpi_status, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
 			aprint_error_dev(dev, "could not create sysctl\n");
 
+		if (sysctl_createv(log, 0, &eee_node, &cnode,
+		    CTLFLAG_READONLY, CTLTYPE_BOOL,
+		    "tx_lpi_delay", SYSCTL_DESCR("TX LPI entry delay in microseconds"),
+		    ixgbe_sysctl_eee_tx_lpi_delay, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
+			aprint_error_dev(dev, "could not create sysctl\n");
 	}
 
-	/* for certain 10GBaseT devices */
-	if (hw->device_id == IXGBE_DEV_ID_X550T ||
-	    hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+	/* for WoL-capable devices */
+	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
 		if (sysctl_createv(log, 0, &rnode, &cnode,
 		    CTLFLAG_READWRITE, CTLTYPE_INT,
 		    "wol_enable", SYSCTL_DESCR("Enable/Disable Wake on LAN"),
@@ -4376,7 +4464,7 @@ ixgbe_add_device_sysctls(struct adapter 
 			aprint_error_dev(dev, "could not create sysctl\n");
 	}
 
-	/* for X550EM 10GBaseT devices */
+	/* for X552/X557-AT devices */
 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
 		const struct sysctlnode *phy_node;
 
@@ -4464,10 +4552,10 @@ ixgbe_add_hw_stats(struct adapter *adapt
 
 	for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) {
 		snprintf(adapter->queues[i].evnamebuf,
-		    sizeof(adapter->queues[i].evnamebuf), "%s queue%d",
+		    sizeof(adapter->queues[i].evnamebuf), "%s q%d",
 		    device_xname(dev), i);
 		snprintf(adapter->queues[i].namebuf,
-		    sizeof(adapter->queues[i].namebuf), "queue%d", i);
+		    sizeof(adapter->queues[i].namebuf), "q%d", i);
 
 		if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
 			aprint_error_dev(dev, "could not create sysctl root\n");
@@ -4726,9 +4814,9 @@ ixgbe_set_sysctl_value(struct adapter *a
 		return;
 	}
 	if (sysctl_createv(log, 0, &rnode, &cnode,
-	    CTLFLAG_READWRITE, CTLTYPE_INT,
+	    CTLFLAG_READWRITE|CTLFLAG_IMMEDIATE, CTLTYPE_INT,
 	    name, SYSCTL_DESCR(description),
-		NULL, 0, limit, 0, CTL_CREATE, CTL_EOL) != 0)
+		NULL, value, limit, 0, CTL_CREATE, CTL_EOL) != 0)
 		aprint_error_dev(dev, "could not create sysctl\n");
 	*limit = value;
 }
@@ -4807,6 +4895,10 @@ ixgbe_set_advertise(SYSCTLFN_ARGS)
 	if (error != 0 || newp == NULL)
 		return error;
 
+	/* No speed changes for backplane media */
+	if (hw->phy.media_type == ixgbe_media_type_backplane)
+		return (ENODEV);
+
 	/* Checks to validate new value */
 	if (requested == old) /* no change */
 		return (0);
@@ -4850,7 +4942,7 @@ ixgbe_set_advertise(SYSCTLFN_ARGS)
 }
 
 /*
- * The following two sysctls are for X550 BaseT devices;
+ * The following two sysctls are for X552/X557-AT devices;
  * they deal with the external PHY used in them.
  */
 static int
@@ -4972,34 +5064,25 @@ ixgbe_sysctl_dmac(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
-	struct ixgbe_hw *hw = &adapter->hw;
 	struct ifnet *ifp = adapter->ifp;
 	int		error;
 	u16		oldval;
-	int		buffer;
+	int		newval;
 
 	oldval = adapter->dmac;
-	buffer = oldval;
-	node.sysctl_data = &buffer;
+	newval = oldval;
+	node.sysctl_data = &newval;
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
 	if ((error) || (newp == NULL))
 		return (error);
 
-	switch (hw->mac.type) {
-	case ixgbe_mac_X550:
-	case ixgbe_mac_X550EM_x:
-		break;
-	default:
-		device_printf(adapter->dev,
-		    "DMA Coalescing is only supported on X550 devices\n");
-		return (ENODEV);
-	}
-
-	switch (adapter->dmac) {
+	switch (newval) {
 	case 0:
 		/* Disabled */
+		adapter->dmac = 0;
 		break;
-	case 1: /* Enable and use default */
+	case 1:
+		/* Enable and use default */
 		adapter->dmac = 1000;
 		break;
 	case 50:
@@ -5011,10 +5094,10 @@ ixgbe_sysctl_dmac(SYSCTLFN_ARGS)
 	case 5000:
 	case 10000:
 		/* Legal values - allow */
+		adapter->dmac = newval;
 		break;
 	default:
 		/* Do nothing, illegal value */
-		adapter->dmac = oldval;
 		return (EINVAL);
 	}
 
@@ -5025,6 +5108,47 @@ ixgbe_sysctl_dmac(SYSCTLFN_ARGS)
 	return (0);
 }
 
+#ifdef IXGBE_DEBUG
+/**
+ * Sysctl to test power states
+ * Values:
+ *	0      - set device to D0
+ *	3      - set device to D3
+ *	(none) - get current device power state
+ */
+static int
+ixgbe_sysctl_power_state(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node = *rnode;
+	struct adapter *adapter = (struct adapter *)node.sysctl_data;
+	device_t dev =  adapter->dev;
+	int curr_ps, new_ps, error = 0;
+
+#if notyet
+	curr_ps = new_ps = pci_get_powerstate(dev);
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if ((error) || (req->newp == NULL))
+		return (error);
+
+	if (new_ps == curr_ps)
+		return (0);
+
+	if (new_ps == 3 && curr_ps == 0)
+		error = DEVICE_SUSPEND(dev);
+	else if (new_ps == 0 && curr_ps == 3)
+		error = DEVICE_RESUME(dev);
+	else
+		return (EINVAL);
+
+	device_printf(dev, "New state: %d\n", pci_get_powerstate(dev));
+
+	return (error);
+#else
+	return 0;
+#endif
+}
+#endif
 /*
  * Sysctl to enable/disable the WoL capability, if supported by the adapter.
  * Values:
@@ -5044,13 +5168,14 @@ ixgbe_sysctl_wol_enable(SYSCTLFN_ARGS)
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
 	if ((error) || (newp == NULL))
 		return (error);
+	new_wol_enabled = !!(new_wol_enabled);
 	if (new_wol_enabled == hw->wol_enabled)
 		return (0);
 
 	if (new_wol_enabled > 0 && !adapter->wol_support)
 		return (ENODEV);
 	else
-		hw->wol_enabled = !!(new_wol_enabled);
+		hw->wol_enabled = new_wol_enabled;
 
 	return (0);
 }
@@ -5076,13 +5201,14 @@ ixgbe_sysctl_eee_enable(SYSCTLFN_ARGS)
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
 	if ((error) || (newp == NULL))
 		return (error);
+	new_eee_enabled = !!(new_eee_enabled);
 	if (new_eee_enabled == adapter->eee_enabled)
 		return (0);
 
 	if (new_eee_enabled > 0 && !hw->mac.ops.setup_eee)
 		return (ENODEV);
 	else
-		adapter->eee_enabled = !!(new_eee_enabled);
+		adapter->eee_enabled = new_eee_enabled;
 
 	/* Re-initialize hardware if it's already running */
 	if (ifp->if_flags & IFF_RUNNING)
@@ -5146,6 +5272,24 @@ ixgbe_sysctl_eee_tx_lpi_status(SYSCTLFN_
 }
 
 /*
+ * Read-only sysctl indicating TX Link LPI delay
+ */
+static int
+ixgbe_sysctl_eee_tx_lpi_delay(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node = *rnode;
+	struct adapter *adapter = (struct adapter *)node.sysctl_data;
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 reg;
+
+	reg = IXGBE_READ_REG(hw, IXGBE_EEE_SU);
+
+	reg >>= 26;
+	node.sysctl_data = &reg;
+	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
+}
+
+/*
  * Sysctl to enable/disable the types of packets that the
  * adapter will wake up on upon receipt.
  * WUFC - Wake Up Filter Control
@@ -5189,6 +5333,58 @@ ixgbe_sysctl_wufc(SYSCTLFN_ARGS)
 	return (0);
 }
 
+#ifdef IXGBE_DEBUG
+static int
+ixgbe_sysctl_print_rss_config(SYSCTLFN_ARGS)
+{
+	struct adapter *adapter = (struct adapter *)node.sysctl_data;
+	struct ixgbe_hw *hw = &adapter->hw;
+	device_t dev = adapter->dev;
+	int error = 0, reta_size;
+	struct sbuf *buf;
+	u32 reg;
+
+	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
+	if (!buf) {
+		device_printf(dev, "Could not allocate sbuf for output.\n");
+		return (ENOMEM);
+	}
+
+	// TODO: use sbufs to make a string to print out
+	/* Set multiplier for RETA setup and table size based on MAC */
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_X550:
+	case ixgbe_mac_X550EM_x:
+		reta_size = 128;
+		break;
+	default:
+		reta_size = 32;
+		break;
+	}
+
+	/* Print out the redirection table */
+	sbuf_cat(buf, "\n");
+	for (int i = 0; i < reta_size; i++) {
+		if (i < 32) {
+			reg = IXGBE_READ_REG(hw, IXGBE_RETA(i));
+			sbuf_printf(buf, "RETA(%2d): 0x%08x\n", i, reg);
+		} else {
+			reg = IXGBE_READ_REG(hw, IXGBE_ERETA(i - 32));
+			sbuf_printf(buf, "ERETA(%2d): 0x%08x\n", i - 32, reg);
+		}
+	}
+
+	// TODO: print more config
+
+	error = sbuf_finish(buf);
+	if (error)
+		device_printf(dev, "Error finishing sbuf: %d\n", error);
+
+	sbuf_delete(buf);
+	return (0);
+}
+#endif /* IXGBE_DEBUG */
+
 /*
 ** Enable the hardware to drop packets when the buffer is
 ** full. This is useful when multiqueue,so that no single

Index: src/sys/dev/pci/ixgbe/ixgbe.h
diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.15 src/sys/dev/pci/ixgbe/ixgbe.h:1.16
--- src/sys/dev/pci/ixgbe/ixgbe.h:1.15	Fri Dec  2 10:34:23 2016
+++ src/sys/dev/pci/ixgbe/ixgbe.h	Fri Dec  2 10:42:04 2016
@@ -58,8 +58,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe.h 289238 2015-10-13 17:34:18Z sbruno $*/
-/*$NetBSD: ixgbe.h,v 1.15 2016/12/02 10:34:23 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe.h 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe.h,v 1.16 2016/12/02 10:42:04 msaitoh Exp $*/
 
 
 #ifndef _IXGBE_H_
@@ -153,12 +153,6 @@
 #define DBA_ALIGN	128
 
 /*
- * This parameter controls the maximum no of times the driver will loop in
- * the isr. Minimum Value = 1
- */
-#define MAX_LOOP	10
-
-/*
  * This is the max watchdog interval, ie. the time that can
  * pass between any two TX clean operations, such only happening
  * when the TX hardware is functioning.
@@ -174,9 +168,11 @@
 
 /* These defines are used in MTU calculations */
 #define IXGBE_MAX_FRAME_SIZE	9728
-#define IXGBE_MTU_HDR		(ETHER_HDR_LEN + ETHER_CRC_LEN + \
+#define IXGBE_MTU_HDR		(ETHER_HDR_LEN + ETHER_CRC_LEN)
+#define IXGBE_MTU_HDR_VLAN	(ETHER_HDR_LEN + ETHER_CRC_LEN + \
 				 ETHER_VLAN_ENCAP_LEN)
 #define IXGBE_MAX_MTU		(IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR)
+#define IXGBE_MAX_MTU_VLAN	(IXGBE_MAX_FRAME_SIZE - IXGBE_MTU_HDR_VLAN)
 
 /* Flow control constants */
 #define IXGBE_FC_PAUSE		0xFFFF
@@ -224,7 +220,6 @@
 #define MSIX_82598_BAR			3
 #define MSIX_82599_BAR			4
 #define IXGBE_TSO_SIZE			262140
-#define IXGBE_TX_BUFFER_SIZE		((u32) 1514)
 #define IXGBE_RX_HDR			128
 #define IXGBE_VFTA_SIZE			128
 #define IXGBE_BR_SIZE			4096
@@ -234,8 +229,6 @@
 
 #define IXV_EITR_DEFAULT		128
 
-#define IXV_EITR_DEFAULT		128
-
 /* IOCTL define to gather SFP+ Diagnostic data */
 #define SIOCGI2C	SIOCGIFGENERIC
 
@@ -258,7 +251,11 @@
 #define IXGBE_LOW_LATENCY	128
 #define IXGBE_AVE_LATENCY	400
 #define IXGBE_BULK_LATENCY	1200
-#define IXGBE_LINK_ITR		2000
+
+/* Using 1FF (the max value), the interval is ~1.05ms */
+#define IXGBE_LINK_ITR_QUANTA	0x1FF
+#define IXGBE_LINK_ITR		((IXGBE_LINK_ITR_QUANTA << 3) & \
+				    IXGBE_EITR_ITR_INT_MASK)
 
 /* MAC type macros */
 #define IXGBE_IS_X550VF(_adapter) \
@@ -474,11 +471,11 @@ struct ixgbe_vf {
 
 /* Our adapter structure */
 struct adapter {
-	struct ifnet		*ifp;
 	struct ixgbe_hw		hw;
-
 	struct ixgbe_osdep	osdep;
+
 	device_t		dev;
+	struct ifnet		*ifp;
 
 	struct resource		*pci_mem;
 	struct resource		*msix_mem;
Index: src/sys/dev/pci/ixgbe/ixgbe_type.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.15 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.16
--- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.15	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_type.h	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_type.h 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_type.h,v 1.15 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_type.h 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_type.h,v 1.16 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #ifndef _IXGBE_TYPE_H_
 #define _IXGBE_TYPE_H_
@@ -145,6 +145,7 @@
 #define IXGBE_DEV_ID_X540_BYPASS		0x155C
 #define IXGBE_DEV_ID_X540T1			0x1560
 #define IXGBE_DEV_ID_X550T			0x1563
+#define IXGBE_DEV_ID_X550T1			0x15D1
 #define IXGBE_DEV_ID_X550EM_X_KX4		0x15AA
 #define IXGBE_DEV_ID_X550EM_X_KR		0x15AB
 #define IXGBE_DEV_ID_X550EM_X_SFP		0x15AC
@@ -1558,7 +1559,9 @@ struct ixgbe_dmac_config {
 #define TN1010_PHY_ID	0x00A19410
 #define TNX_FW_REV	0xB
 #define X540_PHY_ID	0x01540200
-#define X550_PHY_ID	0x01540220
+#define X550_PHY_ID1	0x01540220
+#define X550_PHY_ID2	0x01540223
+#define X550_PHY_ID3	0x01540221
 #define X557_PHY_ID	0x01540240
 #define AQ_FW_REV	0x20
 #define QT2022_PHY_ID	0x0043A400
@@ -1951,6 +1954,7 @@ enum {
  *	FIP  (0x8914):	 Filter 4
  *	LLDP (0x88CC):	 Filter 5
  *	LACP (0x8809):	 Filter 6
+ *	FC   (0x8808):	 Filter 7
  */
 #define IXGBE_ETQF_FILTER_EAPOL		0
 #define IXGBE_ETQF_FILTER_FCOE		2
@@ -1958,6 +1962,7 @@ enum {
 #define IXGBE_ETQF_FILTER_FIP		4
 #define IXGBE_ETQF_FILTER_LLDP		5
 #define IXGBE_ETQF_FILTER_LACP		6
+#define IXGBE_ETQF_FILTER_FC		7
 /* VLAN Control Bit Masks */
 #define IXGBE_VLNCTRL_VET		0x0000FFFF  /* bits 0-15 */
 #define IXGBE_VLNCTRL_CFI		0x10000000  /* bit 28 */
@@ -2817,7 +2822,9 @@ enum ixgbe_fdir_pballoc_type {
 #define IXGBE_FDIRCTRL_REPORT_STATUS		0x00000020
 #define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS	0x00000080
 #define IXGBE_FDIRCTRL_DROP_Q_SHIFT		8
+#define IXGBE_FDIRCTRL_DROP_Q_MASK		0x00007F00
 #define IXGBE_FDIRCTRL_FLEX_SHIFT		16
+#define IXGBE_FDIRCTRL_DROP_NO_MATCH		0x00008000
 #define IXGBE_FDIRCTRL_FILTERMODE_SHIFT		21
 #define IXGBE_FDIRCTRL_FILTERMODE_MACVLAN	0x0001 /* bit 23:21, 001b */
 #define IXGBE_FDIRCTRL_FILTERMODE_CLOUD		0x0002 /* bit 23:21, 010b */
@@ -2921,6 +2928,11 @@ enum ixgbe_fdir_pballoc_type {
 #define FW_DISABLE_RXEN_CMD		0xDE
 #define FW_DISABLE_RXEN_LEN		0x1
 #define FW_PHY_MGMT_REQ_CMD		0x20
+#define FW_INT_PHY_REQ_CMD		0xB
+#define FW_INT_PHY_REQ_LEN		10
+#define FW_INT_PHY_REQ_READ		0
+#define FW_INT_PHY_REQ_WRITE		1
+
 /* Host Interface Command Structures */
 
 struct ixgbe_hic_hdr {
@@ -2989,6 +3001,21 @@ struct ixgbe_hic_disable_rxen {
 	u16 pad3;
 };
 
+struct ixgbe_hic_internal_phy_req {
+	struct ixgbe_hic_hdr hdr;
+	u8 port_number;
+	u8 command_type;
+	u16 address;
+	u16 rsv1;
+	u32 write_data;
+	u16 pad;
+};
+
+struct ixgbe_hic_internal_phy_resp {
+	struct ixgbe_hic_hdr hdr;
+	u32 read_data;
+};
+
 
 /* Transmit Descriptor - Legacy */
 struct ixgbe_legacy_tx_desc {
@@ -3324,6 +3351,7 @@ union ixgbe_atr_hash_dword {
 	IXGBE_CAT(SRAMREL, m),		\
 	IXGBE_CAT(FACTPS, m),		\
 	IXGBE_CAT(SWSM, m),		\
+	IXGBE_CAT(SWFW_SYNC, m),	\
 	IXGBE_CAT(FWSM, m),		\
 	IXGBE_CAT(SDP0_GPIEN, m),	\
 	IXGBE_CAT(SDP1_GPIEN, m),	\
@@ -3814,6 +3842,7 @@ struct ixgbe_mac_info {
 	u8				flags;
 	struct ixgbe_dmac_config dmac_config;
 	bool set_lben;
+	u32  max_link_up_time;
 };
 
 struct ixgbe_phy_info {
@@ -3828,6 +3857,7 @@ struct ixgbe_phy_info {
 	u32 phy_semaphore_mask;
 	bool				reset_disable;
 	ixgbe_autoneg_advertised	autoneg_advertised;
+	ixgbe_link_speed speeds_supported;
 	enum ixgbe_smart_speed		smart_speed;
 	bool				smart_speed_active;
 	bool				multispeed_fiber;
@@ -3868,7 +3898,7 @@ struct ixgbe_mbx_info {
 };
 
 struct ixgbe_hw {
-	struct ixgbe_osdep		*back;
+	struct adapter *back;
 	struct ixgbe_mac_info		mac;
 	struct ixgbe_addr_filter_info	addr_ctrl;
 	struct ixgbe_fc_info		fc;
@@ -3939,15 +3969,15 @@ struct ixgbe_hw {
 #define IXGBE_FUSES0_300MHZ		(1 << 5)
 #define IXGBE_FUSES0_REV1		(1 << 6)
 
-#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P)	((P == 0) ? (0x4010) : (0x8010))
-#define IXGBE_KRM_LINK_CTRL_1(P)	((P == 0) ? (0x420C) : (0x820C))
-#define IXGBE_KRM_AN_CNTL_1(P)		((P == 0) ? (0x422C) : (0x822C))
-#define IXGBE_KRM_DSP_TXFFE_STATE_4(P)	((P == 0) ? (0x4634) : (0x8634))
-#define IXGBE_KRM_DSP_TXFFE_STATE_5(P)	((P == 0) ? (0x4638) : (0x8638))
-#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P)	((P == 0) ? (0x4B00) : (0x8B00))
-#define IXGBE_KRM_PMD_DFX_BURNIN(P)	((P == 0) ? (0x4E00) : (0x8E00))
-#define IXGBE_KRM_TX_COEFF_CTRL_1(P)	((P == 0) ? (0x5520) : (0x9520))
-#define IXGBE_KRM_RX_ANA_CTL(P)		((P == 0) ? (0x5A00) : (0x9A00))
+#define IXGBE_KRM_PORT_CAR_GEN_CTRL(P)	((P) ? 0x8010 : 0x4010)
+#define IXGBE_KRM_LINK_CTRL_1(P)	((P) ? 0x820C : 0x420C)
+#define IXGBE_KRM_AN_CNTL_1(P)		((P) ? 0x822C : 0x422C)
+#define IXGBE_KRM_DSP_TXFFE_STATE_4(P)	((P) ? 0x8634 : 0x4634)
+#define IXGBE_KRM_DSP_TXFFE_STATE_5(P)	((P) ? 0x8638 : 0x4638)
+#define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P)	((P) ? 0x8B00 : 0x4B00)
+#define IXGBE_KRM_PMD_DFX_BURNIN(P)	((P) ? 0x8E00 : 0x4E00)
+#define IXGBE_KRM_TX_COEFF_CTRL_1(P)	((P) ? 0x9520 : 0x5520)
+#define IXGBE_KRM_RX_ANA_CTL(P)		((P) ? 0x9A00 : 0x5A00)
 
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B		(1 << 9)
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS		(1 << 11)
@@ -3981,15 +4011,6 @@ struct ixgbe_hw {
 #define IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN		(1 << 3)
 #define IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN		(1 << 31)
 
-#define IXGBE_KX4_LINK_CNTL_1				0x4C
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX		(1 << 16)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4		(1 << 17)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX		(1 << 24)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_EEE_CAP_KX4		(1 << 25)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE		(1 << 29)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_FORCE_LINK_UP	(1 << 30)
-#define IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART		(1 << 31)
-
 #define IXGBE_SB_IOSF_INDIRECT_CTRL	0x00011144
 #define IXGBE_SB_IOSF_INDIRECT_DATA	0x00011148
 
@@ -4006,8 +4027,6 @@ struct ixgbe_hw {
 #define IXGBE_SB_IOSF_CTRL_BUSY_SHIFT		31
 #define IXGBE_SB_IOSF_CTRL_BUSY		(1 << IXGBE_SB_IOSF_CTRL_BUSY_SHIFT)
 #define IXGBE_SB_IOSF_TARGET_KR_PHY	0
-#define IXGBE_SB_IOSF_TARGET_KX4_PHY	1
-#define IXGBE_SB_IOSF_TARGET_KX4_PCS	2
 
 #define IXGBE_NW_MNG_IF_SEL		0x00011178
 #define IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE (1 << 24)

Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.13 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14
--- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.13	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_82599.c	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82599.c 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_82599.c,v 1.13 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82599.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_82599.c,v 1.14 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #include "ixgbe_type.h"
 #include "ixgbe_82599.h"
@@ -383,8 +383,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw
 	mac->max_tx_queues	= IXGBE_82599_MAX_TX_QUEUES;
 	mac->max_msix_vectors	= ixgbe_get_pcie_msix_count_generic(hw);
 
-	mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) &
-				   IXGBE_FWSM_MODE_MASK) ? TRUE : FALSE;
+	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
+				      & IXGBE_FWSM_MODE_MASK);
 
 	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
 
@@ -1371,7 +1371,7 @@ s32 ixgbe_init_fdir_perfect_82599(struct
 	 * Continue setup of fdirctrl register bits:
 	 *  Turn perfect match filtering on
 	 *  Report hash in RSS field of Rx wb descriptor
-	 *  Initialize the drop queue
+	 *  Initialize the drop queue to queue 127
 	 *  Move the flexible bytes to use the ethertype - shift 6 words
 	 *  Set the maximum length per hash bucket to 0xA filters
 	 *  Send interrupt when 64 (0x4 * 16) filters are left
@@ -1382,6 +1382,9 @@ s32 ixgbe_init_fdir_perfect_82599(struct
 		    (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
 		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
 		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
+	if ((hw->mac.type == ixgbe_mac_X550) ||
+	    (hw->mac.type == ixgbe_mac_X550EM_x))
+		fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
 
 	if (cloud_mode)
 		fdirctrl |=(IXGBE_FDIRCTRL_FILTERMODE_CLOUD <<
@@ -1393,6 +1396,39 @@ s32 ixgbe_init_fdir_perfect_82599(struct
 	return IXGBE_SUCCESS;
 }
 
+/**
+ *  ixgbe_set_fdir_drop_queue_82599 - Set Flow Director drop queue
+ *  @hw: pointer to hardware structure
+ *  @dropqueue: Rx queue index used for the dropped packets
+ **/
+void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue)
+{
+	u32 fdirctrl;
+
+	DEBUGFUNC("ixgbe_set_fdir_drop_queue_82599");
+	/* Clear init done bit and drop queue field */
+	fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
+	fdirctrl &= ~(IXGBE_FDIRCTRL_DROP_Q_MASK | IXGBE_FDIRCTRL_INIT_DONE);
+
+	/* Set drop queue */
+	fdirctrl |= (dropqueue << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
+	if ((hw->mac.type == ixgbe_mac_X550) ||
+	    (hw->mac.type == ixgbe_mac_X550EM_x))
+		fdirctrl |= IXGBE_FDIRCTRL_DROP_NO_MATCH;
+
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
+			 IXGBE_FDIRCMD_CLEARHT));
+	IXGBE_WRITE_FLUSH(hw);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
+			 ~IXGBE_FDIRCMD_CLEARHT));
+	IXGBE_WRITE_FLUSH(hw);
+
+	/* write hashes and fdirctrl register, poll for completion */
+	ixgbe_fdir_enable_82599(hw, fdirctrl);
+}
+
 /*
  * These defines allow us to quickly generate all of the necessary instructions
  * in the function below by simply calling out IXGBE_COMPUTE_SIG_HASH_ITERATION
@@ -1493,16 +1529,15 @@ u32 ixgbe_atr_compute_sig_hash_82599(uni
  * Note that the tunnel bit in input must not be set when the hardware
  * tunneling support does not exist.
  **/
-s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
-					  union ixgbe_atr_hash_dword input,
-					  union ixgbe_atr_hash_dword common,
-					  u8 queue)
+void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+					   union ixgbe_atr_hash_dword input,
+					   union ixgbe_atr_hash_dword common,
+					   u8 queue)
 {
 	u64 fdirhashcmd;
 	u8 flow_type;
 	bool tunnel;
 	u32 fdircmd;
-	s32 err;
 
 	DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599");
 
@@ -1524,7 +1559,7 @@ s32 ixgbe_fdir_add_signature_filter_8259
 		break;
 	default:
 		DEBUGOUT(" Error on flow type input\n");
-		return IXGBE_ERR_CONFIG;
+		return;
 	}
 
 	/* configure FDIRCMD register */
@@ -1543,15 +1578,9 @@ s32 ixgbe_fdir_add_signature_filter_8259
 	fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
 	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
 
-	err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
-	if (err) {
-		DEBUGOUT("Flow Director command did not complete!\n");
-		return err;
-	}
-
 	DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd);
 
-	return IXGBE_SUCCESS;
+	return;
 }
 
 #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
Index: src/sys/dev/pci/ixgbe/ixgbe_api.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_api.c:1.13 src/sys/dev/pci/ixgbe/ixgbe_api.c:1.14
--- src/sys/dev/pci/ixgbe/ixgbe_api.c:1.13	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_api.c	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_api.c 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_api.c,v 1.13 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_api.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_api.c,v 1.14 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #include "ixgbe_api.h"
 #include "ixgbe_common.h"
@@ -114,6 +114,7 @@ s32 ixgbe_init_shared_code(struct ixgbe_
 		status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
 		break;
 	}
+	hw->mac.max_link_up_time = IXGBE_LINK_UP_TIME;
 
 	return status;
 }
@@ -188,6 +189,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *
 		hw->mvals = ixgbe_mvals_X540;
 		break;
 	case IXGBE_DEV_ID_X550T:
+	case IXGBE_DEV_ID_X550T1:
 		hw->mac.type = ixgbe_mac_X550;
 		hw->mvals = ixgbe_mvals_X550;
 		break;
Index: src/sys/dev/pci/ixgbe/ixgbe_osdep.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.13 src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.14
--- src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.13	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_osdep.h	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_osdep.h 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_osdep.h,v 1.13 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_osdep.h 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_osdep.h,v 1.14 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #ifndef _IXGBE_OS_H_
 #define _IXGBE_OS_H_
@@ -162,7 +162,7 @@ void prefetch(void *x)
  * non-overlapping regions and 32-byte padding on both src and dst.
  */
 static __inline int
-ixgbe_bcopy(void *_src, void *_dst, int l)
+ixgbe_bcopy(void *restrict _src, void *restrict _dst, int l)
 {
 	uint64_t *src = _src;
 	uint64_t *dst = _dst;
@@ -185,15 +185,17 @@ struct ixgbe_osdep
 	bus_space_handle_t mem_bus_space_handle;
 	bus_size_t         mem_size;
 	bus_dma_tag_t      dmat;
-	device_t           dev;
 	pci_intr_handle_t  *intrs;
 	int		   nintrs;
 	void               *ihs[IXG_MAX_NINTR];
 	bool		   attached;
 };
 
-/* These routines are needed by the shared code */
+/* These routines need struct ixgbe_hw declared */
 struct ixgbe_hw; 
+device_t ixgbe_dev_from_hw(struct ixgbe_hw *hw);
+
+/* These routines are needed by the shared code */
 extern u16 ixgbe_read_pci_cfg(struct ixgbe_hw *, u32);
 #define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg
 
@@ -202,26 +204,18 @@ extern void ixgbe_write_pci_cfg(struct i
 
 #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
 
-#define IXGBE_READ_REG(a, reg) (\
-   bus_space_read_4( ((a)->back)->mem_bus_space_tag, \
-                     ((a)->back)->mem_bus_space_handle, \
-                     reg))
-
-#define IXGBE_WRITE_REG(a, reg, value) (\
-   bus_space_write_4( ((a)->back)->mem_bus_space_tag, \
-                     ((a)->back)->mem_bus_space_handle, \
-                     reg, value))
-
-
-#define IXGBE_READ_REG_ARRAY(a, reg, offset) (\
-   bus_space_read_4( ((a)->back)->mem_bus_space_tag, \
-                     ((a)->back)->mem_bus_space_handle, \
-                     (reg + ((offset) << 2))))
-
-#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) (\
-      bus_space_write_4( ((a)->back)->mem_bus_space_tag, \
-                      ((a)->back)->mem_bus_space_handle, \
-                      (reg + ((offset) << 2)), value))
+extern u32 ixgbe_read_reg(struct ixgbe_hw *, u32);
+#define IXGBE_READ_REG(a, reg) ixgbe_read_reg(a, reg)
+
+extern void ixgbe_write_reg(struct ixgbe_hw *, u32, u32);
+#define IXGBE_WRITE_REG(a, reg, val) ixgbe_write_reg(a, reg, val)
 
+extern u32 ixgbe_read_reg_array(struct ixgbe_hw *, u32, u32);
+#define IXGBE_READ_REG_ARRAY(a, reg, offset) \
+    ixgbe_read_reg_array(a, reg, offset)
+
+extern void ixgbe_write_reg_array(struct ixgbe_hw *, u32, u32, u32);
+#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, val) \
+    ixgbe_write_reg_array(a, reg, offset, val)
 
 #endif /* _IXGBE_OS_H_ */

Index: src/sys/dev/pci/ixgbe/ixgbe_api.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_api.h:1.8 src/sys/dev/pci/ixgbe/ixgbe_api.h:1.9
--- src/sys/dev/pci/ixgbe/ixgbe_api.h:1.8	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_api.h	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_api.h 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_api.h,v 1.8 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_api.h 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_api.h,v 1.9 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #ifndef _IXGBE_API_H_
 #define _IXGBE_API_H_
@@ -149,10 +149,10 @@ s32 ixgbe_reinit_fdir_tables_82599(struc
 s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
 s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl,
 					bool cloud_mode);
-s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
-					  union ixgbe_atr_hash_dword input,
-					  union ixgbe_atr_hash_dword common,
-					  u8 queue);
+void ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+					   union ixgbe_atr_hash_dword input,
+					   union ixgbe_atr_hash_dword common,
+					   u8 queue);
 s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
 				    union ixgbe_atr_input *input_mask, bool cloud_mode);
 s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
@@ -181,6 +181,7 @@ s32 ixgbe_read_i2c_combined_unlocked(str
 				     u16 *val);
 s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
 			 u8 data);
+void ixgbe_set_fdir_drop_queue_82599(struct ixgbe_hw *hw, u8 dropqueue);
 s32 ixgbe_write_i2c_byte_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
 				  u8 dev_addr, u8 data);
 s32 ixgbe_write_i2c_combined(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val);
Index: src/sys/dev/pci/ixgbe/ixgbe_phy.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.8 src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.9
--- src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.8	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_phy.c	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_phy.c 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_phy.c,v 1.8 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_phy.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_phy.c,v 1.9 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #include "ixgbe_api.h"
 #include "ixgbe_common.h"
@@ -509,7 +509,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_f
 	case TN1010_PHY_ID:
 		phy_type = ixgbe_phy_tn;
 		break;
-	case X550_PHY_ID:
+	case X550_PHY_ID1:
+	case X550_PHY_ID2:
+	case X550_PHY_ID3:
 	case X540_PHY_ID:
 		phy_type = ixgbe_phy_aq;
 		break;
@@ -831,7 +833,7 @@ s32 ixgbe_setup_phy_link_generic(struct 
 
 	if (hw->mac.type == ixgbe_mac_X550) {
 		if (speed & IXGBE_LINK_SPEED_5GB_FULL) {
-			/* Set or unset auto-negotiation 1G advertisement */
+			/* Set or unset auto-negotiation 5G advertisement */
 			hw->phy.ops.read_reg(hw,
 				IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
 				IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
@@ -849,7 +851,7 @@ s32 ixgbe_setup_phy_link_generic(struct 
 		}
 
 		if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) {
-			/* Set or unset auto-negotiation 1G advertisement */
+			/* Set or unset auto-negotiation 2.5G advertisement */
 			hw->phy.ops.read_reg(hw,
 				IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
 				IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
@@ -951,54 +953,70 @@ s32 ixgbe_setup_phy_link_speed_generic(s
 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
 
 	/* Setup link based on the new speed settings */
-	hw->phy.ops.setup_link(hw);
+	ixgbe_setup_phy_link(hw);
 
 	return IXGBE_SUCCESS;
 }
 
 /**
- *  ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
- *  @hw: pointer to hardware structure
- *  @speed: pointer to link speed
- *  @autoneg: boolean auto-negotiation value
+ * ixgbe_get_copper_speeds_supported - Get copper link speeds from phy
+ * @hw: pointer to hardware structure
  *
- *  Determines the supported link capabilities by reading the PHY auto
- *  negotiation register.
+ * Determines the supported link capabilities by reading the PHY auto
+ * negotiation register.
  **/
-s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
-					       ixgbe_link_speed *speed,
-					       bool *autoneg)
+static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
 {
 	s32 status;
 	u16 speed_ability;
 
-	DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
-
-	*speed = 0;
-	*autoneg = TRUE;
-
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
 				      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
 				      &speed_ability);
+	if (status)
+		return status;
 
-	if (status == IXGBE_SUCCESS) {
-		if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
-			*speed |= IXGBE_LINK_SPEED_10GB_FULL;
-		if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
-			*speed |= IXGBE_LINK_SPEED_1GB_FULL;
-		if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M)
-			*speed |= IXGBE_LINK_SPEED_100_FULL;
+	if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
+		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL;
+	if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
+		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL;
+	if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M)
+		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_X550:
+		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
+		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
+		break;
+	case ixgbe_mac_X550EM_x:
+		hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
+		break;
+	default:
+		break;
 	}
 
-	/* Internal PHY does not support 100 Mbps */
-	if (hw->mac.type == ixgbe_mac_X550EM_x)
-		*speed &= ~IXGBE_LINK_SPEED_100_FULL;
+	return status;
+}
 
-	if (hw->mac.type == ixgbe_mac_X550) {
-		*speed |= IXGBE_LINK_SPEED_2_5GB_FULL;
-		*speed |= IXGBE_LINK_SPEED_5GB_FULL;
-	}
+/**
+ *  ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
+ *  @hw: pointer to hardware structure
+ *  @speed: pointer to link speed
+ *  @autoneg: boolean auto-negotiation value
+ **/
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+					       ixgbe_link_speed *speed,
+					       bool *autoneg)
+{
+	s32 status = IXGBE_SUCCESS;
+
+	DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic");
+
+	*autoneg = TRUE;
+	if (!hw->phy.speeds_supported)
+		status = ixgbe_get_copper_speeds_supported(hw);
 
+	*speed = hw->phy.speeds_supported;
 	return status;
 }
 

Index: src/sys/dev/pci/ixgbe/ixgbe_common.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_common.c:1.9 src/sys/dev/pci/ixgbe/ixgbe_common.c:1.10
--- src/sys/dev/pci/ixgbe/ixgbe_common.c:1.9	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_common.c	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_common.c 282289 2015-04-30 22:53:27Z erj $*/
-/*$NetBSD: ixgbe_common.c,v 1.9 2016/12/01 06:56:28 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_common.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_common.c,v 1.10 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #include "ixgbe_common.h"
 #include "ixgbe_phy.h"
@@ -71,7 +71,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_
 {
 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
 	struct ixgbe_mac_info *mac = &hw->mac;
-	u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+	u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 	DEBUGFUNC("ixgbe_init_ops_generic");
 
@@ -189,6 +189,7 @@ bool ixgbe_device_supports_autoneg_fc(st
 		case IXGBE_DEV_ID_X540T1:
 		case IXGBE_DEV_ID_X540_BYPASS:
 		case IXGBE_DEV_ID_X550T:
+		case IXGBE_DEV_ID_X550T1:
 		case IXGBE_DEV_ID_X550EM_X_10G_T:
 			supported = TRUE;
 			break;
@@ -1039,7 +1040,7 @@ void ixgbe_set_lan_id_multi_port_pcie(st
 	bus->lan_id = bus->func;
 
 	/* check for a port swap */
-	reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+	reg = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
 	if (reg & IXGBE_FACTPS_LFS)
 		bus->func ^= 0x1;
 }
@@ -1165,7 +1166,7 @@ s32 ixgbe_init_eeprom_params_generic(str
 		 * Check for EEPROM present first.
 		 * If not present leave as none
 		 */
-		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 		if (eec & IXGBE_EEC_PRES) {
 			eeprom->type = ixgbe_eeprom_spi;
 
@@ -1726,14 +1727,14 @@ static s32 ixgbe_acquire_eeprom(struct i
 		status = IXGBE_ERR_SWFW_SYNC;
 
 	if (status == IXGBE_SUCCESS) {
-		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 		/* Request EEPROM Access */
 		eec |= IXGBE_EEC_REQ;
-		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+		IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 
 		for (i = 0; i < IXGBE_EEPROM_GRANT_ATTEMPTS; i++) {
-			eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+			eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 			if (eec & IXGBE_EEC_GNT)
 				break;
 			usec_delay(5);
@@ -1742,7 +1743,7 @@ static s32 ixgbe_acquire_eeprom(struct i
 		/* Release if grant not acquired */
 		if (!(eec & IXGBE_EEC_GNT)) {
 			eec &= ~IXGBE_EEC_REQ;
-			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 			DEBUGOUT("Could not acquire EEPROM grant\n");
 
 			hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
@@ -1753,7 +1754,7 @@ static s32 ixgbe_acquire_eeprom(struct i
 		if (status == IXGBE_SUCCESS) {
 			/* Clear CS and SK */
 			eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
-			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 			IXGBE_WRITE_FLUSH(hw);
 			usec_delay(1);
 		}
@@ -1783,7 +1784,7 @@ static s32 ixgbe_get_eeprom_semaphore(st
 		 * If the SMBI bit is 0 when we read it, then the bit will be
 		 * set and we have the semaphore
 		 */
-		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
 		if (!(swsm & IXGBE_SWSM_SMBI)) {
 			status = IXGBE_SUCCESS;
 			break;
@@ -1808,7 +1809,7 @@ static s32 ixgbe_get_eeprom_semaphore(st
 		 * If the SMBI bit is 0 when we read it, then the bit will be
 		 * set and we have the semaphore
 		 */
-		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
 		if (!(swsm & IXGBE_SWSM_SMBI))
 			status = IXGBE_SUCCESS;
 	}
@@ -1816,17 +1817,17 @@ static s32 ixgbe_get_eeprom_semaphore(st
 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
 	if (status == IXGBE_SUCCESS) {
 		for (i = 0; i < timeout; i++) {
-			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
 
 			/* Set the SW EEPROM semaphore bit to request access */
 			swsm |= IXGBE_SWSM_SWESMBI;
-			IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+			IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
 
 			/*
 			 * If we set the bit successfully then we got the
 			 * semaphore.
 			 */
-			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+			swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
 			if (swsm & IXGBE_SWSM_SWESMBI)
 				break;
 
@@ -1923,15 +1924,15 @@ static void ixgbe_standby_eeprom(struct 
 
 	DEBUGFUNC("ixgbe_standby_eeprom");
 
-	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 	/* Toggle CS to flush commands */
 	eec |= IXGBE_EEC_CS;
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 	IXGBE_WRITE_FLUSH(hw);
 	usec_delay(1);
 	eec &= ~IXGBE_EEC_CS;
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 	IXGBE_WRITE_FLUSH(hw);
 	usec_delay(1);
 }
@@ -1951,7 +1952,7 @@ static void ixgbe_shift_out_eeprom_bits(
 
 	DEBUGFUNC("ixgbe_shift_out_eeprom_bits");
 
-	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 	/*
 	 * Mask is used to shift "count" bits of "data" out to the EEPROM
@@ -1972,7 +1973,7 @@ static void ixgbe_shift_out_eeprom_bits(
 		else
 			eec &= ~IXGBE_EEC_DI;
 
-		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+		IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 		IXGBE_WRITE_FLUSH(hw);
 
 		usec_delay(1);
@@ -1989,7 +1990,7 @@ static void ixgbe_shift_out_eeprom_bits(
 
 	/* We leave the "DI" bit set to "0" when we leave this routine. */
 	eec &= ~IXGBE_EEC_DI;
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 	IXGBE_WRITE_FLUSH(hw);
 }
 
@@ -2012,7 +2013,7 @@ static u16 ixgbe_shift_in_eeprom_bits(st
 	 * the value of the "DO" bit.  During this "shifting in" process the
 	 * "DI" bit should always be clear.
 	 */
-	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 	eec &= ~(IXGBE_EEC_DO | IXGBE_EEC_DI);
 
@@ -2020,7 +2021,7 @@ static u16 ixgbe_shift_in_eeprom_bits(st
 		data = data << 1;
 		ixgbe_raise_eeprom_clk(hw, &eec);
 
-		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 		eec &= ~(IXGBE_EEC_DI);
 		if (eec & IXGBE_EEC_DO)
@@ -2046,7 +2047,7 @@ static void ixgbe_raise_eeprom_clk(struc
 	 * (setting the SK bit), then delay
 	 */
 	*eec = *eec | IXGBE_EEC_SK;
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
 	IXGBE_WRITE_FLUSH(hw);
 	usec_delay(1);
 }
@@ -2065,7 +2066,7 @@ static void ixgbe_lower_eeprom_clk(struc
 	 * delay
 	 */
 	*eec = *eec & ~IXGBE_EEC_SK;
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, *eec);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), *eec);
 	IXGBE_WRITE_FLUSH(hw);
 	usec_delay(1);
 }
@@ -2080,19 +2081,19 @@ static void ixgbe_release_eeprom(struct 
 
 	DEBUGFUNC("ixgbe_release_eeprom");
 
-	eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+	eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 	eec |= IXGBE_EEC_CS;  /* Pull CS high */
 	eec &= ~IXGBE_EEC_SK; /* Lower SCK */
 
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 	IXGBE_WRITE_FLUSH(hw);
 
 	usec_delay(1);
 
 	/* Stop requesting EEPROM access */
 	eec &= ~IXGBE_EEC_REQ;
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), eec);
 
 	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 
@@ -3148,6 +3149,9 @@ s32 ixgbe_disable_pcie_master(struct ixg
 	DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n");
 	hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
 
+	if (hw->mac.type >= ixgbe_mac_X550)
+		goto out;
+
 	/*
 	 * Before proceeding, make sure that the PCIe block does not have
 	 * transactions pending.
@@ -4070,7 +4074,7 @@ s32 ixgbe_check_mac_link_generic(struct 
 	}
 
 	if (link_up_wait_to_complete) {
-		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+		for (i = 0; i < hw->mac.max_link_up_time; i++) {
 			if (links_reg & IXGBE_LINKS_UP) {
 				*link_up = TRUE;
 				break;
@@ -4716,7 +4720,7 @@ bool ixgbe_mng_present(struct ixgbe_hw *
 	if (hw->mac.type < ixgbe_mac_82599EB)
 		return FALSE;
 
-	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
 	fwsm &= IXGBE_FWSM_MODE_MASK;
 	return fwsm == IXGBE_FWSM_FW_MODE_PT;
 }
@@ -4731,7 +4735,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *
 {
 	u32 fwsm, manc, factps;
 
-	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
 	if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
 		return FALSE;
 
@@ -4740,7 +4744,7 @@ bool ixgbe_mng_enabled(struct ixgbe_hw *
 		return FALSE;
 
 	if (hw->mac.type <= ixgbe_mac_X540) {
-		factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+		factps = IXGBE_READ_REG(hw, IXGBE_FACTPS_BY_MAC(hw));
 		if (factps & IXGBE_FACTPS_MNGCG)
 			return FALSE;
 	}
Index: src/sys/dev/pci/ixgbe/ixgbe_mbx.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.9 src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10
--- src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.9	Fri Dec  2 10:34:23 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_mbx.h	Fri Dec  2 10:42:04 2016
@@ -31,7 +31,7 @@
 
 ******************************************************************************/
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_mbx.h 283883 2015-06-01 17:43:34Z jfv $*/
-/*$NetBSD: ixgbe_mbx.h,v 1.9 2016/12/02 10:34:23 msaitoh Exp $*/
+/*$NetBSD: ixgbe_mbx.h,v 1.10 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #ifndef _IXGBE_MBX_H_
 #define _IXGBE_MBX_H_

Index: src/sys/dev/pci/ixgbe/ixgbe_dcb.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_dcb.c:1.3 src/sys/dev/pci/ixgbe/ixgbe_dcb.c:1.4
--- src/sys/dev/pci/ixgbe/ixgbe_dcb.c:1.3	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_dcb.c	Fri Dec  2 10:42:04 2016
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_dcb.c 282289 2015-04-30 22:53:27Z erj $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_dcb.c 292674 2015-12-23 22:45:17Z sbruno $*/
 
 
 #include "ixgbe_type.h"
@@ -148,6 +148,11 @@ s32 ixgbe_dcb_calculate_tc_credits_cee(s
 		/* Calculate credit refill ratio using multiplier */
 		credit_refill = min(link_percentage * min_multiplier,
 				    (u32)IXGBE_DCB_MAX_CREDIT_REFILL);
+
+		/* Refill at least minimum credit */
+		if (credit_refill < min_credit)
+			credit_refill = min_credit;
+
 		p->data_credits_refill = (u16)credit_refill;
 
 		/* Calculate maximum credit for the TC */
@@ -158,7 +163,7 @@ s32 ixgbe_dcb_calculate_tc_credits_cee(s
 		 * of a TC is too small, the maximum credit may not be
 		 * enough to send out a jumbo frame in data plane arbitration.
 		 */
-		if (credit_max && (credit_max < min_credit))
+		if (credit_max < min_credit)
 			credit_max = min_credit;
 
 		if (direction == IXGBE_DCB_TX_CONFIG) {

Index: src/sys/dev/pci/ixgbe/ixgbe_vf.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.11 src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12
--- src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.11	Fri Dec  2 10:34:23 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_vf.c	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_vf.c 285590 2015-07-15 00:35:50Z pkelsey $*/
-/*$NetBSD: ixgbe_vf.c,v 1.11 2016/12/02 10:34:23 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_vf.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixgbe_vf.c,v 1.12 2016/12/02 10:42:04 msaitoh Exp $*/
 
 
 #include "ixgbe_api.h"
@@ -226,8 +226,6 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h
 	if (ret_val)
 		return ret_val;
 
-	msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
-
 	if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK) &&
 	    msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_NACK))
 		return IXGBE_ERR_INVALID_MAC_ADDR;

Index: src/sys/dev/pci/ixgbe/ixgbe_x540.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.6 src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.7
--- src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.6	Thu Dec  1 06:56:28 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_x540.c	Fri Dec  2 10:42:04 2016
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x540.c 282289 2015-04-30 22:53:27Z erj $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x540.c 292674 2015-12-23 22:45:17Z sbruno $*/
 
 #include "ixgbe_x540.h"
 #include "ixgbe_type.h"
@@ -138,8 +138,8 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw 
 	 * ARC supported; valid only if manageability features are
 	 * enabled.
 	 */
-	mac->arc_subsystem_valid = (IXGBE_READ_REG(hw, IXGBE_FWSM) &
-				   IXGBE_FWSM_MODE_MASK) ? TRUE : FALSE;
+	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
+				     & IXGBE_FWSM_MODE_MASK);
 
 	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
 
@@ -356,7 +356,7 @@ s32 ixgbe_init_eeprom_params_X540(struct
 		eeprom->semaphore_delay = 10;
 		eeprom->type = ixgbe_flash;
 
-		eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+		eec = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 		eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >>
 				    IXGBE_EEC_SIZE_SHIFT);
 		eeprom->word_size = 1 << (eeprom_size +
@@ -681,8 +681,8 @@ s32 ixgbe_update_flash_X540(struct ixgbe
 		goto out;
 	}
 
-	flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
-	IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+	flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw)) | IXGBE_EEC_FLUP;
+	IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
 
 	status = ixgbe_poll_flash_update_done_X540(hw);
 	if (status == IXGBE_SUCCESS)
@@ -691,11 +691,11 @@ s32 ixgbe_update_flash_X540(struct ixgbe
 		DEBUGOUT("Flash update time out\n");
 
 	if (hw->mac.type == ixgbe_mac_X540 && hw->revision_id == 0) {
-		flup = IXGBE_READ_REG(hw, IXGBE_EEC);
+		flup = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 
 		if (flup & IXGBE_EEC_SEC1VAL) {
 			flup |= IXGBE_EEC_FLUP;
-			IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+			IXGBE_WRITE_REG(hw, IXGBE_EEC_BY_MAC(hw), flup);
 		}
 
 		status = ixgbe_poll_flash_update_done_X540(hw);
@@ -724,7 +724,7 @@ static s32 ixgbe_poll_flash_update_done_
 	DEBUGFUNC("ixgbe_poll_flash_update_done_X540");
 
 	for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
-		reg = IXGBE_READ_REG(hw, IXGBE_EEC);
+		reg = IXGBE_READ_REG(hw, IXGBE_EEC_BY_MAC(hw));
 		if (reg & IXGBE_EEC_FLUDONE) {
 			status = IXGBE_SUCCESS;
 			break;
@@ -775,10 +775,11 @@ s32 ixgbe_acquire_swfw_sync_X540(struct 
 		if (ixgbe_get_swfw_sync_semaphore(hw))
 			return IXGBE_ERR_SWFW_SYNC;
 
-		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
 		if (!(swfw_sync & (fwmask | swmask | hwmask))) {
 			swfw_sync |= swmask;
-			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+			IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw),
+					swfw_sync);
 			ixgbe_release_swfw_sync_semaphore(hw);
 			msec_delay(5);
 			return IXGBE_SUCCESS;
@@ -805,10 +806,10 @@ s32 ixgbe_acquire_swfw_sync_X540(struct 
 	 */
 	if (ixgbe_get_swfw_sync_semaphore(hw))
 		return IXGBE_ERR_SWFW_SYNC;
-	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
 	if (swfw_sync & (fwmask | hwmask)) {
 		swfw_sync |= swmask;
-		IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+		IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
 		ixgbe_release_swfw_sync_semaphore(hw);
 		msec_delay(5);
 		return IXGBE_SUCCESS;
@@ -852,9 +853,9 @@ void ixgbe_release_swfw_sync_X540(struct
 		swmask |= mask & IXGBE_GSSR_I2C_MASK;
 	ixgbe_get_swfw_sync_semaphore(hw);
 
-	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
 	swfw_sync &= ~swmask;
-	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync);
 
 	ixgbe_release_swfw_sync_semaphore(hw);
 	msec_delay(5);
@@ -881,7 +882,7 @@ static s32 ixgbe_get_swfw_sync_semaphore
 		 * If the SMBI bit is 0 when we read it, then the bit will be
 		 * set and we have the semaphore
 		 */
-		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
 		if (!(swsm & IXGBE_SWSM_SMBI)) {
 			status = IXGBE_SUCCESS;
 			break;
@@ -892,7 +893,7 @@ static s32 ixgbe_get_swfw_sync_semaphore
 	/* Now get the semaphore between SW/FW through the REGSMP bit */
 	if (status == IXGBE_SUCCESS) {
 		for (i = 0; i < timeout; i++) {
-			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+			swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
 			if (!(swsm & IXGBE_SWFW_REGSMP))
 				break;
 
@@ -932,13 +933,13 @@ static void ixgbe_release_swfw_sync_sema
 
 	/* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
 
-	swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+	swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
 	swsm &= ~IXGBE_SWFW_REGSMP;
-	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm);
+	IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swsm);
 
-	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+	swsm = IXGBE_READ_REG(hw, IXGBE_SWSM_BY_MAC(hw));
 	swsm &= ~IXGBE_SWSM_SMBI;
-	IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+	IXGBE_WRITE_REG(hw, IXGBE_SWSM_BY_MAC(hw), swsm);
 
 	IXGBE_WRITE_FLUSH(hw);
 }

Index: src/sys/dev/pci/ixgbe/ixgbe_x550.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.1 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.2
--- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.1	Thu Dec  1 07:44:58 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.c	Fri Dec  2 10:42:04 2016
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x550.c 282289 2015-04-30 22:53:27Z erj $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x550.c 292674 2015-12-23 22:45:17Z sbruno $*/
 
 #include "ixgbe_x550.h"
 #include "ixgbe_x540.h"
@@ -115,119 +115,6 @@ static s32 ixgbe_write_cs4227(struct ixg
 }
 
 /**
- * ixgbe_get_cs4227_status - Return CS4227 status
- * @hw: pointer to hardware structure
- *
- * Returns error if CS4227 not successfully initialized
- **/
-static s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw)
-{
-	s32 status;
-	u16 value = 0;
-	u16 reg_slice, reg_val;
-	u8 retry;
-
-	for (retry = 0; retry < IXGBE_CS4227_RETRIES; ++retry) {
-		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_GLOBAL_ID_LSB,
-					   &value);
-		if (status != IXGBE_SUCCESS)
-			return status;
-		if (value == IXGBE_CS4227_GLOBAL_ID_VALUE)
-			break;
-		msec_delay(IXGBE_CS4227_CHECK_DELAY);
-	}
-	if (value != IXGBE_CS4227_GLOBAL_ID_VALUE)
-		return IXGBE_ERR_PHY;
-
-	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
-	if (status != IXGBE_SUCCESS)
-		return status;
-
-	/* If this is the first time after power-on, check the ucode.
-	 * Otherwise, this will disrupt link on all ports. Because we
-	 * can only do this the first time, we must check all ports,
-	 * not just our own.
-	 */
-	if (value != IXGBE_CS4227_SCRATCH_VALUE) {
-		reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB;
-		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
-		status = ixgbe_write_cs4227(hw, reg_slice,
-					    reg_val);
-		if (status != IXGBE_SUCCESS)
-			return status;
-
-		reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB;
-		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
-		status = ixgbe_write_cs4227(hw, reg_slice,
-					    reg_val);
-		if (status != IXGBE_SUCCESS)
-			return status;
-
-		reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12);
-		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
-		status = ixgbe_write_cs4227(hw, reg_slice,
-					    reg_val);
-		if (status != IXGBE_SUCCESS)
-			return status;
-
-		reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12);
-		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
-		status = ixgbe_write_cs4227(hw, reg_slice,
-					    reg_val);
-		if (status != IXGBE_SUCCESS)
-			return status;
-
-		msec_delay(10);
-	}
-
-	/* Verify that the ucode is operational on all ports. */
-	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB;
-	reg_val = 0xFFFF;
-	status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
-	if (status != IXGBE_SUCCESS)
-		return status;
-	if (reg_val != 0)
-		return IXGBE_ERR_PHY;
-
-	reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB;
-	reg_val = 0xFFFF;
-	status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
-	if (status != IXGBE_SUCCESS)
-		return status;
-	if (reg_val != 0)
-		return IXGBE_ERR_PHY;
-
-	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (1 << 12);
-	reg_val = 0xFFFF;
-	status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
-	if (status != IXGBE_SUCCESS)
-		return status;
-	if (reg_val != 0)
-		return IXGBE_ERR_PHY;
-
-	reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (1 << 12);
-	reg_val = 0xFFFF;
-	status = ixgbe_read_cs4227(hw, reg_slice, &reg_val);
-	if (status != IXGBE_SUCCESS)
-		return status;
-	if (reg_val != 0)
-		return IXGBE_ERR_PHY;
-
-	/* Set scratch for next time. */
-	status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
-				    IXGBE_CS4227_SCRATCH_VALUE);
-	if (status != IXGBE_SUCCESS)
-		return status;
-	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
-	if (status != IXGBE_SUCCESS)
-		return status;
-	if (value != IXGBE_CS4227_SCRATCH_VALUE)
-		return IXGBE_ERR_PHY;
-
-	return IXGBE_SUCCESS;
-}
-
-/**
  * ixgbe_read_pe - Read register from port expander
  * @hw: pointer to hardware structure
  * @reg: register number to read
@@ -269,13 +156,17 @@ static s32 ixgbe_write_pe(struct ixgbe_h
  * ixgbe_reset_cs4227 - Reset CS4227 using port expander
  * @hw: pointer to hardware structure
  *
+ * This function assumes that the caller has acquired the proper semaphore.
  * Returns error code
  **/
 static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw)
 {
 	s32 status;
+	u32 retry;
+	u16 value;
 	u8 reg;
 
+	/* Trigger hard reset. */
 	status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, &reg);
 	if (status != IXGBE_SUCCESS)
 		return status;
@@ -310,7 +201,29 @@ static s32 ixgbe_reset_cs4227(struct ixg
 	if (status != IXGBE_SUCCESS)
 		return status;
 
+	/* Wait for the reset to complete. */
 	msec_delay(IXGBE_CS4227_RESET_DELAY);
+	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
+		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS,
+					   &value);
+		if (status == IXGBE_SUCCESS &&
+		    value == IXGBE_CS4227_EEPROM_LOAD_OK)
+			break;
+		msec_delay(IXGBE_CS4227_CHECK_DELAY);
+	}
+	if (retry == IXGBE_CS4227_RETRIES) {
+		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
+			"CS4227 reset did not complete.");
+		return IXGBE_ERR_PHY;
+	}
+
+	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
+	if (status != IXGBE_SUCCESS ||
+	    !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
+		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
+			"CS4227 EEPROM did not load successfully.");
+		return IXGBE_ERR_PHY;
+	}
 
 	return IXGBE_SUCCESS;
 }
@@ -321,29 +234,75 @@ static s32 ixgbe_reset_cs4227(struct ixg
  **/
 static void ixgbe_check_cs4227(struct ixgbe_hw *hw)
 {
+	s32 status = IXGBE_SUCCESS;
 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
-	s32 status;
+	u16 value = 0;
 	u8 retry;
 
 	for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) {
 		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
 		if (status != IXGBE_SUCCESS) {
 			ERROR_REPORT2(IXGBE_ERROR_CAUTION,
-				      "semaphore failed with %d\n", status);
-			return;
+				"semaphore failed with %d", status);
+			msec_delay(IXGBE_CS4227_CHECK_DELAY);
+			continue;
 		}
-		status = ixgbe_get_cs4227_status(hw);
-		if (status == IXGBE_SUCCESS) {
-			hw->mac.ops.release_swfw_sync(hw, swfw_mask);
-			msec_delay(hw->eeprom.semaphore_delay);
+
+		/* Get status of reset flow. */
+		status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value);
+
+		if (status == IXGBE_SUCCESS &&
+		    value == IXGBE_CS4227_RESET_COMPLETE)
+			goto out;
+
+		if (status != IXGBE_SUCCESS ||
+		    value != IXGBE_CS4227_RESET_PENDING)
+			break;
+
+		/* Reset is pending. Wait and check again. */
+		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+		msec_delay(IXGBE_CS4227_CHECK_DELAY);
+	}
+
+	/* If still pending, assume other instance failed. */
+	if (retry == IXGBE_CS4227_RETRIES) {
+		status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+		if (status != IXGBE_SUCCESS) {
+			ERROR_REPORT2(IXGBE_ERROR_CAUTION,
+				      "semaphore failed with %d", status);
 			return;
 		}
-		ixgbe_reset_cs4227(hw);
-		hw->mac.ops.release_swfw_sync(hw, swfw_mask);
-		msec_delay(hw->eeprom.semaphore_delay);
 	}
-	ERROR_REPORT2(IXGBE_ERROR_CAUTION,
-		      "Unable to initialize CS4227, err=%d\n", status);
+
+	/* Reset the CS4227. */
+	status = ixgbe_reset_cs4227(hw);
+	if (status != IXGBE_SUCCESS) {
+		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+			"CS4227 reset failed: %d", status);
+		goto out;
+	}
+
+	/* Reset takes so long, temporarily release semaphore in case the
+	 * other driver instance is waiting for the reset indication.
+	 */
+	ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
+			   IXGBE_CS4227_RESET_PENDING);
+	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+	msec_delay(10);
+	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+	if (status != IXGBE_SUCCESS) {
+		ERROR_REPORT2(IXGBE_ERROR_CAUTION,
+			"semaphore failed with %d", status);
+		return;
+	}
+
+	/* Record completion for next time. */
+	status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH,
+		IXGBE_CS4227_RESET_COMPLETE);
+
+out:
+	hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+	msec_delay(hw->eeprom.semaphore_delay);
 }
 
 /**
@@ -452,8 +411,11 @@ s32 ixgbe_init_ops_X550EM(struct ixgbe_h
 	hw->bus.type = ixgbe_bus_type_internal;
 	mac->ops.get_bus_info = ixgbe_get_bus_info_X550em;
 
-	mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
-	mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
+	if (hw->mac.type == ixgbe_mac_X550EM_x) {
+		mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550;
+		mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550;
+	}
+
 	mac->ops.get_media_type = ixgbe_get_media_type_X550em;
 	mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em;
 	mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em;
@@ -679,7 +641,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw
 	if (enable_eee) {
 		eeer |= (IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
 
-		if (hw->device_id == IXGBE_DEV_ID_X550T) {
+		if (hw->mac.type == ixgbe_mac_X550) {
 			/* Advertise EEE capability */
 			hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
 				IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg);
@@ -717,7 +679,7 @@ s32 ixgbe_setup_eee_X550(struct ixgbe_hw
 	} else {
 		eeer &= ~(IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
 
-		if (hw->device_id == IXGBE_DEV_ID_X550T) {
+		if (hw->mac.type == ixgbe_mac_X550) {
 			/* Disable advertised EEE capability */
 			hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT,
 				IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_eee_reg);
@@ -1444,8 +1406,6 @@ static s32 ixgbe_setup_kr_speed_x550em(s
 		return status;
 
 	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
-	reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_FEC_REQ |
-		     IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC);
 	reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR |
 		     IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX);
 
@@ -1492,14 +1452,10 @@ s32 ixgbe_init_phy_ops_X550em(struct ixg
 		 * to determine internal PHY mode.
 		 */
 		phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL);
-
-		/* If internal PHY mode is KR, then initialize KR link */
 		if (phy->nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE) {
 			speed = IXGBE_LINK_SPEED_10GB_FULL |
 				IXGBE_LINK_SPEED_1GB_FULL;
-			ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
 		}
-
 		phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em;
 	}
 
@@ -1516,7 +1472,7 @@ s32 ixgbe_init_phy_ops_X550em(struct ixg
 	/* Set functions pointers based on phy type */
 	switch (hw->phy.type) {
 	case ixgbe_phy_x550em_kx4:
-		phy->ops.setup_link = ixgbe_setup_kx4_x550em;
+		phy->ops.setup_link = NULL;
 		phy->ops.read_reg = ixgbe_read_phy_reg_x550em;
 		phy->ops.write_reg = ixgbe_write_phy_reg_x550em;
 		break;
@@ -1543,7 +1499,11 @@ s32 ixgbe_init_phy_ops_X550em(struct ixg
 			ret_val = ixgbe_setup_kr_speed_x550em(hw, speed);
 		}
 
-		phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
+		/* setup SW LPLU only for first revision */
+		if (!(IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw,
+						       IXGBE_FUSES0_GROUP(0))))
+			phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em;
+
 		phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em;
 		phy->ops.reset = ixgbe_reset_phy_t_X550em;
 		break;
@@ -1580,9 +1540,14 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_h
 	/* flush pending Tx transactions */
 	ixgbe_clear_tx_pending(hw);
 
-	/* PHY ops must be identified and initialized prior to reset */
+	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
+		/* Config MDIO clock speed before the first MDIO PHY access */
+		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+		hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
+		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+	}
 
-	/* Identify PHY and related function pointers */
+	/* PHY ops must be identified and initialized prior to reset */
 	status = hw->phy.ops.init(hw);
 
 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
@@ -1659,13 +1624,6 @@ mac_reset_top:
 	hw->mac.num_rar_entries = 128;
 	hw->mac.ops.init_rx_addrs(hw);
 
-	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_10G_T) {
-		/* Config MDIO clock speed. */
-		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
-		hlreg0 &= ~IXGBE_HLREG0_MDCSPD;
-		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
-	}
-
 	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP)
 		ixgbe_setup_mux_ctl(hw);
 
@@ -1727,43 +1685,6 @@ s32 ixgbe_setup_kr_x550em(struct ixgbe_h
 }
 
 /**
- *  ixgbe_setup_kx4_x550em - Configure the KX4 PHY.
- *  @hw: pointer to hardware structure
- *
- *  Configures the integrated KX4 PHY.
- **/
-s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw)
-{
-	s32 status;
-	u32 reg_val;
-
-	status = ixgbe_read_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1,
-		IXGBE_SB_IOSF_TARGET_KX4_PCS, &reg_val);
-	if (status)
-		return status;
-
-	reg_val &= ~(IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4 |
-			IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX);
-
-	reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_ENABLE;
-
-	/* Advertise 10G support. */
-	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
-		reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX4;
-
-	/* Advertise 1G support. */
-	if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
-		reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_CAP_KX;
-
-	/* Restart auto-negotiation. */
-	reg_val |= IXGBE_KX4_LINK_CNTL_1_TETH_AN_RESTART;
-	status = ixgbe_write_iosf_sb_reg_x550(hw, IXGBE_KX4_LINK_CNTL_1,
-		IXGBE_SB_IOSF_TARGET_KX4_PCS, reg_val);
-
-	return status;
-}
-
-/**
  *  ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP
  *  @hw: pointer to hardware structure
  *
@@ -1791,38 +1712,53 @@ s32 ixgbe_setup_mac_link_sfp_x550em(stru
 	if (ret_val != IXGBE_SUCCESS)
 		return ret_val;
 
-	/* Configure CS4227 for LINE connection rate then type. */
-	reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12);
-	reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
-	ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
-					   reg_val);
-
-	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
-	if (setup_linear)
-		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
-	else
-		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
-	ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
-					   reg_val);
+	if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
+		/* Configure CS4227 LINE side to 10G SR. */
+		reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB +
+			    (hw->bus.lan_id << 12);
+		reg_val = IXGBE_CS4227_SPEED_10G;
+		ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+						   reg_val);
 
-	/* Configure CS4227 for HOST connection rate then type. */
-	reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12);
-	reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
-	ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
-					   reg_val);
-
-	reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12);
-	if (setup_linear)
-		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
-	else
+		reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
+			    (hw->bus.lan_id << 12);
 		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
-	ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
-					   reg_val);
+		ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+						   reg_val);
 
-	/* If internal link mode is XFI, then setup XFI internal link. */
-	if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))
+		/* Configure CS4227 for HOST connection rate then type. */
+		reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB +
+			    (hw->bus.lan_id << 12);
+		reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ?
+		IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G;
+		ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+						   reg_val);
+
+		reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB +
+			    (hw->bus.lan_id << 12);
+		if (setup_linear)
+			reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+		else
+			reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+		ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+						   reg_val);
+
+		/* Setup XFI internal link. */
 		ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
+	} else {
+		/* Configure internal PHY for KR/KX. */
+		ixgbe_setup_kr_speed_x550em(hw, speed);
 
+		/* Configure CS4227 LINE side to proper mode. */
+		reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB +
+			    (hw->bus.lan_id << 12);
+		if (setup_linear)
+			reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+		else
+			reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+		ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+						   reg_val);
+	}
 	return ret_val;
 }
 
@@ -2743,6 +2679,10 @@ s32 ixgbe_enter_lplu_t_x550em(struct ixg
 	u32 save_autoneg;
 	bool link_up;
 
+	/* SW LPLU not required on later HW revisions. */
+	if (IXGBE_FUSES0_REV1 & IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))
+		return IXGBE_SUCCESS;
+
 	/* If blocked by MNG FW, then don't restart AN */
 	if (ixgbe_check_reset_blocked(hw))
 		return IXGBE_SUCCESS;
@@ -2924,7 +2864,7 @@ s32 ixgbe_setup_fc_X550em(struct ixgbe_h
 		goto out;
 	}
 
-	if (hw->phy.media_type == ixgbe_media_type_backplane) {
+	if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR) {
 		ret_val = ixgbe_read_iosf_sb_reg_x550(hw,
 			IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
 			IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
@@ -2940,9 +2880,8 @@ s32 ixgbe_setup_fc_X550em(struct ixgbe_h
 			IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
 			IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
 
-		/* Not all devices fully support AN. */
-		if (hw->device_id == IXGBE_DEV_ID_X550EM_X_KR)
-			hw->fc.disable_fc_autoneg = TRUE;
+		/* This device does not fully support AN. */
+		hw->fc.disable_fc_autoneg = TRUE;
 	}
 
 out:
Index: src/sys/dev/pci/ixgbe/ixgbe_x550.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.1 src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.2
--- src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.1	Thu Dec  1 07:44:58 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.h	Fri Dec  2 10:42:04 2016
@@ -30,7 +30,7 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x550.h 282289 2015-04-30 22:53:27Z erj $*/
+/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x550.h 292674 2015-12-23 22:45:17Z sbruno $*/
 
 #ifndef _IXGBE_X550_H_
 #define _IXGBE_X550_H_
@@ -69,7 +69,7 @@ void ixgbe_set_ethertype_anti_spoofing_X
 s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
 				 u32 device_type, u32 data);
 s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr,
-				u32 device_type, u32 *data);
+	u32 device_type, u32 *data);
 void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw);
 void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw);
 void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap);
@@ -82,7 +82,6 @@ void ixgbe_init_mac_link_ops_X550em(stru
 s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw);
 s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw);
 s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw);
-s32 ixgbe_setup_kx4_x550em(struct ixgbe_hw *hw);
 s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw);
 s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw);
 s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw);

Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.25 src/sys/dev/pci/ixgbe/ixv.c:1.26
--- src/sys/dev/pci/ixgbe/ixv.c:1.25	Fri Dec  2 10:34:23 2016
+++ src/sys/dev/pci/ixgbe/ixv.c	Fri Dec  2 10:42:04 2016
@@ -30,8 +30,8 @@
   POSSIBILITY OF SUCH DAMAGE.
 
 ******************************************************************************/
-/*$FreeBSD: head/sys/dev/ixgbe/if_ixv.c 289238 2015-10-13 17:34:18Z sbruno $*/
-/*$NetBSD: ixv.c,v 1.25 2016/12/02 10:34:23 msaitoh Exp $*/
+/*$FreeBSD: head/sys/dev/ixgbe/if_ixv.c 292674 2015-12-23 22:45:17Z sbruno $*/
+/*$NetBSD: ixv.c,v 1.26 2016/12/02 10:42:04 msaitoh Exp $*/
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -42,7 +42,7 @@
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixv_driver_version[] = "1.4.0";
+char ixv_driver_version[] = "1.4.6-k";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -330,8 +330,14 @@ ixv_attach(device_t parent, device_t dev
 
 	/* Allocate, clear, and link in our adapter structure */
 	adapter = device_private(dev);
-	adapter->dev = adapter->osdep.dev = dev;
+	adapter->dev = dev;
 	hw = &adapter->hw;
+
+#ifdef DEV_NETMAP
+	adapter->init_locked = ixv_init_locked;
+	adapter->stop_locked = ixv_stop;
+#endif
+
 	adapter->osdep.pc = pa->pa_pc;
 	adapter->osdep.tag = pa->pa_tag;
 	adapter->osdep.dmat = pa->pa_dmat;
@@ -344,11 +350,6 @@ ixv_attach(device_t parent, device_t dev
 	aprint_normal(": %s, Version - %s\n",
 	    ixv_strings[ent->index], ixv_driver_version);
 
-#ifdef DEV_NETMAP
-	adapter->init_locked = ixv_init_locked;
-	adapter->stop_locked = ixv_stop;
-#endif
-
 	/* Core Lock Init*/
 	IXGBE_CORE_LOCK_INIT(adapter, device_xname(dev));
 
@@ -363,7 +364,7 @@ ixv_attach(device_t parent, device_t dev
 
 	/* Do base PCI setup - map BAR0 */
 	if (ixv_allocate_pci_resources(adapter, pa)) {
-		aprint_error_dev(dev, "Allocation of PCI resources failed\n");
+		aprint_error_dev(dev, "ixv_allocate_pci_resources() failed!\n");
 		error = ENXIO;
 		goto err_out;
 	}
@@ -394,6 +395,7 @@ ixv_attach(device_t parent, device_t dev
 
 	/* Allocate our TX/RX Queues */
 	if (ixgbe_allocate_queues(adapter)) {
+		aprint_error_dev(dev, "ixgbe_allocate_queues() failed!\n");
 		error = ENOMEM;
 		goto err_out;
 	}
@@ -404,7 +406,7 @@ ixv_attach(device_t parent, device_t dev
 	*/
 	error = ixgbe_init_shared_code(hw);
 	if (error) {
-		aprint_error_dev(dev,"Shared Code Initialization Failure\n");
+		aprint_error_dev(dev, "ixgbe_init_shared_code() failed!\n");
 		error = EIO;
 		goto err_late;
 	}
@@ -412,23 +414,37 @@ ixv_attach(device_t parent, device_t dev
 	/* Setup the mailbox */
 	ixgbe_init_mbx_params_vf(hw);
 
-	ixgbe_reset_hw(hw);
+	/* Reset mbox api to 1.0 */
+	error = ixgbe_reset_hw(hw);
+	if (error == IXGBE_ERR_RESET_FAILED)
+		aprint_error_dev(dev, "ixgbe_reset_hw() failure: Reset Failed!\n");
+	else if (error)
+		aprint_error_dev(dev, "ixgbe_reset_hw() failed with error %d\n", error);
+	if (error) {
+		error = EIO;
+		goto err_late;
+	}
 
-	/* Get the Mailbox API version */
-	device_printf(dev,"MBX API %d negotiation: %d\n",
-	    ixgbe_mbox_api_11,
-	    ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11));
+	/* Negotiate mailbox API version */
+	error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
+	if (error) {
+		device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
+		error = EIO;
+		goto err_late;
+	}
 
 	error = ixgbe_init_hw(hw);
 	if (error) {
-		aprint_error_dev(dev,"Hardware Initialization Failure\n");
+		aprint_error_dev(dev, "ixgbe_init_hw() failed!\n");
 		error = EIO;
 		goto err_late;
 	}
 	
 	error = ixv_allocate_msix(adapter, pa); 
-	if (error) 
+	if (error) {
+		device_printf(dev, "ixv_allocate_msix() failed!\n");
 		goto err_late;
+	}
 
 	/* If no mac address was assigned, make a random one */
 	if (!ixv_check_ether_addr(hw->mac.addr)) {
@@ -500,7 +516,7 @@ ixv_detach(device_t dev, int flags)
 	else if ((flags & (DETACH_SHUTDOWN|DETACH_FORCE)) != 0)
 		vlan_ifdetach(adapter->ifp);
 	else {
-		aprint_error_dev(dev, "VLANs in use\n");
+		aprint_error_dev(dev, "VLANs in use, detach first\n");
 		return EBUSY;
 	}
 #endif
@@ -683,9 +699,9 @@ ixv_init_locked(struct adapter *adapter)
 	struct ifnet	*ifp = adapter->ifp;
 	device_t 	dev = adapter->dev;
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32		mhadd, gpie;
+	int error = 0;
 
-	INIT_DEBUGOUT("ixv_init: begin");
+	INIT_DEBUGOUT("ixv_init_locked: begin");
 	KASSERT(mutex_owned(&adapter->core_mtx));
 	hw->adapter_stopped = FALSE;
 	ixgbe_stop_adapter(hw);
@@ -702,12 +718,17 @@ ixv_init_locked(struct adapter *adapter)
 
 	/* Prepare transmit descriptors and buffers */
 	if (ixgbe_setup_transmit_structures(adapter)) {
-		aprint_error_dev(dev,"Could not setup transmit structures\n");
+		aprint_error_dev(dev, "Could not setup transmit structures\n");
 		ixv_stop(adapter);
 		return;
 	}
 
+	/* Reset VF and renegotiate mailbox API version */
 	ixgbe_reset_hw(hw);
+	error = ixgbevf_negotiate_api_version(hw, ixgbe_mbox_api_11);
+	if (error)
+		device_printf(dev, "MBX API 1.1 negotiation failed! Error %d\n", error);
+
 	ixv_initialize_transmit_units(adapter);
 
 	/* Setup Multicast table */
@@ -724,7 +745,7 @@ ixv_init_locked(struct adapter *adapter)
 
 	/* Prepare receive descriptors and buffers */
 	if (ixgbe_setup_receive_structures(adapter)) {
-		device_printf(dev,"Could not setup receive structures\n");
+		device_printf(dev, "Could not setup receive structures\n");
 		ixv_stop(adapter);
 		return;
 	}
@@ -732,12 +753,6 @@ ixv_init_locked(struct adapter *adapter)
 	/* Configure RX settings */
 	ixv_initialize_receive_units(adapter);
 
-	/* Enable Enhanced MSIX mode */
-	gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
-	gpie |= IXGBE_GPIE_MSIX_MODE | IXGBE_GPIE_EIAME;
-	gpie |= IXGBE_GPIE_PBA_SUPPORT | IXGBE_GPIE_OCD;
-        IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
-
 #if 0 /* XXX isn't it required? -- msaitoh  */
 	/* Set the various hardware offload abilities */
 	ifp->if_hwassist = 0;
@@ -751,19 +766,9 @@ ixv_init_locked(struct adapter *adapter)
 	}
 #endif
 	
-	/* Set MTU size */
-	if (ifp->if_mtu > ETHERMTU) {
-		mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
-		mhadd &= ~IXGBE_MHADD_MFS_MASK;
-		mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
-		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
-	}
-
 	/* Set up VLAN offload and filter */
 	ixv_setup_vlan_support(adapter);
 
-	callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
-
 	/* Set up MSI/X routing */
 	ixv_configure_ivars(adapter);
 
@@ -779,6 +784,9 @@ ixv_init_locked(struct adapter *adapter)
 	/* Config/Enable Link */
 	ixv_config_link(adapter);
 
+	/* Start watchdog */
+	callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
+
 	/* And now turn on interrupts */
 	ixv_enable_intr(adapter);
 
@@ -1506,7 +1514,7 @@ map_err:
 	/* Pick up the tuneable queues */
 	adapter->num_queues = ixv_num_queues;
 
-	adapter->hw.back = &adapter->osdep;
+	adapter->hw.back = adapter;
 
 	/*
 	** Now setup MSI/X, should
@@ -1596,7 +1604,7 @@ ixv_setup_interface(device_t dev, struct
 	ether_set_ifflags_cb(ec, ixv_ifflags_cb);
 
 	adapter->max_frame_size =
-	    ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
+	    ifp->if_mtu + IXGBE_MTU_HDR_VLAN;
 
 	/*
 	 * Tell the upper layer(s) we support long frames.
@@ -1634,7 +1642,6 @@ ixv_setup_interface(device_t dev, struct
 	 */
 	ifmedia_init(&adapter->media, IFM_IMASK, ixv_media_change,
 		     ixv_media_status);
-	ifmedia_add(&adapter->media, IFM_ETHER | IFM_FDX, 0, NULL);
 	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
 
@@ -1645,19 +1652,11 @@ static void
 ixv_config_link(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32	autoneg, err = 0;
+	u32	autoneg;
 
 	if (hw->mac.ops.check_link)
-		err = hw->mac.ops.check_link(hw, &autoneg,
+		hw->mac.ops.check_link(hw, &autoneg,
 		    &adapter->link_up, FALSE);
-	if (err)
-		goto out;
-
-	if (hw->mac.ops.setup_link)
-               	err = hw->mac.ops.setup_link(hw,
-		    autoneg, adapter->link_up);
-out:
-	return;
 }
 
 
@@ -1724,7 +1723,6 @@ ixv_initialize_receive_units(struct adap
 	struct ixgbe_hw	*hw = &adapter->hw;
 	struct ifnet	*ifp = adapter->ifp;
 	u32		bufsz, rxcsum, psrtype;
-	int		max_frame;
 
 	if (ifp->if_mtu > ETHERMTU)
 		bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
@@ -1737,9 +1735,8 @@ ixv_initialize_receive_units(struct adap
 
 	IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype);
 
-	/* Tell PF our expected packet-size */
-	max_frame = ifp->if_mtu + IXGBE_MTU_HDR;
-	ixgbevf_rlpml_set_vf(hw, max_frame);
+	/* Tell PF our max_frame size */
+	ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size);
 
 	for (int i = 0; i < adapter->num_queues; i++, rxr++) {
 		u64 rdba = rxr->rxdma.dma_paddr;
@@ -1841,7 +1838,7 @@ ixv_setup_vlan_support(struct adapter *a
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32		ctrl, vid, vfta, retry;
-
+	struct rx_ring	*rxr;
 
 	/*
 	** We get here thru init_locked, meaning
@@ -1857,6 +1854,12 @@ ixv_setup_vlan_support(struct adapter *a
 		ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i));
 		ctrl |= IXGBE_RXDCTL_VME;
 		IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), ctrl);
+		/*
+		 * Let Rx path know that it needs to store VLAN tag
+		 * as part of extra mbuf info.
+		 */
+		rxr = &adapter->rx_rings[i];
+		rxr->vtag_strip = TRUE;
 	}
 
 	/*
@@ -1872,7 +1875,7 @@ ixv_setup_vlan_support(struct adapter *a
 		** based on the bits set in each
 		** of the array ints.
 		*/
-		for ( int j = 0; j < 32; j++) {
+		for (int j = 0; j < 32; j++) {
 			retry = 0;
 			if ((vfta & (1 << j)) == 0)
 				continue;
@@ -1900,10 +1903,10 @@ ixv_register_vlan(void *arg, struct ifne
 	struct adapter	*adapter = ifp->if_softc;
 	u16		index, bit;
 
-	if (ifp->if_softc !=  arg)   /* Not our event */
+	if (ifp->if_softc != arg) /* Not our event */
 		return;
 
-	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
+	if ((vtag == 0) || (vtag > 4095)) /* Invalid */
 		return;
 
 	IXGBE_CORE_LOCK(adapter);
@@ -2193,8 +2196,9 @@ ixv_set_sysctl_value(struct adapter *ada
 	if (sysctl_createv(log, 0, &rnode, &cnode,
 	    CTLFLAG_READWRITE|CTLFLAG_IMMEDIATE, CTLTYPE_INT,
 	    name, SYSCTL_DESCR(description),
-	    NULL, value, limit, CTL_CREATE, CTL_EOL) != 0)
+	    NULL, 0, limit, CTL_CREATE, CTL_EOL) != 0)
 		aprint_error_dev(dev, "could not create sysctl\n");
+	*limit = value;
 }
 
 /**********************************************************************

Added files:

Index: src/sys/dev/pci/ixgbe/ixgbe_osdep.c
diff -u /dev/null src/sys/dev/pci/ixgbe/ixgbe_osdep.c:1.1
--- /dev/null	Fri Dec  2 10:42:04 2016
+++ src/sys/dev/pci/ixgbe/ixgbe_osdep.c	Fri Dec  2 10:42:04 2016
@@ -0,0 +1,117 @@
+/******************************************************************************
+
+  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: head/sys/dev/ixgbe/ixgbe_osdep.c 292674 2015-12-23 22:45:17Z sbruno $*/
+
+#include "ixgbe_osdep.h"
+#include "ixgbe.h"
+
+inline device_t
+ixgbe_dev_from_hw(struct ixgbe_hw *hw)
+{
+	return ((struct adapter *)hw->back)->dev;
+}
+
+u16
+ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg)
+{
+	pci_chipset_tag_t  pc = hw->back->osdep.pc;
+	pcitag_t           tag = hw->back->osdep.tag;
+
+	switch (reg % 4) {
+	case 0:
+		return pci_conf_read(pc, tag, reg) & __BITS(15, 0);
+	case 2:
+		return __SHIFTOUT(pci_conf_read(pc, tag, reg - 2),
+		    __BITS(31, 16));
+	default:
+		panic("%s: invalid register (%" PRIx32, __func__, reg); 
+		break;
+	}
+}
+
+void
+ixgbe_write_pci_cfg(struct ixgbe_hw *hw, u32 reg, u16 value)
+{
+	pci_chipset_tag_t  pc = hw->back->osdep.pc;
+	pcitag_t           tag = hw->back->osdep.tag;
+	pcireg_t old;
+
+	switch (reg % 4) {
+	case 0:
+		old = pci_conf_read(pc, tag, reg) & __BITS(31, 16);
+		pci_conf_write(pc, tag, reg, value | old);
+		break;
+	case 2:
+		old = pci_conf_read(pc, tag, reg - 2) & __BITS(15, 0);
+		pci_conf_write(pc, tag, reg - 2,
+		    __SHIFTIN(value, __BITS(31, 16)) | old);
+		break;
+	default:
+		panic("%s: invalid register (%" PRIx32, __func__, reg); 
+		break;
+	}
+
+	return;
+}
+
+inline u32
+ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg)
+{
+	return bus_space_read_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+	    ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+	    reg);
+}
+
+inline void
+ixgbe_write_reg(struct ixgbe_hw *hw, u32 reg, u32 val)
+{
+	bus_space_write_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+	    ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+	    reg, val);
+}
+
+inline u32
+ixgbe_read_reg_array(struct ixgbe_hw *hw, u32 reg, u32 offset)
+{
+	return bus_space_read_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+	    ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+	    reg + (offset << 2));
+}
+
+inline void
+ixgbe_write_reg_array(struct ixgbe_hw *hw, u32 reg, u32 offset, u32 val)
+{
+	bus_space_write_4(((struct adapter *)hw->back)->osdep.mem_bus_space_tag,
+	    ((struct adapter *)hw->back)->osdep.mem_bus_space_handle,
+	    reg + (offset << 2), val);
+}

Reply via email to