Module Name: src Committed By: martin Date: Thu Jun 2 10:45:12 UTC 2022
Modified Files: src/sys/dev/pci/ixgbe [netbsd-9]: ixgbe.c ixgbe.h ixgbe_type.h ixgbe_x550.c ixv.c Log Message: Pull up the following revisions, all via patch, requested by msaitoh in ticket #1459: sys/dev/pci/ixgbe/ixgbe.c 1.261,1.265-1.268,1.273,1.275-1.277, 1.312,1.316-1.319 via patch sys/dev/pci/ixgbe/ixgbe.h 1.85 via patch sys/dev/pci/ixgbe/ixgbe_type.h 1.46-1.47 sys/dev/pci/ixgbe/ixgbe_x550.c 1.26 sys/dev/pci/ixgbe/ixv.c 1.182 - Reduce code duplication between ixgbe_msix_admin() and ixgbe_legacy_irq(). - Add missing code which was not in ixgbe_msix_admin() from ixgbe_legacy_irq() and vice versa. - Reorder code. - Disable/enable the OTHER interrupts correctly. - Don't return in the middle of ixgbe_msix_admin() when an flow director reinit failed. NetBSD currently doesn't support flow director, so this is not a real bug. - Print ECC, PHY and temp error log using with ratecheck(). - Correctly re-enable queue interrupt in ixgbe_legacy_irq(). - Correctly enter the recovery mode. - No functional change: - Add some debug printf()s. - Don't use "more" flag for simplify. - Fix typos in comment. - KNF. To generate a diff of this commit: cvs rdiff -u -r1.199.2.22 -r1.199.2.23 src/sys/dev/pci/ixgbe/ixgbe.c cvs rdiff -u -r1.56.2.8 -r1.56.2.9 src/sys/dev/pci/ixgbe/ixgbe.h cvs rdiff -u -r1.41.2.6 -r1.41.2.7 src/sys/dev/pci/ixgbe/ixgbe_type.h cvs rdiff -u -r1.15.2.5 -r1.15.2.6 src/sys/dev/pci/ixgbe/ixgbe_x550.c cvs rdiff -u -r1.125.2.19 -r1.125.2.20 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/ixgbe.c diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.22 src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.23 --- src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.22 Tue May 31 14:03:26 2022 +++ src/sys/dev/pci/ixgbe/ixgbe.c Thu Jun 2 10:45:12 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.c,v 1.199.2.22 2022/05/31 14:03:26 martin Exp $ */ +/* $NetBSD: ixgbe.c,v 1.199.2.23 2022/06/02 10:45:12 martin Exp $ */ /****************************************************************************** @@ -64,7 +64,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1.199.2.22 2022/05/31 14:03:26 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1.199.2.23 2022/06/02 10:45:12 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -262,12 +262,11 @@ static int ixgbe_sysctl_wufc(SYSCTLFN_PR /* Support for pluggable optic modules */ static bool ixgbe_sfp_probe(struct adapter *); -/* Legacy (single vector) interrupt handler */ -static int ixgbe_legacy_irq(void *); - -/* The MSI/MSI-X Interrupt handlers */ +/* Interrupt functions */ static int ixgbe_msix_que(void *); -static int ixgbe_msix_link(void *); +static int ixgbe_msix_admin(void *); +static void ixgbe_intr_admin_common(struct adapter *, u32, u32 *); +static int ixgbe_legacy_irq(void *); /* Software interrupts for deferred work */ static void ixgbe_handle_que(void *); @@ -422,6 +421,9 @@ static int (*ixgbe_ring_empty)(struct if #endif #define IXGBE_WORKQUEUE_PRI PRI_SOFTNET +/* Interval between reports of errors */ +static const struct timeval ixgbe_errlog_intrvl = { 60, 0 }; /* 60s */ + /************************************************************************ * ixgbe_initialize_rss_mapping ************************************************************************/ @@ -624,12 +626,11 @@ ixgbe_initialize_receive_units(struct ad * so we do not need to clear the bit, but do it just in case * this code is moved elsewhere. */ - if (adapter->num_queues > 1 && - adapter->hw.fc.requested_mode == ixgbe_fc_none) { + if ((adapter->num_queues > 1) && + (adapter->hw.fc.requested_mode == ixgbe_fc_none)) srrctl |= IXGBE_SRRCTL_DROP_EN; - } else { + else srrctl &= ~IXGBE_SRRCTL_DROP_EN; - } IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(j), srrctl); @@ -847,7 +848,8 @@ ixgbe_attach(device_t parent, device_t d * Initialize the shared code */ if (ixgbe_init_shared_code(hw) != 0) { - aprint_error_dev(dev, "Unable to initialize the shared code\n"); + aprint_error_dev(dev, + "Unable to initialize the shared code\n"); error = ENXIO; goto err_out; } @@ -1153,7 +1155,8 @@ ixgbe_attach(device_t parent, device_t d error = ixgbe_start_hw(hw); switch (error) { case IXGBE_ERR_EEPROM_VERSION: - aprint_error_dev(dev, "This device is a pre-production adapter/" + aprint_error_dev(dev, + "This device is a pre-production adapter/" "LOM. Please be aware there may be issues associated " "with your hardware.\nIf you are experiencing problems " "please contact your Intel or hardware representative " @@ -1439,60 +1442,45 @@ ixgbe_add_media_types(struct adapter *ad ADD(IFM_NONE, 0); /* Media types with matching NetBSD media defines */ - if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) { + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T) ADD(IFM_10G_T | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) { + if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_T) ADD(IFM_1000_T | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) { + if (layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) ADD(IFM_100_TX | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) { + if (layer & IXGBE_PHYSICAL_LAYER_10BASE_T) ADD(IFM_10_T | IFM_FDX, 0); - } if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || - layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) { + layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) ADD(IFM_10G_TWINAX | IFM_FDX, 0); - } if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) { ADD(IFM_10G_LR | IFM_FDX, 0); - if (hw->phy.multispeed_fiber) { + if (hw->phy.multispeed_fiber) ADD(IFM_1000_LX | IFM_FDX, 0); - } } if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR) { ADD(IFM_10G_SR | IFM_FDX, 0); - if (hw->phy.multispeed_fiber) { + if (hw->phy.multispeed_fiber) ADD(IFM_1000_SX | IFM_FDX, 0); - } - } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) { + } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) ADD(IFM_1000_SX | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) { + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) ADD(IFM_10G_CX4 | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) { + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) ADD(IFM_10G_KR | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) { + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) ADD(IFM_10G_KX4 | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) { + if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) ADD(IFM_1000_KX | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) { + if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_KX) ADD(IFM_2500_KX | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_T) { + if (layer & IXGBE_PHYSICAL_LAYER_2500BASE_T) ADD(IFM_2500_T | IFM_FDX, 0); - } - if (layer & IXGBE_PHYSICAL_LAYER_5GBASE_T) { + if (layer & IXGBE_PHYSICAL_LAYER_5GBASE_T) ADD(IFM_5000_T | IFM_FDX, 0); - } if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_BX) ADD(IFM_1000_BX10 | IFM_FDX, 0); /* XXX no ifmedia_set? */ @@ -1626,13 +1614,17 @@ ixgbe_update_stats_counters(struct adapt IXGBE_EVC_REGADD(hw, stats, IXGBE_PXONTXC(i), pxontxc[i]); IXGBE_EVC_REGADD(hw, stats, IXGBE_PXOFFTXC(i), pxofftxc[i]); if (hw->mac.type >= ixgbe_mac_82599EB) { - IXGBE_EVC_REGADD(hw, stats, IXGBE_PXONRXCNT(i), pxonrxc[i]); - IXGBE_EVC_REGADD(hw, stats, IXGBE_PXOFFRXCNT(i), pxoffrxc[i]); - IXGBE_EVC_REGADD(hw, stats, IXGBE_PXON2OFFCNT(i), - pxon2offc[i]); + IXGBE_EVC_REGADD(hw, stats, + IXGBE_PXONRXCNT(i), pxonrxc[i]); + IXGBE_EVC_REGADD(hw, stats, + IXGBE_PXOFFRXCNT(i), pxoffrxc[i]); + IXGBE_EVC_REGADD(hw, stats, + IXGBE_PXON2OFFCNT(i), pxon2offc[i]); } else { - IXGBE_EVC_REGADD(hw, stats, IXGBE_PXONRXC(i), pxonrxc[i]); - IXGBE_EVC_REGADD(hw, stats, IXGBE_PXOFFRXC(i), pxoffrxc[i]); + IXGBE_EVC_REGADD(hw, stats, + IXGBE_PXONRXC(i), pxonrxc[i]); + IXGBE_EVC_REGADD(hw, stats, + IXGBE_PXOFFRXC(i), pxoffrxc[i]); } } IXGBE_EVC_ADD(&stats->mpctotal, total_missed_rx); @@ -1782,8 +1774,8 @@ ixgbe_add_hw_stats(struct adapter *adapt NULL, xname, "Watchdog timeouts"); evcnt_attach_dynamic(&adapter->tso_err, EVCNT_TYPE_MISC, NULL, xname, "TSO errors"); - evcnt_attach_dynamic(&adapter->link_irq, EVCNT_TYPE_INTR, - NULL, xname, "Link MSI-X IRQ Handled"); + evcnt_attach_dynamic(&adapter->admin_irq, EVCNT_TYPE_INTR, + NULL, xname, "Admin MSI-X IRQ Handled"); evcnt_attach_dynamic(&adapter->link_sicount, EVCNT_TYPE_INTR, NULL, xname, "Link softint"); evcnt_attach_dynamic(&adapter->mod_sicount, EVCNT_TYPE_INTR, @@ -1797,8 +1789,7 @@ ixgbe_add_hw_stats(struct adapter *adapt KASSERT(IXGBE_DCB_MAX_TRAFFIC_CLASS == 8); for (i = 0; i < IXGBE_TC_COUNTER_NUM; i++) { snprintf(adapter->tcs[i].evnamebuf, - sizeof(adapter->tcs[i].evnamebuf), "%s tc%d", - xname, i); + sizeof(adapter->tcs[i].evnamebuf), "%s tc%d", xname, i); if (i < __arraycount(stats->mpc)) { evcnt_attach_dynamic(&stats->mpc[i], EVCNT_TYPE_MISC, NULL, adapter->tcs[i].evnamebuf, @@ -1826,7 +1817,7 @@ ixgbe_add_hw_stats(struct adapter *adapt evcnt_attach_dynamic(&stats->pxon2offc[i], EVCNT_TYPE_MISC, NULL, adapter->tcs[i].evnamebuf, - "pxon2offc"); + "pxon2offc"); } } @@ -1836,13 +1827,13 @@ ixgbe_add_hw_stats(struct adapter *adapt #endif /* LRO */ snprintf(adapter->queues[i].evnamebuf, - sizeof(adapter->queues[i].evnamebuf), "%s q%d", - xname, i); + sizeof(adapter->queues[i].evnamebuf), "%s q%d", xname, i); snprintf(adapter->queues[i].namebuf, sizeof(adapter->queues[i].namebuf), "q%d", i); if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) { - aprint_error_dev(dev, "could not create sysctl root\n"); + aprint_error_dev(dev, + "could not create sysctl root\n"); break; } @@ -2090,7 +2081,7 @@ ixgbe_clear_evcnt(struct adapter *adapte IXGBE_EVC_STORE(&adapter->enomem_tx_dma_setup, 0); IXGBE_EVC_STORE(&adapter->tso_err, 0); IXGBE_EVC_STORE(&adapter->watchdog_events, 0); - IXGBE_EVC_STORE(&adapter->link_irq, 0); + IXGBE_EVC_STORE(&adapter->admin_irq, 0); IXGBE_EVC_STORE(&adapter->link_sicount, 0); IXGBE_EVC_STORE(&adapter->mod_sicount, 0); IXGBE_EVC_STORE(&adapter->msf_sicount, 0); @@ -2632,7 +2623,9 @@ display: "PCIE Gen3 slot is required.\n"); } } else - device_printf(dev, "Unable to determine slot speed/width. The speed/width reported are that of the internal switch.\n"); + device_printf(dev, + "Unable to determine slot speed/width. The speed/width " + "reported are that of the internal switch.\n"); return; } /* ixgbe_get_slot_info */ @@ -2737,9 +2730,8 @@ ixgbe_sched_handle_que(struct adapter *a * twice workqueue_enqueue() is not required . */ workqueue_enqueue(adapter->que_wq, &que->wq_cookie, curcpu()); - } else { + } else softint_schedule(que->que_si); - } } /************************************************************************ @@ -2753,7 +2745,6 @@ ixgbe_msix_que(void *arg) struct ifnet *ifp = adapter->ifp; struct tx_ring *txr = que->txr; struct rx_ring *rxr = que->rxr; - bool more; u32 newitr = 0; /* Protect against spurious interrupts */ @@ -2769,13 +2760,6 @@ ixgbe_msix_que(void *arg) */ que->txrx_use_workqueue = adapter->txrx_use_workqueue; -#ifdef __NetBSD__ - /* Don't run ixgbe_rxeof in interrupt context */ - more = true; -#else - more = ixgbe_rxeof(que); -#endif - IXGBE_TX_LOCK(txr); ixgbe_txeof(txr); IXGBE_TX_UNLOCK(txr); @@ -2821,10 +2805,9 @@ ixgbe_msix_que(void *arg) * on 1G and higher. */ if ((adapter->link_speed != IXGBE_LINK_SPEED_100_FULL) - && (adapter->link_speed != IXGBE_LINK_SPEED_10_FULL)) { + && (adapter->link_speed != IXGBE_LINK_SPEED_10_FULL)) if (newitr < IXGBE_MIN_RSC_EITR_10G1G) newitr = IXGBE_MIN_RSC_EITR_10G1G; - } /* save for next interrupt */ que->eitr_setting = newitr; @@ -2836,10 +2819,7 @@ ixgbe_msix_que(void *arg) rxr->packets = 0; no_calc: - if (more) - ixgbe_sched_handle_que(adapter, que); - else - ixgbe_enable_queue(adapter, que->msix); + ixgbe_sched_handle_que(adapter, que); return 1; } /* ixgbe_msix_que */ @@ -3099,34 +3079,57 @@ invalid: } /* ixgbe_media_change */ /************************************************************************ - * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) + * ixgbe_msix_admin - Link status change ISR (MSI/MSI-X) ************************************************************************/ static int -ixgbe_msix_link(void *arg) +ixgbe_msix_admin(void *arg) { struct adapter *adapter = arg; struct ixgbe_hw *hw = &adapter->hw; u32 eicr; - s32 retval; + u32 eims_orig; + u32 eims_disable = 0; - IXGBE_EVC_ADD(&adapter->link_irq, 1); + IXGBE_EVC_ADD(&adapter->admin_irq, 1); + eims_orig = IXGBE_READ_REG(hw, IXGBE_EIMS); /* Pause other interrupts */ - IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER); + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_MSIX_OTHER_CLEAR_MASK); - /* First get the cause */ /* + * First get the cause. + * * The specifications of 82598, 82599, X540 and X550 say EICS register * is write only. However, Linux says it is a workaround for silicon - * errata to read EICS instead of EICR to get interrupt cause. It seems - * there is a problem about read clear mechanism for EICR register. + * errata to read EICS instead of EICR to get interrupt cause. + * At least, reading EICR clears lower 16bits of EIMS on 82598. */ eicr = IXGBE_READ_REG(hw, IXGBE_EICS); /* Be sure the queue bits are not cleared */ eicr &= ~IXGBE_EICR_RTX_QUEUE; - /* Clear interrupt with write */ + /* Clear all OTHER interrupts with write */ IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); + ixgbe_intr_admin_common(adapter, eicr, &eims_disable); + + /* Re-enable some OTHER interrupts */ + IXGBE_WRITE_REG(hw, IXGBE_EIMS, eims_orig & ~eims_disable); + + return 1; +} /* ixgbe_msix_admin */ + +static void +ixgbe_intr_admin_common(struct adapter *adapter, u32 eicr, u32 *eims_disable) +{ + struct ixgbe_hw *hw = &adapter->hw; + s32 retval; + + /* Link status change */ + if (eicr & IXGBE_EICR_LSC) { + softint_schedule(adapter->link_si); + *eims_disable |= IXGBE_EIMS_LSC; + } + if (ixgbe_is_sfp(hw)) { u32 eicr_mask; @@ -3145,41 +3148,34 @@ ixgbe_msix_link(void *arg) if ((eicr & eicr_mask) || ((hw->phy.sfp_type == ixgbe_sfp_type_not_present) && (eicr & IXGBE_EICR_LSC))) { - IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); softint_schedule(adapter->mod_si); + *eims_disable |= IXGBE_EIMS_LSC; } if ((hw->mac.type == ixgbe_mac_82599EB) && (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { - IXGBE_WRITE_REG(hw, IXGBE_EICR, - IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); softint_schedule(adapter->msf_si); + *eims_disable |= IXGBE_EIMS_GPI_SDP1_BY_MAC(hw); } } - /* Link status change */ - if (eicr & IXGBE_EICR_LSC) { - IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); - softint_schedule(adapter->link_si); - } - if (adapter->hw.mac.type != ixgbe_mac_82598EB) { #ifdef IXGBE_FDIR if ((adapter->feat_en & IXGBE_FEATURE_FDIR) && (eicr & IXGBE_EICR_FLOW_DIR)) { - /* This is probably overkill :) */ - if (!atomic_cas_uint(&adapter->fdir_reinit, 0, 1)) - return 1; - /* Disable the interrupt */ - IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR); - softint_schedule(adapter->fdir_si); + if (!atomic_cas_uint(&adapter->fdir_reinit, 0, 1)) { + softint_schedule(adapter->fdir_si); + /* Disable the interrupt */ + *eims_disable |= IXGBE_EIMS_FLOW_DIR; + } } #endif if (eicr & IXGBE_EICR_ECC) { - device_printf(adapter->dev, - "CRITICAL: ECC ERROR!! Please Reboot!!\n"); - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC); + if (ratecheck(&adapter->lasterr_time, + &ixgbe_errlog_intrvl)) + device_printf(adapter->dev, + "CRITICAL: ECC ERROR!! Please Reboot!!\n"); } /* Check for over temp condition */ @@ -3188,18 +3184,17 @@ ixgbe_msix_link(void *arg) case ixgbe_mac_X550EM_a: if (!(eicr & IXGBE_EICR_GPI_SDP0_X550EM_a)) break; - IXGBE_WRITE_REG(hw, IXGBE_EIMC, - IXGBE_EICR_GPI_SDP0_X550EM_a); - IXGBE_WRITE_REG(hw, IXGBE_EICR, - IXGBE_EICR_GPI_SDP0_X550EM_a); retval = hw->phy.ops.check_overtemp(hw); if (retval != IXGBE_ERR_OVERTEMP) break; - device_printf(adapter->dev, - "CRITICAL: OVER TEMP!! " - "PHY IS SHUT DOWN!!\n"); - device_printf(adapter->dev, - "System shutdown required!\n"); + if (ratecheck(&adapter->lasterr_time, + &ixgbe_errlog_intrvl)) { + device_printf(adapter->dev, + "CRITICAL: OVER TEMP!! " + "PHY IS SHUT DOWN!!\n"); + device_printf(adapter->dev, + "System shutdown required!\n"); + } break; default: if (!(eicr & IXGBE_EICR_TS)) @@ -3207,39 +3202,37 @@ ixgbe_msix_link(void *arg) retval = hw->phy.ops.check_overtemp(hw); if (retval != IXGBE_ERR_OVERTEMP) break; - device_printf(adapter->dev, - "CRITICAL: OVER TEMP!! " - "PHY IS SHUT DOWN!!\n"); - device_printf(adapter->dev, - "System shutdown required!\n"); - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_TS); + if (ratecheck(&adapter->lasterr_time, + &ixgbe_errlog_intrvl)) { + device_printf(adapter->dev, + "CRITICAL: OVER TEMP!! " + "PHY IS SHUT DOWN!!\n"); + device_printf(adapter->dev, + "System shutdown required!\n"); + } break; } } /* Check for VF message */ if ((adapter->feat_en & IXGBE_FEATURE_SRIOV) && - (eicr & IXGBE_EICR_MAILBOX)) + (eicr & IXGBE_EICR_MAILBOX)) { softint_schedule(adapter->mbx_si); + *eims_disable |= IXGBE_EIMS_MAILBOX; + } } /* Check for fan failure */ - if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { - ixgbe_check_fan_failure(adapter, eicr, TRUE); - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); - } + if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) + ixgbe_check_fan_failure(adapter, eicr, true); /* External PHY interrupt */ if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && (eicr & IXGBE_EICR_GPI_SDP0_X540)) { - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); softint_schedule(adapter->phy_si); + *eims_disable |= IXGBE_EICR_GPI_SDP0_X540; } - - /* Re-enable other interrupts */ - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); - return 1; -} /* ixgbe_msix_link */ +} static void ixgbe_eitr_write(struct adapter *adapter, uint32_t index, uint32_t itr) @@ -3710,7 +3703,7 @@ ixgbe_detach(device_t dev, int flags) evcnt_detach(&adapter->enomem_tx_dma_setup); evcnt_detach(&adapter->watchdog_events); evcnt_detach(&adapter->tso_err); - evcnt_detach(&adapter->link_irq); + evcnt_detach(&adapter->admin_irq); evcnt_detach(&adapter->link_sicount); evcnt_detach(&adapter->mod_sicount); evcnt_detach(&adapter->msf_sicount); @@ -3877,7 +3870,6 @@ ixgbe_setup_low_power_mode(struct adapte /* Enable wakeups and power management in Wakeup Control */ IXGBE_WRITE_REG(hw, IXGBE_WUC, IXGBE_WUC_WKEN | IXGBE_WUC_PME_EN); - } return error; @@ -4650,9 +4642,13 @@ ixgbe_recovery_mode_timer(void *arg) IXGBE_CORE_LOCK(adapter); if (ixgbe_fw_recovery_mode(hw)) { - if (atomic_cas_uint(&adapter->recovery_mode, 0, 1)) { + if (atomic_cas_uint(&adapter->recovery_mode, 0, 1) == 0) { /* Firmware error detected, entering recovery mode */ - device_printf(adapter->dev, "Firmware recovery mode detected. Limiting functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n"); + device_printf(adapter->dev, + "Firmware recovery mode detected. Limiting " + "functionality. Refer to the Intel(R) Ethernet " + "Adapters and Devices User Guide for details on " + "firmware recovery mode.\n"); if (hw->adapter_stopped == FALSE) ixgbe_stop_locked(adapter); @@ -5126,9 +5122,10 @@ ixgbe_legacy_irq(void *arg) struct ixgbe_hw *hw = &adapter->hw; struct ifnet *ifp = adapter->ifp; struct tx_ring *txr = adapter->tx_rings; - bool more = false; u32 eicr; u32 eims_orig; + u32 eims_enable = 0; + u32 eims_disable = 0; eims_orig = IXGBE_READ_REG(hw, IXGBE_EIMS); /* @@ -5137,6 +5134,7 @@ ixgbe_legacy_irq(void *arg) */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); + /* Read and clear EICR */ eicr = IXGBE_READ_REG(hw, IXGBE_EICR); if (eicr == 0) { @@ -5157,13 +5155,6 @@ ixgbe_legacy_irq(void *arg) */ que->txrx_use_workqueue = adapter->txrx_use_workqueue; -#ifdef __NetBSD__ - /* Don't run ixgbe_rxeof in interrupt context */ - more = true; -#else - more = ixgbe_rxeof(que); -#endif - IXGBE_TX_LOCK(txr); ixgbe_txeof(txr); #ifdef notyet @@ -5171,50 +5162,19 @@ ixgbe_legacy_irq(void *arg) ixgbe_start_locked(ifp, txr); #endif IXGBE_TX_UNLOCK(txr); - } - - /* Check for fan failure */ - if (adapter->feat_en & IXGBE_FEATURE_FAN_FAIL) { - ixgbe_check_fan_failure(adapter, eicr, true); - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); - } - /* Link status change */ - if (eicr & IXGBE_EICR_LSC) - softint_schedule(adapter->link_si); - - if (ixgbe_is_sfp(hw)) { - u32 eicr_mask; - - /* Pluggable optics-related interrupt */ - if (hw->mac.type >= ixgbe_mac_X540) - eicr_mask = IXGBE_EICR_GPI_SDP0_X540; - else - eicr_mask = IXGBE_EICR_GPI_SDP2_BY_MAC(hw); - - if (eicr & eicr_mask) { - IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); - softint_schedule(adapter->mod_si); - } - - if ((hw->mac.type == ixgbe_mac_82599EB) && - (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { - IXGBE_WRITE_REG(hw, IXGBE_EICR, - IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); - softint_schedule(adapter->msf_si); - } - } - - /* External PHY interrupt */ - if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && - (eicr & IXGBE_EICR_GPI_SDP0_X540)) - softint_schedule(adapter->phy_si); - - if (more) { IXGBE_EVC_ADD(&que->req, 1); ixgbe_sched_handle_que(adapter, que); + /* Disable queue 0 interrupt */ + eims_disable |= 1UL << 0; } else - ixgbe_enable_intr(adapter); + eims_enable |= eims_orig & IXGBE_EIMC_RTX_QUEUE; + + ixgbe_intr_admin_common(adapter, eicr, &eims_disable); + + /* Re-enable some interrupts */ + IXGBE_WRITE_REG(hw, IXGBE_EIMS, + (eims_orig & ~eims_disable) | eims_enable); return 1; } /* ixgbe_legacy_irq */ @@ -5462,7 +5422,8 @@ ixgbe_set_advertise(struct adapter *adap } if (advertise < 0x0 || advertise > 0x3f) { - device_printf(dev, "Invalid advertised speed; valid modes are 0x0 through 0x3f\n"); + device_printf(dev, "Invalid advertised speed; " + "valid modes are 0x0 through 0x3f\n"); return (EINVAL); } @@ -5470,7 +5431,8 @@ ixgbe_set_advertise(struct adapter *adap err = hw->mac.ops.get_link_capabilities(hw, &link_caps, &negotiate); if (err != IXGBE_SUCCESS) { - device_printf(dev, "Unable to determine supported advertise speeds\n"); + device_printf(dev, "Unable to determine supported " + "advertise speeds\n"); return (ENODEV); } } @@ -5478,42 +5440,48 @@ ixgbe_set_advertise(struct adapter *adap /* Set new value and report new advertised mode */ if (advertise & 0x1) { if (!(link_caps & IXGBE_LINK_SPEED_100_FULL)) { - device_printf(dev, "Interface does not support 100Mb advertised speed\n"); + device_printf(dev, "Interface does not support 100Mb " + "advertised speed\n"); return (EINVAL); } speed |= IXGBE_LINK_SPEED_100_FULL; } if (advertise & 0x2) { if (!(link_caps & IXGBE_LINK_SPEED_1GB_FULL)) { - device_printf(dev, "Interface does not support 1Gb advertised speed\n"); + device_printf(dev, "Interface does not support 1Gb " + "advertised speed\n"); return (EINVAL); } speed |= IXGBE_LINK_SPEED_1GB_FULL; } if (advertise & 0x4) { if (!(link_caps & IXGBE_LINK_SPEED_10GB_FULL)) { - device_printf(dev, "Interface does not support 10Gb advertised speed\n"); + device_printf(dev, "Interface does not support 10Gb " + "advertised speed\n"); return (EINVAL); } speed |= IXGBE_LINK_SPEED_10GB_FULL; } if (advertise & 0x8) { if (!(link_caps & IXGBE_LINK_SPEED_10_FULL)) { - device_printf(dev, "Interface does not support 10Mb advertised speed\n"); + device_printf(dev, "Interface does not support 10Mb " + "advertised speed\n"); return (EINVAL); } speed |= IXGBE_LINK_SPEED_10_FULL; } if (advertise & 0x10) { if (!(link_caps & IXGBE_LINK_SPEED_2_5GB_FULL)) { - device_printf(dev, "Interface does not support 2.5Gb advertised speed\n"); + device_printf(dev, "Interface does not support 2.5Gb " + "advertised speed\n"); return (EINVAL); } speed |= IXGBE_LINK_SPEED_2_5GB_FULL; } if (advertise & 0x20) { if (!(link_caps & IXGBE_LINK_SPEED_5GB_FULL)) { - device_printf(dev, "Interface does not support 5Gb advertised speed\n"); + device_printf(dev, "Interface does not support 5Gb " + "advertised speed\n"); return (EINVAL); } speed |= IXGBE_LINK_SPEED_5GB_FULL; @@ -6059,6 +6027,8 @@ ixgbe_print_debug_info(struct adapter *a device_printf(dev, "EIMS_EX(1):\t%08x\n", IXGBE_READ_REG(hw, IXGBE_EIMS_EX(1))); } + device_printf(dev, "EIAM:\t%08x\n", IXGBE_READ_REG(hw, IXGBE_EIAM)); + device_printf(dev, "EIAC:\t%08x\n", IXGBE_READ_REG(hw, IXGBE_EIAC)); } /* ixgbe_print_debug_info */ /************************************************************************ @@ -6521,7 +6491,16 @@ ixgbe_check_fan_failure(struct adapter * mask = (in_interrupt) ? IXGBE_EICR_GPI_SDP1_BY_MAC(&adapter->hw) : IXGBE_ESDP_SDP1; - if (reg & mask) + if ((reg & mask) == 0) + return; + + /* + * Use ratecheck() just in case interrupt occur frequently. + * When EXPX9501AT's fan stopped, interrupt occurred only once, + * an red LED on the board turned on and link never up until + * power off. + */ + if (ratecheck(&adapter->lasterr_time, &ixgbe_errlog_intrvl)) device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! REPLACE IMMEDIATELY!!\n"); } /* ixgbe_check_fan_failure */ @@ -6559,10 +6538,12 @@ ixgbe_handle_que(void *context) IXGBE_EVC_ADD(&que->req, 1); ixgbe_sched_handle_que(adapter, que); } else if (que->res != NULL) { - /* Re-enable this interrupt */ + /* MSIX: Re-enable this interrupt */ ixgbe_enable_queue(adapter, que->msix); - } else + } else { + /* INTx or MSI */ ixgbe_enable_intr(adapter); + } return; } /* ixgbe_handle_que */ @@ -6863,7 +6844,7 @@ ixgbe_allocate_msix(struct adapter *adap #endif /* Set the link handler function */ adapter->osdep.ihs[vector] = pci_intr_establish_xname(pc, - adapter->osdep.intrs[vector], IPL_NET, ixgbe_msix_link, adapter, + adapter->osdep.intrs[vector], IPL_NET, ixgbe_msix_admin, adapter, intr_xname); if (adapter->osdep.ihs[vector] == NULL) { aprint_error_dev(dev, "Failed to register LINK handler\n"); @@ -6953,7 +6934,9 @@ ixgbe_configure_interrupts(struct adapte queues = uimin(queues, rss_getnumbuckets()); #endif if (ixgbe_num_queues > queues) { - aprint_error_dev(adapter->dev, "ixgbe_num_queues (%d) is too large, using reduced amount (%d).\n", ixgbe_num_queues, queues); + aprint_error_dev(adapter->dev, + "ixgbe_num_queues (%d) is too large, " + "using reduced amount (%d).\n", ixgbe_num_queues, queues); ixgbe_num_queues = queues; } @@ -6975,8 +6958,7 @@ ixgbe_configure_interrupts(struct adapte msgs = want; else { aprint_error_dev(dev, "MSI-X Configuration Problem, " - "%d vectors but %d queues wanted!\n", - msgs, want); + "%d vectors but %d queues wanted!\n", msgs, want); goto msi; } adapter->num_queues = queues; Index: src/sys/dev/pci/ixgbe/ixgbe.h diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.56.2.8 src/sys/dev/pci/ixgbe/ixgbe.h:1.56.2.9 --- src/sys/dev/pci/ixgbe/ixgbe.h:1.56.2.8 Tue May 31 14:03:27 2022 +++ src/sys/dev/pci/ixgbe/ixgbe.h Thu Jun 2 10:45:12 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.h,v 1.56.2.8 2022/05/31 14:03:27 martin Exp $ */ +/* $NetBSD: ixgbe.h,v 1.56.2.9 2022/06/02 10:45:12 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -601,7 +601,7 @@ struct adapter { struct evcnt enomem_tx_dma_setup; struct evcnt tso_err; struct evcnt watchdog_events; - struct evcnt link_irq; + struct evcnt admin_irq; struct evcnt link_sicount; struct evcnt mod_sicount; struct evcnt msf_sicount; @@ -633,6 +633,7 @@ struct adapter { struct sysctllog *sysctllog; const struct sysctlnode *sysctltop; + struct timeval lasterr_time; }; /* Precision Time Sync (IEEE 1588) defines */ Index: src/sys/dev/pci/ixgbe/ixgbe_type.h diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41.2.6 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41.2.7 --- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41.2.6 Mon Jan 31 17:36:25 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_type.h Thu Jun 2 10:45:12 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_type.h,v 1.41.2.6 2022/01/31 17:36:25 martin Exp $ */ +/* $NetBSD: ixgbe_type.h,v 1.41.2.7 2022/06/02 10:45:12 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -2007,6 +2007,13 @@ enum { #define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EIMS_DHER IXGBE_EICR_DHER /* Descr Handler Error */ #define IXGBE_EIMS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ +/* + * EIMS_OTHER is R/W on 82598 though the document says it's reserved. + * It MUST be required to set this bit to get OTHER interrupt. + * + * On other chips, it's read only. It's set if any bits of 29..16 is not zero. + * Bit 30 (TCP_TIMER) doesn't affect to EIMS_OTHER. + */ #define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ /* Extended Interrupt Mask Clear */ @@ -2028,6 +2035,7 @@ enum { #define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */ #define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Err */ #define IXGBE_EIMC_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */ +/* EIMC_OTHER works only on 82598. See EIMS_OTHER's comment */ #define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ #define IXGBE_EIMS_ENABLE_MASK ( \ @@ -2081,7 +2089,8 @@ enum { #define IXGBE_FTQF_QUEUE_ENABLE 0x80000000 /* Interrupt clear mask */ -#define IXGBE_IRQ_CLEAR_MASK 0xFFFFFFFF +#define IXGBE_IRQ_CLEAR_MASK 0xFFFFFFFF +#define IXGBE_MSIX_OTHER_CLEAR_MASK 0xFFFF0000 /* Interrupt Vector Allocation Registers */ #define IXGBE_IVAR_REG_NUM 25 Index: src/sys/dev/pci/ixgbe/ixgbe_x550.c diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15.2.5 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15.2.6 --- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15.2.5 Sun Jan 30 15:58:29 2022 +++ src/sys/dev/pci/ixgbe/ixgbe_x550.c Thu Jun 2 10:45:12 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_x550.c,v 1.15.2.5 2022/01/30 15:58:29 martin Exp $ */ +/* $NetBSD: ixgbe_x550.c,v 1.15.2.6 2022/06/02 10:45:12 martin Exp $ */ /****************************************************************************** @@ -35,7 +35,7 @@ /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x550.c 331224 2018-03-19 20:55:05Z erj $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixgbe_x550.c,v 1.15.2.5 2022/01/30 15:58:29 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixgbe_x550.c,v 1.15.2.6 2022/06/02 10:45:12 martin Exp $"); #include "ixgbe_x550.h" #include "ixgbe_x540.h" @@ -1215,7 +1215,7 @@ s32 ixgbe_init_eeprom_params_X550(struct } /** - * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning + * ixgbe_set_source_address_pruning_X550 - Enable/Disable source address pruning * @hw: pointer to hardware structure * @enable: enable or disable source address pruning * @pool: Rx pool to set source address pruning for Index: src/sys/dev/pci/ixgbe/ixv.c diff -u src/sys/dev/pci/ixgbe/ixv.c:1.125.2.19 src/sys/dev/pci/ixgbe/ixv.c:1.125.2.20 --- src/sys/dev/pci/ixgbe/ixv.c:1.125.2.19 Tue May 31 14:03:26 2022 +++ src/sys/dev/pci/ixgbe/ixv.c Thu Jun 2 10:45:12 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ixv.c,v 1.125.2.19 2022/05/31 14:03:26 martin Exp $ */ +/* $NetBSD: ixv.c,v 1.125.2.20 2022/06/02 10:45:12 martin Exp $ */ /****************************************************************************** @@ -35,7 +35,7 @@ /*$FreeBSD: head/sys/dev/ixgbe/if_ixv.c 331224 2018-03-19 20:55:05Z erj $*/ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ixv.c,v 1.125.2.19 2022/05/31 14:03:26 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ixv.c,v 1.125.2.20 2022/06/02 10:45:12 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -647,7 +647,7 @@ ixv_detach(device_t dev, int flags) evcnt_detach(&adapter->enomem_tx_dma_setup); evcnt_detach(&adapter->watchdog_events); evcnt_detach(&adapter->tso_err); - evcnt_detach(&adapter->link_irq); + evcnt_detach(&adapter->admin_irq); txr = adapter->tx_rings; for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) { @@ -962,7 +962,7 @@ ixv_msix_mbx(void *arg) struct adapter *adapter = arg; struct ixgbe_hw *hw = &adapter->hw; - IXGBE_EVC_ADD(&adapter->link_irq, 1); + IXGBE_EVC_ADD(&adapter->admin_irq, 1); /* NetBSD: We use auto-clear, so it's not required to write VTEICR */ /* Link status change */ @@ -1787,18 +1787,18 @@ ixv_initialize_rss_mapping(struct adapte if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_TCP; if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX) - device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_IPV6_EX defined, but not supported\n", - __func__); + device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_IPV6_EX " + "defined, but not supported\n", __func__); if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6_EX) - device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_TCP_IPV6_EX defined, but not supported\n", - __func__); + device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_TCP_IPV6_EX " + "defined, but not supported\n", __func__); if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP; if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) - device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV6_EX defined, but not supported\n", - __func__); + device_printf(adapter->dev, "%s: RSS_HASHTYPE_RSS_UDP_IPV6_EX " + "defined, but not supported\n", __func__); IXGBE_WRITE_REG(hw, IXGBE_VFMRQC, mrqc); } /* ixv_initialize_rss_mapping */ @@ -1832,7 +1832,9 @@ ixv_initialize_receive_units(struct adap /* Tell PF our max_frame size */ if (ixgbevf_rlpml_set_vf(hw, adapter->max_frame_size) != 0) { - device_printf(adapter->dev, "There is a problem with the PF setup. It is likely the receive unit for this VF will not function correctly.\n"); + device_printf(adapter->dev, "There is a problem with the PF " + "setup. It is likely the receive unit for this VF will " + "not function correctly.\n"); } for (int i = 0; i < adapter->num_queues; i++, rxr++) { @@ -2588,18 +2590,18 @@ ixv_add_stats_sysctls(struct adapter *ad NULL, xname, "Watchdog timeouts"); evcnt_attach_dynamic(&adapter->tso_err, EVCNT_TYPE_MISC, NULL, xname, "TSO errors"); - evcnt_attach_dynamic(&adapter->link_irq, EVCNT_TYPE_INTR, - NULL, xname, "Link MSI-X IRQ Handled"); + evcnt_attach_dynamic(&adapter->admin_irq, EVCNT_TYPE_INTR, + NULL, xname, "Admin MSI-X IRQ Handled"); for (int i = 0; i < adapter->num_queues; i++, rxr++, txr++) { snprintf(adapter->queues[i].evnamebuf, - sizeof(adapter->queues[i].evnamebuf), "%s q%d", - xname, i); + sizeof(adapter->queues[i].evnamebuf), "%s q%d", xname, i); snprintf(adapter->queues[i].namebuf, sizeof(adapter->queues[i].namebuf), "q%d", i); if ((rnode = ixv_sysctl_instance(adapter)) == NULL) { - aprint_error_dev(dev, "could not create sysctl root\n"); + aprint_error_dev(dev, + "could not create sysctl root\n"); break; } @@ -2764,7 +2766,7 @@ ixv_clear_evcnt(struct adapter *adapter) IXGBE_EVC_STORE(&adapter->enomem_tx_dma_setup, 0); IXGBE_EVC_STORE(&adapter->watchdog_events, 0); IXGBE_EVC_STORE(&adapter->tso_err, 0); - IXGBE_EVC_STORE(&adapter->link_irq, 0); + IXGBE_EVC_STORE(&adapter->admin_irq, 0); for (i = 0; i < adapter->num_queues; i++, rxr++, txr++) { IXGBE_EVC_STORE(&adapter->queues[i].irqs, 0); @@ -3482,8 +3484,7 @@ ixv_configure_interrupts(struct adapter else { aprint_error_dev(dev, "MSI-X Configuration Problem, " - "%d vectors but %d queues wanted!\n", - msgs, want); + "%d vectors but %d queues wanted!\n", msgs, want); return -1; }