[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