summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/pensando/ionic/ionic_dev.c
diff options
context:
space:
mode:
authorShannon Nelson <snelson@pensando.io>2021-07-27 20:43:26 +0300
committerDavid S. Miller <davem@davemloft.net>2021-07-27 22:15:21 +0300
commitd2662072c094be6dd7544c7752a36a5dc030076c (patch)
treeba7b3a41268553dbbd39f10471e5f8a3b6fb54a0 /drivers/net/ethernet/pensando/ionic/ionic_dev.c
parentc0b03e8399505a5aafe3a38e287213f523d890af (diff)
downloadlinux-d2662072c094be6dd7544c7752a36a5dc030076c.tar.xz
ionic: monitor fw status generation
The top 4 bits of the fw_status in dev_info_regs is reserved for the status generation. This generation number is an arbitrary value defined when firmware starts up. If the FW is killed/crashed/stopped and then restarted, it will create a different generation number. With this mechanism, the host driver can detect that the FW has crashed and restarted, and the driver can then take steps to re-initialize its connection. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/pensando/ionic/ionic_dev.c')
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_dev.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
index 1dfe962e22e0..9aac647290f7 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
@@ -106,6 +106,8 @@ int ionic_dev_setup(struct ionic *ionic)
idev->last_fw_hb = 0;
idev->fw_hb_ready = true;
idev->fw_status_ready = true;
+ idev->fw_generation = IONIC_FW_STS_F_GENERATION &
+ ioread8(&idev->dev_info_regs->fw_status);
mod_timer(&ionic->watchdog_timer,
round_jiffies(jiffies + ionic->watchdog_period));
@@ -121,7 +123,9 @@ int ionic_heartbeat_check(struct ionic *ionic)
{
struct ionic_dev *idev = &ionic->idev;
unsigned long check_time, last_check_time;
- bool fw_status_ready, fw_hb_ready;
+ bool fw_status_ready = true;
+ bool fw_hb_ready;
+ u8 fw_generation;
u8 fw_status;
u32 fw_hb;
@@ -140,9 +144,29 @@ do_check_time:
/* firmware is useful only if the running bit is set and
* fw_status != 0xff (bad PCI read)
+ * If fw_status is not ready don't bother with the generation.
*/
fw_status = ioread8(&idev->dev_info_regs->fw_status);
- fw_status_ready = (fw_status != 0xff) && (fw_status & IONIC_FW_STS_F_RUNNING);
+
+ if (fw_status == 0xff || !(fw_status & IONIC_FW_STS_F_RUNNING)) {
+ fw_status_ready = false;
+ } else {
+ fw_generation = fw_status & IONIC_FW_STS_F_GENERATION;
+ if (idev->fw_generation != fw_generation) {
+ dev_info(ionic->dev, "FW generation 0x%02x -> 0x%02x\n",
+ idev->fw_generation, fw_generation);
+
+ idev->fw_generation = fw_generation;
+
+ /* If the generation changed, the fw status is not
+ * ready so we need to trigger a fw-down cycle. After
+ * the down, the next watchdog will see the fw is up
+ * and the generation value stable, so will trigger
+ * the fw-up activity.
+ */
+ fw_status_ready = false;
+ }
+ }
/* is this a transition? */
if (fw_status_ready != idev->fw_status_ready) {