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