Module Name:    src
Committed By:   msaitoh
Date:           Mon Aug 31 06:20:06 UTC 2020

Modified Files:
        src/sys/dev/pci/ixgbe: ixgbe.c ixgbe_phy.c

Log Message:
 Fix 82598 SFP+ problems.

 On 82598, SFP+'s MOD_ABS isn't connected to the MAC's GPIO pin, so we can't
call ixgbe_sfp_cage_full(). Always issue TASK_MOD from ixgbe_handle_timer()
on 82598.

 Fix ixgbe_identify_sfp_module_generic() for ixgbe_phy_nl. In the driver,
hw->phy.type sometimes be compared with ixgbe_phy_nl.
In ixgbe_identify_sfp_module_generic(), hw->phy.type may be overridden with
another value. For ixgbe_phy_nl, some code don't override phy.type but others
were not. Make it consistently keep ixgbe_phy_nl. This change fixes a problem
that ixgbe_is_sfp() change the return value true to false when any SFP+
devices are connected to the cage on 82598 and never recover from it.

 Don't schedule MSF(multi speed fiber) task from ixgbe_handle_mod() on 82598.
This task is only for devices which support multi speed fiber and 82598
doesn't support it. Before ixgbe.c rev. 1.237, ixgbe_handle_mod() isn't
called on 82598 because 82598 has no SFP+ module insertion/removal interrupt.
ixgbe.c rev. 1.237 changed to call the function via timer on 82598.
This change fixes a bug that 82598 DA interface's link flaps.


