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