Skip to content

Commit f40e74f

Browse files
Praveen Madhavandavem330
authored andcommitted
csiostor:firmware upgrade fix
This patch fixes removes older means of upgrading Firmware using MAJOR version and adds newer interface version checking mechanism. Please apply this patch on net-next since it depends on previous commits. Signed-off-by: Praveen Madhavan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3552c31 commit f40e74f

File tree

3 files changed

+247
-82
lines changed

3 files changed

+247
-82
lines changed

drivers/scsi/csiostor/csio_hw.c

Lines changed: 201 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -681,43 +681,6 @@ csio_hw_get_tp_version(struct csio_hw *hw, u32 *vers)
681681
vers, 0);
682682
}
683683

684-
/*
685-
* csio_hw_check_fw_version - check if the FW is compatible with
686-
* this driver
687-
* @hw: HW module
688-
*
689-
* Checks if an adapter's FW is compatible with the driver. Returns 0
690-
* if there's exact match, a negative error if the version could not be
691-
* read or there's a major/minor version mismatch/minor.
692-
*/
693-
static int
694-
csio_hw_check_fw_version(struct csio_hw *hw)
695-
{
696-
int ret, major, minor, micro;
697-
698-
ret = csio_hw_get_fw_version(hw, &hw->fwrev);
699-
if (!ret)
700-
ret = csio_hw_get_tp_version(hw, &hw->tp_vers);
701-
if (ret)
702-
return ret;
703-
704-
major = FW_HDR_FW_VER_MAJOR_G(hw->fwrev);
705-
minor = FW_HDR_FW_VER_MINOR_G(hw->fwrev);
706-
micro = FW_HDR_FW_VER_MICRO_G(hw->fwrev);
707-
708-
if (major != FW_VERSION_MAJOR(hw)) { /* major mismatch - fail */
709-
csio_err(hw, "card FW has major version %u, driver wants %u\n",
710-
major, FW_VERSION_MAJOR(hw));
711-
return -EINVAL;
712-
}
713-
714-
if (minor == FW_VERSION_MINOR(hw) && micro == FW_VERSION_MICRO(hw))
715-
return 0; /* perfect match */
716-
717-
/* Minor/micro version mismatch */
718-
return -EINVAL;
719-
}
720-
721684
/*
722685
* csio_hw_fw_dload - download firmware.
723686
* @hw: HW module
@@ -1967,55 +1930,224 @@ csio_hw_no_fwconfig(struct csio_hw *hw, int reset)
19671930
return rv;
19681931
}
19691932

1933+
/* Is the given firmware API compatible with the one the driver was compiled
1934+
* with?
1935+
*/
1936+
static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2)
1937+
{
1938+
1939+
/* short circuit if it's the exact same firmware version */
1940+
if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver)
1941+
return 1;
1942+
1943+
#define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x)
1944+
if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) &&
1945+
SAME_INTF(ri) && SAME_INTF(iscsi) && SAME_INTF(fcoe))
1946+
return 1;
1947+
#undef SAME_INTF
1948+
1949+
return 0;
1950+
}
1951+
1952+
/* The firmware in the filesystem is usable, but should it be installed?
1953+
* This routine explains itself in detail if it indicates the filesystem
1954+
* firmware should be installed.
1955+
*/
1956+
static int csio_should_install_fs_fw(struct csio_hw *hw, int card_fw_usable,
1957+
int k, int c)
1958+
{
1959+
const char *reason;
1960+
1961+
if (!card_fw_usable) {
1962+
reason = "incompatible or unusable";
1963+
goto install;
1964+
}
1965+
1966+
if (k > c) {
1967+
reason = "older than the version supported with this driver";
1968+
goto install;
1969+
}
1970+
1971+
return 0;
1972+
1973+
install:
1974+
csio_err(hw, "firmware on card (%u.%u.%u.%u) is %s, "
1975+
"installing firmware %u.%u.%u.%u on card.\n",
1976+
FW_HDR_FW_VER_MAJOR_G(c), FW_HDR_FW_VER_MINOR_G(c),
1977+
FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c), reason,
1978+
FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k),
1979+
FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k));
1980+
1981+
return 1;
1982+
}
1983+
1984+
static struct fw_info fw_info_array[] = {
1985+
{
1986+
.chip = CHELSIO_T5,
1987+
.fs_name = FW_CFG_NAME_T5,
1988+
.fw_mod_name = FW_FNAME_T5,
1989+
.fw_hdr = {
1990+
.chip = FW_HDR_CHIP_T5,
1991+
.fw_ver = __cpu_to_be32(FW_VERSION(T5)),
1992+
.intfver_nic = FW_INTFVER(T5, NIC),
1993+
.intfver_vnic = FW_INTFVER(T5, VNIC),
1994+
.intfver_ri = FW_INTFVER(T5, RI),
1995+
.intfver_iscsi = FW_INTFVER(T5, ISCSI),
1996+
.intfver_fcoe = FW_INTFVER(T5, FCOE),
1997+
},
1998+
}
1999+
};
2000+
2001+
static struct fw_info *find_fw_info(int chip)
2002+
{
2003+
int i;
2004+
2005+
for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) {
2006+
if (fw_info_array[i].chip == chip)
2007+
return &fw_info_array[i];
2008+
}
2009+
return NULL;
2010+
}
2011+
2012+
int csio_hw_prep_fw(struct csio_hw *hw, struct fw_info *fw_info,
2013+
const u8 *fw_data, unsigned int fw_size,
2014+
struct fw_hdr *card_fw, enum csio_dev_state state,
2015+
int *reset)
2016+
{
2017+
int ret, card_fw_usable, fs_fw_usable;
2018+
const struct fw_hdr *fs_fw;
2019+
const struct fw_hdr *drv_fw;
2020+
2021+
drv_fw = &fw_info->fw_hdr;
2022+
2023+
/* Read the header of the firmware on the card */
2024+
ret = csio_hw_read_flash(hw, FLASH_FW_START,
2025+
sizeof(*card_fw) / sizeof(uint32_t),
2026+
(uint32_t *)card_fw, 1);
2027+
if (ret == 0) {
2028+
card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw);
2029+
} else {
2030+
csio_err(hw,
2031+
"Unable to read card's firmware header: %d\n", ret);
2032+
card_fw_usable = 0;
2033+
}
2034+
2035+
if (fw_data != NULL) {
2036+
fs_fw = (const void *)fw_data;
2037+
fs_fw_usable = fw_compatible(drv_fw, fs_fw);
2038+
} else {
2039+
fs_fw = NULL;
2040+
fs_fw_usable = 0;
2041+
}
2042+
2043+
if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
2044+
(!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) {
2045+
/* Common case: the firmware on the card is an exact match and
2046+
* the filesystem one is an exact match too, or the filesystem
2047+
* one is absent/incompatible.
2048+
*/
2049+
} else if (fs_fw_usable && state == CSIO_DEV_STATE_UNINIT &&
2050+
csio_should_install_fs_fw(hw, card_fw_usable,
2051+
be32_to_cpu(fs_fw->fw_ver),
2052+
be32_to_cpu(card_fw->fw_ver))) {
2053+
ret = csio_hw_fw_upgrade(hw, hw->pfn, fw_data,
2054+
fw_size, 0);
2055+
if (ret != 0) {
2056+
csio_err(hw,
2057+
"failed to install firmware: %d\n", ret);
2058+
goto bye;
2059+
}
2060+
2061+
/* Installed successfully, update the cached header too. */
2062+
memcpy(card_fw, fs_fw, sizeof(*card_fw));
2063+
card_fw_usable = 1;
2064+
*reset = 0; /* already reset as part of load_fw */
2065+
}
2066+
2067+
if (!card_fw_usable) {
2068+
uint32_t d, c, k;
2069+
2070+
d = be32_to_cpu(drv_fw->fw_ver);
2071+
c = be32_to_cpu(card_fw->fw_ver);
2072+
k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0;
2073+
2074+
csio_err(hw, "Cannot find a usable firmware: "
2075+
"chip state %d, "
2076+
"driver compiled with %d.%d.%d.%d, "
2077+
"card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
2078+
state,
2079+
FW_HDR_FW_VER_MAJOR_G(d), FW_HDR_FW_VER_MINOR_G(d),
2080+
FW_HDR_FW_VER_MICRO_G(d), FW_HDR_FW_VER_BUILD_G(d),
2081+
FW_HDR_FW_VER_MAJOR_G(c), FW_HDR_FW_VER_MINOR_G(c),
2082+
FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c),
2083+
FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k),
2084+
FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k));
2085+
ret = EINVAL;
2086+
goto bye;
2087+
}
2088+
2089+
/* We're using whatever's on the card and it's known to be good. */
2090+
hw->fwrev = be32_to_cpu(card_fw->fw_ver);
2091+
hw->tp_vers = be32_to_cpu(card_fw->tp_microcode_ver);
2092+
2093+
bye:
2094+
return ret;
2095+
}
2096+
19702097
/*
19712098
* Returns -EINVAL if attempts to flash the firmware failed
19722099
* else returns 0,
19732100
* if flashing was not attempted because the card had the
19742101
* latest firmware ECANCELED is returned
19752102
*/
19762103
static int
1977-
csio_hw_flash_fw(struct csio_hw *hw)
2104+
csio_hw_flash_fw(struct csio_hw *hw, int *reset)
19782105
{
19792106
int ret = -ECANCELED;
19802107
const struct firmware *fw;
1981-
const struct fw_hdr *hdr;
1982-
u32 fw_ver;
2108+
struct fw_info *fw_info;
2109+
struct fw_hdr *card_fw;
19832110
struct pci_dev *pci_dev = hw->pdev;
19842111
struct device *dev = &pci_dev->dev ;
2112+
const u8 *fw_data = NULL;
2113+
unsigned int fw_size = 0;
2114+
2115+
/* This is the firmware whose headers the driver was compiled
2116+
* against
2117+
*/
2118+
fw_info = find_fw_info(CHELSIO_CHIP_VERSION(hw->chip_id));
2119+
if (fw_info == NULL) {
2120+
csio_err(hw,
2121+
"unable to get firmware info for chip %d.\n",
2122+
CHELSIO_CHIP_VERSION(hw->chip_id));
2123+
return -EINVAL;
2124+
}
19852125

19862126
if (request_firmware(&fw, CSIO_FW_FNAME(hw), dev) < 0) {
19872127
csio_err(hw, "could not find firmware image %s, err: %d\n",
19882128
CSIO_FW_FNAME(hw), ret);
19892129
return -EINVAL;
19902130
}
19912131

1992-
hdr = (const struct fw_hdr *)fw->data;
1993-
fw_ver = ntohl(hdr->fw_ver);
1994-
if (FW_HDR_FW_VER_MAJOR_G(fw_ver) != FW_VERSION_MAJOR(hw))
1995-
return -EINVAL; /* wrong major version, won't do */
1996-
1997-
/*
1998-
* If the flash FW is unusable or we found something newer, load it.
2132+
/* allocate memory to read the header of the firmware on the
2133+
* card
19992134
*/
2000-
if (FW_HDR_FW_VER_MAJOR_G(hw->fwrev) != FW_VERSION_MAJOR(hw) ||
2001-
fw_ver > hw->fwrev) {
2002-
ret = csio_hw_fw_upgrade(hw, hw->pfn, fw->data, fw->size,
2003-
/*force=*/false);
2004-
if (!ret)
2005-
csio_info(hw,
2006-
"firmware upgraded to version %pI4 from %s\n",
2007-
&hdr->fw_ver, CSIO_FW_FNAME(hw));
2008-
else
2009-
csio_err(hw, "firmware upgrade failed! err=%d\n", ret);
2010-
} else
2011-
ret = -EINVAL;
2135+
card_fw = kmalloc(sizeof(*card_fw), GFP_KERNEL);
20122136

2013-
release_firmware(fw);
2137+
fw_data = fw->data;
2138+
fw_size = fw->size;
20142139

2140+
/* upgrade FW logic */
2141+
ret = csio_hw_prep_fw(hw, fw_info, fw_data, fw_size, card_fw,
2142+
hw->fw_state, reset);
2143+
2144+
/* Cleaning up */
2145+
if (fw != NULL)
2146+
release_firmware(fw);
2147+
kfree(card_fw);
20152148
return ret;
20162149
}
20172150

