Module Name:    src
Committed By:   martin
Date:           Wed Apr  4 16:18:49 UTC 2018

Modified Files:
        src/sys/dev/pci/ixgbe [netbsd-8]: ix_txrx.c ixgbe.c ixgbe.h
            ixgbe_82599.c ixgbe_api.h ixgbe_common.c ixgbe_common.h
            ixgbe_x550.c ixgbe_x550.h ixv.c

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #690):
        sys/dev/pci/ixgbe/ixgbe_82599.c: revision 1.17
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.138
        sys/dev/pci/ixgbe/ixv.c: revision 1.90
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.139
        sys/dev/pci/ixgbe/ixgbe_common.c: revision 1.19
        sys/dev/pci/ixgbe/ixgbe_common.h: revision 1.11
        sys/dev/pci/ixgbe/ixgbe.h: revision 1.38
        sys/dev/pci/ixgbe/ixgbe_api.h: revision 1.12
        sys/dev/pci/ixgbe/ixgbe.h: revision 1.39
        sys/dev/pci/ixgbe/ixgbe_x550.c: revision 1.10
        sys/dev/pci/ixgbe/ixgbe_x550.c: revision 1.11
        sys/dev/pci/ixgbe/ix_txrx.c: revision 1.37
        sys/dev/pci/ixgbe/ix_txrx.c: revision 1.38
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.140
        sys/dev/pci/ixgbe/ixgbe_common.c: revision 1.20
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.141
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.142
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.143
        sys/dev/pci/ixgbe/ixgbe.h: revision 1.40
        sys/dev/pci/ixgbe/ixgbe_x550.h: revision 1.4

Fix the problem between eitr and link_speed.

In ixgbe_msix_que(), que->eitr_setting is limited to IXGBE_MIN_RSC_EITR_10G1G
when link_speed is 1Gbps or 10Gbps. However, que->eitr_setting is set to EITR
register in the *next* Tx/Rx interrupt. If link_speed changes from 100Mbps to
1Gbps ro 10Gbps, que->eitr_setting which is not limited can be set to EITR
register, that is, the problem fixed by ixgbe.c:r1.124 can occur in this case.

To fix this case, que->eitr_setting should be clear when link_speed is changed
or link state is changed.

Furthermore, expand the variants used for AIM (txr->bytes, txr->packets,
rxr->bytes and rxr->packets) from u32 to u64 to avoid wraparound which causes
que->eitr_setting calculation mistake.
XXX pullup-8

Don't write EIMC directly. It is required to manage with struct ix_queue status.
XXX pullup-8

