Merge branch 'Devlink-notification-after-recovery-complete-by-bnxt_en-driver'

Vikas Gupta says:

====================
Devlink notification after recovery complete by bnxt_en driver

 This patchset adds following feature in devlink
  1) Recovery complete direct call API to be used by drivers when it
     successfully completes. It is required as recovery triggered by
     devlink may return with EINPROGRESS and eventually recovery
     completes in different context.
  2) A notification when health status is updated by reporter.

 Patchset also contains required changes in bnxt_en driver to
 mark recovery in progress when recovery is triggered from kernel
 devlink.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-01-08 15:47:50 -08:00
commit 8d2ff12653
5 changed files with 63 additions and 17 deletions

View File

@ -10822,6 +10822,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
smp_mb__before_atomic();
clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
bnxt_ulp_start(bp, rc);
bnxt_dl_health_recovery_done(bp);
bnxt_dl_health_status_update(bp, true);
rtnl_unlock();
break;

View File

@ -89,7 +89,7 @@ static int bnxt_fw_reset_recover(struct devlink_health_reporter *reporter,
return -EOPNOTSUPP;
bnxt_fw_reset(bp);
return 0;
return -EINPROGRESS;
}
static const
@ -116,7 +116,7 @@ static int bnxt_fw_fatal_recover(struct devlink_health_reporter *reporter,
else if (event == BNXT_FW_EXCEPTION_SP_EVENT)
bnxt_fw_exception(bp);
return 0;
return -EINPROGRESS;
}
static const
@ -262,6 +262,16 @@ void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy)
health->fatal = false;
}
void bnxt_dl_health_recovery_done(struct bnxt *bp)
{
struct bnxt_fw_health *hlth = bp->fw_health;
if (hlth->fatal)
devlink_health_reporter_recovery_done(hlth->fw_fatal_reporter);
else
devlink_health_reporter_recovery_done(hlth->fw_reset_reporter);
}
static const struct devlink_ops bnxt_dl_ops = {
#ifdef CONFIG_BNXT_SRIOV
.eswitch_mode_set = bnxt_dl_eswitch_mode_set,

View File

@ -58,6 +58,7 @@ struct bnxt_dl_nvm_param {
void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event);
void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy);
void bnxt_dl_health_recovery_done(struct bnxt *bp);
void bnxt_dl_fw_reporters_create(struct bnxt *bp);
void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all);
int bnxt_dl_register(struct bnxt *bp);

View File

@ -1000,6 +1000,8 @@ int devlink_health_report(struct devlink_health_reporter *reporter,
void
devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
enum devlink_health_reporter_state state);
void
devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter);
bool devlink_is_reload_failed(const struct devlink *devlink);

View File

@ -4844,21 +4844,12 @@ devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
void
devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
enum devlink_health_reporter_state state)
devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter)
{
if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
return;
if (reporter->health_state == state)
return;
reporter->health_state = state;
trace_devlink_health_reporter_state_update(reporter->devlink,
reporter->ops->name, state);
reporter->recovery_count++;
reporter->last_recovery_ts = jiffies;
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
static int
devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
@ -4876,9 +4867,8 @@ devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
if (err)
return err;
reporter->recovery_count++;
devlink_health_reporter_recovery_done(reporter);
reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
reporter->last_recovery_ts = jiffies;
return 0;
}
@ -5090,6 +5080,48 @@ genlmsg_cancel:
return -EMSGSIZE;
}
static void devlink_recover_notify(struct devlink_health_reporter *reporter,
enum devlink_command cmd)
{
struct sk_buff *msg;
int err;
WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
return;
err = devlink_nl_health_reporter_fill(msg, reporter->devlink,
reporter, cmd, 0, 0, 0);
if (err) {
nlmsg_free(msg);
return;
}
genlmsg_multicast_netns(&devlink_nl_family,
devlink_net(reporter->devlink),
msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
}
void
devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
enum devlink_health_reporter_state state)
{
if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
return;
if (reporter->health_state == state)
return;
reporter->health_state = state;
trace_devlink_health_reporter_state_update(reporter->devlink,
reporter->ops->name, state);
devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
struct genl_info *info)
{