Module Name:    src
Committed By:   martin
Date:           Tue Jan 28 11:09:27 UTC 2020

Modified Files:
        src/sys/dev/pci/ixgbe [netbsd-9]: ixgbe.c ixgbe_82598.c ixgbe_82599.c
            ixgbe_phy.c ixgbe_type.h ixgbe_x550.c

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #664):

        sys/dev/pci/ixgbe/ixgbe_82598.c: revision 1.13
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.219
        sys/dev/pci/ixgbe/ixgbe_phy.c: revision 1.20
        sys/dev/pci/ixgbe/ixgbe_x550.c: revision 1.17
        sys/dev/pci/ixgbe/ixgbe_82599.c: revision 1.22
        sys/dev/pci/ixgbe/ixgbe_type.h: revision 1.44

Add recovery code for unsupported SFP+.

Before this commit:
   If an unsupported SFP module is inserted before booting, the driver attach
   failed and there was no way to recover form it without rebooting or
   detaching/reattaching driver (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.199.2.9 -r1.199.2.10 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.12.8.1 -r1.12.8.2 src/sys/dev/pci/ixgbe/ixgbe_82598.c
cvs rdiff -u -r1.21 -r1.21.4.1 src/sys/dev/pci/ixgbe/ixgbe_82599.c
cvs rdiff -u -r1.18.4.1 -r1.18.4.2 src/sys/dev/pci/ixgbe/ixgbe_phy.c
cvs rdiff -u -r1.41.2.1 -r1.41.2.2 src/sys/dev/pci/ixgbe/ixgbe_type.h
cvs rdiff -u -r1.15.2.1 -r1.15.2.2 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.199.2.9 src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.10
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.9	Sun Jan 26 11:03:17 2020
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Tue Jan 28 11:09:27 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.199.2.9 2020/01/26 11:03:17 martin Exp $ */
+/* $NetBSD: ixgbe.c,v 1.199.2.10 2020/01/28 11:09:27 martin 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];
 
@@ -959,8 +960,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;
@@ -1129,13 +1130,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;
 	}
@@ -1168,16 +1162,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);
@@ -3896,6 +3896,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! */
@@ -3903,6 +3904,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);
@@ -4076,12 +4078,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);
@@ -4092,10 +4096,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);
@@ -4631,15 +4637,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.8.1 src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.12.8.2
--- src/sys/dev/pci/ixgbe/ixgbe_82598.c:1.12.8.1	Sun Jan 26 11:03:17 2020
+++ src/sys/dev/pci/ixgbe/ixgbe_82598.c	Tue Jan 28 11:09:27 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82598.c,v 1.12.8.1 2020/01/26 11:03:17 martin Exp $ */
+/* $NetBSD: ixgbe_82598.c,v 1.12.8.2 2020/01/28 11:09:27 martin 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.21.4.1
--- 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	Tue Jan 28 11:09:27 2020
@@ -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.21.4.1 2020/01/28 11:09:27 martin 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.18.4.1 src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.18.4.2
--- src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.18.4.1	Sun Jan 26 11:03:17 2020
+++ src/sys/dev/pci/ixgbe/ixgbe_phy.c	Tue Jan 28 11:09:27 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_phy.c,v 1.18.4.1 2020/01/26 11:03:17 martin Exp $ */
+/* $NetBSD: ixgbe_phy.c,v 1.18.4.2 2020/01/28 11:09:27 martin 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.41.2.1 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41.2.2
--- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41.2.1	Thu Sep 26 19:07:22 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_type.h	Tue Jan 28 11:09:27 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_type.h,v 1.41.2.1 2019/09/26 19:07:22 martin Exp $ */
+/* $NetBSD: ixgbe_type.h,v 1.41.2.2 2020/01/28 11:09:27 martin 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.15.2.1 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15.2.2
--- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15.2.1	Thu Sep 26 19:07:22 2019
+++ src/sys/dev/pci/ixgbe/ixgbe_x550.c	Tue Jan 28 11:09:27 2020
@@ -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;
 }
 

Reply via email to