Module Name:    src
Committed By:   knakahara
Date:           Mon Apr  2 05:02:55 UTC 2018

Modified Files:
        src/sys/dev/pci/ixgbe: ix_txrx.c ixgbe.c ixgbe.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/sys/dev/pci/ixgbe/ix_txrx.c
cvs rdiff -u -r1.140 -r1.141 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.39 -r1.40 src/sys/dev/pci/ixgbe/ixgbe.h

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.37 src/sys/dev/pci/ixgbe/ix_txrx.c:1.38
--- src/sys/dev/pci/ixgbe/ix_txrx.c:1.37	Fri Mar 30 03:58:20 2018
+++ src/sys/dev/pci/ixgbe/ix_txrx.c	Mon Apr  2 05:02:55 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ix_txrx.c,v 1.37 2018/03/30 03:58:20 knakahara Exp $ */
+/* $NetBSD: ix_txrx.c,v 1.38 2018/04/02 05:02:55 knakahara 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

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.140 src/sys/dev/pci/ixgbe/ixgbe.c:1.141
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.140	Fri Mar 30 06:44:30 2018
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Mon Apr  2 05:02:55 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.140 2018/03/30 06:44:30 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.141 2018/04/02 05:02:55 knakahara Exp $ */
 
 /******************************************************************************
 
@@ -4600,6 +4600,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 */

Index: src/sys/dev/pci/ixgbe/ixgbe.h
diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.39 src/sys/dev/pci/ixgbe/ixgbe.h:1.40
--- src/sys/dev/pci/ixgbe/ixgbe.h:1.39	Fri Mar 30 03:58:20 2018
+++ src/sys/dev/pci/ixgbe/ixgbe.h	Mon Apr  2 05:02:55 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.h,v 1.39 2018/03/30 03:58:20 knakahara Exp $ */
+/* $NetBSD: ixgbe.h,v 1.40 2018/04/02 05:02:55 knakahara Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -746,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 *);

Reply via email to