Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Sep 2010 15:58:25 GMT
From:      Andrew Boyer <aboyer@averesystems.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/150251: [ixgbe] Late cable insertion broken
Message-ID:  <201009031558.o83FwPq7095002@www.freebsd.org>
Resent-Message-ID: <201009031600.o83G07RZ040500@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         150251
>Category:       misc
>Synopsis:       [ixgbe] Late cable insertion broken
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 03 16:00:07 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Andrew Boyer
>Release:        7.1p3
>Organization:
Avere Systems
>Environment:
N/A
>Description:
On an 82599 card, the PHY type is not known until the SFP+ module is connected.  If no module is installed when the driver loads, the PHY type will be set to ixgbe_phy_none in ixgbe_identify_phy_82599().  Once it is set there, it will never be re-set, even after a cable is plugged in.  SFP+ modules which require initialization won't get it.

The detection logic in ixgbe_sfp_probe() won't do anything unless the PHY type is set to ixgbe_phy_nl, so it works on 82598 cards but not on 82599 cards.

>How-To-Repeat:
Install an 82599 card but no SFP+ module.  Boot the system, then install a cable (copper or optical).
>Fix:
Add PHY detection logic to ixgbe_handle_mod().
Add locking to ixgbe_handle_mod() and ixgbe_handle_msf() since PHY detection sometimes fails without it.
Since mod_task will call msf_task if necessary, simplify logic in ixgbe_config_link().

Patch attached with submission follows:

--- ixgbe.c	2010-09-03 11:30:17.000000000 -0400
+++ ixgbe.c	2010-09-03 11:38:03.000000000 -0400
@@ -2448,11 +2448,7 @@
 	sfp = ixgbe_is_sfp(hw);
 
 	if (sfp) { 
-		if (hw->phy.multispeed_fiber) {
-			hw->mac.ops.setup_sfp(hw);
-			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
-		} else
-			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+		taskqueue_enqueue(adapter->tq, &adapter->mod_task);
 	} else {
 		if (hw->mac.ops.check_link)
 			err = ixgbe_check_link(hw, &autoneg,
@@ -4654,22 +4650,67 @@
 {
 	struct adapter  *adapter = context;
 	struct ixgbe_hw *hw = &adapter->hw;
+	enum ixgbe_phy_type orig_type = hw->phy.type;
 	device_t	dev = adapter->dev;
 	u32 err;
 
+	IXGBE_CORE_LOCK(adapter);
+
+	/* Check to see if the PHY type changed */
+	if (hw->phy.ops.identify) {
+		hw->phy.type = ixgbe_phy_unknown;
+		hw->phy.ops.identify(hw);
+	}
+
+	if (hw->phy.type != orig_type) {
+		device_printf(dev, "Detected phy_type %d\n", hw->phy.type);
+
+		if (hw->phy.type == ixgbe_phy_none) {
+			hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+			goto out;
+		}
+
+		/* Try to do the initialization that was skipped before */
+		if (hw->phy.ops.init)
+			hw->phy.ops.init(hw);
+		if (hw->phy.ops.reset)
+			hw->phy.ops.reset(hw);
+	}
+
 	err = hw->phy.ops.identify_sfp(hw);
 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
 		device_printf(dev,
 		    "Unsupported SFP+ module type was detected.\n");
-		return;
+		goto out;
 	}
 	err = hw->mac.ops.setup_sfp(hw);
 	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
 		device_printf(dev,
 		    "Setup failure - unsupported SFP+ module type.\n");
-		return;
+		goto out;
 	}
-	taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+
+	if (hw->phy.multispeed_fiber)
+		taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+
+ out:
+	/* Update media type */
+	switch (hw->mac.ops.get_media_type(hw)) {
+	case ixgbe_media_type_fiber:
+		adapter->optics = IFM_10G_SR;
+		break;
+	case ixgbe_media_type_copper:
+		adapter->optics = IFM_10G_TWINAX;
+		break;
+	case ixgbe_media_type_cx4:
+		adapter->optics = IFM_10G_CX4;
+		break;
+	default:
+		adapter->optics = 0;
+		break;
+	}
+
+	IXGBE_CORE_UNLOCK(adapter);
 	return;
 }
 
@@ -4685,6 +4726,8 @@
 	u32 autoneg;
 	bool negotiate;
 
+	IXGBE_CORE_LOCK(adapter);
+
 	autoneg = hw->phy.autoneg_advertised;
 	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
 		hw->mac.ops.get_link_capabilities(hw, &autoneg, &negotiate);
@@ -4694,6 +4737,8 @@
 	ixgbe_check_link(&adapter->hw, &speed, &adapter->link_up, 0);
        	ixgbe_update_link_status(adapter);
 #endif
+
+	IXGBE_CORE_UNLOCK(adapter);
 	return;
 }
 


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009031558.o83FwPq7095002>