Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fed38cf authored by Rick Farrington's avatar Rick Farrington Committed by David S. Miller
Browse files

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: default avatarRick Farrington <ricardo.farrington@cavium.com>
Signed-off-by: default avatarFelix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9ebcb397
Loading
Loading
Loading
Loading
+24 −2
Original line number Diff line number Diff line
@@ -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, &micro) != 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) {
			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;
+9 −0
Original line number Diff line number Diff line
@@ -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;