scsi: be2iscsi: Fix POST check and reset sequence
authorJitendra Bhivare <jitendra.bhivare@broadcom.com>
Fri, 19 Aug 2016 09:50:16 +0000 (15:20 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 24 Aug 2016 02:42:44 +0000 (22:42 -0400)
SLIPORT FUNCTION_RESET does not reset the chip.
So POST status needs to be checked before issuing FUNCTION_RESET.
The completion of FUNCTION_RESET is indicated in BMBX Rdy bit.

be_cmd_fw_initialize too needs to be done before issuing any cmd to FW.
be_cmd_fw_initialize is renamed as beiscsi_cmd_special_wrb.
Rearrange and rename few functions in init and cleanup path.

Signed-off-by: Jitendra Bhivare <jitendra.bhivare@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/be2iscsi/be_cmds.c
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h

index 1ebb6ce127429f3985f371411d1d404f363a3c4f..771670c0682b2ca4a6f51ea34fded4b990a003e4 100644 (file)
 #include "be.h"
 #include "be_mgmt.h"
 
-int be_chk_reset_complete(struct beiscsi_hba *phba)
-{
-       unsigned int num_loop;
-       u8 *mpu_sem = 0;
-       u32 status;
-
-       num_loop = 1000;
-       mpu_sem = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
-       msleep(5000);
-
-       while (num_loop) {
-               status = readl((void *)mpu_sem);
-
-               if ((status & 0x80000000) || (status & 0x0000FFFF) == 0xC000)
-                       break;
-               msleep(60);
-               num_loop--;
-       }
-
-       if ((status & 0x80000000) || (!num_loop)) {
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BC_%d : Failed in be_chk_reset_complete"
-                           "status = 0x%x\n", status);
-               return -EIO;
-       }
-
-       return 0;
-}
-
 struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba,
                                 unsigned int *ref_tag)
 {
@@ -769,87 +740,6 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
        return status;
 }
 
-/**
- * be_cmd_fw_initialize()- Initialize FW
- * @ctrl: Pointer to function control structure
- *
- * Send FW initialize pattern for the function.
- *
- * return
- * Success: 0
- * Failure: Non-Zero value
- **/
-int be_cmd_fw_initialize(struct be_ctrl_info *ctrl)
-{
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-       struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
-       int status;
-       u8 *endian_check;
-
-       mutex_lock(&ctrl->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
-
-       endian_check = (u8 *) wrb;
-       *endian_check++ = 0xFF;
-       *endian_check++ = 0x12;
-       *endian_check++ = 0x34;
-       *endian_check++ = 0xFF;
-       *endian_check++ = 0xFF;
-       *endian_check++ = 0x56;
-       *endian_check++ = 0x78;
-       *endian_check++ = 0xFF;
-       be_dws_cpu_to_le(wrb, sizeof(*wrb));
-
-       status = be_mbox_notify(ctrl);
-       if (status)
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BC_%d : be_cmd_fw_initialize Failed\n");
-
-       mutex_unlock(&ctrl->mbox_lock);
-       return status;
-}
-
-/**
- * be_cmd_fw_uninit()- Uinitialize FW
- * @ctrl: Pointer to function control structure
- *
- * Send FW uninitialize pattern for the function
- *
- * return
- * Success: 0
- * Failure: Non-Zero value
- **/
-int be_cmd_fw_uninit(struct be_ctrl_info *ctrl)
-{
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-       struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
-       int status;
-       u8 *endian_check;
-
-       mutex_lock(&ctrl->mbox_lock);
-       memset(wrb, 0, sizeof(*wrb));
-
-       endian_check = (u8 *) wrb;
-       *endian_check++ = 0xFF;
-       *endian_check++ = 0xAA;
-       *endian_check++ = 0xBB;
-       *endian_check++ = 0xFF;
-       *endian_check++ = 0xFF;
-       *endian_check++ = 0xCC;
-       *endian_check++ = 0xDD;
-       *endian_check = 0xFF;
-
-       be_dws_cpu_to_le(wrb, sizeof(*wrb));
-
-       status = be_mbox_notify(ctrl);
-       if (status)
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BC_%d : be_cmd_fw_uninit Failed\n");
-
-       mutex_unlock(&ctrl->mbox_lock);
-       return status;
-}
-
 int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl,
                          struct be_queue_info *cq, struct be_queue_info *eq,
                          bool sol_evts, bool no_delay, int coalesce_wm)
