|
@@ -276,9 +276,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
|
|
|
{ 0, }
|
|
|
};
|
|
|
|
|
|
-#define FW_FNAME "cxgb4/t4fw.bin"
|
|
|
+#define FW4_FNAME "cxgb4/t4fw.bin"
|
|
|
#define FW5_FNAME "cxgb4/t5fw.bin"
|
|
|
-#define FW_CFNAME "cxgb4/t4-config.txt"
|
|
|
+#define FW4_CFNAME "cxgb4/t4-config.txt"
|
|
|
#define FW5_CFNAME "cxgb4/t5-config.txt"
|
|
|
|
|
|
MODULE_DESCRIPTION(DRV_DESC);
|
|
@@ -286,7 +286,7 @@ MODULE_AUTHOR("Chelsio Communications");
|
|
|
MODULE_LICENSE("Dual BSD/GPL");
|
|
|
MODULE_VERSION(DRV_VERSION);
|
|
|
MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
|
|
|
-MODULE_FIRMWARE(FW_FNAME);
|
|
|
+MODULE_FIRMWARE(FW4_FNAME);
|
|
|
MODULE_FIRMWARE(FW5_FNAME);
|
|
|
|
|
|
/*
|
|
@@ -1070,72 +1070,6 @@ freeout: t4_free_sge_resources(adap);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Returns 0 if new FW was successfully loaded, a positive errno if a load was
|
|
|
- * started but failed, and a negative errno if flash load couldn't start.
|
|
|
- */
|
|
|
-static int upgrade_fw(struct adapter *adap)
|
|
|
-{
|
|
|
- int ret;
|
|
|
- u32 vers, exp_major;
|
|
|
- const struct fw_hdr *hdr;
|
|
|
- const struct firmware *fw;
|
|
|
- struct device *dev = adap->pdev_dev;
|
|
|
- char *fw_file_name;
|
|
|
-
|
|
|
- switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
|
|
|
- case CHELSIO_T4:
|
|
|
- fw_file_name = FW_FNAME;
|
|
|
- exp_major = FW_VERSION_MAJOR;
|
|
|
- break;
|
|
|
- case CHELSIO_T5:
|
|
|
- fw_file_name = FW5_FNAME;
|
|
|
- exp_major = FW_VERSION_MAJOR_T5;
|
|
|
- break;
|
|
|
- default:
|
|
|
- dev_err(dev, "Unsupported chip type, %x\n", adap->params.chip);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- ret = request_firmware(&fw, fw_file_name, dev);
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(dev, "unable to load firmware image %s, error %d\n",
|
|
|
- fw_file_name, ret);
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- hdr = (const struct fw_hdr *)fw->data;
|
|
|
- vers = ntohl(hdr->fw_ver);
|
|
|
- if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) {
|
|
|
- ret = -EINVAL; /* wrong major version, won't do */
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * If the flash FW is unusable or we found something newer, load it.
|
|
|
- */
|
|
|
- if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major ||
|
|
|
- vers > adap->params.fw_vers) {
|
|
|
- dev_info(dev, "upgrading firmware ...\n");
|
|
|
- ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size,
|
|
|
- /*force=*/false);
|
|
|
- if (!ret)
|
|
|
- dev_info(dev,
|
|
|
- "firmware upgraded to version %pI4 from %s\n",
|
|
|
- &hdr->fw_ver, fw_file_name);
|
|
|
- else
|
|
|
- dev_err(dev, "firmware upgrade failed! err=%d\n", -ret);
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * Tell our caller that we didn't upgrade the firmware.
|
|
|
- */
|
|
|
- ret = -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
-out: release_firmware(fw);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
|
|
|
* The allocated memory is cleared.
|
|
@@ -4668,8 +4602,10 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
|
|
const struct firmware *cf;
|
|
|
unsigned long mtype = 0, maddr = 0;
|
|
|
u32 finiver, finicsum, cfcsum;
|
|
|
- int ret, using_flash;
|
|
|
+ int ret;
|
|
|
+ int config_issued = 0;
|
|
|
char *fw_config_file, fw_config_file_path[256];
|
|
|
+ char *config_name = NULL;
|
|
|
|
|
|
/*
|
|
|
* Reset device if necessary.
|
|
@@ -4688,7 +4624,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
|
|
*/
|
|
|
switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
|
|
|
case CHELSIO_T4:
|
|
|
- fw_config_file = FW_CFNAME;
|
|
|
+ fw_config_file = FW4_CFNAME;
|
|
|
break;
|
|
|
case CHELSIO_T5:
|
|
|
fw_config_file = FW5_CFNAME;
|
|
@@ -4702,13 +4638,16 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
|
|
|
|
|
ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev);
|
|
|
if (ret < 0) {
|
|
|
- using_flash = 1;
|
|
|
+ config_name = "On FLASH";
|
|
|
mtype = FW_MEMTYPE_CF_FLASH;
|
|
|
maddr = t4_flash_cfg_addr(adapter);
|
|
|
} else {
|
|
|
u32 params[7], val[7];
|
|
|
|
|
|
- using_flash = 0;
|
|
|
+ sprintf(fw_config_file_path,
|
|
|
+ "/lib/firmware/%s", fw_config_file);
|
|
|
+ config_name = fw_config_file_path;
|
|
|
+
|
|
|
if (cf->size >= FLASH_CFG_MAX_SIZE)
|
|
|
ret = -ENOMEM;
|
|
|
else {
|
|
@@ -4776,6 +4715,26 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
|
|
FW_LEN16(caps_cmd));
|
|
|
ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
|
|
|
&caps_cmd);
|
|
|
+
|
|
|
+ /* If the CAPS_CONFIG failed with an ENOENT (for a Firmware
|
|
|
+ * Configuration File in FLASH), our last gasp effort is to use the
|
|
|
+ * Firmware Configuration File which is embedded in the firmware. A
|
|
|
+ * very few early versions of the firmware didn't have one embedded
|
|
|
+ * but we can ignore those.
|
|
|
+ */
|
|
|
+ if (ret == -ENOENT) {
|
|
|
+ memset(&caps_cmd, 0, sizeof(caps_cmd));
|
|
|
+ caps_cmd.op_to_write =
|
|
|
+ htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
|
|
|
+ FW_CMD_REQUEST |
|
|
|
+ FW_CMD_READ);
|
|
|
+ caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
|
|
|
+ ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd,
|
|
|
+ sizeof(caps_cmd), &caps_cmd);
|
|
|
+ config_name = "Firmware Default";
|
|
|
+ }
|
|
|
+
|
|
|
+ config_issued = 1;
|
|
|
if (ret < 0)
|
|
|
goto bye;
|
|
|
|
|
@@ -4816,7 +4775,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
|
|
if (ret < 0)
|
|
|
goto bye;
|
|
|
|
|
|
- sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file);
|
|
|
/*
|
|
|
* Return successfully and note that we're operating with parameters
|
|
|
* not supplied by the driver, rather than from hard-wired
|
|
@@ -4824,11 +4782,8 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
|
|
*/
|
|
|
adapter->flags |= USING_SOFT_PARAMS;
|
|
|
dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\
|
|
|
- "Configuration File %s, version %#x, computed checksum %#x\n",
|
|
|
- (using_flash
|
|
|
- ? "in device FLASH"
|
|
|
- : fw_config_file_path),
|
|
|
- finiver, cfcsum);
|
|
|
+ "Configuration File \"%s\", version %#x, computed checksum %#x\n",
|
|
|
+ config_name, finiver, cfcsum);
|
|
|
return 0;
|
|
|
|
|
|
/*
|
|
@@ -4837,9 +4792,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
|
|
* want to issue a warning since this is fairly common.)
|
|
|
*/
|
|
|
bye:
|
|
|
- if (ret != -ENOENT)
|
|
|
- dev_warn(adapter->pdev_dev, "Configuration file error %d\n",
|
|
|
- -ret);
|
|
|
+ if (config_issued && ret != -ENOENT)
|
|
|
+ dev_warn(adapter->pdev_dev, "\"%s\" configuration file error %d\n",
|
|
|
+ config_name, -ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -5086,6 +5041,47 @@ bye:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static struct fw_info fw_info_array[] = {
|
|
|
+ {
|
|
|
+ .chip = CHELSIO_T4,
|
|
|
+ .fs_name = FW4_CFNAME,
|
|
|
+ .fw_mod_name = FW4_FNAME,
|
|
|
+ .fw_hdr = {
|
|
|
+ .chip = FW_HDR_CHIP_T4,
|
|
|
+ .fw_ver = __cpu_to_be32(FW_VERSION(T4)),
|
|
|
+ .intfver_nic = FW_INTFVER(T4, NIC),
|
|
|
+ .intfver_vnic = FW_INTFVER(T4, VNIC),
|
|
|
+ .intfver_ri = FW_INTFVER(T4, RI),
|
|
|
+ .intfver_iscsi = FW_INTFVER(T4, ISCSI),
|
|
|
+ .intfver_fcoe = FW_INTFVER(T4, FCOE),
|
|
|
+ },
|
|
|
+ }, {
|
|
|
+ .chip = CHELSIO_T5,
|
|
|
+ .fs_name = FW5_CFNAME,
|
|
|
+ .fw_mod_name = FW5_FNAME,
|
|
|
+ .fw_hdr = {
|
|
|
+ .chip = FW_HDR_CHIP_T5,
|
|
|
+ .fw_ver = __cpu_to_be32(FW_VERSION(T5)),
|
|
|
+ .intfver_nic = FW_INTFVER(T5, NIC),
|
|
|
+ .intfver_vnic = FW_INTFVER(T5, VNIC),
|
|
|
+ .intfver_ri = FW_INTFVER(T5, RI),
|
|
|
+ .intfver_iscsi = FW_INTFVER(T5, ISCSI),
|
|
|
+ .intfver_fcoe = FW_INTFVER(T5, FCOE),
|
|
|
+ },
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+static struct fw_info *find_fw_info(int chip)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) {
|
|
|
+ if (fw_info_array[i].chip == chip)
|
|
|
+ return &fw_info_array[i];
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Phase 0 of initialization: contact FW, obtain config, perform basic init.
|
|
|
*/
|
|
@@ -5123,44 +5119,54 @@ static int adap_init0(struct adapter *adap)
|
|
|
* later reporting and B. to warn if the currently loaded firmware
|
|
|
* is excessively mismatched relative to the driver.)
|
|
|
*/
|
|
|
- ret = t4_check_fw_version(adap);
|
|
|
-
|
|
|
- /* The error code -EFAULT is returned by t4_check_fw_version() if
|
|
|
- * firmware on adapter < supported firmware. If firmware on adapter
|
|
|
- * is too old (not supported by driver) and we're the MASTER_PF set
|
|
|
- * adapter state to DEV_STATE_UNINIT to force firmware upgrade
|
|
|
- * and reinitialization.
|
|
|
- */
|
|
|
- if ((adap->flags & MASTER_PF) && ret == -EFAULT)
|
|
|
- state = DEV_STATE_UNINIT;
|
|
|
+ t4_get_fw_version(adap, &adap->params.fw_vers);
|
|
|
+ t4_get_tp_version(adap, &adap->params.tp_vers);
|
|
|
if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
|
|
|
- if (ret == -EINVAL || ret == -EFAULT || ret > 0) {
|
|
|
- if (upgrade_fw(adap) >= 0) {
|
|
|
- /*
|
|
|
- * Note that the chip was reset as part of the
|
|
|
- * firmware upgrade so we don't reset it again
|
|
|
- * below and grab the new firmware version.
|
|
|
- */
|
|
|
- reset = 0;
|
|
|
- ret = t4_check_fw_version(adap);
|
|
|
- } else
|
|
|
- if (ret == -EFAULT) {
|
|
|
- /*
|
|
|
- * Firmware is old but still might
|
|
|
- * work if we force reinitialization
|
|
|
- * of the adapter. Ignoring FW upgrade
|
|
|
- * failure.
|
|
|
- */
|
|
|
- dev_warn(adap->pdev_dev,
|
|
|
- "Ignoring firmware upgrade "
|
|
|
- "failure, and forcing driver "
|
|
|
- "to reinitialize the "
|
|
|
- "adapter.\n");
|
|
|
- ret = 0;
|
|
|
- }
|
|
|
+ struct fw_info *fw_info;
|
|
|
+ struct fw_hdr *card_fw;
|
|
|
+ const struct firmware *fw;
|
|
|
+ const u8 *fw_data = NULL;
|
|
|
+ unsigned int fw_size = 0;
|
|
|
+
|
|
|
+ /* This is the firmware whose headers the driver was compiled
|
|
|
+ * against
|
|
|
+ */
|
|
|
+ fw_info = find_fw_info(CHELSIO_CHIP_VERSION(adap->params.chip));
|
|
|
+ if (fw_info == NULL) {
|
|
|
+ dev_err(adap->pdev_dev,
|
|
|
+ "unable to get firmware info for chip %d.\n",
|
|
|
+ CHELSIO_CHIP_VERSION(adap->params.chip));
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
+
|
|
|
+ /* allocate memory to read the header of the firmware on the
|
|
|
+ * card
|
|
|
+ */
|
|
|
+ card_fw = t4_alloc_mem(sizeof(*card_fw));
|
|
|
+
|
|
|
+ /* Get FW from from /lib/firmware/ */
|
|
|
+ ret = request_firmware(&fw, fw_info->fw_mod_name,
|
|
|
+ adap->pdev_dev);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(adap->pdev_dev,
|
|
|
+ "unable to load firmware image %s, error %d\n",
|
|
|
+ fw_info->fw_mod_name, ret);
|
|
|
+ } else {
|
|
|
+ fw_data = fw->data;
|
|
|
+ fw_size = fw->size;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* upgrade FW logic */
|
|
|
+ ret = t4_prep_fw(adap, fw_info, fw_data, fw_size, card_fw,
|
|
|
+ state, &reset);
|
|
|
+
|
|
|
+ /* Cleaning up */
|
|
|
+ if (fw != NULL)
|
|
|
+ release_firmware(fw);
|
|
|
+ t4_free_mem(card_fw);
|
|
|
+
|
|
|
if (ret < 0)
|
|
|
- return ret;
|
|
|
+ goto bye;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -5245,7 +5251,7 @@ static int adap_init0(struct adapter *adap)
|
|
|
if (ret == -ENOENT) {
|
|
|
dev_info(adap->pdev_dev,
|
|
|
"No Configuration File present "
|
|
|
- "on adapter. Using hard-wired "
|
|
|
+ "on adapter. Using hard-wired "
|
|
|
"configuration parameters.\n");
|
|
|
ret = adap_init0_no_config(adap, reset);
|
|
|
}
|