-  Add missing IFM_NONE support. If a interface support linkdown,
  "ifconfig ixgN media none" drpos link.  Not all interface can do link down.
 Tested:
        82598 AT2 (T)
        92599 SF+(SFI) (X520-DA2)
        X540
        X550-T1
        X550EM_x (X10SDV-8C-TLN4F)
        X550EM_a (A2SDi-H-TP4F port 0, 1 (T))
 Doesn't work:
        X550EM_a (A2SDi-H-TP4F port 2, 3 (SFP+ (KR)))
        X550EM_a (MA10-ST0 port 2, 3 (SFP+ (SFI)))
        (Denverton SFP+ can't force link down because SFP+'s TX_DISABLE pin is
        pull down. Is there a way to shutdown SFP+ cage's power?)
 Not tested:
        82598 fiber.
- Change some functions static.

Avoid issues caused by sending old packets at next link-up time.

This modification consists by the following two parts.
    - drain packets in if_snd queue or corresponding txr->txr_interq
      when link_active == false in ifp->if_start(), ifp->if_transmit(),
      and deferred Tx processing
    - drain packets in if_snd queue and all of txr->txr_interq's
      at link-down time
ok by msaitoh@n.o.

 Fix long standing bug that 82598 SFP+ panics in ixgbe_handle_mod() because
hw->mac.ops.setup_sfp is NULL. This change is a part of FreeBSD r327031.

Fix a bug that "ifconfig ixgN down up" forgot IFM_NONE setting.
 - Don't assume autoneg == 0 is the first call of ixgbe_config_link().
   Check ifm_media, too.
 - Don't override autoneg_advertised in ixgbe_get_phy_id_fw() to not to
   be inconsistent with if_media value.


To generate a diff of this commit:
cvs rdiff -u -r1.24.2.8 -r1.24.2.9 src/sys/dev/pci/ixgbe/ix_txrx.c
cvs rdiff -u -r1.88.2.15 -r1.88.2.16 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.24.6.8 -r1.24.6.9 src/sys/dev/pci/ixgbe/ixgbe.h
cvs rdiff -u -r1.14.8.1 -r1.14.8.2 src/sys/dev/pci/ixgbe/ixgbe_82599.c
cvs rdiff -u -r1.9.8.1 -r1.9.8.2 src/sys/dev/pci/ixgbe/ixgbe_api.h
cvs rdiff -u -r1.13.2.2 -r1.13.2.3 src/sys/dev/pci/ixgbe/ixgbe_common.c
cvs rdiff -u -r1.7.8.2 -r1.7.8.3 src/sys/dev/pci/ixgbe/ixgbe_common.h
cvs rdiff -u -r1.5.6.2 -r1.5.6.3 src/sys/dev/pci/ixgbe/ixgbe_x550.c
cvs rdiff -u -r1.2.12.1 -r1.2.12.2 src/sys/dev/pci/ixgbe/ixgbe_x550.h
cvs rdiff -u -r1.56.2.12 -r1.56.2.13 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.8 src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.9
--- src/sys/dev/pci/ixgbe/ix_txrx.c:1.24.2.8	Fri Mar 30 12:07:34 2018
+++ src/sys/dev/pci/ixgbe/ix_txrx.c	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ix_txrx.c,v 1.24.2.8 2018/03/30 12:07:34 martin Exp $ */
+/* $NetBSD: ix_txrx.c,v 1.24.2.9 2018/04/04 16:18:49 martin Exp $ */
 
 /******************************************************************************
 
@@ -103,6 +103,7 @@ static void          ixgbe_free_receive_
 static void          ixgbe_rx_checksum(u32, struct mbuf *, u32,
                                        struct ixgbe_hw_stats *);
 static void          ixgbe_refresh_mbufs(struct rx_ring *, int);
+static void          ixgbe_drain(struct ifnet *, struct tx_ring *);
 static int           ixgbe_xmit(struct tx_ring *, struct mbuf *);
 static int           ixgbe_tx_ctx_setup(struct tx_ring *,
                                         struct mbuf *, u32 *, u32 *);
@@ -135,9 +136,15 @@ ixgbe_legacy_start_locked(struct ifnet *
 
 	IXGBE_TX_LOCK_ASSERT(txr);
 
-	if ((ifp->if_flags & IFF_RUNNING) == 0)
+	if (!adapter->link_active) {
+		/*
+		 * discard all packets buffered in IFQ to avoid
+		 * sending old packets at next link up timing.
+		 */
+		ixgbe_drain(ifp, txr);
 		return (ENETDOWN);
-	if (!adapter->link_active)
+	}
+	if ((ifp->if_flags & IFF_RUNNING) == 0)
 		return (ENETDOWN);
 
 	while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
@@ -271,9 +278,15 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
 	struct mbuf    *next;
 	int            enqueued = 0, err = 0;
 
-	if ((ifp->if_flags & IFF_RUNNING) == 0)
+	if (!txr->adapter->link_active) {
+		/*
+		 * discard all packets buffered in txr_interq to avoid
+		 * sending old packets at next link up timing.
+		 */
+		ixgbe_drain(ifp, txr);
 		return (ENETDOWN);
-	if (txr->adapter->link_active == 0)
+	}
+	if ((ifp->if_flags & IFF_RUNNING) == 0)
 		return (ENETDOWN);
 
 	/* Process the queue */
