[ewg] [PATCH 4/4] RDMA/nes: fix incorrect SFP link status detection on driver init

Maciej Sosnowski maciej.sosnowski at intel.com
Fri Dec 3 07:53:48 PST 2010


During iw_nes initialization link status for SFP phy is always detected
as "up" regardless of real state (cable either connected or disconnected).
Add SFP phy specific link status detection to iw_nes initialization procedure.
Use link status recheck for netdev_open to detect delayed state updates.

Signed-off-by: Maciej Sosnowski <maciej.sosnowski at intel.com>
---

 .../fixes/nes_0050_init_sfp_port_state.patch       |   74 +++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/kernel_patches/fixes/nes_0050_init_sfp_port_state.patch b/kernel_patches/fixes/nes_0050_init_sfp_port_state.patch
new file mode 100644
index 0000000..91e7d86
--- /dev/null
+++ b/kernel_patches/fixes/nes_0050_init_sfp_port_state.patch
@@ -0,0 +1,74 @@
+diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
+index 9500cb0..0aaa1db 100644
+--- a/drivers/infiniband/hw/nes/nes_nic.c
++++ b/drivers/infiniband/hw/nes/nes_nic.c
+@@ -240,6 +240,15 @@ static int nes_netdev_open(struct net_de
+ 		netif_carrier_on(netdev);
+ 	}
+ 
++	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
++	if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) {
++		if (nesdev->link_recheck)
++			cancel_delayed_work(&nesdev->work);
++		nesdev->link_recheck = 1;
++		schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);
++	}
++	spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
++
+ 	spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags);
+ 	if (nesvnic->of_device_registered) {
+ 		nesdev->nesadapter->send_term_ok = 1;
+@@ -1760,8 +1769,11 @@ struct net_device *nes_netdev_init(struc
+ 	      (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
+ 	       ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
+ 		u32 u32temp;
+-		u32 link_mask;
+-		u32 link_val;
++		u32 link_mask = 0;
++		u32 link_val = 0;
++		u16 temp_phy_data;
++		u16 phy_data = 0;
++		unsigned long flags;
+ 
+ 		u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+ 				(0x200 * (nesdev->mac_index & 1)));
+@@ -1783,6 +1795,23 @@ struct net_device *nes_netdev_init(struc
+ 				link_val = 0x02020000;
+ 			}
+ 			break;
++		case NES_PHY_TYPE_SFP_D:
++			spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
++			nes_read_10G_phy_reg(nesdev,
++					     nesdev->nesadapter->phy_index[nesdev->mac_index],
++					     1, 0x9003);
++			temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++			nes_read_10G_phy_reg(nesdev,
++					     nesdev->nesadapter->phy_index[nesdev->mac_index],
++					     3, 0x0021);
++			nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++			nes_read_10G_phy_reg(nesdev,
++					     nesdev->nesadapter->phy_index[nesdev->mac_index],
++					     3, 0x0021);
++			phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++			spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
++			phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
++			break;
+ 		default:
+ 			link_mask = 0x0f1f0000;
+ 			link_val = 0x0f0f0000;
+@@ -1793,8 +1822,13 @@ struct net_device *nes_netdev_init(struc
+ 					   NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+ 					   (0x200 * (nesdev->mac_index & 1)));
+ 
+-		if ((u32temp & link_mask) == link_val)
+-			nesvnic->linkup = 1;
++		if (phy_type == NES_PHY_TYPE_SFP_D) {
++			if (phy_data & 0x0004)
++				nesvnic->linkup = 1;
++		} else {
++			if ((u32temp & link_mask) == link_val)
++				nesvnic->linkup = 1;
++		}
+ 
+ 		/* clear the MAC interrupt status, assumes direct logical to physical mapping */
+ 		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));




More information about the ewg mailing list