scsi: lpfc: Improve firmware download logging
authorJames Smart <jsmart2021@gmail.com>
Wed, 7 Jul 2021 18:43:34 +0000 (11:43 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 19 Jul 2021 02:30:35 +0000 (22:30 -0400)
Define additional status fields in mailbox commands to help provide
additional information when downloading new firmware.

Link: https://lore.kernel.org/r/20210707184351.67872-4-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index eb8c735..7d4d179 100644 (file)
@@ -959,6 +959,12 @@ union lpfc_sli4_cfg_shdr {
 #define lpfc_mbox_hdr_add_status_SHIFT         8
 #define lpfc_mbox_hdr_add_status_MASK          0x000000FF
 #define lpfc_mbox_hdr_add_status_WORD          word7
+#define LPFC_ADD_STATUS_INCOMPAT_OBJ           0xA2
+#define lpfc_mbox_hdr_add_status_2_SHIFT       16
+#define lpfc_mbox_hdr_add_status_2_MASK                0x000000FF
+#define lpfc_mbox_hdr_add_status_2_WORD                word7
+#define LPFC_ADD_STATUS_2_INCOMPAT_FLASH       0x01
+#define LPFC_ADD_STATUS_2_INCORRECT_ASIC       0x02
                uint32_t response_length;
                uint32_t actual_response_length;
        } response;
@@ -3603,6 +3609,9 @@ struct lpfc_controller_attribute {
 #define lpfc_cntl_attr_eprom_ver_hi_SHIFT      8
 #define lpfc_cntl_attr_eprom_ver_hi_MASK       0x000000ff
 #define lpfc_cntl_attr_eprom_ver_hi_WORD       word17
+#define lpfc_cntl_attr_flash_id_SHIFT          16
+#define lpfc_cntl_attr_flash_id_MASK           0x000000ff
+#define lpfc_cntl_attr_flash_id_WORD           word17
        uint32_t mbx_da_struct_ver;
        uint32_t ep_fw_da_struct_ver;
        uint32_t ncsi_ver_str[3];
index f530d8f..e844d9a 100644 (file)
@@ -5674,16 +5674,20 @@ lpfc_sli4_get_ctl_attr(struct lpfc_hba *phba)
                bf_get(lpfc_cntl_attr_lnk_type, cntl_attr);
        phba->sli4_hba.lnk_info.lnk_no =
                bf_get(lpfc_cntl_attr_lnk_numb, cntl_attr);
+       phba->sli4_hba.flash_id = bf_get(lpfc_cntl_attr_flash_id, cntl_attr);
+       phba->sli4_hba.asic_rev = bf_get(lpfc_cntl_attr_asic_rev, cntl_attr);
 
        memset(phba->BIOSVersion, 0, sizeof(phba->BIOSVersion));
        strlcat(phba->BIOSVersion, (char *)cntl_attr->bios_ver_str,
                sizeof(phba->BIOSVersion));
 
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                       "3086 lnk_type:%d, lnk_numb:%d, bios_ver:%s\n",
+                       "3086 lnk_type:%d, lnk_numb:%d, bios_ver:%s, "
+                       "flash_id: x%02x, asic_rev: x%02x\n",
                        phba->sli4_hba.lnk_info.lnk_tp,
                        phba->sli4_hba.lnk_info.lnk_no,
-                       phba->BIOSVersion);
+                       phba->BIOSVersion, phba->sli4_hba.flash_id,
+                       phba->sli4_hba.asic_rev);
 out_free_mboxq:
        if (bf_get(lpfc_mqe_command, &mboxq->u.mqe) == MBX_SLI4_CONFIG)
                lpfc_sli4_mbox_cmd_free(phba, mboxq);
