From: Shannon Nelson Date: Tue, 27 Jul 2021 17:43:26 +0000 (-0700) Subject: ionic: monitor fw status generation X-Git-Tag: v5.15~428^2~375^2~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d2662072c094be6dd7544c7752a36a5dc030076c;p=platform%2Fkernel%2Flinux-starfive.git 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 Signed-off-by: David S. Miller --- diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c index 1dfe962..9aac647 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) { diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h index c25cf9b..8945aed 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h @@ -143,6 +143,7 @@ struct ionic_dev { u32 last_fw_hb; bool fw_hb_ready; bool fw_status_ready; + u8 fw_generation; u64 __iomem *db_pages; dma_addr_t phy_db_pages; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h index 0478b48..278610e 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_if.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h @@ -2936,6 +2936,8 @@ struct ionic_hwstamp_regs { * @asic_type: Asic type * @asic_rev: Asic revision * @fw_status: Firmware status + * bit 0 - 1 = fw running + * bit 4-7 - 4 bit generation number, changes on fw restart * @fw_heartbeat: Firmware heartbeat counter * @serial_num: Serial number * @fw_version: Firmware version @@ -2949,7 +2951,8 @@ union ionic_dev_info_regs { u8 version; u8 asic_type; u8 asic_rev; -#define IONIC_FW_STS_F_RUNNING 0x1 +#define IONIC_FW_STS_F_RUNNING 0x01 +#define IONIC_FW_STS_F_GENERATION 0xF0 u8 fw_status; u32 fw_heartbeat; char fw_version[IONIC_DEVINFO_FWVERS_BUFLEN];