Module Name:    src
Committed By:   martin
Date:           Mon Jul 22 17:53:35 UTC 2019

Modified Files:
        src/sys/dev/pci/ixgbe [netbsd-8]: if_sriov.c ix_txrx.c ixgbe.c ixgbe.h
            ixgbe_82599.c ixgbe_api.c ixgbe_api.h ixgbe_common.c ixgbe_common.h
            ixgbe_features.h ixgbe_mbx.c ixgbe_mbx.h ixgbe_netbsd.c
            ixgbe_netbsd.h ixgbe_netmap.c ixgbe_phy.c ixgbe_type.h ixgbe_vf.c
            ixgbe_x550.c ixgbe_x550.h ixv.c

Log Message:
Pull up the following revisions (via patch), requested by msaitoh in
ticket #1301:

        sys/dev/pci/ixgbe/if_sriov.c                    1.5-1.6
        sys/dev/pci/ixgbe/ix_txrx.c                     1.53-1.54
        sys/dev/pci/ixgbe/ixgbe_x550.h                  1.5
        sys/dev/pci/ixgbe/ixgbe.c                       
1.169-1.170,1.176,1.179,1.181,1.185-1.186,1.188-1.192 via patch
        sys/dev/pci/ixgbe/ixgbe.h                       1.53,1.55
        sys/dev/pci/ixgbe/ixgbe_82599.c                 1.21
        sys/dev/pci/ixgbe/ixgbe_api.c                   1.22-1.23
        sys/dev/pci/ixgbe/ixgbe_api.h                   1.14-1.15
        sys/dev/pci/ixgbe/ixgbe_x550.c                  1.14-1.15
        sys/dev/pci/ixgbe/ixgbe_common.c                1.23
        sys/dev/pci/ixgbe/ixgbe_common.h                1.14
        sys/dev/pci/ixgbe/ixgbe_mbx.c                   1.11
        sys/dev/pci/ixgbe/ixgbe_mbx.h                   1.14
        sys/dev/pci/ixgbe/ixgbe_netmap.c                1.2
        sys/dev/pci/ixgbe/ixgbe_features.h              1.2
        sys/dev/pci/ixgbe/ixgbe_netbsd.c                1.9
        sys/dev/pci/ixgbe/ixgbe_netbsd.h                1.9-1.10
        sys/dev/pci/ixgbe/ixgbe_phy.c                   1.18
        sys/dev/pci/ixgbe/ixgbe_type.h                  1.37,1.39-1.40
        sys/dev/pci/ixgbe/ixgbe_vf.c                    1.18
        sys/dev/pci/ixgbe/ixv.c                         1.112-1.114,1.117,1.119 
via patch

Sync ixgbe up to 20190717 except ETHERCAP or ixv's VLAN stuff:
- Add firmware recovery mode for X550, X550A(Xeon D) and X550EM(C3000).
- Remove IXGBE_DEV_ID_82599_LS(0x154f) support again.
- On X550EMU, use ixgbe_identify_sfp_module_X550em() instead of
  ixgbe_identify_module_generic(). ixgbe_identify_sfp_module_X550em()
  has extra check (e.g. exclude 1G copper).
- It's not required to calculate unused queues' statistics.
- Remove ETHERCAP_VLAN_HWFILTER's definition.
- Match 82598_BX(0x1508), 82599_KR(0x1517), 82599_SFP_EM(0x1507),
  X550EM_X_XFI(0x15b0), X550EM_A_QSFP(0x15ca) and
  X550EM_A_QSFP_N(0x15cc)
- Add missing XFI support into ixgbe_get_link_capabilities_X550em().
- Other than IXGBE_VF_RESET should wait ACK, so use
  ixgbevf_write_msg_read_ack() instead of write_posted() in
  ixgbe_update_mc_addr_list_vf().
- When ixv_check_link() failed in the watchdog function, reset the
  interface.
- Remove RXCSUM register modification in
  ixv_initialize_receive_units(). It seems it's not required.
- Remove some debug printf in ixv_print_debug_info().
- Calculate vector's bit location correctly when the vector >= 31
  in ixgbe_allocate_msix().
- Fix hung queue check when the queue number >= 31.
- On ENETRESET case, not continue and quit the ifflags_cb() function
  because if_init() will do the same thing.
- Fix bugs in unused code.
- Fix typo in comment.
- Fix typo in unused code.
- Whitespace fixes. KNF.


To generate a diff of this commit:
cvs rdiff -u -r1.1.4.4 -r1.1.4.5 src/sys/dev/pci/ixgbe/if_sriov.c
cvs rdiff -u -r1.24.2.15 -r1.24.2.16 src/sys/dev/pci/ixgbe/ix_txrx.c
cvs rdiff -u -r1.88.2.29 -r1.88.2.30 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.24.6.16 -r1.24.6.17 src/sys/dev/pci/ixgbe/ixgbe.h
cvs rdiff -u -r1.14.8.4 -r1.14.8.5 src/sys/dev/pci/ixgbe/ixgbe_82599.c
cvs rdiff -u -r1.15.8.4 -r1.15.8.5 src/sys/dev/pci/ixgbe/ixgbe_api.c
cvs rdiff -u -r1.9.8.3 -r1.9.8.4 src/sys/dev/pci/ixgbe/ixgbe_api.h
cvs rdiff -u -r1.13.2.4 -r1.13.2.5 src/sys/dev/pci/ixgbe/ixgbe_common.c
cvs rdiff -u -r1.7.8.4 -r1.7.8.5 src/sys/dev/pci/ixgbe/ixgbe_common.h
cvs rdiff -u -r1.1.4.2 -r1.1.4.3 src/sys/dev/pci/ixgbe/ixgbe_features.h \
    src/sys/dev/pci/ixgbe/ixgbe_netmap.c
cvs rdiff -u -r1.6.8.2 -r1.6.8.3 src/sys/dev/pci/ixgbe/ixgbe_mbx.c
cvs rdiff -u -r1.10.8.2 -r1.10.8.3 src/sys/dev/pci/ixgbe/ixgbe_mbx.h
cvs rdiff -u -r1.6.2.2 -r1.6.2.3 src/sys/dev/pci/ixgbe/ixgbe_netbsd.c
cvs rdiff -u -r1.7.6.1 -r1.7.6.2 src/sys/dev/pci/ixgbe/ixgbe_netbsd.h
cvs rdiff -u -r1.11.6.3 -r1.11.6.4 src/sys/dev/pci/ixgbe/ixgbe_phy.c
cvs rdiff -u -r1.22.2.8 -r1.22.2.9 src/sys/dev/pci/ixgbe/ixgbe_type.h
cvs rdiff -u -r1.12.8.2 -r1.12.8.3 src/sys/dev/pci/ixgbe/ixgbe_vf.c
cvs rdiff -u -r1.5.6.5 -r1.5.6.6 src/sys/dev/pci/ixgbe/ixgbe_x550.c
cvs rdiff -u -r1.2.12.2 -r1.2.12.3 src/sys/dev/pci/ixgbe/ixgbe_x550.h
cvs rdiff -u -r1.56.2.21 -r1.56.2.22 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/if_sriov.c
diff -u src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.4 src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.5
--- src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.4	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/if_sriov.c	Mon Jul 22 17:53:35 2019
@@ -250,6 +250,20 @@ ixgbe_vf_set_default_vlan(struct adapter
 } /* ixgbe_vf_set_default_vlan */
 
 
+static void
+ixgbe_clear_vfmbmem(struct ixgbe_hw *hw, struct ixgbe_vf *vf)
+{
+	uint32_t vf_index = IXGBE_VF_INDEX(vf->pool);
+	uint16_t mbx_size = hw->mbx.size;
+	uint16_t i;
+
+	IXGBE_CORE_LOCK_ASSERT(adapter);
+
+	for (i = 0; i < mbx_size; ++i)
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_index), i, 0x0);
+} /* ixgbe_clear_vfmbmem */
+
+
 static boolean_t
 ixgbe_vf_frame_size_compatible(struct adapter *adapter, struct ixgbe_vf *vf)
 {
@@ -305,6 +319,8 @@ ixgbe_process_vf_reset(struct adapter *a
 	// XXX clear multicast addresses
 
 	ixgbe_clear_rar(&adapter->hw, vf->rar_index);
+	ixgbe_clear_vfmbmem(&adapter->hw, vf);
+	ixgbe_toggle_txdctl(&adapter->hw, IXGBE_VF_INDEX(vf->pool));
 
 	vf->api_ver = IXGBE_API_VER_UNKNOWN;
 } /* ixgbe_process_vf_reset */

Index: src/sys/dev/pci/ixgbe/ix_txrx.c
diff -u src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.15 src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.16
--- src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.15	Fri Mar  1 17:33:24 2019
+++ src/sys/dev/pci/ixgbe/ix_txrx.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ix_txrx.c,v 1.24.2.15 2019/03/01 17:33:24 martin Exp $ */
+/* $NetBSD: ix_txrx.c,v 1.24.2.16 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
 
@@ -233,7 +233,7 @@ ixgbe_mq_start(struct ifnet *ifp, struct
 		i = (cpu_index(curcpu()) % ncpu) % adapter->num_queues;
 
 	/* Check for a hung queue and pick alternative */
-	if (((1 << i) & adapter->active_queues) == 0)
+	if (((1ULL << i) & adapter->active_queues) == 0)
 		i = ffs64(adapter->active_queues);
 
 	txr = &adapter->tx_rings[i];
@@ -694,7 +694,7 @@ ixgbe_setup_transmit_ring(struct tx_ring
 		 * netmap_idx_n2k() handles wraparounds properly.
 		 */
 		if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) && slot) {
-			int si = netmap_idx_n2k(&na->tx_rings[txr->me], i);
+			int si = netmap_idx_n2k(na->tx_rings[txr->me], i);
 			netmap_load_map(na, txr->txtag,
 			    txbuf->map, NMB(na, slot + si));
 		}
@@ -1105,7 +1105,7 @@ ixgbe_txeof(struct tx_ring *txr)
 	if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
 	    (adapter->ifp->if_capenable & IFCAP_NETMAP)) {
 		struct netmap_adapter *na = NA(adapter->ifp);
-		struct netmap_kring *kring = &na->tx_rings[txr->me];
+		struct netmap_kring *kring = na->tx_rings[txr->me];
 		txd = txr->tx_base;
 		bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
 		    BUS_DMASYNC_POSTREAD);
@@ -1123,9 +1123,8 @@ ixgbe_txeof(struct tx_ring *txr)
 		 * - the driver ignores tx interrupts unless netmap_mitigate=0
 		 *   or the slot has the DD bit set.
 		 */
