Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 843276ad authored by Maciej Sosnowski's avatar Maciej Sosnowski Committed by Roland Dreier
Browse files

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: default avatarMaciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 5f61b2c6
Loading
Loading
Loading
Loading
+39 −4
Original line number Diff line number Diff line
@@ -241,6 +241,15 @@ static int nes_netdev_open(struct net_device *netdev)
		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;
@@ -1782,8 +1791,11 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
	      (((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)));
@@ -1805,6 +1817,23 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
				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;
@@ -1814,8 +1843,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
		u32temp = nes_read_indexed(nesdev,
					   NES_IDX_PHY_PCS_CONTROL_STATUS0 +
					   (0x200 * (nesdev->mac_index & 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));