eth: fbnic: use fw uptime to detect fw crashes
Currently we only detect FW crashes when it stops responding to heartbeat messages. FW has a watchdog which will reset it in case of crashes. Use FW uptime sent in the ownership and heartbeat messages to detect that the watchdog has fired (uptime went down). Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Link: https://patch.msgid.link/20250916231420.1693955-3-kuba@kernel.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
e6c8ab0a11
commit
7fd1f7bac2
@@ -84,6 +84,10 @@ struct fbnic_dev {
|
||||
/* Local copy of hardware statistics */
|
||||
struct fbnic_hw_stats hw_stats;
|
||||
|
||||
/* Firmware time since boot in milliseconds */
|
||||
u64 firmware_time;
|
||||
u64 prev_firmware_time;
|
||||
|
||||
struct fbnic_fw_log fw_log;
|
||||
};
|
||||
|
||||
|
||||
@@ -495,6 +495,11 @@ int fbnic_fw_xmit_ownership_msg(struct fbnic_dev *fbd, bool take_ownership)
|
||||
|
||||
fbd->last_heartbeat_request = req_time;
|
||||
|
||||
/* Set prev_firmware_time to 0 to avoid triggering firmware crash
|
||||
* detection until we receive the second uptime in a heartbeat resp.
|
||||
*/
|
||||
fbd->prev_firmware_time = 0;
|
||||
|
||||
/* Set heartbeat detection based on if we are taking ownership */
|
||||
fbd->fw_heartbeat_enabled = take_ownership;
|
||||
|
||||
@@ -660,6 +665,7 @@ static int fbnic_fw_parse_cap_resp(void *opaque, struct fbnic_tlv_msg **results)
|
||||
}
|
||||
|
||||
static const struct fbnic_tlv_index fbnic_ownership_resp_index[] = {
|
||||
FBNIC_TLV_ATTR_U64(FBNIC_FW_OWNERSHIP_TIME),
|
||||
FBNIC_TLV_ATTR_LAST
|
||||
};
|
||||
|
||||
@@ -671,10 +677,14 @@ static int fbnic_fw_parse_ownership_resp(void *opaque,
|
||||
/* Count the ownership response as a heartbeat reply */
|
||||
fbd->last_heartbeat_response = jiffies;
|
||||
|
||||
/* Capture firmware time for logging and firmware crash check */
|
||||
fbd->firmware_time = fta_get_uint(results, FBNIC_FW_OWNERSHIP_TIME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fbnic_tlv_index fbnic_heartbeat_resp_index[] = {
|
||||
FBNIC_TLV_ATTR_U64(FBNIC_FW_HEARTBEAT_UPTIME),
|
||||
FBNIC_TLV_ATTR_LAST
|
||||
};
|
||||
|
||||
@@ -685,6 +695,9 @@ static int fbnic_fw_parse_heartbeat_resp(void *opaque,
|
||||
|
||||
fbd->last_heartbeat_response = jiffies;
|
||||
|
||||
/* Capture firmware time for logging and firmware crash check */
|
||||
fbd->firmware_time = fta_get_uint(results, FBNIC_FW_HEARTBEAT_UPTIME);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -706,6 +719,7 @@ static int fbnic_fw_xmit_heartbeat_message(struct fbnic_dev *fbd)
|
||||
goto free_message;
|
||||
|
||||
fbd->last_heartbeat_request = req_time;
|
||||
fbd->prev_firmware_time = fbd->firmware_time;
|
||||
|
||||
return err;
|
||||
|
||||
@@ -766,7 +780,8 @@ void fbnic_fw_check_heartbeat(struct fbnic_dev *fbd)
|
||||
return;
|
||||
|
||||
/* Was the last heartbeat response long time ago? */
|
||||
if (!fbnic_fw_heartbeat_current(fbd)) {
|
||||
if (!fbnic_fw_heartbeat_current(fbd) ||
|
||||
fbd->firmware_time < fbd->prev_firmware_time) {
|
||||
dev_warn(fbd->dev,
|
||||
"Firmware did not respond to heartbeat message\n");
|
||||
fbd->fw_heartbeat_enabled = false;
|
||||
|
||||
@@ -198,9 +198,16 @@ enum {
|
||||
|
||||
enum {
|
||||
FBNIC_FW_OWNERSHIP_FLAG = 0x0,
|
||||
FBNIC_FW_OWNERSHIP_TIME = 0x1,
|
||||
FBNIC_FW_OWNERSHIP_MSG_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
FBNIC_FW_HEARTBEAT_UPTIME = 0x0,
|
||||
FBNIC_FW_HEARTBEAT_NUMBER_OF_MESSAGES = 0x1,
|
||||
FBNIC_FW_HEARTBEAT_MSG_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
FBNIC_FW_START_UPGRADE_ERROR = 0x0,
|
||||
FBNIC_FW_START_UPGRADE_SECTION = 0x1,
|
||||
|
||||
Reference in New Issue
Block a user