diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h index c90e9956fed8..292343ce4c88 100644 --- a/sys/dev/cxgbe/common/common.h +++ b/sys/dev/cxgbe/common/common.h @@ -693,6 +693,8 @@ int t4_fw_halt(struct adapter *adap, unsigned int mbox, int force); 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, diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 85ca854f6f5a..e29f23b16060 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -6745,6 +6745,31 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, 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 diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index c0cec806893f..919034bcc595 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -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,18 +3001,6 @@ prep_firmware(struct adapter *sc) */ default_cfg = firmware_get(fw_info->kld_name); - /* 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) - card_fw_usable = fw_compatible(drv_fw, (const void*)card_fw); - 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) { @@ -3044,6 +3011,74 @@ prep_firmware(struct adapter *sc) 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) { + card_fw_usable = fw_compatible(drv_fw, (const void*)card_fw); + 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; + } + + /* 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 && (!kld_fw_usable || kld_fw->fw_ver == drv_fw->fw_ver)) { /*