be2net: move FW flash cmd code to be_cmds.c
[cascardo/linux.git] / drivers / net / ethernet / emulex / benet / be_cmds.c
index 8083eca..da3b398 100644 (file)
@@ -2291,10 +2291,11 @@ err:
        return status;
 }
 
-int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
-                           u32 data_size, u32 data_offset,
-                           const char *obj_name, u32 *data_written,
-                           u8 *change_status, u8 *addn_status)
+static int lancer_cmd_write_object(struct be_adapter *adapter,
+                                  struct be_dma_mem *cmd, u32 data_size,
+                                  u32 data_offset, const char *obj_name,
+                                  u32 *data_written, u8 *change_status,
+                                  u8 *addn_status)
 {
        struct be_mcc_wrb *wrb;
        struct lancer_cmd_req_write_object *req;
@@ -2410,7 +2411,8 @@ int be_cmd_query_sfp_info(struct be_adapter *adapter)
        return status;
 }
 
-int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
+static int lancer_cmd_delete_object(struct be_adapter *adapter,
+                                   const char *obj_name)
 {
        struct lancer_cmd_req_delete_object *req;
        struct be_mcc_wrb *wrb;
@@ -2485,9 +2487,9 @@ err_unlock:
        return status;
 }
 
-int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
-                         u32 flash_type, u32 flash_opcode, u32 img_offset,
-                         u32 buf_size)
+static int be_cmd_write_flashrom(struct be_adapter *adapter,
+                                struct be_dma_mem *cmd, u32 flash_type,
+                                u32 flash_opcode, u32 img_offset, u32 buf_size)
 {
        struct be_mcc_wrb *wrb;
        struct be_cmd_write_flashrom *req;
@@ -2533,8 +2535,8 @@ err_unlock:
        return status;
 }
 
-int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
-                        u16 img_optype, u32 img_offset, u32 crc_offset)
+static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
+                               u16 img_optype, u32 img_offset, u32 crc_offset)
 {
        struct be_cmd_read_flash_crc *req;
        struct be_mcc_wrb *wrb;
@@ -2571,6 +2573,567 @@ err:
        return status;
 }
 