@@ -1293,25 +1183,6 @@ error:
        return status;
 }
 
-int beiscsi_cmd_reset_function(struct beiscsi_hba  *phba)
-{
-       struct be_ctrl_info *ctrl = &phba->ctrl;
-       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
-       struct be_post_sgl_pages_req *req = embedded_payload(wrb);
-       int status;
-
-       mutex_lock(&ctrl->mbox_lock);
-
-       req = embedded_payload(wrb);
-       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
-       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-                          OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
-       status = be_mbox_notify(ctrl);
-
-       mutex_unlock(&ctrl->mbox_lock);
-       return status;
-}
-
 /**
  * be_cmd_set_vlan()- Configure VLAN paramters on the adapter
  * @phba: device priv structure instance
@@ -1653,3 +1524,124 @@ int beiscsi_set_uer_feature(struct beiscsi_hba *phba)
        mutex_unlock(&ctrl->mbox_lock);
        return ret;
 }
+
+static u32 beiscsi_get_post_stage(struct beiscsi_hba *phba)
+{
+       u32 sem;
+
+       if (is_chip_be2_be3r(phba))
+               sem = ioread32(phba->csr_va + SLIPORT_SEMAPHORE_OFFSET_BEx);
+       else
+               pci_read_config_dword(phba->pcidev,
+                                     SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
+       return sem;
+}
+
+int beiscsi_check_fw_rdy(struct beiscsi_hba *phba)
+{
+       u32 loop, post, rdy = 0;
+
+       loop = 1000;
+       while (loop--) {
+               post = beiscsi_get_post_stage(phba);
+               if (post & POST_ERROR_BIT)
+                       break;
+               if ((post & POST_STAGE_MASK) == POST_STAGE_ARMFW_RDY) {
+                       rdy = 1;
+                       break;
+               }
+               msleep(60);
+       }
+
+       if (!rdy) {
+               __beiscsi_log(phba, KERN_ERR,
+                             "BC_%d : FW not ready 0x%x\n", post);
+       }
+
+       return rdy;
+}
+
+static int beiscsi_cmd_function_reset(struct beiscsi_hba  *phba)
+{
+       struct be_ctrl_info *ctrl = &phba->ctrl;
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct be_post_sgl_pages_req *req = embedded_payload(wrb);
+       int status;
+
+       mutex_lock(&ctrl->mbox_lock);
+
+       req = embedded_payload(wrb);
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                          OPCODE_COMMON_FUNCTION_RESET, sizeof(*req));
+       status = be_mbox_notify(ctrl);
+
+       mutex_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load)
+{
+       struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+       struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
+       u8 *endian_check;
+       int status;
+
+       mutex_lock(&ctrl->mbox_lock);
+       memset(wrb, 0, sizeof(*wrb));
+
+       endian_check = (u8 *) wrb;
+       if (load) {
+               /* to start communicating */
+               *endian_check++ = 0xFF;
+               *endian_check++ = 0x12;
+               *endian_check++ = 0x34;
+               *endian_check++ = 0xFF;
+               *endian_check++ = 0xFF;
+               *endian_check++ = 0x56;
+               *endian_check++ = 0x78;
+               *endian_check++ = 0xFF;
+       } else {
+               /* to stop communicating */
+               *endian_check++ = 0xFF;
+               *endian_check++ = 0xAA;
+               *endian_check++ = 0xBB;
+               *endian_check++ = 0xFF;
+               *endian_check++ = 0xFF;
+               *endian_check++ = 0xCC;
+               *endian_check++ = 0xDD;
+               *endian_check = 0xFF;
+       }
+       be_dws_cpu_to_le(wrb, sizeof(*wrb));
+
+       status = be_mbox_notify(ctrl);
+       if (status)
+               beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
+                           "BC_%d : special WRB message failed\n");
+       mutex_unlock(&ctrl->mbox_lock);
+       return status;
+}
+
+int beiscsi_init_sliport(struct beiscsi_hba *phba)
+{
+       int status;
+
+       /* check POST stage before talking to FW */
+       status = beiscsi_check_fw_rdy(phba);
+       if (!status)
+               return -EIO;
+
+       /*
+        * SLI COMMON_FUNCTION_RESET completion is indicated by BMBX RDY bit.
+        * It should clean up any stale info in FW for this fn.
+        */
+       status = beiscsi_cmd_function_reset(phba);
+       if (status) {
+               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
+                           "BC_%d : SLI Function Reset failed\n");
+               return status;
+       }
+
+       /* indicate driver is loading */
+       return beiscsi_cmd_special_wrb(&phba->ctrl, 1);
+}
index c9823b00b254a7d1cc6ced9a811ee070b5a73cd7..47b7197f17a2b77d98888805b4f845bb02ded642 100644 (file)
@@ -98,11 +98,23 @@ struct be_mcc_compl {
 #define MPU_MAILBOX_DB_RDY_MASK        0x1     /* bit 0 */
 #define MPU_MAILBOX_DB_HI_MASK 0x2     /* bit 1 */
 
-/********** MPU semphore ******************/
-#define MPU_EP_SEMAPHORE_OFFSET 0xac
-#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF
-#define EP_SEMAPHORE_POST_ERR_MASK 0x1
-#define EP_SEMAPHORE_POST_ERR_SHIFT 31
+/********** MPU semphore: used for SH & BE ******************/
+#define SLIPORT_SOFTRESET_OFFSET               0x5c    /* CSR BAR offset */
+#define SLIPORT_SEMAPHORE_OFFSET_BEx           0xac    /* CSR BAR offset */
+#define SLIPORT_SEMAPHORE_OFFSET_SH            0x94    /* PCI-CFG offset */
+#define POST_STAGE_MASK                                0x0000FFFF
+#define POST_ERROR_BIT                         0x80000000
+#define POST_ERR_RECOVERY_CODE_MASK            0xF000
+
+/* Soft Reset register masks */
+#define SLIPORT_SOFTRESET_SR_MASK              0x00000080      /* SR bit */
+
+/* MPU semphore POST stage values */
+#define POST_STAGE_AWAITING_HOST_RDY   0x1 /* FW awaiting goahead from host */
+#define POST_STAGE_HOST_RDY            0x2 /* Host has given go-ahed to FW */
+#define POST_STAGE_BE_RESET            0x3 /* Host wants to reset chip */
+#define POST_STAGE_ARMFW_RDY           0xC000 /* FW is done with POST */
+#define POST_STAGE_RECOVERABLE_ERR     0xE000 /* Recoverable err detected */
 
 /********** MCC door bell ************/
 #define DB_MCCQ_OFFSET 0x140
@@ -110,9 +122,6 @@ struct be_mcc_compl {
 /* Number of entries posted */
 #define DB_MCCQ_NUM_POSTED_SHIFT 16            /* bits 16 - 29 */
 
-/* MPU semphore POST stage values */
-#define POST_STAGE_ARMFW_RDY           0xc000  /* FW is done with POST */
-
 /**
  * When the async bit of mcc_compl is set, the last 4 bytes of
  * mcc_compl is interpreted as follows:
@@ -753,6 +762,12 @@ struct be_cmd_set_features {
        } param;
 } __packed;
 
+int beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load);
+
+int beiscsi_check_fw_rdy(struct beiscsi_hba *phba);
+
+int beiscsi_init_sliport(struct beiscsi_hba *phba);
+
 int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
                          struct be_queue_info *eq, int eq_delay);
 
@@ -784,9 +799,6 @@ int __beiscsi_mcc_compl_status(struct beiscsi_hba *phba,
                               struct be_mcc_wrb **wrb,
                               struct be_dma_mem *mbx_cmd_mem);
 /*ISCSI Functuions */
-int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
-int be_cmd_fw_uninit(struct be_ctrl_info *ctrl);
-
 struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
 int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag);
 void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag);