-		if (!netmap_mitigate ||
-		    (kring->nr_kflags < kring->nkr_num_slots &&
-		     txd[kring->nr_kflags].wb.status & IXGBE_TXD_STAT_DD)) {
+		if (kring->nr_kflags < kring->nkr_num_slots &&
+		    txd[kring->nr_kflags].wb.status & IXGBE_TXD_STAT_DD) {
 			netmap_tx_irq(ifp, txr->me);
 		}
 		return false;
@@ -1405,7 +1404,7 @@ update:
 static int
 ixgbe_allocate_receive_buffers(struct rx_ring *rxr)
 {
-	struct	adapter     *adapter = rxr->adapter;
+	struct adapter      *adapter = rxr->adapter;
 	device_t            dev = adapter->dev;
 	struct ixgbe_rx_buf *rxbuf;
 	int                 bsize, error;
@@ -1530,7 +1529,7 @@ ixgbe_setup_receive_ring(struct rx_ring 
 		 * an mbuf, so end the block with a continue;
 		 */
 		if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) && slot) {
-			int sj = netmap_idx_n2k(&na->rx_rings[rxr->me], j);
+			int sj = netmap_idx_n2k(na->rx_rings[rxr->me], j);
 			uint64_t paddr;
 			void *addr;
 
@@ -1827,7 +1826,7 @@ ixgbe_rxeof(struct ix_queue *que)
 		u16         len;
 		u16         vtag = 0;
 		bool        eop;
- 
+
 		/* Sync the ring. */
 		ixgbe_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
@@ -2307,7 +2306,7 @@ ixgbe_allocate_queues(struct adapter *ad
 
 	/*
 	 * Next the RX queues...
-	 */ 
+	 */
 	rsize = roundup2(adapter->num_rx_desc * sizeof(union ixgbe_adv_rx_desc),
 	    DBA_ALIGN);
 	for (int i = 0; i < adapter->num_queues; i++, rxconf++) {

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.29 src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.30
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.29	Mon Apr  1 12:35:38 2019
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.88.2.29 2019/04/01 12:35:38 martin Exp $ */
+/* $NetBSD: ixgbe.c,v 1.88.2.30 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
 
@@ -81,7 +81,7 @@
  * Driver version
  ************************************************************************/
 static const char ixgbe_driver_version[] = "4.0.1-k";
-
+/* XXX NetBSD: + 3.3.10 */
 
 /************************************************************************
  * PCI Device ID Table
@@ -100,14 +100,17 @@ static const ixgbe_vendor_info_t ixgbe_v
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_BX, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KR, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_EM, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
@@ -127,8 +130,11 @@ static const ixgbe_vendor_info_t ixgbe_v
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_10G_T, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_1G_T, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_SFP, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_XFI, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_KR_L, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_QSFP, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_QSFP_N, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SFP_N, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_SGMII, 0, 0, 0},
@@ -152,38 +158,39 @@ static const char    *ixgbe_strings[] = 
 /************************************************************************
  * Function prototypes
  ************************************************************************/
-static int      ixgbe_probe(device_t, cfdata_t, void *);
-static void     ixgbe_attach(device_t, device_t, void *);
-static int      ixgbe_detach(device_t, int);
+static int	ixgbe_probe(device_t, cfdata_t, void *);
+static void	ixgbe_attach(device_t, device_t, void *);
+static int	ixgbe_detach(device_t, int);
 #if 0
-static int      ixgbe_shutdown(device_t);
+static int	ixgbe_shutdown(device_t);
 #endif
 static bool	ixgbe_suspend(device_t, const pmf_qual_t *);
 static bool	ixgbe_resume(device_t, const pmf_qual_t *);
 static int	ixgbe_ifflags_cb(struct ethercom *);
-static int      ixgbe_ioctl(struct ifnet *, u_long, void *);
+static int	ixgbe_ioctl(struct ifnet *, u_long, void *);
 static void	ixgbe_ifstop(struct ifnet *, int);
 static int	ixgbe_init(struct ifnet *);
 static void	ixgbe_init_locked(struct adapter *);
-static void     ixgbe_stop(void *);
-static void     ixgbe_init_device_features(struct adapter *);
-static void     ixgbe_check_fan_failure(struct adapter *, u32, bool);
+static void	ixgbe_stop(void *);
+static void	ixgbe_init_device_features(struct adapter *);
+static void	ixgbe_check_fan_failure(struct adapter *, u32, bool);
 static void	ixgbe_add_media_types(struct adapter *);
-static void     ixgbe_media_status(struct ifnet *, struct ifmediareq *);
-static int      ixgbe_media_change(struct ifnet *);
-static int      ixgbe_allocate_pci_resources(struct adapter *,
+static void	ixgbe_media_status(struct ifnet *, struct ifmediareq *);
+static int	ixgbe_media_change(struct ifnet *);
+static int	ixgbe_allocate_pci_resources(struct adapter *,
 		    const struct pci_attach_args *);
-static void     ixgbe_free_softint(struct adapter *);
+static void	ixgbe_free_softint(struct adapter *);
 static void	ixgbe_get_slot_info(struct adapter *);
-static int      ixgbe_allocate_msix(struct adapter *,
+static int	ixgbe_allocate_msix(struct adapter *,
 		    const struct pci_attach_args *);
-static int      ixgbe_allocate_legacy(struct adapter *,
+static int	ixgbe_allocate_legacy(struct adapter *,
 		    const struct pci_attach_args *);
-static int      ixgbe_configure_interrupts(struct adapter *);
+static int	ixgbe_configure_interrupts(struct adapter *);
 static void	ixgbe_free_pciintr_resources(struct adapter *);
 static void	ixgbe_free_pci_resources(struct adapter *);
 static void	ixgbe_local_timer(void *);
 static void	ixgbe_local_timer1(void *);
+static void	ixgbe_recovery_mode_timer(void *);
 static int	ixgbe_setup_interface(device_t, struct adapter *);
 static void	ixgbe_config_gpie(struct adapter *);
 static void	ixgbe_config_dmac(struct adapter *);
@@ -193,18 +200,18 @@ static void	ixgbe_check_wol_support(stru
 static int	ixgbe_setup_low_power_mode(struct adapter *);
 static void	ixgbe_rearm_queues(struct adapter *, u64);
 
-static void     ixgbe_initialize_transmit_units(struct adapter *);
-static void     ixgbe_initialize_receive_units(struct adapter *);
+static void	ixgbe_initialize_transmit_units(struct adapter *);
+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 *);
-static void     ixgbe_update_stats_counters(struct adapter *);
-static void     ixgbe_set_promisc(struct adapter *);
-static void     ixgbe_set_multi(struct adapter *);
-static void     ixgbe_update_link_status(struct adapter *);
+static void	ixgbe_enable_intr(struct adapter *);
+static void	ixgbe_disable_intr(struct adapter *);
+static void	ixgbe_update_stats_counters(struct adapter *);
+static void	ixgbe_set_promisc(struct adapter *);
+static void	ixgbe_set_multi(struct adapter *);
+static void	ixgbe_update_link_status(struct adapter *);
 static void	ixgbe_set_ivar(struct adapter *, u8, u8, s8);
 static void	ixgbe_configure_ivars(struct adapter *);
 static u8 *	ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
@@ -217,18 +224,18 @@ static void	ixgbe_unregister_vlan(void *
 #endif
 
 static void	ixgbe_add_device_sysctls(struct adapter *);
-static void     ixgbe_add_hw_stats(struct adapter *);
+static void	ixgbe_add_hw_stats(struct adapter *);
 static void	ixgbe_clear_evcnt(struct adapter *);
 static int	ixgbe_set_flowcntl(struct adapter *, int);
 static int	ixgbe_set_advertise(struct adapter *, int);
-static int      ixgbe_get_advertise(struct adapter *);
+static int	ixgbe_get_advertise(struct adapter *);
 
 /* Sysctl handlers */
 static void	ixgbe_set_sysctl_value(struct adapter *, const char *,
 		     const char *, int *, int);
 static int	ixgbe_sysctl_flowcntl(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_advertise(SYSCTLFN_PROTO);
-static int      ixgbe_sysctl_interrupt_rate_handler(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_interrupt_rate_handler(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);
@@ -236,12 +243,12 @@ static int	ixgbe_sysctl_phy_overtemp_occ
 static int	ixgbe_sysctl_power_state(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_print_rss_config(SYSCTLFN_PROTO);
 #endif
-static int      ixgbe_sysctl_next_to_check_handler(SYSCTLFN_PROTO);
-static int      ixgbe_sysctl_rdh_handler(SYSCTLFN_PROTO);
-static int      ixgbe_sysctl_rdt_handler(SYSCTLFN_PROTO);
-static int      ixgbe_sysctl_tdt_handler(SYSCTLFN_PROTO);
-static int      ixgbe_sysctl_tdh_handler(SYSCTLFN_PROTO);
-static int      ixgbe_sysctl_eee_state(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_next_to_check_handler(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_rdh_handler(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_rdt_handler(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_tdt_handler(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_tdh_handler(SYSCTLFN_PROTO);
+static int	ixgbe_sysctl_eee_state(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_debug(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_wol_enable(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_wufc(SYSCTLFN_PROTO);
@@ -321,7 +328,7 @@ static int ixgbe_flow_control = ixgbe_fc
 SYSCTL_INT(_hw_ix, OID_AUTO, flow_control, CTLFLAG_RDTUN,
     &ixgbe_flow_control, 0, "Default flow control used for all adapters");
 
-/* Which pakcet processing uses workqueue or softint */
+/* Which packet processing uses workqueue or softint */
 static bool ixgbe_txrx_workqueue = false;
 
 /*
@@ -416,10 +423,10 @@ static void
 ixgbe_initialize_rss_mapping(struct adapter *adapter)
 {
 	struct ixgbe_hw	*hw = &adapter->hw;
-	u32             reta = 0, mrqc, rss_key[10];
-	int             queue_id, table_size, index_mult;
-	int             i, j;
-	u32             rss_hash_config;
+	u32		reta = 0, mrqc, rss_key[10];
+	int		queue_id, table_size, index_mult;
+	int		i, j;
+	u32		rss_hash_config;
 
 	/* force use default RSS key. */
 #ifdef __NetBSD__
@@ -496,11 +503,11 @@ ixgbe_initialize_rss_mapping(struct adap
 		 * traffic.
 		 */
 		rss_hash_config = RSS_HASHTYPE_RSS_IPV4
-		                | RSS_HASHTYPE_RSS_TCP_IPV4
-		                | RSS_HASHTYPE_RSS_IPV6
-		                | RSS_HASHTYPE_RSS_TCP_IPV6
-		                | RSS_HASHTYPE_RSS_IPV6_EX
-		                | RSS_HASHTYPE_RSS_TCP_IPV6_EX;
+				| RSS_HASHTYPE_RSS_TCP_IPV4
+				| RSS_HASHTYPE_RSS_IPV6
+				| RSS_HASHTYPE_RSS_TCP_IPV6
+				| RSS_HASHTYPE_RSS_IPV6_EX
+				| RSS_HASHTYPE_RSS_TCP_IPV6_EX;
 	}
 
 	mrqc = IXGBE_MRQC_RSSEN;
@@ -530,14 +537,14 @@ ixgbe_initialize_rss_mapping(struct adap
  * ixgbe_initialize_receive_units - Setup receive registers and features.
  ************************************************************************/
 #define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
-	
+
 static void
 ixgbe_initialize_receive_units(struct adapter *adapter)
 {
 	struct	rx_ring	*rxr = adapter->rx_rings;
 	struct ixgbe_hw	*hw = &adapter->hw;
-	struct ifnet    *ifp = adapter->ifp;
-	int             i, j;
+	struct ifnet	*ifp = adapter->ifp;
+	int		i, j;
 	u32		bufsz, fctrl, srrctl, rxcsum;
 	u32		hlreg;
 
@@ -630,9 +637,9 @@ ixgbe_initialize_receive_units(struct ad
 
 	if (adapter->hw.mac.type != ixgbe_mac_82598EB) {
 		u32 psrtype = IXGBE_PSRTYPE_TCPHDR
-		            | IXGBE_PSRTYPE_UDPHDR
-		            | IXGBE_PSRTYPE_IPV4HDR
-		            | IXGBE_PSRTYPE_IPV6HDR;
+			    | IXGBE_PSRTYPE_UDPHDR
+			    | IXGBE_PSRTYPE_IPV4HDR
+			    | IXGBE_PSRTYPE_IPV6HDR;
 		IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
 	}
 
@@ -662,7 +669,7 @@ ixgbe_initialize_receive_units(struct ad
 static void
 ixgbe_initialize_transmit_units(struct adapter *adapter)
 {
-	struct tx_ring  *txr = adapter->tx_rings;
+	struct tx_ring	*txr = adapter->tx_rings;
 	struct ixgbe_hw	*hw = &adapter->hw;
 	int i;
 
@@ -760,9 +767,9 @@ ixgbe_initialize_transmit_units(struct a
 static void
 ixgbe_attach(device_t parent, device_t dev, void *aux)
 {
-	struct adapter  *adapter;
+	struct adapter	*adapter;
 	struct ixgbe_hw *hw;
-	int             error = -1;
+	int		error = -1;
 	u32		ctrl_ext;
 	u16		high, low, nvmreg;
 	pcireg_t	id, subid;
@@ -965,6 +972,7 @@ ixgbe_attach(device_t parent, device_t d
 
 	aprint_normal("%s:", device_xname(dev));
 	/* NVM Image Version */
+	high = low = 0;
 	switch (hw->mac.type) {
 	case ixgbe_mac_X540:
 	case ixgbe_mac_X550EM_a:
@@ -994,6 +1002,8 @@ ixgbe_attach(device_t parent, device_t d
 	default:
 		break;
 	}
+	hw->eeprom.nvm_image_ver_high = high;
+	hw->eeprom.nvm_image_ver_low = low;
 
 	/* PHY firmware revision */
 	switch (hw->mac.type) {
@@ -1066,9 +1076,24 @@ ixgbe_attach(device_t parent, device_t d
 			}
 		}
 	}
+	/* Recovery mode */
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_X550:
+	case ixgbe_mac_X550EM_x:
+	case ixgbe_mac_X550EM_a:
+		/* >= 2.00 */
+		if (hw->eeprom.nvm_image_ver_high >= 2) {
+			adapter->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE;
+			adapter->feat_en |= IXGBE_FEATURE_RECOVERY_MODE;
+		}
+		break;
+	default:
+		break;
+	}
+
 	if ((adapter->feat_en & IXGBE_FEATURE_MSIX) == 0)
 		error = ixgbe_allocate_legacy(adapter, pa);
-	if (error) 
+	if (error)
 		goto err_late;
 
 	/* Tasklets for Link, SFP, Multispeed Fiber and Flow Director */
@@ -1193,6 +1218,19 @@ ixgbe_attach(device_t parent, device_t d
 	else
 		aprint_error_dev(dev, "couldn't establish power handler\n");
 
+	/* Init recovery mode timer and state variable */
+	if (adapter->feat_en & IXGBE_FEATURE_RECOVERY_MODE) {
+		adapter->recovery_mode = 0;
+
+		/* Set up the timer callout */
+		callout_init(&adapter->recovery_mode_timer,
+		    IXGBE_CALLOUT_FLAGS);
+
+		/* Start the task */
+		callout_reset(&adapter->recovery_mode_timer, hz,
+		    ixgbe_recovery_mode_timer, adapter);
+	}
+
 	INIT_DEBUGOUT("ixgbe_attach: end");
 	adapter->osdep.attached = true;
 
@@ -1228,7 +1266,7 @@ static void
 ixgbe_check_wol_support(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u16             dev_caps = 0;
+	u16		dev_caps = 0;
 
 	/* Find out WoL support for port */
 	adapter->wol_support = hw->wol_enabled = 0;
@@ -1311,15 +1349,15 @@ ixgbe_setup_interface(device_t dev, stru
 
 	/* Set capability flags */
 	ifp->if_capabilities |= IFCAP_RXCSUM
-			     |  IFCAP_TXCSUM
-			     |  IFCAP_TSOv4
-			     |  IFCAP_TSOv6;
+			     |	IFCAP_TXCSUM
+			     |	IFCAP_TSOv4
+			     |	IFCAP_TSOv6;
 	ifp->if_capenable = 0;
 
 	ec->ec_capabilities |= ETHERCAP_VLAN_HWTAGGING
-	    		    |  ETHERCAP_VLAN_HWCSUM
-	    		    |  ETHERCAP_JUMBO_MTU
-	    		    |  ETHERCAP_VLAN_MTU;
+			    |  ETHERCAP_VLAN_HWCSUM
+			    |  ETHERCAP_JUMBO_MTU
+			    |  ETHERCAP_VLAN_MTU;
 
 	/* Enable the above capabilities by default */
 	ec->ec_capenable = ec->ec_capabilities;
@@ -1359,8 +1397,8 @@ static void
 ixgbe_add_media_types(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	device_t        dev = adapter->dev;
-	u64             layer;
+	device_t	dev = adapter->dev;
+	u64		layer;
 
 	layer = adapter->phy_layer;
 
@@ -1440,7 +1478,7 @@ ixgbe_add_media_types(struct adapter *ad
 	if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX)
 		device_printf(dev, "Media supported: 1000baseBX\n");
 	/* XXX no ifmedia_set? */
-	
+
 	ADD(IFM_AUTO, 0);
 
 #undef ADD
@@ -1482,12 +1520,12 @@ static void
 ixgbe_config_link(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32             autoneg, err = 0;
-	bool            sfp, negotiate = false;
+	u32		autoneg, err = 0;
+	bool		sfp, negotiate = false;
 
 	sfp = ixgbe_is_sfp(hw);
 
-	if (sfp) { 
+	if (sfp) {
 		if (hw->phy.multispeed_fiber) {
 			ixgbe_enable_tx_laser(hw);
 			kpreempt_disable();
@@ -1498,7 +1536,7 @@ ixgbe_config_link(struct adapter *adapte
 		softint_schedule(adapter->mod_si);
 		kpreempt_enable();
 	} else {
-		struct ifmedia  *ifm = &adapter->media;
+		struct ifmedia	*ifm = &adapter->media;
 
 		if (hw->mac.ops.check_link)
 			err = ixgbe_check_link(hw, &adapter->link_speed,
@@ -1513,12 +1551,12 @@ ixgbe_config_link(struct adapter *adapte
 		autoneg = hw->phy.autoneg_advertised;
 		if ((IFM_SUBTYPE(ifm->ifm_cur->ifm_media) != IFM_NONE)
 		    && ((!autoneg) && (hw->mac.ops.get_link_capabilities)))
-                	err = hw->mac.ops.get_link_capabilities(hw, &autoneg,
+			err = hw->mac.ops.get_link_capabilities(hw, &autoneg,
 			    &negotiate);
 		if (err)
 			return;
 		if (hw->mac.ops.setup_link)
-                	err = hw->mac.ops.setup_link(hw, autoneg,
+			err = hw->mac.ops.setup_link(hw, autoneg,
 			    adapter->link_up);
 	}
 
@@ -1530,13 +1568,14 @@ ixgbe_config_link(struct adapter *adapte
 static void
 ixgbe_update_stats_counters(struct adapter *adapter)
 {
-	struct ifnet          *ifp = adapter->ifp;
-	struct ixgbe_hw       *hw = &adapter->hw;
+	struct ifnet	      *ifp = adapter->ifp;
+	struct ixgbe_hw	      *hw = &adapter->hw;
 	struct ixgbe_hw_stats *stats = &adapter->stats.pf;
-	u32                   missed_rx = 0, bprc, lxon, lxoff, total;
-	u64                   total_missed_rx = 0;
-	uint64_t              crcerrs, rlec;
-	int		      i, j;
+	u32		      missed_rx = 0, bprc, lxon, lxoff, total;
+	u64		      total_missed_rx = 0;
+	uint64_t	      crcerrs, rlec;
+	unsigned int	      queue_counters;
+	int		      i;
 
 	crcerrs = IXGBE_READ_REG(hw, IXGBE_CRCERRS);
 	stats->crcerrs.ev_count += crcerrs;
@@ -1546,14 +1585,13 @@ ixgbe_update_stats_counters(struct adapt
 	if (hw->mac.type == ixgbe_mac_X550)
 		stats->mbsdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MBSDC);
 
-	/* 16 registers */
-	for (i = 0; i < __arraycount(stats->qprc); i++) {
-		j = i % adapter->num_queues;
-
-		stats->qprc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
-		stats->qptc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+	/* 16 registers exist */
+	queue_counters = min(__arraycount(stats->qprc), adapter->num_queues);
+	for (i = 0; i < queue_counters; i++) {
+		stats->qprc[i].ev_count += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+		stats->qptc[i].ev_count += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
 		if (hw->mac.type >= ixgbe_mac_82599EB) {
-			stats->qprdc[j].ev_count
+			stats->qprdc[i].ev_count
 			    += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
 		}
 	}
@@ -2150,17 +2188,22 @@ ixgbe_clear_evcnt(struct adapter *adapte
  *
  *   Retrieves the TDH value from the hardware
  ************************************************************************/
-static int 
+static int
 ixgbe_sysctl_tdh_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
+	struct adapter *adapter;
 	uint32_t val;
 
 	if (!txr)
 		return (0);
 
-	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me));
+	adapter = txr->adapter;
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
+	val = IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(txr->me));
 	node.sysctl_data = &val;
 	return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_tdh_handler */
@@ -2170,17 +2213,22 @@ ixgbe_sysctl_tdh_handler(SYSCTLFN_ARGS)
  *
  *   Retrieves the TDT value from the hardware
  ************************************************************************/
-static int 
+static int
 ixgbe_sysctl_tdt_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct tx_ring *txr = (struct tx_ring *)node.sysctl_data;
+	struct adapter *adapter;
 	uint32_t val;
 
 	if (!txr)
 		return (0);
 
-	val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me));
+	adapter = txr->adapter;
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
+	val = IXGBE_READ_REG(&adapter->hw, IXGBE_TDT(txr->me));
 	node.sysctl_data = &val;
 	return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_tdt_handler */
@@ -2191,16 +2239,21 @@ ixgbe_sysctl_tdt_handler(SYSCTLFN_ARGS)
  *
  *   Retrieves the next_to_check value
  ************************************************************************/
-static int 
+static int
 ixgbe_sysctl_next_to_check_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+	struct adapter *adapter;
 	uint32_t val;
 
 	if (!rxr)
 		return (0);
 
+	adapter = rxr->adapter;
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
 	val = rxr->next_to_check;
 	node.sysctl_data = &val;
 	return sysctl_lookup(SYSCTLFN_CALL(&node));
@@ -2211,17 +2264,22 @@ ixgbe_sysctl_next_to_check_handler(SYSCT
  *
  *   Retrieves the RDH value from the hardware
  ************************************************************************/
-static int 
+static int
 ixgbe_sysctl_rdh_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+	struct adapter *adapter;
 	uint32_t val;
 
 	if (!rxr)
 		return (0);
 
-	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me));
+	adapter = rxr->adapter;
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
+	val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDH(rxr->me));
 	node.sysctl_data = &val;
 	return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_rdh_handler */
@@ -2231,17 +2289,22 @@ ixgbe_sysctl_rdh_handler(SYSCTLFN_ARGS)
  *
  *   Retrieves the RDT value from the hardware
  ************************************************************************/
-static int 
+static int
 ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+	struct adapter *adapter;
 	uint32_t val;
 
 	if (!rxr)
 		return (0);
 
-	val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me));
+	adapter = rxr->adapter;
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
+	val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDT(rxr->me));
 	node.sysctl_data = &val;
 	return sysctl_lookup(SYSCTLFN_CALL(&node));
 } /* ixgbe_sysctl_rdt_handler */
@@ -2308,7 +2371,7 @@ ixgbe_setup_vlan_hw_support(struct adapt
 	struct ethercom *ec = &adapter->osdep.ec;
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct rx_ring	*rxr;
-	int             i;
+	int		i;
 	u32		ctrl;
 	bool		hwtagging;
 
@@ -2374,9 +2437,9 @@ ixgbe_get_slot_info(struct adapter *adap
 {
 	device_t		dev = adapter->dev;
 	struct ixgbe_hw		*hw = &adapter->hw;
-	u32                   offset;
+	u32		      offset;
 	u16			link;
-	int                   bus_info_valid = TRUE;
+	int		      bus_info_valid = TRUE;
 
 	/* Some devices are behind an internal bridge */
 	switch (hw->device_id) {
@@ -2437,9 +2500,9 @@ get_parent_info:
 
 display:
 	device_printf(dev, "PCI Express Bus: Speed %s Width %s\n",
-	    ((hw->bus.speed == ixgbe_bus_speed_8000)    ? "8.0GT/s" :
-	     (hw->bus.speed == ixgbe_bus_speed_5000)    ? "5.0GT/s" :
-	     (hw->bus.speed == ixgbe_bus_speed_2500)    ? "2.5GT/s" :
+	    ((hw->bus.speed == ixgbe_bus_speed_8000)	? "8.0GT/s" :
+	     (hw->bus.speed == ixgbe_bus_speed_5000)	? "5.0GT/s" :
+	     (hw->bus.speed == ixgbe_bus_speed_2500)	? "2.5GT/s" :
 	     "Unknown"),
 	    ((hw->bus.width == ixgbe_bus_width_pcie_x8) ? "x8" :
 	     (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "x4" :
@@ -2479,8 +2542,8 @@ ixgbe_enable_queue(struct adapter *adapt
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que = &adapter->queues[vector];
-	u64             queue = (u64)(1ULL << vector);
-	u32             mask;
+	u64		queue = (u64)(1ULL << vector);
+	u32		mask;
 
 	mutex_enter(&que->dc_mtx);
 	if (que->disabled_count > 0 && --que->disabled_count > 0)
@@ -2509,8 +2572,8 @@ ixgbe_disable_queue_internal(struct adap
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que = &adapter->queues[vector];
-	u64             queue = (u64)(1ULL << vector);
-	u32             mask;
+	u64		queue = (u64)(1ULL << vector);
+	u32		mask;
 
 	mutex_enter(&que->dc_mtx);
 
@@ -2553,7 +2616,7 @@ static inline void
 ixgbe_sched_handle_que(struct adapter *adapter, struct ix_queue *que)
 {
 
-	if(que->txrx_use_workqueue) {
+	if (que->txrx_use_workqueue) {
 		/*
 		 * adapter->que_wq is bound to each CPU instead of
 		 * each NIC queue to reduce workqueue kthread. As we
@@ -2583,8 +2646,8 @@ static int
 ixgbe_msix_que(void *arg)
 {
 	struct ix_queue	*que = arg;
-	struct adapter  *adapter = que->adapter;
-	struct ifnet    *ifp = adapter->ifp;
+	struct adapter	*adapter = que->adapter;
+	struct ifnet	*ifp = adapter->ifp;
 	struct tx_ring	*txr = que->txr;
 	struct rx_ring	*rxr = que->rxr;
 	bool		more;
@@ -2630,9 +2693,9 @@ ixgbe_msix_que(void *arg)
 	que->eitr_setting = 0;
 
 	/* Idle, do nothing */
-        if ((txr->bytes == 0) && (rxr->bytes == 0))
-                goto no_calc;
-                                
+	if ((txr->bytes == 0) && (rxr->bytes == 0))
+		goto no_calc;
+
 	if ((txr->bytes) && (txr->packets))
 		newitr = txr->bytes/txr->packets;
 	if ((rxr->bytes) && (rxr->packets))
@@ -2660,8 +2723,8 @@ ixgbe_msix_que(void *arg)
 			newitr = IXGBE_MIN_RSC_EITR_10G1G;
 	}
 
-        /* save for next interrupt */
-        que->eitr_setting = newitr;
+	/* save for next interrupt */
+	que->eitr_setting = newitr;
 
 	/* Reset state */
 	txr->bytes = 0;
@@ -2843,9 +2906,9 @@ ixgbe_media_status(struct ifnet *ifp, st
 static int
 ixgbe_media_change(struct ifnet *ifp)
 {
-	struct adapter   *adapter = ifp->if_softc;
-	struct ifmedia   *ifm = &adapter->media;
-	struct ixgbe_hw  *hw = &adapter->hw;
+	struct adapter	 *adapter = ifp->if_softc;
+	struct ifmedia	 *ifm = &adapter->media;
+	struct ixgbe_hw	 *hw = &adapter->hw;
 	ixgbe_link_speed speed = 0;
 	ixgbe_link_speed link_caps = 0;
 	bool negotiate = false;
@@ -2881,10 +2944,9 @@ ixgbe_media_change(struct ifnet *ifp)
 	case IFM_10G_LRM:
 	case IFM_10G_LR:
 	case IFM_10G_TWINAX:
-#ifndef IFM_ETH_XTYPE
-	case IFM_10G_SR: /* KR, too */
-	case IFM_10G_CX4: /* KX4 */
-#else
+	case IFM_10G_SR:
+	case IFM_10G_CX4:
+#ifdef IFM_ETH_XTYPE
 	case IFM_10G_KR:
 	case IFM_10G_KX4:
 #endif
@@ -2950,8 +3012,8 @@ static void
 ixgbe_set_promisc(struct adapter *adapter)
 {
 	struct ifnet *ifp = adapter->ifp;
-	int          mcnt = 0;
-	u32          rctl;
+	int	     mcnt = 0;
+	u32	     rctl;
 	struct ether_multi *enm;
 	struct ether_multistep step;
 	struct ethercom *ec = &adapter->osdep.ec;
@@ -2995,7 +3057,7 @@ ixgbe_msix_link(void *arg)
 	struct adapter	*adapter = arg;
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32		eicr, eicr_mask;
-	s32             retval;
+	s32		retval;
 
 	++adapter->link_irq.ev_count;
 
@@ -3104,7 +3166,7 @@ ixgbe_msix_link(void *arg)
 	    (eicr & IXGBE_EICR_GPI_SDP0_X540)) {
 		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540);
 		softint_schedule(adapter->phy_si);
- 	}
+	}
 
 	/* Re-enable other interrupts */
 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
@@ -3114,11 +3176,11 @@ ixgbe_msix_link(void *arg)
 static void
 ixgbe_eitr_write(struct adapter *adapter, uint32_t index, uint32_t itr)
 {
-	
-        if (adapter->hw.mac.type == ixgbe_mac_82598EB)
-                itr |= itr << 16;
-        else
-                itr |= IXGBE_EITR_CNT_WDIS;
+
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+		itr |= itr << 16;
+	else
+		itr |= IXGBE_EITR_CNT_WDIS;
 
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(index), itr);
 }
@@ -3132,13 +3194,18 @@ ixgbe_sysctl_interrupt_rate_handler(SYSC
 {
 	struct sysctlnode node = *rnode;
 	struct ix_queue *que = (struct ix_queue *)node.sysctl_data;
-	struct adapter  *adapter = que->adapter;
+	struct adapter	*adapter;
 	uint32_t reg, usec, rate;
 	int error;
 
 	if (que == NULL)
 		return 0;
-	reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix));
+
+	adapter = que->adapter;
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
+	reg = IXGBE_READ_REG(&adapter->hw, IXGBE_EITR(que->msix));
 	usec = ((reg & 0x0FF8) >> 3);
 	if (usec > 0)
 		rate = 500000 / usec;
@@ -3205,8 +3272,8 @@ err:
 static void
 ixgbe_add_device_sysctls(struct adapter *adapter)
 {
-	device_t               dev = adapter->dev;
-	struct ixgbe_hw        *hw = &adapter->hw;
+	device_t	       dev = adapter->dev;
+	struct ixgbe_hw	       *hw = &adapter->hw;
 	struct sysctllog **log;
 	const struct sysctlnode *rnode, *cnode;
 
@@ -3374,7 +3441,7 @@ ixgbe_allocate_pci_resources(struct adap
 	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
 		adapter->osdep.mem_bus_space_tag = pa->pa_memt;
 		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(0),
-	              memtype, &addr, &adapter->osdep.mem_size, &flags) != 0)
+		      memtype, &addr, &adapter->osdep.mem_size, &flags) != 0)
 			goto map_err;
 		if ((flags & BUS_SPACE_MAP_PREFETCHABLE) != 0) {
 			aprint_normal_dev(dev, "clearing prefetchable bit\n");
@@ -3493,8 +3560,8 @@ ixgbe_detach(device_t dev, int flags)
 #if NVLAN > 0
 	/* Make sure VLANs are not using driver */
 	if (!VLAN_ATTACHED(&adapter->osdep.ec))
-		;	/* nothing to do: no VLANs */ 
-	else if ((flags & (DETACH_SHUTDOWN|DETACH_FORCE)) != 0)
+		;	/* nothing to do: no VLANs */
+	else if ((flags & (DETACH_SHUTDOWN | DETACH_FORCE)) != 0)
 		vlan_ifdetach(adapter->ifp);
 	else {
 		aprint_error_dev(dev, "VLANs in use, detach first\n");
@@ -3511,13 +3578,15 @@ ixgbe_detach(device_t dev, int flags)
 	IXGBE_CORE_UNLOCK(adapter);
 
 	ixgbe_free_softint(adapter);
-	
+
 	/* let hardware know driver is unloading */
 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
 
 	callout_halt(&adapter->timer, NULL);
+	if (adapter->feat_en & IXGBE_FEATURE_RECOVERY_MODE)
+		callout_halt(&adapter->recovery_mode_timer, NULL);
 
 	if (adapter->feat_en & IXGBE_FEATURE_NETMAP)
 		netmap_detach(adapter->ifp);
@@ -3667,8 +3736,8 @@ static int
 ixgbe_setup_low_power_mode(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	device_t        dev = adapter->dev;
-	s32             error = 0;
+	device_t	dev = adapter->dev;
+	s32		error = 0;
 
 	KASSERT(mutex_owned(&adapter->core_mtx));
 
@@ -3747,7 +3816,7 @@ static bool
 ixgbe_suspend(device_t dev, const pmf_qual_t *qual)
 {
 	struct adapter *adapter = device_private(dev);
-	int            error = 0;
+	int	       error = 0;
 
 	INIT_DEBUGOUT("ixgbe_suspend: begin");
 
@@ -3768,10 +3837,10 @@ ixgbe_suspend(device_t dev, const pmf_qu
 static bool
 ixgbe_resume(device_t dev, const pmf_qual_t *qual)
 {
-	struct adapter  *adapter = device_private(dev);
-	struct ifnet    *ifp = adapter->ifp;
+	struct adapter	*adapter = device_private(dev);
+	struct ifnet	*ifp = adapter->ifp;
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32             wus;
+	u32		wus;
 
 	INIT_DEBUGOUT("ixgbe_resume: begin");
 
@@ -3825,15 +3894,15 @@ static void
 ixgbe_init_locked(struct adapter *adapter)
 {
 	struct ifnet   *ifp = adapter->ifp;
-	device_t 	dev = adapter->dev;
+	device_t	dev = adapter->dev;
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que;
-	struct tx_ring  *txr;
-	struct rx_ring  *rxr;
+	struct tx_ring	*txr;
+	struct rx_ring	*rxr;
 	u32		txdctl, mhadd;
 	u32		rxdctl, rxctrl;
-	u32             ctrl_ext;
-	int             i, j, err;
+	u32		ctrl_ext;
+	int		i, j, err;
 
 	/* XXX check IFF_UP and IFF_RUNNING, power-saving state! */
 
@@ -3842,7 +3911,7 @@ ixgbe_init_locked(struct adapter *adapte
 
 	hw->adapter_stopped = FALSE;
 	ixgbe_stop_adapter(hw);
-        callout_stop(&adapter->timer);
+	callout_stop(&adapter->timer);
 	for (i = 0, que = adapter->queues; i < adapter->num_queues; i++, que++)
 		que->disabled_count = 0;
 
@@ -3970,7 +4039,7 @@ ixgbe_init_locked(struct adapter *adapte
 		if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
 		    (ifp->if_capenable & IFCAP_NETMAP)) {
 			struct netmap_adapter *na = NA(adapter->ifp);
-			struct netmap_kring *kring = &na->rx_rings[i];
+			struct netmap_kring *kring = na->rx_rings[i];
 			int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
 
 			IXGBE_WRITE_REG(hw, IXGBE_RDT(rxr->me), t);
@@ -4014,10 +4083,10 @@ ixgbe_init_locked(struct adapter *adapte
 	if (hw->phy.type == ixgbe_phy_none) {
 		err = hw->phy.ops.identify(hw);
 		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-                	device_printf(dev,
+			device_printf(dev,
 			    "Unsupported SFP+ module type was detected.\n");
 			return;
-        	}
+		}
 	}
 
 	/* Set moderation on the Link interrupt */
@@ -4035,7 +4104,7 @@ ixgbe_init_locked(struct adapter *adapte
 	ixgbe_config_link(adapter);
 
 	/* Hardware Packet Buffer & Flow Control setup */
-	ixgbe_config_delay_values(adapter);	
+	ixgbe_config_delay_values(adapter);
 
 	/* Initialize the FC settings */
 	ixgbe_start_hw(hw);
@@ -4140,7 +4209,7 @@ static void
 ixgbe_configure_ivars(struct adapter *adapter)
 {
 	struct ix_queue *que = adapter->queues;
-	u32             newitr;
+	u32		newitr;
 
 	if (ixgbe_max_interrupt_rate > 0)
 		newitr = (4000000 / ixgbe_max_interrupt_rate) & 0x0FF8;
@@ -4153,11 +4222,11 @@ ixgbe_configure_ivars(struct adapter *ad
 		newitr = 0;
 	}
 
-        for (int i = 0; i < adapter->num_queues; i++, que++) {
+	for (int i = 0; i < adapter->num_queues; i++, que++) {
 		struct rx_ring *rxr = &adapter->rx_rings[i];
 		struct tx_ring *txr = &adapter->tx_rings[i];
 		/* First the RX queue entry */
-                ixgbe_set_ivar(adapter, rxr->me, que->msix, 0);
+		ixgbe_set_ivar(adapter, rxr->me, que->msix, 0);
 		/* ... and the TX */
 		ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
 		/* Set an Initial EITR value */
@@ -4172,7 +4241,7 @@ ixgbe_configure_ivars(struct adapter *ad
 	}
 
 	/* For the Link interrupt */
-        ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
+	ixgbe_set_ivar(adapter, 1, adapter->vector, -1);
 } /* ixgbe_configure_ivars */
 
 /************************************************************************
@@ -4182,16 +4251,16 @@ static void
 ixgbe_config_gpie(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32             gpie;
+	u32		gpie;
 
 	gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
 
 	if (adapter->feat_en & IXGBE_FEATURE_MSIX) {
 		/* Enable Enhanced MSI-X mode */
 		gpie |= IXGBE_GPIE_MSIX_MODE
-		     |  IXGBE_GPIE_EIAME
-		     |  IXGBE_GPIE_PBA_SUPPORT
-		     |  IXGBE_GPIE_OCD;
+		     |	IXGBE_GPIE_EIAME
+		     |	IXGBE_GPIE_PBA_SUPPORT
+		     |	IXGBE_GPIE_OCD;
 	}
 
 	/* Fan Failure Interrupt */
@@ -4228,7 +4297,7 @@ static void
 ixgbe_config_delay_values(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32             rxpb, frame, size, tmp;
+	u32		rxpb, frame, size, tmp;
 
 	frame = adapter->max_frame_size;
 
@@ -4386,7 +4455,7 @@ ixgbe_local_timer1(void *arg)
 	v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = 0;
 	que = adapter->queues;
 	for (i = 0; i < adapter->num_queues; i++, que++) {
-		struct tx_ring  *txr = que->txr;
+		struct tx_ring	*txr = que->txr;
 
 		v0 += txr->q_efbig_tx_dma_setup;
 		v1 += txr->q_mbuf_defrag_failed;
@@ -4408,14 +4477,14 @@ ixgbe_local_timer1(void *arg)
 
 	/*
 	 * Check the TX queues status
-	 *      - mark hung queues so we don't schedule on them
-	 *      - watchdog only if all queues show hung
+	 *	- mark hung queues so we don't schedule on them
+	 *	- watchdog only if all queues show hung
 	 */
 	que = adapter->queues;
 	for (i = 0; i < adapter->num_queues; i++, que++) {
 		/* Keep track of queues with work for soft irq */
 		if (que->txr->busy)
-			queues |= ((u64)1 << que->me);
+			queues |= 1ULL << que->me;
 		/*
 		 * Each time txeof runs without cleaning, but there
 		 * are uncleaned descriptors it increments busy. If
@@ -4424,12 +4493,12 @@ ixgbe_local_timer1(void *arg)
 		if (que->busy == IXGBE_QUEUE_HUNG) {
 			++hung;
 			/* Mark the queue as inactive */
-			adapter->active_queues &= ~((u64)1 << que->me);
+			adapter->active_queues &= ~(1ULL << que->me);
 			continue;
 		} else {
 			/* Check if we've come back from hung */
-			if ((adapter->active_queues & ((u64)1 << que->me)) == 0)
-				adapter->active_queues |= ((u64)1 << que->me);
+			if ((adapter->active_queues & (1ULL << que->me)) == 0)
+				adapter->active_queues |= 1ULL << que->me;
 		}
 		if (que->busy >= IXGBE_MAX_TX_BUSY) {
 			device_printf(dev,
@@ -4467,6 +4536,32 @@ watchdog:
 } /* ixgbe_local_timer */
 
 /************************************************************************
+ * ixgbe_recovery_mode_timer - Recovery mode timer routine
+ ************************************************************************/
+static void
+ixgbe_recovery_mode_timer(void *arg)
+{
+	struct adapter *adapter = arg;
+	struct ixgbe_hw *hw = &adapter->hw;
+
+	IXGBE_CORE_LOCK(adapter);
+	if (ixgbe_fw_recovery_mode(hw)) {
+		if (atomic_cas_uint(&adapter->recovery_mode, 0, 1)) {
+			/* Firmware error detected, entering recovery mode */
+			device_printf(adapter->dev, "Firmware recovery mode detected. Limiting functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n");
+
+			if (hw->adapter_stopped == FALSE)
+				ixgbe_stop(adapter);
+		}
+	} else
+		atomic_cas_uint(&adapter->recovery_mode, 1, 0);
+
+	callout_reset(&adapter->recovery_mode_timer, hz,
+	    ixgbe_recovery_mode_timer, adapter);
+	IXGBE_CORE_UNLOCK(adapter);
+} /* ixgbe_recovery_mode_timer */
+
+/************************************************************************
  * ixgbe_sfp_probe
  *
  *   Determine if a port had optics inserted.
@@ -4489,7 +4584,7 @@ ixgbe_sfp_probe(struct adapter *adapter)
 			device_printf(dev,"Unsupported SFP+ module detected!");
 			device_printf(dev,
 			    "Reload driver with supported module.\n");
-                        goto out;
+			goto out;
 		} else
 			device_printf(dev, "SFP+ module detected!\n");
 		/* We now have supported optics */
@@ -4506,10 +4601,10 @@ out:
 static void
 ixgbe_handle_mod(void *context)
 {
-	struct adapter  *adapter = context;
+	struct adapter	*adapter = context;
 	struct ixgbe_hw *hw = &adapter->hw;
 	device_t	dev = adapter->dev;
-	u32             err, cage_full = 0;
+	u32		err, cage_full = 0;
 
 	++adapter->mod_sicount.ev_count;
 	if (adapter->hw.need_crosstalk_fix) {
@@ -4558,11 +4653,12 @@ ixgbe_handle_mod(void *context)
 static void
 ixgbe_handle_msf(void *context)
 {
-	struct adapter  *adapter = context;
+	struct adapter	*adapter = context;
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32             autoneg;
-	bool            negotiate;
+	u32		autoneg;
+	bool		negotiate;
 
+	IXGBE_CORE_LOCK(adapter);
 	++adapter->msf_sicount.ev_count;
 	/* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */
 	adapter->phy_layer = ixgbe_get_supported_physical_layer(hw);
@@ -4579,6 +4675,7 @@ ixgbe_handle_msf(void *context)
 	ifmedia_removeall(&adapter->media);
 	ixgbe_add_media_types(adapter);
 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
+	IXGBE_CORE_UNLOCK(adapter);
 } /* ixgbe_handle_msf */
 
 /************************************************************************
@@ -4587,7 +4684,7 @@ ixgbe_handle_msf(void *context)
 static void
 ixgbe_handle_phy(void *context)
 {
-	struct adapter  *adapter = context;
+	struct adapter	*adapter = context;
 	struct ixgbe_hw *hw = &adapter->hw;
 	int error;
 
@@ -4621,8 +4718,8 @@ ixgbe_ifstop(struct ifnet *ifp, int disa
 static void
 ixgbe_stop(void *arg)
 {
-	struct ifnet    *ifp;
-	struct adapter  *adapter = arg;
+	struct ifnet	*ifp;
+	struct adapter	*adapter = arg;
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	ifp = adapter->ifp;
@@ -4658,14 +4755,14 @@ ixgbe_stop(void *arg)
  * ixgbe_update_link_status - Update OS on link state
  *
  * Note: Only updates the OS on the cached link state.
- *       The real check of the hardware only happens with
- *       a link interrupt.
+ *	 The real check of the hardware only happens with
+ *	 a link interrupt.
  ************************************************************************/
 static void
 ixgbe_update_link_status(struct adapter *adapter)
 {
 	struct ifnet	*ifp = adapter->ifp;
-	device_t        dev = adapter->dev;
+	device_t	dev = adapter->dev;
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	KASSERT(mutex_owned(&adapter->core_mtx));
@@ -4734,7 +4831,7 @@ ixgbe_update_link_status(struct adapter 
 		/*
 		 * Do it when link active changes to DOWN. i.e.
 		 * a) LINK_STATE_UNKNOWN -> LINK_STATE_DOWN
-		 * b) LINK_STATE_UP      -> LINK_STATE_DOWN
+		 * b) LINK_STATE_UP	 -> LINK_STATE_DOWN
 		 */
 		if (adapter->link_active != LINK_STATE_DOWN) {
 			if (bootverbose)
@@ -4851,8 +4948,8 @@ ixgbe_enable_intr(struct adapter *adapte
 	 * allow for handling the extended (beyond 32) MSI-X
 	 * vectors that can be used by 82599
 	 */
-        for (int i = 0; i < adapter->num_queues; i++, que++)
-                ixgbe_enable_queue(adapter, que->msix);
+	for (int i = 0; i < adapter->num_queues; i++, que++)
+		ixgbe_enable_queue(adapter, que->msix);
 
 	IXGBE_WRITE_FLUSH(hw);
 
@@ -4908,10 +5005,10 @@ ixgbe_legacy_irq(void *arg)
 	struct ix_queue *que = arg;
 	struct adapter	*adapter = que->adapter;
 	struct ixgbe_hw	*hw = &adapter->hw;
-	struct ifnet    *ifp = adapter->ifp;
-	struct 		tx_ring *txr = adapter->tx_rings;
+	struct ifnet	*ifp = adapter->ifp;
+	struct		tx_ring *txr = adapter->tx_rings;
 	bool		more = false;
-	u32             eicr, eicr_mask;
+	u32		eicr, eicr_mask;
 
 	/* Silicon errata #26 on 82598 */
 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
@@ -5056,10 +5153,15 @@ static void
 ixgbe_set_sysctl_value(struct adapter *adapter, const char *name,
     const char *description, int *limit, int value)
 {
-	device_t dev =  adapter->dev;
+	device_t dev =	adapter->dev;
 	struct sysctllog **log;
 	const struct sysctlnode *rnode, *cnode;
 
+	/*
+	 * It's not required to check recovery mode because this function never
+	 * touches hardware.
+	 */
+
 	log = &adapter->sysctllog;
 	if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) {
 		aprint_error_dev(dev, "could not create sysctl root\n");
@@ -5085,6 +5187,9 @@ ixgbe_sysctl_flowcntl(SYSCTLFN_ARGS)
 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
 	int error, fc;
 
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
 	fc = adapter->hw.fc.current_mode;
 	node.sysctl_data = &fc;
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
@@ -5149,8 +5254,8 @@ static void
 ixgbe_enable_rx_drop(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	struct rx_ring  *rxr;
-	u32             srrctl;
+	struct rx_ring	*rxr;
+	u32		srrctl;
 
 	for (int i = 0; i < adapter->num_queues; i++) {
 		rxr = &adapter->rx_rings[i];
@@ -5174,14 +5279,14 @@ static void
 ixgbe_disable_rx_drop(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	struct rx_ring  *rxr;
-	u32             srrctl;
+	struct rx_ring	*rxr;
+	u32		srrctl;
 
 	for (int i = 0; i < adapter->num_queues; i++) {
 		rxr = &adapter->rx_rings[i];
-        	srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
-        	srrctl &= ~IXGBE_SRRCTL_DROP_EN;
-        	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
+		srrctl = IXGBE_READ_REG(hw, IXGBE_SRRCTL(rxr->me));
+		srrctl &= ~IXGBE_SRRCTL_DROP_EN;
+		IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rxr->me), srrctl);
 	}
 
 	/* disable drop for each vf */
@@ -5201,7 +5306,10 @@ ixgbe_sysctl_advertise(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
-	int            error = 0, advertise;
+	int	       error = 0, advertise;
+
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
 
 	advertise = adapter->advertise;
 	node.sysctl_data = &advertise;
@@ -5227,12 +5335,12 @@ ixgbe_sysctl_advertise(SYSCTLFN_ARGS)
 static int
 ixgbe_set_advertise(struct adapter *adapter, int advertise)
 {
-	device_t         dev;
-	struct ixgbe_hw  *hw;
+	device_t	 dev;
+	struct ixgbe_hw	 *hw;
 	ixgbe_link_speed speed = 0;
 	ixgbe_link_speed link_caps = 0;
-	s32              err = IXGBE_NOT_IMPLEMENTED;
-	bool             negotiate = FALSE;
+	s32		 err = IXGBE_NOT_IMPLEMENTED;
+	bool		 negotiate = FALSE;
 
 	/* Checks to validate new value */
 	if (adapter->advertise == advertise) /* no change */
@@ -5336,11 +5444,11 @@ ixgbe_set_advertise(struct adapter *adap
 static int
 ixgbe_get_advertise(struct adapter *adapter)
 {
-	struct ixgbe_hw  *hw = &adapter->hw;
-	int              speed;
+	struct ixgbe_hw	 *hw = &adapter->hw;
+	int		 speed;
 	ixgbe_link_speed link_caps = 0;
-	s32              err;
-	bool             negotiate = FALSE;
+	s32		 err;
+	bool		 negotiate = FALSE;
 
 	/*
 	 * Advertised speed means nothing unless it's copper or
@@ -5382,8 +5490,11 @@ ixgbe_sysctl_dmac(SYSCTLFN_ARGS)
 	struct sysctlnode node = *rnode;
 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
 	struct ifnet   *ifp = adapter->ifp;
-	int            error;
-	int            newval;
+	int	       error;
+	int	       newval;
+
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
 
 	newval = adapter->dmac;
 	node.sysctl_data = &newval;
@@ -5440,7 +5551,10 @@ 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;
+	int	       curr_ps, new_ps, error = 0;
+
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
 
 	curr_ps = new_ps = pci_get_powerstate(dev);
 
@@ -5481,11 +5595,15 @@ static int
 ixgbe_sysctl_wol_enable(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
-	struct adapter  *adapter = (struct adapter *)node.sysctl_data;
+	struct adapter	*adapter = (struct adapter *)node.sysctl_data;
 	struct ixgbe_hw *hw = &adapter->hw;
-	bool            new_wol_enabled;
-	int             error = 0;
+	bool		new_wol_enabled;
+	int		error = 0;
 
+	/*
+	 * It's not required to check recovery mode because this function never
+	 * touches hardware.
+	 */
 	new_wol_enabled = hw->wol_enabled;
 	node.sysctl_data = &new_wol_enabled;
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
@@ -5527,6 +5645,10 @@ ixgbe_sysctl_wufc(SYSCTLFN_ARGS)
 	int error = 0;
 	u32 new_wufc;
 
+	/*
+	 * It's not required to check recovery mode because this function never
+	 * touches hardware.
+	 */
 	new_wufc = adapter->wufc;
 	node.sysctl_data = &new_wufc;
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
@@ -5554,12 +5676,15 @@ ixgbe_sysctl_print_rss_config(SYSCTLFN_A
 {
 #ifdef notyet
 	struct sysctlnode node = *rnode;
-	struct adapter  *adapter = (struct adapter *)node.sysctl_data;
+	struct adapter	*adapter = (struct adapter *)node.sysctl_data;
 	struct ixgbe_hw *hw = &adapter->hw;
-	device_t        dev = adapter->dev;
-	struct sbuf     *buf;
-	int             error = 0, reta_size;
-	u32             reg;
+	device_t	dev = adapter->dev;
+	struct sbuf	*buf;
+	int		error = 0, reta_size;
+	u32		reg;
+
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
 
 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
 	if (!buf) {
@@ -5619,6 +5744,9 @@ ixgbe_sysctl_phy_temp(SYSCTLFN_ARGS)
 	u16 reg;
 	int		error;
 
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
 		device_printf(adapter->dev,
 		    "Device has no supported external thermal sensor.\n");
@@ -5659,6 +5787,9 @@ ixgbe_sysctl_phy_overtemp_occurred(SYSCT
 	int val, error;
 	u16 reg;
 
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
+
 	if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) {
 		device_printf(adapter->dev,
 		    "Device has no supported external thermal sensor.\n");
@@ -5700,8 +5831,11 @@ ixgbe_sysctl_eee_state(SYSCTLFN_ARGS)
 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
 	struct ifnet   *ifp = adapter->ifp;
 	device_t       dev = adapter->dev;
-	int            curr_eee, new_eee, error = 0;
-	s32            retval;
+	int	       curr_eee, new_eee, error = 0;
+	s32	       retval;
+
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
 
 	curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE);
 	node.sysctl_data = &new_eee;
@@ -5765,8 +5899,8 @@ ixgbe_sysctl_eee_state(SYSCTLFN_ARGS)
 static void
 ixgbe_print_debug_info(struct adapter *adapter)
 {
-        device_t        dev = adapter->dev;
-        struct ixgbe_hw *hw = &adapter->hw;
+	device_t	dev = adapter->dev;
+	struct ixgbe_hw *hw = &adapter->hw;
 	int table_size;
 	int i;
 
@@ -5780,7 +5914,7 @@ ixgbe_print_debug_info(struct adapter *a
 		table_size = 32;
 		break;
 	}
-	
+
 	device_printf(dev, "[E]RETA:\n");
 	for (i = 0; i < table_size; i++) {
 		if (i < 32)
@@ -5818,7 +5952,7 @@ ixgbe_print_debug_info(struct adapter *a
 		printf("%8d", adapter->queues[i].disabled_count);
 	}
 	printf("\n");
-	
+
 	device_printf(dev, "EIMS:\t%08x\n", IXGBE_READ_REG(hw, IXGBE_EIMS));
 	if (hw->mac.type != ixgbe_mac_82598EB) {
 		device_printf(dev, "EIMS_EX(0):\t%08x\n",
@@ -5836,7 +5970,10 @@ ixgbe_sysctl_debug(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
-	int            error, result = 0;
+	int	       error, result = 0;
+
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
 
 	node.sysctl_data = &result;
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
@@ -5857,11 +5994,11 @@ static void
 ixgbe_init_device_features(struct adapter *adapter)
 {
 	adapter->feat_cap = IXGBE_FEATURE_NETMAP
-	                  | IXGBE_FEATURE_RSS
-	                  | IXGBE_FEATURE_MSI
-	                  | IXGBE_FEATURE_MSIX
-	                  | IXGBE_FEATURE_LEGACY_IRQ
-	                  | IXGBE_FEATURE_LEGACY_TX;
+			  | IXGBE_FEATURE_RSS
+			  | IXGBE_FEATURE_MSI
+			  | IXGBE_FEATURE_MSIX
+			  | IXGBE_FEATURE_LEGACY_IRQ
+			  | IXGBE_FEATURE_LEGACY_TX;
 
 	/* Set capabilities first... */
 	switch (adapter->hw.mac.type) {
@@ -5877,17 +6014,29 @@ ixgbe_init_device_features(struct adapte
 			adapter->feat_cap |= IXGBE_FEATURE_BYPASS;
 		break;
 	case ixgbe_mac_X550:
+		/*
+		 * IXGBE_FEATURE_RECOVERY_MODE will be set after reading
+		 * NVM Image version.
+		 */
 		adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR;
 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
 		break;
 	case ixgbe_mac_X550EM_x:
+		/*
+		 * IXGBE_FEATURE_RECOVERY_MODE will be set after reading
+		 * NVM Image version.
+		 */
 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
 		if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR)
 			adapter->feat_cap |= IXGBE_FEATURE_EEE;
 		break;
 	case ixgbe_mac_X550EM_a:
+		/*
+		 * IXGBE_FEATURE_RECOVERY_MODE will be set after reading
+		 * NVM Image version.
+		 */
 		adapter->feat_cap |= IXGBE_FEATURE_SRIOV;
 		adapter->feat_cap |= IXGBE_FEATURE_FDIR;
 		adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ;
@@ -5923,6 +6072,11 @@ ixgbe_init_device_features(struct adapte
 	/* Thermal Sensor */
 	if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR)
 		adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR;
+	/*
+	 * Recovery mode:
+	 * NetBSD: IXGBE_FEATURE_RECOVERY_MODE will be controlled after reading
+	 * NVM Image version.
+	 */
 
 	/* Enabled via global sysctl... */
 	/* Flow Director */
@@ -6003,7 +6157,7 @@ ixgbe_ifflags_cb(struct ethercom *ec)
 {
 	struct ifnet *ifp = &ec->ec_if;
 	struct adapter *adapter = ifp->if_softc;
-	int change, rc = 0;
+	int change, rv = 0;
 
 	IXGBE_CORE_LOCK(adapter);
 
@@ -6011,17 +6165,19 @@ ixgbe_ifflags_cb(struct ethercom *ec)
 	if (change != 0)
 		adapter->if_flags = ifp->if_flags;
 
-	if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0)
-		rc = ENETRESET;
-	else if ((change & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+	if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
+		rv = ENETRESET;
+		goto out;
+	} else if ((change & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
 		ixgbe_set_promisc(adapter);
 
 	/* Set up VLAN support and filter */
 	ixgbe_setup_vlan_hw_support(adapter);
 
+out:
 	IXGBE_CORE_UNLOCK(adapter);
 
-	return rc;
+	return rv;
 }
 
 /************************************************************************
@@ -6038,10 +6194,13 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ifcapreq *ifcr = data;
 	struct ifreq	*ifr = data;
-	int             error = 0;
+	int		error = 0;
 	int l4csum_en;
-	const int l4csum = IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx|
-	     IFCAP_CSUM_TCPv6_Rx|IFCAP_CSUM_UDPv6_Rx;
+	const int l4csum = IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |
+	     IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx;
+
+	if (ixgbe_fw_recovery_mode_swflag(adapter))
+		return (EPERM);
 
 	switch (command) {
 	case SIOCSIFFLAGS:
@@ -6188,9 +6347,9 @@ static void
 ixgbe_handle_que(void *context)
 {
 	struct ix_queue *que = context;
-	struct adapter  *adapter = que->adapter;
-	struct tx_ring  *txr = que->txr;
-	struct ifnet    *ifp = adapter->ifp;
+	struct adapter	*adapter = que->adapter;
+	struct tx_ring	*txr = que->txr;
+	struct ifnet	*ifp = adapter->ifp;
 	bool		more = false;
 
 	que->handleq.ev_count++;
@@ -6246,12 +6405,12 @@ ixgbe_allocate_legacy(struct adapter *ad
 {
 	device_t	dev = adapter->dev;
 	struct ix_queue *que = adapter->queues;
-	struct tx_ring  *txr = adapter->tx_rings;
+	struct tx_ring	*txr = adapter->tx_rings;
 	int		counts[PCI_INTR_TYPE_SIZE];
 	pci_intr_type_t intr_type, max_type;
-	char            intrbuf[PCI_INTRSTR_LEN];
+	char		intrbuf[PCI_INTRSTR_LEN];
 	const char	*intrstr = NULL;
- 
+
 	/* We allocate a single interrupt resource */
 	max_type = PCI_INTR_TYPE_MSI;
 	counts[PCI_INTR_TYPE_MSIX] = 0;
@@ -6322,7 +6481,7 @@ alloc_retry:
 	if ((!(adapter->feat_en & IXGBE_FEATURE_LEGACY_TX)
 		& (txr->txr_si == NULL)) || (que->que_si == NULL)) {
 		aprint_error_dev(dev,
-		    "could not establish software interrupts\n"); 
+		    "could not establish software interrupts\n");
 
 		return ENXIO;
 	}
@@ -6338,19 +6497,19 @@ alloc_retry:
 static int
 ixgbe_allocate_msix(struct adapter *adapter, const struct pci_attach_args *pa)
 {
-	device_t        dev = adapter->dev;
-	struct 		ix_queue *que = adapter->queues;
-	struct  	tx_ring *txr = adapter->tx_rings;
+	device_t	dev = adapter->dev;
+	struct		ix_queue *que = adapter->queues;
+	struct		tx_ring *txr = adapter->tx_rings;
 	pci_chipset_tag_t pc;
 	char		intrbuf[PCI_INTRSTR_LEN];
 	char		intr_xname[32];
 	char		wqname[MAXCOMLEN];
 	const char	*intrstr = NULL;
-	int 		error, vector = 0;
+	int		error, vector = 0;
 	int		cpu_id = 0;
 	kcpuset_t	*affinity;
 #ifdef RSS
-	unsigned int    rss_buckets = 0;
+	unsigned int	rss_buckets = 0;
 	kcpuset_t	cpu_mask;
 #endif
 
@@ -6406,7 +6565,7 @@ ixgbe_allocate_msix(struct adapter *adap
 			goto err_out;
 		}
 		que->msix = vector;
-		adapter->active_queues |= (u64)(1 << que->msix);
+		adapter->active_queues |= 1ULL << que->msix;
 
 		if (adapter->feat_en & IXGBE_FEATURE_RSS) {
 #ifdef	RSS
@@ -6465,7 +6624,7 @@ ixgbe_allocate_msix(struct adapter *adap
 			ixgbe_handle_que, que);
 		if (que->que_si == NULL) {
 			aprint_error_dev(dev,
-			    "couldn't establish software interrupt\n"); 
+			    "couldn't establish software interrupt\n");
 			error = ENXIO;
 			goto err_out;
 		}
@@ -6527,7 +6686,7 @@ ixgbe_allocate_msix(struct adapter *adap
 			ixgbe_handle_mbx, adapter);
 		if (adapter->mbx_si == NULL) {
 			aprint_error_dev(dev,
-			    "could not establish software interrupts\n"); 
+			    "could not establish software interrupts\n");
 
 			error = ENXIO;
 			goto err_out;
@@ -6573,7 +6732,7 @@ ixgbe_configure_interrupts(struct adapte
 	 */
 	if (ncpu == 1)
 		goto msi;
-	
+
 	/* First try MSI-X */
 	msgs = pci_msix_count(adapter->osdep.pc, adapter->osdep.tag);
 	msgs = MIN(msgs, IXG_MAX_NINTR);
@@ -6612,7 +6771,7 @@ ixgbe_configure_interrupts(struct adapte
 	if (msgs >= want)
 		msgs = want;
 	else {
-               	aprint_error_dev(dev, "MSI-X Configuration Problem, "
+		aprint_error_dev(dev, "MSI-X Configuration Problem, "
 		    "%d vectors but %d queues wanted!\n",
 		    msgs, want);
 		goto msi;
@@ -6633,7 +6792,7 @@ msi:
 	adapter->feat_cap &= ~IXGBE_FEATURE_SRIOV;
 	adapter->feat_en  &= ~IXGBE_FEATURE_SRIOV;
 
-       	msgs = pci_msi_count(adapter->osdep.pc, adapter->osdep.tag);
+	msgs = pci_msi_count(adapter->osdep.pc, adapter->osdep.tag);
 	adapter->msix_mem = NULL; /* XXX */
 	if (msgs > 1)
 		msgs = 1;
@@ -6663,7 +6822,7 @@ msi:
 static void
 ixgbe_handle_link(void *context)
 {
-	struct adapter  *adapter = context;
+	struct adapter	*adapter = context;
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	IXGBE_CORE_LOCK(adapter);

Index: src/sys/dev/pci/ixgbe/ixgbe.h
diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.16 src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.17
--- src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.16	Fri Mar  1 17:33:24 2019
+++ src/sys/dev/pci/ixgbe/ixgbe.h	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.h,v 1.24.6.16 2019/03/01 17:33:24 martin Exp $ */
+/* $NetBSD: ixgbe.h,v 1.24.6.17 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -240,7 +240,7 @@
 #endif
 
 /*
- * Interrupt Moderation parameters 
+ * Interrupt Moderation parameters
  */
 #define IXGBE_LOW_LATENCY	128
 #define IXGBE_AVE_LATENCY	400
@@ -348,7 +348,7 @@ struct ix_queue {
  * The transmit ring, one per queue
  */
 struct tx_ring {
-        struct adapter		*adapter;
+	struct adapter		*adapter;
 	kmutex_t		tx_mtx;
 	u32			me;
 	u32			tail;
@@ -396,7 +396,7 @@ struct tx_ring {
  * The Receive ring, one per rx queue
  */
 struct rx_ring {
-        struct adapter		*adapter;
+	struct adapter		*adapter;
 	kmutex_t		rx_mtx;
 	u32			me;
 	u32			tail;
@@ -408,8 +408,8 @@ struct rx_ring {
 	bool			lro_enabled;
 	bool			hw_rsc;
 	bool			vtag_strip;
-        u16			next_to_refresh;
-        u16 			next_to_check;
+	u16			next_to_refresh;
+	u16 			next_to_check;
 	u16			num_desc;
 	u16			mbuf_sz;
 #if 0
@@ -574,6 +574,10 @@ struct adapter {
 	void 			(*init_locked)(struct adapter *);
 	void 			(*stop_locked)(void *);
 
+	/* Firmware error check */
+	u_int                   recovery_mode;
+	struct callout          recovery_mode_timer;
+
 	/* Misc stats maintained by the driver */
 	struct evcnt	   	efbig_tx_dma_setup;
 	struct evcnt   		mbuf_defrag_failed;
@@ -674,11 +678,11 @@ struct adapter {
 	"\nControl advertised link speed using these flags:\n" \
 	"\t0x01 - advertise 100M\n" \
 	"\t0x02 - advertise 1G\n" \
-        "\t0x04 - advertise 10G\n" \
-        "\t0x08 - advertise 10M\n" \
-        "\t0x10 - advertise 2.5G\n" \
-        "\t0x20 - advertise 5G\n\n" \
-        "\t5G, 2.5G, 100M and 10M are only supported on certain adapters."
+	"\t0x04 - advertise 10G\n" \
+	"\t0x08 - advertise 10M\n" \
+	"\t0x10 - advertise 2.5G\n" \
+	"\t0x20 - advertise 5G\n\n" \
+	"\t5G, 2.5G, 100M and 10M are only supported on certain adapters."
 
 #define IXGBE_SYSCTL_DESC_SET_FC \
 	"\nSet flow control mode using these values:\n" \
@@ -745,6 +749,18 @@ ixv_check_ether_addr(u8 *addr)
 	return (status);
 }
 
+/*
+ * This checks the adapter->recovery_mode software flag which is
+ * set by ixgbe_fw_recovery_mode().
+ *
+ */
+static inline bool
+ixgbe_fw_recovery_mode_swflag(struct adapter *adapter)
+{
+	return (adapter->feat_en & IXGBE_FEATURE_RECOVERY_MODE) &&
+	    atomic_load_acq_uint(&adapter->recovery_mode);
+}
+
 /* Shared Prototypes */
 void ixgbe_legacy_start(struct ifnet *);
 int  ixgbe_legacy_start_locked(struct ifnet *, struct tx_ring *);

Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.4 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.5
--- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.4	Thu Jul 26 23:21:54 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_82599.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82599.c,v 1.14.8.4 2018/07/26 23:21:54 snj Exp $ */
+/* $NetBSD: ixgbe_82599.c,v 1.14.8.5 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -566,9 +566,6 @@ enum ixgbe_media_type ixgbe_get_media_ty
 	case IXGBE_DEV_ID_82599_T3_LOM:
 		media_type = ixgbe_media_type_copper;
 		break;
-	case IXGBE_DEV_ID_82599_LS:
-		media_type = ixgbe_media_type_fiber_lco;
-		break;
 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
 		media_type = ixgbe_media_type_fiber_qsfp;
 		break;

Index: src/sys/dev/pci/ixgbe/ixgbe_api.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_api.c:1.15.8.4 src/sys/dev/pci/ixgbe/ixgbe_api.c:1.15.8.5
--- src/sys/dev/pci/ixgbe/ixgbe_api.c:1.15.8.4	Thu Jul 26 23:21:54 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_api.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_api.c,v 1.15.8.4 2018/07/26 23:21:54 snj Exp $ */
+/* $NetBSD: ixgbe_api.c,v 1.15.8.5 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -173,7 +173,6 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *
 	case IXGBE_DEV_ID_82599_SFP_SF_QP:
 	case IXGBE_DEV_ID_82599_QSFP_SF_QP:
 	case IXGBE_DEV_ID_82599EN_SFP:
-	case IXGBE_DEV_ID_82599_LS:
 	case IXGBE_DEV_ID_82599_CX4:
 	case IXGBE_DEV_ID_82599_BYPASS:
 	case IXGBE_DEV_ID_82599_T3_LOM:
@@ -1107,6 +1106,19 @@ s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, 
 }
 
 /**
+ *  ixgbe_toggle_txdctl - Toggle VF's queues
+ *  @hw: pointer to hardware structure
+ *  @vind: VMDq pool index
+ *
+ *  Enable and disable each queue in VF.
+ */
+s32 ixgbe_toggle_txdctl(struct ixgbe_hw *hw, u32 vind)
+{
+	return ixgbe_call_func(hw, hw->mac.ops.toggle_txdctl, (hw,
+			       vind), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
  *  ixgbe_fc_enable - Enable flow control
  *  @hw: pointer to hardware structure
  *
@@ -1310,6 +1322,18 @@ void ixgbe_restore_mdd_vf(struct ixgbe_h
 }
 
 /**
+ *  ixgbe_fw_recovery_mode - Check if in FW NVM recovery mode
+ *  @hw: pointer to hardware structure
+ *
+ **/
+bool ixgbe_fw_recovery_mode(struct ixgbe_hw *hw)
+{
+	if (hw->mac.ops.fw_recovery_mode)
+		return hw->mac.ops.fw_recovery_mode(hw);
+	return FALSE;
+}
+
+/**
  *  ixgbe_enter_lplu - Transition to low power states
  *  @hw: pointer to hardware structure
  *

Index: src/sys/dev/pci/ixgbe/ixgbe_api.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_api.h:1.9.8.3 src/sys/dev/pci/ixgbe/ixgbe_api.h:1.9.8.4
--- src/sys/dev/pci/ixgbe/ixgbe_api.h:1.9.8.3	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_api.h	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_api.h,v 1.9.8.3 2018/04/14 10:25:11 martin Exp $ */
+/* $NetBSD: ixgbe_api.h,v 1.9.8.4 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -133,6 +133,7 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, 
 s32 ixgbe_set_vlvf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
 		   bool vlan_on, u32 *vfta_delta, u32 vfta,
 		   bool vlvf_bypass);
+s32 ixgbe_toggle_txdctl(struct ixgbe_hw *hw, u32 vind);
 s32 ixgbe_fc_enable(struct ixgbe_hw *hw);
 s32 ixgbe_setup_fc(struct ixgbe_hw *hw);
 s32 ixgbe_set_fw_drv_ver(struct ixgbe_hw *hw, u8 maj, u8 min, u8 build,
@@ -219,6 +220,7 @@ void ixgbe_disable_mdd(struct ixgbe_hw *
 void ixgbe_enable_mdd(struct ixgbe_hw *hw);
 void ixgbe_mdd_event(struct ixgbe_hw *hw, u32 *vf_bitmap);
 void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf);
+bool ixgbe_fw_recovery_mode(struct ixgbe_hw *hw);
 s32 ixgbe_enter_lplu(struct ixgbe_hw *hw);
 s32 ixgbe_handle_lasi(struct ixgbe_hw *hw);
 void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed);

Index: src/sys/dev/pci/ixgbe/ixgbe_common.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_common.c:1.13.2.4 src/sys/dev/pci/ixgbe/ixgbe_common.c:1.13.2.5
--- src/sys/dev/pci/ixgbe/ixgbe_common.c:1.13.2.4	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_common.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_common.c,v 1.13.2.4 2018/04/14 10:25:11 martin Exp $ */
+/* $NetBSD: ixgbe_common.c,v 1.13.2.5 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -136,6 +136,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_
 	mac->ops.init_uta_tables = NULL;
 	mac->ops.enable_rx = ixgbe_enable_rx_generic;
 	mac->ops.disable_rx = ixgbe_disable_rx_generic;
+	mac->ops.toggle_txdctl = ixgbe_toggle_txdctl_generic;
 
 	/* Flow Control */
 	mac->ops.fc_enable = ixgbe_fc_enable_generic;
@@ -4163,6 +4164,61 @@ s32 ixgbe_clear_vfta_generic(struct ixgb
 }
 
 /**
+ *  ixgbe_toggle_txdctl_generic - Toggle VF's queues
+ *  @hw: pointer to hardware structure
+ *  @vf_number: VF index
+ *
+ *  Enable and disable each queue in VF.
+ */
+s32 ixgbe_toggle_txdctl_generic(struct ixgbe_hw *hw, u32 vf_number)
+{
+	u8  queue_count, i;
+	u32 offset, reg;
+
+	if (vf_number > 63)
+		return IXGBE_ERR_PARAM;
+
+	/*
+	 * Determine number of queues by checking
+	 * number of virtual functions
+	 */
+	reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT);
+	switch (reg & IXGBE_GCR_EXT_VT_MODE_MASK) {
+	case IXGBE_GCR_EXT_VT_MODE_64:
+		queue_count = 2;
+		break;
+	case IXGBE_GCR_EXT_VT_MODE_32:
+		queue_count = 4;
+		break;
+	case IXGBE_GCR_EXT_VT_MODE_16:
+		queue_count = 8;
+		break;
+	default:
+		return IXGBE_ERR_CONFIG;
+	}
+
+	/* Toggle queues */
+	for (i = 0; i < queue_count; ++i) {
+		/* Calculate offset of current queue */
+		offset = queue_count * vf_number + i;
+
+		/* Enable queue */
+		reg = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(offset));
+		reg |= IXGBE_TXDCTL_ENABLE;
+		IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(offset), reg);
+		IXGBE_WRITE_FLUSH(hw);
+
+		/* Disable queue */
+		reg = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(offset));
+		reg &= ~IXGBE_TXDCTL_ENABLE;
+		IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(offset), reg);
+		IXGBE_WRITE_FLUSH(hw);
+	}
+
+	return IXGBE_SUCCESS;
+}
+
+/**
  *  ixgbe_need_crosstalk_fix - Determine if we need to do cross talk fix
  *  @hw: pointer to hardware structure
  *
@@ -4579,11 +4635,18 @@ s32 ixgbe_hic_unlocked(struct ixgbe_hw *
 		msec_delay(1);
 	}
 
+	/* For each command except "Apply Update" perform
+	 * status checks in the HICR registry.
+	 */
+	if ((buffer[0] & IXGBE_HOST_INTERFACE_MASK_CMD) ==
+	    IXGBE_HOST_INTERFACE_APPLY_UPDATE_CMD)
+		return IXGBE_SUCCESS;
+
 	/* Check command completion */
 	if ((timeout && i == timeout) ||
 	    !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) {
 		ERROR_REPORT1(IXGBE_ERROR_CAUTION,
-			     "Command has failed with no status valid.\n");
+			      "Command has failed with no status valid.\n");
 		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
 	}
 
@@ -4651,7 +4714,7 @@ s32 ixgbe_host_interface_command(struct 
 	 * Read Flash command requires reading buffer length from
 	 * two byes instead of one byte
 	 */
-	if (resp->cmd == 0x30) {
+	if (resp->cmd == 0x30 || resp->cmd == 0x31) {
 		for (; bi < dword_len + 2; bi++) {
 			buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
 							  bi);

Index: src/sys/dev/pci/ixgbe/ixgbe_common.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_common.h:1.7.8.4 src/sys/dev/pci/ixgbe/ixgbe_common.h:1.7.8.5
--- src/sys/dev/pci/ixgbe/ixgbe_common.h:1.7.8.4	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_common.h	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_common.h,v 1.7.8.4 2018/04/14 10:25:11 martin Exp $ */
+/* $NetBSD: ixgbe_common.h,v 1.7.8.5 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -146,6 +146,7 @@ s32 ixgbe_set_vlvf_generic(struct ixgbe_
 			   bool vlvf_bypass);
 s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw);
 s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan, bool vlvf_bypass);
+s32 ixgbe_toggle_txdctl_generic(struct ixgbe_hw *hw, u32 vind);
 
 s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw,
 			       ixgbe_link_speed *speed,

Index: src/sys/dev/pci/ixgbe/ixgbe_features.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_features.h:1.1.4.2 src/sys/dev/pci/ixgbe/ixgbe_features.h:1.1.4.3
--- src/sys/dev/pci/ixgbe/ixgbe_features.h:1.1.4.2	Thu Dec 21 19:28:54 2017
+++ src/sys/dev/pci/ixgbe/ixgbe_features.h	Mon Jul 22 17:53:35 2019
@@ -57,12 +57,13 @@
 #define IXGBE_FEATURE_EEE                       (u32)(1 << 11)
 #define IXGBE_FEATURE_LEGACY_IRQ                (u32)(1 << 12)
 #define IXGBE_FEATURE_NEEDS_CTXD                (u32)(1 << 13)
+#define IXGBE_FEATURE_RECOVERY_MODE             (u32)(1 << 15)
 
 #define IXGBE_FEATURE_FLAGS "\20" \
 	"\1" "VF"	"\2" "SRIOV"	"\3" "RSS"	"\4" "NETMAP"	\
 	"\5" "FAN_FAIL"	"\6" "TEMP_SENSOR" "\7" "BYPASS" "\10" "LEGACY_TX" \
 	"\11" "FDIR"	"\12" "MSI"	"\13" "MSIX"	"\14" "EEE"	\
-	"\15" "LEGACY_IRQ" "\16" "NEEDS_CTXD"
+	"\15" "LEGACY_IRQ" "\16" "NEEDS_CTXD"		"\20" "RECOVERY_MODE"
 
 /* Check for OS support.  Undefine features if not included in the OS */
 #ifndef PCI_IOV
Index: src/sys/dev/pci/ixgbe/ixgbe_netmap.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_netmap.c:1.1.4.2 src/sys/dev/pci/ixgbe/ixgbe_netmap.c:1.1.4.3
--- src/sys/dev/pci/ixgbe/ixgbe_netmap.c:1.1.4.2	Thu Dec 21 19:28:54 2017
+++ src/sys/dev/pci/ixgbe/ixgbe_netmap.c	Mon Jul 22 17:53:35 2019
@@ -408,7 +408,6 @@ ixgbe_netmap_rxsync(struct netmap_kring 
 	 */
 	if (netmap_no_pendintr || force_update) {
 		int crclen = (ix_crcstrip) ? 0 : 4;
-		uint16_t slot_flags = kring->nkr_slot_flags;
 
 		nic_i = rxr->next_to_check; // or also k2n(kring->nr_hwtail)
 		nm_i = netmap_idx_n2k(kring, nic_i);
@@ -420,7 +419,7 @@ ixgbe_netmap_rxsync(struct netmap_kring 
 			if ((staterr & IXGBE_RXD_STAT_DD) == 0)
 				break;
 			ring->slot[nm_i].len = le16toh(curr->wb.upper.length) - crclen;
-			ring->slot[nm_i].flags = slot_flags;
+			ring->slot[nm_i].flags = 0;
 			bus_dmamap_sync(rxr->ptag,
 			    rxr->rx_buffers[nic_i].pmap, BUS_DMASYNC_POSTREAD);
 			nm_i = nm_next(nm_i, lim);

Index: src/sys/dev/pci/ixgbe/ixgbe_mbx.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.2 src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.3
--- src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.2	Sat Apr 14 10:25:12 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_mbx.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_mbx.c,v 1.6.8.2 2018/04/14 10:25:12 martin Exp $ */
+/* $NetBSD: ixgbe_mbx.c,v 1.6.8.3 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -39,6 +39,26 @@
 #include "ixgbe_mbx.h"
 
 /**
+ *  ixgbe_clear_mbx - Clear Mailbox Memory
+ *  @hw: pointer to the HW structure
+ *  @vf_number: id of mailbox to write
+ *
+ *  Set VFMBMEM of given VF to 0x0.
+ **/
+s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 vf_number)
+{
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+	s32 ret_val = IXGBE_SUCCESS;
+
+	DEBUGFUNC("ixgbe_clear_mbx");
+
+	if (mbx->ops.clear)
+		ret_val = mbx->ops.clear(hw, vf_number);
+
+	return ret_val;
+}
+
+/**
  *  ixgbe_poll_for_msg - Wait for message notification
  *  @hw: pointer to the HW structure
  *  @mbx_id: id of mailbox to write
@@ -408,6 +428,7 @@ void ixgbe_init_mbx_params_vf(struct ixg
 	mbx->ops.check_for_msg = ixgbe_check_for_msg_vf;
 	mbx->ops.check_for_ack = ixgbe_check_for_ack_vf;
 	mbx->ops.check_for_rst = ixgbe_check_for_rst_vf;
+	mbx->ops.clear = NULL;
 
 	mbx->stats.msgs_tx.ev_count = 0;
 	mbx->stats.msgs_rx.ev_count = 0;
@@ -625,6 +646,27 @@ out_no_read:
 }
 
 /**
+ *  ixgbe_clear_mbx_pf - Clear Mailbox Memory
+ *  @hw: pointer to the HW structure
+ *  @vf_number: the VF index
+ *
+ *  Set VFMBMEM of given VF to 0x0.
+ **/
+static s32 ixgbe_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_number)
+{
+	u16 mbx_size = hw->mbx.size;
+	u16 i;
+
+	if (vf_number > 63)
+		return IXGBE_ERR_PARAM;
+
+	for (i = 0; i < mbx_size; ++i)
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, 0x0);
+
+	return IXGBE_SUCCESS;
+}
+
+/**
  *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox
  *  @hw: pointer to the HW structure
  *
@@ -653,6 +695,7 @@ void ixgbe_init_mbx_params_pf(struct ixg
 	mbx->ops.check_for_msg = ixgbe_check_for_msg_pf;
 	mbx->ops.check_for_ack = ixgbe_check_for_ack_pf;
 	mbx->ops.check_for_rst = ixgbe_check_for_rst_pf;
+	mbx->ops.clear = ixgbe_clear_mbx_pf;
 
 	mbx->stats.msgs_tx.ev_count = 0;
 	mbx->stats.msgs_rx.ev_count = 0;

Index: src/sys/dev/pci/ixgbe/ixgbe_mbx.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.2 src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.3
--- src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.2	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_mbx.h	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_mbx.h,v 1.10.8.2 2018/04/14 10:25:11 martin Exp $ */
+/* $NetBSD: ixgbe_mbx.h,v 1.10.8.3 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -155,6 +155,7 @@ enum ixgbevf_xcast_modes {
 #define IXGBE_VF_MBX_INIT_TIMEOUT	2000 /* number of retries on mailbox */
 #define IXGBE_VF_MBX_INIT_DELAY		500  /* microseconds between retries */
 
+s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 vf_number);
 void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw);
 void ixgbe_init_mbx_params_vf(struct ixgbe_hw *);
 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);

Index: src/sys/dev/pci/ixgbe/ixgbe_netbsd.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.6.2.2 src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.6.2.3
--- src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.6.2.2	Tue Aug  7 13:33:23 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_netbsd.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_netbsd.c,v 1.6.2.2 2018/08/07 13:33:23 martin Exp $ */
+/* $NetBSD: ixgbe_netbsd.c,v 1.6.2.3 2019/07/22 17:53:35 martin Exp $ */
 /*
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -273,3 +273,19 @@ ixgbe_pci_enable_busmaster(pci_chipset_t
 		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, pci_cmd_word);
 	}
 }
+
+u_int
+atomic_load_acq_uint(volatile u_int *p)
+{
+	u_int rv;
+
+	rv = *p;
+	/*
+	 * XXX
+	 * membar_sync() is far more than we need on most CPUs;
+	 * we just don't have an MI load-acqure operation.
+	 */
+	membar_sync();
+
+	return rv;
+}

Index: src/sys/dev/pci/ixgbe/ixgbe_netbsd.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.7.6.1 src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.7.6.2
--- src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.7.6.1	Sat Jun  9 14:59:43 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_netbsd.h	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/*$NetBSD: ixgbe_netbsd.h,v 1.7.6.1 2018/06/09 14:59:43 martin Exp $*/
+/*$NetBSD: ixgbe_netbsd.h,v 1.7.6.2 2019/07/22 17:53:35 martin Exp $*/
 /*
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -96,4 +96,6 @@ void ixgbe_dmamap_unload(ixgbe_dma_tag_t
 struct mbuf *ixgbe_getjcl(ixgbe_extmem_head_t *, int, int, int, size_t);
 void ixgbe_pci_enable_busmaster(pci_chipset_tag_t, pcitag_t);
 
+u_int atomic_load_acq_uint(volatile u_int *);
+
 #endif /* _IXGBE_NETBSD_H */

Index: src/sys/dev/pci/ixgbe/ixgbe_phy.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.11.6.3 src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.11.6.4
--- src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.11.6.3	Sat Apr 14 10:25:12 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_phy.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_phy.c,v 1.11.6.3 2018/04/14 10:25:12 martin Exp $ */
+/* $NetBSD: ixgbe_phy.c,v 1.11.6.4 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -2612,7 +2612,6 @@ static bool ixgbe_get_i2c_data(struct ix
 {
 	u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw);
 	bool data;
-	UNREFERENCED_1PARAMETER(hw);
 
 	DEBUGFUNC("ixgbe_get_i2c_data");
 

Index: src/sys/dev/pci/ixgbe/ixgbe_type.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.8 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.9
--- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.8	Mon Apr  1 12:35:38 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_type.h	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_type.h,v 1.22.2.8 2019/04/01 12:35:38 martin Exp $ */
+/* $NetBSD: ixgbe_type.h,v 1.22.2.9 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -131,7 +131,6 @@
 #define IXGBE_SUBDEV_ID_82599EN_SFP_OCP1	0x0001
 #define IXGBE_DEV_ID_82599_XAUI_LOM		PCI_PRODUCT_INTEL_82599_XAUI_LOM
 #define IXGBE_DEV_ID_82599_T3_LOM		0x151C
-#define IXGBE_DEV_ID_82599_LS			0x154F
 #define IXGBE_DEV_ID_82599_VF			0x10ED
 #define IXGBE_DEV_ID_82599_VF_HV		0x152E
 #define IXGBE_DEV_ID_82599_BYPASS		0x155D
@@ -211,6 +210,10 @@
 #define IXGBE_FLA_X550EM_x	IXGBE_FLA
 #define IXGBE_FLA_X550EM_a	0x15F68
 #define IXGBE_FLA_BY_MAC(_hw)	IXGBE_BY_MAC((_hw), FLA)
+#define IXGBE_FLA_FL_SIZE_SHIFT_X540	17
+#define IXGBE_FLA_FL_SIZE_SHIFT_X550	12
+#define IXGBE_FLA_FL_SIZE_MASK_X540	(0x7 << IXGBE_FLA_FL_SIZE_SHIFT_X540)
+#define IXGBE_FLA_FL_SIZE_MASK_X550	(0x7 << IXGBE_FLA_FL_SIZE_SHIFT_X550)
 
 #define IXGBE_EEMNGCTL	0x10110
 #define IXGBE_EEMNGDATA	0x10114
@@ -878,6 +881,10 @@ struct ixgbe_dmac_config {
 #define IXGBE_RTTDQSEL		0x04904
 #define IXGBE_RTTDT1C		0x04908
 #define IXGBE_RTTDT1S		0x0490C
+#define IXGBE_RTTQCNCR		0x08B00
+#define IXGBE_RTTQCNTG		0x04A90
+#define IXGBE_RTTBCNRD		0x0498C
+#define IXGBE_RTTQCNRR		0x0498C
 #define IXGBE_RTTDTECC		0x04990
 #define IXGBE_RTTDTECC_NO_BCN	0x00000100
 
@@ -888,6 +895,7 @@ struct ixgbe_dmac_config {
 #define IXGBE_RTTBCNRC_RF_INT_MASK \
 	(IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT)
 #define IXGBE_RTTBCNRM	0x04980
+#define IXGBE_RTTQCNRM	0x04980
 
 /* BCN (for DCB) Registers */
 #define IXGBE_RTTBCNRS	0x04988
@@ -1096,6 +1104,9 @@ struct ixgbe_dmac_config {
 #define IXGBE_FWSM_MODE_MASK	0xE
 #define IXGBE_FWSM_TS_ENABLED	0x1
 #define IXGBE_FWSM_FW_MODE_PT	0x4
+#define IXGBE_FWSM_FW_NVM_RECOVERY_MODE (1 << 5)
+#define IXGBE_FWSM_EXT_ERR_IND_MASK 0x01F80000
+#define IXGBE_FWSM_FW_VAL_BIT	(1 << 15)
 
 /* ARC Subsystem registers */
 #define IXGBE_HICR		0x15F00
@@ -1441,6 +1452,7 @@ struct ixgbe_dmac_config {
 #define IXGBE_BARCTRL_FLSIZE		0x0700
 #define IXGBE_BARCTRL_FLSIZE_SHIFT	8
 #define IXGBE_BARCTRL_CSRSIZE		0x2000
+#define IXGBE_BARCTRL_CSRSIZE_SHIFT	13
 
 /* RSCCTL Bit Masks */
 #define IXGBE_RSCCTL_RSCEN	0x01
@@ -3759,7 +3771,6 @@ enum ixgbe_media_type {
 	ixgbe_media_type_fiber,
 	ixgbe_media_type_fiber_fixed,
 	ixgbe_media_type_fiber_qsfp,
-	ixgbe_media_type_fiber_lco,
 	ixgbe_media_type_copper,
 	ixgbe_media_type_backplane,
 	ixgbe_media_type_cx4,
@@ -4049,6 +4060,7 @@ struct ixgbe_mac_operations {
 	s32 (*init_uta_tables)(struct ixgbe_hw *);
 	void (*set_mac_anti_spoofing)(struct ixgbe_hw *, bool, int);
 	void (*set_vlan_anti_spoofing)(struct ixgbe_hw *, bool, int);
+	s32 (*toggle_txdctl)(struct ixgbe_hw *hw, u32 vf_index);
 
 	/* Flow Control */
 	s32 (*fc_enable)(struct ixgbe_hw *);
@@ -4078,6 +4090,7 @@ struct ixgbe_mac_operations {
 	void (*enable_mdd)(struct ixgbe_hw *hw);
 	void (*mdd_event)(struct ixgbe_hw *hw, u32 *vf_bitmap);
 	void (*restore_mdd_vf)(struct ixgbe_hw *hw, u32 vf);
+	bool (*fw_recovery_mode)(struct ixgbe_hw *hw);
 };
 
 struct ixgbe_phy_operations {
@@ -4132,6 +4145,8 @@ struct ixgbe_eeprom_info {
 	u16				address_bits;
 	u16 word_page_size;
 	u16 ctrl_word_3;
+	u8  nvm_image_ver_high;
+	u8  nvm_image_ver_low;
 };
 
 #define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED	0x01
@@ -4205,6 +4220,7 @@ struct ixgbe_mbx_operations {
 	s32  (*check_for_msg)(struct ixgbe_hw *, u16);
 	s32  (*check_for_ack)(struct ixgbe_hw *, u16);
 	s32  (*check_for_rst)(struct ixgbe_hw *, u16);
+	s32  (*clear)(struct ixgbe_hw *hw, u16 vf_number);
 };
 
 struct ixgbe_mbx_stats {
@@ -4505,4 +4521,16 @@ struct ixgbe_bypass_eeprom {
 #define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD	\
 				(0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT)
 
+/* Code Command (Flash I/F Interface) */
+#define IXGBE_HOST_INTERFACE_FLASH_READ_CMD			0x30
+#define IXGBE_HOST_INTERFACE_SHADOW_RAM_READ_CMD		0x31
+#define IXGBE_HOST_INTERFACE_FLASH_WRITE_CMD			0x32
+#define IXGBE_HOST_INTERFACE_SHADOW_RAM_WRITE_CMD		0x33
+#define IXGBE_HOST_INTERFACE_FLASH_MODULE_UPDATE_CMD		0x34
+#define IXGBE_HOST_INTERFACE_FLASH_BLOCK_EREASE_CMD		0x35
+#define IXGBE_HOST_INTERFACE_SHADOW_RAM_DUMP_CMD		0x36
+#define IXGBE_HOST_INTERFACE_FLASH_INFO_CMD			0x37
+#define IXGBE_HOST_INTERFACE_APPLY_UPDATE_CMD			0x38
+#define IXGBE_HOST_INTERFACE_MASK_CMD				0x000000FF
+
 #endif /* _IXGBE_TYPE_H_ */

Index: src/sys/dev/pci/ixgbe/ixgbe_vf.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.2 src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.3
--- src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.2	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_vf.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_vf.c,v 1.12.8.2 2018/04/14 10:25:11 martin Exp $ */
+/* $NetBSD: ixgbe_vf.c,v 1.12.8.3 2019/07/22 17:53:35 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -388,7 +388,6 @@ s32 ixgbe_update_mc_addr_list_vf(struct 
 				 u32 mc_addr_count, ixgbe_mc_addr_itr next,
 				 bool clear)
 {
-	struct ixgbe_mbx_info *mbx = &hw->mbx;
 	u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
 	u16 *vector_list = (u16 *)&msgbuf[1];
 	u32 vector;
@@ -419,8 +418,8 @@ s32 ixgbe_update_mc_addr_list_vf(struct 
 		DEBUGOUT1("Hash value = 0x%03X\n", vector);
 		vector_list[i] = (u16)vector;
 	}
-
-	return mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE, 0);
+	return ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf,
+	    IXGBE_VFMAILBOX_SIZE);
 }
 
 /**

Index: src/sys/dev/pci/ixgbe/ixgbe_x550.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.5.6.5 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.5.6.6
--- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.5.6.5	Tue Aug  7 13:33:23 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.c	Mon Jul 22 17:53:35 2019
@@ -87,6 +87,7 @@ s32 ixgbe_init_ops_X550(struct ixgbe_hw 
 	mac->ops.enable_mdd = ixgbe_enable_mdd_X550;
 	mac->ops.mdd_event = ixgbe_mdd_event_X550;
 	mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550;
+	mac->ops.fw_recovery_mode = ixgbe_fw_recovery_mode_X550;
 	mac->ops.disable_rx = ixgbe_disable_rx_x550;
 	/* Manageability interface */
 	mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550;
@@ -446,7 +447,7 @@ static s32 ixgbe_identify_phy_x550em(str
 
 	switch (hw->device_id) {
 	case IXGBE_DEV_ID_X550EM_A_SFP:
-		return ixgbe_identify_module_generic(hw);
+		return ixgbe_identify_sfp_module_X550em(hw);
 	case IXGBE_DEV_ID_X550EM_X_SFP:
 		/* set up for CS4227 usage */
 		ixgbe_setup_mux_ctl(hw);
@@ -454,7 +455,7 @@ static s32 ixgbe_identify_phy_x550em(str
 		/* Fallthrough */
 
 	case IXGBE_DEV_ID_X550EM_A_SFP_N:
-		return ixgbe_identify_module_generic(hw);
+		return ixgbe_identify_sfp_module_X550em(hw);
 		break;
 	case IXGBE_DEV_ID_X550EM_X_KX4:
 		hw->phy.type = ixgbe_phy_x550em_kx4;
@@ -2083,7 +2084,14 @@ s32 ixgbe_get_link_capabilities_X550em(s
 		else
 			*speed = IXGBE_LINK_SPEED_10GB_FULL;
 	} else {
+		*autoneg = TRUE;
+
 		switch (hw->phy.type) {
+		case ixgbe_phy_x550em_xfi:
+			*speed = IXGBE_LINK_SPEED_1GB_FULL |
+				 IXGBE_LINK_SPEED_10GB_FULL;
+			*autoneg = FALSE;
+			break;
 		case ixgbe_phy_ext_1g_t:
 		case ixgbe_phy_sgmii:
 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
@@ -2107,7 +2115,6 @@ s32 ixgbe_get_link_capabilities_X550em(s
 			    IXGBE_LINK_SPEED_1GB_FULL;
 			break;
 		}
-		*autoneg = TRUE;
 	}
 
 	return IXGBE_SUCCESS;
@@ -4817,3 +4824,19 @@ s32 ixgbe_set_fw_drv_ver_x550(struct ixg
 
 	return ret_val;
 }
+
+/**
+ * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode
+ * @hw: pointer t hardware structure
+ *
+ * Returns TRUE if in FW NVM recovery mode.
+ **/
+bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw)
+{
+	u32 fwsm;
+
+	fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
+
+	return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE);
+}
+

Index: src/sys/dev/pci/ixgbe/ixgbe_x550.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.2.12.2 src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.2.12.3
--- src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.2.12.2	Wed Apr  4 16:18:49 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.h	Mon Jul 22 17:53:35 2019
@@ -119,4 +119,5 @@ s32 ixgbe_reset_phy_t_X550em(struct ixgb
 s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw);
 s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx);
 s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx);
+bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw);
 #endif /* _IXGBE_X550_H_ */

Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.56.2.21 src/sys/dev/pci/ixgbe/ixv.c:1.56.2.22
--- src/sys/dev/pci/ixgbe/ixv.c:1.56.2.21	Mon Apr  1 12:35:38 2019
+++ src/sys/dev/pci/ixgbe/ixv.c	Mon Jul 22 17:53:35 2019
@@ -1,4 +1,4 @@
-/*$NetBSD: ixv.c,v 1.56.2.21 2019/04/01 12:35:38 martin Exp $*/
+/*$NetBSD: ixv.c,v 1.56.2.22 2019/07/22 17:53:35 martin Exp $*/
 
 /******************************************************************************
 
@@ -47,6 +47,7 @@
  * Driver version
  ************************************************************************/
 static const char ixv_driver_version[] = "2.0.1-k";
+/* XXX NetBSD: + 1.5.17 */
 
 /************************************************************************
  * PCI Device ID Table
@@ -78,41 +79,41 @@ static const char *ixv_strings[] = {
 /*********************************************************************
  *  Function prototypes
  *********************************************************************/
-static int      ixv_probe(device_t, cfdata_t, void *);
+static int	ixv_probe(device_t, cfdata_t, void *);
 static void	ixv_attach(device_t, device_t, void *);
-static int      ixv_detach(device_t, int);
+static int	ixv_detach(device_t, int);
 #if 0
-static int      ixv_shutdown(device_t);
+static int	ixv_shutdown(device_t);
 #endif
 static int	ixv_ifflags_cb(struct ethercom *);
-static int      ixv_ioctl(struct ifnet *, u_long, void *);
+static int	ixv_ioctl(struct ifnet *, u_long, void *);
 static int	ixv_init(struct ifnet *);
 static void	ixv_init_locked(struct adapter *);
 static void	ixv_ifstop(struct ifnet *, int);
-static void     ixv_stop(void *);
-static void     ixv_init_device_features(struct adapter *);
-static void     ixv_media_status(struct ifnet *, struct ifmediareq *);
-static int      ixv_media_change(struct ifnet *);
-static int      ixv_allocate_pci_resources(struct adapter *,
+static void	ixv_stop(void *);
+static void	ixv_init_device_features(struct adapter *);
+static void	ixv_media_status(struct ifnet *, struct ifmediareq *);
+static int	ixv_media_change(struct ifnet *);
+static int	ixv_allocate_pci_resources(struct adapter *,
 		    const struct pci_attach_args *);
-static int      ixv_allocate_msix(struct adapter *,
+static int	ixv_allocate_msix(struct adapter *,
 		    const struct pci_attach_args *);
-static int      ixv_configure_interrupts(struct adapter *);
+static int	ixv_configure_interrupts(struct adapter *);
 static void	ixv_free_pci_resources(struct adapter *);
-static void     ixv_local_timer(void *);
-static void     ixv_local_timer_locked(void *);
-static int      ixv_setup_interface(device_t, struct adapter *);
-static int      ixv_negotiate_api(struct adapter *);
-
-static void     ixv_initialize_transmit_units(struct adapter *);
-static void     ixv_initialize_receive_units(struct adapter *);
-static void     ixv_initialize_rss_mapping(struct adapter *);
-static void     ixv_check_link(struct adapter *);
-
-static void     ixv_enable_intr(struct adapter *);
-static void     ixv_disable_intr(struct adapter *);
-static void     ixv_set_multi(struct adapter *);
-static void     ixv_update_link_status(struct adapter *);
+static void	ixv_local_timer(void *);
+static void	ixv_local_timer_locked(void *);
+static int	ixv_setup_interface(device_t, struct adapter *);
+static int	ixv_negotiate_api(struct adapter *);
+
+static void	ixv_initialize_transmit_units(struct adapter *);
+static void	ixv_initialize_receive_units(struct adapter *);
+static void	ixv_initialize_rss_mapping(struct adapter *);
+static s32	ixv_check_link(struct adapter *);
+
+static void	ixv_enable_intr(struct adapter *);
+static void	ixv_disable_intr(struct adapter *);
+static void	ixv_set_multi(struct adapter *);
+static void	ixv_update_link_status(struct adapter *);
 static int	ixv_sysctl_debug(SYSCTLFN_PROTO);
 static void	ixv_set_ivar(struct adapter *, u8, u8, s8);
 static void	ixv_configure_ivars(struct adapter *);
@@ -131,16 +132,15 @@ static void	ixv_init_stats(struct adapte
 static void	ixv_update_stats(struct adapter *);
 static void	ixv_add_stats_sysctls(struct adapter *);
 
-
 /* Sysctl handlers */
 static void	ixv_set_sysctl_value(struct adapter *, const char *,
 		    const char *, int *, int);
-static int      ixv_sysctl_interrupt_rate_handler(SYSCTLFN_PROTO);
-static int      ixv_sysctl_next_to_check_handler(SYSCTLFN_PROTO);
-static int      ixv_sysctl_rdh_handler(SYSCTLFN_PROTO);
-static int      ixv_sysctl_rdt_handler(SYSCTLFN_PROTO);
-static int      ixv_sysctl_tdt_handler(SYSCTLFN_PROTO);
-static int      ixv_sysctl_tdh_handler(SYSCTLFN_PROTO);
+static int	ixv_sysctl_interrupt_rate_handler(SYSCTLFN_PROTO);
+static int	ixv_sysctl_next_to_check_handler(SYSCTLFN_PROTO);
+static int	ixv_sysctl_rdh_handler(SYSCTLFN_PROTO);
+static int	ixv_sysctl_rdt_handler(SYSCTLFN_PROTO);
+static int	ixv_sysctl_tdt_handler(SYSCTLFN_PROTO);
+static int	ixv_sysctl_tdh_handler(SYSCTLFN_PROTO);
 
 /* The MSI-X Interrupt handlers */
 static int	ixv_msix_que(void *);
@@ -148,7 +148,7 @@ static int	ixv_msix_mbx(void *);
 
 /* Deferred interrupt tasklets */
 static void	ixv_handle_que(void *);
-static void     ixv_handle_link(void *);
+static void	ixv_handle_link(void *);
 
 /* Workqueue handler for deferred work */
 static void	ixv_handle_que_work(struct work *, void *);
@@ -203,7 +203,7 @@ TUNABLE_INT("hw.ixv.rx_process_limit", &
 static int ixv_tx_process_limit = 256;
 TUNABLE_INT("hw.ixv.tx_process_limit", &ixv_tx_process_limit);
 
-/* Which pakcet processing uses workqueue or softint */
+/* Which packet processing uses workqueue or softint */
 static bool ixv_txrx_workqueue = false;
 
 /*
@@ -307,7 +307,7 @@ ixv_attach(device_t parent, device_t dev
 {
 	struct adapter *adapter;
 	struct ixgbe_hw *hw;
-	int             error = 0;
+	int		error = 0;
 	pcireg_t	id, subid;
 	const ixgbe_vendor_info_t *ent;
 	const struct pci_attach_args *pa = aux;
@@ -580,7 +580,7 @@ err_out:
 static int
 ixv_detach(device_t dev, int flags)
 {
-	struct adapter  *adapter = device_private(dev);
+	struct adapter	*adapter = device_private(dev);
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que = adapter->queues;
 	struct tx_ring *txr = adapter->tx_rings;
@@ -597,8 +597,8 @@ ixv_detach(device_t dev, int flags)
 #if NVLAN > 0
 	/* Make sure VLANs are not using driver */
 	if (!VLAN_ATTACHED(&adapter->osdep.ec))
-		;	/* nothing to do: no VLANs */ 
-	else if ((flags & (DETACH_SHUTDOWN|DETACH_FORCE)) != 0)
+		;	/* nothing to do: no VLANs */
+	else if ((flags & (DETACH_SHUTDOWN | DETACH_FORCE)) != 0)
 		vlan_ifdetach(adapter->ifp);
 	else {
 		aprint_error_dev(dev, "VLANs in use, detach first\n");
@@ -724,10 +724,10 @@ static void
 ixv_init_locked(struct adapter *adapter)
 {
 	struct ifnet	*ifp = adapter->ifp;
-	device_t 	dev = adapter->dev;
+	device_t	dev = adapter->dev;
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue	*que;
-	int             error = 0;
+	int		error = 0;
 	uint32_t mask;
 	int i;
 
@@ -798,7 +798,7 @@ ixv_init_locked(struct adapter *adapter)
 #endif
 	}
 #endif
-	
+
 	/* Set up VLAN offload and filter */
 	ixv_setup_vlan_support(adapter);
 
@@ -846,8 +846,8 @@ ixv_enable_queue(struct adapter *adapter
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que = &adapter->queues[vector];
-	u32             queue = 1 << vector;
-	u32             mask;
+	u32		queue = 1 << vector;
+	u32		mask;
 
 	mutex_enter(&que->dc_mtx);
 	if (que->disabled_count > 0 && --que->disabled_count > 0)
@@ -867,8 +867,8 @@ ixv_disable_queue(struct adapter *adapte
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que = &adapter->queues[vector];
-	u64             queue = (u64)(1 << vector);
-	u32             mask;
+	u64		queue = (u64)(1 << vector);
+	u32		mask;
 
 	mutex_enter(&que->dc_mtx);
 	if (que->disabled_count++ > 0)
@@ -895,7 +895,7 @@ static int
 ixv_msix_que(void *arg)
 {
 	struct ix_queue	*que = arg;
-	struct adapter  *adapter = que->adapter;
+	struct adapter	*adapter = que->adapter;
 	struct tx_ring	*txr = que->txr;
 	struct rx_ring	*rxr = que->rxr;
 	bool		more;
@@ -1105,10 +1105,10 @@ static int
 ixv_negotiate_api(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	int             mbx_api[] = { ixgbe_mbox_api_11,
-	                              ixgbe_mbox_api_10,
-	                              ixgbe_mbox_api_unknown };
-	int             i = 0;
+	int		mbx_api[] = { ixgbe_mbox_api_11,
+				      ixgbe_mbox_api_10,
+				      ixgbe_mbox_api_unknown };
+	int		i = 0;
 
 	while (mbx_api[i] != ixgbe_mbox_api_unknown) {
 		if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0)
@@ -1132,8 +1132,8 @@ ixv_set_multi(struct adapter *adapter)
 	struct ether_multistep step;
 	struct ethercom *ec = &adapter->osdep.ec;
 	u8	mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];
-	u8                 *update_ptr;
-	int                mcnt = 0;
+	u8		   *update_ptr;
+	int		   mcnt = 0;
 
 	KASSERT(mutex_owned(&adapter->core_mtx));
 	IOCTL_DEBUGOUT("ixv_set_multi: begin");
@@ -1208,7 +1208,10 @@ ixv_local_timer_locked(void *arg)
 
 	KASSERT(mutex_owned(&adapter->core_mtx));
 
-	ixv_check_link(adapter);
+	if (ixv_check_link(adapter)) {
+		ixv_init_locked(adapter);
+		return;
+	}
 
 	/* Stats Update */
 	ixv_update_stats(adapter);
@@ -1217,7 +1220,7 @@ ixv_local_timer_locked(void *arg)
 	v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = 0;
 	que = adapter->queues;
 	for (i = 0; i < adapter->num_queues; i++, que++) {
-		struct tx_ring  *txr = que->txr;
+		struct tx_ring	*txr = que->txr;
 
 		v0 += txr->q_efbig_tx_dma_setup;
 		v1 += txr->q_mbuf_defrag_failed;
@@ -1239,8 +1242,8 @@ ixv_local_timer_locked(void *arg)
 
 	/*
 	 * Check the TX queues status
-	 *      - mark hung queues so we don't schedule on them
-	 *      - watchdog only if all queues show hung
+	 *	- mark hung queues so we don't schedule on them
+	 *	- watchdog only if all queues show hung
 	 */
 	que = adapter->queues;
 	for (i = 0; i < adapter->num_queues; i++, que++) {
@@ -1295,8 +1298,8 @@ watchdog:
  * ixv_update_link_status - Update OS on link state
  *
  * Note: Only updates the OS on the cached link state.
- *       The real check of the hardware only happens with
- *       a link interrupt.
+ *	 The real check of the hardware only happens with
+ *	 a link interrupt.
  ************************************************************************/
 static void
 ixv_update_link_status(struct adapter *adapter)
@@ -1344,7 +1347,7 @@ ixv_update_link_status(struct adapter *a
 		/*
 		 * Do it when link active changes to DOWN. i.e.
 		 * a) LINK_STATE_UNKNOWN -> LINK_STATE_DOWN
-		 * b) LINK_STATE_UP      -> LINK_STATE_DOWN
+		 * b) LINK_STATE_UP	 -> LINK_STATE_DOWN
 		 */
 		if (adapter->link_active != LINK_STATE_DOWN) {
 			if (bootverbose)
@@ -1375,8 +1378,8 @@ ixv_ifstop(struct ifnet *ifp, int disabl
 static void
 ixv_stop(void *arg)
 {
-	struct ifnet    *ifp;
-	struct adapter  *adapter = arg;
+	struct ifnet	*ifp;
+	struct adapter	*adapter = arg;
 	struct ixgbe_hw *hw = &adapter->hw;
 
 	ifp = adapter->ifp;
@@ -1409,7 +1412,7 @@ ixv_allocate_pci_resources(struct adapte
     const struct pci_attach_args *pa)
 {
 	pcireg_t	memtype, csr;
-	device_t        dev = adapter->dev;
+	device_t	dev = adapter->dev;
 	bus_addr_t addr;
 	int flags;
 
@@ -1419,7 +1422,7 @@ ixv_allocate_pci_resources(struct adapte
 	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
 		adapter->osdep.mem_bus_space_tag = pa->pa_memt;
 		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(0),
-	              memtype, &addr, &adapter->osdep.mem_size, &flags) != 0)
+		      memtype, &addr, &adapter->osdep.mem_size, &flags) != 0)
 			goto map_err;
 		if ((flags & BUS_SPACE_MAP_PREFETCHABLE) != 0) {
 			aprint_normal_dev(dev, "clearing prefetchable bit\n");
@@ -1460,7 +1463,7 @@ map_err:
 static void
 ixv_free_pci_resources(struct adapter * adapter)
 {
-	struct 		ix_queue *que = adapter->queues;
+	struct		ix_queue *que = adapter->queues;
 	int		rid;
 
 	/*
@@ -1555,8 +1558,8 @@ ixv_setup_interface(device_t dev, struct
 
 	/* Set capability flags */
 	ifp->if_capabilities |= IFCAP_HWCSUM
-	                     |  IFCAP_TSOv4
-	                     |  IFCAP_TSOv6;
+			     |	IFCAP_TSOv4
+			     |	IFCAP_TSOv6;
 	ifp->if_capenable = 0;
 
 	ec->ec_capabilities |= ETHERCAP_VLAN_HWTAGGING
@@ -1644,10 +1647,10 @@ static void
 ixv_initialize_rss_mapping(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32             reta = 0, mrqc, rss_key[10];
-	int             queue_id;
-	int             i, j;
-	u32             rss_hash_config;
+	u32		reta = 0, mrqc, rss_key[10];
+	int		queue_id;
+	int		i, j;
+	u32		rss_hash_config;
 
 	/* force use default RSS key. */
 #ifdef __NetBSD__
@@ -1704,9 +1707,9 @@ ixv_initialize_rss_mapping(struct adapte
 		 * traffic.
 		 */
 		rss_hash_config = RSS_HASHTYPE_RSS_IPV4
-		                | RSS_HASHTYPE_RSS_TCP_IPV4
-		                | RSS_HASHTYPE_RSS_IPV6
-		                | RSS_HASHTYPE_RSS_TCP_IPV6;
+				| RSS_HASHTYPE_RSS_TCP_IPV4
+				| RSS_HASHTYPE_RSS_IPV6
+				| RSS_HASHTYPE_RSS_TCP_IPV6;
 	}
 
 	mrqc = IXGBE_MRQC_RSSEN;
@@ -1744,7 +1747,7 @@ ixv_initialize_receive_units(struct adap
 	struct	rx_ring	*rxr = adapter->rx_rings;
 	struct ixgbe_hw	*hw = &adapter->hw;
 	struct ifnet	*ifp = adapter->ifp;
-	u32		bufsz, rxcsum, psrtype;
+	u32		bufsz, psrtype;
 
 	if (ifp->if_mtu > ETHERMTU)
 		bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
@@ -1752,10 +1755,10 @@ ixv_initialize_receive_units(struct adap
 		bufsz = 2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
 
 	psrtype = IXGBE_PSRTYPE_TCPHDR
-	        | IXGBE_PSRTYPE_UDPHDR
-	        | IXGBE_PSRTYPE_IPV4HDR
-	        | IXGBE_PSRTYPE_IPV6HDR
-	        | IXGBE_PSRTYPE_L2HDR;
+		| IXGBE_PSRTYPE_UDPHDR
+		| IXGBE_PSRTYPE_IPV4HDR
+		| IXGBE_PSRTYPE_IPV6HDR
+		| IXGBE_PSRTYPE_L2HDR;
 
 	if (adapter->num_queues > 1)
 		psrtype |= 1 << 29;
@@ -1838,7 +1841,7 @@ ixv_initialize_receive_units(struct adap
 		if ((adapter->feat_en & IXGBE_FEATURE_NETMAP) &&
 		    (ifp->if_capenable & IFCAP_NETMAP)) {
 			struct netmap_adapter *na = NA(adapter->ifp);
-			struct netmap_kring *kring = &na->rx_rings[i];
+			struct netmap_kring *kring = na->rx_rings[i];
 			int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
 
 			IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rxr->me), t);
@@ -1848,22 +1851,7 @@ ixv_initialize_receive_units(struct adap
 			    adapter->num_rx_desc - 1);
 	}
 
-	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
-
 	ixv_initialize_rss_mapping(adapter);
-
-	if (adapter->num_queues > 1) {
-		/* RSS and RX IPP Checksum are mutually exclusive */
-		rxcsum |= IXGBE_RXCSUM_PCSD;
-	}
-
-	if (ifp->if_capenable & IFCAP_RXCSUM)
-		rxcsum |= IXGBE_RXCSUM_PCSD;
-
-	if (!(rxcsum & IXGBE_RXCSUM_PCSD))
-		rxcsum |= IXGBE_RXCSUM_IPPCSE;
-
-	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
 } /* ixv_initialize_receive_units */
 
 /************************************************************************
@@ -1871,7 +1859,7 @@ ixv_initialize_receive_units(struct adap
  *
  *   Retrieves the TDH value from the hardware
  ************************************************************************/
-static int 
+static int
 ixv_sysctl_tdh_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
@@ -1891,7 +1879,7 @@ ixv_sysctl_tdh_handler(SYSCTLFN_ARGS)
  *
  *   Retrieves the TDT value from the hardware
  ************************************************************************/
-static int 
+static int
 ixv_sysctl_tdt_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
@@ -1912,7 +1900,7 @@ ixv_sysctl_tdt_handler(SYSCTLFN_ARGS)
  *
  *   Retrieves the next_to_check value
  ************************************************************************/
-static int 
+static int
 ixv_sysctl_next_to_check_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
@@ -1932,7 +1920,7 @@ ixv_sysctl_next_to_check_handler(SYSCTLF
  *
  *   Retrieves the RDH value from the hardware
  ************************************************************************/
-static int 
+static int
 ixv_sysctl_rdh_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
@@ -1952,7 +1940,7 @@ ixv_sysctl_rdh_handler(SYSCTLFN_ARGS)
  *
  *   Retrieves the RDT value from the hardware
  ************************************************************************/
-static int 
+static int
 ixv_sysctl_rdt_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
@@ -2097,7 +2085,7 @@ ixv_enable_intr(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que = adapter->queues;
-	u32             mask;
+	u32		mask;
 	int i;
 
 	/* For VTEIAC */
@@ -2146,7 +2134,7 @@ static void
 ixv_set_ivar(struct adapter *adapter, u8 entry, u8 vector, s8 type)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32             ivar, index;
+	u32		ivar, index;
 
 	vector |= IXGBE_IVAR_ALLOC_VAL;
 
@@ -2155,7 +2143,7 @@ ixv_set_ivar(struct adapter *adapter, u8
 		ivar &= ~0xFF;
 		ivar |= vector;
 		IXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, ivar);
-	} else {          /* RX/TX IVARS */
+	} else {	  /* RX/TX IVARS */
 		index = (16 * (entry & 1)) + (8 * type);
 		ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR(entry >> 1));
 		ivar &= ~(0xFF << index);
@@ -2243,7 +2231,7 @@ ixv_init_stats(struct adapter *adapter)
 } /* ixv_init_stats */
 
 #define UPDATE_STAT_32(reg, last, count)		\
-{                                                       \
+{							\
 	u32 current = IXGBE_READ_REG(hw, (reg));	\
 	if (current < (last))				\
 		count.ev_count += 0x100000000LL;	\
@@ -2252,11 +2240,11 @@ ixv_init_stats(struct adapter *adapter)
 	count.ev_count |= current;			\
 }
 
-#define UPDATE_STAT_36(lsb, msb, last, count)           \
-{                                                       \
+#define UPDATE_STAT_36(lsb, msb, last, count)		\
+{							\
 	u64 cur_lsb = IXGBE_READ_REG(hw, (lsb));	\
 	u64 cur_msb = IXGBE_READ_REG(hw, (msb));	\
-	u64 current = ((cur_msb << 32) | cur_lsb);      \
+	u64 current = ((cur_msb << 32) | cur_lsb);	\
 	if (current < (last))				\
 		count.ev_count += 0x1000000000LL;	\
 	(last) = current;				\
@@ -2297,7 +2285,7 @@ ixv_sysctl_interrupt_rate_handler(SYSCTL
 {
 	struct sysctlnode node = *rnode;
 	struct ix_queue *que = (struct ix_queue *)node.sysctl_data;
-	struct adapter  *adapter = que->adapter;
+	struct adapter	*adapter = que->adapter;
 	uint32_t reg, usec, rate;
 	int error;
 
@@ -2401,9 +2389,9 @@ ixv_add_device_sysctls(struct adapter *a
 static void
 ixv_add_stats_sysctls(struct adapter *adapter)
 {
-	device_t                dev = adapter->dev;
-	struct tx_ring          *txr = adapter->tx_rings;
-	struct rx_ring          *rxr = adapter->rx_rings;
+	device_t		dev = adapter->dev;
+	struct tx_ring		*txr = adapter->tx_rings;
+	struct rx_ring		*rxr = adapter->rx_rings;
 	struct ixgbevf_hw_stats *stats = &adapter->stats.vf;
 	struct ixgbe_hw *hw = &adapter->hw;
 	const struct sysctlnode *rnode, *cnode;
@@ -2587,7 +2575,7 @@ static void
 ixv_set_sysctl_value(struct adapter *adapter, const char *name,
 	const char *description, int *limit, int value)
 {
-	device_t dev =  adapter->dev;
+	device_t dev =	adapter->dev;
 	struct sysctllog **log;
 	const struct sysctlnode *rnode, *cnode;
 
@@ -2614,18 +2602,14 @@ ixv_set_sysctl_value(struct adapter *ada
 static void
 ixv_print_debug_info(struct adapter *adapter)
 {
-        device_t        dev = adapter->dev;
-        struct ixgbe_hw *hw = &adapter->hw;
-        struct ix_queue *que = adapter->queues;
-        struct rx_ring  *rxr;
-        struct tx_ring  *txr;
+	device_t	dev = adapter->dev;
+	struct ix_queue *que = adapter->queues;
+	struct rx_ring	*rxr;
+	struct tx_ring	*txr;
 #ifdef LRO
-        struct lro_ctrl *lro;
+	struct lro_ctrl *lro;
 #endif /* LRO */
 
-	device_printf(dev, "Error Byte Count = %u \n",
-	    IXGBE_READ_REG(hw, IXGBE_ERRBC));
-
 	for (int i = 0; i < adapter->num_queues; i++, que++) {
 		txr = que->txr;
 		rxr = que->rxr;
@@ -2639,10 +2623,10 @@ ixv_print_debug_info(struct adapter *ada
 		device_printf(dev, "RX(%d) Bytes Received: %lu\n",
 		    rxr->me, (long)rxr->rx_bytes.ev_count);
 #ifdef LRO
-		device_printf(dev, "RX(%d) LRO Queued= %lld\n",
-		    rxr->me, (long long)lro->lro_queued);
-		device_printf(dev, "RX(%d) LRO Flushed= %lld\n",
-		    rxr->me, (long long)lro->lro_flushed);
+		device_printf(dev, "RX(%d) LRO Queued= %ju\n",
+		    rxr->me, (uintmax_t)lro->lro_queued);
+		device_printf(dev, "RX(%d) LRO Flushed= %ju\n",
+		    rxr->me, (uintmax_t)lro->lro_flushed);
 #endif /* LRO */
 		device_printf(dev, "TX(%d) Packets Sent: %lu\n",
 		    txr->me, (long)txr->total_packets.ev_count);
@@ -2662,7 +2646,7 @@ ixv_sysctl_debug(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node = *rnode;
 	struct adapter *adapter = (struct adapter *)node.sysctl_data;
-	int            error, result;
+	int	       error, result;
 
 	node.sysctl_data = &result;
 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
@@ -2683,9 +2667,9 @@ static void
 ixv_init_device_features(struct adapter *adapter)
 {
 	adapter->feat_cap = IXGBE_FEATURE_NETMAP
-	                  | IXGBE_FEATURE_VF
-	                  | IXGBE_FEATURE_RSS
-	                  | IXGBE_FEATURE_LEGACY_TX;
+			  | IXGBE_FEATURE_VF
+			  | IXGBE_FEATURE_RSS
+			  | IXGBE_FEATURE_LEGACY_TX;
 
 	/* A tad short on feature flags for VFs, atm. */
 	switch (adapter->hw.mac.type) {
@@ -2774,10 +2758,10 @@ ixv_ioctl(struct ifnet *ifp, u_long comm
 	struct adapter	*adapter = ifp->if_softc;
 	struct ifcapreq *ifcr = data;
 	struct ifreq	*ifr = data;
-	int             error = 0;
+	int		error = 0;
 	int l4csum_en;
-	const int l4csum = IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx|
-	     IFCAP_CSUM_TCPv6_Rx|IFCAP_CSUM_UDPv6_Rx;
+	const int l4csum = IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx |
+	     IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx;
 
 	switch (command) {
 	case SIOCSIFFLAGS:
@@ -2864,9 +2848,9 @@ static void
 ixv_handle_que(void *context)
 {
 	struct ix_queue *que = context;
-	struct adapter  *adapter = que->adapter;
+	struct adapter	*adapter = que->adapter;
 	struct tx_ring	*txr = que->txr;
-	struct ifnet    *ifp = adapter->ifp;
+	struct ifnet	*ifp = adapter->ifp;
 	bool		more;
 
 	que->handleq.ev_count++;
@@ -2929,7 +2913,7 @@ ixv_allocate_msix(struct adapter *adapte
 	device_t	dev = adapter->dev;
 	struct ix_queue *que = adapter->queues;
 	struct		tx_ring *txr = adapter->tx_rings;
-	int 		error, msix_ctrl, rid, vector = 0;
+	int		error, msix_ctrl, rid, vector = 0;
 	pci_chipset_tag_t pc;
 	pcitag_t	tag;
 	char		intrbuf[PCI_INTRSTR_LEN];
@@ -2973,7 +2957,7 @@ ixv_allocate_msix(struct adapter *adapte
 			return (ENXIO);
 		}
 		que->msix = vector;
-        	adapter->active_queues |= (u64)(1 << que->msix);
+		adapter->active_queues |= (u64)(1 << que->msix);
 
 		cpu_id = i;
 		/* Round-robin affinity */
@@ -2999,7 +2983,7 @@ ixv_allocate_msix(struct adapter *adapte
 			ixv_handle_que, que);
 		if (que->que_si == NULL) {
 			aprint_error_dev(dev,
-			    "could not establish software interrupt\n"); 
+			    "could not establish software interrupt\n");
 		}
 	}
 	snprintf(wqname, sizeof(wqname), "%sdeferTx", device_xname(dev));
@@ -3042,7 +3026,8 @@ ixv_allocate_msix(struct adapter *adapte
 	/* Round-robin affinity */
 	kcpuset_zero(affinity);
 	kcpuset_set(affinity, cpu_id % ncpu);
-	error = interrupt_distribute(adapter->osdep.ihs[vector], affinity,NULL);
+	error = interrupt_distribute(adapter->osdep.ihs[vector],
+	    affinity, NULL);
 
 	aprint_normal_dev(dev,
 	    "for link, interrupting at %s", intrstr);
@@ -3108,7 +3093,7 @@ ixv_configure_interrupts(struct adapter 
 	if (msgs >= want)
 		msgs = want;
 	else {
-               	aprint_error_dev(dev,
+		aprint_error_dev(dev,
 		    "MSI-X Configuration Problem, "
 		    "%d vectors but %d queues wanted!\n",
 		    msgs, want);
@@ -3146,15 +3131,18 @@ ixv_handle_link(void *context)
 /************************************************************************
  * ixv_check_link - Used in the local timer to poll for link changes
  ************************************************************************/
-static void
+static s32
 ixv_check_link(struct adapter *adapter)
 {
+	s32 error;
 
 	KASSERT(mutex_owned(&adapter->core_mtx));
 
 	adapter->hw.mac.get_link_status = TRUE;
 
-	adapter->hw.mac.ops.check_link(&adapter->hw, &adapter->link_speed,
-	    &adapter->link_up, FALSE);
+	error = adapter->hw.mac.ops.check_link(&adapter->hw,
+	    &adapter->link_speed, &adapter->link_up, FALSE);
 	ixv_update_link_status(adapter);
+
+	return error;
 } /* ixv_check_link */

Reply via email to