Module Name:    src
Committed By:   martin
Date:           Sat Jun  9 14:59:43 UTC 2018

Modified Files:
        src/sys/dev/pci/ixgbe [netbsd-8]: ix_txrx.c ixgbe.c ixgbe.h
            ixgbe_netbsd.c ixgbe_netbsd.h ixgbe_osdep.h ixv.c

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #864):

        sys/dev/pci/ixgbe/ix_txrx.c                     1.40-1.47 (patch)
        sys/dev/pci/ixgbe/ixgbe.c                       1.148,1.149,1.151,
                                                        1.152,1.154,
                                                        1.155,1.157-1.160 
(patch)
        sys/dev/pci/ixgbe/ixgbe.h                       1.43,1.44,1.46,1.49 
(patch)
        sys/dev/pci/ixgbe/ixgbe_netbsd.c                1.7 (patch)
        sys/dev/pci/ixgbe/ixgbe_netbsd.h                1.8 (patch)
        sys/dev/pci/ixgbe/ixgbe_osdep.h                 1.22 (patch)
        sys/dev/pci/ixgbe/ixv.c                         1.100-1.104 (patch)
        sys/dev/pci/ixgbe/ixv.c                         1.94,1.95,1.99 (patch)

 Remove unused structure entries. No functional change.
 -
 Remove unused IXGBE_FC_HI and IXGBE_FC_LO. The watermark of the flow control
is automatically calculated from the size of the packet buffer.
 -
 Use ixgbe_eitr_write() when writing the EITR for the link interrupt like
queue's EITR to write the register safely. This change is not relatively
so important than queue's EITR because link's EITR is written in if_init().
 -
 Don't free and reallocate bus_dmamem when it's not required. Currently,
the watchdog timer is completely broken and never fire (it's from FreeBSD
(pre iflib)). If the problem is fixed and watchdog fired, ixgbe_init() always
calls ixgbe_jcl_reinit() and it causes panic. The reason is that
ixgbe_local_timer1(it includes watchdog function) is softint and
xgbe_jcl_reinit() calls bus_dmamem*() functions. bus_dmamem*() can't be called
from interrupt context.

 One of the way to prevent panic is use worqueue for the timer, but it's
not a small change. (I'll do it in future).

 Another way is not reallocate dmamem if it's not required. If both the MTU
(rx_mbuf_sz in reality) and the number of RX descriptors are not changed, it's
not required to call bus_dmamem_{unmap,free}(). Even if we use workque, this
change save time of ixgbe_init().

 I have a code to fix broken watchdog timer but it sometime causes watchdog
timeout, so I don't commit it yet.
 -
Count some register correctly:
- QPRDC register is only for 82599 and newer.
- Count IXGBE_QPRDC, PX{ON,OFF}{T,R}XC[NT].
 The TQSMR register is not for receiving but for transmitting, so move the
initialization from ixgbe_initialize_receive_units() to
ixgbe_initialize_transmit_units(). No functional change.
 -
 Whitespace fix. No functional change.
 -
 Add rxd_nxck (Receive Descriptor next to check) read only sysctl.
 Don't check IFF_RUNNING in ixgbe_rxeof(). Doing break and leaving a deacriptor
with DD bit is worse than just processing the entry. And it's also racy to
check IFF_RUNNING in rxeof(). If you'd like to strictly obey IFF_RUNNING,
it would be better to do it in the upper layer.
 Same as DragonFly (a part of 79251f5ebe4cf9dd2f3e6aed590e09d756d39922).
 Add "bool txr_no_space" for TX descriptor shortage. Use it like IFF_OACTIVE.
 Clear que->disabled_count in {ixgbe,ixv}_init_locked(). Without this,
interrupt mask state and EIMS may mismatch and if_init doesn't recover
from TX/RX stall problem.
 This change itself doesn't fix PR#53294.
 -
 Add hw.ixgN.debug sysctl. "sysctl -w hw.ixgN.debug=1" dumps some registers
to console.
 -
Constify several variables in ixgbe/ so that they land in .rodata (1038
bytes).
 -
 Don't call ixgbe_rearm_queues() in ixgbe_local_timer1().
   ixgbe_enable_queue() and ixgbe_disable_queue() try to enable/disable queue
  interrupt safely. It has the internal counter. When a queue's MSI-X is
  received, ixgbe_msix_que() is called (IPL_NET). This function disable the
  queue's interrupt by ixgbe_disable_queue() and issues an softint.
  ixgbe_handle() queue is called by the softint (IPL_SOFTNET), process TX, RX
  and call ixgbe_enable_queue() at the end.

   ixgbe_local_timer1() is a callout and run always on CPU 0 (IPL_SOFTCLOCK).
  When ixgbe_rearm_queues() called, an MSI-X interrupt is issued for a specific
  queue. It may not CPU 0. If this interrupt's ixgbe_msix_que() is called and
  sofint_schedule() is called before the last sofint's softint_execute() is not
  called, the softint_schedule() fails because of SOFTINT_PENDING. It result
  in breaking ixgbe_{enable,disable}_queue()'s internal counter.
   ixgbe_local_timer1() is written not to call ixgbe_rearm_queues() if
  the interrupt is disabled, but it's called because of unknown bug or a race.

  One solution to avoid this problem is to not to use the internal counter,
  but it's little difficult. Another solution is stop using
  ixgbe_rearm_queues() at all. Essentially, ixgbe_rearm_queues() is not
  required (it was added in ixgbe.c rev. 1.43 (2016/12/01)).
  ixgbe_rearm_queues() helps for lost interrupt problem but I've never seen it
  other than ixgbe_rearm_queues() problem.

XXX pullup-8.


To generate a diff of this commit:
cvs rdiff -u -r1.24.2.10 -r1.24.2.11 src/sys/dev/pci/ixgbe/ix_txrx.c
cvs rdiff -u -r1.88.2.19 -r1.88.2.20 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.24.6.11 -r1.24.6.12 src/sys/dev/pci/ixgbe/ixgbe.h
cvs rdiff -u -r1.6 -r1.6.2.1 src/sys/dev/pci/ixgbe/ixgbe_netbsd.c
cvs rdiff -u -r1.7 -r1.7.6.1 src/sys/dev/pci/ixgbe/ixgbe_netbsd.h
cvs rdiff -u -r1.17.6.3 -r1.17.6.4 src/sys/dev/pci/ixgbe/ixgbe_osdep.h
cvs rdiff -u -r1.56.2.16 -r1.56.2.17 src/sys/dev/pci/ixgbe/ixv.c

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

Modified files:

Index: src/sys/dev/pci/ixgbe/ix_txrx.c
diff -u src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.10 src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.11
--- src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.10	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/ix_txrx.c	Sat Jun  9 14:59:43 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ix_txrx.c,v 1.24.2.10 2018/04/14 10:25:11 martin Exp $ */
+/* $NetBSD: ix_txrx.c,v 1.24.2.11 2018/06/09 14:59:43 martin Exp $ */
 
 /******************************************************************************
 
@@ -146,7 +146,9 @@ ixgbe_legacy_start_locked(struct ifnet *
 	}
 	if ((ifp->if_flags & IFF_RUNNING) == 0)
 		return (ENETDOWN);
-
+	if (txr->txr_no_space)
+		return (ENETDOWN);
+	
 	while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 		if (txr->tx_avail <= IXGBE_QUEUE_MIN_FREE)
 			break;
@@ -247,6 +249,8 @@ ixgbe_mq_start(struct ifnet *ifp, struct
 		IXGBE_TX_UNLOCK(txr);
 	} else {
 		if (adapter->txrx_use_workqueue) {
+			u_int *enqueued;
+
 			/*
 			 * This function itself is not called in interrupt
 			 * context, however it can be called in fast softint
@@ -255,11 +259,12 @@ ixgbe_mq_start(struct ifnet *ifp, struct
 			 * enqueuing when the machine uses both spontaneous
 			 * packets and forwarding packets.
 			 */
-			u_int *enqueued = percpu_getref(adapter->txr_wq_enqueued);
+			enqueued = percpu_getref(adapter->txr_wq_enqueued);
 			if (*enqueued == 0) {
 				*enqueued = 1;
 				percpu_putref(adapter->txr_wq_enqueued);
-				workqueue_enqueue(adapter->txr_wq, &txr->wq_cookie, curcpu());
+				workqueue_enqueue(adapter->txr_wq,
+				    &txr->wq_cookie, curcpu());
 			} else
 				percpu_putref(adapter->txr_wq_enqueued);
 		} else