To generate a diff of this commit:
cvs rdiff -u -r1.248 -r1.249 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.21 -r1.22 src/sys/dev/pci/ixgbe/ixgbe_phy.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.248 src/sys/dev/pci/ixgbe/ixgbe.c:1.249
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.248	Thu Aug 27 04:54:43 2020
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Mon Aug 31 06:20:06 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.248 2020/08/27 04:54:43 msaitoh Exp $ */
+/* $NetBSD: ixgbe.c,v 1.249 2020/08/31 06:20:06 msaitoh Exp $ */
 
 /******************************************************************************
 
@@ -4506,11 +4506,26 @@ ixgbe_handle_timer(struct work *wk, void
 
 	/* Check for pluggable optics */
 	if (ixgbe_is_sfp(hw)) {
-		bool was_full = hw->phy.sfp_type != ixgbe_sfp_type_not_present;
-		bool is_full = ixgbe_sfp_cage_full(adapter);
+		bool sched_mod_task = false;
 
-		/* do probe if cage state changed */
-		if (was_full ^ is_full) {
+		if (hw->mac.type == ixgbe_mac_82598EB) {
+			/*
+			 * On 82598EB, SFP+'s MOD_ABS pin is not connected to
+			 * any GPIP(SDP). So just schedule TASK_MOD.
+			 */
+			sched_mod_task = true;
+		} else {
+			bool was_full, is_full;
+
+			was_full =
+			    hw->phy.sfp_type != ixgbe_sfp_type_not_present;
+			is_full = ixgbe_sfp_cage_full(adapter);
+
+			/* Do probe if cage state changed */
+			if (was_full ^ is_full)
+				sched_mod_task = true;
+		}
+		if (sched_mod_task) {
 			atomic_or_32(&adapter->task_requests,
 			    IXGBE_REQUEST_TASK_MOD);
 			ixgbe_schedule_admin_tasklet(adapter);
@@ -4683,8 +4698,12 @@ ixgbe_handle_mod(void *context)
 	struct adapter	*adapter = context;
 	struct ixgbe_hw *hw = &adapter->hw;
 	device_t	dev = adapter->dev;
+	enum ixgbe_sfp_type last_sfp_type;
 	u32		err, cage_full = 0;
+	bool		last_unsupported_sfp_recovery;
 
+	last_sfp_type = hw->phy.sfp_type;
+	last_unsupported_sfp_recovery = hw->need_unsupported_sfp_recovery;
 	++adapter->mod_workev.ev_count;
 	if (adapter->hw.need_crosstalk_fix) {
 		switch (hw->mac.type) {
@@ -4711,8 +4730,9 @@ ixgbe_handle_mod(void *context)
 
 	err = hw->phy.ops.identify_sfp(hw);
 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-		device_printf(dev,
-		    "Unsupported SFP+ module type was detected.\n");
+		if (last_unsupported_sfp_recovery == false)
+			device_printf(dev,
+			    "Unsupported SFP+ module type was detected.\n");
 		goto out;
 	}
 
@@ -4726,7 +4746,10 @@ ixgbe_handle_mod(void *context)
 		 * approach.
 		 */
 		ixgbe_init_locked(adapter);
-	} else {
+	} else if ((hw->phy.sfp_type != ixgbe_sfp_type_not_present) &&
+	    (hw->phy.sfp_type != last_sfp_type)) {
+		/* A module is inserted and changed. */
+
 		if (hw->mac.type == ixgbe_mac_82598EB)
 			err = hw->phy.ops.reset(hw);
 		else {
@@ -4751,7 +4774,14 @@ out:
 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
 	IXGBE_CORE_LOCK(adapter);
 
-	atomic_or_32(&adapter->task_requests, IXGBE_REQUEST_TASK_MSF);
+	/*
+	 * Don't shedule MSF event if the chip is 82598. 82598 doesn't support
+	 * MSF. At least, calling ixgbe_handle_msf on 82598 DA makes the link
+	 * flap because the function call setup_link().
+	 */
+	if (hw->mac.type != ixgbe_mac_82598EB)
+		atomic_or_32(&adapter->task_requests, IXGBE_REQUEST_TASK_MSF);
+
 	/*
 	 * Don't call ixgbe_schedule_admin_tasklet() because we are on
 	 * the workqueue now.

Index: src/sys/dev/pci/ixgbe/ixgbe_phy.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.21 src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.22
--- src/sys/dev/pci/ixgbe/ixgbe_phy.c:1.21	Fri Apr 17 02:21:25 2020
+++ src/sys/dev/pci/ixgbe/ixgbe_phy.c	Mon Aug 31 06:20:06 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_phy.c,v 1.21 2020/04/17 02:21:25 msaitoh Exp $ */
+/* $NetBSD: ixgbe_phy.c,v 1.22 2020/08/31 06:20:06 msaitoh Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -1356,7 +1356,8 @@ s32 ixgbe_identify_sfp_module_generic(st
 		goto err_read_i2c_eeprom;
 
 	if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
-		hw->phy.type = ixgbe_phy_sfp_unsupported;
+		if (hw->phy.type != ixgbe_phy_nl)
+			hw->phy.type = ixgbe_phy_sfp_unsupported;
 		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
 	} else {
 		status = hw->phy.ops.read_i2c_eeprom(hw,
@@ -1529,12 +1530,17 @@ s32 ixgbe_identify_sfp_module_generic(st
 
 		/* Allow any DA cable vendor */
 		if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
-			IXGBE_SFF_DA_ACTIVE_CABLE)) {
+		    IXGBE_SFF_DA_ACTIVE_CABLE)) {
+			status = IXGBE_SUCCESS;
+
+			/* Keep phy.type for ixgbe_phy_nl */
+			if (hw->phy.type == ixgbe_phy_nl)
+				goto out;
+
 			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 				hw->phy.type = ixgbe_phy_sfp_passive_unknown;
 			else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
 				hw->phy.type = ixgbe_phy_sfp_active_unknown;
-			status = IXGBE_SUCCESS;
 			goto out;
 		}
 
@@ -1546,7 +1552,8 @@ s32 ixgbe_identify_sfp_module_generic(st
 		      hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1 ||
 		      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
 		      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
-			hw->phy.type = ixgbe_phy_sfp_unsupported;
+			if (hw->phy.type != ixgbe_phy_nl)
+				hw->phy.type = ixgbe_phy_sfp_unsupported;
 			status = IXGBE_ERR_SFP_NOT_SUPPORTED;
 			goto out;
 		}
@@ -1574,8 +1581,9 @@ s32 ixgbe_identify_sfp_module_generic(st
 					status = IXGBE_SUCCESS;
 				} else {
 					DEBUGOUT("SFP+ module not supported\n");
-					hw->phy.type =
-						ixgbe_phy_sfp_unsupported;
+					if (hw->phy.type != ixgbe_phy_nl)
+						hw->phy.type =
+						    ixgbe_phy_sfp_unsupported;
 					status = IXGBE_ERR_SFP_NOT_SUPPORTED;
 				}
 			}
@@ -1585,7 +1593,7 @@ s32 ixgbe_identify_sfp_module_generic(st
 	}
 
 out:
-	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
 		hw->need_unsupported_sfp_recovery = true;
 	return status;
 

Reply via email to