@@ -812,8 +824,6 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl,
                                struct be_dma_mem *q_mem, u32 page_offset,
                                u32 num_pages);
 
-int beiscsi_cmd_reset_function(struct beiscsi_hba *phba);
-
 int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
                       struct be_queue_info *wrbq,
                       struct hwi_wrb_context *pwrb_context,
@@ -1422,8 +1432,6 @@ struct be_cmd_get_port_name {
                                                 * the cxn
                                                 */
 
-int be_chk_reset_complete(struct beiscsi_hba *phba);
-
 void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
                        bool embedded, u8 sge_cnt);
 
index 77ecd6c482073164aab6a4bb2e67b58b5b03e900..b4e6fc222d6013afc4a41df9d1104b515faec220 100644 (file)
@@ -3544,7 +3544,7 @@ static void be_mcc_queues_destroy(struct beiscsi_hba *phba)
        }
 }
 
-static void hwi_cleanup(struct beiscsi_hba *phba)
+static void hwi_cleanup_port(struct beiscsi_hba *phba)
 {
        struct be_queue_info *q;
        struct be_ctrl_info *ctrl = &phba->ctrl;
@@ -3603,7 +3603,8 @@ static void hwi_cleanup(struct beiscsi_hba *phba)
                        beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);
                }
        }
