aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHariprasad Shenai <hariprasad@chelsio.com>2013-12-03 06:35:58 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-03 16:55:40 -0500
commit16e47624e76b43dbef5671af7b9e26589d7018b9 (patch)
treea96b387a9b7b592e65515d25d293fd52715cb18e
parent70ee366689bd6d81f7f25553fc81efddc07eb65b (diff)
cxgb4: Add new scheme to update T4/T5 firmware
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h37
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c242
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c193
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h7
4 files changed, 289 insertions, 190 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 9710a16a26e0..6c9308850453 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -49,13 +49,15 @@
49#include <asm/io.h> 49#include <asm/io.h>
50#include "cxgb4_uld.h" 50#include "cxgb4_uld.h"
51 51
52#define FW_VERSION_MAJOR 1 52#define T4FW_VERSION_MAJOR 0x01
53#define FW_VERSION_MINOR 4 53#define T4FW_VERSION_MINOR 0x06
54#define FW_VERSION_MICRO 0 54#define T4FW_VERSION_MICRO 0x18
55#define T4FW_VERSION_BUILD 0x00
55 56
56#define FW_VERSION_MAJOR_T5 0 57#define T5FW_VERSION_MAJOR 0x01
57#define FW_VERSION_MINOR_T5 0 58#define T5FW_VERSION_MINOR 0x08
58#define FW_VERSION_MICRO_T5 0 59#define T5FW_VERSION_MICRO 0x1C
60#define T5FW_VERSION_BUILD 0x00
59 61
60#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) 62#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
61 63
@@ -287,6 +289,23 @@ struct adapter_params {
287 unsigned int ofldq_wr_cred; 289 unsigned int ofldq_wr_cred;
288}; 290};
289 291
292#include "t4fw_api.h"
293
294#define FW_VERSION(chip) ( \
295 FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \
296 FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \
297 FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \
298 FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD))
299#define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf)
300
301struct fw_info {
302 u8 chip;
303 char *fs_name;
304 char *fw_mod_name;
305 struct fw_hdr fw_hdr;
306};
307
308
290struct trace_params { 309struct trace_params {
291 u32 data[TRACE_LEN / 4]; 310 u32 data[TRACE_LEN / 4];
292 u32 mask[TRACE_LEN / 4]; 311 u32 mask[TRACE_LEN / 4];
@@ -901,7 +920,11 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
901int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size); 920int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
902unsigned int t4_flash_cfg_addr(struct adapter *adapter); 921unsigned int t4_flash_cfg_addr(struct adapter *adapter);
903int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size); 922int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
904int t4_check_fw_version(struct adapter *adapter); 923int t4_get_fw_version(struct adapter *adapter, u32 *vers);
924int t4_get_tp_version(struct adapter *adapter, u32 *vers);
925int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
926 const u8 *fw_data, unsigned int fw_size,
927 struct fw_hdr *card_fw, enum dev_state state, int *reset);
905int t4_prep_adapter(struct adapter *adapter); 928int t4_prep_adapter(struct adapter *adapter);
906int t4_port_init(struct adapter *adap, int mbox, int pf, int vf); 929int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
907void t4_fatal_err(struct adapter *adapter); 930void t4_fatal_err(struct adapter *adapter);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 35933cd18e0f..d6b12e035a7d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -276,9 +276,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
276 { 0, } 276 { 0, }
277}; 277};
278 278
279#define FW_FNAME "cxgb4/t4fw.bin" 279#define FW4_FNAME "cxgb4/t4fw.bin"
280#define FW5_FNAME "cxgb4/t5fw.bin" 280#define FW5_FNAME "cxgb4/t5fw.bin"
281#define FW_CFNAME "cxgb4/t4-config.txt" 281#define FW4_CFNAME "cxgb4/t4-config.txt"
282#define FW5_CFNAME "cxgb4/t5-config.txt" 282#define FW5_CFNAME "cxgb4/t5-config.txt"
283 283
284MODULE_DESCRIPTION(DRV_DESC); 284MODULE_DESCRIPTION(DRV_DESC);
@@ -286,7 +286,7 @@ MODULE_AUTHOR("Chelsio Communications");
286MODULE_LICENSE("Dual BSD/GPL"); 286MODULE_LICENSE("Dual BSD/GPL");
287MODULE_VERSION(DRV_VERSION); 287MODULE_VERSION(DRV_VERSION);
288MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl); 288MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
289MODULE_FIRMWARE(FW_FNAME); 289MODULE_FIRMWARE(FW4_FNAME);
290MODULE_FIRMWARE(FW5_FNAME); 290MODULE_FIRMWARE(FW5_FNAME);
291 291
292/* 292/*
@@ -1071,72 +1071,6 @@ freeout: t4_free_sge_resources(adap);
1071} 1071}
1072 1072
1073/* 1073/*
1074 * Returns 0 if new FW was successfully loaded, a positive errno if a load was
1075 * started but failed, and a negative errno if flash load couldn't start.
1076 */
1077static int upgrade_fw(struct adapter *adap)
1078{
1079 int ret;
1080 u32 vers, exp_major;
1081 const struct fw_hdr *hdr;
1082 const struct firmware *fw;
1083 struct device *dev = adap->pdev_dev;
1084 char *fw_file_name;
1085
1086 switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
1087 case CHELSIO_T4:
1088 fw_file_name = FW_FNAME;
1089 exp_major = FW_VERSION_MAJOR;
1090 break;
1091 case CHELSIO_T5:
1092 fw_file_name = FW5_FNAME;
1093 exp_major = FW_VERSION_MAJOR_T5;
1094 break;
1095 default:
1096 dev_err(dev, "Unsupported chip type, %x\n", adap->params.chip);
1097 return -EINVAL;
1098 }
1099
1100 ret = request_firmware(&fw, fw_file_name, dev);
1101 if (ret < 0) {
1102 dev_err(dev, "unable to load firmware image %s, error %d\n",
1103 fw_file_name, ret);
1104 return ret;
1105 }
1106
1107 hdr = (const struct fw_hdr *)fw->data;
1108 vers = ntohl(hdr->fw_ver);
1109 if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) {
1110 ret = -EINVAL; /* wrong major version, won't do */
1111 goto out;
1112 }
1113
1114 /*
1115 * If the flash FW is unusable or we found something newer, load it.
1116 */
1117 if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major ||
1118 vers > adap->params.fw_vers) {
1119 dev_info(dev, "upgrading firmware ...\n");
1120 ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size,
1121 /*force=*/false);
1122 if (!ret)
1123 dev_info(dev,
1124 "firmware upgraded to version %pI4 from %s\n",
1125 &hdr->fw_ver, fw_file_name);
1126 else
1127 dev_err(dev, "firmware upgrade failed! err=%d\n", -ret);
1128 } else {
1129 /*
1130 * Tell our caller that we didn't upgrade the firmware.
1131 */
1132 ret = -EINVAL;
1133 }
1134
1135out: release_firmware(fw);
1136 return ret;
1137}
1138
1139/*
1140 * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc. 1074 * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
1141 * The allocated memory is cleared. 1075 * The allocated memory is cleared.
1142 */ 1076 */
@@ -4668,8 +4602,10 @@ static int adap_init0_config(struct adapter *adapter, int reset)
4668 const struct firmware *cf; 4602 const struct firmware *cf;
4669 unsigned long mtype = 0, maddr = 0; 4603 unsigned long mtype = 0, maddr = 0;
4670 u32 finiver, finicsum, cfcsum; 4604 u32 finiver, finicsum, cfcsum;
4671 int ret, using_flash; 4605 int ret;
4606 int config_issued = 0;
4672 char *fw_config_file, fw_config_file_path[256]; 4607 char *fw_config_file, fw_config_file_path[256];
4608 char *config_name = NULL;
4673 4609
4674 /* 4610 /*
4675 * Reset device if necessary. 4611 * Reset device if necessary.
@@ -4688,7 +4624,7 @@ static int adap_init0_config(struct adapter *adapter, int reset)
4688 */ 4624 */
4689 switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) { 4625 switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
4690 case CHELSIO_T4: 4626 case CHELSIO_T4:
4691 fw_config_file = FW_CFNAME; 4627 fw_config_file = FW4_CFNAME;
4692 break; 4628 break;
4693 case CHELSIO_T5: 4629 case CHELSIO_T5:
4694 fw_config_file = FW5_CFNAME; 4630 fw_config_file = FW5_CFNAME;
@@ -4702,13 +4638,16 @@ static int adap_init0_config(struct adapter *adapter, int reset)
4702 4638
4703 ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev); 4639 ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev);
4704 if (ret < 0) { 4640 if (ret < 0) {
4705 using_flash = 1; 4641 config_name = "On FLASH";
4706 mtype = FW_MEMTYPE_CF_FLASH; 4642 mtype = FW_MEMTYPE_CF_FLASH;
4707 maddr = t4_flash_cfg_addr(adapter); 4643 maddr = t4_flash_cfg_addr(adapter);
4708 } else { 4644 } else {
4709 u32 params[7], val[7]; 4645 u32 params[7], val[7];
4710 4646
4711 using_flash = 0; 4647 sprintf(fw_config_file_path,
4648 "/lib/firmware/%s", fw_config_file);
4649 config_name = fw_config_file_path;
4650
4712 if (cf->size >= FLASH_CFG_MAX_SIZE) 4651 if (cf->size >= FLASH_CFG_MAX_SIZE)
4713 ret = -ENOMEM; 4652 ret = -ENOMEM;
4714 else { 4653 else {
@@ -4776,6 +4715,26 @@ static int adap_init0_config(struct adapter *adapter, int reset)
4776 FW_LEN16(caps_cmd)); 4715 FW_LEN16(caps_cmd));
4777 ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd), 4716 ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
4778 &caps_cmd); 4717 &caps_cmd);
4718
4719 /* If the CAPS_CONFIG failed with an ENOENT (for a Firmware
4720 * Configuration File in FLASH), our last gasp effort is to use the
4721 * Firmware Configuration File which is embedded in the firmware. A
4722 * very few early versions of the firmware didn't have one embedded
4723 * but we can ignore those.
4724 */
4725 if (ret == -ENOENT) {
4726 memset(&caps_cmd, 0, sizeof(caps_cmd));
4727 caps_cmd.op_to_write =
4728 htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
4729 FW_CMD_REQUEST |
4730 FW_CMD_READ);
4731 caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
4732 ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd,
4733 sizeof(caps_cmd), &caps_cmd);
4734 config_name = "Firmware Default";
4735 }
4736
4737 config_issued = 1;
4779 if (ret < 0) 4738 if (ret < 0)
4780 goto bye; 4739 goto bye;
4781 4740
@@ -4816,7 +4775,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
4816 if (ret < 0) 4775 if (ret < 0)
4817 goto bye; 4776 goto bye;
4818 4777
4819 sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file);
4820 /* 4778 /*
4821 * Return successfully and note that we're operating with parameters 4779 * Return successfully and note that we're operating with parameters
4822 * not supplied by the driver, rather than from hard-wired 4780 * not supplied by the driver, rather than from hard-wired
@@ -4824,11 +4782,8 @@ static int adap_init0_config(struct adapter *adapter, int reset)
4824 */ 4782 */
4825 adapter->flags |= USING_SOFT_PARAMS; 4783 adapter->flags |= USING_SOFT_PARAMS;
4826 dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\ 4784 dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\
4827 "Configuration File %s, version %#x, computed checksum %#x\n", 4785 "Configuration File \"%s\", version %#x, computed checksum %#x\n",
4828 (using_flash 4786 config_name, finiver, cfcsum);
4829 ? "in device FLASH"
4830 : fw_config_file_path),
4831 finiver, cfcsum);
4832 return 0; 4787 return 0;
4833 4788
4834 /* 4789 /*
@@ -4837,9 +4792,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
4837 * want to issue a warning since this is fairly common.) 4792 * want to issue a warning since this is fairly common.)
4838 */ 4793 */
4839bye: 4794bye:
4840 if (ret != -ENOENT) 4795 if (config_issued && ret != -ENOENT)
4841 dev_warn(adapter->pdev_dev, "Configuration file error %d\n", 4796 dev_warn(adapter->pdev_dev, "\"%s\" configuration file error %d\n",
4842 -ret); 4797 config_name, -ret);
4843 return ret; 4798 return ret;
4844} 4799}
4845 4800
@@ -5086,6 +5041,47 @@ bye:
5086 return ret; 5041 return ret;
5087} 5042}
5088 5043
5044static struct fw_info fw_info_array[] = {
5045 {
5046 .chip = CHELSIO_T4,
5047 .fs_name = FW4_CFNAME,
5048 .fw_mod_name = FW4_FNAME,
5049 .fw_hdr = {
5050 .chip = FW_HDR_CHIP_T4,
5051 .fw_ver = __cpu_to_be32(FW_VERSION(T4)),
5052 .intfver_nic = FW_INTFVER(T4, NIC),
5053 .intfver_vnic = FW_INTFVER(T4, VNIC),
5054 .intfver_ri = FW_INTFVER(T4, RI),
5055 .intfver_iscsi = FW_INTFVER(T4, ISCSI),
5056 .intfver_fcoe = FW_INTFVER(T4, FCOE),
5057 },
5058 }, {
5059 .chip = CHELSIO_T5,
5060 .fs_name = FW5_CFNAME,
5061 .fw_mod_name = FW5_FNAME,
5062 .fw_hdr = {
5063 .chip = FW_HDR_CHIP_T5,
5064 .fw_ver = __cpu_to_be32(FW_VERSION(T5)),
5065 .intfver_nic = FW_INTFVER(T5, NIC),
5066 .intfver_vnic = FW_INTFVER(T5, VNIC),
5067 .intfver_ri = FW_INTFVER(T5, RI),
5068 .intfver_iscsi = FW_INTFVER(T5, ISCSI),
5069 .intfver_fcoe = FW_INTFVER(T5, FCOE),
5070 },
5071 }
5072};
5073
5074static struct fw_info *find_fw_info(int chip)
5075{
5076 int i;
5077
5078 for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) {
5079 if (fw_info_array[i].chip == chip)
5080 return &fw_info_array[i];
5081 }
5082 return NULL;
5083}
5084
5089/* 5085/*
5090 * Phase 0 of initialization: contact FW, obtain config, perform basic init. 5086 * Phase 0 of initialization: contact FW, obtain config, perform basic init.
5091 */ 5087 */
@@ -5123,44 +5119,54 @@ static int adap_init0(struct adapter *adap)
5123 * later reporting and B. to warn if the currently loaded firmware 5119 * later reporting and B. to warn if the currently loaded firmware
5124 * is excessively mismatched relative to the driver.) 5120 * is excessively mismatched relative to the driver.)
5125 */ 5121 */
5126 ret = t4_check_fw_version(adap); 5122 t4_get_fw_version(adap, &adap->params.fw_vers);
5127 5123 t4_get_tp_version(adap, &adap->params.tp_vers);
5128 /* The error code -EFAULT is returned by t4_check_fw_version() if
5129 * firmware on adapter < supported firmware. If firmware on adapter
5130 * is too old (not supported by driver) and we're the MASTER_PF set
5131 * adapter state to DEV_STATE_UNINIT to force firmware upgrade
5132 * and reinitialization.
5133 */
5134 if ((adap->flags & MASTER_PF) && ret == -EFAULT)
5135 state = DEV_STATE_UNINIT;
5136 if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) { 5124 if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
5137 if (ret == -EINVAL || ret == -EFAULT || ret > 0) { 5125 struct fw_info *fw_info;
5138 if (upgrade_fw(adap) >= 0) { 5126 struct fw_hdr *card_fw;
5139 /* 5127 const struct firmware *fw;
5140 * Note that the chip was reset as part of the 5128 const u8 *fw_data = NULL;
5141 * firmware upgrade so we don't reset it again 5129 unsigned int fw_size = 0;
5142 * below and grab the new firmware version. 5130
5143 */ 5131 /* This is the firmware whose headers the driver was compiled
5144 reset = 0; 5132 * against
5145 ret = t4_check_fw_version(adap); 5133 */
5146 } else 5134 fw_info = find_fw_info(CHELSIO_CHIP_VERSION(adap->params.chip));
5147 if (ret == -EFAULT) { 5135 if (fw_info == NULL) {
5148 /* 5136 dev_err(adap->pdev_dev,
5149 * Firmware is old but still might 5137 "unable to get firmware info for chip %d.\n",
5150 * work if we force reinitialization 5138 CHELSIO_CHIP_VERSION(adap->params.chip));
5151 * of the adapter. Ignoring FW upgrade 5139 return -EINVAL;
5152 * failure.
5153 */
5154 dev_warn(adap->pdev_dev,
5155 "Ignoring firmware upgrade "
5156 "failure, and forcing driver "
5157 "to reinitialize the "
5158 "adapter.\n");
5159 ret = 0;
5160 }
5161 } 5140 }
5141
5142 /* allocate memory to read the header of the firmware on the
5143 * card
5144 */
5145 card_fw = t4_alloc_mem(sizeof(*card_fw));
5146
5147 /* Get FW from from /lib/firmware/ */
5148 ret = request_firmware(&fw, fw_info->fw_mod_name,
5149 adap->pdev_dev);
5150 if (ret < 0) {
5151 dev_err(adap->pdev_dev,
5152 "unable to load firmware image %s, error %d\n",
5153 fw_info->fw_mod_name, ret);
5154 } else {
5155 fw_data = fw->data;
5156 fw_size = fw->size;
5157 }
5158
5159 /* upgrade FW logic */
5160 ret = t4_prep_fw(adap, fw_info, fw_data, fw_size, card_fw,
5161 state, &reset);
5162
5163 /* Cleaning up */
5164 if (fw != NULL)
5165 release_firmware(fw);
5166 t4_free_mem(card_fw);
5167
5162 if (ret < 0) 5168 if (ret < 0)
5163 return ret; 5169 goto bye;
5164 } 5170 }
5165 5171
5166 /* 5172 /*
@@ -5245,7 +5251,7 @@ static int adap_init0(struct adapter *adap)
5245 if (ret == -ENOENT) { 5251 if (ret == -ENOENT) {
5246 dev_info(adap->pdev_dev, 5252 dev_info(adap->pdev_dev,
5247 "No Configuration File present " 5253 "No Configuration File present "
5248 "on adapter. Using hard-wired " 5254 "on adapter. Using hard-wired "
5249 "configuration parameters.\n"); 5255 "configuration parameters.\n");
5250 ret = adap_init0_no_config(adap, reset); 5256 ret = adap_init0_no_config(adap, reset);
5251 } 5257 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 83b5e42b66a9..74a6fce5a15a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -863,104 +863,169 @@ unlock:
863} 863}
864 864
865/** 865/**
866 * get_fw_version - read the firmware version 866 * t4_get_fw_version - read the firmware version
867 * @adapter: the adapter 867 * @adapter: the adapter
868 * @vers: where to place the version 868 * @vers: where to place the version
869 * 869 *
870 * Reads the FW version from flash. 870 * Reads the FW version from flash.
871 */ 871 */
872static int get_fw_version(struct adapter *adapter, u32 *vers) 872int t4_get_fw_version(struct adapter *adapter, u32 *vers)
873{ 873{
874 return t4_read_flash(adapter, adapter->params.sf_fw_start + 874 return t4_read_flash(adapter, FLASH_FW_START +
875 offsetof(struct fw_hdr, fw_ver), 1, vers, 0); 875 offsetof(struct fw_hdr, fw_ver), 1,
876 vers, 0);
876} 877}
877 878
878/** 879/**
879 * get_tp_version - read the TP microcode version 880 * t4_get_tp_version - read the TP microcode version
880 * @adapter: the adapter 881 * @adapter: the adapter
881 * @vers: where to place the version 882 * @vers: where to place the version
882 * 883 *
883 * Reads the TP microcode version from flash. 884 * Reads the TP microcode version from flash.
884 */ 885 */
885static int get_tp_version(struct adapter *adapter, u32 *vers) 886int t4_get_tp_version(struct adapter *adapter, u32 *vers)
886{ 887{
887 return t4_read_flash(adapter, adapter->params.sf_fw_start + 888 return t4_read_flash(adapter, FLASH_FW_START +
888 offsetof(struct fw_hdr, tp_microcode_ver), 889 offsetof(struct fw_hdr, tp_microcode_ver),
889 1, vers, 0); 890 1, vers, 0);
890} 891}
891 892
892/** 893/* Is the given firmware API compatible with the one the driver was compiled
893 * t4_check_fw_version - check if the FW is compatible with this driver 894 * with?
894 * @adapter: the adapter
895 *
896 * Checks if an adapter's FW is compatible with the driver. Returns 0
897 * if there's exact match, a negative error if the version could not be
898 * read or there's a major version mismatch, and a positive value if the
899 * expected major version is found but there's a minor version mismatch.
900 */ 895 */
901int t4_check_fw_version(struct adapter *adapter) 896static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2)
902{ 897{
903 u32 api_vers[2];
904 int ret, major, minor, micro;
905 int exp_major, exp_minor, exp_micro;
906 898
907 ret = get_fw_version(adapter, &adapter->params.fw_vers); 899 /* short circuit if it's the exact same firmware version */
908 if (!ret) 900 if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver)
909 ret = get_tp_version(adapter, &adapter->params.tp_vers); 901 return 1;
910 if (!ret)
911 ret = t4_read_flash(adapter, adapter->params.sf_fw_start +
912 offsetof(struct fw_hdr, intfver_nic),
913 2, api_vers, 1);
914 if (ret)
915 return ret;
916 902
917 major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers); 903#define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x)
918 minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers); 904 if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) &&
919 micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers); 905 SAME_INTF(ri) && SAME_INTF(iscsi) && SAME_INTF(fcoe))
906 return 1;
907#undef SAME_INTF
920 908
921 switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) { 909 return 0;
922 case CHELSIO_T4: 910}
923 exp_major = FW_VERSION_MAJOR;
924 exp_minor = FW_VERSION_MINOR;
925 exp_micro = FW_VERSION_MICRO;
926 break;
927 case CHELSIO_T5:
928 exp_major = FW_VERSION_MAJOR_T5;
929 exp_minor = FW_VERSION_MINOR_T5;
930 exp_micro = FW_VERSION_MICRO_T5;
931 break;
932 default:
933 dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n",
934 adapter->params.chip);
935 return -EINVAL;
936 }
937 911
938 memcpy(adapter->params.api_vers, api_vers, 912/* The firmware in the filesystem is usable, but should it be installed?
939 sizeof(adapter->params.api_vers)); 913 * This routine explains itself in detail if it indicates the filesystem
914 * firmware should be installed.
915 */
916static int should_install_fs_fw(struct adapter *adap, int card_fw_usable,
917 int k, int c)
918{
919 const char *reason;
940 920
941 if (major < exp_major || (major == exp_major && minor < exp_minor) || 921 if (!card_fw_usable) {
942 (major == exp_major && minor == exp_minor && micro < exp_micro)) { 922 reason = "incompatible or unusable";
943 dev_err(adapter->pdev_dev, 923 goto install;
944 "Card has firmware version %u.%u.%u, minimum "
945 "supported firmware is %u.%u.%u.\n", major, minor,
946 micro, exp_major, exp_minor, exp_micro);
947 return -EFAULT;
948 } 924 }
949 925
950 if (major != exp_major) { /* major mismatch - fail */ 926 if (k > c) {
951 dev_err(adapter->pdev_dev, 927 reason = "older than the version supported with this driver";
952 "card FW has major version %u, driver wants %u\n", 928 goto install;
953 major, exp_major);
954 return -EINVAL;
955 } 929 }
956 930
957 if (minor == exp_minor && micro == exp_micro) 931 return 0;
958 return 0; /* perfect match */ 932
933install:
934 dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, "
935 "installing firmware %u.%u.%u.%u on card.\n",
936 FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
937 FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason,
938 FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
939 FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
959 940
960 /* Minor/micro version mismatch. Report it but often it's OK. */
961 return 1; 941 return 1;
962} 942}
963 943
944int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
945 const u8 *fw_data, unsigned int fw_size,
946 struct fw_hdr *card_fw, enum dev_state state,
947 int *reset)
948{
949 int ret, card_fw_usable, fs_fw_usable;
950 const struct fw_hdr *fs_fw;
951 const struct fw_hdr *drv_fw;
952
953 drv_fw = &fw_info->fw_hdr;
954
955 /* Read the header of the firmware on the card */
956 ret = -t4_read_flash(adap, FLASH_FW_START,
957 sizeof(*card_fw) / sizeof(uint32_t),
958 (uint32_t *)card_fw, 1);
959 if (ret == 0) {
960 card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw);
961 } else {
962 dev_err(adap->pdev_dev,
963 "Unable to read card's firmware header: %d\n", ret);
964 card_fw_usable = 0;
965 }
966
967 if (fw_data != NULL) {
968 fs_fw = (const void *)fw_data;
969 fs_fw_usable = fw_compatible(drv_fw, fs_fw);
970 } else {
971 fs_fw = NULL;
972 fs_fw_usable = 0;
973 }
974
975 if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
976 (!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) {
977 /* Common case: the firmware on the card is an exact match and
978 * the filesystem one is an exact match too, or the filesystem
979 * one is absent/incompatible.
980 */
981 } else if (fs_fw_usable && state == DEV_STATE_UNINIT &&
982 should_install_fs_fw(adap, card_fw_usable,
983 be32_to_cpu(fs_fw->fw_ver),
984 be32_to_cpu(card_fw->fw_ver))) {
985 ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
986 fw_size, 0);
987 if (ret != 0) {
988 dev_err(adap->pdev_dev,
989 "failed to install firmware: %d\n", ret);
990 goto bye;
991 }
992
993 /* Installed successfully, update the cached header too. */
994 memcpy(card_fw, fs_fw, sizeof(*card_fw));
995 card_fw_usable = 1;
996 *reset = 0; /* already reset as part of load_fw */
997 }
998
999 if (!card_fw_usable) {
1000 uint32_t d, c, k;
1001
1002 d = be32_to_cpu(drv_fw->fw_ver);
1003 c = be32_to_cpu(card_fw->fw_ver);
1004 k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0;
1005
1006 dev_err(adap->pdev_dev, "Cannot find a usable firmware: "
1007 "chip state %d, "
1008 "driver compiled with %d.%d.%d.%d, "
1009 "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
1010 state,
1011 FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d),
1012 FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d),
1013 FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
1014 FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c),
1015 FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
1016 FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
1017 ret = EINVAL;
1018 goto bye;
1019 }
1020
1021 /* We're using whatever's on the card and it's known to be good. */
1022 adap->params.fw_vers = be32_to_cpu(card_fw->fw_ver);
1023 adap->params.tp_vers = be32_to_cpu(card_fw->tp_microcode_ver);
1024
1025bye:
1026 return ret;
1027}
1028
964/** 1029/**
965 * t4_flash_erase_sectors - erase a range of flash sectors 1030 * t4_flash_erase_sectors - erase a range of flash sectors
966 * @adapter: the adapter 1031 * @adapter: the adapter
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index 6f77ac487743..74fea74ce0aa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -2157,7 +2157,7 @@ struct fw_debug_cmd {
2157 2157
2158struct fw_hdr { 2158struct fw_hdr {
2159 u8 ver; 2159 u8 ver;
2160 u8 reserved1; 2160 u8 chip; /* terminator chip type */
2161 __be16 len512; /* bin length in units of 512-bytes */ 2161 __be16 len512; /* bin length in units of 512-bytes */
2162 __be32 fw_ver; /* firmware version */ 2162 __be32 fw_ver; /* firmware version */
2163 __be32 tp_microcode_ver; 2163 __be32 tp_microcode_ver;
@@ -2176,6 +2176,11 @@ struct fw_hdr {
2176 __be32 reserved6[23]; 2176 __be32 reserved6[23];
2177}; 2177};
2178 2178
2179enum fw_hdr_chip {
2180 FW_HDR_CHIP_T4,
2181 FW_HDR_CHIP_T5
2182};
2183
2179#define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff) 2184#define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff)
2180#define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff) 2185#define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
2181#define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff) 2186#define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)