Date: Sun, 23 Jul 2017 18:10:47 +0000 (UTC) From: Navdeep Parhar <np@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r321390 - in head/sys/dev/cxgbe: . common Message-ID: <201707231810.v6NIAljj034987@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: np Date: Sun Jul 23 18:10:47 2017 New Revision: 321390 URL: https://svnweb.freebsd.org/changeset/base/321390 Log: cxgbe(4): Install the firmware bundled with the driver to the card if it doesn't seem to have one. This lets the driver recover automatically from incomplete firmware upgrades (panic, reboot, power loss, etc. in the middle of an upgrade). MFC after: 2 weeks Sponsored by: Chelsio Communications Modified: head/sys/dev/cxgbe/common/common.h head/sys/dev/cxgbe/common/t4_hw.c head/sys/dev/cxgbe/t4_main.c Modified: head/sys/dev/cxgbe/common/common.h ============================================================================== --- head/sys/dev/cxgbe/common/common.h Sun Jul 23 18:00:11 2017 (r321389) +++ head/sys/dev/cxgbe/common/common.h Sun Jul 23 18:10:47 2017 (r321390) @@ -693,6 +693,8 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox int t4_fw_restart(struct adapter *adap, unsigned int mbox, int reset); int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, const u8 *fw_data, unsigned int size, int force); +int t4_fw_forceinstall(struct adapter *adap, const u8 *fw_data, + unsigned int size); int t4_fw_initialize(struct adapter *adap, unsigned int mbox); int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int nparams, const u32 *params, Modified: head/sys/dev/cxgbe/common/t4_hw.c ============================================================================== --- head/sys/dev/cxgbe/common/t4_hw.c Sun Jul 23 18:00:11 2017 (r321389) +++ head/sys/dev/cxgbe/common/t4_hw.c Sun Jul 23 18:10:47 2017 (r321390) @@ -6745,6 +6745,31 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int m return t4_fw_restart(adap, mbox, reset); } +/* + * Card doesn't have a firmware, install one. + */ +int t4_fw_forceinstall(struct adapter *adap, const u8 *fw_data, + unsigned int size) +{ + const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data; + unsigned int bootstrap = + be32_to_cpu(fw_hdr->magic) == FW_HDR_MAGIC_BOOTSTRAP; + int ret; + + if (!t4_fw_matches_chip(adap, fw_hdr) || bootstrap) + return -EINVAL; + + t4_set_reg_field(adap, A_CIM_BOOT_CFG, F_UPCRST, F_UPCRST); + t4_write_reg(adap, A_PCIE_FW, 0); /* Clobber internal state */ + ret = t4_load_fw(adap, fw_data, size); + if (ret < 0) + return ret; + t4_write_reg(adap, A_PL_RST, F_PIORST | F_PIORSTMODE); + msleep(1000); + + return (0); +} + /** * t4_fw_initialize - ask FW to initialize the device * @adap: the adapter Modified: head/sys/dev/cxgbe/t4_main.c ============================================================================== --- head/sys/dev/cxgbe/t4_main.c Sun Jul 23 18:00:11 2017 (r321389) +++ head/sys/dev/cxgbe/t4_main.c Sun Jul 23 18:10:47 2017 (r321390) @@ -2968,6 +2968,7 @@ install: return (1); } + /* * Establish contact with the firmware and determine if we are the master driver * or not, and whether we are responsible for chip initialization. @@ -2984,28 +2985,6 @@ prep_firmware(struct adapter *sc) const struct fw_hdr *drv_fw; /* fw header the driver was compiled against */ - /* Contact firmware. */ - rc = t4_fw_hello(sc, sc->mbox, sc->mbox, MASTER_MAY, &state); - if (rc < 0 || state == DEV_STATE_ERR) { - rc = -rc; - device_printf(sc->dev, - "failed to connect to the firmware: %d, %d.\n", rc, state); - return (rc); - } - pf = rc; - if (pf == sc->mbox) - sc->flags |= MASTER_PF; - else if (state == DEV_STATE_UNINIT) { - /* - * We didn't get to be the master so we definitely won't be - * configuring the chip. It's a bug if someone else hasn't - * configured it already. - */ - device_printf(sc->dev, "couldn't be master(%d), " - "device not already initialized either(%d).\n", rc, state); - return (EDOOFUS); - } - /* This is the firmware whose headers the driver was compiled against */ fw_info = find_fw_info(chip_id(sc)); if (fw_info == NULL) { @@ -3022,26 +3001,82 @@ prep_firmware(struct adapter *sc) */ default_cfg = firmware_get(fw_info->kld_name); + /* This is the firmware in the KLD */ + fw = firmware_get(fw_info->fw_mod_name); + if (fw != NULL) { + kld_fw = (const void *)fw->data; + kld_fw_usable = fw_compatible(drv_fw, kld_fw); + } else { + kld_fw = NULL; + kld_fw_usable = 0; + } + /* Read the header of the firmware on the card */ card_fw = malloc(sizeof(*card_fw), M_CXGBE, M_ZERO | M_WAITOK); rc = -t4_read_flash(sc, FLASH_FW_START, sizeof (*card_fw) / sizeof (uint32_t), (uint32_t *)card_fw, 1); - if (rc == 0) + if (rc == 0) { card_fw_usable = fw_compatible(drv_fw, (const void*)card_fw); - else { + if (card_fw->fw_ver == be32toh(0xffffffff)) { + uint32_t d = be32toh(kld_fw->fw_ver); + + if (!kld_fw_usable) { + device_printf(sc->dev, + "no firmware on the card and no usable " + "firmware bundled with the driver.\n"); + rc = EIO; + goto done; + } else if (t4_fw_install == 0) { + device_printf(sc->dev, + "no firmware on the card and the driver " + "is prohibited from installing new " + "firmware.\n"); + rc = EIO; + goto done; + } + + device_printf(sc->dev, "no firmware on the card, " + "installing firmware %d.%d.%d.%d\n", + G_FW_HDR_FW_VER_MAJOR(d), G_FW_HDR_FW_VER_MINOR(d), + G_FW_HDR_FW_VER_MICRO(d), G_FW_HDR_FW_VER_BUILD(d)); + rc = t4_fw_forceinstall(sc, fw->data, fw->datasize); + if (rc < 0) { + rc = -rc; + device_printf(sc->dev, + "firmware install failed: %d.\n", rc); + goto done; + } + memcpy(card_fw, kld_fw, sizeof(*card_fw)); + card_fw_usable = 1; + need_fw_reset = 0; + } + } else { device_printf(sc->dev, "Unable to read card's firmware header: %d\n", rc); card_fw_usable = 0; } - /* This is the firmware in the KLD */ - fw = firmware_get(fw_info->fw_mod_name); - if (fw != NULL) { - kld_fw = (const void *)fw->data; - kld_fw_usable = fw_compatible(drv_fw, kld_fw); - } else { - kld_fw = NULL; - kld_fw_usable = 0; + /* Contact firmware. */ + rc = t4_fw_hello(sc, sc->mbox, sc->mbox, MASTER_MAY, &state); + if (rc < 0 || state == DEV_STATE_ERR) { + rc = -rc; + device_printf(sc->dev, + "failed to connect to the firmware: %d, %d.\n", rc, state); + goto done; + } + pf = rc; + if (pf == sc->mbox) + sc->flags |= MASTER_PF; + else if (state == DEV_STATE_UNINIT) { + /* + * We didn't get to be the master so we definitely won't be + * configuring the chip. It's a bug if someone else hasn't + * configured it already. + */ + device_printf(sc->dev, "couldn't be master(%d), " + "device not already initialized either(%d).\n", rc, state); + rc = EPROTO; + goto done; } if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707231810.v6NIAljj034987>