コード例 #1
0
ファイル: tenxpress.c プロジェクト: 119-org/hi3518-osdrv
static int tenxpress_phy_reconfigure(struct efx_nic *efx)
{
	struct tenxpress_phy_data *phy_data = efx->phy_data;
	bool phy_mode_change, loop_reset;

	if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
		phy_data->phy_mode = efx->phy_mode;
		return 0;
	}

	phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
			   phy_data->phy_mode != PHY_MODE_NORMAL);
	loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, LOOPBACKS_EXTERNAL(efx)) ||
		      LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));

	if (loop_reset || phy_mode_change) {
		tenxpress_special_reset(efx);
		falcon_reset_xaui(efx);
	}

	tenxpress_low_power(efx);
	efx_mdio_transmit_disable(efx);
	efx_mdio_phy_reconfigure(efx);
	tenxpress_ext_loopback(efx);
	efx_mdio_an_reconfigure(efx);

	phy_data->loopback_mode = efx->loopback_mode;
	phy_data->phy_mode = efx->phy_mode;

	return 0;
}
コード例 #2
0
static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
{
	int rc = 0, rc2, i, ctrl_reg, res_reg;

	/* Initialise cable diagnostic results to unknown failure */
	for (i = 1; i < 9; ++i)
		results[i] = -1;

	/* Run cable diagnostics; wait up to 5 seconds for them to complete.
	 * A cable fault is not a self-test failure, but a timeout is. */
	ctrl_reg = ((1 << CDIAG_CTRL_IMMED_LBN) |
		    (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN));
	if (flags & ETH_TEST_FL_OFFLINE) {
		/* Break the link in order to run full diagnostics.  We
		 * must reset the PHY to resume normal service. */
		ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN);
	}
	efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG,
		       ctrl_reg);
	i = 0;
	while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) &
	       (1 << CDIAG_CTRL_IN_PROG_LBN)) {
		if (++i == 50) {
			rc = -ETIMEDOUT;
			goto out;
		}
		msleep(100);
	}
	res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG);
	for (i = 0; i < 4; i++) {
		int pair_res =
			(res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
			& ((1 << CDIAG_RES_WIDTH) - 1);
		int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD,
					    PMA_PMD_CDIAG_LEN_REG + i);
		if (pair_res == CDIAG_RES_OK)
			results[1 + i] = 1;
		else if (pair_res == CDIAG_RES_INVALID)
			results[1 + i] = -1;
		else
			results[1 + i] = -pair_res;
		if (pair_res != CDIAG_RES_INVALID &&
		    pair_res != CDIAG_RES_OPEN &&
		    len_reg != 0xffff)
			results[5 + i] = len_reg;
	}

out:
	if (flags & ETH_TEST_FL_OFFLINE) {
		/* Reset, running the BIST and then resuming normal service. */
		rc2 = tenxpress_special_reset(efx);
		results[0] = rc2 ? -1 : 1;
		if (!rc)
			rc = rc2;

		efx_mdio_an_reconfigure(efx);
	}

	return rc;
}
コード例 #3
0
static void tenxpress_phy_reconfigure(struct efx_nic *efx)
{
	struct tenxpress_phy_data *phy_data = efx->phy_data;
	struct ethtool_cmd ecmd;
	bool phy_mode_change, loop_reset;

	if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
		phy_data->phy_mode = efx->phy_mode;
		return;
	}

	tenxpress_low_power(efx);

	phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
			   phy_data->phy_mode != PHY_MODE_NORMAL);
	loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
		      LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));

	if (loop_reset || phy_mode_change) {
		int rc;

		efx->phy_op->get_settings(efx, &ecmd);

		if (loop_reset || phy_mode_change) {
			tenxpress_special_reset(efx);

			/* Reset XAUI if we were in 10G, and are staying
			 * in 10G. If we're moving into and out of 10G
			 * then xaui will be reset anyway */
			if (EFX_IS10G(efx))
				falcon_reset_xaui(efx);
		}

		rc = efx->phy_op->set_settings(efx, &ecmd);
		WARN_ON(rc);
	}

	mdio_clause45_transmit_disable(efx);
	mdio_clause45_phy_reconfigure(efx);
	tenxpress_ext_loopback(efx);

	phy_data->loopback_mode = efx->loopback_mode;
	phy_data->phy_mode = efx->phy_mode;

	if (efx->phy_type == PHY_TYPE_SFX7101) {
		efx->link_speed = 10000;
		efx->link_fd = true;
		efx->link_up = sfx7101_link_ok(efx);
	} else {
		efx->phy_op->get_settings(efx, &ecmd);
		efx->link_speed = ecmd.speed;
		efx->link_fd = ecmd.duplex == DUPLEX_FULL;
		efx->link_up = sft9001_link_ok(efx, &ecmd);
	}
	efx->link_fc = mdio_clause45_get_pause(efx);
}
コード例 #4
0
static int
sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
{
	int rc;

	if (!(flags & ETH_TEST_FL_OFFLINE))
		return 0;

	/* BIST is automatically run after a special software reset */
	rc = tenxpress_special_reset(efx);
	results[0] = rc ? -1 : 1;
	return rc;
}
コード例 #5
0
static int
sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
{
	int rc;

	if (!(flags & ETH_TEST_FL_OFFLINE))
		return 0;

	
	rc = tenxpress_special_reset(efx);
	results[0] = rc ? -1 : 1;

	efx_mdio_an_reconfigure(efx);

	return rc;
}
コード例 #6
0
static int tenxpress_phy_reconfigure(struct efx_nic *efx)
{
	struct tenxpress_phy_data *phy_data = efx->phy_data;
	bool phy_mode_change, loop_reset;

	if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
		phy_data->phy_mode = efx->phy_mode;
		return 0;
	}

	phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
			   phy_data->phy_mode != PHY_MODE_NORMAL);
	loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, LOOPBACKS_EXTERNAL(efx)) ||
		      LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));

	if (loop_reset || phy_mode_change) {
		tenxpress_special_reset(efx);

		/* Reset XAUI if we were in 10G, and are staying
		 * in 10G. If we're moving into and out of 10G
		 * then xaui will be reset anyway */
		if (EFX_IS10G(efx))
			falcon_reset_xaui(efx);
	}

	tenxpress_low_power(efx);
	efx_mdio_transmit_disable(efx);
	efx_mdio_phy_reconfigure(efx);
	tenxpress_ext_loopback(efx);
	efx_mdio_an_reconfigure(efx);

	phy_data->loopback_mode = efx->loopback_mode;
	phy_data->phy_mode = efx->phy_mode;

	return 0;
}