diff options
author | Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com> | 2012-10-20 02:04:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-10-21 22:15:37 -0400 |
commit | 773a2d7c55a3d63207841c824d21920bd3683460 (patch) | |
tree | 225134f3340d917bfdacbe2055ca98887c5a029d /drivers/net/ethernet/emulex | |
parent | 028991e49a706652cfaec06947ef755e6161a5f4 (diff) |
be2net: Fix FW flashing on Skyhawk-R
FW flash layout on Skyhawk-R is different from BE3-R.
Hence the code needs to be fixed to flash FW on Skyhawk-R.
Also cleaning up code in BE3-R flashing function.
Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 248 |
2 files changed, 173 insertions, 76 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 1a05b79d5c66..d95825f91a9a 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -459,6 +459,7 @@ struct be_adapter { | |||
459 | /* BladeEngine Generation numbers */ | 459 | /* BladeEngine Generation numbers */ |
460 | #define BE_GEN2 2 | 460 | #define BE_GEN2 2 |
461 | #define BE_GEN3 3 | 461 | #define BE_GEN3 3 |
462 | #define SH_HW 4 | ||
462 | 463 | ||
463 | #define ON 1 | 464 | #define ON 1 |
464 | #define OFF 0 | 465 | #define OFF 0 |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index ab077fbeeb5b..2143e06f1ae9 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -3088,6 +3088,47 @@ struct flash_section_info *get_fsec_info(struct be_adapter *adapter, | |||
3088 | return NULL; | 3088 | return NULL; |
3089 | } | 3089 | } |
3090 | 3090 | ||
3091 | static int be_flash(struct be_adapter *adapter, const u8 *img, | ||
3092 | struct be_dma_mem *flash_cmd, int optype, int img_size) | ||
3093 | { | ||
3094 | u32 total_bytes = 0, flash_op, num_bytes = 0; | ||
3095 | int status = 0; | ||
3096 | struct be_cmd_write_flashrom *req = flash_cmd->va; | ||
3097 | |||
3098 | total_bytes = img_size; | ||
3099 | while (total_bytes) { | ||
3100 | num_bytes = min_t(u32, 32*1024, total_bytes); | ||
3101 | |||
3102 | total_bytes -= num_bytes; | ||
3103 | |||
3104 | if (!total_bytes) { | ||
3105 | if (optype == OPTYPE_PHY_FW) | ||
3106 | flash_op = FLASHROM_OPER_PHY_FLASH; | ||
3107 | else | ||
3108 | flash_op = FLASHROM_OPER_FLASH; | ||
3109 | } else { | ||
3110 | if (optype == OPTYPE_PHY_FW) | ||
3111 | flash_op = FLASHROM_OPER_PHY_SAVE; | ||
3112 | else | ||
3113 | flash_op = FLASHROM_OPER_SAVE; | ||
3114 | } | ||
3115 | |||
3116 | memcpy(req->params.data_buf, img, num_bytes); | ||
3117 | img += num_bytes; | ||
3118 | status = be_cmd_write_flashrom(adapter, flash_cmd, optype, | ||
3119 | flash_op, num_bytes); | ||
3120 | if (status) { | ||
3121 | if (status == ILLEGAL_IOCTL_REQ && | ||
3122 | optype == OPTYPE_PHY_FW) | ||
3123 | break; | ||
3124 | dev_err(&adapter->pdev->dev, | ||
3125 | "cmd to write to flash rom failed.\n"); | ||
3126 | return status; | ||
3127 | } | ||
3128 | } | ||
3129 | return 0; | ||
3130 | } | ||
3131 | |||
3091 | static int be_flash_data(struct be_adapter *adapter, | 3132 | static int be_flash_data(struct be_adapter *adapter, |
3092 | const struct firmware *fw, | 3133 | const struct firmware *fw, |
3093 | struct be_dma_mem *flash_cmd, | 3134 | struct be_dma_mem *flash_cmd, |
@@ -3096,12 +3137,9 @@ static int be_flash_data(struct be_adapter *adapter, | |||
3096 | { | 3137 | { |
3097 | int status = 0, i, filehdr_size = 0; | 3138 | int status = 0, i, filehdr_size = 0; |
3098 | int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); | 3139 | int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); |
3099 | u32 total_bytes = 0, flash_op; | ||
3100 | int num_bytes; | ||
3101 | const u8 *p = fw->data; | 3140 | const u8 *p = fw->data; |
3102 | struct be_cmd_write_flashrom *req = flash_cmd->va; | ||
3103 | const struct flash_comp *pflashcomp; | 3141 | const struct flash_comp *pflashcomp; |
3104 | int num_comp, hdr_size; | 3142 | int num_comp, redboot; |
3105 | struct flash_section_info *fsec = NULL; | 3143 | struct flash_section_info *fsec = NULL; |
3106 | 3144 | ||
3107 | struct flash_comp gen3_flash_types[] = { | 3145 | struct flash_comp gen3_flash_types[] = { |
@@ -3170,70 +3208,105 @@ static int be_flash_data(struct be_adapter *adapter, | |||
3170 | memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) | 3208 | memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) |
3171 | continue; | 3209 | continue; |
3172 | 3210 | ||
3173 | if (pflashcomp[i].optype == OPTYPE_PHY_FW) { | 3211 | if (pflashcomp[i].optype == OPTYPE_PHY_FW && |
3174 | if (!phy_flashing_required(adapter)) | 3212 | !phy_flashing_required(adapter)) |
3175 | continue; | 3213 | continue; |
3176 | } | ||
3177 | |||
3178 | hdr_size = filehdr_size + | ||
3179 | (num_of_images * sizeof(struct image_hdr)); | ||
3180 | 3214 | ||
3181 | if ((pflashcomp[i].optype == OPTYPE_REDBOOT) && | 3215 | if (pflashcomp[i].optype == OPTYPE_REDBOOT) { |
3182 | (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, | 3216 | redboot = be_flash_redboot(adapter, fw->data, |
3183 | pflashcomp[i].size, hdr_size))) | 3217 | pflashcomp[i].offset, pflashcomp[i].size, |
3184 | continue; | 3218 | filehdr_size + img_hdrs_size); |
3219 | if (!redboot) | ||
3220 | continue; | ||
3221 | } | ||
3185 | 3222 | ||
3186 | /* Flash the component */ | ||
3187 | p = fw->data; | 3223 | p = fw->data; |
3188 | p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; | 3224 | p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; |
3189 | if (p + pflashcomp[i].size > fw->data + fw->size) | 3225 | if (p + pflashcomp[i].size > fw->data + fw->size) |
3190 | return -1; | 3226 | return -1; |
3191 | total_bytes = pflashcomp[i].size; | 3227 | |
3192 | while (total_bytes) { | 3228 | status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, |
3193 | if (total_bytes > 32*1024) | 3229 | pflashcomp[i].size); |
3194 | num_bytes = 32*1024; | 3230 | if (status) { |
3195 | else | 3231 | dev_err(&adapter->pdev->dev, |
3196 | num_bytes = total_bytes; | 3232 | "Flashing section type %d failed.\n", |
3197 | total_bytes -= num_bytes; | 3233 | pflashcomp[i].img_type); |
3198 | if (!total_bytes) { | 3234 | return status; |
3199 | if (pflashcomp[i].optype == OPTYPE_PHY_FW) | ||
3200 | flash_op = FLASHROM_OPER_PHY_FLASH; | ||
3201 | else | ||
3202 | flash_op = FLASHROM_OPER_FLASH; | ||
3203 | } else { | ||
3204 | if (pflashcomp[i].optype == OPTYPE_PHY_FW) | ||
3205 | flash_op = FLASHROM_OPER_PHY_SAVE; | ||
3206 | else | ||
3207 | flash_op = FLASHROM_OPER_SAVE; | ||
3208 | } | ||
3209 | memcpy(req->params.data_buf, p, num_bytes); | ||
3210 | p += num_bytes; | ||
3211 | status = be_cmd_write_flashrom(adapter, flash_cmd, | ||
3212 | pflashcomp[i].optype, flash_op, num_bytes); | ||
3213 | if (status) { | ||
3214 | if ((status == ILLEGAL_IOCTL_REQ) && | ||
3215 | (pflashcomp[i].optype == | ||
3216 | OPTYPE_PHY_FW)) | ||
3217 | break; | ||
3218 | dev_err(&adapter->pdev->dev, | ||
3219 | "cmd to write to flash rom failed.\n"); | ||
3220 | return -1; | ||
3221 | } | ||
3222 | } | 3235 | } |
3223 | } | 3236 | } |
3224 | return 0; | 3237 | return 0; |
3225 | } | 3238 | } |
3226 | 3239 | ||
3227 | static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) | 3240 | static int be_flash_skyhawk(struct be_adapter *adapter, |
3241 | const struct firmware *fw, | ||
3242 | struct be_dma_mem *flash_cmd, int num_of_images) | ||
3228 | { | 3243 | { |
3229 | if (fhdr == NULL) | 3244 | int status = 0, i, filehdr_size = 0; |
3230 | return 0; | 3245 | int img_offset, img_size, img_optype, redboot; |
3231 | if (fhdr->build[0] == '3') | 3246 | int img_hdrs_size = num_of_images * sizeof(struct image_hdr); |
3232 | return BE_GEN3; | 3247 | const u8 *p = fw->data; |
3233 | else if (fhdr->build[0] == '2') | 3248 | struct flash_section_info *fsec = NULL; |
3234 | return BE_GEN2; | 3249 | |
3235 | else | 3250 | filehdr_size = sizeof(struct flash_file_hdr_g3); |
3236 | return 0; | 3251 | fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); |
3252 | if (!fsec) { | ||
3253 | dev_err(&adapter->pdev->dev, | ||
3254 | "Invalid Cookie. UFI corrupted ?\n"); | ||
3255 | return -1; | ||
3256 | } | ||
3257 | |||
3258 | for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { | ||
3259 | img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); | ||
3260 | img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); | ||
3261 | |||
3262 | switch (le32_to_cpu(fsec->fsec_entry[i].type)) { | ||
3263 | case IMAGE_FIRMWARE_iSCSI: | ||
3264 | img_optype = OPTYPE_ISCSI_ACTIVE; | ||
3265 | break; | ||
3266 | case IMAGE_BOOT_CODE: | ||
3267 | img_optype = OPTYPE_REDBOOT; | ||
3268 | break; | ||
3269 | case IMAGE_OPTION_ROM_ISCSI: | ||
3270 | img_optype = OPTYPE_BIOS; | ||
3271 | break; | ||
3272 | case IMAGE_OPTION_ROM_PXE: | ||
3273 | img_optype = OPTYPE_PXE_BIOS; | ||
3274 | break; | ||
3275 | case IMAGE_OPTION_ROM_FCoE: | ||
3276 | img_optype = OPTYPE_FCOE_BIOS; | ||
3277 | break; | ||
3278 | case IMAGE_FIRMWARE_BACKUP_iSCSI: | ||
3279 | img_optype = OPTYPE_ISCSI_BACKUP; | ||
3280 | break; | ||
3281 | case IMAGE_NCSI: | ||
3282 | img_optype = OPTYPE_NCSI_FW; | ||
3283 | break; | ||
3284 | default: | ||
3285 | continue; | ||
3286 | } | ||
3287 | |||
3288 | if (img_optype == OPTYPE_REDBOOT) { | ||
3289 | redboot = be_flash_redboot(adapter, fw->data, | ||
3290 | img_offset, img_size, | ||
3291 | filehdr_size + img_hdrs_size); | ||
3292 | if (!redboot) | ||
3293 | continue; | ||
3294 | } | ||
3295 | |||
3296 | p = fw->data; | ||
3297 | p += filehdr_size + img_offset + img_hdrs_size; | ||
3298 | if (p + img_size > fw->data + fw->size) | ||
3299 | return -1; | ||
3300 | |||
3301 | status = be_flash(adapter, p, flash_cmd, img_optype, img_size); | ||
3302 | if (status) { | ||
3303 | dev_err(&adapter->pdev->dev, | ||
3304 | "Flashing section type %d failed.\n", | ||
3305 | fsec->fsec_entry[i].type); | ||
3306 | return status; | ||
3307 | } | ||
3308 | } | ||
3309 | return 0; | ||
3237 | } | 3310 | } |
3238 | 3311 | ||
3239 | static int lancer_wait_idle(struct be_adapter *adapter) | 3312 | static int lancer_wait_idle(struct be_adapter *adapter) |
@@ -3367,6 +3440,27 @@ lancer_fw_exit: | |||
3367 | return status; | 3440 | return status; |
3368 | } | 3441 | } |
3369 | 3442 | ||
3443 | static int be_get_ufi_gen(struct be_adapter *adapter, | ||
3444 | struct flash_file_hdr_g2 *fhdr) | ||
3445 | { | ||
3446 | if (fhdr == NULL) | ||
3447 | goto be_get_ufi_exit; | ||
3448 | |||
3449 | if (adapter->generation == BE_GEN3) { | ||
3450 | if (skyhawk_chip(adapter) && fhdr->build[0] == '4') | ||
3451 | return SH_HW; | ||
3452 | else if (!skyhawk_chip(adapter) && fhdr->build[0] == '3') | ||
3453 | return BE_GEN3; | ||
3454 | } else if (adapter->generation == BE_GEN2 && fhdr->build[0] == '2') { | ||
3455 | return BE_GEN2; | ||
3456 | } | ||
3457 | |||
3458 | be_get_ufi_exit: | ||
3459 | dev_err(&adapter->pdev->dev, | ||
3460 | "UFI and Interface are not compatible for flashing\n"); | ||
3461 | return -1; | ||
3462 | } | ||
3463 | |||
3370 | static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) | 3464 | static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) |
3371 | { | 3465 | { |
3372 | struct flash_file_hdr_g2 *fhdr; | 3466 | struct flash_file_hdr_g2 *fhdr; |
@@ -3374,10 +3468,7 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) | |||
3374 | struct image_hdr *img_hdr_ptr = NULL; | 3468 | struct image_hdr *img_hdr_ptr = NULL; |
3375 | struct be_dma_mem flash_cmd; | 3469 | struct be_dma_mem flash_cmd; |
3376 | const u8 *p; | 3470 | const u8 *p; |
3377 | int status = 0, i = 0, num_imgs = 0; | 3471 | int status = 0, i = 0, num_imgs = 0, ufi_type = 0; |
3378 | |||
3379 | p = fw->data; | ||
3380 | fhdr = (struct flash_file_hdr_g2 *) p; | ||
3381 | 3472 | ||
3382 | flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; | 3473 | flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; |
3383 | flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, | 3474 | flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, |
@@ -3389,26 +3480,31 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) | |||
3389 | goto be_fw_exit; | 3480 | goto be_fw_exit; |
3390 | } | 3481 | } |
3391 | 3482 | ||
3392 | if ((adapter->generation == BE_GEN3) && | 3483 | p = fw->data; |
3393 | (get_ufigen_type(fhdr) == BE_GEN3)) { | 3484 | fhdr = (struct flash_file_hdr_g2 *)p; |
3394 | fhdr3 = (struct flash_file_hdr_g3 *) fw->data; | 3485 | |
3395 | num_imgs = le32_to_cpu(fhdr3->num_imgs); | 3486 | ufi_type = be_get_ufi_gen(adapter, fhdr); |
3396 | for (i = 0; i < num_imgs; i++) { | 3487 | |
3397 | img_hdr_ptr = (struct image_hdr *) (fw->data + | 3488 | fhdr3 = (struct flash_file_hdr_g3 *)fw->data; |
3398 | (sizeof(struct flash_file_hdr_g3) + | 3489 | num_imgs = le32_to_cpu(fhdr3->num_imgs); |
3399 | i * sizeof(struct image_hdr))); | 3490 | for (i = 0; i < num_imgs; i++) { |
3400 | if (le32_to_cpu(img_hdr_ptr->imageid) == 1) | 3491 | img_hdr_ptr = (struct image_hdr *)(fw->data + |
3401 | status = be_flash_data(adapter, fw, &flash_cmd, | 3492 | (sizeof(struct flash_file_hdr_g3) + |
3402 | num_imgs); | 3493 | i * sizeof(struct image_hdr))); |
3494 | if (le32_to_cpu(img_hdr_ptr->imageid) == 1) { | ||
3495 | if (ufi_type == SH_HW) | ||
3496 | status = be_flash_skyhawk(adapter, fw, | ||
3497 | &flash_cmd, num_imgs); | ||
3498 | else if (ufi_type == BE_GEN3) | ||
3499 | status = be_flash_data(adapter, fw, | ||
3500 | &flash_cmd, num_imgs); | ||
3403 | } | 3501 | } |
3404 | } else if ((adapter->generation == BE_GEN2) && | 3502 | } |
3405 | (get_ufigen_type(fhdr) == BE_GEN2)) { | 3503 | |
3504 | if (ufi_type == BE_GEN2) | ||
3406 | status = be_flash_data(adapter, fw, &flash_cmd, 0); | 3505 | status = be_flash_data(adapter, fw, &flash_cmd, 0); |
3407 | } else { | 3506 | else if (ufi_type == -1) |
3408 | dev_err(&adapter->pdev->dev, | ||
3409 | "UFI and Interface are not compatible for flashing\n"); | ||
3410 | status = -1; | 3507 | status = -1; |
3411 | } | ||
3412 | 3508 | ||
3413 | dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, | 3509 | dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, |
3414 | flash_cmd.dma); | 3510 | flash_cmd.dma); |