cxgbe(4): Minor updates to the shared routines that deal with firmware images.

This commit is contained in:
Navdeep Parhar
2016-03-08 10:07:40 +00:00
parent 89308a40ba
commit fa6d184d93
2 changed files with 58 additions and 85 deletions
-1
View File
@@ -525,7 +525,6 @@ int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
int t4_get_fw_version(struct adapter *adapter, u32 *vers);
int t4_get_tp_version(struct adapter *adapter, u32 *vers);
int t4_get_exprom_version(struct adapter *adapter, u32 *vers);
int t4_check_fw_version(struct adapter *adapter);
int t4_init_hw(struct adapter *adapter, u32 fw_params);
int t4_prep_adapter(struct adapter *adapter, u8 *buf);
int t4_shutdown_adapter(struct adapter *adapter);
+58 -84
View File
@@ -3146,8 +3146,8 @@ int t4_write_flash(struct adapter *adapter, unsigned int addr,
*/
int t4_get_fw_version(struct adapter *adapter, u32 *vers)
{
return t4_read_flash(adapter,
FLASH_FW_START + offsetof(struct fw_hdr, fw_ver), 1,
return t4_read_flash(adapter, FLASH_FW_START +
offsetof(struct fw_hdr, fw_ver), 1,
vers, 0);
}
@@ -3160,8 +3160,8 @@ int t4_get_fw_version(struct adapter *adapter, u32 *vers)
*/
int t4_get_tp_version(struct adapter *adapter, u32 *vers)
{
return t4_read_flash(adapter, FLASH_FW_START + offsetof(struct fw_hdr,
tp_microcode_ver),
return t4_read_flash(adapter, FLASH_FW_START +
offsetof(struct fw_hdr, tp_microcode_ver),
1, vers, 0);
}
@@ -3202,60 +3202,6 @@ int t4_get_exprom_version(struct adapter *adap, u32 *vers)
return 0;
}
/**
* t4_check_fw_version - check if the FW is compatible with this driver
* @adapter: the adapter
*
* Checks if an adapter's FW is compatible with the driver. Returns 0
* if there's exact match, a negative error if the version could not be
* read or there's a major version mismatch, and a positive value if the
* expected major version is found but there's a minor version mismatch.
*/
int t4_check_fw_version(struct adapter *adapter)
{
int ret, major, minor, micro;
int exp_major, exp_minor, exp_micro;
ret = t4_get_fw_version(adapter, &adapter->params.fw_vers);
if (!ret)
ret = t4_get_tp_version(adapter, &adapter->params.tp_vers);
if (ret)
return ret;
major = G_FW_HDR_FW_VER_MAJOR(adapter->params.fw_vers);
minor = G_FW_HDR_FW_VER_MINOR(adapter->params.fw_vers);
micro = G_FW_HDR_FW_VER_MICRO(adapter->params.fw_vers);
switch (chip_id(adapter)) {
case CHELSIO_T4:
exp_major = T4FW_VERSION_MAJOR;
exp_minor = T4FW_VERSION_MINOR;
exp_micro = T4FW_VERSION_MICRO;
break;
case CHELSIO_T5:
exp_major = T5FW_VERSION_MAJOR;
exp_minor = T5FW_VERSION_MINOR;
exp_micro = T5FW_VERSION_MICRO;
break;
default:
CH_ERR(adapter, "Unsupported chip type, %x\n",
chip_id(adapter));
return -EINVAL;
}
if (major != exp_major) { /* major mismatch - fail */
CH_ERR(adapter, "card FW has major version %u, driver wants "
"%u\n", major, exp_major);
return -EINVAL;
}
if (minor == exp_minor && micro == exp_micro)
return 0; /* perfect match */
/* Minor/micro version mismatch. Report it but often it's OK. */
return 1;
}
/**
* t4_flash_erase_sectors - erase a range of flash sectors
* @adapter: the adapter
@@ -3307,6 +3253,29 @@ int t4_flash_cfg_addr(struct adapter *adapter)
return FLASH_CFG_START;
}
/*
* Return TRUE if the specified firmware matches the adapter. I.e. T4
* firmware for T4 adapters, T5 firmware for T5 adapters, etc. We go ahead
* and emit an error message for mismatched firmware to save our caller the
* effort ...
*/
static int t4_fw_matches_chip(struct adapter *adap,
const struct fw_hdr *hdr)
{
/*
* The expression below will return FALSE for any unsupported adapter
* which will keep us "honest" in the future ...
*/
if ((is_t4(adap) && hdr->chip == FW_HDR_CHIP_T4) ||
(is_t5(adap) && hdr->chip == FW_HDR_CHIP_T5) ||
(is_t6(adap) && hdr->chip == FW_HDR_CHIP_T6))
return 1;
CH_ERR(adap,
"FW image (%d) is not suitable for this adapter (%d)\n",
hdr->chip, chip_id(adap));
return 0;
}
/**
* t4_load_fw - download firmware
@@ -3338,40 +3307,39 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
fw_start = FLASH_FW_START;
fw_size = FLASH_FW_MAX_SIZE;
}
if (!size) {
CH_ERR(adap, "FW image has no data\n");
return -EINVAL;
}
if (size & 511) {
CH_ERR(adap, "FW image size not multiple of 512 bytes\n");
CH_ERR(adap,
"FW image size not multiple of 512 bytes\n");
return -EINVAL;
}
if (ntohs(hdr->len512) * 512 != size) {
CH_ERR(adap, "FW image size differs from size in FW header\n");
if ((unsigned int) be16_to_cpu(hdr->len512) * 512 != size) {
CH_ERR(adap,
"FW image size differs from size in FW header\n");
return -EINVAL;
}
if (size > fw_size) {
CH_ERR(adap, "FW image too large, max is %u bytes\n", fw_size);
CH_ERR(adap, "FW image too large, max is %u bytes\n",
fw_size);
return -EFBIG;
}
if ((is_t4(adap) && hdr->chip != FW_HDR_CHIP_T4) ||
(is_t5(adap) && hdr->chip != FW_HDR_CHIP_T5)) {
CH_ERR(adap,
"FW image (%d) is not suitable for this adapter (%d)\n",
hdr->chip, chip_id(adap));
if (!t4_fw_matches_chip(adap, hdr))
return -EINVAL;
}
for (csum = 0, i = 0; i < size / sizeof(csum); i++)
csum += ntohl(p[i]);
csum += be32_to_cpu(p[i]);
if (csum != 0xffffffff) {
CH_ERR(adap, "corrupted firmware image, checksum %#x\n",
csum);
CH_ERR(adap,
"corrupted firmware image, checksum %#x\n", csum);
return -EINVAL;
}
i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */
i = DIV_ROUND_UP(size, sf_sec_size); /* # of sectors spanned */
ret = t4_flash_erase_sectors(adap, fw_start_sec, fw_start_sec + i - 1);
if (ret)
goto out;
@@ -3382,7 +3350,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
* first page with a bad version.
*/
memcpy(first_page, fw_data, SF_PAGE_SIZE);
((struct fw_hdr *)first_page)->fw_ver = htonl(0xffffffff);
((struct fw_hdr *)first_page)->fw_ver = cpu_to_be32(0xffffffff);
ret = t4_write_flash(adap, fw_start, SF_PAGE_SIZE, first_page, 1);
if (ret)
goto out;
@@ -3401,7 +3369,8 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver, 1);
out:
if (ret)
CH_ERR(adap, "firmware download failed, error %d\n", ret);
CH_ERR(adap, "firmware download failed, error %d\n",
ret);
return ret;
}
@@ -6712,11 +6681,11 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
retry:
memset(&c, 0, sizeof(c));
INIT_CMD(c, HELLO, WRITE);
c.err_to_clearinit = htonl(
c.err_to_clearinit = cpu_to_be32(
V_FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
V_FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
V_FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox :
M_FW_HELLO_CMD_MBMASTER) |
V_FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ?
mbox : M_FW_HELLO_CMD_MBMASTER) |
V_FW_HELLO_CMD_MBASYNCNOT(evt_mbox) |
V_FW_HELLO_CMD_STAGE(FW_HELLO_CMD_STAGE_OS) |
F_FW_HELLO_CMD_CLEARINIT);
@@ -6737,7 +6706,7 @@ int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
return ret;
}
v = ntohl(c.err_to_clearinit);
v = be32_to_cpu(c.err_to_clearinit);
master_mbox = G_FW_HELLO_CMD_MBMASTER(v);
if (state) {
if (v & F_FW_HELLO_CMD_ERR)
@@ -6849,7 +6818,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
memset(&c, 0, sizeof(c));
INIT_CMD(c, RESET, WRITE);
c.val = htonl(reset);
c.val = cpu_to_be32(reset);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -6882,8 +6851,8 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
memset(&c, 0, sizeof(c));
INIT_CMD(c, RESET, WRITE);
c.val = htonl(F_PIORST | F_PIORSTMODE);
c.halt_pkd = htonl(F_FW_RESET_CMD_HALT);
c.val = cpu_to_be32(F_PIORST | F_PIORSTMODE);
c.halt_pkd = cpu_to_be32(F_FW_RESET_CMD_HALT);
ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
}
@@ -6902,7 +6871,8 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force)
*/
if (ret == 0 || force) {
t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, F_UPCRST);
t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT, F_PCIE_FW_HALT);
t4_set_reg_field(adap, A_PCIE_FW, F_PCIE_FW_HALT,
F_PCIE_FW_HALT);
}
/*
@@ -7000,9 +6970,13 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
const u8 *fw_data, unsigned int size, int force)
{
const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
unsigned int bootstrap = ntohl(fw_hdr->magic) == FW_HDR_MAGIC_BOOTSTRAP;
unsigned int bootstrap =
be32_to_cpu(fw_hdr->magic) == FW_HDR_MAGIC_BOOTSTRAP;
int reset, ret;
if (!t4_fw_matches_chip(adap, fw_hdr))
return -EINVAL;
if (!bootstrap) {
ret = t4_fw_halt(adap, mbox, force);
if (ret < 0 && !force)
@@ -7021,7 +6995,7 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
* the newly loaded firmware will handle this right by checking
* its header flags to see if it advertises the capability.
*/
reset = ((ntohl(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0);
reset = ((be32_to_cpu(fw_hdr->flags) & FW_HDR_FLAGS_RESET_HALT) == 0);
return t4_fw_restart(adap, mbox, reset);
}