-       be_cmd_fw_uninit(ctrl);
+       /* last communication, indicate driver is unloading */
+       beiscsi_cmd_special_wrb(&phba->ctrl, 0);
 }
 
 static int be_mcc_queues_create(struct beiscsi_hba *phba,
@@ -3700,8 +3701,7 @@ static int hwi_init_port(struct beiscsi_hba *phba)
        phwi_context->max_eqd = 128;
        phwi_context->min_eqd = 0;
        phwi_context->cur_eqd = 0;
-       be_cmd_fw_initialize(&phba->ctrl);
-       /* set optic state to unknown */
+       /* set port optic state to unknown */
        phba->optic_state = 0xff;
 
        status = beiscsi_create_eqs(phba, phwi_context);
@@ -3807,7 +3807,7 @@ static int hwi_init_port(struct beiscsi_hba *phba)
 error:
        beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
                    "BM_%d : hwi_init_port failed");
-       hwi_cleanup(phba);
+       hwi_cleanup_port(phba);
        return status;
 }
 
@@ -4196,7 +4196,7 @@ static int beiscsi_init_port(struct beiscsi_hba *phba)
        return ret;
 
 do_cleanup_ctrlr:
-       hwi_cleanup(phba);
+       hwi_cleanup_port(phba);
        return ret;
 }
 
@@ -4233,7 +4233,7 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)
        }
 }
 
-static void beiscsi_clean_port(struct beiscsi_hba *phba)
+static void beiscsi_cleanup_port(struct beiscsi_hba *phba)
 {
        int mgmt_status, ulp_num;
        struct ulp_cid_info *ptr_cid_info = NULL;
@@ -4250,7 +4250,7 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba)
        }
 
        hwi_purge_eq(phba);
-       hwi_cleanup(phba);
+       hwi_cleanup_port(phba);
        kfree(phba->io_sgl_hndl_base);
        kfree(phba->eh_sgl_hndl_base);
        kfree(phba->ep_array);
@@ -5011,12 +5011,12 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba)
        /* PCI_ERR is set then check if driver is not unloading */
        if (test_bit(BEISCSI_HBA_RUNNING, &phba->state) &&
            test_bit(BEISCSI_HBA_PCI_ERR, &phba->state)) {
-               hwi_cleanup(phba);
+               hwi_cleanup_port(phba);
                return;
        }
 
        destroy_workqueue(phba->wq);
