Skip to content

Commit c577e59

Browse files
Daniel Pieczkodavem330
authored andcommitted
sfc: fully reset if MC_REBOOT event received without warm_boot_count increment
On EF10, MC_CMD_VPORT_RECONFIGURE can cause a CODE_MC_REBOOT event to be sent to a function without incrementing the (adapter-wide) warm_boot_count. In this case, the reboot is not detected by the loop on efx_mcdi_poll_reboot(), so prepare for recovery from an MC reboot anyway. When this codepath is run, the MC has always just rebooted, so this recovery is valid. The loop on efx_mcdi_poll_reboot() is still required for other MC reboot cases, so that actions in response to an MC reboot are performed, such as clearing locally calculated statistics. Siena NICs are unaffected by this change as the above scenario does not apply. Signed-off-by: Shradha Shah <sshah@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d540491 commit c577e59

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

drivers/net/ethernet/sfc/ef10.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,22 @@ efx_ef10_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf,
16041604
memcpy(outbuf, pdu + offset, outlen);
16051605
}
16061606

1607+
static void efx_ef10_mcdi_reboot_detected(struct efx_nic *efx)
1608+
{
1609+
struct efx_ef10_nic_data *nic_data = efx->nic_data;
1610+
1611+
/* All our allocations have been reset */
1612+
efx_ef10_reset_mc_allocations(efx);
1613+
1614+
/* The datapath firmware might have been changed */
1615+
nic_data->must_check_datapath_caps = true;
1616+
1617+
/* MAC statistics have been cleared on the NIC; clear the local
1618+
* statistic that we update with efx_update_diff_stat().
1619+
*/
1620+
nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0;
1621+
}
1622+
16071623
static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)
16081624
{
16091625
struct efx_ef10_nic_data *nic_data = efx->nic_data;
@@ -1623,17 +1639,7 @@ static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)
16231639
return 0;
16241640

16251641
nic_data->warm_boot_count = rc;
1626-
1627-
/* All our allocations have been reset */
1628-
efx_ef10_reset_mc_allocations(efx);
1629-
1630-
/* The datapath firmware might have been changed */
1631-
nic_data->must_check_datapath_caps = true;
1632-
1633-
/* MAC statistics have been cleared on the NIC; clear the local
1634-
* statistic that we update with efx_update_diff_stat().
1635-
*/
1636-
nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0;
1642+
efx_ef10_mcdi_reboot_detected(efx);
16371643

16381644
return -EIO;
16391645
}
@@ -4670,6 +4676,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
46704676
.mcdi_poll_response = efx_ef10_mcdi_poll_response,
46714677
.mcdi_read_response = efx_ef10_mcdi_read_response,
46724678
.mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot,
4679+
.mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected,
46734680
.irq_enable_master = efx_port_dummy_op_void,
46744681
.irq_test_generate = efx_ef10_irq_test_generate,
46754682
.irq_disable_non_ev = efx_port_dummy_op_void,
@@ -4774,6 +4781,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
47744781
.mcdi_poll_response = efx_ef10_mcdi_poll_response,
47754782
.mcdi_read_response = efx_ef10_mcdi_read_response,
47764783
.mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot,
4784+
.mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected,
47774785
.irq_enable_master = efx_port_dummy_op_void,
47784786
.irq_test_generate = efx_ef10_irq_test_generate,
47794787
.irq_disable_non_ev = efx_port_dummy_op_void,

drivers/net/ethernet/sfc/mcdi.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1028,10 +1028,21 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
10281028

10291029
/* Consume the status word since efx_mcdi_rpc_finish() won't */
10301030
for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
1031-
if (efx_mcdi_poll_reboot(efx))
1031+
rc = efx_mcdi_poll_reboot(efx);
1032+
if (rc)
10321033
break;
10331034
udelay(MCDI_STATUS_DELAY_US);
10341035
}
1036+
1037+
/* On EF10, a CODE_MC_REBOOT event can be received without the
1038+
* reboot detection in efx_mcdi_poll_reboot() being triggered.
1039+
* If zero was returned from the final call to
1040+
* efx_mcdi_poll_reboot(), the MC reboot wasn't noticed but the
1041+
* MC has definitely rebooted so prepare for the reset.
1042+
*/
1043+
if (!rc && efx->type->mcdi_reboot_detected)
1044+
efx->type->mcdi_reboot_detected(efx);
1045+
10351046
mcdi->new_epoch = true;
10361047

10371048
/* Nobody was waiting for an MCDI request, so trigger a reset */

drivers/net/ethernet/sfc/net_driver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,7 @@ struct efx_nic_type {
12771277
void (*mcdi_read_response)(struct efx_nic *efx, efx_dword_t *pdu,
12781278
size_t pdu_offset, size_t pdu_len);
12791279
int (*mcdi_poll_reboot)(struct efx_nic *efx);
1280+
void (*mcdi_reboot_detected)(struct efx_nic *efx);
12801281
void (*irq_enable_master)(struct efx_nic *efx);
12811282
void (*irq_test_generate)(struct efx_nic *efx);
12821283
void (*irq_disable_non_ev)(struct efx_nic *efx);

0 commit comments

Comments
 (0)