liquidio: fix kernel panic when NIC firmware is older than 1.7.2
Pre-1.7.2 NIC firmware does not support (and does not respond to) the "get speed" command which is sent by the 1.7.2 driver (for CN23XX-225 cards only) during modprobe. Due to a bug in older firmware (with respect to unknown commands), this unsupported command causes a cascade of errors that ends in a kernel panic. Fix it by making the sending of the "get speed" command conditional on the firmware version. Signed-off-by: Rick Farrington <ricardo.farrington@cavium.com> Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9ebcb397aa
commit
4fed38cf26
|
@ -3299,7 +3299,9 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||
{
|
||||
struct lio *lio = NULL;
|
||||
struct net_device *netdev;
|
||||
u8 mac[6], i, j, *fw_ver;
|
||||
u8 mac[6], i, j, *fw_ver, *micro_ver;
|
||||
unsigned long micro;
|
||||
u32 cur_ver;
|
||||
struct octeon_soft_command *sc;
|
||||
struct liquidio_if_cfg_context *ctx;
|
||||
struct liquidio_if_cfg_resp *resp;
|
||||
|
@ -3429,6 +3431,14 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||
fw_ver);
|
||||
}
|
||||
|
||||
/* extract micro version field; point past '<maj>.<min>.' */
|
||||
micro_ver = fw_ver + strlen(LIQUIDIO_BASE_VERSION) + 1;
|
||||
if (kstrtoul(micro_ver, 10, µ) != 0)
|
||||
micro = 0;
|
||||
octeon_dev->fw_info.ver.maj = LIQUIDIO_BASE_MAJOR_VERSION;
|
||||
octeon_dev->fw_info.ver.min = LIQUIDIO_BASE_MINOR_VERSION;
|
||||
octeon_dev->fw_info.ver.rev = micro;
|
||||
|
||||
octeon_swap_8B_data((u64 *)(&resp->cfg_info),
|
||||
(sizeof(struct liquidio_if_cfg_info)) >> 3);
|
||||
|
||||
|
@ -3671,7 +3681,19 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||
OCTEON_CN2350_25GB_SUBSYS_ID ||
|
||||
octeon_dev->subsystem_id ==
|
||||
OCTEON_CN2360_25GB_SUBSYS_ID) {
|
||||
liquidio_get_speed(lio);
|
||||
cur_ver = OCT_FW_VER(octeon_dev->fw_info.ver.maj,
|
||||
octeon_dev->fw_info.ver.min,
|
||||
octeon_dev->fw_info.ver.rev);
|
||||
|
||||
/* speed control unsupported in f/w older than 1.7.2 */
|
||||
if (cur_ver < OCT_FW_VER(1, 7, 2)) {
|
||||
dev_info(&octeon_dev->pci_dev->dev,
|
||||
"speed setting not supported by f/w.");
|
||||
octeon_dev->speed_setting = 25;
|
||||
octeon_dev->no_speed_setting = 1;
|
||||
} else {
|
||||
liquidio_get_speed(lio);
|
||||
}
|
||||
|
||||
if (octeon_dev->speed_setting == 0) {
|
||||
octeon_dev->speed_setting = 25;
|
||||
|
|
|
@ -288,8 +288,17 @@ struct oct_fw_info {
|
|||
*/
|
||||
u32 app_mode;
|
||||
char liquidio_firmware_version[32];
|
||||
/* Fields extracted from legacy string 'liquidio_firmware_version' */
|
||||
struct {
|
||||
u8 maj;
|
||||
u8 min;
|
||||
u8 rev;
|
||||
} ver;
|
||||
};
|
||||
|
||||
#define OCT_FW_VER(maj, min, rev) \
|
||||
(((u32)(maj) << 16) | ((u32)(min) << 8) | ((u32)(rev)))
|
||||
|
||||
/* wrappers around work structs */
|
||||
struct cavium_wk {
|
||||
struct delayed_work work;
|
||||
|
|
Loading…
Reference in New Issue