sfc: Simplify XMAC link polling
From: Steve Hodgson <shodgson@solarflare.com> Only the XMAC on Falcon needs help from the driver to poll and reset the MAC-PHY link (XAUI); GMII is a simple parallel bus and on later NICs firmware takes care of the XAUI link. Also, an XMAC interrupt currently schedules a work item which simply clears a flag (efx_nic::mac_up) to be checked by the regular monitor (or the next link reconfiguration, if that is sooner). Rename the flag to xmac_poll_required, changing its sense. Remove the needless indirection and just set the flag immediately. Call falcon_xmac_poll() directly where required. Add a new generic operation mac_op::check_fault to check the link outside of regular monitoring, as required during self-tests. (Note that this leaves us with an unused work item, but we will immediately have another use for it.) Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
fe75820b99
commit
9007b9fa36
|
@ -693,8 +693,6 @@ static void efx_mac_work(struct work_struct *data)
|
||||||
struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
|
struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
|
||||||
|
|
||||||
mutex_lock(&efx->mac_lock);
|
mutex_lock(&efx->mac_lock);
|
||||||
if (efx->port_enabled)
|
|
||||||
efx->mac_op->irq(efx);
|
|
||||||
mutex_unlock(&efx->mac_lock);
|
mutex_unlock(&efx->mac_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,7 +772,6 @@ static void efx_start_port(struct efx_nic *efx)
|
||||||
mutex_lock(&efx->mac_lock);
|
mutex_lock(&efx->mac_lock);
|
||||||
efx->port_enabled = true;
|
efx->port_enabled = true;
|
||||||
__efx_reconfigure_port(efx);
|
__efx_reconfigure_port(efx);
|
||||||
efx->mac_op->irq(efx);
|
|
||||||
mutex_unlock(&efx->mac_lock);
|
mutex_unlock(&efx->mac_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1903,8 +1900,6 @@ void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
|
||||||
|
|
||||||
static struct efx_mac_operations efx_dummy_mac_operations = {
|
static struct efx_mac_operations efx_dummy_mac_operations = {
|
||||||
.reconfigure = efx_port_dummy_op_void,
|
.reconfigure = efx_port_dummy_op_void,
|
||||||
.poll = efx_port_dummy_op_void,
|
|
||||||
.irq = efx_port_dummy_op_void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct efx_phy_operations efx_dummy_phy_operations = {
|
static struct efx_phy_operations efx_dummy_phy_operations = {
|
||||||
|
|
|
@ -900,7 +900,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
|
||||||
|
|
||||||
if ((falcon_rev(efx) >= FALCON_REV_B0) &&
|
if ((falcon_rev(efx) >= FALCON_REV_B0) &&
|
||||||
EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
|
EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
|
||||||
queue_work(efx->workqueue, &efx->mac_work);
|
efx->xmac_poll_required = true;
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2251,7 +2251,7 @@ int falcon_switch_mac(struct efx_nic *efx)
|
||||||
|
|
||||||
EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
|
EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
|
||||||
/* Not all macs support a mac-level link state */
|
/* Not all macs support a mac-level link state */
|
||||||
efx->mac_up = true;
|
efx->xmac_poll_required = false;
|
||||||
|
|
||||||
rc = falcon_reset_macs(efx);
|
rc = falcon_reset_macs(efx);
|
||||||
out:
|
out:
|
||||||
|
@ -2624,7 +2624,8 @@ void falcon_monitor(struct efx_nic *efx)
|
||||||
falcon_sim_phy_event(efx);
|
falcon_sim_phy_event(efx);
|
||||||
}
|
}
|
||||||
efx->phy_op->poll(efx);
|
efx->phy_op->poll(efx);
|
||||||
efx->mac_op->poll(efx);
|
if (EFX_IS10G(efx))
|
||||||
|
falcon_poll_xmac(efx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zeroes out the SRAM contents. This routine must be called in
|
/* Zeroes out the SRAM contents. This routine must be called in
|
||||||
|
|
|
@ -209,4 +209,6 @@ extern int falcon_test_registers(struct efx_nic *efx);
|
||||||
extern void falcon_generate_event(struct efx_channel *channel,
|
extern void falcon_generate_event(struct efx_channel *channel,
|
||||||
efx_qword_t *event);
|
efx_qword_t *event);
|
||||||
|
|
||||||
|
extern void falcon_poll_xmac(struct efx_nic *efx);
|
||||||
|
|
||||||
#endif /* EFX_FALCON_H */
|
#endif /* EFX_FALCON_H */
|
||||||
|
|
|
@ -380,7 +380,7 @@ static int sfe4001_check_hw(struct efx_nic *efx)
|
||||||
s32 status;
|
s32 status;
|
||||||
|
|
||||||
/* If XAUI link is up then do not monitor */
|
/* If XAUI link is up then do not monitor */
|
||||||
if (EFX_WORKAROUND_7884(efx) && efx->mac_up)
|
if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check the powered status of the PHY. Lack of power implies that
|
/* Check the powered status of the PHY. Lack of power implies that
|
||||||
|
@ -468,7 +468,7 @@ static int sfn4111t_check_hw(struct efx_nic *efx)
|
||||||
s32 status;
|
s32 status;
|
||||||
|
|
||||||
/* If XAUI link is up then do not monitor */
|
/* If XAUI link is up then do not monitor */
|
||||||
if (EFX_WORKAROUND_7884(efx) && efx->mac_up)
|
if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
|
/* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
|
||||||
|
|
|
@ -216,9 +216,13 @@ static void falcon_update_stats_gmac(struct efx_nic *efx)
|
||||||
mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
|
mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool falcon_gmac_check_fault(struct efx_nic *efx)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct efx_mac_operations falcon_gmac_operations = {
|
struct efx_mac_operations falcon_gmac_operations = {
|
||||||
.reconfigure = falcon_reconfigure_gmac,
|
.reconfigure = falcon_reconfigure_gmac,
|
||||||
.update_stats = falcon_update_stats_gmac,
|
.update_stats = falcon_update_stats_gmac,
|
||||||
.irq = efx_port_dummy_op_void,
|
.check_fault = falcon_gmac_check_fault,
|
||||||
.poll = efx_port_dummy_op_void,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -98,7 +98,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
|
||||||
|
|
||||||
/* We can only use this interrupt to signal the negative edge of
|
/* We can only use this interrupt to signal the negative edge of
|
||||||
* xaui_align [we have to poll the positive edge]. */
|
* xaui_align [we have to poll the positive edge]. */
|
||||||
if (!efx->mac_up)
|
if (efx->xmac_poll_required)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Flush the ISR */
|
/* Flush the ISR */
|
||||||
|
@ -243,29 +243,35 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
|
/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */
|
||||||
* to come back up. Bash it until it comes back up */
|
static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
|
||||||
static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
|
|
||||||
{
|
{
|
||||||
efx->mac_up = falcon_xaui_link_ok(efx);
|
bool mac_up = falcon_xaui_link_ok(efx);
|
||||||
|
|
||||||
if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
|
if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
|
||||||
efx_phy_mode_disabled(efx->phy_mode))
|
efx_phy_mode_disabled(efx->phy_mode))
|
||||||
/* XAUI link is expected to be down */
|
/* XAUI link is expected to be down */
|
||||||
return;
|
return mac_up;
|
||||||
|
|
||||||
falcon_stop_nic_stats(efx);
|
falcon_stop_nic_stats(efx);
|
||||||
|
|
||||||
while (!efx->mac_up && tries) {
|
while (!mac_up && tries) {
|
||||||
EFX_LOG(efx, "bashing xaui\n");
|
EFX_LOG(efx, "bashing xaui\n");
|
||||||
falcon_reset_xaui(efx);
|
falcon_reset_xaui(efx);
|
||||||
udelay(200);
|
udelay(200);
|
||||||
|
|
||||||
efx->mac_up = falcon_xaui_link_ok(efx);
|
mac_up = falcon_xaui_link_ok(efx);
|
||||||
--tries;
|
--tries;
|
||||||
}
|
}
|
||||||
|
|
||||||
falcon_start_nic_stats(efx);
|
falcon_start_nic_stats(efx);
|
||||||
|
|
||||||
|
return mac_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool falcon_xmac_check_fault(struct efx_nic *efx)
|
||||||
|
{
|
||||||
|
return !falcon_check_xaui_link_up(efx, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void falcon_reconfigure_xmac(struct efx_nic *efx)
|
static void falcon_reconfigure_xmac(struct efx_nic *efx)
|
||||||
|
@ -277,7 +283,7 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx)
|
||||||
|
|
||||||
falcon_reconfigure_mac_wrapper(efx);
|
falcon_reconfigure_mac_wrapper(efx);
|
||||||
|
|
||||||
falcon_check_xaui_link_up(efx, 5);
|
efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5);
|
||||||
falcon_mask_status_intr(efx, true);
|
falcon_mask_status_intr(efx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,35 +347,19 @@ static void falcon_update_stats_xmac(struct efx_nic *efx)
|
||||||
mac_stats->rx_control * 64);
|
mac_stats->rx_control * 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void falcon_xmac_irq(struct efx_nic *efx)
|
void falcon_poll_xmac(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
/* The XGMII link has a transient fault, which indicates either:
|
if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up ||
|
||||||
* - there's a transient xgmii fault
|
!efx->xmac_poll_required)
|
||||||
* - falcon's end of the xaui link may need a kick
|
|
||||||
* - the wire-side link may have gone down, but the lasi/poll()
|
|
||||||
* hasn't noticed yet.
|
|
||||||
*
|
|
||||||
* We only want to even bother polling XAUI if we're confident it's
|
|
||||||
* not (1) or (3). In both cases, the only reliable way to spot this
|
|
||||||
* is to wait a bit. We do this here by forcing the mac link state
|
|
||||||
* to down, and waiting for the mac poll to come round and check
|
|
||||||
*/
|
|
||||||
efx->mac_up = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void falcon_poll_xmac(struct efx_nic *efx)
|
|
||||||
{
|
|
||||||
if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || efx->mac_up)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
falcon_mask_status_intr(efx, false);
|
falcon_mask_status_intr(efx, false);
|
||||||
falcon_check_xaui_link_up(efx, 1);
|
efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 1);
|
||||||
falcon_mask_status_intr(efx, true);
|
falcon_mask_status_intr(efx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct efx_mac_operations falcon_xmac_operations = {
|
struct efx_mac_operations falcon_xmac_operations = {
|
||||||
.reconfigure = falcon_reconfigure_xmac,
|
.reconfigure = falcon_reconfigure_xmac,
|
||||||
.update_stats = falcon_update_stats_xmac,
|
.update_stats = falcon_update_stats_xmac,
|
||||||
.irq = falcon_xmac_irq,
|
.check_fault = falcon_xmac_check_fault,
|
||||||
.poll = falcon_poll_xmac,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -507,14 +507,12 @@ struct efx_link_state {
|
||||||
* struct efx_mac_operations - Efx MAC operations table
|
* struct efx_mac_operations - Efx MAC operations table
|
||||||
* @reconfigure: Reconfigure MAC. Serialised by the mac_lock
|
* @reconfigure: Reconfigure MAC. Serialised by the mac_lock
|
||||||
* @update_stats: Update statistics
|
* @update_stats: Update statistics
|
||||||
* @irq: Hardware MAC event callback. Serialised by the mac_lock
|
* @check_fault: Check fault state. True if fault present.
|
||||||
* @poll: Poll for hardware state. Serialised by the mac_lock
|
|
||||||
*/
|
*/
|
||||||
struct efx_mac_operations {
|
struct efx_mac_operations {
|
||||||
void (*reconfigure) (struct efx_nic *efx);
|
void (*reconfigure) (struct efx_nic *efx);
|
||||||
void (*update_stats) (struct efx_nic *efx);
|
void (*update_stats) (struct efx_nic *efx);
|
||||||
void (*irq) (struct efx_nic *efx);
|
bool (*check_fault)(struct efx_nic *efx);
|
||||||
void (*poll) (struct efx_nic *efx);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -725,7 +723,7 @@ union efx_multicast_hash {
|
||||||
* @phy_data: PHY private data (including PHY-specific stats)
|
* @phy_data: PHY private data (including PHY-specific stats)
|
||||||
* @mdio: PHY MDIO interface
|
* @mdio: PHY MDIO interface
|
||||||
* @phy_mode: PHY operating mode. Serialised by @mac_lock.
|
* @phy_mode: PHY operating mode. Serialised by @mac_lock.
|
||||||
* @mac_up: MAC link state
|
* @xmac_poll_required: XMAC link state needs polling
|
||||||
* @link_state: Current state of the link
|
* @link_state: Current state of the link
|
||||||
* @n_link_state_changes: Number of times the link has changed state
|
* @n_link_state_changes: Number of times the link has changed state
|
||||||
* @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
|
* @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
|
||||||
|
@ -810,7 +808,7 @@ struct efx_nic {
|
||||||
struct mdio_if_info mdio;
|
struct mdio_if_info mdio;
|
||||||
enum efx_phy_mode phy_mode;
|
enum efx_phy_mode phy_mode;
|
||||||
|
|
||||||
bool mac_up;
|
bool xmac_poll_required;
|
||||||
struct efx_link_state link_state;
|
struct efx_link_state link_state;
|
||||||
unsigned int n_link_state_changes;
|
unsigned int n_link_state_changes;
|
||||||
|
|
||||||
|
|
|
@ -610,13 +610,10 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
|
||||||
flush_workqueue(efx->workqueue);
|
flush_workqueue(efx->workqueue);
|
||||||
rmb();
|
rmb();
|
||||||
|
|
||||||
/* We need both the phy and xaui links to be ok.
|
/* We need both the PHY and MAC-PHY links to be OK */
|
||||||
* rather than relying on the falcon_xmac irq/poll
|
|
||||||
* regime, just poll xaui directly */
|
|
||||||
link_up = efx->link_state.up;
|
link_up = efx->link_state.up;
|
||||||
if (link_up && EFX_IS10G(efx) &&
|
if (link_up)
|
||||||
!falcon_xaui_link_ok(efx))
|
link_up = !efx->mac_op->check_fault(efx);
|
||||||
link_up = false;
|
|
||||||
|
|
||||||
} while ((++count < 20) && !link_up);
|
} while ((++count < 20) && !link_up);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue