Module Name: src
Committed By: msaitoh
Date: Mon Dec 23 09:36:18 UTC 2019
Modified Files:
src/sys/dev/pci/ixgbe: ixgbe.c ixgbe_82598.c ixgbe_82599.c ixgbe_phy.c
ixgbe_type.h ixgbe_x550.c
Log Message:
Add recovery code for unsupported SFP+.
Before this commit:
If an unsuppored SFP module is inserted before booting, the driver attach
failed and there was no way to recover form it without rebooting or
detaching/reattaching drvier (drvctl -d && drvctl -r pciN).
After this commit:
We can automatically recover any time by replacing it with a supported
module.
To generate a diff of this commit:
cvs rdiff -u -r1.218 -r1.219 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/pci/ixgbe/ixgbe_82598.c
cvs rdiff -u -r1.21 -r1.22 src/sys/dev/pci/ixgbe/ixgbe_82599.c
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/pci/ixgbe/ixgbe_phy.c
cvs rdiff -u -r1.43 -r1.44 src/sys/dev/pci/ixgbe/ixgbe_type.h
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/ixgbe/ixgbe_x550.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.218 src/sys/dev/pci/ixgbe/ixgbe.c:1.219
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.218 Mon Dec 23 09:19:40 2019
+++ src/sys/dev/pci/ixgbe/ixgbe.c Mon Dec 23 09:36:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.218 2019/12/23 09:19:40 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.219 2019/12/23 09:36:17 msaitoh Exp $ */
/******************************************************************************
@@ -776,6 +776,7 @@ ixgbe_attach(device_t parent, device_t d
pcireg_t id, subid;
const ixgbe_vendor_info_t *ent;
struct pci_attach_args *pa = aux;
+ bool unsupported_sfp = false;
const char *str;
char buf[256];
@@ -954,8 +955,8 @@ ixgbe_attach(device_t parent, device_t d
error = IXGBE_SUCCESS;
} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED) {
aprint_error_dev(dev, "Unsupported SFP+ module detected!\n");
- error = EIO;
- goto err_late;
+ unsupported_sfp = true;
+ error = IXGBE_SUCCESS;
} else if (error) {
aprint_error_dev(dev, "Hardware initialization failed\n");
error = EIO;
@@ -1126,13 +1127,6 @@ ixgbe_attach(device_t parent, device_t d
"please contact your Intel or hardware representative "
"who provided you with this hardware.\n");
break;
- case IXGBE_ERR_SFP_NOT_SUPPORTED:
- aprint_error_dev(dev, "Unsupported SFP+ Module\n");
- error = EIO;
- goto err_late;
- case IXGBE_ERR_SFP_NOT_PRESENT:
- aprint_error_dev(dev, "No SFP+ Module found\n");
- /* falls thru */
default:
break;
}
@@ -1165,16 +1159,22 @@ ixgbe_attach(device_t parent, device_t d
oui, model, rev);
}
- /* Enable the optics for 82599 SFP+ fiber */
- ixgbe_enable_tx_laser(hw);
-
/* Enable EEE power saving */
if (adapter->feat_cap & IXGBE_FEATURE_EEE)
hw->mac.ops.setup_eee(hw,
adapter->feat_en & IXGBE_FEATURE_EEE);
/* Enable power to the phy. */
- ixgbe_set_phy_power(hw, TRUE);
+ if (!unsupported_sfp) {
+ /* Enable the optics for 82599 SFP+ fiber */
+ ixgbe_enable_tx_laser(hw);
+
+ /*
+ * XXX Currently, ixgbe_set_phy_power() supports only copper
+ * PHY, so it's not required to test with !unsupported_sfp.
+ */
+ ixgbe_set_phy_power(hw, TRUE);
+ }
/* Initialize statistics */
ixgbe_update_stats_counters(adapter);
@@ -3901,6 +3901,7 @@ ixgbe_init_locked(struct adapter *adapte
u32 txdctl, mhadd;
u32 rxdctl, rxctrl;
u32 ctrl_ext;
+ bool unsupported_sfp = false;
int i, j, err;
/* XXX check IFF_UP and IFF_RUNNING, power-saving state! */
@@ -3908,6 +3909,7 @@ ixgbe_init_locked(struct adapter *adapte
KASSERT(mutex_owned(&adapter->core_mtx));
INIT_DEBUGOUT("ixgbe_init_locked: begin");
+ hw->need_unsupported_sfp_recovery = false;
hw->adapter_stopped = FALSE;
ixgbe_stop_adapter(hw);
callout_stop(&adapter->timer);
@@ -4081,12 +4083,14 @@ ixgbe_init_locked(struct adapter *adapte
*/
if (hw->phy.type == ixgbe_phy_none) {
err = hw->phy.ops.identify(hw);
- if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,
- "Unsupported SFP+ module type was detected.\n");
- return;
- }
- }
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ unsupported_sfp = true;
+ } else if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+ unsupported_sfp = true;
+
+ if (unsupported_sfp)
+ device_printf(dev,
+ "Unsupported SFP+ module type was detected.\n");
/* Set moderation on the Link interrupt */
ixgbe_eitr_write(adapter, adapter->vector, IXGBE_LINK_ITR);
@@ -4097,10 +4101,12 @@ ixgbe_init_locked(struct adapter *adapte
adapter->feat_en & IXGBE_FEATURE_EEE);
/* Enable power to the phy. */
- ixgbe_set_phy_power(hw, TRUE);
+ if (!unsupported_sfp) {
+ ixgbe_set_phy_power(hw, TRUE);
- /* Config/Enable Link */
- ixgbe_config_link(adapter);
+ /* Config/Enable Link */
+ ixgbe_config_link(adapter);
+ }
/* Hardware Packet Buffer & Flow Control setup */
ixgbe_config_delay_values(adapter);
@@ -4636,15 +4642,28 @@ ixgbe_handle_mod(void *context)
goto out;
}
- if (hw->mac.type == ixgbe_mac_82598EB)
- err = hw->phy.ops.reset(hw);
- else
- err = hw->mac.ops.setup_sfp(hw);
-
- if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
- device_printf(dev,
- "Setup failure - unsupported SFP+ module type.\n");
- goto out;
+ if (hw->need_unsupported_sfp_recovery) {
+ device_printf(dev, "Recovering from unsupported SFP\n");
+ /*
+ * We could recover the status by calling setup_sfp(),
+ * setup_link() and some others. It's complex and might not
+ * work correctly on some unknown cases. To avoid such type of
+ * problem, call ixgbe_init_locked(). It's simple and safe
+ * approach.
+ */
+ ixgbe_init_locked(adapter);
+ } else {
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ err = hw->phy.ops.reset(hw);
+ else {
+ err = hw->mac.ops.setup_sfp(hw);
+ hw->phy.sfp_setup_needed = FALSE;
+ }
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev,
+ "Setup failure - unsupported SFP+ module type.\n");
+ goto out;
+ }
}
softint_schedule(adapter->msf_si);
out:
Index: src/sys/dev/pci/ixgbe/ixgbe_82598.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.12 src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.13
--- src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.12 Wed Apr 4 08:59:22 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_82598.c Mon Dec 23 09:36:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82598.c,v 1.12 2018/04/04 08:59:22 msaitoh Exp $ */
+/* $NetBSD: ixgbe_82598.c,v 1.13 2019/12/23 09:36:17 msaitoh Exp $ */
/******************************************************************************
SPDX-License-Identifier: BSD-3-Clause
@@ -866,9 +866,8 @@ static s32 ixgbe_reset_hw_82598(struct i
/* Init PHY and function pointers, perform SFP setup */
phy_status = hw->phy.ops.init(hw);
- if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
- goto reset_hw_out;
- if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
+ if ((phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED) ||
+ (phy_status == IXGBE_ERR_SFP_NOT_PRESENT))
goto mac_reset_top;
hw->phy.ops.reset(hw);
Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.21 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.22
--- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.21 Thu Dec 6 13:25:02 2018
+++ src/sys/dev/pci/ixgbe/ixgbe_82599.c Mon Dec 23 09:36:17 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82599.c,v 1.21 2018/12/06 13:25:02 msaitoh Exp $ */
+/* $NetBSD: ixgbe_82599.c,v 1.22 2019/12/23 09:36:17 msaitoh Exp $ */
/******************************************************************************
SPDX-License-Identifier: BSD-3-Clause
@@ -1041,6 +1041,7 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw
{
ixgbe_link_speed link_speed;
s32 status;
+ s32 phy_status = IXGBE_SUCCESS;
u32 ctrl = 0;
u32 i, autoc, autoc2;
u32 curr_lms;
@@ -1059,28 +1060,29 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw
/* PHY ops must be identified and initialized prior to reset */
/* Identify PHY and related function pointers */
- status = hw->phy.ops.init(hw);
+ phy_status = hw->phy.ops.init(hw);
- if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
- goto reset_hw_out;
+ if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto mac_reset_top;
/* Setup SFP module if there is one present. */
if (hw->phy.sfp_setup_needed) {
- status = hw->mac.ops.setup_sfp(hw);
+ phy_status = hw->mac.ops.setup_sfp(hw);
hw->phy.sfp_setup_needed = FALSE;
}
- if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
- goto reset_hw_out;
+ if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto mac_reset_top;
/* Reset PHY */
if (hw->phy.reset_disable == FALSE && hw->phy.ops.reset != NULL)
hw->phy.ops.reset(hw);
+mac_reset_top:
/* remember AUTOC from before we reset */
curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
-mac_reset_top:
+mac_reset_retry:
/*
* Issue global reset to the MAC. Needs to be SW reset if link is up.
* If link reset is used when link is up, it might reset the PHY when
@@ -1120,7 +1122,7 @@ mac_reset_top:
*/
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
- goto mac_reset_top;
+ goto mac_reset_retry;
}
/*
@@ -1208,6 +1210,9 @@ mac_reset_top:
&hw->mac.wwpn_prefix);
reset_hw_out:
+ if (phy_status != IXGBE_SUCCESS)
+ status = phy_status;
+
return status;
}
Index: src/sys/dev/pci/ixgbe/ixgbe_phy.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.19 src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.20
--- src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.19 Mon Dec 16 02:50:54 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_phy.c Mon Dec 23 09:36:18 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_phy.c,v 1.19 2019/12/16 02:50:54 msaitoh Exp $ */
+/* $NetBSD: ixgbe_phy.c,v 1.20 2019/12/23 09:36:18 msaitoh Exp $ */
/******************************************************************************
SPDX-License-Identifier: BSD-3-Clause
@@ -1585,6 +1585,8 @@ s32 ixgbe_identify_sfp_module_generic(st
}
out:
+ if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+ hw->need_unsupported_sfp_recovery = true;
return status;
err_read_i2c_eeprom:
@@ -1838,6 +1840,8 @@ s32 ixgbe_identify_qsfp_module_generic(s
}
out:
+ if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+ hw->need_unsupported_sfp_recovery = true;
return status;
err_read_i2c_eeprom:
Index: src/sys/dev/pci/ixgbe/ixgbe_type.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.43 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.44
--- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.43 Fri Sep 20 09:28:37 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_type.h Mon Dec 23 09:36:18 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_type.h,v 1.43 2019/09/20 09:28:37 msaitoh Exp $ */
+/* $NetBSD: ixgbe_type.h,v 1.44 2019/12/23 09:36:18 msaitoh Exp $ */
/******************************************************************************
SPDX-License-Identifier: BSD-3-Clause
@@ -4263,6 +4263,7 @@ struct ixgbe_hw {
bool allow_unsupported_sfp;
bool wol_enabled;
bool need_crosstalk_fix;
+ bool need_unsupported_sfp_recovery;
};
#define ixgbe_call_func(hw, func, params, error) \
Index: src/sys/dev/pci/ixgbe/ixgbe_x550.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.16 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.17
--- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.16 Tue Aug 6 05:37:30 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.c Mon Dec 23 09:36:18 2019
@@ -2604,6 +2604,7 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_h
{
ixgbe_link_speed link_speed;
s32 status;
+ s32 phy_status = IXGBE_SUCCESS;
u32 ctrl = 0;
u32 i;
bool link_up = FALSE;
@@ -2623,16 +2624,16 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_h
ixgbe_set_mdio_speed(hw);
/* PHY ops must be identified and initialized prior to reset */
- status = hw->phy.ops.init(hw);
+ phy_status = hw->phy.ops.init(hw);
- if (status)
+ if (phy_status)
DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n",
status);
- if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
- status == IXGBE_ERR_PHY_ADDR_INVALID) {
+ if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
+ phy_status == IXGBE_ERR_PHY_ADDR_INVALID) {
DEBUGOUT("Returning from reset HW due to PHY init failure\n");
- return status;
+ goto mac_reset_top;
}
/* start the external PHY */
@@ -2647,12 +2648,12 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_h
/* Setup SFP module if there is one present. */
if (hw->phy.sfp_setup_needed) {
- status = hw->mac.ops.setup_sfp(hw);
+ phy_status = hw->mac.ops.setup_sfp(hw);
hw->phy.sfp_setup_needed = FALSE;
}
- if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
- return status;
+ if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto mac_reset_top;
/* Reset PHY */
if (!hw->phy.reset_disable && hw->phy.ops.reset) {
@@ -2726,6 +2727,9 @@ mac_reset_top:
if (status != IXGBE_SUCCESS)
DEBUGOUT1("Reset HW failed, STATUS = %d\n", status);
+ if (phy_status != IXGBE_SUCCESS)
+ status = phy_status;
+
return status;
}