2018-
20192151
/*
20202152
* csio_hw_configure - Configure HW
20212153
* @hw - HW module
@@ -2071,25 +2203,18 @@ csio_hw_configure(struct csio_hw *hw)
20712203
if (rv != 0)
20722204
goto out;
20732205

2206+
csio_hw_get_fw_version(hw, &hw->fwrev);
2207+
csio_hw_get_tp_version(hw, &hw->tp_vers);
20742208
if (csio_is_hw_master(hw) && hw->fw_state != CSIO_DEV_STATE_INIT) {
2075-
rv = csio_hw_check_fw_version(hw);
2076-
if (rv == -EINVAL) {
20772209

20782210
/* Do firmware update */
2079-
spin_unlock_irq(&hw->lock);
2080-
rv = csio_hw_flash_fw(hw);
2081-
spin_lock_irq(&hw->lock);
2211+
spin_unlock_irq(&hw->lock);
2212+
rv = csio_hw_flash_fw(hw, &reset);
2213+
spin_lock_irq(&hw->lock);
2214+
2215+
if (rv != 0)
2216+
goto out;
20822217

2083-
if (rv == 0) {
2084-
reset = 0;
2085-
/*
2086-
* Note that the chip was reset as part of the
2087-
* firmware upgrade so we don't reset it again
2088-
* below and grab the new firmware version.
2089-
*/
2090-
rv = csio_hw_check_fw_version(hw);
2091-
}
2092-
}
20932218
/*
20942219
* If the firmware doesn't support Configuration
20952220
* Files, use the old Driver-based, hard-wired

drivers/scsi/csiostor/csio_hw.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,8 @@ enum {
201201
SF_ERASE_SECTOR = 0xd8, /* erase sector */
202202

203203
FW_START_SEC = 8, /* first flash sector for FW */
204-
FW_END_SEC = 15, /* last flash sector for FW */
205204
FW_IMG_START = FW_START_SEC * SF_SEC_SIZE,
206-
FW_MAX_SIZE = (FW_END_SEC - FW_START_SEC + 1) * SF_SEC_SIZE,
205+
FW_MAX_SIZE = 16 * SF_SEC_SIZE,
207206

208207
FLASH_CFG_MAX_SIZE = 0x10000 , /* max size of the flash config file*/
209208
FLASH_CFG_OFFSET = 0x1f0000,
@@ -221,7 +220,7 @@ enum {
221220
* Location of firmware image in FLASH.
222221
*/
223222
FLASH_FW_START_SEC = 8,
224-
FLASH_FW_NSECS = 8,
223+
FLASH_FW_NSECS = 16,
225224
FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC),
226225
FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS),
227226

0 commit comments

Comments
 (0)