diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 2e28f6c419fe253231864707225e5a09b68e033d..23c73fe426484534a3c53efbc84a546fe62a50af 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -98,6 +98,14 @@ struct be_mcc_obj { struct be_queue_info cq; }; +struct beiscsi_mcc_tag_state { +#define MCC_TAG_STATE_COMPLETED 0x00 +#define MCC_TAG_STATE_RUNNING 0x01 +#define MCC_TAG_STATE_TIMEOUT 0x02 + uint8_t tag_state; + struct be_dma_mem tag_mem_state; +}; + struct be_ctrl_info { u8 __iomem *csr; u8 __iomem *db; /* Door Bell */ @@ -122,6 +130,8 @@ struct be_ctrl_info { unsigned short mcc_alloc_index; unsigned short mcc_free_index; unsigned int mcc_tag_available; + + struct beiscsi_mcc_tag_state ptag_state[MAX_MCC_CMD + 1]; }; #include "be_cmds.h" diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 3338391b64de9b1aba50844c014f7e5fc44706b3..b14949a71eda3da4df089eb8e1c6c4de8d55f2a7 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -138,7 +138,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) * @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 + * @mbx_cmd_mem: ptr to memory allocated for MBX Cmd * * Waits for MBX completion with the passed TAG. * @@ -148,21 +148,26 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) **/ int beiscsi_mccq_compl(struct beiscsi_hba *phba, uint32_t tag, struct be_mcc_wrb **wrb, - void *cmd_hdr) + struct be_dma_mem *mbx_cmd_mem) { 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_cmd_resp_hdr *ioctl_resp_hdr; + struct be_cmd_req_hdr *mbx_hdr; + struct be_cmd_resp_hdr *mbx_resp_hdr; struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; if (beiscsi_error(phba)) { free_mcc_tag(&phba->ctrl, tag); - return -EIO; + return -EPERM; } + /* Set MBX Tag state to Active */ + spin_lock(&phba->ctrl.mbox_lock); + phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; + spin_unlock(&phba->ctrl.mbox_lock); + /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( phba->ctrl.mcc_wait[tag], @@ -171,56 +176,71 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, BEISCSI_HOST_MBX_TIMEOUT)); if (rc <= 0) { + struct be_dma_mem *tag_mem; + /* Set MBX Tag state to timeout */ + spin_lock(&phba->ctrl.mbox_lock); + phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; + spin_unlock(&phba->ctrl.mbox_lock); + + /* Store resource addr to be freed later */ + tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; + if (mbx_cmd_mem) { + tag_mem->size = mbx_cmd_mem->size; + tag_mem->va = mbx_cmd_mem->va; + tag_mem->dma = mbx_cmd_mem->dma; + } else + tag_mem->size = 0; + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | BEISCSI_LOG_EH | BEISCSI_LOG_CONFIG, "BC_%d : MBX Cmd Completion timed out\n"); - rc = -EBUSY; - - /* decrement the mccq used count */ - atomic_dec(&phba->ctrl.mcc_obj.q.used); - - goto release_mcc_tag; - } else + return -EBUSY; + } else { rc = 0; + /* Set MBX Tag state to completed */ + spin_lock(&phba->ctrl.mbox_lock); + phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; + spin_unlock(&phba->ctrl.mbox_lock); + } 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; + if (mbx_cmd_mem) { + mbx_hdr = (struct be_cmd_req_hdr *)mbx_cmd_mem->va; } 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); + mbx_hdr = embedded_payload(temp_wrb); if (wrb) *wrb = temp_wrb; } if (status || addl_status) { - beiscsi_log(phba, KERN_ERR, + beiscsi_log(phba, KERN_WARNING, 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, + mbx_hdr->subsystem, + mbx_hdr->opcode, status, addl_status); if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { - ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; + mbx_resp_hdr = (struct be_cmd_resp_hdr *) mbx_hdr; beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT | BEISCSI_LOG_EH | BEISCSI_LOG_CONFIG, "BC_%d : Insufficent Buffer Error " "Resp_Len : %d Actual_Resp_Len : %d\n", - ioctl_resp_hdr->response_length, - ioctl_resp_hdr->actual_resp_len); + mbx_resp_hdr->response_length, + mbx_resp_hdr->actual_resp_len); rc = -EAGAIN; goto release_mcc_tag; @@ -319,6 +339,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, struct be_mcc_compl *compl) { + struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); u16 compl_status, extd_status; unsigned short tag; @@ -338,7 +359,32 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, ctrl->mcc_numtag[tag] |= (compl->tag0 & 0x00FF0000); ctrl->mcc_numtag[tag] |= (extd_status & 0x000000FF) << 8; ctrl->mcc_numtag[tag] |= (compl_status & 0x000000FF); - wake_up_interruptible(&ctrl->mcc_wait[tag]); + + if (ctrl->ptag_state[tag].tag_state == MCC_TAG_STATE_RUNNING) { + wake_up_interruptible(&ctrl->mcc_wait[tag]); + } else if (ctrl->ptag_state[tag].tag_state == MCC_TAG_STATE_TIMEOUT) { + struct be_dma_mem *tag_mem; + tag_mem = &ctrl->ptag_state[tag].tag_mem_state; + + beiscsi_log(phba, KERN_WARNING, + BEISCSI_LOG_MBOX | BEISCSI_LOG_INIT | + BEISCSI_LOG_CONFIG, + "BC_%d : MBX Completion for timeout Command " + "from FW\n"); + /* Check if memory needs to be freed */ + if (tag_mem->size) + pci_free_consistent(ctrl->pdev, tag_mem->size, + tag_mem->va, tag_mem->dma); + + /* Change tag state */ + spin_lock(&phba->ctrl.mbox_lock); + ctrl->ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; + spin_unlock(&phba->ctrl.mbox_lock); + + /* Free MCC Tag */ + free_mcc_tag(ctrl, tag); + } + return 0; } diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 627ebbe0172c89d6f1fdf501c09cc7f7f854a8f8..770b6c8bcad864d77bd6e54b11e6d743a24491c5 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -709,7 +709,8 @@ unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba); void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); int beiscsi_mccq_compl(struct beiscsi_hba *phba, - uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va); + uint32_t tag, 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); diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 889066d9d6fb92a3a43e0e2dd5173f8f9c19d347..bdd0f05a33423fb35aee80febd36a124e53b0d7d 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1153,16 +1153,18 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, return -EAGAIN; } - ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); + ret = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, "BS_%d : mgmt_open_connection Failed"); - pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, - nonemb_cmd.va, nonemb_cmd.dma); + if (ret != -EBUSY) + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); + beiscsi_free_ep(beiscsi_ep); - return -EBUSY; + return ret; } ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va; diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 5642a9b250c2fe11201510460563ec576c70461c..c8f90cef728d458d8dc5798ec1c7bcada9a43246 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -228,6 +228,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) struct invalidate_command_table *inv_tbl; struct be_dma_mem nonemb_cmd; unsigned int cid, tag, num_invalidate; + int rc; cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; @@ -285,9 +286,11 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) return FAILED; } - beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); - pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, - nonemb_cmd.va, nonemb_cmd.dma); + rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); + if (rc != -EBUSY) + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); + return iscsi_eh_abort(sc); } @@ -303,6 +306,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) struct invalidate_command_table *inv_tbl; struct be_dma_mem nonemb_cmd; unsigned int cid, tag, i, num_invalidate; + int rc; /* invalidate iocbs */ cls_session = starget_to_session(scsi_target(sc->device)); @@ -363,9 +367,10 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) return FAILED; } - beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); - pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, - nonemb_cmd.va, nonemb_cmd.dma); + rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); + if (rc != -EBUSY) + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); return iscsi_eh_device_reset(sc); } @@ -4360,12 +4365,16 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) goto boot_freemem; } - ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); + ret = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, "BM_%d : beiscsi_get_session_info Failed"); - goto boot_freemem; + + if (ret != -EBUSY) + goto boot_freemem; + else + return ret; } session_resp = nonemb_cmd.va ; @@ -5594,6 +5603,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, phba->ctrl.mcc_tag[i] = i + 1; phba->ctrl.mcc_numtag[i + 1] = 0; phba->ctrl.mcc_tag_available++; + memset(&phba->ctrl.ptag_state[i].tag_mem_state, 0, + sizeof(struct beiscsi_mcc_tag_state)); } phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index b2fcac78feaa995430fe62e4cd2587735313dabb..088bdf752cfafac10630ce830e4b12f6602dbf4a 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -828,22 +828,25 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba, be_mcc_notify(phba); spin_unlock(&ctrl->mbox_lock); - rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd->va); + rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd); + + if (resp_buf) + memcpy(resp_buf, nonemb_cmd->va, resp_buf_len); + if (rc) { - /* Check if the IOCTL needs to be re-issued */ + /* Check if the MBX Cmd needs to be re-issued */ if (rc == -EAGAIN) return rc; - beiscsi_log(phba, KERN_ERR, + beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, "BG_%d : mgmt_exec_nonemb_cmd Failed status\n"); - goto free_cmd; + if (rc != -EBUSY) + goto free_cmd; + else + return rc; } - - if (resp_buf) - memcpy(resp_buf, nonemb_cmd->va, resp_buf_len); - free_cmd: pci_free_consistent(ctrl->pdev, nonemb_cmd->size, nonemb_cmd->va, nonemb_cmd->dma); @@ -1348,7 +1351,6 @@ int mgmt_set_vlan(struct beiscsi_hba *phba, { int rc; unsigned int tag; - struct be_mcc_wrb *wrb = NULL; tag = be_cmd_set_vlan(phba, vlan_tag); if (!tag) { @@ -1358,7 +1360,7 @@ int mgmt_set_vlan(struct beiscsi_hba *phba, return -EBUSY; } - rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL); + rc = beiscsi_mccq_compl(phba, tag, NULL, NULL); if (rc) { beiscsi_log(phba, KERN_ERR, (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),