diff options
| author | Maciej Sosnowski <maciej.sosnowski@intel.com> | 2010-11-24 12:29:54 -0500 |
|---|---|---|
| committer | Roland Dreier <rolandd@cisco.com> | 2011-01-16 16:23:35 -0500 |
| commit | 843276ad985cb59212ceb70d989474521ff516f6 (patch) | |
| tree | d8c80eb0e35533735e219dc94d5ea43bcde6cd6a /drivers/infiniband/hw/nes | |
| parent | 5f61b2c6939bb6d26393df15765bc3cb260db063 (diff) | |
RDMA/nes: Fix incorrect SFP+ link status detection on driver init
During iw_nes initialization the 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 the
iw_nes initialization procedure. Use link status recheck for
netdev_open to detect delayed state updates.
Signed-off-by: Maciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/nes')
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_nic.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 81052fbcd9ba..2c9c1933bbe3 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c | |||
| @@ -241,6 +241,15 @@ static int nes_netdev_open(struct net_device *netdev) | |||
| 241 | netif_carrier_on(netdev); | 241 | netif_carrier_on(netdev); |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); | ||
| 245 | if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) { | ||
| 246 | if (nesdev->link_recheck) | ||
| 247 | cancel_delayed_work(&nesdev->work); | ||
| 248 | nesdev->link_recheck = 1; | ||
| 249 | schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY); | ||
| 250 | } | ||
| 251 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
| 252 | |||
| 244 | spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags); | 253 | spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags); |
| 245 | if (nesvnic->of_device_registered) { | 254 | if (nesvnic->of_device_registered) { |
| 246 | nesdev->nesadapter->send_term_ok = 1; | 255 | nesdev->nesadapter->send_term_ok = 1; |
| @@ -1782,8 +1791,11 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
| 1782 | (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) || | 1791 | (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) || |
| 1783 | ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) { | 1792 | ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) { |
| 1784 | u32 u32temp; | 1793 | u32 u32temp; |
| 1785 | u32 link_mask; | 1794 | u32 link_mask = 0; |
| 1786 | u32 link_val; | 1795 | u32 link_val = 0; |
| 1796 | u16 temp_phy_data; | ||
| 1797 | u16 phy_data = 0; | ||
| 1798 | unsigned long flags; | ||
| 1787 | 1799 | ||
| 1788 | u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + | 1800 | u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + |
| 1789 | (0x200 * (nesdev->mac_index & 1))); | 1801 | (0x200 * (nesdev->mac_index & 1))); |
| @@ -1805,6 +1817,23 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
| 1805 | link_val = 0x02020000; | 1817 | link_val = 0x02020000; |
| 1806 | } | 1818 | } |
| 1807 | break; | 1819 | break; |
| 1820 | case NES_PHY_TYPE_SFP_D: | ||
| 1821 | spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); | ||
| 1822 | nes_read_10G_phy_reg(nesdev, | ||
| 1823 | nesdev->nesadapter->phy_index[nesdev->mac_index], | ||
| 1824 | 1, 0x9003); | ||
| 1825 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
| 1826 | nes_read_10G_phy_reg(nesdev, | ||
| 1827 | nesdev->nesadapter->phy_index[nesdev->mac_index], | ||
| 1828 | 3, 0x0021); | ||
| 1829 | nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
| 1830 | nes_read_10G_phy_reg(nesdev, | ||
| 1831 | nesdev->nesadapter->phy_index[nesdev->mac_index], | ||
| 1832 | 3, 0x0021); | ||
| 1833 | phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
| 1834 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
| 1835 | phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0; | ||
| 1836 | break; | ||
| 1808 | default: | 1837 | default: |
| 1809 | link_mask = 0x0f1f0000; | 1838 | link_mask = 0x0f1f0000; |
| 1810 | link_val = 0x0f0f0000; | 1839 | link_val = 0x0f0f0000; |
| @@ -1814,8 +1843,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
| 1814 | u32temp = nes_read_indexed(nesdev, | 1843 | u32temp = nes_read_indexed(nesdev, |
| 1815 | NES_IDX_PHY_PCS_CONTROL_STATUS0 + | 1844 | NES_IDX_PHY_PCS_CONTROL_STATUS0 + |
| 1816 | (0x200 * (nesdev->mac_index & 1))); | 1845 | (0x200 * (nesdev->mac_index & 1))); |
| 1817 | if ((u32temp & link_mask) == link_val) | 1846 | |
| 1818 | nesvnic->linkup = 1; | 1847 | if (phy_type == NES_PHY_TYPE_SFP_D) { |
| 1848 | if (phy_data & 0x0004) | ||
| 1849 | nesvnic->linkup = 1; | ||
| 1850 | } else { | ||
| 1851 | if ((u32temp & link_mask) == link_val) | ||
| 1852 | nesvnic->linkup = 1; | ||
| 1853 | } | ||
| 1819 | 1854 | ||
| 1820 | /* clear the MAC interrupt status, assumes direct logical to physical mapping */ | 1855 | /* clear the MAC interrupt status, assumes direct logical to physical mapping */ |
| 1821 | u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); | 1856 | u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); |
