From nobody@FreeBSD.org  Fri Sep  3 15:58:26 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 533011065742
	for <freebsd-gnats-submit@FreeBSD.org>; Fri,  3 Sep 2010 15:58:26 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 425648FC16
	for <freebsd-gnats-submit@FreeBSD.org>; Fri,  3 Sep 2010 15:58:26 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o83FwQ3X095003
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 3 Sep 2010 15:58:26 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o83FwPq7095002;
	Fri, 3 Sep 2010 15:58:25 GMT
	(envelope-from nobody)
Message-Id: <201009031558.o83FwPq7095002@www.freebsd.org>
Date: Fri, 3 Sep 2010 15:58:25 GMT
From: Andrew Boyer <aboyer@averesystems.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [ixgbe] Late cable insertion broken
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         150251
>Category:       kern
>Synopsis:       [patch] [ixgbe] Late cable insertion broken
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-net
>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:  Fri Sep 03 19:52:00 UTC 2010
>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:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: vwe 
Responsible-Changed-When: Fri Sep 3 18:58:05 UTC 2010 
Responsible-Changed-Why:  

Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=150251 
>Unformatted:
