atl1c: improve link detection reliability on Mikrotik 10/25G NIC
Mikrotik 10/25G NIC emulates the MDIO accesses, but the emulation is not 100% reliable - the MDIO ops occasionally can timeout. This adds a reliable way of detecting link on Mikrotik 10/25G NIC. Signed-off-by: Gatis Peisenieks <gatis@mikrotik.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b039000950
commit
ea0fbd05d7
|
@ -636,6 +636,23 @@ int atl1c_phy_init(struct atl1c_hw *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool atl1c_get_link_status(struct atl1c_hw *hw)
|
||||
{
|
||||
u16 phy_data;
|
||||
|
||||
if (hw->nic_type == athr_mt) {
|
||||
u32 spd;
|
||||
|
||||
AT_READ_REG(hw, REG_MT_SPEED, &spd);
|
||||
return !!spd;
|
||||
}
|
||||
|
||||
/* MII_BMSR must be read twice */
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
return !!(phy_data & BMSR_LSTATUS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detects the current speed and duplex settings of the hardware.
|
||||
*
|
||||
|
@ -695,15 +712,12 @@ int atl1c_phy_to_ps_link(struct atl1c_hw *hw)
|
|||
int ret = 0;
|
||||
u16 autoneg_advertised = ADVERTISED_10baseT_Half;
|
||||
u16 save_autoneg_advertised;
|
||||
u16 phy_data;
|
||||
u16 mii_lpa_data;
|
||||
u16 speed = SPEED_0;
|
||||
u16 duplex = FULL_DUPLEX;
|
||||
int i;
|
||||
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
if (phy_data & BMSR_LSTATUS) {
|
||||
if (atl1c_get_link_status(hw)) {
|
||||
atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data);
|
||||
if (mii_lpa_data & LPA_10FULL)
|
||||
autoneg_advertised = ADVERTISED_10baseT_Full;
|
||||
|
@ -726,9 +740,7 @@ int atl1c_phy_to_ps_link(struct atl1c_hw *hw)
|
|||
if (mii_lpa_data) {
|
||||
for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
|
||||
mdelay(100);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
if (phy_data & BMSR_LSTATUS) {
|
||||
if (atl1c_get_link_status(hw)) {
|
||||
if (atl1c_get_speed_and_duplex(hw, &speed,
|
||||
&duplex) != 0)
|
||||
dev_dbg(&pdev->dev,
|
||||
|
|
|
@ -26,6 +26,7 @@ void atl1c_phy_disable(struct atl1c_hw *hw);
|
|||
void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr);
|
||||
int atl1c_phy_reset(struct atl1c_hw *hw);
|
||||
int atl1c_read_mac_addr(struct atl1c_hw *hw);
|
||||
bool atl1c_get_link_status(struct atl1c_hw *hw);
|
||||
int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
|
||||
u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr);
|
||||
void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value);
|
||||
|
|
|
@ -232,15 +232,14 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter)
|
|||
struct pci_dev *pdev = adapter->pdev;
|
||||
int err;
|
||||
unsigned long flags;
|
||||
u16 speed, duplex, phy_data;
|
||||
u16 speed, duplex;
|
||||
bool link;
|
||||
|
||||
spin_lock_irqsave(&adapter->mdio_lock, flags);
|
||||
/* MII_BMSR must read twise */
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
|
||||
link = atl1c_get_link_status(hw);
|
||||
spin_unlock_irqrestore(&adapter->mdio_lock, flags);
|
||||
|
||||
if ((phy_data & BMSR_LSTATUS) == 0) {
|
||||
if (!link) {
|
||||
/* link down */
|
||||
netif_carrier_off(netdev);
|
||||
hw->hibernate = true;
|
||||
|
@ -284,16 +283,13 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
|
|||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct pci_dev *pdev = adapter->pdev;
|
||||
u16 phy_data;
|
||||
u16 link_up;
|
||||
bool link;
|
||||
|
||||
spin_lock(&adapter->mdio_lock);
|
||||
atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
|
||||
atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
|
||||
link = atl1c_get_link_status(&adapter->hw);
|
||||
spin_unlock(&adapter->mdio_lock);
|
||||
link_up = phy_data & BMSR_LSTATUS;
|
||||
/* notify upper layer link down ASAP */
|
||||
if (!link_up) {
|
||||
if (!link) {
|
||||
if (netif_carrier_ok(netdev)) {
|
||||
/* old link state: Up */
|
||||
netif_carrier_off(netdev);
|
||||
|
|
Loading…
Reference in New Issue