static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata) { unsigned long link_timeout; link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ); if (time_after(jiffies, link_timeout)) { netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n"); xgbe_phy_config_aneg(pdata); } }
static void xgbe_phy_status(struct xgbe_prv_data *pdata) { unsigned int link_aneg; int an_restart; if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) { netif_carrier_off(pdata->netdev); pdata->phy.link = 0; goto adjust_link; } link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE); pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata, &an_restart); if (an_restart) { xgbe_phy_config_aneg(pdata); return; } if (pdata->phy.link) { if (link_aneg && !xgbe_phy_aneg_done(pdata)) { xgbe_check_link_timeout(pdata); return; } xgbe_phy_status_result(pdata); if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) clear_bit(XGBE_LINK_INIT, &pdata->dev_state); netif_carrier_on(pdata->netdev); } else { if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) { xgbe_check_link_timeout(pdata); if (link_aneg) return; } xgbe_phy_status_result(pdata); netif_carrier_off(pdata->netdev); } adjust_link: xgbe_phy_adjust_link(pdata); }
static int xgbe_phy_start(struct xgbe_prv_data *pdata) { struct net_device *netdev = pdata->netdev; int ret; netif_dbg(pdata, link, pdata->netdev, "starting PHY\n"); ret = devm_request_irq(pdata->dev, pdata->an_irq, xgbe_an_isr, 0, pdata->an_name, pdata); if (ret) { netdev_err(netdev, "phy irq request failed\n"); return ret; } /* Set initial mode - call the mode setting routines * directly to insure we are properly configured */ if (xgbe_use_xgmii_mode(pdata)) { xgbe_xgmii_mode(pdata); } else if (xgbe_use_gmii_mode(pdata)) { xgbe_gmii_mode(pdata); } else if (xgbe_use_gmii_2500_mode(pdata)) { xgbe_gmii_2500_mode(pdata); } else { ret = -EINVAL; goto err_irq; } /* Set up advertisement registers based on current settings */ xgbe_an_init(pdata); /* Enable auto-negotiation interrupts */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07); return xgbe_phy_config_aneg(pdata); err_irq: devm_free_irq(pdata->dev, pdata->an_irq, pdata); return ret; }
static int xgbe_phy_start(struct xgbe_prv_data *pdata) { struct net_device *netdev = pdata->netdev; int ret; netif_dbg(pdata, link, pdata->netdev, "starting PHY\n"); ret = pdata->phy_if.phy_impl.start(pdata); if (ret) return ret; /* If we have a separate AN irq, enable it */ if (pdata->dev_irq != pdata->an_irq) { ret = devm_request_irq(pdata->dev, pdata->an_irq, xgbe_an_isr, 0, pdata->an_name, pdata); if (ret) { netdev_err(netdev, "phy irq request failed\n"); goto err_stop; } } /* Set initial mode - call the mode setting routines * directly to insure we are properly configured */ if (xgbe_use_mode(pdata, XGBE_MODE_KR)) { xgbe_kr_mode(pdata); } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) { xgbe_kx_2500_mode(pdata); } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) { xgbe_kx_1000_mode(pdata); } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) { xgbe_sfi_mode(pdata); } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) { xgbe_x_mode(pdata); } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) { xgbe_sgmii_1000_mode(pdata); } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) { xgbe_sgmii_100_mode(pdata); } else { ret = -EINVAL; goto err_irq; } /* Indicate the PHY is up and running */ pdata->phy_started = 1; xgbe_an_init(pdata); xgbe_an_enable_interrupts(pdata); return xgbe_phy_config_aneg(pdata); err_irq: if (pdata->dev_irq != pdata->an_irq) devm_free_irq(pdata->dev, pdata->an_irq, pdata); err_stop: pdata->phy_if.phy_impl.stop(pdata); return ret; }