@@ -288,6 +293,8 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
 	}
 	if ((ifp->if_flags & IFF_RUNNING) == 0)
 		return (ENETDOWN);
+	if (txr->txr_no_space)
+		return (ENETDOWN);
 
 	/* Process the queue */
 	while ((next = pcq_get(txr->txr_interq)) != NULL) {
@@ -458,6 +465,7 @@ retry:
 
 	/* Make certain there are enough descriptors */
 	if (txr->tx_avail < (map->dm_nsegs + 2)) {
+		txr->txr_no_space = true;
 		txr->no_desc_avail.ev_count++;
 		ixgbe_dmamap_unload(txr->txtag, txbuf->map);
 		return EAGAIN;
@@ -494,8 +502,7 @@ retry:
 		segaddr = htole64(map->dm_segs[j].ds_addr);
 
 		txd->read.buffer_addr = segaddr;
-		txd->read.cmd_type_len = htole32(txr->txd_cmd |
-		    cmd_type_len | seglen);
+		txd->read.cmd_type_len = htole32(cmd_type_len | seglen);
 		txd->read.olinfo_status = htole32(olinfo_status);
 
 		if (++i == txr->num_desc)
@@ -1157,6 +1164,7 @@ ixgbe_txeof(struct tx_ring *txr)
 			buf->m_head = NULL;
 		}
 		buf->eop = NULL;
+		txr->txr_no_space = false;
 		++txr->tx_avail;
 
 		/* We clean the range if multi segment */
@@ -1608,7 +1616,7 @@ ixgbe_setup_receive_structures(struct ad
 	 * or size of jumbo mbufs may have changed.
 	 * Assume all of rxr->ptag are the same.
 	 */
-	ixgbe_jcl_reinit(&adapter->jcl_head, rxr->ptag->dt_dmat,
+	ixgbe_jcl_reinit(adapter, rxr->ptag->dt_dmat,
 	    (2 * adapter->num_rx_desc) * adapter->num_queues,
 	    adapter->rx_mbuf_sz);
 
@@ -1831,8 +1839,6 @@ ixgbe_rxeof(struct ix_queue *que)
 
 		if ((staterr & IXGBE_RXD_STAT_DD) == 0)
 			break;
-		if ((ifp->if_flags & IFF_RUNNING) == 0)
-			break;
 
 		count--;
 		sendmp = NULL;
@@ -1970,46 +1976,46 @@ ixgbe_rxeof(struct ix_queue *que)
 			if (adapter->num_queues > 1) {
 				sendmp->m_pkthdr.flowid =
 				    le32toh(cur->wb.lower.hi_dword.rss);
-				switch (pkt_info & IXGBE_RXDADV_RSSTYPE_MASK) {	 
-				    case IXGBE_RXDADV_RSSTYPE_IPV4:
+				switch (pkt_info & IXGBE_RXDADV_RSSTYPE_MASK) {
+				case IXGBE_RXDADV_RSSTYPE_IPV4:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_IPV4);
 					break;
-				    case IXGBE_RXDADV_RSSTYPE_IPV4_TCP:
+				case IXGBE_RXDADV_RSSTYPE_IPV4_TCP:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_TCP_IPV4);
 					break;
-				    case IXGBE_RXDADV_RSSTYPE_IPV6:
+				case IXGBE_RXDADV_RSSTYPE_IPV6:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_IPV6);
 					break;
-				    case IXGBE_RXDADV_RSSTYPE_IPV6_TCP:
+				case IXGBE_RXDADV_RSSTYPE_IPV6_TCP:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_TCP_IPV6);
 					break;
-				    case IXGBE_RXDADV_RSSTYPE_IPV6_EX:
+				case IXGBE_RXDADV_RSSTYPE_IPV6_EX:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_IPV6_EX);
 					break;
-				    case IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX:
+				case IXGBE_RXDADV_RSSTYPE_IPV6_TCP_EX:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_TCP_IPV6_EX);
 					break;
 #if __FreeBSD_version > 1100000
-				    case IXGBE_RXDADV_RSSTYPE_IPV4_UDP:
+				case IXGBE_RXDADV_RSSTYPE_IPV4_UDP:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_UDP_IPV4);
 					break;
-				    case IXGBE_RXDADV_RSSTYPE_IPV6_UDP:
+				case IXGBE_RXDADV_RSSTYPE_IPV6_UDP:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_UDP_IPV6);
 					break;
-				    case IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX:
+				case IXGBE_RXDADV_RSSTYPE_IPV6_UDP_EX:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_RSS_UDP_IPV6_EX);
 					break;
 #endif
-				    default:
+				default:
 					M_HASHTYPE_SET(sendmp,
 					    M_HASHTYPE_OPAQUE_HASH);
 				}
@@ -2134,7 +2140,8 @@ ixgbe_dma_malloc(struct adapter *adapter
 			       &dma->dma_tag);
 	if (r != 0) {
 		aprint_error_dev(dev,
-		    "%s: ixgbe_dma_tag_create failed; error %d\n", __func__, r);
+		    "%s: ixgbe_dma_tag_create failed; error %d\n", __func__,
+		    r);
 		goto fail_0;
 	}
 
