diff options
author | John Soni Jose <sony.john-n@emulex.com> | 2012-10-20 04:45:40 +0530 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-11-27 08:59:41 +0400 |
commit | e175defea7b2019613765fee63afcca354e0041d (patch) | |
tree | cf66278fcceaf328d3e4b34171455aae3398f88e /drivers/scsi/be2iscsi/be_cmds.c | |
parent | 5faf17b4f46c4c066ccd5eb2aa5b4a100ade2702 (diff) |
[SCSI] be2iscsi: Fix for MBX timeout issue
The MBX timeout value set to 100 and if adapter doesn;t
return response in that time driver will return from waiting
for completion with an error to the caller. In the earlier code
driver use to wait until MBX response comes from adapter.
Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/be2iscsi/be_cmds.c')
-rw-r--r-- | drivers/scsi/be2iscsi/be_cmds.c | 188 |
1 files changed, 158 insertions, 30 deletions
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 977b7532a01e..352fc53e91b8 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -133,6 +133,84 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) return tag; } +/* + * beiscsi_mccq_compl()- Wait for completion of MBX + * @phba: Driver private structure + * @tag: Tag for the MBX Command + * @wrb: the WRB used for the MBX Command + * @cmd_hdr: IOCTL Hdr for the MBX Cmd + * + * Waits for MBX completion with the passed TAG. + * + * return + * Success: 0 + * Failure: Non-Zero + **/ +int beiscsi_mccq_compl(struct beiscsi_hba *phba, + uint32_t tag, struct be_mcc_wrb **wrb, + void *cmd_hdr) +{ + int rc = 0; + uint32_t mcc_tag_response; + uint16_t status = 0, addl_status = 0, wrb_num = 0; + struct be_mcc_wrb *temp_wrb; + struct be_cmd_req_hdr *ioctl_hdr; + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + + /* wait for the mccq completion */ + rc = wait_event_interruptible_timeout( + phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag], + msecs_to_jiffies( + BEISCSI_HOST_MBX_TIMEOUT)); + + if (rc <= 0) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_INIT | BEISCSI_LOG_EH | + BEISCSI_LOG_CONFIG, + "BC_%d : MBX Cmd Completion timed out\n"); + rc = -EAGAIN; + goto release_mcc_tag; + } else + rc = 0; + + mcc_tag_response = phba->ctrl.mcc_numtag[tag]; + status = (mcc_tag_response & CQE_STATUS_MASK); + addl_status = ((mcc_tag_response & CQE_STATUS_ADDL_MASK) >> + CQE_STATUS_ADDL_SHIFT); + + if (cmd_hdr) { + ioctl_hdr = (struct be_cmd_req_hdr *)cmd_hdr; + } else { + wrb_num = (mcc_tag_response & CQE_STATUS_WRB_MASK) >> + CQE_STATUS_WRB_SHIFT; + temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num); + ioctl_hdr = embedded_payload(temp_wrb); + + if (wrb) + *wrb = temp_wrb; + } + + if (status || addl_status) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_INIT | BEISCSI_LOG_EH | + BEISCSI_LOG_CONFIG, + "BC_%d : MBX Cmd Failed for " + "Subsys : %d Opcode : %d with " + "Status : %d and Extd_Status : %d\n", + ioctl_hdr->subsystem, + ioctl_hdr->opcode, + status, addl_status); + rc = -EAGAIN; + } + +release_mcc_tag: + /* Release the MCC entry */ + free_mcc_tag(&phba->ctrl, tag); + + return rc; +} + void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { spin_lock(&ctrl->mbox_lock); @@ -168,11 +246,24 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) compl->flags = 0; } +/* + * be_mcc_compl_process()- Check the MBX comapletion status + * @ctrl: Function specific MBX data structure + * @compl: Completion status of MBX Command + * + * Check for the MBX completion status when BMBX method used + * + * return + * Success: Zero + * Failure: Non-Zero + **/ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, struct be_mcc_compl *compl) { u16 compl_status, extd_status; + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + struct be_cmd_req_hdr *hdr = embedded_payload(wrb); be_dws_le_to_cpu(compl, 4); @@ -184,7 +275,10 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : error in cmd completion: status(compl/extd)=%d/%d\n", + "BC_%d : error in cmd completion: " + "Subsystem : %d Opcode : %d " + "status(compl/extd)=%d/%d\n", + hdr->subsystem, hdr->opcode, compl_status, extd_status); return -EBUSY; @@ -314,11 +408,24 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) return status; } -/* Wait till no more pending mcc requests are present */ +/* + * be_mcc_wait_compl()- Wait for MBX completion + * @phba: driver private structure + * + * Wait till no more pending mcc requests are present + * + * return + * Success: 0 + * Failure: Non-Zero + * + **/ static int be_mcc_wait_compl(struct beiscsi_hba *phba) { int i, status; for (i = 0; i < mcc_timeout; i++) { + if (phba->fw_timeout) + return -EIO; + status = beiscsi_process_mcc(phba); if (status) return status; @@ -330,51 +437,80 @@ static int be_mcc_wait_compl(struct beiscsi_hba *phba) if (i == mcc_timeout) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : mccq poll timed out\n"); - + "BC_%d : FW Timed Out\n"); + phba->fw_timeout = true; return -EBUSY; } return 0; } -/* Notify MCC requests and wait for completion */ +/* + * be_mcc_notify_wait()- Notify and wait for Compl + * @phba: driver private structure + * + * Notify MCC requests and wait for completion + * + * return + * Success: 0 + * Failure: Non-Zero + **/ int be_mcc_notify_wait(struct beiscsi_hba *phba) { be_mcc_notify(phba); return be_mcc_wait_compl(phba); } +/* + * be_mbox_db_ready_wait()- Check ready status + * @ctrl: Function specific MBX data structure + * + * Check for the ready status of FW to send BMBX + * commands to adapter. + * + * return + * Success: 0 + * Failure: Non-Zero + **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define long_delay 2000 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; - int cnt = 0, wait = 5; /* in usecs */ + struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + int wait = 0; u32 ready; do { + if (phba->fw_timeout) + return -EIO; + ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; if (ready) break; - if (cnt > 12000000) { - struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + if (wait > BEISCSI_HOST_MBX_TIMEOUT) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : mbox_db poll timed out\n"); - + "BC_%d : FW Timed Out\n"); + phba->fw_timeout = true; return -EBUSY; } - if (cnt > 50) { - wait = long_delay; - mdelay(long_delay / 1000); - } else - udelay(wait); - cnt += wait; + mdelay(1); + wait++; } while (true); return 0; } +/* + * be_mbox_notify: Notify adapter of new BMBX command + * @ctrl: Function specific MBX data structure + * + * Ring doorbell to inform adapter of a BMBX command + * to process + * + * return + * Success: 0 + * Failure: Non-Zero + **/ int be_mbox_notify(struct be_ctrl_info *ctrl) { int status; @@ -391,13 +527,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) iowrite32(val, db); status = be_mbox_db_ready_wait(ctrl); - if (status != 0) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : be_mbox_db_ready_wait failed\n"); - + if (status) return status; - } + val = 0; val &= ~MPU_MAILBOX_DB_RDY_MASK; val &= ~MPU_MAILBOX_DB_HI_MASK; @@ -405,13 +537,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) iowrite32(val, db); status = be_mbox_db_ready_wait(ctrl); - if (status != 0) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : be_mbox_db_ready_wait failed\n"); - + if (status) return status; - } + if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); @@ -499,7 +627,7 @@ void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, req_hdr->opcode = opcode; req_hdr->subsystem = subsystem; req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); - req_hdr->timeout = 120; + req_hdr->timeout = BEISCSI_FW_MBX_TIMEOUT; } static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, |