@@ -342,6 +355,23 @@ ixgbe_deferred_mq_start_work(struct work
 	ixgbe_deferred_mq_start(txr);
 } /* ixgbe_deferred_mq_start */
 
+/************************************************************************
+ * ixgbe_drain_all
+ ************************************************************************/
+void
+ixgbe_drain_all(struct adapter *adapter)
+{
+	struct ifnet *ifp = adapter->ifp;
+	struct ix_queue *que = adapter->queues;
+
+	for (int i = 0; i < adapter->num_queues; i++, que++) {
+		struct tx_ring  *txr = que->txr;
+
+		IXGBE_TX_LOCK(txr);
+		ixgbe_drain(ifp, txr);
+		IXGBE_TX_UNLOCK(txr);
+	}
+}
 
 /************************************************************************
  * ixgbe_xmit
@@ -515,6 +545,29 @@ retry:
 	return (0);
 } /* ixgbe_xmit */
 
+/************************************************************************
+ * ixgbe_drain
+ ************************************************************************/
+static void
+ixgbe_drain(struct ifnet *ifp, struct tx_ring *txr)
+{
+	struct mbuf *m;
+
+	IXGBE_TX_LOCK_ASSERT(txr);
+
+	if (txr->me == 0) {
+		while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
+			IFQ_DEQUEUE(&ifp->if_snd, m);
+			m_freem(m);
+			IF_DROP(&ifp->if_snd);
+		}
+	}
+
+	while ((m = pcq_get(txr->txr_interq)) != NULL) {
+		m_freem(m);
+		txr->pcq_drops.ev_count++;
+	}
+}
 
 /************************************************************************
  * ixgbe_allocate_transmit_buffers
@@ -2298,8 +2351,8 @@ ixgbe_allocate_queues(struct adapter *ad
 		que->txr = &adapter->tx_rings[i];
 		que->rxr = &adapter->rx_rings[i];
 
-		mutex_init(&que->im_mtx, MUTEX_DEFAULT, IPL_NET);
-		que->im_nest = 0;
+		mutex_init(&que->dc_mtx, MUTEX_DEFAULT, IPL_NET);
+		que->disabled_count = 0;
 	}
 
 	return (0);

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.15 src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.16
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.15	Fri Mar 30 12:07:34 2018
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.88.2.15 2018/03/30 12:07:34 martin Exp $ */
+/* $NetBSD: ixgbe.c,v 1.88.2.16 2018/04/04 16:18:49 martin Exp $ */
 
 /******************************************************************************
 
@@ -1378,6 +1378,8 @@ ixgbe_add_media_types(struct adapter *ad
 #define	ADD(mm, dd)							\
 	ifmedia_add(&adapter->media, IFM_ETHER | (mm), (dd), NULL);
 
+	ADD(IFM_NONE, 0);
+
 	/* Media types with matching NetBSD media defines */
 	if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) {
 		ADD(IFM_10G_T | IFM_FDX, 0);
@@ -1509,13 +1511,21 @@ ixgbe_config_link(struct adapter *adapte
 			kpreempt_enable();
 		}
 	} else {
+		struct ifmedia  *ifm = &adapter->media;
+
 		if (hw->mac.ops.check_link)
 			err = ixgbe_check_link(hw, &adapter->link_speed,
 			    &adapter->link_up, FALSE);
 		if (err)
 			goto out;
+
+		/*
+		 * Check if it's the first call. If it's the first call,
+		 * get value for auto negotiation.
+		 */
 		autoneg = hw->phy.autoneg_advertised;
-		if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
+		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,
 			    &negotiate);
 		if (err)
