Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src/sys/dev/pci/ixgbe Pull up following revision(s) (requeste...



details:   https://anonhg.NetBSD.org/src/rev/dfb6cd642a7c
branches:  netbsd-8
changeset: 434821:dfb6cd642a7c
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Apr 04 16:18:49 2018 +0000

description:
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.

diffstat:

 sys/dev/pci/ixgbe/ix_txrx.c      |   67 ++++++++++++++++++++++--
 sys/dev/pci/ixgbe/ixgbe.c        |  105 +++++++++++++++++++++++++++++++-------
 sys/dev/pci/ixgbe/ixgbe.h        |   20 ++++--
 sys/dev/pci/ixgbe/ixgbe_82599.c  |   15 +++-
 sys/dev/pci/ixgbe/ixgbe_api.h    |    4 +-
 sys/dev/pci/ixgbe/ixgbe_common.c |   31 ++++++++++-
 sys/dev/pci/ixgbe/ixgbe_common.h |    3 +-
 sys/dev/pci/ixgbe/ixgbe_x550.c   |   15 +++++-
 sys/dev/pci/ixgbe/ixgbe_x550.h   |    3 -
 sys/dev/pci/ixgbe/ixv.c          |   16 ++--
 10 files changed, 224 insertions(+), 55 deletions(-)

diffs (truncated from 653 to 300 lines):

diff -r 98d58350be42 -r dfb6cd642a7c sys/dev/pci/ixgbe/ix_txrx.c
--- a/sys/dev/pci/ixgbe/ix_txrx.c       Wed Apr 04 16:07:33 2018 +0000
+++ b/sys/dev/pci/ixgbe/ix_txrx.c       Wed Apr 04 16:18:49 2018 +0000
@@ -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_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_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 @@
        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(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 @@
        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 @@
                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);
diff -r 98d58350be42 -r dfb6cd642a7c sys/dev/pci/ixgbe/ixgbe.c
--- a/sys/dev/pci/ixgbe/ixgbe.c Wed Apr 04 16:07:33 2018 +0000
+++ b/sys/dev/pci/ixgbe/ixgbe.c Wed Apr 04 16:18:49 2018 +0000
@@ -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 @@
 #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 @@
                        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 @@
        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_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_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 @@
        case IFM_10_T:
                speed |= IXGBE_LINK_SPEED_10_FULL;
                break;
+       case IFM_NONE:
+               break;
        default:
                goto invalid;
        }
@@ -3511,7 +3538,7 @@
        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_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 @@
        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 @@
                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 @@
 
        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 @@



Home | Main Index | Thread Index | Old Index