net/sfc: handle MC reboot event
Implement handling of the MC reboot event received on management event queue or detected by MCDI processing. Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru> Reviewed-by: Andy Moreton <amoreton@solarflare.com>
This commit is contained in:
parent
f042136ee2
commit
e77f9f1906
@ -33,6 +33,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rte_errno.h>
|
||||
#include <rte_alarm.h>
|
||||
|
||||
#include "efx.h"
|
||||
|
||||
@ -389,6 +390,58 @@ sfc_stop(struct sfc_adapter *sa)
|
||||
sfc_log_init(sa, "done");
|
||||
}
|
||||
|
||||
static int
|
||||
sfc_restart(struct sfc_adapter *sa)
|
||||
{
|
||||
int rc;
|
||||
|
||||
SFC_ASSERT(sfc_adapter_is_locked(sa));
|
||||
|
||||
if (sa->state != SFC_ADAPTER_STARTED)
|
||||
return EINVAL;
|
||||
|
||||
sfc_stop(sa);
|
||||
|
||||
rc = sfc_start(sa);
|
||||
if (rc != 0)
|
||||
sfc_err(sa, "restart failed");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
sfc_restart_if_required(void *arg)
|
||||
{
|
||||
struct sfc_adapter *sa = arg;
|
||||
|
||||
/* If restart is scheduled, clear the flag and do it */
|
||||
if (rte_atomic32_cmpset((volatile uint32_t *)&sa->restart_required,
|
||||
1, 0)) {
|
||||
sfc_adapter_lock(sa);
|
||||
if (sa->state == SFC_ADAPTER_STARTED)
|
||||
(void)sfc_restart(sa);
|
||||
sfc_adapter_unlock(sa);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sfc_schedule_restart(struct sfc_adapter *sa)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Schedule restart alarm if it is not scheduled yet */
|
||||
if (!rte_atomic32_test_and_set(&sa->restart_required))
|
||||
return;
|
||||
|
||||
rc = rte_eal_alarm_set(1, sfc_restart_if_required, sa);
|
||||
if (rc == -ENOTSUP)
|
||||
sfc_warn(sa, "alarms are not supported, restart is pending");
|
||||
else if (rc != 0)
|
||||
sfc_err(sa, "cannot arm restart alarm (rc=%d)", rc);
|
||||
else
|
||||
sfc_info(sa, "restart scheduled");
|
||||
}
|
||||
|
||||
int
|
||||
sfc_configure(struct sfc_adapter *sa)
|
||||
{
|
||||
@ -679,6 +732,7 @@ sfc_probe(struct sfc_adapter *sa)
|
||||
SFC_ASSERT(sfc_adapter_is_locked(sa));
|
||||
|
||||
sa->socket_id = rte_socket_id();
|
||||
rte_atomic32_init(&sa->restart_required);
|
||||
|
||||
sfc_log_init(sa, "init mem bar");
|
||||
rc = sfc_mem_bar_init(sa);
|
||||
@ -743,6 +797,14 @@ sfc_unprobe(struct sfc_adapter *sa)
|
||||
|
||||
sfc_mcdi_fini(sa);
|
||||
|
||||
/*
|
||||
* Make sure there is no pending alarm to restart since we are
|
||||
* going to free device private which is passed as the callback
|
||||
* opaque data. A new alarm cannot be scheduled since MCDI is
|
||||
* shut down.
|
||||
*/
|
||||
rte_eal_alarm_cancel(sfc_restart_if_required, sa);
|
||||
|
||||
sfc_log_init(sa, "destroy nic");
|
||||
sa->nic = NULL;
|
||||
efx_nic_destroy(enp);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_kvargs.h>
|
||||
#include <rte_spinlock.h>
|
||||
#include <rte_atomic.h>
|
||||
|
||||
#include "efx.h"
|
||||
|
||||
@ -197,6 +198,7 @@ struct sfc_adapter {
|
||||
efx_family_t family;
|
||||
efx_nic_t *nic;
|
||||
rte_spinlock_t nic_lock;
|
||||
rte_atomic32_t restart_required;
|
||||
|
||||
struct sfc_mcdi mcdi;
|
||||
struct sfc_intr intr;
|
||||
@ -329,6 +331,8 @@ void sfc_detach(struct sfc_adapter *sa);
|
||||
int sfc_start(struct sfc_adapter *sa);
|
||||
void sfc_stop(struct sfc_adapter *sa);
|
||||
|
||||
void sfc_schedule_restart(struct sfc_adapter *sa);
|
||||
|
||||
int sfc_mcdi_init(struct sfc_adapter *sa);
|
||||
void sfc_mcdi_fini(struct sfc_adapter *sa);
|
||||
|
||||
|
@ -176,7 +176,7 @@ sfc_mcdi_exception(void *arg, efx_mcdi_exception_t eme)
|
||||
(eme == EFX_MCDI_EXCEPTION_MC_REBOOT) ? "REBOOT" :
|
||||
(eme == EFX_MCDI_EXCEPTION_MC_BADASSERT) ? "BADASSERT" : "UNKNOWN");
|
||||
|
||||
sfc_panic(sa, "MCDI exceptions handling is not implemented\n");
|
||||
sfc_schedule_restart(sa);
|
||||
}
|
||||
|
||||
#define SFC_MCDI_LOG_BUF_SIZE 128
|
||||
|
Loading…
Reference in New Issue
Block a user