@@ -20021,6 +20025,91 @@ out:
 }
 
 /**
+ * lpfc_log_fw_write_cmpl - logs firmware write completion status
+ * @phba: pointer to lpfc hba data structure
+ * @shdr_status: wr_object rsp's status field
+ * @shdr_add_status: wr_object rsp's add_status field
+ * @shdr_add_status_2: wr_object rsp's add_status_2 field
+ * @shdr_change_status: wr_object rsp's change_status field
+ * @shdr_csf: wr_object rsp's csf bit
+ *
+ * This routine is intended to be called after a firmware write completes.
+ * It will log next action items to be performed by the user to instantiate
+ * the newly downloaded firmware or reason for incompatibility.
+ **/
+static void
+lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status,
+                      u32 shdr_add_status, u32 shdr_add_status_2,
+                      u32 shdr_change_status, u32 shdr_csf)
+{
+       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+                       "4198 %s: flash_id x%02x, asic_rev x%02x, "
+                       "status x%02x, add_status x%02x, add_status_2 x%02x, "
+                       "change_status x%02x, csf %01x\n", __func__,
+                       phba->sli4_hba.flash_id, phba->sli4_hba.asic_rev,
+                       shdr_status, shdr_add_status, shdr_add_status_2,
+                       shdr_change_status, shdr_csf);
+
+       if (shdr_add_status == LPFC_ADD_STATUS_INCOMPAT_OBJ) {
+               switch (shdr_add_status_2) {
+               case LPFC_ADD_STATUS_2_INCOMPAT_FLASH:
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+                                       "4199 Firmware write failed: "
+                                       "image incompatible with flash x%02x\n",
+                                       phba->sli4_hba.flash_id);
+                       break;
+               case LPFC_ADD_STATUS_2_INCORRECT_ASIC:
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+                                       "4200 Firmware write failed: "
+                                       "image incompatible with ASIC "
+                                       "architecture x%02x\n",
+                                       phba->sli4_hba.asic_rev);
+                       break;
+               default:
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI,
+                                       "4210 Firmware write failed: "
+                                       "add_status_2 x%02x\n",
+                                       shdr_add_status_2);
+                       break;
+               }
+       } else if (!shdr_status && !shdr_add_status) {
+               if (shdr_change_status == LPFC_CHANGE_STATUS_FW_RESET ||
+                   shdr_change_status == LPFC_CHANGE_STATUS_PORT_MIGRATION) {
+                       if (shdr_csf)
+                               shdr_change_status =
+                                                  LPFC_CHANGE_STATUS_PCI_RESET;
+               }
+
+               switch (shdr_change_status) {
+               case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET):
+                       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+                                       "3198 Firmware write complete: System "
+                                       "reboot required to instantiate\n");
+                       break;
+               case (LPFC_CHANGE_STATUS_FW_RESET):
+                       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+                                       "3199 Firmware write complete: "
+                                       "Firmware reset required to "
+                                       "instantiate\n");
+                       break;
+               case (LPFC_CHANGE_STATUS_PORT_MIGRATION):
+                       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+                                       "3200 Firmware write complete: Port "
+                                       "Migration or PCI Reset required to "
+                                       "instantiate\n");
+                       break;
+               case (LPFC_CHANGE_STATUS_PCI_RESET):
+                       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
+                                       "3201 Firmware write complete: PCI "
+                                       "Reset required to instantiate\n");
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+/**
  * lpfc_wr_object - write an object to the firmware
  * @phba: HBA structure that indicates port to create a queue on.
  * @dmabuf_list: list of dmabufs to write to the port.
@@ -20046,7 +20135,8 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
        struct lpfc_mbx_wr_object *wr_object;
        LPFC_MBOXQ_t *mbox;
        int rc = 0, i = 0;
-       uint32_t shdr_status, shdr_add_status, shdr_change_status, shdr_csf;
+       uint32_t shdr_status, shdr_add_status, shdr_add_status_2;
+       uint32_t shdr_change_status = 0, shdr_csf = 0;
        uint32_t mbox_tmo;
        struct lpfc_dmabuf *dmabuf;
        uint32_t written = 0;
@@ -20100,58 +20190,36 @@ lpfc_wr_object(struct lpfc_hba *phba, struct list_head *dmabuf_list,
                             &wr_object->header.cfg_shdr.response);
        shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
                                 &wr_object->header.cfg_shdr.response);
+       shdr_add_status_2 = bf_get(lpfc_mbox_hdr_add_status_2,
+                                  &wr_object->header.cfg_shdr.response);
        if (check_change_status) {
                shdr_change_status = bf_get(lpfc_wr_object_change_status,
                                            &wr_object->u.response);
-
-               if (shdr_change_status == LPFC_CHANGE_STATUS_FW_RESET ||
-                   shdr_change_status == LPFC_CHANGE_STATUS_PORT_MIGRATION) {
-                       shdr_csf = bf_get(lpfc_wr_object_csf,
-                                         &wr_object->u.response);
-                       if (shdr_csf)
-                               shdr_change_status =
-                                                  LPFC_CHANGE_STATUS_PCI_RESET;
-               }
-
-               switch (shdr_change_status) {
-               case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET):
-                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                                       "3198 Firmware write complete: System "
-                                       "reboot required to instantiate\n");
-                       break;
-               case (LPFC_CHANGE_STATUS_FW_RESET):
-                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                                       "3199 Firmware write complete: Firmware"
-                                       " reset required to instantiate\n");
-                       break;
-               case (LPFC_CHANGE_STATUS_PORT_MIGRATION):
-                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                                       "3200 Firmware write complete: Port "
-                                       "Migration or PCI Reset required to "
-                                       "instantiate\n");
-                       break;
-               case (LPFC_CHANGE_STATUS_PCI_RESET):
-                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                                       "3201 Firmware write complete: PCI "
-                                       "Reset required to instantiate\n");
-                       break;
-               default:
-                       break;
-               }
+               shdr_csf = bf_get(lpfc_wr_object_csf,
+                                 &wr_object->u.response);
        }
+
        if (!phba->sli4_hba.intr_enable)
                mempool_free(mbox, phba->mbox_mem_pool);
        else if (rc != MBX_TIMEOUT)
                mempool_free(mbox, phba->mbox_mem_pool);
-       if (shdr_status || shdr_add_status || rc) {
+       if (shdr_status || shdr_add_status || shdr_add_status_2 || rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
                                "3025 Write Object mailbox failed with "
-                               "status x%x add_status x%x, mbx status x%x\n",
-                               shdr_status, shdr_add_status, rc);
+                               "status x%x add_status x%x, add_status_2 x%x, "
+                               "mbx status x%x\n",
+                               shdr_status, shdr_add_status, shdr_add_status_2,
+                               rc);
                rc = -ENXIO;
                *offset = shdr_add_status;
-       } else
+       } else {
                *offset += wr_object->u.response.actual_write_length;
+       }
+
+       if (rc || check_change_status)
+               lpfc_log_fw_write_cmpl(phba, shdr_status, shdr_add_status,
+                                      shdr_add_status_2, shdr_change_status,
+                                      shdr_csf);
        return rc;
 }
 
index 26f19c9..021edbf 100644 (file)
@@ -978,6 +978,8 @@ struct lpfc_sli4_hba {
 #define lpfc_conf_trunk_port3_nd_WORD  conf_trunk
 #define lpfc_conf_trunk_port3_nd_SHIFT 7
 #define lpfc_conf_trunk_port3_nd_MASK  0x1
+       uint8_t flash_id;
+       uint8_t asic_rev;
 };
 
 enum lpfc_sge_type {