|
@@ -2650,6 +2650,13 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ if (nesadapter->phy_type[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(&nesadapter->phy_lock, flags);
|
|
spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
|
|
@@ -2657,6 +2664,80 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
|
|
nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;
|
|
nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void nes_recheck_link_status(struct work_struct *work)
|
|
|
|
+{
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ struct nes_device *nesdev = container_of(work, struct nes_device, work.work);
|
|
|
|
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
|
|
|
|
+ struct nes_vnic *nesvnic;
|
|
|
|
+ u32 mac_index = nesdev->mac_index;
|
|
|
|
+ u16 phy_data;
|
|
|
|
+ u16 temp_phy_data;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&nesadapter->phy_lock, flags);
|
|
|
|
+
|
|
|
|
+ /* check link status */
|
|
|
|
+ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
|
|
|
|
+ temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
|
|
|
|
+
|
|
|
|
+ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
|
|
|
|
+ nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
|
|
|
|
+ nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021);
|
|
|
|
+ phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
|
|
|
|
+
|
|
|
|
+ phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0;
|
|
|
|
+
|
|
|
|
+ nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
|
|
|
|
+ __func__, phy_data,
|
|
|
|
+ nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
|
|
|
|
+
|
|
|
|
+ if (phy_data & 0x0004) {
|
|
|
|
+ nesadapter->mac_link_down[mac_index] = 0;
|
|
|
|
+ list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
|
|
|
|
+ if (nesvnic->linkup == 0) {
|
|
|
|
+ printk(PFX "The Link is now up for port %s, netdev %p.\n",
|
|
|
|
+ nesvnic->netdev->name, nesvnic->netdev);
|
|
|
|
+ if (netif_queue_stopped(nesvnic->netdev))
|
|
|
|
+ netif_start_queue(nesvnic->netdev);
|
|
|
|
+ nesvnic->linkup = 1;
|
|
|
|
+ netif_carrier_on(nesvnic->netdev);
|
|
|
|
+
|
|
|
|
+ spin_lock(&nesvnic->port_ibevent_lock);
|
|
|
|
+ if (nesdev->iw_status == 0) {
|
|
|
|
+ nesdev->iw_status = 1;
|
|
|
|
+ nes_port_ibevent(nesvnic);
|
|
|
|
+ }
|
|
|
|
+ spin_unlock(&nesvnic->port_ibevent_lock);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ nesadapter->mac_link_down[mac_index] = 1;
|
|
|
|
+ list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
|
|
|
|
+ if (nesvnic->linkup == 1) {
|
|
|
|
+ printk(PFX "The Link is now down for port %s, netdev %p.\n",
|
|
|
|
+ nesvnic->netdev->name, nesvnic->netdev);
|
|
|
|
+ if (!(netif_queue_stopped(nesvnic->netdev)))
|
|
|
|
+ netif_stop_queue(nesvnic->netdev);
|
|
|
|
+ nesvnic->linkup = 0;
|
|
|
|
+ netif_carrier_off(nesvnic->netdev);
|
|
|
|
+
|
|
|
|
+ spin_lock(&nesvnic->port_ibevent_lock);
|
|
|
|
+ if (nesdev->iw_status == 1) {
|
|
|
|
+ nesdev->iw_status = 0;
|
|
|
|
+ nes_port_ibevent(nesvnic);
|
|
|
|
+ }
|
|
|
|
+ spin_unlock(&nesvnic->port_ibevent_lock);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (nesdev->link_recheck++ < NES_LINK_RECHECK_MAX)
|
|
|
|
+ schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);
|
|
|
|
+ else
|
|
|
|
+ nesdev->link_recheck = 0;
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
|
static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|