be2net: move FW flash cmd code to be_cmds.c
[cascardo/linux.git] / drivers / net / ethernet / emulex / benet / be_main.c
index 34e324f..646b021 100644 (file)
@@ -4490,570 +4490,6 @@ static void be_netpoll(struct net_device *netdev)
 }
 #endif
 
-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[] = {
-               { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE,
-                       FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_iSCSI},
-               { FLASH_REDBOOT_START_g3, OPTYPE_REDBOOT,
-                       FLASH_REDBOOT_IMAGE_MAX_SIZE_g3, IMAGE_BOOT_CODE},
-               { FLASH_iSCSI_BIOS_START_g3, OPTYPE_BIOS,
-                       FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_ISCSI},
-               { FLASH_PXE_BIOS_START_g3, OPTYPE_PXE_BIOS,
-                       FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_PXE},
-               { FLASH_FCoE_BIOS_START_g3, OPTYPE_FCOE_BIOS,
-                       FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_FCoE},
-               { FLASH_iSCSI_BACKUP_IMAGE_START_g3, OPTYPE_ISCSI_BACKUP,
-                       FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_iSCSI},
-               { FLASH_FCoE_PRIMARY_IMAGE_START_g3, OPTYPE_FCOE_FW_ACTIVE,
-                       FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_FCoE},
-               { FLASH_FCoE_BACKUP_IMAGE_START_g3, OPTYPE_FCOE_FW_BACKUP,
-                       FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_FCoE},
-               { FLASH_NCSI_START_g3, OPTYPE_NCSI_FW,
-                       FLASH_NCSI_IMAGE_MAX_SIZE_g3, IMAGE_NCSI},
-               { FLASH_PHY_FW_START_g3, OPTYPE_PHY_FW,
-                       FLASH_PHY_FW_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_PHY}
-       };
-
-       struct flash_comp gen2_flash_types[] = {
-               { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, OPTYPE_ISCSI_ACTIVE,
-                       FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_iSCSI},
-               { FLASH_REDBOOT_START_g2, OPTYPE_REDBOOT,
-                       FLASH_REDBOOT_IMAGE_MAX_SIZE_g2, IMAGE_BOOT_CODE},
-               { FLASH_iSCSI_BIOS_START_g2, OPTYPE_BIOS,
-                       FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_ISCSI},
-               { FLASH_PXE_BIOS_START_g2, OPTYPE_PXE_BIOS,
-                       FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_PXE},
-               { FLASH_FCoE_BIOS_START_g2, OPTYPE_FCOE_BIOS,
-                       FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_FCoE},
-               { FLASH_iSCSI_BACKUP_IMAGE_START_g2, OPTYPE_ISCSI_BACKUP,
-                       FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_iSCSI},
-               { FLASH_FCoE_PRIMARY_IMAGE_START_g2, OPTYPE_FCOE_FW_ACTIVE,
-                       FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_FCoE},
-               { FLASH_FCoE_BACKUP_IMAGE_START_g2, OPTYPE_FCOE_FW_BACKUP,
-                        FLASH_IMAGE_MAX_SIZE_g2, 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;
-}
-
-static int lancer_fw_download(struct be_adapter *adapter,
-                             const struct firmware *fw)
-{
-#define LANCER_FW_DOWNLOAD_CHUNK      (32 * 1024)
-#define LANCER_FW_DOWNLOAD_LOCATION   "/prg"
-       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);
-}
-
-static 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_load_fw(struct be_adapter *adapter, u8 *fw_file)
 {
        const struct firmware *fw;
@@ -5108,6 +4544,9 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
                        return -EINVAL;
 
                mode = nla_get_u16(attr);
+               if (BE3_chip(adapter) && mode == BRIDGE_MODE_VEPA)
+                       return -EOPNOTSUPP;
+
                if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
                        return -EINVAL;