-       beiscsi_clean_port(phba);
+       beiscsi_cleanup_port(phba);
        beiscsi_free_mem(phba);
 
        beiscsi_unmap_pci_function(phba);
@@ -5461,9 +5461,8 @@ static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev)
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
 
-       /* Wait for the CHIP Reset to complete */
-       status = be_chk_reset_complete(phba);
-       if (!status) {
+       status = beiscsi_check_fw_rdy(phba);
+       if (status) {
                beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
                            "BM_%d : EEH Reset Completed\n");
        } else {
@@ -5478,7 +5477,7 @@ static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev)
 
 static void beiscsi_eeh_resume(struct pci_dev *pdev)
 {
-       int ret = 0, i;
+       int ret, i;
        struct be_eq_obj *pbe_eq;
        struct beiscsi_hba *phba = NULL;
        struct hwi_controller *phwi_ctrlr;
@@ -5498,19 +5497,9 @@ static void beiscsi_eeh_resume(struct pci_dev *pdev)
                        phba->num_cpus = 1;
        }
 
-       ret = beiscsi_cmd_reset_function(phba);
-       if (ret) {
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BM_%d : Reset Failed\n");
-               goto ret_err;
-       }
-
-       ret = be_chk_reset_complete(phba);
-       if (ret) {
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BM_%d : Failed to get out of reset.\n");
+       ret = beiscsi_init_sliport(phba);
+       if (ret)
                goto ret_err;
-       }
 
        beiscsi_get_params(phba);
        phba->shost->max_id = phba->params.cxns_per_ctrl;
@@ -5627,28 +5616,15 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
        ret = be_ctrl_init(phba, pcidev);
        if (ret) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BM_%d : beiscsi_dev_probe-"
-                           "Failed in be_ctrl_init\n");
+                           "BM_%d : be_ctrl_init failed\n");
                goto hba_free;
        }
 
-       set_bit(BEISCSI_HBA_RUNNING, &phba->state);
-       /*
-        * FUNCTION_RESET should clean up any stale info in FW for this fn
-        */
-       ret = beiscsi_cmd_reset_function(phba);
-       if (ret) {
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BM_%d : Reset Failed\n");
-               goto hba_free;
-       }
-       ret = be_chk_reset_complete(phba);
-       if (ret) {
-               beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-                           "BM_%d : Failed to get out of reset.\n");
+       ret = beiscsi_init_sliport(phba);
+       if (ret)
                goto hba_free;
-       }
 
+       set_bit(BEISCSI_HBA_RUNNING, &phba->state);
        spin_lock_init(&phba->io_sgl_lock);
        spin_lock_init(&phba->mgmt_sgl_lock);
        spin_lock_init(&phba->async_pdu_lock);
@@ -5772,7 +5748,7 @@ free_blkenbld:
                irq_poll_disable(&pbe_eq->iopoll);
        }
 free_twq:
-       beiscsi_clean_port(phba);
+       beiscsi_cleanup_port(phba);
        beiscsi_free_mem(phba);
 free_port:
        pci_free_consistent(phba->pcidev,
index 0a5de01c38830d457d9557bebc9f387cb7438727..4cdb34c3de5dc31514b0a75af27ec74bf14fa2f7 100644 (file)
 #define BEISCSI_MAX_FRAGS_INIT 192
 #define BE_NUM_MSIX_ENTRIES    1
 
-#define MPU_EP_CONTROL          0
-#define MPU_EP_SEMAPHORE        0xac
-#define BE2_SOFT_RESET          0x5c
-#define BE2_PCI_ONLINE0         0xb0
-#define BE2_PCI_ONLINE1         0xb4
-#define BE2_SET_RESET           0x80
-#define BE2_MPU_IRAM_ONLINE     0x00000080
-
 #define BE_SENSE_INFO_SIZE             258
 #define BE_ISCSI_PDU_HEADER_SIZE       64
 #define BE_MIN_MEM_SIZE                        16384