예제 #1
0
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);
	}
}
예제 #2
0
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);
}
예제 #3
0
파일: xgbe-mdio.c 프로젝트: DenisLug/mptcp
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;
}
예제 #4
0
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;
}