Module Name: src Committed By: msaitoh Date: Thu Dec 6 13:25:02 UTC 2018
Modified Files: src/sys/dev/pci/ixgbe: if_sriov.c ixgbe.c ixgbe.h ixgbe_82599.c ixgbe_api.c ixgbe_api.h ixgbe_features.h ixgbe_netbsd.c ixgbe_netbsd.h ixgbe_phy.c ixgbe_type.h ixgbe_x550.c ixgbe_x550.h Log Message: Apply FreeBSD ix-3.3.6.tar.gz's change to NetBSD. Tested on C3000 and X550-T1, but not tested on Xeon D: - Add firmware recovery mode for X550, X550A(Xeon D) and X550EM (C3000): - FreeBSD always set IXGBE_FEATURE_RECOVERY_MODE without checking the NVM image version. We compare it against 2.0 to not to make new callout and not to call extra atomic operations. - In some FreeBSD's sysctl functions, atomic_load_acq_int() is called before a null pointer check. We call it after null pointer check. - Before calling atomic_load_acq_uint(), check adapter->feat_en flags to save atomic operation call. - We don't check recovery_mode in ixgbe_set_sysctl_value() because this function doesn't touch any hardware register. - NetBSD don't have FreeBSD's atomic_load_acq_int()-like function, so do it with membar_sync(). Thanks riastradh@ for the advice. - FreeBSD's ix-3.3.6 changed ixgbe_enable_aim from TRUE to FALSE, but we will keep it as TRUE because we have already fixed some bugs. - Remove IXGBE_DEV_ID_82599_LS(0x154f) support again. I don't know why. This was added in ix-3.2.18.tar.gz(NetBSD: ixgbe_82599.c rev. 1.20) and removed in ix-3.3.6.tar.gz. - On X550EMU, use ixgbe_identify_sfp_module_X550em() instead of ixgbe_identify_module_generic(). ixgbe_identify_sfp_module_X550em() has extra check (e.g. exclude 1G copper). - if_sriov.c's change doesn't affect to NetBSD because we don't support SR-IOV PF function. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/sys/dev/pci/ixgbe/if_sriov.c \ src/sys/dev/pci/ixgbe/ixgbe_x550.h cvs rdiff -u -r1.168 -r1.169 src/sys/dev/pci/ixgbe/ixgbe.c cvs rdiff -u -r1.52 -r1.53 src/sys/dev/pci/ixgbe/ixgbe.h cvs rdiff -u -r1.20 -r1.21 src/sys/dev/pci/ixgbe/ixgbe_82599.c cvs rdiff -u -r1.21 -r1.22 src/sys/dev/pci/ixgbe/ixgbe_api.c cvs rdiff -u -r1.13 -r1.14 src/sys/dev/pci/ixgbe/ixgbe_api.h \ src/sys/dev/pci/ixgbe/ixgbe_x550.c cvs rdiff -u -r1.1 -r1.2 src/sys/dev/pci/ixgbe/ixgbe_features.h cvs rdiff -u -r1.8 -r1.9 src/sys/dev/pci/ixgbe/ixgbe_netbsd.c \ src/sys/dev/pci/ixgbe/ixgbe_netbsd.h cvs rdiff -u -r1.17 -r1.18 src/sys/dev/pci/ixgbe/ixgbe_phy.c cvs rdiff -u -r1.36 -r1.37 src/sys/dev/pci/ixgbe/ixgbe_type.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/if_sriov.c diff -u src/sys/dev/pci/ixgbe/if_sriov.c:1.4 src/sys/dev/pci/ixgbe/if_sriov.c:1.5 --- src/sys/dev/pci/ixgbe/if_sriov.c:1.4 Mon Sep 3 16:29:33 2018 +++ src/sys/dev/pci/ixgbe/if_sriov.c Thu Dec 6 13:25:02 2018 @@ -250,6 +250,64 @@ ixgbe_vf_set_default_vlan(struct adapter } /* ixgbe_vf_set_default_vlan */ +static void +ixgbe_clear_vfmbmem(struct ixgbe_hw *hw, struct ixgbe_vf *vf) +{ + uint32_t vf_index = IXGBE_VF_INDEX(vf->pool); + uint16_t mbx_size = hw->mbx.size; + uint16_t i; + + IXGBE_CORE_LOCK_ASSERT(adapter); + + for (i = 0; i < mbx_size; ++i) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_index), i, 0x0); +} /* ixgbe_clear_vfmbmem */ + + +static void +ixgbe_toggle_txdctl(struct ixgbe_hw *hw, struct ixgbe_vf *vf) +{ + uint32_t vf_index, offset, reg; + uint8_t queue_count, i; + + IXGBE_CORE_LOCK_ASSERT(adapter); + + vf_index = IXGBE_VF_INDEX(vf->pool); + + /* Determine number of queues by checking + * number of virtual functions */ + reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); + switch (reg & IXGBE_GCR_EXT_VT_MODE_MASK) { + case IXGBE_GCR_EXT_VT_MODE_64: + queue_count = 2; + break; + case IXGBE_GCR_EXT_VT_MODE_32: + queue_count = 4; + break; + default: + return; + } + + /* Toggle queues */ + for (i = 0; i < queue_count; ++i) { + /* Calculate offset of current queue */ + offset = queue_count * vf_index + i; + + /* Enable queue */ + reg = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(offset)); + reg |= IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(offset), reg); + IXGBE_WRITE_FLUSH(hw); + + /* Disable queue */ + reg = IXGBE_READ_REG(hw, IXGBE_PVFTXDCTL(offset)); + reg &= ~IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_PVFTXDCTL(offset), reg); + IXGBE_WRITE_FLUSH(hw); + } +} /* ixgbe_toggle_txdctl */ + + static boolean_t ixgbe_vf_frame_size_compatible(struct adapter *adapter, struct ixgbe_vf *vf) { @@ -305,6 +363,8 @@ ixgbe_process_vf_reset(struct adapter *a // XXX clear multicast addresses ixgbe_clear_rar(&adapter->hw, vf->rar_index); + ixgbe_clear_vfmbmem(&adapter->hw, vf); + ixgbe_toggle_txdctl(&adapter->hw, vf); vf->api_ver = IXGBE_API_VER_UNKNOWN; } /* ixgbe_process_vf_reset */ Index: src/sys/dev/pci/ixgbe/ixgbe_x550.h diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.4 src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.5 --- src/sys/dev/pci/ixgbe/ixgbe_x550.h:1.4 Fri Mar 30 06:44:30 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_x550.h Thu Dec 6 13:25:02 2018 @@ -119,4 +119,5 @@ s32 ixgbe_reset_phy_t_X550em(struct ixgb s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw); s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx); s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx); +bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw); #endif /* _IXGBE_X550_H_ */ Index: src/sys/dev/pci/ixgbe/ixgbe.c diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.168 src/sys/dev/pci/ixgbe/ixgbe.c:1.169 --- src/sys/dev/pci/ixgbe/ixgbe.c:1.168 Mon Dec 3 04:39:44 2018 +++ src/sys/dev/pci/ixgbe/ixgbe.c Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.c,v 1.168 2018/12/03 04:39:44 msaitoh Exp $ */ +/* $NetBSD: ixgbe.c,v 1.169 2018/12/06 13:25:02 msaitoh Exp $ */ /****************************************************************************** @@ -81,7 +81,7 @@ * Driver version ************************************************************************/ static const char ixgbe_driver_version[] = "4.0.1-k"; - +/* XXX NetBSD: + 3.3.6 */ /************************************************************************ * PCI Device ID Table @@ -184,6 +184,7 @@ static void ixgbe_free_pciintr_resources static void ixgbe_free_pci_resources(struct adapter *); static void ixgbe_local_timer(void *); static void ixgbe_local_timer1(void *); +static void ixgbe_recovery_mode_timer(void *); static int ixgbe_setup_interface(device_t, struct adapter *); static void ixgbe_config_gpie(struct adapter *); static void ixgbe_config_dmac(struct adapter *); @@ -971,6 +972,7 @@ ixgbe_attach(device_t parent, device_t d aprint_normal("%s:", device_xname(dev)); /* NVM Image Version */ + high = low = 0; switch (hw->mac.type) { case ixgbe_mac_X540: case ixgbe_mac_X550EM_a: @@ -1000,6 +1002,8 @@ ixgbe_attach(device_t parent, device_t d default: break; } + hw->eeprom.nvm_image_ver_high = high; + hw->eeprom.nvm_image_ver_low = low; /* PHY firmware revision */ switch (hw->mac.type) { @@ -1072,6 +1076,21 @@ ixgbe_attach(device_t parent, device_t d } } } + /* Recovery mode */ + switch (adapter->hw.mac.type) { + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: + case ixgbe_mac_X550EM_a: + /* >= 2.00 */ + if (hw->eeprom.nvm_image_ver_high >= 2) { + adapter->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; + adapter->feat_en |= IXGBE_FEATURE_RECOVERY_MODE; + } + break; + default: + break; + } + if ((adapter->feat_en & IXGBE_FEATURE_MSIX) == 0) error = ixgbe_allocate_legacy(adapter, pa); if (error) @@ -1194,6 +1213,19 @@ ixgbe_attach(device_t parent, device_t d else aprint_error_dev(dev, "couldn't establish power handler\n"); + /* Init recovery mode timer and state variable */ + if (adapter->feat_en & IXGBE_FEATURE_RECOVERY_MODE) { + adapter->recovery_mode = 0; + + /* Set up the timer callout */ + callout_init(&adapter->recovery_mode_timer, + IXGBE_CALLOUT_FLAGS); + + /* Start the task */ + callout_reset(&adapter->recovery_mode_timer, hz, + ixgbe_recovery_mode_timer, adapter); + } + INIT_DEBUGOUT("ixgbe_attach: end"); adapter->osdep.attached = true; @@ -2156,12 +2188,17 @@ ixgbe_sysctl_tdh_handler(SYSCTLFN_ARGS) { struct sysctlnode node = *rnode; struct tx_ring *txr = (struct tx_ring *)node.sysctl_data; + struct adapter *adapter; uint32_t val; if (!txr) return (0); - val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDH(txr->me)); + adapter = txr->adapter; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + + val = IXGBE_READ_REG(&adapter->hw, IXGBE_TDH(txr->me)); node.sysctl_data = &val; return sysctl_lookup(SYSCTLFN_CALL(&node)); } /* ixgbe_sysctl_tdh_handler */ @@ -2176,12 +2213,17 @@ ixgbe_sysctl_tdt_handler(SYSCTLFN_ARGS) { struct sysctlnode node = *rnode; struct tx_ring *txr = (struct tx_ring *)node.sysctl_data; + struct adapter *adapter; uint32_t val; if (!txr) return (0); - val = IXGBE_READ_REG(&txr->adapter->hw, IXGBE_TDT(txr->me)); + adapter = txr->adapter; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + + val = IXGBE_READ_REG(&adapter->hw, IXGBE_TDT(txr->me)); node.sysctl_data = &val; return sysctl_lookup(SYSCTLFN_CALL(&node)); } /* ixgbe_sysctl_tdt_handler */ @@ -2197,11 +2239,16 @@ ixgbe_sysctl_next_to_check_handler(SYSCT { struct sysctlnode node = *rnode; struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data; + struct adapter *adapter; uint32_t val; if (!rxr) return (0); + adapter = rxr->adapter; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + val = rxr->next_to_check; node.sysctl_data = &val; return sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -2217,12 +2264,17 @@ ixgbe_sysctl_rdh_handler(SYSCTLFN_ARGS) { struct sysctlnode node = *rnode; struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data; + struct adapter *adapter; uint32_t val; if (!rxr) return (0); - val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDH(rxr->me)); + adapter = rxr->adapter; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + + val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDH(rxr->me)); node.sysctl_data = &val; return sysctl_lookup(SYSCTLFN_CALL(&node)); } /* ixgbe_sysctl_rdh_handler */ @@ -2237,12 +2289,17 @@ ixgbe_sysctl_rdt_handler(SYSCTLFN_ARGS) { struct sysctlnode node = *rnode; struct rx_ring *rxr = (struct rx_ring *)node.sysctl_data; + struct adapter *adapter; uint32_t val; if (!rxr) return (0); - val = IXGBE_READ_REG(&rxr->adapter->hw, IXGBE_RDT(rxr->me)); + adapter = rxr->adapter; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + + val = IXGBE_READ_REG(&adapter->hw, IXGBE_RDT(rxr->me)); node.sysctl_data = &val; return sysctl_lookup(SYSCTLFN_CALL(&node)); } /* ixgbe_sysctl_rdt_handler */ @@ -3127,13 +3184,18 @@ ixgbe_sysctl_interrupt_rate_handler(SYSC { struct sysctlnode node = *rnode; struct ix_queue *que = (struct ix_queue *)node.sysctl_data; - struct adapter *adapter = que->adapter; + struct adapter *adapter; uint32_t reg, usec, rate; int error; if (que == NULL) return 0; - reg = IXGBE_READ_REG(&que->adapter->hw, IXGBE_EITR(que->msix)); + + adapter = que->adapter; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + + reg = IXGBE_READ_REG(&adapter->hw, IXGBE_EITR(que->msix)); usec = ((reg & 0x0FF8) >> 3); if (usec > 0) rate = 500000 / usec; @@ -3504,6 +3566,7 @@ ixgbe_detach(device_t dev, int flags) IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext); callout_halt(&adapter->timer, NULL); + callout_halt(&adapter->recovery_mode_timer, NULL); if (adapter->feat_en & IXGBE_FEATURE_NETMAP) netmap_detach(adapter->ifp); @@ -4448,6 +4511,32 @@ watchdog: } /* ixgbe_local_timer */ /************************************************************************ + * ixgbe_recovery_mode_timer - Recovery mode timer routine + ************************************************************************/ +static void +ixgbe_recovery_mode_timer(void *arg) +{ + struct adapter *adapter = arg; + struct ixgbe_hw *hw = &adapter->hw; + + IXGBE_CORE_LOCK(adapter); + if (ixgbe_fw_recovery_mode(hw)) { + if (atomic_cas_uint(&adapter->recovery_mode, 0, 1)) { + /* 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"); + + if (hw->adapter_stopped == FALSE) + ixgbe_stop(adapter); + } + } else + atomic_cas_uint(&adapter->recovery_mode, 1, 0); + + callout_reset(&adapter->recovery_mode_timer, hz, + ixgbe_recovery_mode_timer, adapter); + IXGBE_CORE_UNLOCK(adapter); +} /* ixgbe_recovery_mode_timer */ + +/************************************************************************ * ixgbe_sfp_probe * * Determine if a port had optics inserted. @@ -4544,6 +4633,7 @@ ixgbe_handle_msf(void *context) u32 autoneg; bool negotiate; + IXGBE_CORE_LOCK(adapter); ++adapter->msf_sicount.ev_count; /* get_supported_phy_layer will call hw->phy.ops.identify_sfp() */ adapter->phy_layer = ixgbe_get_supported_physical_layer(hw); @@ -4560,6 +4650,7 @@ ixgbe_handle_msf(void *context) ifmedia_removeall(&adapter->media); ixgbe_add_media_types(adapter); ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO); + IXGBE_CORE_UNLOCK(adapter); } /* ixgbe_handle_msf */ /************************************************************************ @@ -5036,6 +5127,11 @@ ixgbe_set_sysctl_value(struct adapter *a struct sysctllog **log; const struct sysctlnode *rnode, *cnode; + /* + * It's not required to check recovery mode because this function never + * touches hardware. + */ + log = &adapter->sysctllog; if ((rnode = ixgbe_sysctl_instance(adapter)) == NULL) { aprint_error_dev(dev, "could not create sysctl root\n"); @@ -5061,6 +5157,9 @@ ixgbe_sysctl_flowcntl(SYSCTLFN_ARGS) struct adapter *adapter = (struct adapter *)node.sysctl_data; int error, fc; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + fc = adapter->hw.fc.current_mode; node.sysctl_data = &fc; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5179,6 +5278,9 @@ ixgbe_sysctl_advertise(SYSCTLFN_ARGS) struct adapter *adapter = (struct adapter *)node.sysctl_data; int error = 0, advertise; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + advertise = adapter->advertise; node.sysctl_data = &advertise; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5361,6 +5463,9 @@ ixgbe_sysctl_dmac(SYSCTLFN_ARGS) int error; int newval; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + newval = adapter->dmac; node.sysctl_data = &newval; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5418,6 +5523,9 @@ ixgbe_sysctl_power_state(SYSCTLFN_ARGS) device_t dev = adapter->dev; int curr_ps, new_ps, error = 0; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + curr_ps = new_ps = pci_get_powerstate(dev); error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5462,6 +5570,10 @@ ixgbe_sysctl_wol_enable(SYSCTLFN_ARGS) bool new_wol_enabled; int error = 0; + /* + * It's not required to check recovery mode because this function never + * touches hardware. + */ new_wol_enabled = hw->wol_enabled; node.sysctl_data = &new_wol_enabled; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5503,6 +5615,10 @@ ixgbe_sysctl_wufc(SYSCTLFN_ARGS) int error = 0; u32 new_wufc; + /* + * It's not required to check recovery mode because this function never + * touches hardware. + */ new_wufc = adapter->wufc; node.sysctl_data = &new_wufc; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5537,6 +5653,9 @@ ixgbe_sysctl_print_rss_config(SYSCTLFN_A int error = 0, reta_size; u32 reg; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + buf = sbuf_new_for_sysctl(NULL, NULL, 128, req); if (!buf) { device_printf(dev, "Could not allocate sbuf for output.\n"); @@ -5595,6 +5714,9 @@ ixgbe_sysctl_phy_temp(SYSCTLFN_ARGS) u16 reg; int error; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { device_printf(adapter->dev, "Device has no supported external thermal sensor.\n"); @@ -5635,6 +5757,9 @@ ixgbe_sysctl_phy_overtemp_occurred(SYSCT int val, error; u16 reg; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + if (hw->device_id != IXGBE_DEV_ID_X550EM_X_10G_T) { device_printf(adapter->dev, "Device has no supported external thermal sensor.\n"); @@ -5679,6 +5804,9 @@ ixgbe_sysctl_eee_state(SYSCTLFN_ARGS) int curr_eee, new_eee, error = 0; s32 retval; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + curr_eee = new_eee = !!(adapter->feat_en & IXGBE_FEATURE_EEE); node.sysctl_data = &new_eee; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5814,6 +5942,9 @@ ixgbe_sysctl_debug(SYSCTLFN_ARGS) struct adapter *adapter = (struct adapter *)node.sysctl_data; int error, result = 0; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + node.sysctl_data = &result; error = sysctl_lookup(SYSCTLFN_CALL(&node)); @@ -5853,17 +5984,29 @@ ixgbe_init_device_features(struct adapte adapter->feat_cap |= IXGBE_FEATURE_BYPASS; break; case ixgbe_mac_X550: + /* + * IXGBE_FEATURE_RECOVERY_MODE will be set after reading + * NVM Image version. + */ adapter->feat_cap |= IXGBE_FEATURE_TEMP_SENSOR; adapter->feat_cap |= IXGBE_FEATURE_SRIOV; adapter->feat_cap |= IXGBE_FEATURE_FDIR; break; case ixgbe_mac_X550EM_x: + /* + * IXGBE_FEATURE_RECOVERY_MODE will be set after reading + * NVM Image version. + */ adapter->feat_cap |= IXGBE_FEATURE_SRIOV; adapter->feat_cap |= IXGBE_FEATURE_FDIR; if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_KR) adapter->feat_cap |= IXGBE_FEATURE_EEE; break; case ixgbe_mac_X550EM_a: + /* + * IXGBE_FEATURE_RECOVERY_MODE will be set after reading + * NVM Image version. + */ adapter->feat_cap |= IXGBE_FEATURE_SRIOV; adapter->feat_cap |= IXGBE_FEATURE_FDIR; adapter->feat_cap &= ~IXGBE_FEATURE_LEGACY_IRQ; @@ -5899,6 +6042,11 @@ ixgbe_init_device_features(struct adapte /* Thermal Sensor */ if (adapter->feat_cap & IXGBE_FEATURE_TEMP_SENSOR) adapter->feat_en |= IXGBE_FEATURE_TEMP_SENSOR; + /* + * Recovery mode: + * NetBSD: IXGBE_FEATURE_RECOVERY_MODE will be controlled after reading + * NVM Image version. + */ /* Enabled via global sysctl... */ /* Flow Director */ @@ -6019,6 +6167,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c const int l4csum = IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx| IFCAP_CSUM_TCPv6_Rx|IFCAP_CSUM_UDPv6_Rx; + if (ixgbe_fw_recovery_mode_swflag(adapter)) + return (EPERM); + switch (command) { case SIOCSIFFLAGS: IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)"); Index: src/sys/dev/pci/ixgbe/ixgbe.h diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.52 src/sys/dev/pci/ixgbe/ixgbe.h:1.53 --- src/sys/dev/pci/ixgbe/ixgbe.h:1.52 Mon Dec 3 04:39:44 2018 +++ src/sys/dev/pci/ixgbe/ixgbe.h Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.h,v 1.52 2018/12/03 04:39:44 msaitoh Exp $ */ +/* $NetBSD: ixgbe.h,v 1.53 2018/12/06 13:25:02 msaitoh Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -574,6 +574,10 @@ struct adapter { void (*init_locked)(struct adapter *); void (*stop_locked)(void *); + /* Firmware error check */ + u_int recovery_mode; + struct callout recovery_mode_timer; + /* Misc stats maintained by the driver */ struct evcnt efbig_tx_dma_setup; struct evcnt mbuf_defrag_failed; @@ -745,6 +749,18 @@ ixv_check_ether_addr(u8 *addr) return (status); } +/* + * This checks the adapter->recovery_mode software flag which is + * set by ixgbe_fw_recovery_mode(). + * + */ +static inline bool +ixgbe_fw_recovery_mode_swflag(struct adapter *adapter) +{ + return (adapter->feat_en & IXGBE_FEATURE_RECOVERY_MODE) && + atomic_load_acq_uint(&adapter->recovery_mode); +} + /* Shared Prototypes */ void ixgbe_legacy_start(struct ifnet *); int ixgbe_legacy_start_locked(struct ifnet *, struct tx_ring *); Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.20 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.21 --- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.20 Mon Jun 11 10:34:18 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_82599.c Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_82599.c,v 1.20 2018/06/11 10:34:18 msaitoh Exp $ */ +/* $NetBSD: ixgbe_82599.c,v 1.21 2018/12/06 13:25:02 msaitoh Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -566,9 +566,6 @@ enum ixgbe_media_type ixgbe_get_media_ty case IXGBE_DEV_ID_82599_T3_LOM: media_type = ixgbe_media_type_copper; break; - case IXGBE_DEV_ID_82599_LS: - media_type = ixgbe_media_type_fiber_lco; - break; case IXGBE_DEV_ID_82599_QSFP_SF_QP: media_type = ixgbe_media_type_fiber_qsfp; break; Index: src/sys/dev/pci/ixgbe/ixgbe_api.c diff -u src/sys/dev/pci/ixgbe/ixgbe_api.c:1.21 src/sys/dev/pci/ixgbe/ixgbe_api.c:1.22 --- src/sys/dev/pci/ixgbe/ixgbe_api.c:1.21 Mon Jun 11 10:34:18 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_api.c Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_api.c,v 1.21 2018/06/11 10:34:18 msaitoh Exp $ */ +/* $NetBSD: ixgbe_api.c,v 1.22 2018/12/06 13:25:02 msaitoh Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -173,7 +173,6 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw * case IXGBE_DEV_ID_82599_SFP_SF_QP: case IXGBE_DEV_ID_82599_QSFP_SF_QP: case IXGBE_DEV_ID_82599EN_SFP: - case IXGBE_DEV_ID_82599_LS: case IXGBE_DEV_ID_82599_CX4: case IXGBE_DEV_ID_82599_BYPASS: case IXGBE_DEV_ID_82599_T3_LOM: @@ -1310,6 +1309,18 @@ void ixgbe_restore_mdd_vf(struct ixgbe_h } /** + * ixgbe_fw_recovery_mode - Check if in FW NVM recovery mode + * @hw: pointer to hardware structure + * + **/ +bool ixgbe_fw_recovery_mode(struct ixgbe_hw *hw) +{ + if (hw->mac.ops.fw_recovery_mode) + return hw->mac.ops.fw_recovery_mode(hw); + return FALSE; +} + +/** * ixgbe_enter_lplu - Transition to low power states * @hw: pointer to hardware structure * Index: src/sys/dev/pci/ixgbe/ixgbe_api.h diff -u src/sys/dev/pci/ixgbe/ixgbe_api.h:1.13 src/sys/dev/pci/ixgbe/ixgbe_api.h:1.14 --- src/sys/dev/pci/ixgbe/ixgbe_api.h:1.13 Wed Apr 4 08:13:07 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_api.h Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_api.h,v 1.13 2018/04/04 08:13:07 msaitoh Exp $ */ +/* $NetBSD: ixgbe_api.h,v 1.14 2018/12/06 13:25:02 msaitoh Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -219,6 +219,7 @@ void ixgbe_disable_mdd(struct ixgbe_hw * void ixgbe_enable_mdd(struct ixgbe_hw *hw); void ixgbe_mdd_event(struct ixgbe_hw *hw, u32 *vf_bitmap); void ixgbe_restore_mdd_vf(struct ixgbe_hw *hw, u32 vf); +bool ixgbe_fw_recovery_mode(struct ixgbe_hw *hw); s32 ixgbe_enter_lplu(struct ixgbe_hw *hw); s32 ixgbe_handle_lasi(struct ixgbe_hw *hw); void ixgbe_set_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed); Index: src/sys/dev/pci/ixgbe/ixgbe_x550.c diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.13 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.14 --- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.13 Fri Jul 6 02:36:35 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_x550.c Thu Dec 6 13:25:02 2018 @@ -87,6 +87,7 @@ s32 ixgbe_init_ops_X550(struct ixgbe_hw mac->ops.enable_mdd = ixgbe_enable_mdd_X550; mac->ops.mdd_event = ixgbe_mdd_event_X550; mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550; + mac->ops.fw_recovery_mode = ixgbe_fw_recovery_mode_X550; mac->ops.disable_rx = ixgbe_disable_rx_x550; /* Manageability interface */ mac->ops.set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550; @@ -446,7 +447,7 @@ static s32 ixgbe_identify_phy_x550em(str switch (hw->device_id) { case IXGBE_DEV_ID_X550EM_A_SFP: - return ixgbe_identify_module_generic(hw); + return ixgbe_identify_sfp_module_X550em(hw); case IXGBE_DEV_ID_X550EM_X_SFP: /* set up for CS4227 usage */ ixgbe_setup_mux_ctl(hw); @@ -454,7 +455,7 @@ static s32 ixgbe_identify_phy_x550em(str /* Fallthrough */ case IXGBE_DEV_ID_X550EM_A_SFP_N: - return ixgbe_identify_module_generic(hw); + return ixgbe_identify_sfp_module_X550em(hw); break; case IXGBE_DEV_ID_X550EM_X_KX4: hw->phy.type = ixgbe_phy_x550em_kx4; @@ -4817,3 +4818,19 @@ s32 ixgbe_set_fw_drv_ver_x550(struct ixg return ret_val; } + +/** + * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode + * @hw: pointer t hardware structure + * + * Returns TRUE if in FW NVM recovery mode. + **/ +bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw) +{ + u32 fwsm; + + fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw)); + + return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE); +} + Index: src/sys/dev/pci/ixgbe/ixgbe_features.h diff -u src/sys/dev/pci/ixgbe/ixgbe_features.h:1.1 src/sys/dev/pci/ixgbe/ixgbe_features.h:1.2 --- src/sys/dev/pci/ixgbe/ixgbe_features.h:1.1 Wed Aug 30 08:49:18 2017 +++ src/sys/dev/pci/ixgbe/ixgbe_features.h Thu Dec 6 13:25:02 2018 @@ -57,12 +57,13 @@ #define IXGBE_FEATURE_EEE (u32)(1 << 11) #define IXGBE_FEATURE_LEGACY_IRQ (u32)(1 << 12) #define IXGBE_FEATURE_NEEDS_CTXD (u32)(1 << 13) +#define IXGBE_FEATURE_RECOVERY_MODE (u32)(1 << 15) #define IXGBE_FEATURE_FLAGS "\20" \ "\1" "VF" "\2" "SRIOV" "\3" "RSS" "\4" "NETMAP" \ "\5" "FAN_FAIL" "\6" "TEMP_SENSOR" "\7" "BYPASS" "\10" "LEGACY_TX" \ "\11" "FDIR" "\12" "MSI" "\13" "MSIX" "\14" "EEE" \ - "\15" "LEGACY_IRQ" "\16" "NEEDS_CTXD" + "\15" "LEGACY_IRQ" "\16" "NEEDS_CTXD" "\20" "RECOVERY_MODE" /* Check for OS support. Undefine features if not included in the OS */ #ifndef PCI_IOV Index: src/sys/dev/pci/ixgbe/ixgbe_netbsd.c diff -u src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.8 src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.9 --- src/sys/dev/pci/ixgbe/ixgbe_netbsd.c:1.8 Tue Jul 31 09:19:34 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_netbsd.c Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_netbsd.c,v 1.8 2018/07/31 09:19:34 msaitoh Exp $ */ +/* $NetBSD: ixgbe_netbsd.c,v 1.9 2018/12/06 13:25:02 msaitoh Exp $ */ /* * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. @@ -273,3 +273,19 @@ ixgbe_pci_enable_busmaster(pci_chipset_t pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, pci_cmd_word); } } + +u_int +atomic_load_acq_uint(volatile u_int *p) +{ + u_int rv; + + rv = *p; + /* + * XXX + * membar_sync() is far more than we need on most CPUs; + * we just don't have an MI load-acqure operation. + */ + membar_sync(); + + return rv; +} Index: src/sys/dev/pci/ixgbe/ixgbe_netbsd.h diff -u src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.8 src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.9 --- src/sys/dev/pci/ixgbe/ixgbe_netbsd.h:1.8 Wed Apr 25 08:46:19 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_netbsd.h Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/*$NetBSD: ixgbe_netbsd.h,v 1.8 2018/04/25 08:46:19 msaitoh Exp $*/ +/*$NetBSD: ixgbe_netbsd.h,v 1.9 2018/12/06 13:25:02 msaitoh Exp $*/ /* * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. @@ -96,4 +96,6 @@ void ixgbe_dmamap_unload(ixgbe_dma_tag_t struct mbuf *ixgbe_getjcl(ixgbe_extmem_head_t *, int, int, int, size_t); void ixgbe_pci_enable_busmaster(pci_chipset_tag_t, pcitag_t); +u_int atomic_load_acq_uint(volatile u_int *); + #endif /* _IXGBE_NETBSD_H */ Index: src/sys/dev/pci/ixgbe/ixgbe_phy.c diff -u src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.17 src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.18 --- src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.17 Wed Apr 4 08:59:22 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_phy.c Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_phy.c,v 1.17 2018/04/04 08:59:22 msaitoh Exp $ */ +/* $NetBSD: ixgbe_phy.c,v 1.18 2018/12/06 13:25:02 msaitoh Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -2612,7 +2612,6 @@ static bool ixgbe_get_i2c_data(struct ix { u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN_BY_MAC(hw); bool data; - UNREFERENCED_1PARAMETER(hw); DEBUGFUNC("ixgbe_get_i2c_data"); Index: src/sys/dev/pci/ixgbe/ixgbe_type.h diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.36 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.37 --- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.36 Fri Jul 6 02:36:35 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_type.h Thu Dec 6 13:25:02 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_type.h,v 1.36 2018/07/06 02:36:35 msaitoh Exp $ */ +/* $NetBSD: ixgbe_type.h,v 1.37 2018/12/06 13:25:02 msaitoh Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -131,7 +131,6 @@ #define IXGBE_SUBDEV_ID_82599EN_SFP_OCP1 0x0001 #define IXGBE_DEV_ID_82599_XAUI_LOM PCI_PRODUCT_INTEL_82599_XAUI_LOM #define IXGBE_DEV_ID_82599_T3_LOM 0x151C -#define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_82599_VF 0x10ED #define IXGBE_DEV_ID_82599_VF_HV 0x152E #define IXGBE_DEV_ID_82599_BYPASS 0x155D @@ -1096,6 +1095,9 @@ struct ixgbe_dmac_config { #define IXGBE_FWSM_MODE_MASK 0xE #define IXGBE_FWSM_TS_ENABLED 0x1 #define IXGBE_FWSM_FW_MODE_PT 0x4 +#define IXGBE_FWSM_FW_NVM_RECOVERY_MODE (1 << 5) +#define IXGBE_FWSM_EXT_ERR_IND_MASK 0x01F80000 +#define IXGBE_FWSM_FW_VAL_BIT (1 << 15) /* ARC Subsystem registers */ #define IXGBE_HICR 0x15F00 @@ -3759,7 +3761,6 @@ enum ixgbe_media_type { ixgbe_media_type_fiber, ixgbe_media_type_fiber_fixed, ixgbe_media_type_fiber_qsfp, - ixgbe_media_type_fiber_lco, ixgbe_media_type_copper, ixgbe_media_type_backplane, ixgbe_media_type_cx4, @@ -4063,6 +4064,7 @@ struct ixgbe_mac_operations { void (*enable_mdd)(struct ixgbe_hw *hw); void (*mdd_event)(struct ixgbe_hw *hw, u32 *vf_bitmap); void (*restore_mdd_vf)(struct ixgbe_hw *hw, u32 vf); + bool (*fw_recovery_mode)(struct ixgbe_hw *hw); }; struct ixgbe_phy_operations { @@ -4117,6 +4119,8 @@ struct ixgbe_eeprom_info { u16 address_bits; u16 word_page_size; u16 ctrl_word_3; + u8 nvm_image_ver_high; + u8 nvm_image_ver_low; }; #define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED 0x01