cxgbe(4): Install the firmware bundled with the driver to the card if it
doesn't seem to have one. This lets the driver recover automatically from incomplete firmware upgrades (panic, reboot, power loss, etc. in the middle of an upgrade). MFC after: 2 weeks Sponsored by: Chelsio Communications
This commit is contained in:
parent
aa52ad5489
commit
98d227f3e8
@ -693,6 +693,8 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force);
|
||||
int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset);
|
||||
int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
|
||||
const u8 *fw_data, unsigned int size, int force);
|
||||
int t4_fw_forceinstall(struct adapter *adap, const u8 *fw_data,
|
||||
unsigned int size);
|
||||
int t4_fw_initialize(struct adapter *adap, unsigned int mbox);
|
||||
int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
|
||||
unsigned int vf, unsigned int nparams, const u32 *params,
|
||||
|
@ -6745,6 +6745,31 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
|
||||
return t4_fw_restart(adap, mbox, reset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Card doesn't have a firmware, install one.
|
||||
*/
|
||||
int t4_fw_forceinstall(struct adapter *adap, const u8 *fw_data,
|
||||
unsigned int size)
|
||||
{
|
||||
const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
|
||||
unsigned int bootstrap =
|
||||
be32_to_cpu(fw_hdr->magic) == FW_HDR_MAGIC_BOOTSTRAP;
|
||||
int ret;
|
||||
|
||||
if (!t4_fw_matches_chip(adap, fw_hdr) || bootstrap)
|
||||
return -EINVAL;
|
||||
|
||||
t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, F_UPCRST);
|
||||
t4_write_reg(adap, A_PCIE_FW, 0); /* Clobber internal state */
|
||||
ret = t4_load_fw(adap, fw_data, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
t4_write_reg(adap, A_PL_RST, F_PIORST | F_PIORSTMODE);
|
||||
msleep(1000);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_fw_initialize - ask FW to initialize the device
|
||||
* @adap: the adapter
|
||||
|
@ -2968,6 +2968,7 @@ install:
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Establish contact with the firmware and determine if we are the master driver
|
||||
* or not, and whether we are responsible for chip initialization.
|
||||
@ -2984,28 +2985,6 @@ prep_firmware(struct adapter *sc)
|
||||
const struct fw_hdr *drv_fw; /* fw header the driver was compiled
|
||||
against */
|
||||
|
||||
/* Contact firmware. */
|
||||
rc = t4_fw_hello(sc, sc->mbox, sc->mbox, MASTER_MAY, &state);
|
||||
if (rc < 0 || state == DEV_STATE_ERR) {
|
||||
rc = -rc;
|
||||
device_printf(sc->dev,
|
||||
"failed to connect to the firmware: %d, %d.\n", rc, state);
|
||||
return (rc);
|
||||
}
|
||||
pf = rc;
|
||||
if (pf == sc->mbox)
|
||||
sc->flags |= MASTER_PF;
|
||||
else if (state == DEV_STATE_UNINIT) {
|
||||
/*
|
||||
* We didn't get to be the master so we definitely won't be
|
||||
* configuring the chip. It's a bug if someone else hasn't
|
||||
* configured it already.
|
||||
*/
|
||||
device_printf(sc->dev, "couldn't be master(%d), "
|
||||
"device not already initialized either(%d).\n", rc, state);
|
||||
return (EDOOFUS);
|
||||
}
|
||||
|
||||
/* This is the firmware whose headers the driver was compiled against */
|
||||
fw_info = find_fw_info(chip_id(sc));
|
||||
if (fw_info == NULL) {
|
||||
@ -3022,18 +3001,6 @@ prep_firmware(struct adapter *sc)
|
||||
*/
|
||||
default_cfg = firmware_get(fw_info->kld_name);
|
||||
|
||||
/* Read the header of the firmware on the card */
|
||||
card_fw = malloc(sizeof(*card_fw), M_CXGBE, M_ZERO | M_WAITOK);
|
||||
rc = -t4_read_flash(sc, FLASH_FW_START,
|
||||
sizeof (*card_fw) / sizeof (uint32_t), (uint32_t *)card_fw, 1);
|
||||
if (rc == 0)
|
||||
card_fw_usable = fw_compatible(drv_fw, (const void*)card_fw);
|
||||
else {
|
||||
device_printf(sc->dev,
|
||||
"Unable to read card's firmware header: %d\n", rc);
|
||||
card_fw_usable = 0;
|
||||
}
|
||||
|
||||
/* This is the firmware in the KLD */
|
||||
fw = firmware_get(fw_info->fw_mod_name);
|
||||
if (fw != NULL) {
|
||||
@ -3044,6 +3011,74 @@ prep_firmware(struct adapter *sc)
|
||||
kld_fw_usable = 0;
|
||||
}
|
||||
|
||||
/* Read the header of the firmware on the card */
|
||||
card_fw = malloc(sizeof(*card_fw), M_CXGBE, M_ZERO | M_WAITOK);
|
||||
rc = -t4_read_flash(sc, FLASH_FW_START,
|
||||
sizeof (*card_fw) / sizeof (uint32_t), (uint32_t *)card_fw, 1);
|
||||
if (rc == 0) {
|
||||
card_fw_usable = fw_compatible(drv_fw, (const void*)card_fw);
|
||||
if (card_fw->fw_ver == be32toh(0xffffffff)) {
|
||||
uint32_t d = be32toh(kld_fw->fw_ver);
|
||||
|
||||
if (!kld_fw_usable) {
|
||||
device_printf(sc->dev,
|
||||
"no firmware on the card and no usable "
|
||||
"firmware bundled with the driver.\n");
|
||||
rc = EIO;
|
||||
goto done;
|
||||
} else if (t4_fw_install == 0) {
|
||||
device_printf(sc->dev,
|
||||
"no firmware on the card and the driver "
|
||||
"is prohibited from installing new "
|
||||
"firmware.\n");
|
||||
rc = EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
device_printf(sc->dev, "no firmware on the card, "
|
||||
"installing firmware %d.%d.%d.%d\n",
|
||||
G_FW_HDR_FW_VER_MAJOR(d), G_FW_HDR_FW_VER_MINOR(d),
|
||||
G_FW_HDR_FW_VER_MICRO(d), G_FW_HDR_FW_VER_BUILD(d));
|
||||
rc = t4_fw_forceinstall(sc, fw->data, fw->datasize);
|
||||
if (rc < 0) {
|
||||
rc = -rc;
|
||||
device_printf(sc->dev,
|
||||
"firmware install failed: %d.\n", rc);
|
||||
goto done;
|
||||
}
|
||||
memcpy(card_fw, kld_fw, sizeof(*card_fw));
|
||||
card_fw_usable = 1;
|
||||
need_fw_reset = 0;
|
||||
}
|
||||
} else {
|
||||
device_printf(sc->dev,
|
||||
"Unable to read card's firmware header: %d\n", rc);
|
||||
card_fw_usable = 0;
|
||||
}
|
||||
|
||||
/* Contact firmware. */
|
||||
rc = t4_fw_hello(sc, sc->mbox, sc->mbox, MASTER_MAY, &state);
|
||||
if (rc < 0 || state == DEV_STATE_ERR) {
|
||||
rc = -rc;
|
||||
device_printf(sc->dev,
|
||||
"failed to connect to the firmware: %d, %d.\n", rc, state);
|
||||
goto done;
|
||||
}
|
||||
pf = rc;
|
||||
if (pf == sc->mbox)
|
||||
sc->flags |= MASTER_PF;
|
||||
else if (state == DEV_STATE_UNINIT) {
|
||||
/*
|
||||
* We didn't get to be the master so we definitely won't be
|
||||
* configuring the chip. It's a bug if someone else hasn't
|
||||
* configured it already.
|
||||
*/
|
||||
device_printf(sc->dev, "couldn't be master(%d), "
|
||||
"device not already initialized either(%d).\n", rc, state);
|
||||
rc = EPROTO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
|
||||
(!kld_fw_usable || kld_fw->fw_ver == drv_fw->fw_ver)) {
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user