@@ -2410,8 +2420,8 @@ ixgbe_enable_queue(struct adapter *adapt
 	u64             queue = (u64)(1ULL << vector);
 	u32             mask;
 
-	mutex_enter(&que->im_mtx);
-	if (que->im_nest > 0 && --que->im_nest > 0)
+	mutex_enter(&que->dc_mtx);
+	if (que->disabled_count > 0 && --que->disabled_count > 0)
 		goto out;
 
 	if (hw->mac.type == ixgbe_mac_82598EB) {
@@ -2426,23 +2436,28 @@ ixgbe_enable_queue(struct adapter *adapt
 			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
 	}
 out:
-	mutex_exit(&que->im_mtx);
+	mutex_exit(&que->dc_mtx);
 } /* ixgbe_enable_queue */
 
 /************************************************************************
- * ixgbe_disable_queue
+ * ixgbe_disable_queue_internal
  ************************************************************************/
 static inline void
-ixgbe_disable_queue(struct adapter *adapter, u32 vector)
+ixgbe_disable_queue_internal(struct adapter *adapter, u32 vector, bool nestok)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct ix_queue *que = &adapter->queues[vector];
 	u64             queue = (u64)(1ULL << vector);
 	u32             mask;
 
-	mutex_enter(&que->im_mtx);
-	if (que->im_nest++ > 0)
-		goto  out;
+	mutex_enter(&que->dc_mtx);
+
+	if (que->disabled_count > 0) {
+		if (nestok)
+			que->disabled_count++;
+		goto out;
+	}
+	que->disabled_count++;
 
 	if (hw->mac.type == ixgbe_mac_82598EB) {
 		mask = (IXGBE_EIMS_RTX_QUEUE & queue);
@@ -2456,7 +2471,17 @@ ixgbe_disable_queue(struct adapter *adap
 			IXGBE_WRITE_REG(hw, IXGBE_EIMC_EX(1), mask);
 	}
 out:
-	mutex_exit(&que->im_mtx);
+	mutex_exit(&que->dc_mtx);
+} /* ixgbe_disable_queue_internal */
+
+/************************************************************************
+ * ixgbe_disable_queue
+ ************************************************************************/
+static inline void
+ixgbe_disable_queue(struct adapter *adapter, u32 vector)
+{
+
+	ixgbe_disable_queue_internal(adapter, vector, true);
 } /* ixgbe_disable_queue */
 
 /************************************************************************
@@ -2814,6 +2839,8 @@ ixgbe_media_change(struct ifnet *ifp)
 	case IFM_10_T:
 		speed |= IXGBE_LINK_SPEED_10_FULL;
 		break;
+	case IFM_NONE:
+		break;
 	default:
 		goto invalid;
 	}
@@ -3511,7 +3538,7 @@ ixgbe_detach(device_t dev, int flags)
 	ixgbe_free_receive_structures(adapter);
 	for (int i = 0; i < adapter->num_queues; i++) {
 		struct ix_queue * que = &adapter->queues[i];
-		mutex_destroy(&que->im_mtx);
+		mutex_destroy(&que->dc_mtx);
 	}
 	free(adapter->queues, M_DEVBUF);
 	free(adapter->mta, M_DEVBUF);
@@ -4012,6 +4039,13 @@ ixgbe_configure_ivars(struct adapter *ad
 		ixgbe_set_ivar(adapter, txr->me, que->msix, 1);
 		/* Set an Initial EITR value */
 		ixgbe_eitr_write(que, newitr);
+		/*
+		 * To eliminate influence of the previous state.
+		 * At this point, Tx/Rx interrupt handler
+		 * (ixgbe_msix_que()) cannot be called, so  both
+		 * IXGBE_TX_LOCK and IXGBE_RX_LOCK are not required.
+		 */
+		que->eitr_setting = 0;
 	}
 
 	/* For the Link interrupt */
@@ -4288,11 +4322,11 @@ ixgbe_local_timer1(void *arg)
 	else if (queues != 0) { /* Force an IRQ on queues with work */
 		que = adapter->queues;
 		for (i = 0; i < adapter->num_queues; i++, que++) {
-			mutex_enter(&que->im_mtx);
-			if (que->im_nest == 0)
+			mutex_enter(&que->dc_mtx);
+			if (que->disabled_count == 0)
 				ixgbe_rearm_queues(adapter,
 				    queues & ((u64)1 << i));
-			mutex_exit(&que->im_mtx);
+			mutex_exit(&que->dc_mtx);
 		}
 	}
 
