diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 9e02f8864593..3b824970f1a6 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1191,6 +1191,67 @@ static void alx_netif_start(struct alx_priv *alx) netif_carrier_on(alx->dev); } +static void alx_check_link(struct alx_priv *alx) +{ + struct alx_hw *hw = &alx->hw; + unsigned long flags; + int old_speed; + int err; + + ASSERT_RTNL(); + + /* clear PHY internal interrupt status, otherwise the main + * interrupt status will be asserted forever + */ + alx_clear_phy_intr(hw); + + old_speed = hw->link_speed; + err = alx_read_phy_link(hw); + if (err < 0) + goto reset; + + spin_lock_irqsave(&alx->irq_lock, flags); + alx->int_mask |= ALX_ISR_PHY; + alx_write_mem32(hw, ALX_IMR, alx->int_mask); + spin_unlock_irqrestore(&alx->irq_lock, flags); + + if (old_speed == hw->link_speed) + return; + + if (hw->link_speed != SPEED_UNKNOWN) { + netif_info(alx, link, alx->dev, + "NIC Up: %s\n", alx_speed_desc(hw)); + alx_post_phy_link(hw); + alx_enable_aspm(hw, true, true); + alx_start_mac(hw); + + if (old_speed == SPEED_UNKNOWN) + alx_netif_start(alx); + } else { + /* link is now down */ + alx_netif_stop(alx); + netif_info(alx, link, alx->dev, "Link Down\n"); + err = alx_reset_mac(hw); + if (err) + goto reset; + alx_irq_disable(alx); + + /* MAC reset causes all HW settings to be lost, restore all */ + err = alx_reinit_rings(alx); + if (err) + goto reset; + alx_configure(alx); + alx_enable_aspm(hw, false, true); + alx_post_phy_link(hw); + alx_irq_enable(alx); + } + + return; + +reset: + alx_schedule_reset(alx); +} + static int __alx_open(struct alx_priv *alx, bool resume) { int err; @@ -1236,7 +1297,7 @@ static int __alx_open(struct alx_priv *alx, bool resume) if (!resume) netif_tx_start_all_queues(alx->dev); - alx_schedule_link_check(alx); + alx_check_link(alx); return 0; out_free_rings: @@ -1277,65 +1338,6 @@ static const char *alx_speed_desc(struct alx_hw *hw) } } -static void alx_check_link(struct alx_priv *alx) -{ - struct alx_hw *hw = &alx->hw; - unsigned long flags; - int old_speed; - int err; - - /* clear PHY internal interrupt status, otherwise the main - * interrupt status will be asserted forever - */ - alx_clear_phy_intr(hw); - - old_speed = hw->link_speed; - err = alx_read_phy_link(hw); - if (err < 0) - goto reset; - - spin_lock_irqsave(&alx->irq_lock, flags); - alx->int_mask |= ALX_ISR_PHY; - alx_write_mem32(hw, ALX_IMR, alx->int_mask); - spin_unlock_irqrestore(&alx->irq_lock, flags); - - if (old_speed == hw->link_speed) - return; - - if (hw->link_speed != SPEED_UNKNOWN) { - netif_info(alx, link, alx->dev, - "NIC Up: %s\n", alx_speed_desc(hw)); - alx_post_phy_link(hw); - alx_enable_aspm(hw, true, true); - alx_start_mac(hw); - - if (old_speed == SPEED_UNKNOWN) - alx_netif_start(alx); - } else { - /* link is now down */ - alx_netif_stop(alx); - netif_info(alx, link, alx->dev, "Link Down\n"); - err = alx_reset_mac(hw); - if (err) - goto reset; - alx_irq_disable(alx); - - /* MAC reset causes all HW settings to be lost, restore all */ - err = alx_reinit_rings(alx); - if (err) - goto reset; - alx_configure(alx); - alx_enable_aspm(hw, false, true); - alx_post_phy_link(hw); - alx_irq_enable(alx); - } - - return; - -reset: - alx_schedule_reset(alx); -} - static int alx_open(struct net_device *netdev) { return __alx_open(netdev_priv(netdev), false);