Skip to content

Commit d266207

Browse files
emuslndavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c0b03e8 commit d266207

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

drivers/net/ethernet/pensando/ionic/ionic_dev.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ int ionic_dev_setup(struct ionic *ionic)
106106
idev->last_fw_hb = 0;
107107
idev->fw_hb_ready = true;
108108
idev->fw_status_ready = true;
109+
idev->fw_generation = IONIC_FW_STS_F_GENERATION &
110+
ioread8(&idev->dev_info_regs->fw_status);
109111

110112
mod_timer(&ionic->watchdog_timer,
111113
round_jiffies(jiffies + ionic->watchdog_period));
@@ -121,7 +123,9 @@ int ionic_heartbeat_check(struct ionic *ionic)
121123
{
122124
struct ionic_dev *idev = &ionic->idev;
123125
unsigned long check_time, last_check_time;
124-
bool fw_status_ready, fw_hb_ready;
126+
bool fw_status_ready = true;
127+
bool fw_hb_ready;
128+
u8 fw_generation;
125129
u8 fw_status;
126130
u32 fw_hb;
127131

@@ -140,9 +144,29 @@ int ionic_heartbeat_check(struct ionic *ionic)
140144

141145
/* firmware is useful only if the running bit is set and
142146
* fw_status != 0xff (bad PCI read)
147+
* If fw_status is not ready don't bother with the generation.
143148
*/
144149
fw_status = ioread8(&idev->dev_info_regs->fw_status);
145-
fw_status_ready = (fw_status != 0xff) && (fw_status & IONIC_FW_STS_F_RUNNING);
150+
151+
if (fw_status == 0xff || !(fw_status & IONIC_FW_STS_F_RUNNING)) {
152+
fw_status_ready = false;
153+
} else {
154+
fw_generation = fw_status & IONIC_FW_STS_F_GENERATION;
155+
if (idev->fw_generation != fw_generation) {
156+
dev_info(ionic->dev, "FW generation 0x%02x -> 0x%02x\n",
157+
idev->fw_generation, fw_generation);
158+
159+
idev->fw_generation = fw_generation;
160+
161+
/* If the generation changed, the fw status is not
162+
* ready so we need to trigger a fw-down cycle. After
163+
* the down, the next watchdog will see the fw is up
164+
* and the generation value stable, so will trigger
165+
* the fw-up activity.
166+
*/
167+
fw_status_ready = false;
168+
}
169+
}
146170

147171
/* is this a transition? */
148172
if (fw_status_ready != idev->fw_status_ready) {

drivers/net/ethernet/pensando/ionic/ionic_dev.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ struct ionic_dev {
143143
u32 last_fw_hb;
144144
bool fw_hb_ready;
145145
bool fw_status_ready;
146+
u8 fw_generation;
146147

147148
u64 __iomem *db_pages;
148149
dma_addr_t phy_db_pages;

drivers/net/ethernet/pensando/ionic/ionic_if.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2936,6 +2936,8 @@ struct ionic_hwstamp_regs {
29362936
* @asic_type: Asic type
29372937
* @asic_rev: Asic revision
29382938
* @fw_status: Firmware status
2939+
* bit 0 - 1 = fw running
2940+
* bit 4-7 - 4 bit generation number, changes on fw restart
29392941
* @fw_heartbeat: Firmware heartbeat counter
29402942
* @serial_num: Serial number
29412943
* @fw_version: Firmware version
@@ -2949,7 +2951,8 @@ union ionic_dev_info_regs {
29492951
u8 version;
29502952
u8 asic_type;
29512953
u8 asic_rev;
2952-
#define IONIC_FW_STS_F_RUNNING 0x1
2954+
#define IONIC_FW_STS_F_RUNNING 0x01
2955+
#define IONIC_FW_STS_F_GENERATION 0xF0
29532956
u8 fw_status;
29542957
u32 fw_heartbeat;
29552958
char fw_version[IONIC_DEVINFO_FWVERS_BUFLEN];

0 commit comments

Comments
 (0)