@@ -4379,7 +4413,11 @@ ixgbe_handle_mod(void *context)
 		return;
 	}
 
-	err = hw->mac.ops.setup_sfp(hw);
+	if (hw->mac.type == ixgbe_mac_82598EB)
+		err = hw->phy.ops.reset(hw);
+	else
+		err = hw->mac.ops.setup_sfp(hw);
+
 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
 		device_printf(dev,
 		    "Setup failure - unsupported SFP+ module type.\n");
@@ -4509,6 +4547,14 @@ ixgbe_update_link_status(struct adapter 
 
 	if (adapter->link_up) {
 		if (adapter->link_active == FALSE) {
+			/*
+			 * To eliminate influence of the previous state
+			 * in the same way as ixgbe_init_locked().
+			 */
+			struct ix_queue	*que = adapter->queues;
+			for (int i = 0; i < adapter->num_queues; i++, que++)
+				que->eitr_setting = 0;
+
 			if (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL){
 				/*
 				 *  Discard count for both MAC Local Fault and
@@ -4566,6 +4612,7 @@ ixgbe_update_link_status(struct adapter 
 			adapter->link_active = FALSE;
 			if (adapter->feat_en & IXGBE_FEATURE_SRIOV)
 				ixgbe_ping_all_vfs(adapter);
+			ixgbe_drain_all(adapter);
 		}
 	}
 } /* ixgbe_update_link_status */
@@ -4682,10 +4729,10 @@ ixgbe_enable_intr(struct adapter *adapte
 } /* ixgbe_enable_intr */
 
 /************************************************************************
- * ixgbe_disable_intr
+ * ixgbe_disable_intr_internal
  ************************************************************************/
 static void
-ixgbe_disable_intr(struct adapter *adapter)
+ixgbe_disable_intr_internal(struct adapter *adapter, bool nestok)
 {
 	struct ix_queue	*que = adapter->queues;
 
@@ -4696,13 +4743,33 @@ ixgbe_disable_intr(struct adapter *adapt
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 0);
 
 	for (int i = 0; i < adapter->num_queues; i++, que++)
-		ixgbe_disable_queue(adapter, que->msix);
+		ixgbe_disable_queue_internal(adapter, que->msix, nestok);
 
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 
+} /* ixgbe_do_disable_intr_internal */
+
+/************************************************************************
+ * ixgbe_disable_intr
+ ************************************************************************/
+static void
+ixgbe_disable_intr(struct adapter *adapter)
+{
+
+	ixgbe_disable_intr_internal(adapter, true);
 } /* ixgbe_disable_intr */
 
 /************************************************************************
+ * ixgbe_ensure_disabled_intr
+ ************************************************************************/
+void
+ixgbe_ensure_disabled_intr(struct adapter *adapter)
+{
+
+	ixgbe_disable_intr_internal(adapter, false);
+} /* ixgbe_ensure_disabled_intr */
+
+/************************************************************************
  * ixgbe_legacy_irq - Legacy Interrupt Service routine
  ************************************************************************/
 static int

Index: src/sys/dev/pci/ixgbe/ixgbe.h
diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.8 src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.9
--- src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.8	Fri Mar 30 12:07:34 2018
+++ src/sys/dev/pci/ixgbe/ixgbe.h	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.h,v 1.24.6.8 2018/03/30 12:07:34 martin Exp $ */
+/* $NetBSD: ixgbe.h,v 1.24.6.9 2018/04/04 16:18:49 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -339,8 +339,13 @@ struct ix_queue {
 	char             namebuf[32];
 	char             evnamebuf[32];
 
-	kmutex_t         im_mtx;	/* lock for im_nest and this queue's EIMS/EIMC bit */
-	int              im_nest;
+	kmutex_t         dc_mtx;	/* lock for disabled_count and this queue's EIMS/EIMC bit */
+	int              disabled_count;/*
+					 * means
+					 *     0   : this queue is enabled
+					 *     > 0 : this queue is disabled
+					 *           the value is ixgbe_disable_queue() called count
+					 */
 };
 
 /*
@@ -370,8 +375,8 @@ struct tx_ring {
 	u16			atr_sample;
 	u16			atr_count;
 
-	u32			bytes;  /* used for AIM */
-	u32			packets;
+	u64			bytes;  /* used for AIM */
+	u64			packets;
 	/* Soft Stats */
 	struct evcnt	   	tso_tx;
 	struct evcnt		no_desc_avail;
@@ -413,8 +418,8 @@ struct rx_ring {
 	struct ixgbe_rx_buf	*rx_buffers;
 	ixgbe_dma_tag_t		*ptag;
 
-	u32			bytes; /* Used for AIM calc */
-	u32			packets;
+	u64			bytes; /* Used for AIM calc */
+	u64			packets;
 
 	/* Soft stats */
 	struct evcnt		rx_copies;
@@ -741,6 +746,7 @@ int  ixgbe_mq_start(struct ifnet *, stru
 int  ixgbe_mq_start_locked(struct ifnet *, struct tx_ring *);
 void ixgbe_deferred_mq_start(void *);
 void ixgbe_deferred_mq_start_work(struct work *, void *);
+void ixgbe_drain_all(struct adapter *);
 
 int  ixgbe_allocate_queues(struct adapter *);
 int  ixgbe_setup_transmit_structures(struct adapter *);

Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.1 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.2
--- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.1	Thu Dec 21 19:28:54 2017
+++ src/sys/dev/pci/ixgbe/ixgbe_82599.c	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82599.c,v 1.14.8.1 2017/12/21 19:28:54 snj Exp $ */
+/* $NetBSD: ixgbe_82599.c,v 1.14.8.2 2018/04/04 16:18:49 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -56,6 +56,7 @@ static s32 ixgbe_read_eeprom_82599(struc
 				   u16 offset, u16 *data);
 static s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 offset,
 					  u16 words, u16 *data);
+static s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 static s32 ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
 					u8 dev_addr, u8 *data);
 static s32 ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, u8 byte_offset,
@@ -914,9 +915,13 @@ s32 ixgbe_setup_mac_link_82599(struct ix
 
 	speed &= link_capabilities;
 
-	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
-		status = IXGBE_ERR_LINK_SETUP;
-		goto out;
+	if (speed == 0) {
+		ixgbe_disable_tx_laser(hw); /* For fiber */
+		ixgbe_set_phy_power(hw, false); /* For copper */
+	} else {
+		/* In case previous media setting was none(down) */
+		ixgbe_enable_tx_laser(hw); /* for Fiber */
+		ixgbe_set_phy_power(hw, true); /* For copper */
 	}
 
 	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
@@ -2475,7 +2480,7 @@ static s32 ixgbe_read_eeprom_82599(struc
  * Reset pipeline by asserting Restart_AN together with LMS change to ensure
  * full pipeline reset.  This function assumes the SW/FW lock is held.
  **/
-s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
+static s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
 {
 	s32 ret_val;
 	u32 anlp1_reg = 0;

Index: src/sys/dev/pci/ixgbe/ixgbe_api.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_api.h:1.9.8.1 src/sys/dev/pci/ixgbe/ixgbe_api.h:1.9.8.2
--- src/sys/dev/pci/ixgbe/ixgbe_api.h:1.9.8.1	Thu Dec 21 19:28:54 2017
+++ src/sys/dev/pci/ixgbe/ixgbe_api.h	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_api.h,v 1.9.8.1 2017/12/21 19:28:54 snj Exp $ */
+/* $NetBSD: ixgbe_api.h,v 1.9.8.2 2018/04/04 16:18:49 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -227,4 +227,6 @@ void ixgbe_enable_rx(struct ixgbe_hw *hw
 s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
 			u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
 
+void ixgbe_ensure_disabled_intr(struct adapter *);
+
 #endif /* _IXGBE_API_H_ */

Index: src/sys/dev/pci/ixgbe/ixgbe_common.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_common.c:1.13.2.2 src/sys/dev/pci/ixgbe/ixgbe_common.c:1.13.2.3
--- src/sys/dev/pci/ixgbe/ixgbe_common.c:1.13.2.2	Fri Mar 30 12:07:34 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_common.c	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_common.c,v 1.13.2.2 2018/03/30 12:07:34 martin Exp $ */
+/* $NetBSD: ixgbe_common.c,v 1.13.2.3 2018/04/04 16:18:49 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -1130,7 +1130,27 @@ s32 ixgbe_stop_adapter_generic(struct ix
 	ixgbe_disable_rx(hw);
 
 	/* Clear interrupt mask to stop interrupts from being generated */
-	IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK);
+	/*
+	 * XXX
+	 * This function is called in the state of both interrupt disabled
+	 * and interrupt enabled, e.g.
+	 * + interrupt disabled case:
+	 *   - ixgbe_stop()
+	 *     - ixgbe_disable_intr() // interrupt disabled here
+	 *     - ixgbe_stop_adapter()
+	 *       - hw->mac.ops.stop_adapter()
+	 *         == this function
+	 * + interrupt enabled case:
+	 *   - ixgbe_local_timer1()
+	 *     - ixgbe_init_locked()
+	 *       - ixgbe_stop_adapter()
+	 *         - hw->mac.ops.stop_adapter()
+	 *           == this function
+	 * Therefore, it causes nest status breaking to nest the status
+	 * (that is, que->im_nest++) at all times. So, this function must
+	 * use ixgbe_ensure_disabled_intr() instead of ixgbe_disable_intr().
+	 */
+	ixgbe_ensure_disabled_intr(hw->back);
 
 	/* Clear any pending interrupts, flush previous writes */
 	IXGBE_READ_REG(hw, IXGBE_EICR);
@@ -5407,6 +5427,13 @@ s32 ixgbe_setup_mac_link_multispeed_fibe
 			goto out;
 	}
 
+	if (speed == 0) {
+		/* Disable the Tx laser for media none */
+		ixgbe_disable_tx_laser(hw);
+
+		goto out;
+	}
+	
 	/* We didn't get link.  Configure back to the highest speed we tried,
 	 * (if there was more than one).  We call ourselves back with just the
 	 * single highest speed that the user requested.

Index: src/sys/dev/pci/ixgbe/ixgbe_common.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_common.h:1.7.8.2 src/sys/dev/pci/ixgbe/ixgbe_common.h:1.7.8.3
--- src/sys/dev/pci/ixgbe/ixgbe_common.h:1.7.8.2	Fri Mar 30 12:07:34 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_common.h	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_common.h,v 1.7.8.2 2018/03/30 12:07:34 martin Exp $ */
+/* $NetBSD: ixgbe_common.h,v 1.7.8.3 2018/04/04 16:18:49 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -177,7 +177,6 @@ s32 ixgbe_bypass_set_generic(struct ixgb
 			     u32 action);
 s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value);
 
-extern s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw);
 bool ixgbe_mng_present(struct ixgbe_hw *hw);
 bool ixgbe_mng_enabled(struct ixgbe_hw *hw);

Index: src/sys/dev/pci/ixgbe/ixgbe_x550.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.5.6.2 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.5.6.3
--- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.5.6.2	Fri Mar 30 12:07:34 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.c	Wed Apr  4 16:18:49 2018
@@ -41,6 +41,9 @@
 #include <dev/mii/mii.h>
 
 static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed);
+static s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
+				    ixgbe_link_speed speed,
+				    bool autoneg_wait_to_complete);
 static s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
 static void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, u32 mask);
 static s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw);
@@ -566,8 +569,15 @@ static s32 ixgbe_get_phy_id_fw(struct ix
 		if (phy_speeds & ixgbe_fw_map[i].fw_speed)
 			hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed;
 	}
+
+#if 0
+	/*
+	 *  Don't set autoneg_advertised here to not to be inconsistent with
+	 * if_media value.
+	 */
 	if (!hw->phy.autoneg_advertised)
 		hw->phy.autoneg_advertised = hw->phy.speeds_supported;
+#endif
 
 	hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK;
 	phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK;
@@ -2840,6 +2850,9 @@ static s32 ixgbe_setup_sfi_x550a(struct 
 	case IXGBE_LINK_SPEED_1GB_FULL:
 		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
 		break;
+	case 0:
+		/* media none (linkdown) */
+		break;
 	default:
 		/* Other link speeds are not supported by internal PHY. */
 		return IXGBE_ERR_LINK_SETUP;
@@ -2861,7 +2874,7 @@ static s32 ixgbe_setup_sfi_x550a(struct 
  *
  *  Configure the the integrated PHY for SFP support.
  **/
-s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
+static s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
 				    ixgbe_link_speed speed,
 				    bool autoneg_wait_to_complete)
 {

Index: src/sys/dev/pci/ixgbe/ixgbe_x550.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.2.12.1 src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.2.12.2
--- src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.2.12.1	Thu Dec 21 19:28:54 2017
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.h	Wed Apr  4 16:18:49 2018
@@ -99,9 +99,6 @@ s32 ixgbe_setup_fc_X550em(struct ixgbe_h
 s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
 				    ixgbe_link_speed speed,
 				    bool autoneg_wait_to_complete);
-s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
-				    ixgbe_link_speed speed,
-				    bool autoneg_wait_to_complete);
 s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
 			       u32 device_type, u16 *phy_data);
 s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,

Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.56.2.12 src/sys/dev/pci/ixgbe/ixv.c:1.56.2.13
--- src/sys/dev/pci/ixgbe/ixv.c:1.56.2.12	Fri Mar 30 12:07:34 2018
+++ src/sys/dev/pci/ixgbe/ixv.c	Wed Apr  4 16:18:49 2018
@@ -1,4 +1,4 @@
-/*$NetBSD: ixv.c,v 1.56.2.12 2018/03/30 12:07:34 martin Exp $*/
+/*$NetBSD: ixv.c,v 1.56.2.13 2018/04/04 16:18:49 martin Exp $*/
 
 /******************************************************************************
 
@@ -701,7 +701,7 @@ ixv_detach(device_t dev, int flags)
 	ixgbe_free_receive_structures(adapter);
 	for (int i = 0; i < adapter->num_queues; i++) {
 		struct ix_queue *lque = &adapter->queues[i];
-		mutex_destroy(&lque->im_mtx);
+		mutex_destroy(&lque->dc_mtx);
 	}
 	free(adapter->queues, M_DEVBUF);
 
@@ -846,14 +846,14 @@ ixv_enable_queue(struct adapter *adapter
 	u32             queue = 1 << vector;
 	u32             mask;
 
-	mutex_enter(&que->im_mtx);
-	if (que->im_nest > 0 && --que->im_nest > 0)
+	mutex_enter(&que->dc_mtx);
+	if (que->disabled_count > 0 && --que->disabled_count > 0)
 		goto out;
 
 	mask = (IXGBE_EIMS_RTX_QUEUE & queue);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask);
 out:
-	mutex_exit(&que->im_mtx);
+	mutex_exit(&que->dc_mtx);
 } /* ixv_enable_queue */
 
 /************************************************************************
@@ -867,14 +867,14 @@ ixv_disable_queue(struct adapter *adapte
 	u64             queue = (u64)(1 << vector);
 	u32             mask;
 
-	mutex_enter(&que->im_mtx);
-	if (que->im_nest++ > 0)
+	mutex_enter(&que->dc_mtx);
+	if (que->disabled_count++ > 0)
 		goto  out;
 
 	mask = (IXGBE_EIMS_RTX_QUEUE & queue);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, mask);
 out:
-	mutex_exit(&que->im_mtx);
+	mutex_exit(&que->dc_mtx);
 } /* ixv_disable_queue */
 
 static inline void

Reply via email to