Ejemplo n.º 1
0
static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
{
	/* Be sure we aren't looping trying to negotiate */
	if (xgbe_in_kr_mode(pdata)) {
		pdata->kr_state = XGBE_RX_ERROR;

		if (!(pdata->phy.advertising & ADVERTISED_1000baseKX_Full) &&
		    !(pdata->phy.advertising & ADVERTISED_2500baseX_Full))
			return XGBE_AN_NO_LINK;

		if (pdata->kx_state != XGBE_RX_BPA)
			return XGBE_AN_NO_LINK;
	} else {
		pdata->kx_state = XGBE_RX_ERROR;

		if (!(pdata->phy.advertising & ADVERTISED_10000baseKR_Full))
			return XGBE_AN_NO_LINK;

		if (pdata->kr_state != XGBE_RX_BPA)
			return XGBE_AN_NO_LINK;
	}

	xgbe_an73_disable(pdata);

	xgbe_switch_mode(pdata);

	xgbe_an73_restart(pdata);

	return XGBE_AN_INCOMPAT_LINK;
}
Ejemplo n.º 2
0
static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
{
	/* If we are in KR switch to KX, and vice-versa */
	if (xgbe_in_kr_mode(pdata)) {
		if (pdata->speed_set == XGBE_SPEEDSET_1000_10000)
			xgbe_gmii_mode(pdata);
		else
			xgbe_gmii_2500_mode(pdata);
	} else {
		xgbe_xgmii_mode(pdata);
	}
}
Ejemplo n.º 3
0
static void xgbe_phy_status_force(struct xgbe_prv_data *pdata)
{
	if (xgbe_in_kr_mode(pdata)) {
		pdata->phy.speed = SPEED_10000;
	} else {
		switch (pdata->speed_set) {
		case XGBE_SPEEDSET_1000_10000:
			pdata->phy.speed = SPEED_1000;
			break;

		case XGBE_SPEEDSET_2500_10000:
			pdata->phy.speed = SPEED_2500;
			break;
		}
	}
	pdata->phy.duplex = DUPLEX_FULL;
}
Ejemplo n.º 4
0
static enum xgbe_an xgbe_an73_page_received(struct xgbe_prv_data *pdata)
{
	enum xgbe_rx *state;
	unsigned long an_timeout;
	enum xgbe_an ret;

	if (!pdata->an_start) {
		pdata->an_start = jiffies;
	} else {
		an_timeout = pdata->an_start +
			     msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
		if (time_after(jiffies, an_timeout)) {
			/* Auto-negotiation timed out, reset state */
			pdata->kr_state = XGBE_RX_BPA;
			pdata->kx_state = XGBE_RX_BPA;

			pdata->an_start = jiffies;

			netif_dbg(pdata, link, pdata->netdev,
				  "CL73 AN timed out, resetting state\n");
		}
	}

	state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state
				       : &pdata->kx_state;

	switch (*state) {
	case XGBE_RX_BPA:
		ret = xgbe_an73_rx_bpa(pdata, state);
		break;

	case XGBE_RX_XNP:
		ret = xgbe_an73_rx_xnp(pdata, state);
		break;

	default:
		ret = XGBE_AN_ERROR;
	}

	return ret;
}
Ejemplo n.º 5
0
static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
					  enum xgbe_rx *state)
{
	unsigned int ad_reg, lp_reg, reg;

	*state = XGBE_RX_COMPLETE;

	/* If we're not in KR mode then we're done */
	if (!xgbe_in_kr_mode(pdata))
		return XGBE_AN_PAGE_RECEIVED;

	/* Enable/Disable FEC */
	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);

	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL);
	reg &= ~(MDIO_PMA_10GBR_FECABLE_ABLE | MDIO_PMA_10GBR_FECABLE_ERRABLE);
	if ((ad_reg & 0xc000) && (lp_reg & 0xc000))
		reg |= pdata->fec_ability;

	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg);

	/* Start KR training */
	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
	if (reg & XGBE_KR_TRAINING_ENABLE) {
		if (pdata->phy_if.phy_impl.kr_training_pre)
			pdata->phy_if.phy_impl.kr_training_pre(pdata);

		reg |= XGBE_KR_TRAINING_START;
		XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
			    reg);

		if (pdata->phy_if.phy_impl.kr_training_post)
			pdata->phy_if.phy_impl.kr_training_post(pdata);

		netif_dbg(pdata, link, pdata->netdev,
			  "KR training initiated\n");
	}

	return XGBE_AN_PAGE_RECEIVED;
}
Ejemplo n.º 6
0
static enum xgbe_an xgbe_an73_rx_bpa(struct xgbe_prv_data *pdata,
				     enum xgbe_rx *state)
{
	unsigned int link_support;
	unsigned int reg, ad_reg, lp_reg;

	/* Read Base Ability register 2 first */
	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);

	/* Check for a supported mode, otherwise restart in a different one */
	link_support = xgbe_in_kr_mode(pdata) ? 0x80 : 0x20;
	if (!(reg & link_support))
		return XGBE_AN_INCOMPAT_LINK;

	/* Check Extended Next Page support */
	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);

	return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
		(lp_reg & XGBE_XNP_NP_EXCHANGE))
	       ? xgbe_an73_tx_xnp(pdata, state)
	       : xgbe_an73_tx_training(pdata, state);
}