+static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
+
+static bool phy_flashing_required(struct be_adapter *adapter)
+{
+       return (adapter->phy.phy_type == PHY_TYPE_TN_8022 &&
+               adapter->phy.interface_type == PHY_TYPE_BASET_10GB);
+}
+
+static bool is_comp_in_ufi(struct be_adapter *adapter,
+                          struct flash_section_info *fsec, int type)
+{
+       int i = 0, img_type = 0;
+       struct flash_section_info_g2 *fsec_g2 = NULL;
+
+       if (BE2_chip(adapter))
+               fsec_g2 = (struct flash_section_info_g2 *)fsec;
+
+       for (i = 0; i < MAX_FLASH_COMP; i++) {
+               if (fsec_g2)
+                       img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type);
+               else
+                       img_type = le32_to_cpu(fsec->fsec_entry[i].type);
+
+               if (img_type == type)
+                       return true;
+       }
+       return false;
+}
+
+static struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
+                                               int header_size,
+                                               const struct firmware *fw)
+{
+       struct flash_section_info *fsec = NULL;
+       const u8 *p = fw->data;
+
+       p += header_size;
+       while (p < (fw->data + fw->size)) {
+               fsec = (struct flash_section_info *)p;
+               if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie)))
+                       return fsec;
+               p += 32;
+       }
+       return NULL;
+}
+
+static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
+                             u32 img_offset, u32 img_size, int hdr_size,
+                             u16 img_optype, bool *crc_match)
+{
+       u32 crc_offset;
+       int status;
+       u8 crc[4];
+
+       status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
+                                     img_size - 4);
+       if (status)
+               return status;
+
+       crc_offset = hdr_size + img_offset + img_size - 4;
+
+       /* Skip flashing, if crc of flashed region matches */
+       if (!memcmp(crc, p + crc_offset, 4))
+               *crc_match = true;
+       else
+               *crc_match = false;
+
+       return status;
+}
+
+static int be_flash(struct be_adapter *adapter, const u8 *img,
+                   struct be_dma_mem *flash_cmd, int optype, int img_size,
+                   u32 img_offset)
+{
+       u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
+       struct be_cmd_write_flashrom *req = flash_cmd->va;
+       int status;
+
+       while (total_bytes) {
+               num_bytes = min_t(u32, 32 * 1024, total_bytes);
+
+               total_bytes -= num_bytes;
+
+               if (!total_bytes) {
+                       if (optype == OPTYPE_PHY_FW)
+                               flash_op = FLASHROM_OPER_PHY_FLASH;
+                       else
+                               flash_op = FLASHROM_OPER_FLASH;
+               } else {
+                       if (optype == OPTYPE_PHY_FW)
+                               flash_op = FLASHROM_OPER_PHY_SAVE;
+                       else
+                               flash_op = FLASHROM_OPER_SAVE;
+               }
+
+               memcpy(req->data_buf, img, num_bytes);
+               img += num_bytes;
+               status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
+                                              flash_op, img_offset +
+                                              bytes_sent, num_bytes);
+               if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
+                   optype == OPTYPE_PHY_FW)
+                       break;
+               else if (status)
+                       return status;
+
+               bytes_sent += num_bytes;
+       }
+       return 0;
+}
+
+/* For BE2, BE3 and BE3-R */
+static int be_flash_BEx(struct be_adapter *adapter,
+                       const struct firmware *fw,
+                       struct be_dma_mem *flash_cmd, int num_of_images)
+{
+       int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
+       struct device *dev = &adapter->pdev->dev;
+       struct flash_section_info *fsec = NULL;
+       int status, i, filehdr_size, num_comp;
+       const struct flash_comp *pflashcomp;
+       bool crc_match;
+       const u8 *p;
+
+       struct flash_comp gen3_flash_types[] = {
+               { BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
+                       BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
+               { BE3_REDBOOT_START, OPTYPE_REDBOOT,
+                       BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
+               { BE3_ISCSI_BIOS_START, OPTYPE_BIOS,
+                       BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
+               { BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS,
+                       BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
+               { BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
+                       BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
+               { BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
+                       BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
+               { BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
+                       BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
+               { BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
+                       BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE},
+               { BE3_NCSI_START, OPTYPE_NCSI_FW,
+                       BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI},
+               { BE3_PHY_FW_START, OPTYPE_PHY_FW,
+                       BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY}
+       };
+
+       struct flash_comp gen2_flash_types[] = {
+               { BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE,
+                       BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI},
+               { BE2_REDBOOT_START, OPTYPE_REDBOOT,
+                       BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE},
+               { BE2_ISCSI_BIOS_START, OPTYPE_BIOS,
+                       BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI},
+               { BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS,
+                       BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE},
+               { BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS,
+                       BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE},
+               { BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP,
+                       BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI},
+               { BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE,
+                       BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE},
+               { BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP,
+                        BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}
+       };
+
+       if (BE3_chip(adapter)) {
+               pflashcomp = gen3_flash_types;
+               filehdr_size = sizeof(struct flash_file_hdr_g3);
+               num_comp = ARRAY_SIZE(gen3_flash_types);
+       } else {
+               pflashcomp = gen2_flash_types;
+               filehdr_size = sizeof(struct flash_file_hdr_g2);
+               num_comp = ARRAY_SIZE(gen2_flash_types);
+               img_hdrs_size = 0;
+       }
+
+       /* Get flash section info*/
+       fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+       if (!fsec) {
+               dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
+               return -1;
+       }
+       for (i = 0; i < num_comp; i++) {
+               if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type))
+                       continue;
+
+               if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) &&
+                   memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
+                       continue;
+
+               if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
+                   !phy_flashing_required(adapter))
+                       continue;
+
+               if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
+                       status = be_check_flash_crc(adapter, fw->data,
+                                                   pflashcomp[i].offset,
+                                                   pflashcomp[i].size,
+                                                   filehdr_size +
+                                                   img_hdrs_size,
+                                                   OPTYPE_REDBOOT, &crc_match);
+                       if (status) {
+                               dev_err(dev,
+                                       "Could not get CRC for 0x%x region\n",
+                                       pflashcomp[i].optype);
+                               continue;
+                       }
+
+                       if (crc_match)
+                               continue;
+               }
+
+               p = fw->data + filehdr_size + pflashcomp[i].offset +
+                       img_hdrs_size;
+               if (p + pflashcomp[i].size > fw->data + fw->size)
+                       return -1;
+
+               status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
+                                 pflashcomp[i].size, 0);
+               if (status) {
+                       dev_err(dev, "Flashing section type 0x%x failed\n",
+                               pflashcomp[i].img_type);
+                       return status;
+               }
+       }
+       return 0;
+}
+
+static u16 be_get_img_optype(struct flash_section_entry fsec_entry)
+{
+       u32 img_type = le32_to_cpu(fsec_entry.type);
+       u16 img_optype = le16_to_cpu(fsec_entry.optype);
+
+       if (img_optype != 0xFFFF)
+               return img_optype;
+
+       switch (img_type) {
+       case IMAGE_FIRMWARE_ISCSI:
+               img_optype = OPTYPE_ISCSI_ACTIVE;
+               break;
+       case IMAGE_BOOT_CODE:
+               img_optype = OPTYPE_REDBOOT;
+               break;
+       case IMAGE_OPTION_ROM_ISCSI:
+               img_optype = OPTYPE_BIOS;
+               break;
+       case IMAGE_OPTION_ROM_PXE:
+               img_optype = OPTYPE_PXE_BIOS;
+               break;
+       case IMAGE_OPTION_ROM_FCOE:
+               img_optype = OPTYPE_FCOE_BIOS;
+               break;
+       case IMAGE_FIRMWARE_BACKUP_ISCSI:
+               img_optype = OPTYPE_ISCSI_BACKUP;
+               break;
+       case IMAGE_NCSI:
+               img_optype = OPTYPE_NCSI_FW;
+               break;
+       case IMAGE_FLASHISM_JUMPVECTOR:
+               img_optype = OPTYPE_FLASHISM_JUMPVECTOR;
+               break;
+       case IMAGE_FIRMWARE_PHY:
+               img_optype = OPTYPE_SH_PHY_FW;
+               break;
+       case IMAGE_REDBOOT_DIR:
+               img_optype = OPTYPE_REDBOOT_DIR;
+               break;
+       case IMAGE_REDBOOT_CONFIG:
+               img_optype = OPTYPE_REDBOOT_CONFIG;
+               break;
+       case IMAGE_UFI_DIR:
+               img_optype = OPTYPE_UFI_DIR;
+               break;
+       default:
+               break;
+       }
+
+       return img_optype;
+}
+
+static int be_flash_skyhawk(struct be_adapter *adapter,
+                           const struct firmware *fw,
+                           struct be_dma_mem *flash_cmd, int num_of_images)
+{
+       int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
+       bool crc_match, old_fw_img, flash_offset_support = true;
+       struct device *dev = &adapter->pdev->dev;
+       struct flash_section_info *fsec = NULL;
+       u32 img_offset, img_size, img_type;
+       u16 img_optype, flash_optype;
+       int status, i, filehdr_size;
+       const u8 *p;
+
+       filehdr_size = sizeof(struct flash_file_hdr_g3);
+       fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+       if (!fsec) {
+               dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
+               return -EINVAL;
+       }
+
+retry_flash:
+       for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
+               img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
+               img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
+               img_type   = le32_to_cpu(fsec->fsec_entry[i].type);
+               img_optype = be_get_img_optype(fsec->fsec_entry[i]);
+               old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF;
+
+               if (img_optype == 0xFFFF)
+                       continue;
+
+               if (flash_offset_support)
+                       flash_optype = OPTYPE_OFFSET_SPECIFIED;
+               else
+                       flash_optype = img_optype;
+
+               /* Don't bother verifying CRC if an old FW image is being
+                * flashed
+                */
+               if (old_fw_img)
+                       goto flash;
+
+               status = be_check_flash_crc(adapter, fw->data, img_offset,
+                                           img_size, filehdr_size +
+                                           img_hdrs_size, flash_optype,
+                                           &crc_match);
+               if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
+                   base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
+                       /* The current FW image on the card does not support
+                        * OFFSET based flashing. Retry using older mechanism
+                        * of OPTYPE based flashing
+                        */
+                       if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
+                               flash_offset_support = false;
+                               goto retry_flash;
+                       }
+
+                       /* The current FW image on the card does not recognize
+                        * the new FLASH op_type. The FW download is partially
+                        * complete. Reboot the server now to enable FW image
+                        * to recognize the new FLASH op_type. To complete the
+                        * remaining process, download the same FW again after
+                        * the reboot.
+                        */
+                       dev_err(dev, "Flash incomplete. Reset the server\n");
+                       dev_err(dev, "Download FW image again after reset\n");
+                       return -EAGAIN;
+               } else if (status) {
+                       dev_err(dev, "Could not get CRC for 0x%x region\n",
+                               img_optype);
+                       return -EFAULT;
+               }
+
+               if (crc_match)
+                       continue;
+
+flash:
+               p = fw->data + filehdr_size + img_offset + img_hdrs_size;
+               if (p + img_size > fw->data + fw->size)
+                       return -1;
+
+               status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
+                                 img_offset);
+
+               /* The current FW image on the card does not support OFFSET
+                * based flashing. Retry using older mechanism of OPTYPE based
+                * flashing
+                */
+               if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
+                   flash_optype == OPTYPE_OFFSET_SPECIFIED) {
+                       flash_offset_support = false;
+                       goto retry_flash;
+               }
+
+               /* For old FW images ignore ILLEGAL_FIELD error or errors on
+                * UFI_DIR region
+                */
+               if (old_fw_img &&
+                   (base_status(status) == MCC_STATUS_ILLEGAL_FIELD ||
+                    (img_optype == OPTYPE_UFI_DIR &&
+                     base_status(status) == MCC_STATUS_FAILED))) {
+                       continue;
+               } else if (status) {
+                       dev_err(dev, "Flashing section type 0x%x failed\n",
+                               img_type);
+                       return -EFAULT;
+               }
+       }
+       return 0;
+}
+
+int lancer_fw_download(struct be_adapter *adapter,
+                      const struct firmware *fw)
+{
+       struct device *dev = &adapter->pdev->dev;
+       struct be_dma_mem flash_cmd;
+       const u8 *data_ptr = NULL;
+       u8 *dest_image_ptr = NULL;
+       size_t image_size = 0;
+       u32 chunk_size = 0;
+       u32 data_written = 0;
+       u32 offset = 0;
+       int status = 0;
+       u8 add_status = 0;
+       u8 change_status;
+
+       if (!IS_ALIGNED(fw->size, sizeof(u32))) {
+               dev_err(dev, "FW image size should be multiple of 4\n");
+               return -EINVAL;
+       }
+
+       flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
+                               + LANCER_FW_DOWNLOAD_CHUNK;
+       flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size,
+                                          &flash_cmd.dma, GFP_KERNEL);
+       if (!flash_cmd.va)
+               return -ENOMEM;
+
+       dest_image_ptr = flash_cmd.va +
+                               sizeof(struct lancer_cmd_req_write_object);
+       image_size = fw->size;
+       data_ptr = fw->data;
+
+       while (image_size) {
+               chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK);
+
+               /* Copy the image chunk content. */
+               memcpy(dest_image_ptr, data_ptr, chunk_size);
+
+               status = lancer_cmd_write_object(adapter, &flash_cmd,
+                                                chunk_size, offset,
+                                                LANCER_FW_DOWNLOAD_LOCATION,
+                                                &data_written, &change_status,
+                                                &add_status);
+               if (status)
+                       break;
+
+               offset += data_written;
+               data_ptr += data_written;
+               image_size -= data_written;
+       }
+
+       if (!status) {
+               /* Commit the FW written */
+               status = lancer_cmd_write_object(adapter, &flash_cmd,
+                                                0, offset,
+                                                LANCER_FW_DOWNLOAD_LOCATION,
+                                                &data_written, &change_status,
+                                                &add_status);
+       }
+
+       dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
+       if (status) {
+               dev_err(dev, "Firmware load error\n");
+               return be_cmd_status(status);
+       }
+
+       dev_info(dev, "Firmware flashed successfully\n");
+
+       if (change_status == LANCER_FW_RESET_NEEDED) {
+               dev_info(dev, "Resetting adapter to activate new FW\n");
+               status = lancer_physdev_ctrl(adapter,
+                                            PHYSDEV_CONTROL_FW_RESET_MASK);
+               if (status) {
+                       dev_err(dev, "Adapter busy, could not reset FW\n");
+                       dev_err(dev, "Reboot server to activate new FW\n");
+               }
+       } else if (change_status != LANCER_NO_RESET_NEEDED) {
+               dev_info(dev, "Reboot server to activate new FW\n");
+       }
+
+       return 0;
+}
+
+/* Check if the flash image file is compatible with the adapter that
+ * is being flashed.
+ */
+static bool be_check_ufi_compatibility(struct be_adapter *adapter,
+                                      struct flash_file_hdr_g3 *fhdr)
+{
+       if (!fhdr) {
+               dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
+               return false;
+       }
+
+       /* First letter of the build version is used to identify
+        * which chip this image file is meant for.
+        */
+       switch (fhdr->build[0]) {
+       case BLD_STR_UFI_TYPE_SH:
+               if (!skyhawk_chip(adapter))
+                       return false;
+               break;
+       case BLD_STR_UFI_TYPE_BE3:
+               if (!BE3_chip(adapter))
+                       return false;
+               break;
+       case BLD_STR_UFI_TYPE_BE2:
+               if (!BE2_chip(adapter))
+                       return false;
+               break;
+       default:
+               return false;
+       }
+
+       /* In BE3 FW images the "asic_type_rev" field doesn't track the
+        * asic_rev of the chips it is compatible with.
+        * When asic_type_rev is 0 the image is compatible only with
+        * pre-BE3-R chips (asic_rev < 0x10)
+        */
+       if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
+               return adapter->asic_rev < 0x10;
+       else
+               return (fhdr->asic_type_rev >= adapter->asic_rev);
+}
+
+int be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
+{
+       struct device *dev = &adapter->pdev->dev;
+       struct flash_file_hdr_g3 *fhdr3;
+       struct image_hdr *img_hdr_ptr;
+       int status = 0, i, num_imgs;
+       struct be_dma_mem flash_cmd;
+
+       fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
+       if (!be_check_ufi_compatibility(adapter, fhdr3)) {
+               dev_err(dev, "Flash image is not compatible with adapter\n");
+               return -EINVAL;
+       }
+
+       flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
+       flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+                                          GFP_KERNEL);
+       if (!flash_cmd.va)
+               return -ENOMEM;
+
+       num_imgs = le32_to_cpu(fhdr3->num_imgs);
+       for (i = 0; i < num_imgs; i++) {
+               img_hdr_ptr = (struct image_hdr *)(fw->data +
+                               (sizeof(struct flash_file_hdr_g3) +
+                                i * sizeof(struct image_hdr)));
+               if (!BE2_chip(adapter) &&
+                   le32_to_cpu(img_hdr_ptr->imageid) != 1)
+                       continue;
+
+               if (skyhawk_chip(adapter))
+                       status = be_flash_skyhawk(adapter, fw, &flash_cmd,
+                                                 num_imgs);
+               else
+                       status = be_flash_BEx(adapter, fw, &flash_cmd,
+                                             num_imgs);
+       }
+
+       dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
+       if (!status)
+               dev_info(dev, "Firmware flashed successfully\n");
+
+       return status;
+}
+
 int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
                            struct be_dma_mem *nonemb_cmd)
 {