/* Poll PHY for interrupt */ static void tenxpress_phy_poll(struct efx_nic *efx) { struct tenxpress_phy_data *phy_data = efx->phy_data; bool change = false; if (efx->phy_type == PHY_TYPE_SFX7101) { bool link_ok = sfx7101_link_ok(efx); if (link_ok != efx->link_up) { change = true; } else { unsigned int link_fc = mdio_clause45_get_pause(efx); if (link_fc != efx->link_fc) change = true; } sfx7101_check_bad_lp(efx, link_ok); } else if (efx->loopback_mode) { bool link_ok = sft9001_link_ok(efx, NULL); if (link_ok != efx->link_up) change = true; } else { u32 status = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, PMA_PMD_LASI_STATUS); if (status & (1 << PMA_PMD_LS_ALARM_LBN)) change = true; } if (change) falcon_sim_phy_event(efx); if (phy_data->phy_mode != PHY_MODE_NORMAL) return; }
/* Poll for link state changes */ static bool tenxpress_phy_poll(struct efx_nic *efx) { struct efx_link_state old_state = efx->link_state; if (efx->phy_type == PHY_TYPE_SFX7101) { efx->link_state.up = sfx7101_link_ok(efx); efx->link_state.speed = 10000; efx->link_state.fd = true; efx->link_state.fc = efx_mdio_get_pause(efx); sfx7101_check_bad_lp(efx, efx->link_state.up); } else { struct ethtool_cmd ecmd; /* Check the LASI alarm first */ if (efx->loopback_mode == LOOPBACK_NONE && !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) & MDIO_PMA_LASI_LSALARM)) return false; tenxpress_get_settings(efx, &ecmd); efx->link_state.up = sft9001_link_ok(efx, &ecmd); efx->link_state.speed = ecmd.speed; efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL); efx->link_state.fc = efx_mdio_get_pause(efx); } return !efx_link_state_equal(&efx->link_state, &old_state); }
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); }
/* Poll for link state changes */ static bool tenxpress_phy_poll(struct efx_nic *efx) { struct efx_link_state old_state = efx->link_state; efx->link_state.up = sfx7101_link_ok(efx); efx->link_state.speed = 10000; efx->link_state.fd = true; efx->link_state.fc = efx_mdio_get_pause(efx); sfx7101_check_bad_lp(efx, efx->link_state.up); return !efx_link_state_equal(&efx->link_state, &old_state); }