@@ -2266,8 +2273,6 @@ ixgbe_allocate_queues(struct adapter *ad
 		txr->num_desc = adapter->num_tx_desc;
 
 		/* Initialize the TX side lock */
-		snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
-		    device_xname(dev), txr->me);
 		mutex_init(&txr->tx_mtx, MUTEX_DEFAULT, IPL_NET);
 
 		if (ixgbe_dma_malloc(adapter, tsize, &txr->txdma,
@@ -2318,8 +2323,6 @@ ixgbe_allocate_queues(struct adapter *ad
 		rxr->num_desc = adapter->num_rx_desc;
 
 		/* Initialize the RX side lock */
-		snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",
-		    device_xname(dev), rxr->me);
 		mutex_init(&rxr->rx_mtx, MUTEX_DEFAULT, IPL_NET);
 
 		if (ixgbe_dma_malloc(adapter, rsize, &rxr->rxdma,

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.19 src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.20
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.19	Thu Jun  7 17:42:24 2018
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Sat Jun  9 14:59:43 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.88.2.19 2018/06/07 17:42:24 martin Exp $ */
+/* $NetBSD: ixgbe.c,v 1.88.2.20 2018/06/09 14:59:43 martin Exp $ */
 
 /******************************************************************************
 
@@ -80,7 +80,7 @@
 /************************************************************************
  * Driver version
  ************************************************************************/
-char ixgbe_driver_version[] = "4.0.1-k";
+static const char ixgbe_driver_version[] = "4.0.1-k";
 
 
 /************************************************************************
@@ -92,7 +92,7 @@ char ixgbe_driver_version[] = "4.0.1-k";
  *
  *   { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
  ************************************************************************/
-static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
+static const ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
 {
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_DUAL_PORT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
@@ -208,7 +208,7 @@ static void     ixgbe_update_link_status
 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 *);
-static void	ixgbe_eitr_write(struct ix_queue *, uint32_t);
+static void	ixgbe_eitr_write(struct adapter *, uint32_t, uint32_t);
 
 static void	ixgbe_setup_vlan_hw_support(struct adapter *);
 #if 0
@@ -236,11 +236,13 @@ 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_debug(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_wol_enable(SYSCTLFN_PROTO);
 static int	ixgbe_sysctl_wufc(SYSCTLFN_PROTO);
 
@@ -264,7 +266,7 @@ static void	ixgbe_handle_phy(void *);
 /* Workqueue handler for deferred work */
 static void	ixgbe_handle_que_work(struct work *, void *);
 
-static ixgbe_vendor_info_t *ixgbe_lookup(const struct pci_attach_args *);
+static const ixgbe_vendor_info_t *ixgbe_lookup(const struct pci_attach_args *);
 
 /************************************************************************
  *  NetBSD Device Interface Entry Points
@@ -581,7 +583,7 @@ ixgbe_initialize_receive_units(struct ad
 
 	for (i = 0; i < adapter->num_queues; i++, rxr++) {
 		u64 rdba = rxr->rxdma.dma_paddr;
-		u32 tqsmreg, reg;
+		u32 reg;
 		int regnum = i / 4;	/* 1 register per 4 queues */
 		int regshift = i % 4;	/* 4 bits per 1 queue */
 		j = rxr->me;
@@ -607,20 +609,6 @@ ixgbe_initialize_receive_units(struct ad
 		IXGBE_WRITE_REG(hw, IXGBE_RQSMR(regnum), reg);
 
 		/*
-		 * Set RQSMR (Receive Queue Statistic Mapping) register.
-		 * Register location for queue 0...7 are different between
-		 * 82598 and newer.
-		 */
-		if (adapter->hw.mac.type == ixgbe_mac_82598EB)
-			tqsmreg = IXGBE_TQSMR(regnum);
-		else
-			tqsmreg = IXGBE_TQSM(regnum);
-		reg = IXGBE_READ_REG(hw, tqsmreg);
-		reg &= ~(0x000000ff << (regshift * 8));
-		reg |= i << (regshift * 8);
-		IXGBE_WRITE_REG(hw, tqsmreg, reg);
-
-		/*
 		 * Set DROP_EN iff we have no flow control and >1 queue.
 		 * Note that srrctl was cleared shortly before during reset,
 		 * so we do not need to clear the bit, but do it just in case
@@ -685,6 +673,9 @@ ixgbe_initialize_transmit_units(struct a
 	for (i = 0; i < adapter->num_queues; i++, txr++) {
 		u64 tdba = txr->txdma.dma_paddr;
 		u32 txctrl = 0;
+		u32 tqsmreg, reg;
+		int regnum = i / 4;	/* 1 register per 4 queues */
+		int regshift = i % 4;	/* 4 bits per 1 queue */
 		int j = txr->me;
 
 		IXGBE_WRITE_REG(hw, IXGBE_TDBAL(j),
@@ -693,6 +684,19 @@ ixgbe_initialize_transmit_units(struct a
 		IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j),
 		    adapter->num_tx_desc * sizeof(union ixgbe_adv_tx_desc));
 
+		/*
+		 * Set TQSMR (Transmit Queue Statistic Mapping) register.
+		 * Register location is different between 82598 and others.
+		 */
+		if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+			tqsmreg = IXGBE_TQSMR(regnum);
+		else
+			tqsmreg = IXGBE_TQSM(regnum);
+		reg = IXGBE_READ_REG(hw, tqsmreg);
+		reg &= ~(0x000000ff << (regshift * 8));
+		reg |= i << (regshift * 8);
+		IXGBE_WRITE_REG(hw, tqsmreg, reg);
+
 		/* Setup the HW Tx Head and Tail descriptor pointers */
 		IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0);
 		IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0);
@@ -700,6 +704,8 @@ ixgbe_initialize_transmit_units(struct a
 		/* Cache the tail address */
 		txr->tail = IXGBE_TDT(j);
 
+		txr->txr_no_space = false;
+
 		/* Disable Head Writeback */
 		/*
 		 * Note: for X550 series devices, these registers are actually
@@ -763,7 +769,7 @@ ixgbe_attach(device_t parent, device_t d
 	u32		ctrl_ext;
 	u16		high, low, nvmreg;
 	pcireg_t	id, subid;
-	ixgbe_vendor_info_t *ent;
+	const ixgbe_vendor_info_t *ent;
 	struct pci_attach_args *pa = aux;
 	const char *str;
 	char buf[256];
@@ -1557,16 +1563,24 @@ 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 (int i = 0; i < __arraycount(stats->qprc); i++) {
 		int 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));
-		stats->qprdc[j].ev_count += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+		if (hw->mac.type >= ixgbe_mac_82599EB) {
+			stats->qprdc[j].ev_count
+			    += IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+		}
 	}
+
+	/* 8 registers */
 	for (int i = 0; i < __arraycount(stats->mpc); i++) {
 		uint32_t mp;
 		int j = i % adapter->num_queues;
 
+		/* MPC */
 		mp = IXGBE_READ_REG(hw, IXGBE_MPC(i));
 		/* global total per queue */
 		stats->mpc[j].ev_count += mp;
@@ -1576,7 +1590,24 @@ ixgbe_update_stats_counters(struct adapt
 		if (hw->mac.type == ixgbe_mac_82598EB)
 			stats->rnbc[j].ev_count
 			    += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
-		
+
+		stats->pxontxc[j].ev_count
+		    += IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
+		stats->pxofftxc[j].ev_count
+		    += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
+		if (hw->mac.type >= ixgbe_mac_82599EB) {
+			stats->pxonrxc[j].ev_count
+			    += IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+			stats->pxoffrxc[j].ev_count
+			    += IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+			stats->pxon2offc[j].ev_count
+			    += IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
+		} else {
+			stats->pxonrxc[j].ev_count
+			    += IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
+			stats->pxoffrxc[j].ev_count
+			    += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+		}
 	}
 	stats->mpctotal.ev_count += total_missed_rx;
 
@@ -1791,6 +1822,14 @@ ixgbe_add_hw_stats(struct adapter *adapt
 		if (sysctl_createv(log, 0, &rnode, &cnode,
 		    CTLFLAG_READONLY,
 		    CTLTYPE_INT,
+		    "rxd_nxck", SYSCTL_DESCR("Receive Descriptor next to check"),
+			ixgbe_sysctl_next_to_check_handler, 0, (void *)rxr, 0,
+		    CTL_CREATE, CTL_EOL) != 0)
+			break;
+
+		if (sysctl_createv(log, 0, &rnode, &cnode,
+		    CTLFLAG_READONLY,
+		    CTLTYPE_INT,
 		    "rxd_head", SYSCTL_DESCR("Receive Descriptor Head"),
 		    ixgbe_sysctl_rdh_handler, 0, (void *)rxr, 0,
 		    CTL_CREATE, CTL_EOL) != 0)
@@ -1827,8 +1866,10 @@ ixgbe_add_hw_stats(struct adapter *adapt
 			evcnt_attach_dynamic(&stats->pxoffrxc[i],
 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
 			    "pxoffrxc");
-			evcnt_attach_dynamic(&stats->pxon2offc[i],
-			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
+			if (hw->mac.type >= ixgbe_mac_82599EB)
+				evcnt_attach_dynamic(&stats->pxon2offc[i],
+				    EVCNT_TYPE_MISC, NULL,
+				    adapter->queues[i].evnamebuf,
 			    "pxon2offc");
 		}
 		if (i < __arraycount(stats->qprc)) {
@@ -1844,9 +1885,10 @@ ixgbe_add_hw_stats(struct adapter *adapt
 			evcnt_attach_dynamic(&stats->qbtc[i],
 			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
 			    "qbtc");
-			evcnt_attach_dynamic(&stats->qprdc[i],
-			    EVCNT_TYPE_MISC, NULL, adapter->queues[i].evnamebuf,
-			    "qprdc");
+			if (hw->mac.type >= ixgbe_mac_82599EB)
+				evcnt_attach_dynamic(&stats->qprdc[i],
+				    EVCNT_TYPE_MISC, NULL,
+				    adapter->queues[i].evnamebuf, "qprdc");
 		}
 
 		evcnt_attach_dynamic(&rxr->rx_packets, EVCNT_TYPE_MISC,
@@ -2035,14 +2077,16 @@ ixgbe_clear_evcnt(struct adapter *adapte
 			stats->pxonrxc[i].ev_count = 0;
 			stats->pxofftxc[i].ev_count = 0;
 			stats->pxoffrxc[i].ev_count = 0;
-			stats->pxon2offc[i].ev_count = 0;
+			if (hw->mac.type >= ixgbe_mac_82599EB)
+				stats->pxon2offc[i].ev_count = 0;
 		}
 		if (i < __arraycount(stats->qprc)) {
 			stats->qprc[i].ev_count = 0;
 			stats->qptc[i].ev_count = 0;
 			stats->qbrc[i].ev_count = 0;
 			stats->qbtc[i].ev_count = 0;
-			stats->qprdc[i].ev_count = 0;
+			if (hw->mac.type >= ixgbe_mac_82599EB)
+				stats->qprdc[i].ev_count = 0;
 		}
 
 		rxr->rx_packets.ev_count = 0;
@@ -2148,6 +2192,27 @@ ixgbe_sysctl_tdt_handler(SYSCTLFN_ARGS)
 } /* ixgbe_sysctl_tdt_handler */
 
 /************************************************************************
+ * ixgbe_sysctl_next_to_check_handler - Receive Descriptor next to check
+ * handler function
+ *
+ *   Retrieves the next_to_check value
+ ************************************************************************/
+static int 
+ixgbe_sysctl_next_to_check_handler(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node = *rnode;
+	struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+	uint32_t val;
+
+	if (!rxr)
+		return (0);
+
+	val = rxr->next_to_check;
+	node.sysctl_data = &val;
+	return sysctl_lookup(SYSCTLFN_CALL(&node));
+} /* ixgbe_sysctl_next_to_check_handler */
+
+/************************************************************************
  * ixgbe_sysctl_rdh_handler - Receive Descriptor Head handler function
  *
  *   Retrieves the RDH value from the hardware
@@ -2560,7 +2625,7 @@ ixgbe_msix_que(void *arg)
 	 *    the last interval.
 	 */
 	if (que->eitr_setting)
-		ixgbe_eitr_write(que, que->eitr_setting);
+		ixgbe_eitr_write(adapter, que->msix, que->eitr_setting);
 
 	que->eitr_setting = 0;
 
@@ -3043,16 +3108,15 @@ ixgbe_msix_link(void *arg)
 } /* ixgbe_msix_link */
 
 static void
-ixgbe_eitr_write(struct ix_queue *que, uint32_t itr)
+ixgbe_eitr_write(struct adapter *adapter, uint32_t index, uint32_t itr)
 {
-	struct adapter *adapter = que->adapter;
 	
         if (adapter->hw.mac.type == ixgbe_mac_82598EB)
                 itr |= itr << 16;
         else
                 itr |= IXGBE_EITR_CNT_WDIS;
 
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(que->msix), itr);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(index), itr);
 }
 
 
@@ -3100,7 +3164,7 @@ ixgbe_sysctl_interrupt_rate_handler(SYSC
 		ixgbe_max_interrupt_rate = rate;
 	} else
 		ixgbe_max_interrupt_rate = 0;
-	ixgbe_eitr_write(que, reg);
+	ixgbe_eitr_write(adapter, que->msix, reg);
 
 	return (0);
 } /* ixgbe_sysctl_interrupt_rate_handler */
@@ -3150,6 +3214,12 @@ ixgbe_add_device_sysctls(struct adapter 
 	}
 
 	if (sysctl_createv(log, 0, &rnode, &cnode,
+	    CTLFLAG_READWRITE, CTLTYPE_INT,
+	    "debug", SYSCTL_DESCR("Debug Info"),
+	    ixgbe_sysctl_debug, 0, (void *)adapter, 0, CTL_CREATE, CTL_EOL) != 0)
+		aprint_error_dev(dev, "could not create sysctl\n");
+
+	if (sysctl_createv(log, 0, &rnode, &cnode,
 	    CTLFLAG_READONLY, CTLTYPE_INT,
 	    "num_rx_desc", SYSCTL_DESCR("Number of rx descriptors"),
 	    NULL, 0, &adapter->num_rx_desc, 0, CTL_CREATE, CTL_EOL) != 0)
@@ -3474,14 +3544,16 @@ ixgbe_detach(device_t dev, int flags)
 			evcnt_detach(&stats->pxonrxc[i]);
 			evcnt_detach(&stats->pxofftxc[i]);
 			evcnt_detach(&stats->pxoffrxc[i]);
-			evcnt_detach(&stats->pxon2offc[i]);
+			if (hw->mac.type >= ixgbe_mac_82599EB)
+				evcnt_detach(&stats->pxon2offc[i]);
 		}
 		if (i < __arraycount(stats->qprc)) {
 			evcnt_detach(&stats->qprc[i]);
 			evcnt_detach(&stats->qptc[i]);
 			evcnt_detach(&stats->qbrc[i]);
 			evcnt_detach(&stats->qbtc[i]);
-			evcnt_detach(&stats->qprdc[i]);
+			if (hw->mac.type >= ixgbe_mac_82599EB)
+				evcnt_detach(&stats->qprdc[i]);
 		}
 
 		evcnt_detach(&rxr->rx_packets);
@@ -3729,6 +3801,7 @@ ixgbe_init_locked(struct adapter *adapte
 	struct ifnet   *ifp = adapter->ifp;
 	device_t 	dev = adapter->dev;
 	struct ixgbe_hw *hw = &adapter->hw;
+	struct ix_queue *que;
 	struct tx_ring  *txr;
 	struct rx_ring  *rxr;
 	u32		txdctl, mhadd;
@@ -3744,6 +3817,8 @@ ixgbe_init_locked(struct adapter *adapte
 	hw->adapter_stopped = FALSE;
 	ixgbe_stop_adapter(hw);
         callout_stop(&adapter->timer);
+	for (i = 0, que = adapter->queues; i < adapter->num_queues; i++, que++)
+		que->disabled_count = 0;
 
 	/* XXX I moved this here from the SIOCSIFMTU case in ixgbe_ioctl(). */
 	adapter->max_frame_size =
@@ -3920,7 +3995,7 @@ ixgbe_init_locked(struct adapter *adapte
 	}
 
 	/* Set moderation on the Link interrupt */
-	IXGBE_WRITE_REG(hw, IXGBE_EITR(adapter->vector), IXGBE_LINK_ITR);
+	ixgbe_eitr_write(adapter, adapter->vector, IXGBE_LINK_ITR);
 
 	/* Enable power to the phy. */
 	ixgbe_set_phy_power(hw, TRUE);
@@ -4055,7 +4130,7 @@ ixgbe_configure_ivars(struct adapter *ad
 		/* ... and the TX */
 		ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
 		/* Set an Initial EITR value */
-		ixgbe_eitr_write(que, newitr);
+		ixgbe_eitr_write(adapter, que->msix, newitr);
 		/*
 		 * To eliminate influence of the previous state.
 		 * At this point, Tx/Rx interrupt handler
@@ -4336,6 +4411,7 @@ ixgbe_local_timer1(void *arg)
 	/* Only truely watchdog if all queues show hung */
 	if (hung == adapter->num_queues)
 		goto watchdog;
+#if 0 /* XXX Avoid unexpectedly disabling interrupt forever (PR#53294) */
 	else if (queues != 0) { /* Force an IRQ on queues with work */
 		que = adapter->queues;
 		for (i = 0; i < adapter->num_queues; i++, que++) {
@@ -4346,6 +4422,7 @@ ixgbe_local_timer1(void *arg)
 			mutex_exit(&que->dc_mtx);
 		}
 	}
+#endif
 
 out:
 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
@@ -5628,6 +5705,115 @@ ixgbe_sysctl_eee_state(SYSCTLFN_ARGS)
 	return (error);
 } /* ixgbe_sysctl_eee_state */
 
+#define PRINTQS(adapter, regname)					\
+	do {								\
+		struct ixgbe_hw	*_hw = &(adapter)->hw;			\
+		int _i;							\
+									\
+		printf("%s: %s", device_xname((adapter)->dev), #regname); \
+		for (_i = 0; _i < (adapter)->num_queues; _i++) {	\
+			printf((_i == 0) ? "\t" : " ");			\
+			printf("%08x", IXGBE_READ_REG(_hw,		\
+				IXGBE_##regname(_i)));			\
+		}							\
+		printf("\n");						\
+	} while (0)
+
+/************************************************************************
+ * ixgbe_print_debug_info
+ *
+ *   Called only when em_display_debug_stats is enabled.
+ *   Provides a way to take a look at important statistics
+ *   maintained by the driver and hardware.
+ ************************************************************************/
+static void
+ixgbe_print_debug_info(struct adapter *adapter)
+{
+        device_t        dev = adapter->dev;
+        struct ixgbe_hw *hw = &adapter->hw;
+	int table_size;
+	int i;
+
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_X550:
+	case ixgbe_mac_X550EM_x:
+	case ixgbe_mac_X550EM_a:
+		table_size = 128;
+		break;
+	default:
+		table_size = 32;
+		break;
+	}
+	
+	device_printf(dev, "[E]RETA:\n");
+	for (i = 0; i < table_size; i++) {
+		if (i < 32)
+			printf("%02x: %08x\n", i, IXGBE_READ_REG(hw,
+				IXGBE_RETA(i)));
+		else
+			printf("%02x: %08x\n", i, IXGBE_READ_REG(hw,
+				IXGBE_ERETA(i - 32)));
+	}
+
+	device_printf(dev, "queue:");
+	for (i = 0; i < adapter->num_queues; i++) {
+		printf((i == 0) ? "\t" : " ");
+		printf("%8d", i);
+	}
+	printf("\n");
+	PRINTQS(adapter, RDBAL);
+	PRINTQS(adapter, RDBAH);
+	PRINTQS(adapter, RDLEN);
+	PRINTQS(adapter, SRRCTL);
+	PRINTQS(adapter, RDH);
+	PRINTQS(adapter, RDT);
+	PRINTQS(adapter, RXDCTL);
+
+	device_printf(dev, "RQSMR:");
+	for (i = 0; i < adapter->num_queues / 4; i++) {
+		printf((i == 0) ? "\t" : " ");
+		printf("%08x", IXGBE_READ_REG(hw, IXGBE_RQSMR(i)));
+	}
+	printf("\n");
+
+	device_printf(dev, "disabled_count:");
+	for (i = 0; i < adapter->num_queues; i++) {
+		printf((i == 0) ? "\t" : " ");
+		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",
+			      IXGBE_READ_REG(hw, IXGBE_EIMS_EX(0)));
+		device_printf(dev, "EIMS_EX(1):\t%08x\n",
+			      IXGBE_READ_REG(hw, IXGBE_EIMS_EX(1)));
+	}
+} /* ixgbe_print_debug_info */
+
+/************************************************************************
+ * ixgbe_sysctl_debug
+ ************************************************************************/
+static int
+ixgbe_sysctl_debug(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node = *rnode;
+	struct adapter *adapter = (struct adapter *)node.sysctl_data;
+	int            error, result = 0;
+
+	node.sysctl_data = &result;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+
+	if (error || newp == NULL)
+		return error;
+
+	if (result == 1)
+		ixgbe_print_debug_info(adapter);
+
+	return 0;
+} /* ixgbe_sysctl_debug */
+
 /************************************************************************
  * ixgbe_init_device_features
  ************************************************************************/
@@ -5750,10 +5936,10 @@ ixgbe_probe(device_t dev, cfdata_t cf, v
 	return (ixgbe_lookup(pa) != NULL) ? 1 : 0;
 }
 
-static ixgbe_vendor_info_t *
+static const ixgbe_vendor_info_t *
 ixgbe_lookup(const struct pci_attach_args *pa)
 {
-	ixgbe_vendor_info_t *ent;
+	const ixgbe_vendor_info_t *ent;
 	pcireg_t subid;
 
 	INIT_DEBUGOUT("ixgbe_lookup: begin");
@@ -6283,7 +6469,6 @@ ixgbe_allocate_msix(struct adapter *adap
 	    adapter->osdep.intrs[vector], IPL_NET, ixgbe_msix_link, adapter,
 	    intr_xname);
 	if (adapter->osdep.ihs[vector] == NULL) {
-		adapter->res = NULL;
 		aprint_error_dev(dev, "Failed to register LINK handler\n");
 		error = ENXIO;
 		goto err_out;
@@ -6460,7 +6645,7 @@ ixgbe_handle_link(void *context)
 /************************************************************************
  * ixgbe_rearm_queues
  ************************************************************************/
-static void
+static __inline void
 ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
 {
 	u32 mask;

Index: src/sys/dev/pci/ixgbe/ixgbe.h
diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.11 src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.12
--- src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.11	Tue Apr 17 08:20:06 2018
+++ src/sys/dev/pci/ixgbe/ixgbe.h	Sat Jun  9 14:59:43 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.h,v 1.24.6.11 2018/04/17 08:20:06 martin Exp $ */
+/* $NetBSD: ixgbe.h,v 1.24.6.12 2018/06/09 14:59:43 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -173,8 +173,6 @@
 
 /* Flow control constants */
 #define IXGBE_FC_PAUSE        0xFFFF
-#define IXGBE_FC_HI           0x20000
-#define IXGBE_FC_LO           0x10000
 
 /*
  * Used for optimizing small rx mbufs.  Effort is made to keep the copy
@@ -322,11 +320,9 @@ struct ixgbe_mc_addr {
 struct ix_queue {
 	struct adapter   *adapter;
 	u32              msix;           /* This queue's MSI-X vector */
-	u32              eims;           /* This queue's EIMS bit */
 	u32              eitr_setting;
 	u32              me;
 	struct resource  *res;
-	void             *tag;
 	int              busy;
 	struct tx_ring   *txr;
 	struct rx_ring   *rxr;
@@ -365,12 +361,14 @@ struct tx_ring {
 	u16			next_avail_desc;
 	u16			next_to_clean;
 	u16			num_desc;
-	u32			txd_cmd;
 	ixgbe_dma_tag_t		*txtag;
-	char			mtx_name[16];
+#if 0
+	char			mtx_name[16]; /* NetBSD has no mutex name */
+#endif
 	pcq_t			*txr_interq;
 	struct work		wq_cookie;
 	void			*txr_si;
+	bool			txr_no_space; /* Like IFF_OACTIVE */
 
 	/* Flow Director */
 	u16			atr_sample;
@@ -415,7 +413,9 @@ struct rx_ring {
         u16 			next_to_check;
 	u16			num_desc;
 	u16			mbuf_sz;
-	char			mtx_name[16];
+#if 0
+	char			mtx_name[16]; /* NetBSD has no mutex name */
+#endif
 	struct ixgbe_rx_buf	*rx_buffers;
 	ixgbe_dma_tag_t		*ptag;
 
@@ -461,17 +461,10 @@ struct adapter {
 	struct resource		*pci_mem;
 	struct resource		*msix_mem;
 
-	/*
-	 * Interrupt resources: this set is
-	 * either used for legacy, or for Link
-	 * when doing MSI-X
-	 */
-	void			*tag;
-	struct resource 	*res;
+	/* NetBSD: Interrupt resources are in osdep */
 
 	struct ifmedia		media;
 	callout_t		timer;
-	int			link_rid;
 	int			if_flags;
 
 	kmutex_t		core_mtx;
@@ -759,6 +752,9 @@ bool ixgbe_rxeof(struct ix_queue *);
 
 const struct sysctlnode *ixgbe_sysctl_instance(struct adapter *);
 
+/* For NetBSD */
+void ixgbe_jcl_reinit(struct adapter *, bus_dma_tag_t, int, size_t);
+
 #include "ixgbe_bypass.h"
 #include "ixgbe_fdir.h"
 #include "ixgbe_rss.h"

Index: src/sys/dev/pci/ixgbe/ixgbe_netbsd.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.6 src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.6.2.1
--- src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.6	Thu Jun  1 02:45:11 2017
+++ src/sys/dev/pci/ixgbe/ixgbe_netbsd.c	Sat Jun  9 14:59:43 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_netbsd.c,v 1.6 2017/06/01 02:45:11 chs Exp $ */
+/* $NetBSD: ixgbe_netbsd.c,v 1.6.2.1 2018/06/09 14:59:43 martin Exp $ */
 /*
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -40,7 +40,7 @@
 #include <sys/workqueue.h>
 #include <dev/pci/pcivar.h>
 
-#include "ixgbe_netbsd.h"
+#include "ixgbe.h"
 
 void
 ixgbe_dma_tag_destroy(ixgbe_dma_tag_t *dt)
@@ -162,11 +162,12 @@ post_zalloc_err:
 }
 
 void
-ixgbe_jcl_reinit(ixgbe_extmem_head_t *eh, bus_dma_tag_t dmat, int nbuf,
+ixgbe_jcl_reinit(struct adapter *adapter, bus_dma_tag_t dmat, int nbuf,
     size_t size)
 {
-	int i;
+	ixgbe_extmem_head_t *eh = &adapter->jcl_head;
 	ixgbe_extmem_t *em;
+	int i;
 
 	if (!eh->eh_initialized) {
 		TAILQ_INIT(&eh->eh_freelist);
@@ -174,6 +175,18 @@ ixgbe_jcl_reinit(ixgbe_extmem_head_t *eh
 		eh->eh_initialized = true;
 	}
 
+	/*
+	 *  Check previous parameters. If it's not required to reinit, just
+	 * return.
+	 *
+	 *  Note that the num_rx_desc is currently fixed value. It's never
+	 * changed after device is attached.
+	 */
+	if ((adapter->osdep.last_rx_mbuf_sz == adapter->rx_mbuf_sz)
+	    && (adapter->osdep.last_num_rx_desc == adapter->num_rx_desc))
+		return;
+
+	/* Free all dmamem */
 	while ((em = ixgbe_getext(eh, 0)) != NULL) {
 		KASSERT(em->em_vaddr != NULL);
 		bus_dmamem_unmap(dmat, em->em_vaddr, em->em_size);
@@ -190,6 +203,10 @@ ixgbe_jcl_reinit(ixgbe_extmem_head_t *eh
 		}
 		ixgbe_putext(em);
 	}
+
+	/* Keep current parameters */
+	adapter->osdep.last_rx_mbuf_sz = adapter->rx_mbuf_sz;
+	adapter->osdep.last_num_rx_desc = adapter->num_rx_desc;
 }
 
 static void

Index: src/sys/dev/pci/ixgbe/ixgbe_netbsd.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.7 src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.7.6.1
--- src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.7	Wed Feb  8 04:32:43 2017
+++ src/sys/dev/pci/ixgbe/ixgbe_netbsd.h	Sat Jun  9 14:59:43 2018
@@ -1,4 +1,4 @@
-/*$NetBSD: ixgbe_netbsd.h,v 1.7 2017/02/08 04:32:43 msaitoh Exp $*/
+/*$NetBSD: ixgbe_netbsd.h,v 1.7.6.1 2018/06/09 14:59:43 martin Exp $*/
 /*
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -93,7 +93,6 @@ void ixgbe_dmamap_destroy(ixgbe_dma_tag_
 void ixgbe_dmamap_sync(ixgbe_dma_tag_t *, bus_dmamap_t, int);
 void ixgbe_dmamap_unload(ixgbe_dma_tag_t *, bus_dmamap_t);
 
-void ixgbe_jcl_reinit(ixgbe_extmem_head_t *, bus_dma_tag_t, int, size_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);
 

Index: src/sys/dev/pci/ixgbe/ixgbe_osdep.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.17.6.3 src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.17.6.4
--- src/sys/dev/pci/ixgbe/ixgbe_osdep.h:1.17.6.3	Sat Apr 14 10:25:11 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_osdep.h	Sat Jun  9 14:59:43 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_osdep.h,v 1.17.6.3 2018/04/14 10:25:11 martin Exp $ */
+/* $NetBSD: ixgbe_osdep.h,v 1.17.6.4 2018/06/09 14:59:43 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -207,6 +207,8 @@ struct ixgbe_osdep
 	bus_space_handle_t mem_bus_space_handle;
 	bus_size_t         mem_size;
 	bus_dma_tag_t      dmat;
+	u16                last_rx_mbuf_sz;
+	u32                last_num_rx_desc;
 	pci_intr_handle_t  *intrs;
 	int		   nintrs;
 	void               *ihs[IXG_MAX_NINTR];

Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.56.2.16 src/sys/dev/pci/ixgbe/ixv.c:1.56.2.17
--- src/sys/dev/pci/ixgbe/ixv.c:1.56.2.16	Thu Jun  7 17:42:24 2018
+++ src/sys/dev/pci/ixgbe/ixv.c	Sat Jun  9 14:59:43 2018
@@ -1,4 +1,4 @@
-/*$NetBSD: ixv.c,v 1.56.2.16 2018/06/07 17:42:24 martin Exp $*/
+/*$NetBSD: ixv.c,v 1.56.2.17 2018/06/09 14:59:43 martin Exp $*/
 
 /******************************************************************************
 
@@ -46,7 +46,7 @@
 /************************************************************************
  * Driver version
  ************************************************************************/
-char ixv_driver_version[] = "2.0.1-k";
+static const char ixv_driver_version[] = "2.0.1-k";
 
 /************************************************************************
  * PCI Device ID Table
@@ -57,7 +57,7 @@ char ixv_driver_version[] = "2.0.1-k";
  *
  *   { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index }
  ************************************************************************/
-static ixgbe_vendor_info_t ixv_vendor_info_array[] =
+static const ixgbe_vendor_info_t ixv_vendor_info_array[] =
 {
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_VF, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540_VF, 0, 0, 0},
@@ -117,7 +117,7 @@ static int	ixv_sysctl_debug(SYSCTLFN_PRO
 static void	ixv_set_ivar(struct adapter *, u8, u8, s8);
 static void	ixv_configure_ivars(struct adapter *);
 static u8 *	ixv_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
-static void	ixv_eitr_write(struct ix_queue *, uint32_t);
+static void	ixv_eitr_write(struct adapter *, uint32_t, uint32_t);
 
 static void	ixv_setup_vlan_support(struct adapter *);
 #if 0
@@ -136,6 +136,7 @@ static void	ixv_add_stats_sysctls(struct
 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);
@@ -153,7 +154,7 @@ static void     ixv_handle_link(void *);
 static void	ixv_handle_que_work(struct work *, void *);
 
 const struct sysctlnode *ixv_sysctl_instance(struct adapter *);
-static ixgbe_vendor_info_t *ixv_lookup(const struct pci_attach_args *);
+static const ixgbe_vendor_info_t *ixv_lookup(const struct pci_attach_args *);
 
 /************************************************************************
  * FreeBSD Device Interface Entry Points
@@ -265,10 +266,10 @@ ixv_probe(device_t dev, cfdata_t cf, voi
 #endif
 } /* ixv_probe */
 
-static ixgbe_vendor_info_t *
+static const ixgbe_vendor_info_t *
 ixv_lookup(const struct pci_attach_args *pa)
 {
-	ixgbe_vendor_info_t *ent;
+	const ixgbe_vendor_info_t *ent;
 	pcireg_t subid;
 
 	INIT_DEBUGOUT("ixv_lookup: begin");
@@ -308,7 +309,7 @@ ixv_attach(device_t parent, device_t dev
 	struct ixgbe_hw *hw;
 	int             error = 0;
 	pcireg_t	id, subid;
-	ixgbe_vendor_info_t *ent;
+	const ixgbe_vendor_info_t *ent;
 	const struct pci_attach_args *pa = aux;
 	const char *apivstr;
 	const char *str;
@@ -725,7 +726,7 @@ ixv_init_locked(struct adapter *adapter)
 	struct ifnet	*ifp = adapter->ifp;
 	device_t 	dev = adapter->dev;
 	struct ixgbe_hw *hw = &adapter->hw;
-	struct ix_queue	*que = adapter->queues;
+	struct ix_queue	*que;
 	int             error = 0;
 	uint32_t mask;
 	int i;
@@ -735,6 +736,8 @@ ixv_init_locked(struct adapter *adapter)
 	hw->adapter_stopped = FALSE;
 	hw->mac.ops.stop_adapter(hw);
 	callout_stop(&adapter->timer);
+	for (i = 0, que = adapter->queues; i < adapter->num_queues; i++, que++)
+		que->disabled_count = 0;
 
 	/* reprogram the RAR[0] in case user changed it. */
 	hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
@@ -804,12 +807,12 @@ ixv_init_locked(struct adapter *adapter)
 
 	/* Set up auto-mask */
 	mask = (1 << adapter->vector);
-	for (i = 0; i < adapter->num_queues; i++, que++)
+	for (i = 0, que = adapter->queues; i < adapter->num_queues; i++, que++)
 		mask |= (1 << que->msix);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, mask);
 
 	/* Set moderation on the Link interrupt */
-	IXGBE_WRITE_REG(hw, IXGBE_VTEITR(adapter->vector), IXGBE_LINK_ITR);
+	ixv_eitr_write(adapter, adapter->vector, IXGBE_LINK_ITR);
 
 	/* Stats init */
 	ixv_init_stats(adapter);
@@ -923,7 +926,7 @@ ixv_msix_que(void *arg)
 	 *    the last interval.
 	 */
 	if (que->eitr_setting)
-		ixv_eitr_write(que, que->eitr_setting);
+		ixv_eitr_write(adapter, que->msix, que->eitr_setting);
 
 	que->eitr_setting = 0;
 
@@ -998,9 +1001,8 @@ ixv_msix_mbx(void *arg)
 } /* ixv_msix_mbx */
 
 static void
-ixv_eitr_write(struct ix_queue *que, uint32_t itr)
+ixv_eitr_write(struct adapter *adapter, uint32_t index, uint32_t itr)
 {
-	struct adapter *adapter = que->adapter;
 
 	/*
 	 * Newer devices than 82598 have VF function, so this function is
@@ -1008,7 +1010,7 @@ ixv_eitr_write(struct ix_queue *que, uin
 	 */
 	itr |= IXGBE_EITR_CNT_WDIS;
 
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEITR(que->msix), itr);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_VTEITR(index), itr);
 }
 
 
@@ -1271,9 +1273,11 @@ ixv_local_timer_locked(void *arg)
 	/* Only truly watchdog if all queues show hung */
 	if (hung == adapter->num_queues)
 		goto watchdog;
+#if 0
 	else if (queues != 0) { /* Force an IRQ on queues with work */
 		ixv_rearm_queues(adapter, queues);
 	}
+#endif
 
 	callout_reset(&adapter->timer, hz, ixv_local_timer, adapter);
 
@@ -1597,6 +1601,8 @@ ixv_initialize_transmit_units(struct ada
 		/* Set Tx Tail register */
 		txr->tail = IXGBE_VFTDT(j);
 
+		txr->txr_no_space = false;
+
 		/* Set Ring parameters */
 		IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(j),
 		    (tdba & 0x00000000ffffffffULL));
@@ -1887,6 +1893,27 @@ ixv_sysctl_tdt_handler(SYSCTLFN_ARGS)
 } /* ixv_sysctl_tdt_handler */
 
 /************************************************************************
+ * ixv_sysctl_next_to_check_handler - Receive Descriptor next to check
+ * handler function
+ *
+ *   Retrieves the next_to_check value
+ ************************************************************************/
+static int 
+ixv_sysctl_next_to_check_handler(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node = *rnode;
+	struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data;
+	uint32_t val;
+
+	if (!rxr)
+		return (0);
+
+	val = rxr->next_to_check;
+	node.sysctl_data = &val;
+	return sysctl_lookup(SYSCTLFN_CALL(&node));
+} /* ixv_sysctl_next_to_check_handler */
+
+/************************************************************************
  * ixv_sysctl_rdh_handler - Receive Descriptor Head handler function
  *
  *   Retrieves the RDH value from the hardware
@@ -2132,7 +2159,7 @@ ixv_configure_ivars(struct adapter *adap
 		/* ... and the TX */
 		ixv_set_ivar(adapter, i, que->msix, 1);
 		/* Set an initial value in EITR */
-		ixv_eitr_write(que, IXGBE_EITR_DEFAULT);
+		ixv_eitr_write(adapter, que->msix, IXGBE_EITR_DEFAULT);
 	}
 
 	/* For the mailbox interrupt */
@@ -2285,7 +2312,7 @@ ixv_sysctl_interrupt_rate_handler(SYSCTL
 		ixv_max_interrupt_rate = rate;
 	} else
 		ixv_max_interrupt_rate = 0;
-	ixv_eitr_write(que, reg);
+	ixv_eitr_write(adapter, que->msix, reg);
 
 	return (0);
 } /* ixv_sysctl_interrupt_rate_handler */
@@ -2451,6 +2478,14 @@ ixv_add_stats_sysctls(struct adapter *ad
 		if (sysctl_createv(log, 0, &rnode, &cnode,
 		    CTLFLAG_READONLY,
 		    CTLTYPE_INT,
+		    "rxd_nxck", SYSCTL_DESCR("Receive Descriptor next to check"),
+			ixv_sysctl_next_to_check_handler, 0, (void *)rxr, 0,
+		    CTL_CREATE, CTL_EOL) != 0)
+			break;
+
+		if (sysctl_createv(log, 0, &rnode, &cnode,
+		    CTLFLAG_READONLY,
+		    CTLTYPE_INT,
 		    "rxd_head", SYSCTL_DESCR("Receive Descriptor Head"),
 		    ixv_sysctl_rdh_handler, 0, (void *)rxr, 0,
 		    CTL_CREATE, CTL_EOL) != 0)
@@ -2979,7 +3014,6 @@ ixv_allocate_msix(struct adapter *adapte
 	    adapter->osdep.intrs[vector], IPL_NET, ixv_msix_mbx, adapter,
 	    intr_xname);
 	if (adapter->osdep.ihs[vector] == NULL) {
-		adapter->res = NULL;
 		aprint_error_dev(dev, "Failed to register LINK handler\n");
 		kcpuset_destroy(affinity);
 		return (ENXIO);

Reply via email to