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>
This commit is contained in:
parent
c0b03e8399
commit
d2662072c0
3 changed files with 31 additions and 3 deletions
|
@ -106,6 +106,8 @@ int ionic_dev_setup(struct ionic *ionic)
|
||||||
idev->last_fw_hb = 0;
|
idev->last_fw_hb = 0;
|
||||||
idev->fw_hb_ready = true;
|
idev->fw_hb_ready = true;
|
||||||
idev->fw_status_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,
|
mod_timer(&ionic->watchdog_timer,
|
||||||
round_jiffies(jiffies + ionic->watchdog_period));
|
round_jiffies(jiffies + ionic->watchdog_period));
|
||||||
|
@ -121,7 +123,9 @@ int ionic_heartbeat_check(struct ionic *ionic)
|
||||||
{
|
{
|
||||||
struct ionic_dev *idev = &ionic->idev;
|
struct ionic_dev *idev = &ionic->idev;
|
||||||
unsigned long check_time, last_check_time;
|
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;
|
u8 fw_status;
|
||||||
u32 fw_hb;
|
u32 fw_hb;
|
||||||
|
|
||||||
|
@ -140,9 +144,29 @@ do_check_time:
|
||||||
|
|
||||||
/* firmware is useful only if the running bit is set and
|
/* firmware is useful only if the running bit is set and
|
||||||
* fw_status != 0xff (bad PCI read)
|
* 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 = 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? */
|
/* is this a transition? */
|
||||||
if (fw_status_ready != idev->fw_status_ready) {
|
if (fw_status_ready != idev->fw_status_ready) {
|
||||||
|
|
|
@ -143,6 +143,7 @@ struct ionic_dev {
|
||||||
u32 last_fw_hb;
|
u32 last_fw_hb;
|
||||||
bool fw_hb_ready;
|
bool fw_hb_ready;
|
||||||
bool fw_status_ready;
|
bool fw_status_ready;
|
||||||
|
u8 fw_generation;
|
||||||
|
|
||||||
u64 __iomem *db_pages;
|
u64 __iomem *db_pages;
|
||||||
dma_addr_t phy_db_pages;
|
dma_addr_t phy_db_pages;
|
||||||
|
|
|
@ -2936,6 +2936,8 @@ struct ionic_hwstamp_regs {
|
||||||
* @asic_type: Asic type
|
* @asic_type: Asic type
|
||||||
* @asic_rev: Asic revision
|
* @asic_rev: Asic revision
|
||||||
* @fw_status: Firmware status
|
* @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
|
* @fw_heartbeat: Firmware heartbeat counter
|
||||||
* @serial_num: Serial number
|
* @serial_num: Serial number
|
||||||
* @fw_version: Firmware version
|
* @fw_version: Firmware version
|
||||||
|
@ -2949,7 +2951,8 @@ union ionic_dev_info_regs {
|
||||||
u8 version;
|
u8 version;
|
||||||
u8 asic_type;
|
u8 asic_type;
|
||||||
u8 asic_rev;
|
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;
|
u8 fw_status;
|
||||||
u32 fw_heartbeat;
|
u32 fw_heartbeat;
|
||||||
char fw_version[IONIC_DEVINFO_FWVERS_BUFLEN];
|
char fw_version[IONIC_DEVINFO_FWVERS_BUFLEN];
|
||||||
|
|
Loading…
Add table
Reference in a new issue