summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/devlink.h3
-rw-r--r--net/devlink/health.c22
2 files changed, 24 insertions, 1 deletions
diff --git a/include/net/devlink.h b/include/net/devlink.h
index c7ad7a981b39..5f44e702c25c 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -748,6 +748,8 @@ enum devlink_health_reporter_state {
* @test: callback to trigger a test event
* @default_graceful_period: default min time (in msec)
* between recovery attempts
+ * @default_burst_period: default time (in msec) for
+ * error recoveries before starting the grace period
*/
struct devlink_health_reporter_ops {
@@ -763,6 +765,7 @@ struct devlink_health_reporter_ops {
int (*test)(struct devlink_health_reporter *reporter,
struct netlink_ext_ack *extack);
u64 default_graceful_period;
+ u64 default_burst_period;
};
/**
diff --git a/net/devlink/health.c b/net/devlink/health.c
index 9d0d4a9face7..94ab77f77add 100644
--- a/net/devlink/health.c
+++ b/net/devlink/health.c
@@ -60,6 +60,7 @@ struct devlink_health_reporter {
struct devlink_port *devlink_port;
struct devlink_fmsg *dump_fmsg;
u64 graceful_period;
+ u64 burst_period;
bool auto_recover;
bool auto_dump;
u8 health_state;
@@ -123,6 +124,7 @@ __devlink_health_reporter_create(struct devlink *devlink,
reporter->ops = ops;
reporter->devlink = devlink;
reporter->graceful_period = ops->default_graceful_period;
+ reporter->burst_period = ops->default_burst_period;
reporter->auto_recover = !!ops->recover;
reporter->auto_dump = !!ops->dump;
return reporter;
@@ -508,11 +510,25 @@ static void devlink_recover_notify(struct devlink_health_reporter *reporter,
devlink_nl_notify_send_desc(devlink, msg, &desc);
}
+static bool
+devlink_health_reporter_in_burst(struct devlink_health_reporter *reporter)
+{
+ unsigned long burst_threshold = reporter->last_recovery_ts +
+ msecs_to_jiffies(reporter->burst_period);
+
+ return time_is_after_jiffies(burst_threshold);
+}
+
void
devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter)
{
reporter->recovery_count++;
- reporter->last_recovery_ts = jiffies;
+ if (!devlink_health_reporter_in_burst(reporter))
+ /* When burst period is set, last_recovery_ts marks the first
+ * recovery within the burst period, not necessarily the last
+ * one.
+ */
+ reporter->last_recovery_ts = jiffies;
}
EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
@@ -599,7 +615,11 @@ devlink_health_recover_abort(struct devlink_health_reporter *reporter,
if (prev_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY)
return true;
+ if (devlink_health_reporter_in_burst(reporter))
+ return false;
+
recover_ts_threshold = reporter->last_recovery_ts +
+ msecs_to_jiffies(reporter->burst_period) +
msecs_to_jiffies(reporter->graceful_period);
if (reporter->last_recovery_ts && reporter->recovery_count &&
time_is_after_jiffies(recover_ts_threshold))