RE: [PATCH v4 00/17] be2iscsi: driver update 11.0.0.0
> -Original Message- > From: Martin K. Petersen [mailto:martin.peter...@oracle.com] > Sent: Wednesday, January 27, 2016 7:15 AM > To: Jitendra Bhivare > Cc: linux-scsi@vger.kernel.org; micha...@cs.wisc.edu > Subject: Re: [PATCH v4 00/17] be2iscsi: driver update 11.0.0.0 > > >>>>> "Jitendra" == Jitendra Bhivare writes: > > Applied to 4.6/scsi-queue. > > PATCH 12/17: "be2iscsi: Fix IOPOLL implementation" conflicted with Christoph's > irq_poll changes. I fixed it up but please verify: > > http://git.kernel.org/cgit/linux/kernel/git/mkp/scsi.git/commit/?h=4.6/scs i- > queue&id=fa512e1a3156 > > -- > Martin K. PetersenOracle Linux Engineering Reviewed by: Jitendra Bhivare Thanks, JB -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/12] be2iscsi: Rename MCC and BMBX processing functions
beiscsi_mccq_compl -> beiscsi_mccq_compl_wait - indicate blocking call. be_mcc_wait_compl -> be_mcc_compl_poll - indicate polling for completion. be_mbox_db_ready_wait -> be_mbox_db_ready_poll - indicate polling for RDY. be_mcc_compl_process -> beiscsi_process_mbox_compl - indicate BMBX compl. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 35 +-- drivers/scsi/be2iscsi/be_cmds.h | 6 +++--- drivers/scsi/be2iscsi/be_iscsi.c | 8 drivers/scsi/be2iscsi/be_main.c | 8 drivers/scsi/be2iscsi/be_mgmt.c | 12 ++-- 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index fa010ac..8dd8521 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -140,7 +140,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) } /* - * beiscsi_mccq_compl()- Wait for completion of MBX + * beiscsi_mccq_compl_wait()- Process completion in MCC CQ * @phba: Driver private structure * @tag: Tag for the MBX Command * @wrb: the WRB used for the MBX Command @@ -152,9 +152,9 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) * Success: 0 * Failure: Non-Zero **/ -int beiscsi_mccq_compl(struct beiscsi_hba *phba, - uint32_t tag, struct be_mcc_wrb **wrb, - struct be_dma_mem *mbx_cmd_mem) +int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, + uint32_t tag, struct be_mcc_wrb **wrb, + struct be_dma_mem *mbx_cmd_mem) { int rc = 0; uint32_t mcc_tag_status; @@ -283,7 +283,7 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) } /* - * be_mcc_compl_process()- Check the MBX comapletion status + * beiscsi_process_mbox_compl()- Check the MBX completion status * @ctrl: Function specific MBX data structure * @compl: Completion status of MBX Command * @@ -293,8 +293,8 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) * Success: Zero * Failure: Non-Zero **/ -static int be_mcc_compl_process(struct be_ctrl_info *ctrl, - struct be_mcc_compl *compl) +static int beiscsi_process_mbox_compl(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); @@ -520,7 +520,7 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, } /* - * be_mcc_wait_compl()- Wait for MBX completion + * be_mcc_compl_poll()- Wait for MBX completion * @phba: driver private structure * * Wait till no more pending mcc requests are present @@ -556,8 +556,7 @@ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) } /* -/* - * be_mbox_db_ready_wait()- Check ready status + * be_mbox_db_ready_poll()- Check ready status * @ctrl: Function specific MBX data structure * * Check for the ready status of FW to send BMBX @@ -567,7 +566,7 @@ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) * Success: 0 * Failure: Non-Zero **/ -static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) +static int be_mbox_db_ready_poll(struct be_ctrl_info *ctrl) { /* wait 30s for generic non-flash MBOX operation */ #define BEISCSI_MBX_RDY_BIT_TIMEOUT3 @@ -629,7 +628,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) struct be_mcc_compl *compl = &mbox->compl; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); - status = be_mbox_db_ready_wait(ctrl); + status = be_mbox_db_ready_poll(ctrl); if (status) return status; @@ -638,7 +637,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; iowrite32(val, db); - status = be_mbox_db_ready_wait(ctrl); + status = be_mbox_db_ready_poll(ctrl); if (status) return status; @@ -648,7 +647,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) val |= (u32) (mbox_mem->dma >> 4) << 2; iowrite32(val, db); - status = be_mbox_db_ready_wait(ctrl); + status = be_mbox_db_ready_poll(ctrl); if (status) return status; @@ -656,7 +655,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) udelay(1); if (be_mcc_compl_is_new(compl)) { - status = be_mcc_compl_process(ctrl, &mbox->compl); + status = beiscsi_process_mbox_compl(ctrl, compl); be_mcc_compl_use(compl); if (status) { beiscsi_log(phba, KERN_ERR, @@ -689,7 +688,7 @@ static int be_mbox_notify_wait(struct beiscsi_hba *phba) struct be_mcc_compl *compl = &mbox->compl; struct be_ctrl_info *ctrl = &phba->ctrl; - status = be_mbox_db_re
[PATCH 06/12] be2iscsi: Fix be_mcc_compl_poll to use tag_state
be_mcc_compl_poll waits till 'used' count of MCC WRBQ is zero. This is to determine the completion of an MCC sent. Change function to poll for the tag of MCC sent, instead, and wait till its tag_state is cleared. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 92 + 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 12b60dd..60db2de 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -104,19 +104,6 @@ int be_chk_reset_complete(struct beiscsi_hba *phba) return 0; } -void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) -{ - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; - u32 val = 0; - - set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); - val |= mccq->id & DB_MCCQ_RING_ID_MASK; - val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; - /* ring doorbell after all of request and state is written */ - wmb(); - iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); -} - unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) { unsigned int tag = 0; @@ -139,6 +126,28 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) return tag; } +void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) +{ + spin_lock_bh(&ctrl->mcc_lock); + tag = tag & MCC_Q_CMD_TAG_MASK; + ctrl->mcc_tag[ctrl->mcc_free_index] = tag; + if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) + ctrl->mcc_free_index = 0; + else + ctrl->mcc_free_index++; + ctrl->mcc_tag_available++; + spin_unlock_bh(&ctrl->mcc_lock); +} + +/** + * beiscsi_fail_session(): Closing session with appropriate error + * @cls_session: ptr to session + **/ +void beiscsi_fail_session(struct iscsi_cls_session *cls_session) +{ + iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); +} + /* * beiscsi_mccq_compl_wait()- Process completion in MCC CQ * @phba: Driver private structure @@ -254,19 +263,6 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, return rc; } -void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) -{ - spin_lock(&ctrl->mcc_lock); - tag = tag & MCC_Q_CMD_TAG_MASK; - ctrl->mcc_tag[ctrl->mcc_free_index] = tag; - if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) - ctrl->mcc_free_index = 0; - else - ctrl->mcc_free_index++; - ctrl->mcc_tag_available++; - spin_unlock(&ctrl->mcc_lock); -} - static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) { if (compl->flags != 0) { @@ -328,15 +324,6 @@ static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, return 0; } -/** - * beiscsi_fail_session(): Closing session with appropriate error - * @cls_session: ptr to session - **/ -void beiscsi_fail_session(struct iscsi_cls_session *cls_session) -{ - iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); -} - static void beiscsi_process_async_link(struct beiscsi_hba *phba, struct be_mcc_compl *compl) { @@ -532,6 +519,7 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, **/ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) { + struct be_ctrl_info *ctrl = &phba->ctrl; int i; for (i = 0; i < mcc_timeout; i++) { @@ -540,19 +528,33 @@ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) beiscsi_process_mcc_cq(phba); - if (atomic_read(&phba->ctrl.mcc_obj.q.used) == 0) + if (!test_bit(MCC_TAG_STATE_RUNNING, + &ctrl->ptag_state[tag].tag_state)) break; udelay(100); } - if (i == mcc_timeout) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : FW Timed Out\n"); - phba->fw_timeout = true; - beiscsi_ue_detect(phba); - return -EBUSY; - } - return 0; + + if (i < mcc_timeout) + return 0; + + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : FW Timed Out\n"); + phba->fw_timeout = true; + beiscsi_ue_detect(phba); + return -EBUSY; +} + +void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) +{ + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + u32 val = 0; + + set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); + val |= mccq->id & DB_MCCQ_RING_ID_MASK; + val |= 1
[PATCH 10/12] be2iscsi: Fix ExpStatSn in management tasks
Connection resets observed from some targets when NOP-Out with wrong ExpStatSn is sent. FW keeps track of StatSn and fills up ExpStatSn accordingly. The header filled up by the stack needs to be modified by driver to clear ExpStatSn. If the field is not cleared, FW recalculates ExpStatSn and wrong offset'ed ExpStatSn is seen in the wire trace. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 3f08a11..03265b6 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -4926,7 +4926,6 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, pwrb = io_task->pwrb_handle->pwrb; - io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; io_task->bhs_len = sizeof(struct be_cmd_bhs); if (writedir) { @@ -4987,7 +4986,6 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, unsigned int doorbell = 0; pwrb = io_task->pwrb_handle->pwrb; - io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; io_task->bhs_len = sizeof(struct be_cmd_bhs); if (writedir) { @@ -5159,23 +5157,21 @@ static int beiscsi_task_xmit(struct iscsi_task *task) { struct beiscsi_io_task *io_task = task->dd_data; struct scsi_cmnd *sc = task->sc; - struct beiscsi_hba *phba = NULL; + struct beiscsi_hba *phba; struct scatterlist *sg; int num_sg; unsigned int writedir = 0, xferlen = 0; - phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba; + if (!io_task->conn->login_in_progress) + task->hdr->exp_statsn = 0; if (!sc) return beiscsi_mtask(task); io_task->scsi_cmnd = sc; num_sg = scsi_dma_map(sc); + phba = io_task->conn->phba; if (num_sg < 0) { - struct iscsi_conn *conn = task->conn; - struct beiscsi_hba *phba = NULL; - - phba = ((struct beiscsi_conn *)conn->dd_data)->phba; beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI, "BM_%d : scsi_dma_map Failed " -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/12] be2iscsi: Remove unused mcc_cq_lock
mcc_cq_lock spin_lock is used only in beiscsi_process_mcc which is called only when all interrupts are disabled from mgmt_epfw_cleanup during unloading of driver. There is no other context where there can be contention for the processing of CQ. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be.h | 1 - drivers/scsi/be2iscsi/be_cmds.c | 2 -- drivers/scsi/be2iscsi/be_main.c | 1 - 3 files changed, 4 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 7d425af..1524fe4 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -132,7 +132,6 @@ struct be_ctrl_info { /* MCC Rings */ struct be_mcc_obj mcc_obj; spinlock_t mcc_lock;/* For serializing mcc cmds to BE card */ - spinlock_t mcc_cq_lock; wait_queue_head_t mcc_wait[MAX_MCC_CMD + 1]; unsigned int mcc_tag[MAX_MCC_CMD]; diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 34c33d4..e8e9d22 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -532,7 +532,6 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) int num = 0, status = 0; struct be_ctrl_info *ctrl = &phba->ctrl; - spin_lock_bh(&phba->ctrl.mcc_cq_lock); while ((compl = be_mcc_compl_get(phba))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { beiscsi_process_async_event(phba, compl); @@ -547,7 +546,6 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) if (num) hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1); - spin_unlock_bh(&phba->ctrl.mcc_cq_lock); return status; } diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 70179e1..314fd2c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -730,7 +730,6 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev) memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); mutex_init(&ctrl->mbox_lock); spin_lock_init(&phba->ctrl.mcc_lock); - spin_lock_init(&phba->ctrl.mcc_cq_lock); return status; } -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/12] be2iscsi: Fix MCC WRB leak in open_connection
In open with IP of unknown address family, only tag is freed and error returned. MCC WRB allocated for the operation is not freed. Added check for supported family of IP in the beginning before allocating the tag and WRB. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_mgmt.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 85044b8..ccac1d7 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -829,6 +829,13 @@ int mgmt_open_connection(struct beiscsi_hba *phba, unsigned short cid = beiscsi_ep->ep_cid; struct be_sge *sge; + if (dst_addr->sa_family != PF_INET && dst_addr->sa_family != PF_INET6) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, + "BG_%d : unknown addr family %d\n", + dst_addr->sa_family); + return -EINVAL; + } + phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; @@ -868,7 +875,8 @@ int mgmt_open_connection(struct beiscsi_hba *phba, beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); beiscsi_ep->ip_type = BE2_IPV4; - } else if (dst_addr->sa_family == PF_INET6) { + } else { + /* else its PF_INET6 family */ req->ip_address.ip_type = BE2_IPV6; memcpy(&req->ip_address.addr, &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); @@ -877,14 +885,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba, memcpy(&beiscsi_ep->dst6_addr, &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); beiscsi_ep->ip_type = BE2_IPV6; - } else{ - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BG_%d : unknown addr family %d\n", - dst_addr->sa_family); - mutex_unlock(&ctrl->mbox_lock); - free_mcc_tag(&phba->ctrl, tag); - return -EINVAL; - } req->cid = cid; i = phba->nxt_cqid++; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/12] be2iscsi: critical fixes for 11.0.0.0
This driver update has critical fixes for following issues: - Management tasks with incorrect ExpStatSn - WRB allocation failures in IO path - MCC WRB leak Jitendra Bhivare (12): be2iscsi: Remove unused mcc_cq_lock be2iscsi: Use macros for MCC WRB and CQE fields be2iscsi: Remove redundant MCC processing code be2iscsi: Rename MCC and BMBX processing functions be2iscsi: Remove be_mbox_notify_wait function be2iscsi: Fix be_mcc_compl_poll to use tag_state be2iscsi: Cleanup processing of BMBX completion be2iscsi: Fix MCC WRB leak in open_connection be2iscsi: Couple MCC tag and WRB alloc and free be2iscsi: Fix ExpStatSn in management tasks be2iscsi: _bh for io_sgl_lock and mgmt_sgl_lock be2iscsi: Add lock to protect WRB alloc and free drivers/scsi/be2iscsi/be.h | 11 +- drivers/scsi/be2iscsi/be_cmds.c | 522 +-- drivers/scsi/be2iscsi/be_cmds.h | 32 +-- drivers/scsi/be2iscsi/be_iscsi.c | 8 +- drivers/scsi/be2iscsi/be_main.c | 73 +++--- drivers/scsi/be2iscsi/be_main.h | 2 + drivers/scsi/be2iscsi/be_mgmt.c | 167 + 7 files changed, 355 insertions(+), 460 deletions(-) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/12] be2iscsi: Couple MCC tag and WRB alloc and free
WARN_ON(atomic_read(&mccq->used) >= mccq->len) seen when FW gets into UE. MCCQ overflow is happening because driver discards any new request and frees up the tag. The tag allocation controls the number of MCC WRB posted. It is being replenished but WRBs are not hence the WARN_ON. Allocation and freeing of WRB and tags for MCC is now done in one place. This helps to achieve proper accounting of WRB indices and MCC tags. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be.h | 2 +- drivers/scsi/be2iscsi/be_cmds.c | 103 +- drivers/scsi/be2iscsi/be_cmds.h | 6 +- drivers/scsi/be2iscsi/be_main.c | 3 +- drivers/scsi/be2iscsi/be_mgmt.c | 134 +++- 5 files changed, 130 insertions(+), 118 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index da1d87a..ee5ace8 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -42,7 +42,7 @@ struct be_queue_info { u16 id; u16 tail, head; bool created; - atomic_t used; /* Number of valid elements in the queue */ + u16 used; /* Number of valid elements in the queue */ }; static inline u32 MODULO(u16 val, u16 limit) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 728aa133..a55eaee 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -126,8 +126,62 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) return tag; } -void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) +struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, +unsigned int *ref_tag) { + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + struct be_mcc_wrb *wrb = NULL; + unsigned int tag; + + spin_lock_bh(&phba->ctrl.mcc_lock); + if (mccq->used == mccq->len) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : MCC queue full: WRB used %u tag avail %u\n", + mccq->used, phba->ctrl.mcc_tag_available); + goto alloc_failed; + } + + if (!phba->ctrl.mcc_tag_available) + goto alloc_failed; + + tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; + if (!tag) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : MCC tag 0 allocated: tag avail %u alloc index %u\n", + phba->ctrl.mcc_tag_available, + phba->ctrl.mcc_alloc_index); + goto alloc_failed; + } + + /* return this tag for further reference */ + *ref_tag = tag; + phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; + phba->ctrl.mcc_tag_status[tag] = 0; + phba->ctrl.ptag_state[tag].tag_state = 0; + phba->ctrl.mcc_tag_available--; + if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) + phba->ctrl.mcc_alloc_index = 0; + else + phba->ctrl.mcc_alloc_index++; + + wrb = queue_head_node(mccq); + memset(wrb, 0, sizeof(*wrb)); + wrb->tag0 = tag; + wrb->tag0 |= (mccq->head << MCC_Q_WRB_IDX_SHIFT) & MCC_Q_WRB_IDX_MASK; + queue_head_inc(mccq); + mccq->used++; + +alloc_failed: + spin_unlock_bh(&phba->ctrl.mcc_lock); + return wrb; +} + +void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag) +{ + struct be_queue_info *mccq = &ctrl->mcc_obj.q; + spin_lock_bh(&ctrl->mcc_lock); tag = tag & MCC_Q_CMD_TAG_MASK; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; @@ -136,6 +190,7 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) else ctrl->mcc_free_index++; ctrl->mcc_tag_available++; + mccq->used--; spin_unlock_bh(&ctrl->mcc_lock); } @@ -173,10 +228,8 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, 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); + if (beiscsi_error(phba)) return -EPERM; - } /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( @@ -259,7 +312,7 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, } } - free_mcc_tag(&phba->ctrl, tag); + free_mcc_wrb(&phba->ctrl, tag); return rc; } @@ -479,7 +532,7 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl,
[PATCH 05/12] be2iscsi: Remove be_mbox_notify_wait function
be_mbox_notify_wait does exactly same thing as be_mbox_notify. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 79 +++-- 1 file changed, 4 insertions(+), 75 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 8dd8521..12b60dd 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -625,8 +625,6 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; struct be_mcc_mailbox *mbox = mbox_mem->va; - struct be_mcc_compl *compl = &mbox->compl; - struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); status = be_mbox_db_ready_poll(ctrl); if (status) @@ -654,77 +652,8 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) /* RDY is set; small delay before CQE read. */ udelay(1); - if (be_mcc_compl_is_new(compl)) { - status = beiscsi_process_mbox_compl(ctrl, compl); - be_mcc_compl_use(compl); - if (status) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : After be_mcc_compl_process\n"); - - return status; - } - } else { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : Invalid Mailbox Completion\n"); - - return -EBUSY; - } - return 0; -} - -/* - * Insert the mailbox address into the doorbell in two steps - * Polls on the mbox doorbell till a command completion (or a timeout) occurs - */ -static int be_mbox_notify_wait(struct beiscsi_hba *phba) -{ - int status; - u32 val = 0; - void __iomem *db = phba->ctrl.db + MPU_MAILBOX_DB_OFFSET; - struct be_dma_mem *mbox_mem = &phba->ctrl.mbox_mem; - struct be_mcc_mailbox *mbox = mbox_mem->va; - struct be_mcc_compl *compl = &mbox->compl; - struct be_ctrl_info *ctrl = &phba->ctrl; - - status = be_mbox_db_ready_poll(ctrl); - if (status) - return status; - - val |= MPU_MAILBOX_DB_HI_MASK; - /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ - val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; - iowrite32(val, db); - - /* wait for ready to be set */ - status = be_mbox_db_ready_poll(ctrl); - if (status != 0) - return status; - - val = 0; - /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ - val |= (u32)(mbox_mem->dma >> 4) << 2; - iowrite32(val, db); - - status = be_mbox_db_ready_poll(ctrl); - if (status != 0) - return status; - - /* A cq entry has been made now */ - if (be_mcc_compl_is_new(compl)) { - status = be_mcc_compl_process(ctrl, &mbox->compl); - be_mcc_compl_use(compl); - if (status) - return status; - } else { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : invalid mailbox completion\n"); - - return -EBUSY; - } - return 0; + status = beiscsi_process_mbox_compl(ctrl, &mbox->compl); + return status; } void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, @@ -1039,7 +968,7 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_notify_wait(phba); + status = be_mbox_notify(ctrl); if (!status) { struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); mccq->id = le16_to_cpu(resp->id); @@ -1381,7 +1310,7 @@ int beiscsi_cmd_reset_function(struct beiscsi_hba *phba) 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_wait(phba); + status = be_mbox_notify(ctrl); mutex_unlock(&ctrl->mbox_lock); return status; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 12/12] be2iscsi: Add lock to protect WRB alloc and free
FW got into UE after running IO stress test With kernel change to split session lock in frwd_lock and back_lock for tx and rx path correspondingly, in the IO path, common resource used in driver such as WRB was left unprotected. Add wrb_lock spinlock to protect allocation and freeing of WRB. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.c | 5 + drivers/scsi/be2iscsi/be_main.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index fa2b589..0892ee2 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1190,12 +1190,14 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, { struct wrb_handle *pwrb_handle; + spin_lock_bh(&pwrb_context->wrb_lock); pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; pwrb_context->wrb_handles_available--; if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) pwrb_context->alloc_index = 0; else pwrb_context->alloc_index++; + spin_unlock_bh(&pwrb_context->wrb_lock); return pwrb_handle; } @@ -1227,12 +1229,14 @@ beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, struct wrb_handle *pwrb_handle, unsigned int wrbs_per_cxn) { + spin_lock_bh(&pwrb_context->wrb_lock); pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; pwrb_context->wrb_handles_available++; if (pwrb_context->free_index == (wrbs_per_cxn - 1)) pwrb_context->free_index = 0; else pwrb_context->free_index++; + spin_unlock_bh(&pwrb_context->wrb_lock); } /** @@ -2920,6 +2924,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) } num_cxn_wrbh--; } + spin_lock_init(&pwrb_context->wrb_lock); } idx = 0; for (index = 0; index < phba->params.cxns_per_ctrl; index++) { diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 5ded3fa..30a4606 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -304,6 +304,7 @@ struct invalidate_command_table { #define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \ (phwi_ctrlr->wrb_context[cri].ulp_num) struct hwi_wrb_context { + spinlock_t wrb_lock; struct list_head wrb_handle_list; struct list_head wrb_handle_drvr_list; struct wrb_handle **pwrb_handle_base; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/12] be2iscsi: Remove redundant MCC processing code
be_mcc_compl_process_isr is removed. MCC CQ processing is done only in beiscsi_process_mcc_cq and MCC CQE processing is done only in beiscsi_process_mcc_compl. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 164 ++-- drivers/scsi/be2iscsi/be_cmds.h | 7 +- drivers/scsi/be2iscsi/be_main.c | 8 +- drivers/scsi/be2iscsi/be_main.h | 1 + drivers/scsi/be2iscsi/be_mgmt.c | 3 +- 5 files changed, 68 insertions(+), 115 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index c5e7739..fa010ac 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -328,76 +328,6 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, return 0; } -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; - struct be_dma_mem *tag_mem; - unsigned int tag, wrb_idx; - - be_dws_le_to_cpu(compl, 4); - tag = (compl->tag0 & MCC_Q_CMD_TAG_MASK); - wrb_idx = (compl->tag0 & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; - - if (!test_bit(MCC_TAG_STATE_RUNNING, - &ctrl->ptag_state[tag].tag_state)) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX | - BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, - "BC_%d : MBX cmd completed but not posted\n"); - return 0; - } - - if (test_bit(MCC_TAG_STATE_TIMEOUT, -&ctrl->ptag_state[tag].tag_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 for the size before freeing resource. -* Only for non-embedded cmd, PCI resource is allocated. -**/ - tag_mem = &ctrl->ptag_state[tag].tag_mem_state; - if (tag_mem->size) - pci_free_consistent(ctrl->pdev, tag_mem->size, - tag_mem->va, tag_mem->dma); - free_mcc_tag(ctrl, tag); - return 0; - } - - compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & - CQE_STATUS_COMPL_MASK; - extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & - CQE_STATUS_EXTD_MASK; - /* The ctrl.mcc_tag_status[tag] is filled with -* [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status, -* [7:0] = compl_status -*/ - ctrl->mcc_tag_status[tag] = CQE_VALID_MASK; - ctrl->mcc_tag_status[tag] |= (wrb_idx << CQE_STATUS_WRB_SHIFT); - ctrl->mcc_tag_status[tag] |= (extd_status << CQE_STATUS_ADDL_SHIFT) & -CQE_STATUS_ADDL_MASK; - ctrl->mcc_tag_status[tag] |= (compl_status & CQE_STATUS_MASK); - - /* write ordering implied in wake_up_interruptible */ - clear_bit(MCC_TAG_STATE_RUNNING, &ctrl->ptag_state[tag].tag_state); - wake_up_interruptible(&ctrl->mcc_wait[tag]); - return 0; -} - -static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) -{ - struct be_queue_info *mcc_cq = &phba->ctrl.mcc_obj.cq; - struct be_mcc_compl *compl = queue_tail_node(mcc_cq); - - if (be_mcc_compl_is_new(compl)) { - queue_tail_inc(mcc_cq); - return compl; - } - return NULL; -} - /** * beiscsi_fail_session(): Closing session with appropriate error * @cls_session: ptr to session @@ -528,27 +458,65 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, evt_code, compl->status, compl->flags); } -int beiscsi_process_mcc(struct beiscsi_hba *phba) +int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, + struct be_mcc_compl *compl) { - struct be_mcc_compl *compl; - int num = 0, status = 0; - struct be_ctrl_info *ctrl = &phba->ctrl; + struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + u16 compl_status, extd_status; + struct be_dma_mem *tag_mem; + unsigned int tag, wrb_idx; - while ((compl = be_mcc_compl_get(phba))) { - if (compl->flags & CQE_FLAGS_ASYNC_MASK) { - beiscsi_process_async_event(phba, compl); - } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { - status = be_mcc_compl_process(ctrl, compl); - atomic_dec(&a
[PATCH 02/12] be2iscsi: Use macros for MCC WRB and CQE fields
Rename mcc_numtag to mcc_tag_status. MCC CQE status is processed using macros already defined in be_cmds.h. Add MCC_Q_WRB_ and MCC_Q_CMD_TAG_MASK macros to map to already defined CQE_STATUS_ macros to be consistent when posting MCC. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be.h | 8 +++- drivers/scsi/be2iscsi/be_cmds.c | 40 +--- drivers/scsi/be2iscsi/be_cmds.h | 13 +++-- drivers/scsi/be2iscsi/be_main.c | 11 ++- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 1524fe4..da1d87a 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -135,7 +135,7 @@ struct be_ctrl_info { wait_queue_head_t mcc_wait[MAX_MCC_CMD + 1]; unsigned int mcc_tag[MAX_MCC_CMD]; - unsigned int mcc_numtag[MAX_MCC_CMD + 1]; + unsigned int mcc_tag_status[MAX_MCC_CMD + 1]; unsigned short mcc_alloc_index; unsigned short mcc_free_index; unsigned int mcc_tag_available; @@ -145,6 +145,12 @@ struct be_ctrl_info { #include "be_cmds.h" +/* WRB index mask for MCC_Q_LEN queue entries */ +#define MCC_Q_WRB_IDX_MASK CQE_STATUS_WRB_MASK +#define MCC_Q_WRB_IDX_SHIFTCQE_STATUS_WRB_SHIFT +/* TAG is from 1...MAX_MCC_CMD, MASK includes MAX_MCC_CMD */ +#define MCC_Q_CMD_TAG_MASK ((MAX_MCC_CMD << 1) - 1) + #define PAGE_SHIFT_4K 12 #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) #define mcc_timeout12 /* 12s timeout */ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index e8e9d22..c5e7739 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -125,7 +125,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) if (phba->ctrl.mcc_tag_available) { tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; - phba->ctrl.mcc_numtag[tag] = 0; + phba->ctrl.mcc_tag_status[tag] = 0; phba->ctrl.ptag_state[tag].tag_state = 0; } if (tag) { @@ -157,7 +157,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, struct be_dma_mem *mbx_cmd_mem) { int rc = 0; - uint32_t mcc_tag_response; + uint32_t mcc_tag_status; uint16_t status = 0, addl_status = 0, wrb_num = 0; struct be_mcc_wrb *temp_wrb; struct be_cmd_req_hdr *mbx_hdr; @@ -172,7 +172,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag], + phba->ctrl.mcc_tag_status[tag], msecs_to_jiffies( BEISCSI_HOST_MBX_TIMEOUT)); /** @@ -209,15 +209,15 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } 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) >> + mcc_tag_status = phba->ctrl.mcc_tag_status[tag]; + status = (mcc_tag_status & CQE_STATUS_MASK); + addl_status = ((mcc_tag_status & CQE_STATUS_ADDL_MASK) >> CQE_STATUS_ADDL_SHIFT); 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) >> + wrb_num = (mcc_tag_status & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num); mbx_hdr = embedded_payload(temp_wrb); @@ -257,7 +257,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { spin_lock(&ctrl->mcc_lock); - tag = tag & 0x00FF; + tag = tag & MCC_Q_CMD_TAG_MASK; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) ctrl->mcc_free_index = 0; @@ -334,10 +334,11 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); u16 compl_status, extd_status; struct be_dma_mem *tag_mem; - unsigned short tag; + unsigned int tag, wrb_idx; be_dws_le_to_cpu(compl, 4); - tag = (compl->tag0 & 0x00FF); + tag = (compl->tag0 & MCC_Q_CMD_TAG_MASK); + wrb_idx = (compl->tag0 & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; if
[PATCH 07/12] be2iscsi: Cleanup processing of BMBX completion
Remove confusingly named be_mcc_compl_is_new and be_mcc_compl_use functions in processing of BMBX. Rearrange beiscsi_process_mbox_compl function. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 75 - 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 60db2de..728aa133 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -263,21 +263,6 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, return rc; } -static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) -{ - if (compl->flags != 0) { - compl->flags = le32_to_cpu(compl->flags); - WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); - return true; - } else - return false; -} - -static inline void be_mcc_compl_use(struct be_mcc_compl *compl) -{ - compl->flags = 0; -} - /* * beiscsi_process_mbox_compl()- Check the MBX completion status * @ctrl: Function specific MBX data structure @@ -298,30 +283,46 @@ static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, struct be_cmd_req_hdr *hdr = embedded_payload(wrb); struct be_cmd_resp_hdr *resp_hdr; - be_dws_le_to_cpu(compl, 4); + /** +* To check if valid bit is set, check the entire word as we don't know +* the endianness of the data (old entry is host endian while a new +* entry is little endian) +*/ + if (!compl->flags) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : BMBX busy, no completion\n"); + return -EBUSY; + } + compl->flags = le32_to_cpu(compl->flags); + WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); + /** +* Just swap the status to host endian; +* mcc tag is opaquely copied from mcc_wrb. +*/ + be_dws_le_to_cpu(compl, 4); compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & - CQE_STATUS_COMPL_MASK; - if (compl_status != MCC_STATUS_SUCCESS) { - extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & - CQE_STATUS_EXTD_MASK; + CQE_STATUS_COMPL_MASK; + extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + /* Need to reset the entire word that houses the valid bit */ + compl->flags = 0; - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : error in cmd completion: " - "Subsystem : %d Opcode : %d " - "status(compl/extd)=%d/%d\n", - hdr->subsystem, hdr->opcode, - compl_status, extd_status); - - if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) { - resp_hdr = (struct be_cmd_resp_hdr *) hdr; - if (resp_hdr->response_length) - return 0; - } - return -EINVAL; + if (compl_status == MCC_STATUS_SUCCESS) + return 0; + + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : error in cmd completion: Subsystem : %d Opcode : %d status(compl/extd)=%d/%d\n", + hdr->subsystem, hdr->opcode, compl_status, extd_status); + + if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) { + /* if status is insufficient buffer, check the length */ + resp_hdr = (struct be_cmd_resp_hdr *) hdr; + if (resp_hdr->response_length) + return 0; } - return 0; + return -EINVAL; } static void beiscsi_process_async_link(struct beiscsi_hba *phba, @@ -453,10 +454,6 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, struct be_dma_mem *tag_mem; unsigned int tag, wrb_idx; - /** -* Just swap the status to host endian; mcc tag is opaquely copied -* from mcc_wrb -*/ be_dws_le_to_cpu(compl, 4); tag = (compl->tag0 & MCC_Q_CMD_TAG_MASK); wrb_idx = (compl->tag0 & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 11/12] be2iscsi: _bh for io_sgl_lock and mgmt_sgl_lock
Processing of mgmt and IO tasks are done in process context and sofitrqs. Allocation and freeing of sgl_handles needs to be done under spin_lock_bh/spin_unlock_bh and move the locks to the routines. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.c | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 03265b6..fa2b589 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1132,6 +1132,7 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) { struct sgl_handle *psgl_handle; + spin_lock_bh(&phba->io_sgl_lock); if (phba->io_sgl_hndl_avbl) { beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, "BM_%d : In alloc_io_sgl_handle," @@ -1149,12 +1150,14 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) phba->io_sgl_alloc_index++; } else psgl_handle = NULL; + spin_unlock_bh(&phba->io_sgl_lock); return psgl_handle; } static void free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { + spin_lock_bh(&phba->io_sgl_lock); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, "BM_%d : In free_,io_sgl_free_index=%d\n", phba->io_sgl_free_index); @@ -1169,6 +1172,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) "value there=%p\n", phba->io_sgl_free_index, phba->io_sgl_hndl_base [phba->io_sgl_free_index]); +spin_unlock_bh(&phba->io_sgl_lock); return; } phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle; @@ -1177,6 +1181,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->io_sgl_free_index = 0; else phba->io_sgl_free_index++; + spin_unlock_bh(&phba->io_sgl_lock); } static inline struct wrb_handle * @@ -1257,6 +1262,7 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) { struct sgl_handle *psgl_handle; + spin_lock_bh(&phba->mgmt_sgl_lock); if (phba->eh_sgl_hndl_avbl) { psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index]; phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL; @@ -1274,13 +1280,14 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) phba->eh_sgl_alloc_index++; } else psgl_handle = NULL; + spin_unlock_bh(&phba->mgmt_sgl_lock); return psgl_handle; } void free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { - + spin_lock_bh(&phba->mgmt_sgl_lock); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, "BM_%d : In free_mgmt_sgl_handle," "eh_sgl_free_index=%d\n", @@ -1295,6 +1302,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) "BM_%d : Double Free in eh SGL ," "eh_sgl_free_index=%d\n", phba->eh_sgl_free_index); + spin_unlock_bh(&phba->mgmt_sgl_lock); return; } phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle; @@ -1304,6 +1312,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->eh_sgl_free_index = 0; else phba->eh_sgl_free_index++; + spin_unlock_bh(&phba->mgmt_sgl_lock); } static void @@ -4616,11 +4625,9 @@ beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, } if (io_task->psgl_handle) { - spin_lock_bh(&phba->mgmt_sgl_lock); free_mgmt_sgl_handle(phba, io_task->psgl_handle); io_task->psgl_handle = NULL; - spin_unlock_bh(&phba->mgmt_sgl_lock); } if (io_task->mtask_addr) { @@ -4666,9 +4673,7 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) } if (io_task->psgl_handle) { - spin_lock(&phba->io_sgl_lock); free_io_sgl_handle(phba, io_task->psgl_handle); - spin_unlock(&phba->io_sgl_lock); io_task->psgl_handle = NULL; } @@ -4784,9 +4789,7 @@ static int beiscsi_alloc_pdu(struct iscsi
[PATCH v1 00/12] be2iscsi: Important fixes for 11.0.0.0 in 4.6/scsi-queue
This driver update has critical fixes for following issues: - Management tasks with incorrect ExpStatSn - WRB allocation failures in IO path - MCC WRB leak Jitendra Bhivare (12): be2iscsi: Remove unused mcc_cq_lock be2iscsi: Use macros for MCC WRB and CQE fields be2iscsi: Remove redundant MCC processing code be2iscsi: Rename MCC and BMBX processing functions be2iscsi: Remove be_mbox_notify_wait function be2iscsi: Fix be_mcc_compl_poll to use tag_state be2iscsi: Cleanup processing of BMBX completion be2iscsi: Fix MCC WRB leak in open_connection be2iscsi: Couple MCC tag and WRB alloc and free be2iscsi: Fix ExpStatSn in management tasks be2iscsi: _bh for io_sgl_lock and mgmt_sgl_lock be2iscsi: Add lock to protect WRB alloc and free drivers/scsi/be2iscsi/be.h | 11 +- drivers/scsi/be2iscsi/be_cmds.c | 522 +-- drivers/scsi/be2iscsi/be_cmds.h | 32 +-- drivers/scsi/be2iscsi/be_iscsi.c | 8 +- drivers/scsi/be2iscsi/be_main.c | 73 +++--- drivers/scsi/be2iscsi/be_main.h | 2 + drivers/scsi/be2iscsi/be_mgmt.c | 167 + 7 files changed, 355 insertions(+), 460 deletions(-) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v1 06/12] be2iscsi: Fix be_mcc_compl_poll to use tag_state
be_mcc_compl_poll waits till 'used' count of MCC WRBQ is zero. This is to determine the completion of an MCC sent. Change function to poll for the tag of MCC sent, instead, and wait till its tag_state is cleared. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_cmds.c | 92 + 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 12b60dd..60db2de 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -104,19 +104,6 @@ int be_chk_reset_complete(struct beiscsi_hba *phba) return 0; } -void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) -{ - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; - u32 val = 0; - - set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); - val |= mccq->id & DB_MCCQ_RING_ID_MASK; - val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; - /* ring doorbell after all of request and state is written */ - wmb(); - iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); -} - unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) { unsigned int tag = 0; @@ -139,6 +126,28 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) return tag; } +void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) +{ + spin_lock_bh(&ctrl->mcc_lock); + tag = tag & MCC_Q_CMD_TAG_MASK; + ctrl->mcc_tag[ctrl->mcc_free_index] = tag; + if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) + ctrl->mcc_free_index = 0; + else + ctrl->mcc_free_index++; + ctrl->mcc_tag_available++; + spin_unlock_bh(&ctrl->mcc_lock); +} + +/** + * beiscsi_fail_session(): Closing session with appropriate error + * @cls_session: ptr to session + **/ +void beiscsi_fail_session(struct iscsi_cls_session *cls_session) +{ + iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); +} + /* * beiscsi_mccq_compl_wait()- Process completion in MCC CQ * @phba: Driver private structure @@ -254,19 +263,6 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, return rc; } -void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) -{ - spin_lock(&ctrl->mcc_lock); - tag = tag & MCC_Q_CMD_TAG_MASK; - ctrl->mcc_tag[ctrl->mcc_free_index] = tag; - if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) - ctrl->mcc_free_index = 0; - else - ctrl->mcc_free_index++; - ctrl->mcc_tag_available++; - spin_unlock(&ctrl->mcc_lock); -} - static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) { if (compl->flags != 0) { @@ -328,15 +324,6 @@ static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, return 0; } -/** - * beiscsi_fail_session(): Closing session with appropriate error - * @cls_session: ptr to session - **/ -void beiscsi_fail_session(struct iscsi_cls_session *cls_session) -{ - iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); -} - static void beiscsi_process_async_link(struct beiscsi_hba *phba, struct be_mcc_compl *compl) { @@ -532,6 +519,7 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, **/ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) { + struct be_ctrl_info *ctrl = &phba->ctrl; int i; for (i = 0; i < mcc_timeout; i++) { @@ -540,19 +528,33 @@ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) beiscsi_process_mcc_cq(phba); - if (atomic_read(&phba->ctrl.mcc_obj.q.used) == 0) + if (!test_bit(MCC_TAG_STATE_RUNNING, + &ctrl->ptag_state[tag].tag_state)) break; udelay(100); } - if (i == mcc_timeout) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : FW Timed Out\n"); - phba->fw_timeout = true; - beiscsi_ue_detect(phba); - return -EBUSY; - } - return 0; + + if (i < mcc_timeout) + return 0; + + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : FW Timed Out\n"); + phba->fw_timeout = true; + beiscsi_ue_detect(phba); + return -EBUSY; +} + +void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) +{ + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + u32 val = 0; + + set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); + val |= mccq->id & DB_MC
[PATCH v1 07/12] be2iscsi: Cleanup processing of BMBX completion
Remove confusingly named be_mcc_compl_is_new and be_mcc_compl_use functions in processing of BMBX. Rearrange beiscsi_process_mbox_compl function. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_cmds.c | 75 - 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 60db2de..728aa133 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -263,21 +263,6 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, return rc; } -static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) -{ - if (compl->flags != 0) { - compl->flags = le32_to_cpu(compl->flags); - WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); - return true; - } else - return false; -} - -static inline void be_mcc_compl_use(struct be_mcc_compl *compl) -{ - compl->flags = 0; -} - /* * beiscsi_process_mbox_compl()- Check the MBX completion status * @ctrl: Function specific MBX data structure @@ -298,30 +283,46 @@ static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, struct be_cmd_req_hdr *hdr = embedded_payload(wrb); struct be_cmd_resp_hdr *resp_hdr; - be_dws_le_to_cpu(compl, 4); + /** +* To check if valid bit is set, check the entire word as we don't know +* the endianness of the data (old entry is host endian while a new +* entry is little endian) +*/ + if (!compl->flags) { + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : BMBX busy, no completion\n"); + return -EBUSY; + } + compl->flags = le32_to_cpu(compl->flags); + WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); + /** +* Just swap the status to host endian; +* mcc tag is opaquely copied from mcc_wrb. +*/ + be_dws_le_to_cpu(compl, 4); compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & - CQE_STATUS_COMPL_MASK; - if (compl_status != MCC_STATUS_SUCCESS) { - extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & - CQE_STATUS_EXTD_MASK; + CQE_STATUS_COMPL_MASK; + extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + /* Need to reset the entire word that houses the valid bit */ + compl->flags = 0; - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : error in cmd completion: " - "Subsystem : %d Opcode : %d " - "status(compl/extd)=%d/%d\n", - hdr->subsystem, hdr->opcode, - compl_status, extd_status); - - if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) { - resp_hdr = (struct be_cmd_resp_hdr *) hdr; - if (resp_hdr->response_length) - return 0; - } - return -EINVAL; + if (compl_status == MCC_STATUS_SUCCESS) + return 0; + + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : error in cmd completion: Subsystem : %d Opcode : %d status(compl/extd)=%d/%d\n", + hdr->subsystem, hdr->opcode, compl_status, extd_status); + + if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) { + /* if status is insufficient buffer, check the length */ + resp_hdr = (struct be_cmd_resp_hdr *) hdr; + if (resp_hdr->response_length) + return 0; } - return 0; + return -EINVAL; } static void beiscsi_process_async_link(struct beiscsi_hba *phba, @@ -453,10 +454,6 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, struct be_dma_mem *tag_mem; unsigned int tag, wrb_idx; - /** -* Just swap the status to host endian; mcc tag is opaquely copied -* from mcc_wrb -*/ be_dws_le_to_cpu(compl, 4); tag = (compl->tag0 & MCC_Q_CMD_TAG_MASK); wrb_idx = (compl->tag0 & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v1 09/12] be2iscsi: Couple MCC tag and WRB alloc and free
WARN_ON(atomic_read(&mccq->used) >= mccq->len) seen when FW gets into UE. MCCQ overflow is happening because driver discards any new request and frees up the tag. The tag allocation controls the number of MCC WRB posted. It is being replenished but WRBs are not hence the WARN_ON. Allocation and freeing of WRB and tags for MCC is now done in one place. This helps to achieve proper accounting of WRB indices and MCC tags. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be.h | 2 +- drivers/scsi/be2iscsi/be_cmds.c | 103 +- drivers/scsi/be2iscsi/be_cmds.h | 6 +- drivers/scsi/be2iscsi/be_main.c | 3 +- drivers/scsi/be2iscsi/be_mgmt.c | 134 +++- 5 files changed, 130 insertions(+), 118 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index da1d87a..ee5ace8 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -42,7 +42,7 @@ struct be_queue_info { u16 id; u16 tail, head; bool created; - atomic_t used; /* Number of valid elements in the queue */ + u16 used; /* Number of valid elements in the queue */ }; static inline u32 MODULO(u16 val, u16 limit) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 728aa133..a55eaee 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -126,8 +126,62 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) return tag; } -void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) +struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, +unsigned int *ref_tag) { + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + struct be_mcc_wrb *wrb = NULL; + unsigned int tag; + + spin_lock_bh(&phba->ctrl.mcc_lock); + if (mccq->used == mccq->len) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : MCC queue full: WRB used %u tag avail %u\n", + mccq->used, phba->ctrl.mcc_tag_available); + goto alloc_failed; + } + + if (!phba->ctrl.mcc_tag_available) + goto alloc_failed; + + tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; + if (!tag) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : MCC tag 0 allocated: tag avail %u alloc index %u\n", + phba->ctrl.mcc_tag_available, + phba->ctrl.mcc_alloc_index); + goto alloc_failed; + } + + /* return this tag for further reference */ + *ref_tag = tag; + phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; + phba->ctrl.mcc_tag_status[tag] = 0; + phba->ctrl.ptag_state[tag].tag_state = 0; + phba->ctrl.mcc_tag_available--; + if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) + phba->ctrl.mcc_alloc_index = 0; + else + phba->ctrl.mcc_alloc_index++; + + wrb = queue_head_node(mccq); + memset(wrb, 0, sizeof(*wrb)); + wrb->tag0 = tag; + wrb->tag0 |= (mccq->head << MCC_Q_WRB_IDX_SHIFT) & MCC_Q_WRB_IDX_MASK; + queue_head_inc(mccq); + mccq->used++; + +alloc_failed: + spin_unlock_bh(&phba->ctrl.mcc_lock); + return wrb; +} + +void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag) +{ + struct be_queue_info *mccq = &ctrl->mcc_obj.q; + spin_lock_bh(&ctrl->mcc_lock); tag = tag & MCC_Q_CMD_TAG_MASK; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; @@ -136,6 +190,7 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) else ctrl->mcc_free_index++; ctrl->mcc_tag_available++; + mccq->used--; spin_unlock_bh(&ctrl->mcc_lock); } @@ -173,10 +228,8 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, 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); + if (beiscsi_error(phba)) return -EPERM; - } /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( @@ -259,7 +312,7 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, } } - free_mcc_tag(&phba->ctrl, tag); + free_mcc_wrb(&phba->ctrl, tag); return rc; } @@ -479,7 +532,7 @@ int beiscsi_process_mcc_compl(str
[PATCH v1 11/12] be2iscsi: _bh for io_sgl_lock and mgmt_sgl_lock
Processing of mgmt and IO tasks are done in process context and sofitrqs. Allocation and freeing of sgl_handles needs to be done under spin_lock_bh/spin_unlock_bh and move the locks to the routines. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_main.c | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 03265b6..fa2b589 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1132,6 +1132,7 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) { struct sgl_handle *psgl_handle; + spin_lock_bh(&phba->io_sgl_lock); if (phba->io_sgl_hndl_avbl) { beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, "BM_%d : In alloc_io_sgl_handle," @@ -1149,12 +1150,14 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) phba->io_sgl_alloc_index++; } else psgl_handle = NULL; + spin_unlock_bh(&phba->io_sgl_lock); return psgl_handle; } static void free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { + spin_lock_bh(&phba->io_sgl_lock); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, "BM_%d : In free_,io_sgl_free_index=%d\n", phba->io_sgl_free_index); @@ -1169,6 +1172,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) "value there=%p\n", phba->io_sgl_free_index, phba->io_sgl_hndl_base [phba->io_sgl_free_index]); +spin_unlock_bh(&phba->io_sgl_lock); return; } phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle; @@ -1177,6 +1181,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->io_sgl_free_index = 0; else phba->io_sgl_free_index++; + spin_unlock_bh(&phba->io_sgl_lock); } static inline struct wrb_handle * @@ -1257,6 +1262,7 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) { struct sgl_handle *psgl_handle; + spin_lock_bh(&phba->mgmt_sgl_lock); if (phba->eh_sgl_hndl_avbl) { psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index]; phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL; @@ -1274,13 +1280,14 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) phba->eh_sgl_alloc_index++; } else psgl_handle = NULL; + spin_unlock_bh(&phba->mgmt_sgl_lock); return psgl_handle; } void free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) { - + spin_lock_bh(&phba->mgmt_sgl_lock); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, "BM_%d : In free_mgmt_sgl_handle," "eh_sgl_free_index=%d\n", @@ -1295,6 +1302,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) "BM_%d : Double Free in eh SGL ," "eh_sgl_free_index=%d\n", phba->eh_sgl_free_index); + spin_unlock_bh(&phba->mgmt_sgl_lock); return; } phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle; @@ -1304,6 +1312,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->eh_sgl_free_index = 0; else phba->eh_sgl_free_index++; + spin_unlock_bh(&phba->mgmt_sgl_lock); } static void @@ -4616,11 +4625,9 @@ beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, } if (io_task->psgl_handle) { - spin_lock_bh(&phba->mgmt_sgl_lock); free_mgmt_sgl_handle(phba, io_task->psgl_handle); io_task->psgl_handle = NULL; - spin_unlock_bh(&phba->mgmt_sgl_lock); } if (io_task->mtask_addr) { @@ -4666,9 +4673,7 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) } if (io_task->psgl_handle) { - spin_lock(&phba->io_sgl_lock); free_io_sgl_handle(phba, io_task->psgl_handle); - spin_unlock(&phba->io_sgl_lock); io_task->psgl_handle = NULL; } @@ -4784,9 +47
[PATCH v1 05/12] be2iscsi: Remove be_mbox_notify_wait function
be_mbox_notify_wait does exactly same thing as be_mbox_notify. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_cmds.c | 79 +++-- 1 file changed, 4 insertions(+), 75 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 1fe8eb8..12b60dd 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -625,8 +625,6 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; struct be_mcc_mailbox *mbox = mbox_mem->va; - struct be_mcc_compl *compl = &mbox->compl; - struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); status = be_mbox_db_ready_poll(ctrl); if (status) @@ -654,77 +652,8 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) /* RDY is set; small delay before CQE read. */ udelay(1); - if (be_mcc_compl_is_new(compl)) { - status = beiscsi_process_mbox_compl(ctrl, compl); - be_mcc_compl_use(compl); - if (status) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : After beiscsi_process_mbox_compl\n"); - - return status; - } - } else { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : Invalid Mailbox Completion\n"); - - return -EBUSY; - } - return 0; -} - -/* - * Insert the mailbox address into the doorbell in two steps - * Polls on the mbox doorbell till a command completion (or a timeout) occurs - */ -static int be_mbox_notify_wait(struct beiscsi_hba *phba) -{ - int status; - u32 val = 0; - void __iomem *db = phba->ctrl.db + MPU_MAILBOX_DB_OFFSET; - struct be_dma_mem *mbox_mem = &phba->ctrl.mbox_mem; - struct be_mcc_mailbox *mbox = mbox_mem->va; - struct be_mcc_compl *compl = &mbox->compl; - struct be_ctrl_info *ctrl = &phba->ctrl; - - status = be_mbox_db_ready_poll(ctrl); - if (status) - return status; - - val |= MPU_MAILBOX_DB_HI_MASK; - /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ - val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; - iowrite32(val, db); - - /* wait for ready to be set */ - status = be_mbox_db_ready_poll(ctrl); - if (status != 0) - return status; - - val = 0; - /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ - val |= (u32)(mbox_mem->dma >> 4) << 2; - iowrite32(val, db); - - status = be_mbox_db_ready_poll(ctrl); - if (status != 0) - return status; - - /* A cq entry has been made now */ - if (be_mcc_compl_is_new(compl)) { - status = beiscsi_process_mbox_compl(ctrl, &mbox->compl); - be_mcc_compl_use(compl); - if (status) - return status; - } else { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : invalid mailbox completion\n"); - - return -EBUSY; - } - return 0; + status = beiscsi_process_mbox_compl(ctrl, &mbox->compl); + return status; } void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, @@ -1039,7 +968,7 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); - status = be_mbox_notify_wait(phba); + status = be_mbox_notify(ctrl); if (!status) { struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); mccq->id = le16_to_cpu(resp->id); @@ -1381,7 +1310,7 @@ int beiscsi_cmd_reset_function(struct beiscsi_hba *phba) 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_wait(phba); + status = be_mbox_notify(ctrl); mutex_unlock(&ctrl->mbox_lock); return status; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v1 10/12] be2iscsi: Fix ExpStatSn in management tasks
Connection resets observed from some targets when NOP-Out with wrong ExpStatSn is sent. FW keeps track of StatSn and fills up ExpStatSn accordingly. The header filled up by the stack needs to be modified by driver to clear ExpStatSn. If the field is not cleared, FW recalculates ExpStatSn and wrong offset'ed ExpStatSn is seen in the wire trace. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_main.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 3f08a11..03265b6 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -4926,7 +4926,6 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, pwrb = io_task->pwrb_handle->pwrb; - io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; io_task->bhs_len = sizeof(struct be_cmd_bhs); if (writedir) { @@ -4987,7 +4986,6 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, unsigned int doorbell = 0; pwrb = io_task->pwrb_handle->pwrb; - io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; io_task->bhs_len = sizeof(struct be_cmd_bhs); if (writedir) { @@ -5159,23 +5157,21 @@ static int beiscsi_task_xmit(struct iscsi_task *task) { struct beiscsi_io_task *io_task = task->dd_data; struct scsi_cmnd *sc = task->sc; - struct beiscsi_hba *phba = NULL; + struct beiscsi_hba *phba; struct scatterlist *sg; int num_sg; unsigned int writedir = 0, xferlen = 0; - phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba; + if (!io_task->conn->login_in_progress) + task->hdr->exp_statsn = 0; if (!sc) return beiscsi_mtask(task); io_task->scsi_cmnd = sc; num_sg = scsi_dma_map(sc); + phba = io_task->conn->phba; if (num_sg < 0) { - struct iscsi_conn *conn = task->conn; - struct beiscsi_hba *phba = NULL; - - phba = ((struct beiscsi_conn *)conn->dd_data)->phba; beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI, "BM_%d : scsi_dma_map Failed " -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v1 12/12] be2iscsi: Add lock to protect WRB alloc and free
FW got into UE after running IO stress test With kernel change to split session lock in frwd_lock and back_lock for tx and rx path correspondingly, in the IO path, common resource used in driver such as WRB was left unprotected. Add wrb_lock spinlock to protect allocation and freeing of WRB. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_main.c | 5 + drivers/scsi/be2iscsi/be_main.h | 1 + 2 files changed, 6 insertions(+) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index fa2b589..0892ee2 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1190,12 +1190,14 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, { struct wrb_handle *pwrb_handle; + spin_lock_bh(&pwrb_context->wrb_lock); pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; pwrb_context->wrb_handles_available--; if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) pwrb_context->alloc_index = 0; else pwrb_context->alloc_index++; + spin_unlock_bh(&pwrb_context->wrb_lock); return pwrb_handle; } @@ -1227,12 +1229,14 @@ beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, struct wrb_handle *pwrb_handle, unsigned int wrbs_per_cxn) { + spin_lock_bh(&pwrb_context->wrb_lock); pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; pwrb_context->wrb_handles_available++; if (pwrb_context->free_index == (wrbs_per_cxn - 1)) pwrb_context->free_index = 0; else pwrb_context->free_index++; + spin_unlock_bh(&pwrb_context->wrb_lock); } /** @@ -2920,6 +2924,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) } num_cxn_wrbh--; } + spin_lock_init(&pwrb_context->wrb_lock); } idx = 0; for (index = 0; index < phba->params.cxns_per_ctrl; index++) { diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 5ded3fa..30a4606 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -304,6 +304,7 @@ struct invalidate_command_table { #define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \ (phwi_ctrlr->wrb_context[cri].ulp_num) struct hwi_wrb_context { + spinlock_t wrb_lock; struct list_head wrb_handle_list; struct list_head wrb_handle_drvr_list; struct wrb_handle **pwrb_handle_base; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v1 08/12] be2iscsi: Fix MCC WRB leak in open_connection
In open with IP of unknown address family, only tag is freed and error returned. MCC WRB allocated for the operation is not freed. Added check for supported family of IP in the beginning before allocating the tag and WRB. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_mgmt.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 85044b8..ccac1d7 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -829,6 +829,13 @@ int mgmt_open_connection(struct beiscsi_hba *phba, unsigned short cid = beiscsi_ep->ep_cid; struct be_sge *sge; + if (dst_addr->sa_family != PF_INET && dst_addr->sa_family != PF_INET6) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, + "BG_%d : unknown addr family %d\n", + dst_addr->sa_family); + return -EINVAL; + } + phwi_ctrlr = phba->phwi_ctrlr; phwi_context = phwi_ctrlr->phwi_ctxt; @@ -868,7 +875,8 @@ int mgmt_open_connection(struct beiscsi_hba *phba, beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); beiscsi_ep->ip_type = BE2_IPV4; - } else if (dst_addr->sa_family == PF_INET6) { + } else { + /* else its PF_INET6 family */ req->ip_address.ip_type = BE2_IPV6; memcpy(&req->ip_address.addr, &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); @@ -877,14 +885,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba, memcpy(&beiscsi_ep->dst6_addr, &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); beiscsi_ep->ip_type = BE2_IPV6; - } else{ - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BG_%d : unknown addr family %d\n", - dst_addr->sa_family); - mutex_unlock(&ctrl->mbox_lock); - free_mcc_tag(&phba->ctrl, tag); - return -EINVAL; - } req->cid = cid; i = phba->nxt_cqid++; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v1 03/12] be2iscsi: Remove redundant MCC processing code
be_mcc_compl_process_isr is removed. MCC CQ processing is done only in beiscsi_process_mcc_cq and MCC CQE processing is done only in beiscsi_process_mcc_compl. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_cmds.c | 165 ++-- drivers/scsi/be2iscsi/be_cmds.h | 7 +- drivers/scsi/be2iscsi/be_main.c | 8 +- drivers/scsi/be2iscsi/be_main.h | 1 + drivers/scsi/be2iscsi/be_mgmt.c | 3 +- 5 files changed, 68 insertions(+), 116 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index c5e7739..f59dbdf 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -328,76 +328,6 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, return 0; } -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; - struct be_dma_mem *tag_mem; - unsigned int tag, wrb_idx; - - be_dws_le_to_cpu(compl, 4); - tag = (compl->tag0 & MCC_Q_CMD_TAG_MASK); - wrb_idx = (compl->tag0 & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; - - if (!test_bit(MCC_TAG_STATE_RUNNING, - &ctrl->ptag_state[tag].tag_state)) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX | - BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, - "BC_%d : MBX cmd completed but not posted\n"); - return 0; - } - - if (test_bit(MCC_TAG_STATE_TIMEOUT, -&ctrl->ptag_state[tag].tag_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 for the size before freeing resource. -* Only for non-embedded cmd, PCI resource is allocated. -**/ - tag_mem = &ctrl->ptag_state[tag].tag_mem_state; - if (tag_mem->size) - pci_free_consistent(ctrl->pdev, tag_mem->size, - tag_mem->va, tag_mem->dma); - free_mcc_tag(ctrl, tag); - return 0; - } - - compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & - CQE_STATUS_COMPL_MASK; - extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & - CQE_STATUS_EXTD_MASK; - /* The ctrl.mcc_tag_status[tag] is filled with -* [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status, -* [7:0] = compl_status -*/ - ctrl->mcc_tag_status[tag] = CQE_VALID_MASK; - ctrl->mcc_tag_status[tag] |= (wrb_idx << CQE_STATUS_WRB_SHIFT); - ctrl->mcc_tag_status[tag] |= (extd_status << CQE_STATUS_ADDL_SHIFT) & -CQE_STATUS_ADDL_MASK; - ctrl->mcc_tag_status[tag] |= (compl_status & CQE_STATUS_MASK); - - /* write ordering implied in wake_up_interruptible */ - clear_bit(MCC_TAG_STATE_RUNNING, &ctrl->ptag_state[tag].tag_state); - wake_up_interruptible(&ctrl->mcc_wait[tag]); - return 0; -} - -static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) -{ - struct be_queue_info *mcc_cq = &phba->ctrl.mcc_obj.cq; - struct be_mcc_compl *compl = queue_tail_node(mcc_cq); - - if (be_mcc_compl_is_new(compl)) { - queue_tail_inc(mcc_cq); - return compl; - } - return NULL; -} - /** * beiscsi_fail_session(): Closing session with appropriate error * @cls_session: ptr to session @@ -528,27 +458,65 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, evt_code, compl->status, compl->flags); } -int beiscsi_process_mcc(struct beiscsi_hba *phba) +int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, + struct be_mcc_compl *compl) { - struct be_mcc_compl *compl; - int num = 0, status = 0; - struct be_ctrl_info *ctrl = &phba->ctrl; + struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); + u16 compl_status, extd_status; + struct be_dma_mem *tag_mem; + unsigned int tag, wrb_idx; - while ((compl = be_mcc_compl_get(phba))) { - if (compl->flags & CQE_FLAGS_ASYNC_MASK) { - beiscsi_process_async_event(phba, compl); - } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { - status = be_mcc_compl_process(ctrl, compl); -
[PATCH v1 02/12] be2iscsi: Use macros for MCC WRB and CQE fields
Rename mcc_numtag to mcc_tag_status. MCC CQE status is processed using macros already defined in be_cmds.h. Add MCC_Q_WRB_ and MCC_Q_CMD_TAG_MASK macros to map to already defined CQE_STATUS_ macros to be consistent when posting MCC. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be.h | 8 +++- drivers/scsi/be2iscsi/be_cmds.c | 40 +--- drivers/scsi/be2iscsi/be_cmds.h | 13 +++-- drivers/scsi/be2iscsi/be_main.c | 11 ++- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 1524fe4..da1d87a 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -135,7 +135,7 @@ struct be_ctrl_info { wait_queue_head_t mcc_wait[MAX_MCC_CMD + 1]; unsigned int mcc_tag[MAX_MCC_CMD]; - unsigned int mcc_numtag[MAX_MCC_CMD + 1]; + unsigned int mcc_tag_status[MAX_MCC_CMD + 1]; unsigned short mcc_alloc_index; unsigned short mcc_free_index; unsigned int mcc_tag_available; @@ -145,6 +145,12 @@ struct be_ctrl_info { #include "be_cmds.h" +/* WRB index mask for MCC_Q_LEN queue entries */ +#define MCC_Q_WRB_IDX_MASK CQE_STATUS_WRB_MASK +#define MCC_Q_WRB_IDX_SHIFTCQE_STATUS_WRB_SHIFT +/* TAG is from 1...MAX_MCC_CMD, MASK includes MAX_MCC_CMD */ +#define MCC_Q_CMD_TAG_MASK ((MAX_MCC_CMD << 1) - 1) + #define PAGE_SHIFT_4K 12 #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) #define mcc_timeout12 /* 12s timeout */ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index e8e9d22..c5e7739 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -125,7 +125,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) if (phba->ctrl.mcc_tag_available) { tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; - phba->ctrl.mcc_numtag[tag] = 0; + phba->ctrl.mcc_tag_status[tag] = 0; phba->ctrl.ptag_state[tag].tag_state = 0; } if (tag) { @@ -157,7 +157,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, struct be_dma_mem *mbx_cmd_mem) { int rc = 0; - uint32_t mcc_tag_response; + uint32_t mcc_tag_status; uint16_t status = 0, addl_status = 0, wrb_num = 0; struct be_mcc_wrb *temp_wrb; struct be_cmd_req_hdr *mbx_hdr; @@ -172,7 +172,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag], + phba->ctrl.mcc_tag_status[tag], msecs_to_jiffies( BEISCSI_HOST_MBX_TIMEOUT)); /** @@ -209,15 +209,15 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } 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) >> + mcc_tag_status = phba->ctrl.mcc_tag_status[tag]; + status = (mcc_tag_status & CQE_STATUS_MASK); + addl_status = ((mcc_tag_status & CQE_STATUS_ADDL_MASK) >> CQE_STATUS_ADDL_SHIFT); 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) >> + wrb_num = (mcc_tag_status & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_SHIFT; temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num); mbx_hdr = embedded_payload(temp_wrb); @@ -257,7 +257,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { spin_lock(&ctrl->mcc_lock); - tag = tag & 0x00FF; + tag = tag & MCC_Q_CMD_TAG_MASK; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) ctrl->mcc_free_index = 0; @@ -334,10 +334,11 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); u16 compl_status, extd_status; struct be_dma_mem *tag_mem; - unsigned short tag; + unsigned int tag, wrb_idx; be_dws_le_to_cpu(compl, 4); - tag = (compl->tag0 & 0x00FF); + tag = (compl->tag0 & MCC_Q_CMD_TAG_MASK); + wrb_idx = (compl->tag0 & CQE_STATUS_WRB_MASK) >> CQE_STATUS_WRB_S
[PATCH v1 04/12] be2iscsi: Rename MCC and BMBX processing functions
beiscsi_mccq_compl -> beiscsi_mccq_compl_wait - indicate blocking call. be_mcc_wait_compl -> be_mcc_compl_poll - indicate polling for completion. be_mbox_db_ready_wait -> be_mbox_db_ready_poll - indicate polling for RDY. be_mcc_compl_process -> beiscsi_process_mbox_compl - indicate BMBX compl. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be_cmds.c | 38 +++--- drivers/scsi/be2iscsi/be_cmds.h | 6 +++--- drivers/scsi/be2iscsi/be_iscsi.c | 8 drivers/scsi/be2iscsi/be_main.c | 8 drivers/scsi/be2iscsi/be_mgmt.c | 12 ++-- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index f59dbdf..1fe8eb8 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -140,7 +140,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) } /* - * beiscsi_mccq_compl()- Wait for completion of MBX + * beiscsi_mccq_compl_wait()- Process completion in MCC CQ * @phba: Driver private structure * @tag: Tag for the MBX Command * @wrb: the WRB used for the MBX Command @@ -152,9 +152,9 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) * Success: 0 * Failure: Non-Zero **/ -int beiscsi_mccq_compl(struct beiscsi_hba *phba, - uint32_t tag, struct be_mcc_wrb **wrb, - struct be_dma_mem *mbx_cmd_mem) +int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, + uint32_t tag, struct be_mcc_wrb **wrb, + struct be_dma_mem *mbx_cmd_mem) { int rc = 0; uint32_t mcc_tag_status; @@ -283,7 +283,7 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) } /* - * be_mcc_compl_process()- Check the MBX comapletion status + * beiscsi_process_mbox_compl()- Check the MBX completion status * @ctrl: Function specific MBX data structure * @compl: Completion status of MBX Command * @@ -293,8 +293,8 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl) * Success: Zero * Failure: Non-Zero **/ -static int be_mcc_compl_process(struct be_ctrl_info *ctrl, - struct be_mcc_compl *compl) +static int beiscsi_process_mbox_compl(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); @@ -520,7 +520,7 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, } /* - * be_mcc_wait_compl()- Wait for MBX completion + * be_mcc_compl_poll()- Wait for MBX completion * @phba: driver private structure * * Wait till no more pending mcc requests are present @@ -556,7 +556,7 @@ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) } /* - * be_mbox_db_ready_wait()- Check ready status + * be_mbox_db_ready_poll()- Check ready status * @ctrl: Function specific MBX data structure * * Check for the ready status of FW to send BMBX @@ -566,7 +566,7 @@ int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) * Success: 0 * Failure: Non-Zero **/ -static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) +static int be_mbox_db_ready_poll(struct be_ctrl_info *ctrl) { /* wait 30s for generic non-flash MBOX operation */ #define BEISCSI_MBX_RDY_BIT_TIMEOUT3 @@ -628,7 +628,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) struct be_mcc_compl *compl = &mbox->compl; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); - status = be_mbox_db_ready_wait(ctrl); + status = be_mbox_db_ready_poll(ctrl); if (status) return status; @@ -637,7 +637,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; iowrite32(val, db); - status = be_mbox_db_ready_wait(ctrl); + status = be_mbox_db_ready_poll(ctrl); if (status) return status; @@ -647,7 +647,7 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) val |= (u32) (mbox_mem->dma >> 4) << 2; iowrite32(val, db); - status = be_mbox_db_ready_wait(ctrl); + status = be_mbox_db_ready_poll(ctrl); if (status) return status; @@ -655,12 +655,12 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) udelay(1); if (be_mcc_compl_is_new(compl)) { - status = be_mcc_compl_process(ctrl, &mbox->compl); + status = beiscsi_process_mbox_compl(ctrl, compl); be_mcc_compl_use(compl); if (status) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : After be_mcc_compl_process\n"); +
[PATCH v1 01/12] be2iscsi: Remove unused mcc_cq_lock
mcc_cq_lock spin_lock is used only in beiscsi_process_mcc which is called only when all interrupts are disabled from mgmt_epfw_cleanup during unloading of driver. There is no other context where there can be contention for the processing of CQ. Signed-off-by: Jitendra Bhivare Reviewed-by: Johannes Thumshirn --- drivers/scsi/be2iscsi/be.h | 1 - drivers/scsi/be2iscsi/be_cmds.c | 2 -- drivers/scsi/be2iscsi/be_main.c | 1 - 3 files changed, 4 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 7d425af..1524fe4 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -132,7 +132,6 @@ struct be_ctrl_info { /* MCC Rings */ struct be_mcc_obj mcc_obj; spinlock_t mcc_lock;/* For serializing mcc cmds to BE card */ - spinlock_t mcc_cq_lock; wait_queue_head_t mcc_wait[MAX_MCC_CMD + 1]; unsigned int mcc_tag[MAX_MCC_CMD]; diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 34c33d4..e8e9d22 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -532,7 +532,6 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) int num = 0, status = 0; struct be_ctrl_info *ctrl = &phba->ctrl; - spin_lock_bh(&phba->ctrl.mcc_cq_lock); while ((compl = be_mcc_compl_get(phba))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { beiscsi_process_async_event(phba, compl); @@ -547,7 +546,6 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) if (num) hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1); - spin_unlock_bh(&phba->ctrl.mcc_cq_lock); return status; } diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 70179e1..314fd2c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -730,7 +730,6 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev) memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); mutex_init(&ctrl->mbox_lock); spin_lock_init(&phba->ctrl.mcc_lock); - spin_lock_init(&phba->ctrl.mcc_cq_lock); return status; } -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] be2iscsi: Fix memory leak in beiscsi_alloc_mem()
In case of error, the memory allocated for phwi_ctrlr was not freed. Signed-off-by: Maurizio Lombardi --- drivers/scsi/be2iscsi/be_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7a6dbfb..360aa88 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -2706,8 +2706,10 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba) phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) * phba->params.cxns_per_ctrl, GFP_KERNEL); - if (!phwi_ctrlr->wrb_context) + if (!phwi_ctrlr->wrb_context) { + kfree(phba->phwi_ctrlr); return -ENOMEM; + } phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr), GFP_KERNEL); -- Maurizio Lombardi -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Reviewed-by: Jitendra Bhivare Thanks, JB -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] be2iscsi: set the boot_kset pointer to NULL in case of failure
>-Original Message- >From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi- >ow...@vger.kernel.org] On Behalf Of Maurizio Lombardi >Sent: Friday, March 04, 2016 3:12 PM >To: jayamohan.kallic...@avagotech.com >Cc: ketan.muka...@avagotech.com; sony.j...@avagotech.com; linux- >s...@vger.kernel.org >Subject: [PATCH] be2iscsi: set the boot_kset pointer to NULL in case of failure > >In beiscsi_setup_boot_info(), the boot_kset pointer should be set to NULL in case >of failure otherwise an invalid pointer dereference may occur later. > >Signed-off-by: Maurizio Lombardi >--- > drivers/scsi/be2iscsi/be_main.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c >index cb9072a..069e5c5 100644 >--- a/drivers/scsi/be2iscsi/be_main.c >+++ b/drivers/scsi/be2iscsi/be_main.c >@@ -4468,6 +4468,7 @@ put_shost: > scsi_host_put(phba->shost); > free_kset: > iscsi_boot_destroy_kset(phba->boot_kset); >+ phba->boot_kset = NULL; > return -ENOMEM; > } > >-- >Maurizio Lombardi > >-- >To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of >a message to majord...@vger.kernel.org More majordomo info at >http://vger.kernel.org/majordomo-info.html Reviewed-by: Jitendra Bhivare Thanks, JB -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH resend 1/2] be2iscsi: Remove unnecessary synchronize_irq() before free_irq()
>-Original Message- >From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi- >ow...@vger.kernel.org] On Behalf Of Lars-Peter Clausen >Sent: Friday, March 04, 2016 3:45 PM >To: James E.J. Bottomley; Martin K. Petersen >Cc: Sathya Prakash; Chaitra P B; Suganath Prabu Subramani; Jitendra Bhivare; >linux-scsi@vger.kernel.org; mpt-fusionlinux@broadcom.com; Lars-Peter >Clausen >Subject: [PATCH resend 1/2] be2iscsi: Remove unnecessary synchronize_irq() >before free_irq() > >Calling synchronize_irq() right before free_irq() is quite useless. On one hand the >IRQ can easily fire again before free_irq() is entered, on the other hand free_irq() >itself calls synchronize_irq() internally (in a race condition free way), before any >state associated with the IRQ is freed. > >Patch was generated using the following semantic patch: >// >@@ >expression irq; >@@ >-synchronize_irq(irq); > free_irq(irq, ...); >// > >Signed-off-by: Lars-Peter Clausen >--- > drivers/scsi/be2iscsi/be_main.c | 5 + > 1 file changed, 1 insertion(+), 4 deletions(-) > >diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c >index b51e726..e89a0f8d 100644 >--- a/drivers/scsi/be2iscsi/be_main.c >+++ b/drivers/scsi/be2iscsi/be_main.c >@@ -5303,15 +5303,12 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba, > if (phba->msix_enabled) { > for (i = 0; i <= phba->num_cpus; i++) { > msix_vec = phba->msix_entries[i].vector; >- synchronize_irq(msix_vec); > free_irq(msix_vec, &phwi_context->be_eq[i]); > kfree(phba->msi_name[i]); > } > } else >- if (phba->pcidev->irq) { >- synchronize_irq(phba->pcidev->irq); >+ if (phba->pcidev->irq) > free_irq(phba->pcidev->irq, phba); >- } > pci_disable_msix(phba->pcidev); > cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); > >-- >2.1.4 Reviewed-by: Jitendra Bhivare Thanks, JB -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 8/9] be2iscsi: Fix WRB leak in login/logout path
From: Jitendra Login/Logout loop was hanging after few hours. /var/log/message showed that alloc_wrb_handle() function was not able to allocate any new WRB. Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not send nopout Sep 11 11:25:22 Jhelum10 kernel: scsi host10: BM_4989 : Alloc of WRB_HANDLE Failedfor the CID : 384 Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not allocate pdu for mgmt task. Driver allocates WRB to pass login negotiated parameters information to FW in beiscsi_offload_connection(). This allocated WRB was not freed so there was WRB_Leak happening. Put WRB used for posting the login-negotiated parameters back in pool. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_main.c | 72 ++ 1 files changed, 49 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 799fe7a..9c65163 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1184,6 +1184,22 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->io_sgl_free_index++; } +static inline struct wrb_handle * +beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, + unsigned int wrbs_per_cxn) +{ + struct wrb_handle *pwrb_handle; + + pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; + pwrb_context->wrb_handles_available--; + if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) + pwrb_context->alloc_index = 0; + else + pwrb_context->alloc_index++; + + return pwrb_handle; +} + /** * alloc_wrb_handle - To allocate a wrb handle * @phba: The hba pointer @@ -1193,30 +1209,30 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) * This happens under session_lock until submission to chip */ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, -struct hwi_wrb_context **pcontext) + struct hwi_wrb_context **pcontext) { struct hwi_wrb_context *pwrb_context; struct hwi_controller *phwi_ctrlr; - struct wrb_handle *pwrb_handle; uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); phwi_ctrlr = phba->phwi_ctrlr; pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; - if (pwrb_context->wrb_handles_available >= 2) { - pwrb_handle = pwrb_context->pwrb_handle_base[ - pwrb_context->alloc_index]; - pwrb_context->wrb_handles_available--; - if (pwrb_context->alloc_index == - (phba->params.wrbs_per_cxn - 1)) - pwrb_context->alloc_index = 0; - else - pwrb_context->alloc_index++; + /* return the context address */ + *pcontext = pwrb_context; + return beiscsi_get_wrb_handle(pwrb_context, phba->params.wrbs_per_cxn); +} - /* Return the context address */ - *pcontext = pwrb_context; - } else - pwrb_handle = NULL; - return pwrb_handle; +static inline void +beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, + struct wrb_handle *pwrb_handle, + unsigned int wrbs_per_cxn) +{ + pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; + pwrb_context->wrb_handles_available++; + if (pwrb_context->free_index == (wrbs_per_cxn - 1)) + pwrb_context->free_index = 0; + else + pwrb_context->free_index++; } /** @@ -1231,13 +1247,9 @@ static void free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, struct wrb_handle *pwrb_handle) { - pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; - pwrb_context->wrb_handles_available++; - if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1)) - pwrb_context->free_index = 0; - else - pwrb_context->free_index++; - + beiscsi_put_wrb_handle(pwrb_context, + pwrb_handle, + phba->params.wrbs_per_cxn); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, "BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x" @@ -4715,6 +4727,20 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; iowrite32(doorbell, phba->db_va + beiscsi_conn->doorbell_offset); + + /* +* There is no completion for CONTEXT_UPDATE. The completion of next +* WRB posted guarantees FW's processing and DMA'ing of it. +* Use beiscsi_put_wrb_handle to put it back
[PATCH 6/9] be2iscsi: Fix IOPOLL implementation
From: Jitendra OS not responding when running 2 port traffic on 72 CPUs system. be2iscsi IRQs gets affined to CPU0 when irqbalancer is disabled. be_iopoll processing completions in BLOCK_IOPOLL_SOFTIRQ hogged CPU0. 1. Use budget to exit the polling loop in beiscsi_process_cq. 2. Rearming of EQ is done only after iopoll completes. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c |2 +- drivers/scsi/be2iscsi/be_iscsi.c |2 +- drivers/scsi/be2iscsi/be_main.c | 91 +- drivers/scsi/be2iscsi/be_main.h |5 +- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 58a9fda..37d1008 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -546,7 +546,7 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) } if (num) - hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1, 0); + hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1); spin_unlock_bh(&phba->ctrl.mcc_cq_lock); return status; diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index c89a025..3545721 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1298,7 +1298,7 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba) for (i = 0; i < phba->num_cpus; i++) { pbe_eq = &phwi_context->be_eq[i]; blk_iopoll_disable(&pbe_eq->iopoll); - beiscsi_process_cq(pbe_eq); + beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC); blk_iopoll_enable(&pbe_eq->iopoll); } } diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index d036706..799fe7a 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -895,32 +895,21 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) static irqreturn_t be_isr_msix(int irq, void *dev_id) { struct beiscsi_hba *phba; - struct be_eq_entry *eqe = NULL; struct be_queue_info *eq; - struct be_queue_info *cq; - unsigned int num_eq_processed; struct be_eq_obj *pbe_eq; pbe_eq = dev_id; eq = &pbe_eq->q; - cq = pbe_eq->cq; - eqe = queue_tail_node(eq); phba = pbe_eq->phba; - num_eq_processed = 0; - while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] - & EQE_VALID_MASK) { - if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) - blk_iopoll_sched(&pbe_eq->iopoll); - - AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); - queue_tail_inc(eq); - eqe = queue_tail_node(eq); - num_eq_processed++; - } - - if (num_eq_processed) - hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); + /* disable interrupt till iopoll completes */ + hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1); + if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) + blk_iopoll_sched(&pbe_eq->iopoll); + else + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO, + "BM_%d: received event while polling eq %d cq %d\n", + eq->id, pbe_eq->cq->id); return IRQ_HANDLED; } @@ -998,6 +987,7 @@ static irqreturn_t be_isr(int irq, void *dev_id) return IRQ_NONE; } + static int beiscsi_init_irqs(struct beiscsi_hba *phba) { struct pci_dev *pcidev = phba->pcidev; @@ -1072,7 +1062,7 @@ free_msix_irqs: void hwi_ring_cq_db(struct beiscsi_hba *phba, unsigned int id, unsigned int num_processed, - unsigned char rearm, unsigned char event) + unsigned char rearm) { u32 val = 0; @@ -2044,7 +2034,7 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) if (num_processed >= 32) { hwi_ring_cq_db(phba, mcc_cq->id, - num_processed, 0, 0); + num_processed, 0); num_processed = 0; } if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) { @@ -2062,24 +2052,25 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) } if (num_processed > 0) - hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0); + hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1); } /** * beiscsi_process_cq()- Process the Completion Queue * @pbe_eq: Event Q on which the Completion has come + * @budget: Max number of events to processed * * return * Number of Completion Entries processed. **/ -unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) +unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int b
[PATCH 9/9] be2iscsi: Update the driver version
From: Jitendra Driver version: 11.0.0.0 Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_main.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 41c708c..16a6fd0 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -36,7 +36,7 @@ #include #define DRV_NAME "be2iscsi" -#define BUILD_STR "10.6.0.1" +#define BUILD_STR "11.0.0.0" #define BE_NAME"Emulex OneConnect" \ "Open-iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/9] be2iscsi: Fix mbox synchronization replacing spinlock with mutex
From: Jitendra This is second part of actual fix for soft lockup. All mbox cmds issued using BMBX and MCC are synchronized using mbox_lock. alloc_mcc_tag/free_mcc_tag is done under mcc_lock and tag_state is accessed using atomic operations. Mailbox command time out is now set to 30s as per FW requirement. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be.h |4 +- drivers/scsi/be2iscsi/be_cmds.c | 94 --- drivers/scsi/be2iscsi/be_iscsi.c |7 +- drivers/scsi/be2iscsi/be_main.c |2 +- drivers/scsi/be2iscsi/be_mgmt.c | 115 -- 5 files changed, 116 insertions(+), 106 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 77f992e..419b53f 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -113,7 +113,7 @@ 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; + atomic_t tag_state; struct be_dma_mem tag_mem_state; }; @@ -124,7 +124,7 @@ struct be_ctrl_info { struct pci_dev *pdev; /* Mbox used for cmd request/response */ - spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ + struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ struct be_dma_mem mbox_mem; /* Mbox mem is adjusted to align to 16 bytes. The allocated addr * is stored for freeing purpose */ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index cd50e3c..1e70053 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -118,6 +118,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) { unsigned int tag = 0; + spin_lock(&phba->ctrl.mcc_lock); if (phba->ctrl.mcc_tag_available) { tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; @@ -130,6 +131,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) else phba->ctrl.mcc_alloc_index++; } + spin_unlock(&phba->ctrl.mcc_lock); return tag; } @@ -164,9 +166,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } /* 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); + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, + MCC_TAG_STATE_RUNNING); /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( @@ -178,9 +179,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, 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); + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, + MCC_TAG_STATE_TIMEOUT); /* Store resource addr to be freed later */ tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; @@ -199,9 +199,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } 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); + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, + MCC_TAG_STATE_COMPLETED); } mcc_tag_response = phba->ctrl.mcc_numtag[tag]; @@ -257,7 +256,7 @@ release_mcc_tag: void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { - spin_lock(&ctrl->mbox_lock); + spin_lock(&ctrl->mcc_lock); tag = tag & 0x00FF; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) @@ -265,7 +264,7 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) else ctrl->mcc_free_index++; ctrl->mcc_tag_available++; - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&ctrl->mcc_lock); } bool is_link_state_evt(u32 trailer) @@ -373,9 +372,11 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, ctrl->mcc_numtag[tag] |= (extd_status & 0x00FF) << 8; ctrl->mcc_numtag[tag] |= (compl_status & 0x00FF); - if (ctrl->ptag_state[tag].tag_state == MCC_TAG_STATE_RUNNING) { + if (atomic_read(&ctrl->ptag_state[tag].tag_state) == + MCC_TAG_STATE_RUNNING) { wake_up_interruptible(&ctrl->mcc_wait[tag]); - } else if (ctrl->ptag_state[
[PATCH 0/9] be2iscsi driver update to 11.0.0.0
From: Jitendra This patch is generated against for-next branch. Jitendra (9): be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx be2iscsi: Fix mbox synchronization replacing spinlock with mutex be2iscsi: Fix to remove shutdown entry point be2iscsi: Fix VLAN support for IPv6 network be2iscsi: Fix to handle misconfigured optics events be2iscsi: Fix IOPOLL implementation be2iscsi: Fix to process 25G link speed info from FW be2iscsi: Fix WRB leak in login/logout path be2iscsi: Update the driver version drivers/scsi/be2iscsi/be.h |4 +- drivers/scsi/be2iscsi/be_cmds.c | 368 ++--- drivers/scsi/be2iscsi/be_cmds.h | 114 ++- drivers/scsi/be2iscsi/be_iscsi.c| 62 ++ drivers/scsi/be2iscsi/be_main.c | 211 ++- drivers/scsi/be2iscsi/be_main.h | 23 ++- drivers/scsi/be2iscsi/be_mgmt.c | 387 +-- drivers/scsi/be2iscsi/be_mgmt.h |2 + drivers/scsi/scsi_transport_iscsi.c |2 + include/scsi/iscsi_if.h |2 + 10 files changed, 653 insertions(+), 522 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/9] be2iscsi: Fix VLAN support for IPv6 network
From: Jitendra Added VLAN operations in set IPv6 address for interface. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_iscsi.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 188d83f..c89a025 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -466,6 +466,10 @@ beiscsi_set_ipv6(struct Scsi_Host *shost, ret = mgmt_set_ip(phba, iface_param, NULL, ISCSI_BOOTPROTO_STATIC); break; + case ISCSI_NET_PARAM_VLAN_ENABLED: + case ISCSI_NET_PARAM_VLAN_TAG: + ret = beiscsi_set_vlan_tag(shost, iface_param); + break; default: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : Param %d not supported\n", -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/9] be2iscsi: Fix to handle misconfigured optics events
From: Jitendra Log messages for misconfigured transceivers reported by FW. Register async events that driver handles using MCC_CREATE_EXT ioctl. Errors messages for faulted/uncertified/unqualified optics are logged. Added FW config validation. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 169 ++--- drivers/scsi/be2iscsi/be_cmds.h | 47 +++- drivers/scsi/be2iscsi/be_main.c | 22 +--- drivers/scsi/be2iscsi/be_main.h | 12 ++- drivers/scsi/be2iscsi/be_mgmt.c | 230 +++ drivers/scsi/be2iscsi/be_mgmt.h |2 + 6 files changed, 327 insertions(+), 155 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index e4cc98f..58a9fda 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -267,26 +267,6 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) spin_unlock(&ctrl->mcc_lock); } -bool is_link_state_evt(u32 trailer) -{ - return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_LINK_STATE); -} - -static bool is_iscsi_evt(u32 trailer) -{ - return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_ISCSI; -} - -static int iscsi_evt_type(u32 trailer) -{ - return (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & -ASYNC_TRAILER_EVENT_TYPE_MASK; -} - static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) { if (compl->flags != 0) { @@ -343,7 +323,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, if (resp_hdr->response_length) return 0; } - return -EBUSY; + return -EINVAL; } return 0; } @@ -422,7 +402,7 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -void beiscsi_async_link_state_process(struct beiscsi_hba *phba, +static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, struct be_async_event_link_state *evt) { if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || @@ -450,6 +430,103 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, } } +static char *beiscsi_port_misconf_event_msg[] = { + "Physical Link is functional.", + "Optics faulted/incorrectly installed/not installed - Reseat optics, if issue not resolved, replace.", + "Optics of two types installed - Remove one optic or install matching pair of optics.", + "Incompatible optics - Replace with compatible optics for card to function.", + "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", + "Uncertified optics - Replace with Avago Certified optics to enable link operation." +}; +#define BEISCSI_PORT_MISCONF_EVENT_MAX \ + (sizeof(beiscsi_port_misconf_event_msg) / \ +sizeof(beiscsi_port_misconf_event_msg[0])) + +static void beiscsi_process_async_sli(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) +{ + struct be_async_event_sli *async_sli; + u8 evt_type, state, old_state, le; + char *sev = KERN_WARNING; + char *msg = NULL; + + evt_type = compl->flags >> ASYNC_TRAILER_EVENT_TYPE_SHIFT; + evt_type &= ASYNC_TRAILER_EVENT_TYPE_MASK; + + /* processing only MISCONFIGURED physical port event */ + if (evt_type != ASYNC_SLI_EVENT_TYPE_MISCONFIGURED) + return; + + async_sli = (struct be_async_event_sli *)compl; + state = async_sli->event_data1 >> +(phba->fw_config.phys_port * 8) & 0xff; + le = async_sli->event_data2 >> +(phba->fw_config.phys_port * 8) & 0xff; + + old_state = phba->optic_state; + phba->optic_state = state; + + if (state >= BEISCSI_PORT_MISCONF_EVENT_MAX) { + /* fw is reporting a state we don't know, log and return */ + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Port %c: Unrecognized optic state 0x%x\n", + phba->port_name, async_sli->event_data1); + return; + } + + if (ASYNC_SLI_LINK_EFFECT_VALID(le)) { + /* log link effect for unqualified-4, uncertified-5 optics */ + if (state > 3) + msg = (ASYNC_SLI_LINK_EFFECT_STATE(le)) ? + " Link is non-operational." : + " Link is operational."; + /* 1 - info */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 1) + sev = KERN_INFO; + /* 2 - error */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 2) +
[PATCH 3/9] be2iscsi: Fix to remove shutdown entry point
From: Jitendra Null pointer dereference in shutdown path after taking dump. Shutdown path is not needed as FW comes up clean every time during probe after issuing FUNCTION reset MBOX command. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 17 +++-- drivers/scsi/be2iscsi/be_cmds.h |2 +- drivers/scsi/be2iscsi/be_main.c | 24 drivers/scsi/be2iscsi/be_main.h |3 +-- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 1e70053..e4cc98f 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -414,22 +414,11 @@ static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) } /** - * be2iscsi_fail_session(): Closing session with appropriate error + * beiscsi_fail_session(): Closing session with appropriate error * @cls_session: ptr to session - * - * Depending on adapter state appropriate error flag is passed. **/ -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session) +void beiscsi_fail_session(struct iscsi_cls_session *cls_session) { - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct beiscsi_hba *phba = iscsi_host_priv(shost); - uint32_t iscsi_err_flag; - - if (phba->state & BE_ADAPTER_STATE_SHUTDOWN) - iscsi_err_flag = ISCSI_ERR_INVALID_HOST; - else - iscsi_err_flag = ISCSI_ERR_CONN_FAILED; - iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } @@ -447,7 +436,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, evt->physical_port); iscsi_host_for_each_session(phba->shost, - be2iscsi_fail_session); + beiscsi_fail_session); } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 4bfca35..5d165ee 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -1367,5 +1367,5 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, u8 subsystem, u8 opcode, int cmd_len); -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session); +void beiscsi_fail_session(struct iscsi_cls_session *cls_session); #endif /* !BEISCSI_CMDS_H */ diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 61ce86b..2f3e118 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5315,7 +5315,6 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba, static void beiscsi_remove(struct pci_dev *pcidev) { - struct beiscsi_hba *phba = NULL; phba = pci_get_drvdata(pcidev); @@ -5325,9 +5324,9 @@ static void beiscsi_remove(struct pci_dev *pcidev) } beiscsi_destroy_def_ifaces(phba); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); iscsi_boot_destroy_kset(phba->boot_kset); iscsi_host_remove(phba->shost); + beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); pci_disable_pcie_error_reporting(pcidev); @@ -5336,23 +5335,6 @@ static void beiscsi_remove(struct pci_dev *pcidev) pci_disable_device(pcidev); } -static void beiscsi_shutdown(struct pci_dev *pcidev) -{ - - struct beiscsi_hba *phba = NULL; - - phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); - if (!phba) { - dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n"); - return; - } - - phba->state = BE_ADAPTER_STATE_SHUTDOWN; - iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); - pci_disable_device(pcidev); -} - static void beiscsi_msix_enable(struct beiscsi_hba *phba) { int i, status; @@ -5673,6 +5655,9 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto hba_free; } + /* +* 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, @@ -5861,7 +5846,6 @@ static struct pci_driver beiscsi_pci_driver = { .name = DRV_NAME, .probe = beiscsi_dev_probe, .remove = beiscsi_remove, - .shutdown = beiscsi_shutdown, .id_table = beiscsi_pci_id_table, .err_handler = &beiscsi_eeh_handlers }; diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 5c67c07..bd9d1e1 100644 -
[PATCH 1/9] be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx
From: Jitendra We are taking mbox_lock spinlock which disables pre-emption before we poll for mbox completion. Waiting there with spinlock held in excess of 20s will cause soft lockup. Actual fix is to change mbox_lock to mutex. The changes are done in phases. This is the first part. 1. Changed mgmt_get_all_if_id to use MCC instead of BMBX. 2. Changed be_mbox_db_ready_wait to busy wait for 12s max and removed wait_event_timeout. Added error handling code for IO reads. OPCODE_COMMON_QUERY_FIRMWARE_CONFIG mbox command takes 8s time when unreachable boot targets are configured. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 60 +++ drivers/scsi/be2iscsi/be_mgmt.c | 32 ++-- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 2778089..cd50e3c 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -587,47 +587,42 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define BEISCSI_MBX_RDY_BIT_TIMEOUT4000/* 4sec */ +#define BEISCSI_MBX_RDY_BIT_TIMEOUT12000 /* 12sec */ void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; - bool read_flag = false; - int ret = 0, i; u32 ready; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q); - if (beiscsi_error(phba)) - return -EIO; + /* +* This BMBX busy wait path is used during init only. +* For the commands executed during init, 5s should suffice. +*/ + timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); + do { + if (beiscsi_error(phba)) + return -EIO; - timeout = jiffies + (HZ * 110); + ready = ioread32(db); + if (ready == 0x) + return -EIO; - do { - for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) { - ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; - if (ready) { - read_flag = true; - break; - } - mdelay(1); - } + ready &= MPU_MAILBOX_DB_RDY_MASK; + if (ready) + return 0; - if (!read_flag) { - wait_event_timeout(rdybit_check_q, - (read_flag != true), - HZ * 5); - } - } while ((time_before(jiffies, timeout)) && !read_flag); + if (time_after(jiffies, timeout)) + break; + mdelay(1); + } while (!ready); - if (!read_flag) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : FW Timed Out\n"); - phba->fw_timeout = true; - beiscsi_ue_detect(phba); - ret = -EBUSY; - } + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : FW Timed Out\n"); - return ret; + phba->fw_timeout = true; + beiscsi_ue_detect(phba); + + return -EBUSY; } /* @@ -674,6 +669,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) if (status) return status; + /* RDY is set; small delay before CQE read. */ + udelay(1); + if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index aea3e6b..7b54b23 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -809,27 +809,39 @@ int mgmt_open_connection(struct beiscsi_hba *phba, unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) { struct be_ctrl_info *ctrl = &phba->ctrl; - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb); - struct be_cmd_get_all_if_id_req *pbe_allid = req; + struct be_mcc_wrb *wrb; + struct be_cmd_get_all_if_id_req *req; + struct be_cmd_get_all_if_id_req *pbe_allid; + unsigned int tag; int status = 0; - memset(wrb, 0, sizeof(*wrb)); - spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); + return -ENOMEM; + } + + wrb = wrb_from_mccq(phba); + req = embedded_payload(wrb); + wrb->tag0 |=
[PATCH 7/9] be2iscsi: Fix to process 25G link speed info from FW
From: Jitendra Async link event provides port_speed info. Use the same to report in ISCSI_HOST_PARAM_PORT_SPEED query. Removed link status query IOCTL used to do the same. 25G and 40G are defined in kernel enum iscsi_port_speed. Fixed get_nic_conf structure definition. Removed rsvd[23] field in be_cmd_get_nic_conf_resp. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 52 +--- drivers/scsi/be2iscsi/be_cmds.h | 65 ++ drivers/scsi/be2iscsi/be_iscsi.c| 49 +++--- drivers/scsi/be2iscsi/be_main.h |1 + drivers/scsi/be2iscsi/be_mgmt.c | 28 --- drivers/scsi/scsi_transport_iscsi.c |2 + include/scsi/iscsi_if.h |2 + 7 files changed, 62 insertions(+), 137 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 37d1008..498eba2 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -402,31 +402,31 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, - struct be_async_event_link_state *evt) +static void beiscsi_process_async_link(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) { - if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) { - phba->state = BE_ADAPTER_LINK_DOWN; + struct be_async_event_link_state *evt; - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link Down on Port %d\n", - evt->physical_port); + evt = (struct be_async_event_link_state *)compl; - iscsi_host_for_each_session(phba->shost, - beiscsi_fail_session); - } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { + phba->port_speed = evt->port_speed; + /** +* Check logical link status in ASYNC event. +* This has been newly introduced in SKH-R Firmware 10.0.338.45. +**/ + if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { phba->state = BE_ADAPTER_LINK_UP | BE_ADAPTER_CHECK_BOOT; phba->get_boot = BE_GET_BOOT_RETRIES; - - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link UP on Port %d\n", - evt->physical_port); + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Up on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + } else { + phba->state = BE_ADAPTER_LINK_DOWN; + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Down on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + iscsi_host_for_each_session(phba->shost, + beiscsi_fail_session); } } @@ -438,9 +438,6 @@ static char *beiscsi_port_misconf_event_msg[] = { "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", "Uncertified optics - Replace with Avago Certified optics to enable link operation." }; -#define BEISCSI_PORT_MISCONF_EVENT_MAX \ - (sizeof(beiscsi_port_misconf_event_msg) / \ -sizeof(beiscsi_port_misconf_event_msg[0])) static void beiscsi_process_async_sli(struct beiscsi_hba *phba, struct be_mcc_compl *compl) @@ -466,7 +463,7 @@ static void beiscsi_process_async_sli(struct beiscsi_hba *phba, old_state = phba->optic_state; phba->optic_state = state; - if (state >= BEISCSI_PORT_MISCONF_EVENT_MAX) { + if (state >= ARRAY_SIZE(beiscsi_port_misconf_event_msg)) { /* fw is reporting a state we don't know, log and return */ __beiscsi_log(phba, KERN_ERR, "BC_%d : Port %c: Unrecognized optic state 0x%x\n", @@ -506,8 +503,7 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, evt_code &= ASYNC_TRAILER_EVENT_CODE_MASK; switch (evt_code) { case ASYNC_EVENT_CODE_LINK_STATE: - beiscsi_async_link_state_process(phba, - (struct be_async_event_link_state *)compl); + beiscsi_process_async_link(phba, compl); break; case ASYNC_
RE: [PATCH 1/9] be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx
be_mbox_db_ready_wait was changed to remove wait_event_timeout done under spinlock held for port initialization FW commands. The timeout change and unrecoverable error check inside the wait loop were needed to be addressed too. Though spinlock was replaced with mutex in patch 2/9. -Original Message- From: Hannes Reinecke [mailto:h...@suse.de] Sent: Monday, December 14, 2015 8:34 PM To: Jitendra Bhivare; linux-scsi@vger.kernel.org; micha...@cs.wisc.edu Subject: Re: [PATCH 1/9] be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx On 12/14/2015 07:10 AM, Jitendra Bhivare wrote: > From: Jitendra > > We are taking mbox_lock spinlock which disables pre-emption before we > poll for mbox completion. Waiting there with spinlock held in excess > of 20s will cause soft lockup. > > Actual fix is to change mbox_lock to mutex. Really? I didn't find that in the patch ... > The changes are done in phases. This is the first part. > 1. Changed mgmt_get_all_if_id to use MCC instead of BMBX. > 2. Changed be_mbox_db_ready_wait to busy wait for 12s max and removed > wait_event_timeout. Added error handling code for IO reads. > OPCODE_COMMON_QUERY_FIRMWARE_CONFIG mbox command takes 8s time when > unreachable boot targets are configured. > Why did you modify be_mbox_db_ready_wait(), seeing that you're not using the mailbox interface anymore after this change? Cheers, Hannes -- Dr. Hannes ReineckezSeries & Storage h...@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nürnberg) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 6/9] be2iscsi: Fix IOPOLL implementation
The problem statement indicates affinity issue but IOPOLL implementation had issues too. 1. IOPOLL budget passed in the callback is not being honored. This was the root cause where the driver kept polling in softirq. 2. The interrupts kept coming even when IOPOLL is scheduled. So we needed to fix EQ rearming. I think, choosing CPU affinity internally by driver is not right thing to do. For setting IRQ affinity you need to have holistic view of the system and better done by external entity which has heuristics of all the varied workloads on the system. -Original Message- From: Hannes Reinecke [mailto:h...@suse.de] Sent: Monday, December 14, 2015 8:54 PM To: Jitendra Bhivare; linux-scsi@vger.kernel.org; micha...@cs.wisc.edu Subject: Re: [PATCH 6/9] be2iscsi: Fix IOPOLL implementation On 12/14/2015 07:11 AM, Jitendra Bhivare wrote: > From: Jitendra > > OS not responding when running 2 port traffic on 72 CPUs system. > > be2iscsi IRQs gets affined to CPU0 when irqbalancer is disabled. > be_iopoll processing completions in BLOCK_IOPOLL_SOFTIRQ hogged CPU0. > > 1. Use budget to exit the polling loop in beiscsi_process_cq. > 2. Rearming of EQ is done only after iopoll completes. > > Signed-off-by: Jitendra > --- > drivers/scsi/be2iscsi/be_cmds.c |2 +- > drivers/scsi/be2iscsi/be_iscsi.c |2 +- > drivers/scsi/be2iscsi/be_main.c | 91 +- > drivers/scsi/be2iscsi/be_main.h |5 +- > 4 files changed, 56 insertions(+), 44 deletions(-) > Hmm. Not sure if I agree with this. Doesn't the be2iscsi driver set the cpu affinity internally? If not, wouldn't that be the better solution? Cheers, Hannes -- Dr. Hannes ReineckezSeries & Storage h...@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nürnberg) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 5/9] be2iscsi: Fix to handle misconfigured optics events
> So please add defines for the individual messages and use a key-value map to lookup the messages. FW events are in sequence 0...5 so key is implied and value is being stored in array of strings. BEISCSI_PORT_MISCONF_EVENT_MAX (replaced with ARRAY_SIZE) is just to verify the event number. Not so sure what you are suggesting. port_name IOCTL is needed to display the error message. Will split FW config validation. Thanks, JB -Original Message- From: Hannes Reinecke [mailto:h...@suse.de] Sent: Monday, December 14, 2015 8:49 PM To: Jitendra Bhivare; linux-scsi@vger.kernel.org; micha...@cs.wisc.edu Subject: Re: [PATCH 5/9] be2iscsi: Fix to handle misconfigured optics events On 12/14/2015 07:11 AM, Jitendra Bhivare wrote: > From: Jitendra > > Log messages for misconfigured transceivers reported by FW. > > Register async events that driver handles using MCC_CREATE_EXT ioctl. > Errors messages for faulted/uncertified/unqualified optics are logged. > Added FW config validation. > > Signed-off-by: Jitendra > --- > drivers/scsi/be2iscsi/be_cmds.c | 169 ++--- > drivers/scsi/be2iscsi/be_cmds.h | 47 +++- > drivers/scsi/be2iscsi/be_main.c | 22 +--- > drivers/scsi/be2iscsi/be_main.h | 12 ++- > drivers/scsi/be2iscsi/be_mgmt.c | 230 +++ > drivers/scsi/be2iscsi/be_mgmt.h |2 + > 6 files changed, 327 insertions(+), 155 deletions(-) > > diff --git a/drivers/scsi/be2iscsi/be_cmds.c > b/drivers/scsi/be2iscsi/be_cmds.c index e4cc98f..58a9fda 100644 > --- a/drivers/scsi/be2iscsi/be_cmds.c > +++ b/drivers/scsi/be2iscsi/be_cmds.c > @@ -267,26 +267,6 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) > spin_unlock(&ctrl->mcc_lock); > } > > -bool is_link_state_evt(u32 trailer) > -{ > - return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & > - ASYNC_TRAILER_EVENT_CODE_MASK) == > - ASYNC_EVENT_CODE_LINK_STATE); > -} > - > -static bool is_iscsi_evt(u32 trailer) -{ > - return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & > - ASYNC_TRAILER_EVENT_CODE_MASK) == > - ASYNC_EVENT_CODE_ISCSI; > -} > - > -static int iscsi_evt_type(u32 trailer) -{ > - return (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & > - ASYNC_TRAILER_EVENT_TYPE_MASK; > -} > - > static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) > { > if (compl->flags != 0) { > @@ -343,7 +323,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, > if (resp_hdr->response_length) > return 0; > } > - return -EBUSY; > + return -EINVAL; > } > return 0; > } How is this related to the above description? Shouldn't it be moved to a different patch? > @@ -422,7 +402,7 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) > iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); > } > > -void beiscsi_async_link_state_process(struct beiscsi_hba *phba, > +static void beiscsi_async_link_state_process(struct beiscsi_hba > +*phba, > struct be_async_event_link_state *evt) > { > if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || @@ -450,6 > +430,103 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, > } > } > > +static char *beiscsi_port_misconf_event_msg[] = { > + "Physical Link is functional.", > + "Optics faulted/incorrectly installed/not installed - Reseat optics, if issue not resolved, replace.", > + "Optics of two types installed - Remove one optic or install matching pair of optics.", > + "Incompatible optics - Replace with compatible optics for card to function.", > + "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", > + "Uncertified optics - Replace with Avago Certified optics to enable link operation." > +}; > +#define BEISCSI_PORT_MISCONF_EVENT_MAX \ > + (sizeof(beiscsi_port_misconf_event_msg) / \ > + sizeof(beiscsi_port_misconf_event_msg[0])) > + Please don't. The above list is tied with event numbers from firmware, and by no means arbitrary. So please add defines for the individual messages and use a key-value map to lookup the messages. > +static void beiscsi_process_async_sli(struct beiscsi_hba *phba, > + struct be_mcc_compl *compl) { > + struct be_async_event_sli *async_sli; > + u8 evt_type, state, old_state, le; > + char *sev = KERN_WARNING; > + char
[PATCH 11/15] be2iscsi: Fix return value for MCC completion
From: Jitendra Change return value of completed MCC EBUSY to EINVAL. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 9bb5905..eced82b 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -323,7 +323,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, if (resp_hdr->response_length) return 0; } - return -EBUSY; + return -EINVAL; } return 0; } -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/15] be2iscsi: Add FW config validation
From: Jitendra System crash in I+T card personality Fix to add validation for ULP in initiator mode, physical port number, and supported queue, icd, cid counts. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_main.c |2 +- drivers/scsi/be2iscsi/be_main.h |2 + drivers/scsi/be2iscsi/be_mgmt.c | 188 +-- 3 files changed, 123 insertions(+), 69 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 8967e05..a665e6a 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5670,6 +5670,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto free_port; } mgmt_get_port_name(&phba->ctrl, phba); + beiscsi_get_params(phba); if (enable_msix) find_num_cpus(phba); @@ -5687,7 +5688,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, } phba->shost->max_id = phba->params.cxns_per_ctrl; - beiscsi_get_params(phba); phba->shost->can_queue = phba->params.ios_per_ctrl; ret = beiscsi_init_port(phba); if (ret < 0) { diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c09082a..f89861b 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -397,7 +397,9 @@ struct beiscsi_hba { * group together since they are used most frequently * for cid to cri conversion */ +#define BEISCSI_PHYS_PORT_MAX 4 unsigned int phys_port; + /* valid values of phys_port id are 0, 1, 2, 3 */ unsigned int eqid_count; unsigned int cqid_count; unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT]; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index ad7aa75..15f7ad7 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -373,90 +373,142 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) { struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_fw_cfg *req = embedded_payload(wrb); - int status = 0; + struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); + uint32_t cid_count, icd_count; + int status = -EINVAL; + uint8_t ulp_num = 0; mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); + be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); - - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, EMBED_MBX_MAX_PAYLOAD_SIZE); - status = be_mbox_notify(ctrl); - if (!status) { - uint8_t ulp_num = 0; - struct be_fw_cfg *pfw_cfg; - pfw_cfg = req; - if (!is_chip_be2_be3r(phba)) { - phba->fw_config.eqid_count = pfw_cfg->eqid_count; - phba->fw_config.cqid_count = pfw_cfg->cqid_count; + if (be_mbox_notify(ctrl)) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : Failed in mgmt_get_fw_config\n"); + goto fail_init; + } - beiscsi_log(phba, KERN_INFO, - BEISCSI_LOG_INIT, - "BG_%d : EQ_Count : %d CQ_Count : %d\n", - phba->fw_config.eqid_count, + /* FW response formats depend on port id */ + phba->fw_config.phys_port = pfw_cfg->phys_port; + if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : invalid physical port id %d\n", + phba->fw_config.phys_port); + goto fail_init; + } + + /* populate and check FW config against min and max values */ + if (!is_chip_be2_be3r(phba)) { + phba->fw_config.eqid_count = pfw_cfg->eqid_count; + phba->fw_config.cqid_count = pfw_cfg->cqid_count; + if (phba->fw_config.eqid_count == 0 || + phba->fw_config.eqid_count > 2048) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : invalid EQ count %d\n", + phba->fw_config.eqid_count); + goto fail_init; + } + if (phba->fw_config.cqid_count == 0 || + phba->fw_config.cqid_count > 4096) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : invalid CQ count %d\n",
[PATCH 08/15] be2iscsi: Fix VLAN support for IPv6 network
From: Jitendra Configuring VLAN parameters through IPv6 interface was not supported in driver. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_iscsi.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 188d83f..c89a025 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -466,6 +466,10 @@ beiscsi_set_ipv6(struct Scsi_Host *shost, ret = mgmt_set_ip(phba, iface_param, NULL, ISCSI_BOOTPROTO_STATIC); break; + case ISCSI_NET_PARAM_VLAN_ENABLED: + case ISCSI_NET_PARAM_VLAN_TAG: + ret = beiscsi_set_vlan_tag(shost, iface_param); + break; default: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : Param %d not supported\n", -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/15] be2iscsi: Fix to handle misconfigured optics events
From: Jitendra Log messages for misconfigured transceivers reported by FW. Register async events that driver handles using MCC_CREATE_EXT ioctl. Errors messages for faulted/uncertified/unqualified optics are logged. Added IOCTL to get port_name to be displayed in error message. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 164 -- drivers/scsi/be2iscsi/be_cmds.h | 47 ++-- drivers/scsi/be2iscsi/be_main.c | 19 + drivers/scsi/be2iscsi/be_main.h | 10 ++- drivers/scsi/be2iscsi/be_mgmt.c | 42 ++ drivers/scsi/be2iscsi/be_mgmt.h |2 + 6 files changed, 199 insertions(+), 85 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index e4cc98f..9bb5905 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -267,26 +267,6 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) spin_unlock(&ctrl->mcc_lock); } -bool is_link_state_evt(u32 trailer) -{ - return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_LINK_STATE); -} - -static bool is_iscsi_evt(u32 trailer) -{ - return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_ISCSI; -} - -static int iscsi_evt_type(u32 trailer) -{ - return (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & -ASYNC_TRAILER_EVENT_TYPE_MASK; -} - static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) { if (compl->flags != 0) { @@ -422,7 +402,7 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -void beiscsi_async_link_state_process(struct beiscsi_hba *phba, +static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, struct be_async_event_link_state *evt) { if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || @@ -450,6 +430,100 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, } } +static char *beiscsi_port_misconf_event_msg[] = { + "Physical Link is functional.", + "Optics faulted/incorrectly installed/not installed - Reseat optics, if issue not resolved, replace.", + "Optics of two types installed - Remove one optic or install matching pair of optics.", + "Incompatible optics - Replace with compatible optics for card to function.", + "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", + "Uncertified optics - Replace with Avago Certified optics to enable link operation." +}; + +static void beiscsi_process_async_sli(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) +{ + struct be_async_event_sli *async_sli; + u8 evt_type, state, old_state, le; + char *sev = KERN_WARNING; + char *msg = NULL; + + evt_type = compl->flags >> ASYNC_TRAILER_EVENT_TYPE_SHIFT; + evt_type &= ASYNC_TRAILER_EVENT_TYPE_MASK; + + /* processing only MISCONFIGURED physical port event */ + if (evt_type != ASYNC_SLI_EVENT_TYPE_MISCONFIGURED) + return; + + async_sli = (struct be_async_event_sli *)compl; + state = async_sli->event_data1 >> +(phba->fw_config.phys_port * 8) & 0xff; + le = async_sli->event_data2 >> +(phba->fw_config.phys_port * 8) & 0xff; + + old_state = phba->optic_state; + phba->optic_state = state; + + if (state >= ARRAY_SIZE(beiscsi_port_misconf_event_msg)) { + /* fw is reporting a state we don't know, log and return */ + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Port %c: Unrecognized optic state 0x%x\n", + phba->port_name, async_sli->event_data1); + return; + } + + if (ASYNC_SLI_LINK_EFFECT_VALID(le)) { + /* log link effect for unqualified-4, uncertified-5 optics */ + if (state > 3) + msg = (ASYNC_SLI_LINK_EFFECT_STATE(le)) ? + " Link is non-operational." : + " Link is operational."; + /* 1 - info */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 1) + sev = KERN_INFO; + /* 2 - error */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 2) + sev = KERN_ERR; + } + + if (old_state != phba->optic_state) + __beiscsi_log(phba, sev, "BC_%d : Port %c: %s%s\n", + phba->port_name, + beiscsi_port_misconf_event_msg[state], + !msg ? "" : msg); +} + +void beiscsi_process_async_event(struct beiscsi_hba *phba, +
[PATCH 05/15] be2iscsi: Set mbox timeout to 30s
From: Jitendra FW recommended timeout for all mbox command is 30s. Use msleep instead mdelay to relinquish CPU when polling for mbox completion. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 6f58063..1e70053 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -587,7 +587,8 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define BEISCSI_MBX_RDY_BIT_TIMEOUT12000 /* 12sec */ + /* wait 30s for generic non-flash MBOX operation */ +#define BEISCSI_MBX_RDY_BIT_TIMEOUT3 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; @@ -612,7 +613,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) if (time_after(jiffies, timeout)) break; - mdelay(1); + msleep(20); } while (!ready); beiscsi_log(phba, KERN_ERR, -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/15] be2iscsi: Fix to synchronize tag allocation using spin_lock
From: Jitendra alloc_mcc_tag/free_mcc_tag is now done under mcc_lock spin_lock Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 21c806f..6f58063 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -118,6 +118,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) { unsigned int tag = 0; + spin_lock(&phba->ctrl.mcc_lock); if (phba->ctrl.mcc_tag_available) { tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; @@ -130,6 +131,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) else phba->ctrl.mcc_alloc_index++; } + spin_unlock(&phba->ctrl.mcc_lock); return tag; } @@ -254,7 +256,7 @@ release_mcc_tag: void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { - spin_lock(&ctrl->mbox_lock); + spin_lock(&ctrl->mcc_lock); tag = tag & 0x00FF; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) @@ -262,7 +264,7 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) else ctrl->mcc_free_index++; ctrl->mcc_tag_available++; - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&ctrl->mcc_lock); } bool is_link_state_evt(u32 trailer) -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/15] be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx
From: Jitendra We are taking mbox_lock spinlock which disables pre-emption before we poll for mbox completion. Waiting there with spinlock held in excess of 20s will cause soft lockup. Actual fix is to change mbox_lock to mutex. The changes are done in phases. This is the first part. 1. Changed mgmt_get_all_if_id to use MCC where after posting lock is released. 2. Changed be_mbox_db_ready_wait to busy wait for 12s max and removed wait_event_timeout. Added error handling code for IO reads. OPCODE_COMMON_QUERY_FIRMWARE_CONFIG mbox command takes 8s time when unreachable boot targets configured. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 60 +++ drivers/scsi/be2iscsi/be_mgmt.c | 32 ++-- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 2778089..cd50e3c 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -587,47 +587,42 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define BEISCSI_MBX_RDY_BIT_TIMEOUT4000/* 4sec */ +#define BEISCSI_MBX_RDY_BIT_TIMEOUT12000 /* 12sec */ void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; - bool read_flag = false; - int ret = 0, i; u32 ready; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q); - if (beiscsi_error(phba)) - return -EIO; + /* +* This BMBX busy wait path is used during init only. +* For the commands executed during init, 5s should suffice. +*/ + timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); + do { + if (beiscsi_error(phba)) + return -EIO; - timeout = jiffies + (HZ * 110); + ready = ioread32(db); + if (ready == 0x) + return -EIO; - do { - for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) { - ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; - if (ready) { - read_flag = true; - break; - } - mdelay(1); - } + ready &= MPU_MAILBOX_DB_RDY_MASK; + if (ready) + return 0; - if (!read_flag) { - wait_event_timeout(rdybit_check_q, - (read_flag != true), - HZ * 5); - } - } while ((time_before(jiffies, timeout)) && !read_flag); + if (time_after(jiffies, timeout)) + break; + mdelay(1); + } while (!ready); - if (!read_flag) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : FW Timed Out\n"); - phba->fw_timeout = true; - beiscsi_ue_detect(phba); - ret = -EBUSY; - } + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : FW Timed Out\n"); - return ret; + phba->fw_timeout = true; + beiscsi_ue_detect(phba); + + return -EBUSY; } /* @@ -674,6 +669,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) if (status) return status; + /* RDY is set; small delay before CQE read. */ + udelay(1); + if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index aea3e6b..7b54b23 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -809,27 +809,39 @@ int mgmt_open_connection(struct beiscsi_hba *phba, unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) { struct be_ctrl_info *ctrl = &phba->ctrl; - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb); - struct be_cmd_get_all_if_id_req *pbe_allid = req; + struct be_mcc_wrb *wrb; + struct be_cmd_get_all_if_id_req *req; + struct be_cmd_get_all_if_id_req *pbe_allid; + unsigned int tag; int status = 0; - memset(wrb, 0, sizeof(*wrb)); - spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); + return -ENOMEM; + } + + wrb = wrb_from_mccq(phba); + req = embedded_payload(wrb); +
[PATCH 06/15] be2iscsi: Added return value check for mgmt_get_all_if_id
From: Jitendra Use of mutex_lock_interruptible can return -EINTR, handle and log the error. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_iscsi.c |7 --- drivers/scsi/be2iscsi/be_mgmt.c | 10 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index b7087ba..188d83f 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -367,13 +367,14 @@ beiscsi_set_vlan_tag(struct Scsi_Host *shost, struct iscsi_iface_param_info *iface_param) { struct beiscsi_hba *phba = iscsi_host_priv(shost); - int ret = 0; + int ret; /* Get the Interface Handle */ - if (mgmt_get_all_if_id(phba)) { + ret = mgmt_get_all_if_id(phba); + if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : Getting Interface Handle Failed\n"); - return -EIO; + return ret; } switch (iface_param->param) { diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index a41013e..a8a1670 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1018,8 +1018,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba, uint32_t ip_type; int rc; - if (mgmt_get_all_if_id(phba)) - return -EIO; + rc = mgmt_get_all_if_id(phba); + if (rc) + return rc; ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? BE2_IPV6 : BE2_IPV4 ; @@ -1188,8 +1189,9 @@ int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); int rc; - if (mgmt_get_all_if_id(phba)) - return -EIO; + rc = mgmt_get_all_if_id(phba); + if (rc) + return rc; do { rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/15] be2iscsi: Fix mbox synchronization replacing spinlock with mutex
From: Jitendra This is second part of actual fix for soft lockup. All mbox cmds issued using BMBX and MCC are synchronized using mutex mbox_lock instead of spin_lock. Used mutex_lock_interruptible where ever possible. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be.h |2 +- drivers/scsi/be2iscsi/be_cmds.c | 73 ++- drivers/scsi/be2iscsi/be_main.c |2 +- drivers/scsi/be2iscsi/be_mgmt.c | 105 -- 4 files changed, 94 insertions(+), 88 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 77f992e..cf19bce 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -124,7 +124,7 @@ struct be_ctrl_info { struct pci_dev *pdev; /* Mbox used for cmd request/response */ - spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ + struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ struct be_dma_mem mbox_mem; /* Mbox mem is adjusted to align to 16 bytes. The allocated addr * is stored for freeing purpose */ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index cd50e3c..6fabded 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -164,9 +164,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } /* Set MBX Tag state to Active */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( @@ -178,9 +178,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, if (rc <= 0) { struct be_dma_mem *tag_mem; /* Set MBX Tag state to timeout */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* Store resource addr to be freed later */ tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; @@ -199,9 +199,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } else { rc = 0; /* Set MBX Tag state to completed */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); } mcc_tag_response = phba->ctrl.mcc_numtag[tag]; @@ -390,9 +390,9 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, tag_mem->va, tag_mem->dma); /* Change tag state */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); ctrl->ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* Free MCC Tag */ free_mcc_tag(ctrl, tag); @@ -831,7 +831,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem = &eq->dma_mem; int status; - spin_lock(&ctrl->mbox_lock); + mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -858,7 +858,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, eq->id = le16_to_cpu(resp->eq_id); eq->created = true; } - spin_unlock(&ctrl->mbox_lock); + mutex_unlock(&ctrl->mbox_lock); return status; } @@ -879,7 +879,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) int status; u8 *endian_check; - spin_lock(&ctrl->mbox_lock); + mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); endian_check = (u8 *) wrb; @@ -898,7 +898,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BC_%d : be_cmd_fw_initialize Failed\n"); - spin_unlock(&ctrl->mbox_lock); + mutex_unlock(&ctrl->mbox_lock); return status; } @@ -919,7 +919,7 @@ int be_cmd_fw_uninit(struct be_ctrl_info *ctrl) int status; u8 *endian_check; - spin_lock(&ctrl->mbox_lock); + mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); endian_check = (u8 *) wrb; @@ -939,7 +939,7 @@ int be_cmd_fw_uninit(struct be_ctrl_info *ctrl) beiscsi_log(phba, KERN_ERR, BEISCSI_
[PATCH 03/15] be2iscsi: Fix to use atomic operations for tag_state
From: Jitendra Replace lock based tag_state manipulations with atomic operations. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be.h |2 +- drivers/scsi/be2iscsi/be_cmds.c | 26 -- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index cf19bce..419b53f 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -113,7 +113,7 @@ 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; + atomic_t tag_state; struct be_dma_mem tag_mem_state; }; diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 6fabded..21c806f 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -164,9 +164,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } /* Set MBX Tag state to Active */ - mutex_lock(&phba->ctrl.mbox_lock); - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; - mutex_unlock(&phba->ctrl.mbox_lock); + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, + MCC_TAG_STATE_RUNNING); /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( @@ -178,9 +177,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, if (rc <= 0) { struct be_dma_mem *tag_mem; /* Set MBX Tag state to timeout */ - mutex_lock(&phba->ctrl.mbox_lock); - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; - mutex_unlock(&phba->ctrl.mbox_lock); + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, + MCC_TAG_STATE_TIMEOUT); /* Store resource addr to be freed later */ tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; @@ -199,9 +197,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } else { rc = 0; /* Set MBX Tag state to completed */ - mutex_lock(&phba->ctrl.mbox_lock); - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - mutex_unlock(&phba->ctrl.mbox_lock); + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, + MCC_TAG_STATE_COMPLETED); } mcc_tag_response = phba->ctrl.mcc_numtag[tag]; @@ -373,9 +370,11 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, ctrl->mcc_numtag[tag] |= (extd_status & 0x00FF) << 8; ctrl->mcc_numtag[tag] |= (compl_status & 0x00FF); - if (ctrl->ptag_state[tag].tag_state == MCC_TAG_STATE_RUNNING) { + if (atomic_read(&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) { + } else if (atomic_read(&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; @@ -390,9 +389,8 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, tag_mem->va, tag_mem->dma); /* Change tag state */ - mutex_lock(&phba->ctrl.mbox_lock); - ctrl->ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - mutex_unlock(&phba->ctrl.mbox_lock); + atomic_set(&ctrl->ptag_state[tag].tag_state, + MCC_TAG_STATE_COMPLETED); /* Free MCC Tag */ free_mcc_tag(ctrl, tag); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/15] be2iscsi: Fix to remove shutdown entry point
From: Jitendra Null pointer dereference in shutdown path after taking dump. Shutdown path is not needed as FW comes up clean every time during probe after issuing FUNCTION reset MBOX command. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 17 +++-- drivers/scsi/be2iscsi/be_cmds.h |2 +- drivers/scsi/be2iscsi/be_main.c | 24 drivers/scsi/be2iscsi/be_main.h |3 +-- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 1e70053..e4cc98f 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -414,22 +414,11 @@ static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) } /** - * be2iscsi_fail_session(): Closing session with appropriate error + * beiscsi_fail_session(): Closing session with appropriate error * @cls_session: ptr to session - * - * Depending on adapter state appropriate error flag is passed. **/ -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session) +void beiscsi_fail_session(struct iscsi_cls_session *cls_session) { - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct beiscsi_hba *phba = iscsi_host_priv(shost); - uint32_t iscsi_err_flag; - - if (phba->state & BE_ADAPTER_STATE_SHUTDOWN) - iscsi_err_flag = ISCSI_ERR_INVALID_HOST; - else - iscsi_err_flag = ISCSI_ERR_CONN_FAILED; - iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } @@ -447,7 +436,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, evt->physical_port); iscsi_host_for_each_session(phba->shost, - be2iscsi_fail_session); + beiscsi_fail_session); } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 4bfca35..5d165ee 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -1367,5 +1367,5 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, u8 subsystem, u8 opcode, int cmd_len); -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session); +void beiscsi_fail_session(struct iscsi_cls_session *cls_session); #endif /* !BEISCSI_CMDS_H */ diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 61ce86b..2f3e118 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5315,7 +5315,6 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba, static void beiscsi_remove(struct pci_dev *pcidev) { - struct beiscsi_hba *phba = NULL; phba = pci_get_drvdata(pcidev); @@ -5325,9 +5324,9 @@ static void beiscsi_remove(struct pci_dev *pcidev) } beiscsi_destroy_def_ifaces(phba); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); iscsi_boot_destroy_kset(phba->boot_kset); iscsi_host_remove(phba->shost); + beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); pci_disable_pcie_error_reporting(pcidev); @@ -5336,23 +5335,6 @@ static void beiscsi_remove(struct pci_dev *pcidev) pci_disable_device(pcidev); } -static void beiscsi_shutdown(struct pci_dev *pcidev) -{ - - struct beiscsi_hba *phba = NULL; - - phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); - if (!phba) { - dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n"); - return; - } - - phba->state = BE_ADAPTER_STATE_SHUTDOWN; - iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); - pci_disable_device(pcidev); -} - static void beiscsi_msix_enable(struct beiscsi_hba *phba) { int i, status; @@ -5673,6 +5655,9 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto hba_free; } + /* +* 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, @@ -5861,7 +5846,6 @@ static struct pci_driver beiscsi_pci_driver = { .name = DRV_NAME, .probe = beiscsi_dev_probe, .remove = beiscsi_remove, - .shutdown = beiscsi_shutdown, .id_table = beiscsi_pci_id_table, .err_handler = &beiscsi_eeh_handlers }; diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 5c67c07..bd9d1e1 100644 -
[PATCH 00/15] be2iscsi: driver update 11.0.0.0
From: Jitendra This patch is generated against for-next branch. Jitendra (15): be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx be2iscsi: Fix mbox synchronization replacing spinlock with mutex be2iscsi: Fix to use atomic operations for tag_state be2iscsi: Fix to synchronize tag allocation using spin_lock be2iscsi: Set mbox timeout to 30s be2iscsi: Added return value check for mgmt_get_all_if_id be2iscsi: Fix to remove shutdown entry point be2iscsi: Fix VLAN support for IPv6 network be2iscsi: Fix to handle misconfigured optics events be2iscsi: Add FW config validation be2iscsi: Fix return value for MCC completion be2iscsi: Fix IOPOLL implementation be2iscsi: Fix to process 25G link speed info from FW be2iscsi: Fix WRB leak in login/logout path be2iscsi: Update the driver version drivers/scsi/be2iscsi/be.h |4 +- drivers/scsi/be2iscsi/be_cmds.c | 368 ++--- drivers/scsi/be2iscsi/be_cmds.h | 114 ++- drivers/scsi/be2iscsi/be_iscsi.c| 54 ++--- drivers/scsi/be2iscsi/be_main.c | 210 ++- drivers/scsi/be2iscsi/be_main.h | 23 ++- drivers/scsi/be2iscsi/be_mgmt.c | 387 +-- drivers/scsi/be2iscsi/be_mgmt.h |2 + drivers/scsi/scsi_transport_iscsi.c |2 + include/scsi/iscsi_if.h |2 + 10 files changed, 648 insertions(+), 518 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 13/15] be2iscsi: Fix to process 25G link speed info from FW
From: Jitendra Async link event provides port_speed info. Use the same to report in ISCSI_HOST_PARAM_PORT_SPEED query. Removed link status query IOCTL used to do the same. 25G and 40G are defined in kernel enum iscsi_port_speed. Fixed get_nic_conf structure definition. Removed rsvd[23] field in be_cmd_get_nic_conf_resp. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c | 47 - drivers/scsi/be2iscsi/be_cmds.h | 65 ++ drivers/scsi/be2iscsi/be_iscsi.c| 41 + drivers/scsi/be2iscsi/be_main.h |1 + drivers/scsi/be2iscsi/be_mgmt.c | 28 --- drivers/scsi/scsi_transport_iscsi.c |2 + include/scsi/iscsi_if.h |2 + 7 files changed, 57 insertions(+), 129 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 3dbf6af..498eba2 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -402,31 +402,31 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, - struct be_async_event_link_state *evt) +static void beiscsi_process_async_link(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) { - if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) { - phba->state = BE_ADAPTER_LINK_DOWN; + struct be_async_event_link_state *evt; - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link Down on Port %d\n", - evt->physical_port); + evt = (struct be_async_event_link_state *)compl; - iscsi_host_for_each_session(phba->shost, - beiscsi_fail_session); - } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { + phba->port_speed = evt->port_speed; + /** +* Check logical link status in ASYNC event. +* This has been newly introduced in SKH-R Firmware 10.0.338.45. +**/ + if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { phba->state = BE_ADAPTER_LINK_UP | BE_ADAPTER_CHECK_BOOT; phba->get_boot = BE_GET_BOOT_RETRIES; - - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link UP on Port %d\n", - evt->physical_port); + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Up on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + } else { + phba->state = BE_ADAPTER_LINK_DOWN; + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Down on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + iscsi_host_for_each_session(phba->shost, + beiscsi_fail_session); } } @@ -503,8 +503,7 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, evt_code &= ASYNC_TRAILER_EVENT_CODE_MASK; switch (evt_code) { case ASYNC_EVENT_CODE_LINK_STATE: - beiscsi_async_link_state_process(phba, - (struct be_async_event_link_state *)compl); + beiscsi_process_async_link(phba, compl); break; case ASYNC_EVENT_CODE_ISCSI: phba->state |= BE_ADAPTER_CHECK_BOOT; @@ -520,8 +519,8 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, } beiscsi_log(phba, sev, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : ASYNC Event: status 0x%08x flags 0x%08x\n", - compl->status, compl->flags); + "BC_%d : ASYNC Event %x: status 0x%08x flags 0x%08x\n", + evt_code, compl->status, compl->flags); } int beiscsi_process_mcc(struct beiscsi_hba *phba) diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 6411f7b..3b9bc2e 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -142,7 +142,6 @@ struct be_async_event_trailer { enum { ASYNC_EVENT_LINK_DOWN = 0x0, ASYNC_EVENT_LINK_UP = 0x1, - ASYNC_EVENT_LOGICAL = 0x2 }; /** @@ -152,13 +151,26 @@ enum { struct be_async_event_link_state { u8 physical_port; u8 port_link_status; +/**
[PATCH 15/15] be2iscsi: Update the driver version
From: Jitendra Driver version: 11.0.0.0 Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_main.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 41c708c..16a6fd0 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -36,7 +36,7 @@ #include #define DRV_NAME "be2iscsi" -#define BUILD_STR "10.6.0.1" +#define BUILD_STR "11.0.0.0" #define BE_NAME"Emulex OneConnect" \ "Open-iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 14/15] be2iscsi: Fix WRB leak in login/logout path
From: Jitendra Login/Logout loop was hanging after few hours. /var/log/message showed that alloc_wrb_handle() function was not able to allocate any new WRB. Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not send nopout Sep 11 11:25:22 Jhelum10 kernel: scsi host10: BM_4989 : Alloc of WRB_HANDLE Failedfor the CID : 384 Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not allocate pdu for mgmt task. Driver allocates WRB to pass login negotiated parameters information to FW in beiscsi_offload_connection(). This allocated WRB was not freed so there was WRB_Leak happening. Put WRB used for posting the login-negotiated parameters back in pool. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_main.c | 72 ++ 1 files changed, 49 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 9a86044..d8cdb4e 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1184,6 +1184,22 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->io_sgl_free_index++; } +static inline struct wrb_handle * +beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, + unsigned int wrbs_per_cxn) +{ + struct wrb_handle *pwrb_handle; + + pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; + pwrb_context->wrb_handles_available--; + if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) + pwrb_context->alloc_index = 0; + else + pwrb_context->alloc_index++; + + return pwrb_handle; +} + /** * alloc_wrb_handle - To allocate a wrb handle * @phba: The hba pointer @@ -1193,30 +1209,30 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) * This happens under session_lock until submission to chip */ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, -struct hwi_wrb_context **pcontext) + struct hwi_wrb_context **pcontext) { struct hwi_wrb_context *pwrb_context; struct hwi_controller *phwi_ctrlr; - struct wrb_handle *pwrb_handle; uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); phwi_ctrlr = phba->phwi_ctrlr; pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; - if (pwrb_context->wrb_handles_available >= 2) { - pwrb_handle = pwrb_context->pwrb_handle_base[ - pwrb_context->alloc_index]; - pwrb_context->wrb_handles_available--; - if (pwrb_context->alloc_index == - (phba->params.wrbs_per_cxn - 1)) - pwrb_context->alloc_index = 0; - else - pwrb_context->alloc_index++; + /* return the context address */ + *pcontext = pwrb_context; + return beiscsi_get_wrb_handle(pwrb_context, phba->params.wrbs_per_cxn); +} - /* Return the context address */ - *pcontext = pwrb_context; - } else - pwrb_handle = NULL; - return pwrb_handle; +static inline void +beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, + struct wrb_handle *pwrb_handle, + unsigned int wrbs_per_cxn) +{ + pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; + pwrb_context->wrb_handles_available++; + if (pwrb_context->free_index == (wrbs_per_cxn - 1)) + pwrb_context->free_index = 0; + else + pwrb_context->free_index++; } /** @@ -1231,13 +1247,9 @@ static void free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, struct wrb_handle *pwrb_handle) { - pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; - pwrb_context->wrb_handles_available++; - if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1)) - pwrb_context->free_index = 0; - else - pwrb_context->free_index++; - + beiscsi_put_wrb_handle(pwrb_context, + pwrb_handle, + phba->params.wrbs_per_cxn); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, "BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x" @@ -4715,6 +4727,20 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; iowrite32(doorbell, phba->db_va + beiscsi_conn->doorbell_offset); + + /* +* There is no completion for CONTEXT_UPDATE. The completion of next +* WRB posted guarantees FW's processing and DMA'ing of it. +* Use beiscsi_put_wrb_handle to put it back
[PATCH 12/15] be2iscsi: Fix IOPOLL implementation
From: Jitendra OS not responding when running 2 port traffic on 72 CPUs system. be2iscsi IRQs gets affined to CPU0 when irqbalancer is disabled. be_iopoll processing completions in BLOCK_IOPOLL_SOFTIRQ hogged CPU0. 1. Use budget to exit the polling loop. beiscsi_process_cq didn't honour it. 2. Rearming of EQ is done only after iopoll completes. Signed-off-by: Jitendra --- drivers/scsi/be2iscsi/be_cmds.c |2 +- drivers/scsi/be2iscsi/be_iscsi.c |2 +- drivers/scsi/be2iscsi/be_main.c | 91 +- drivers/scsi/be2iscsi/be_main.h |5 +- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index eced82b..3dbf6af 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -543,7 +543,7 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) } if (num) - hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1, 0); + hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1); spin_unlock_bh(&phba->ctrl.mcc_cq_lock); return status; diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index c89a025..3545721 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1298,7 +1298,7 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba) for (i = 0; i < phba->num_cpus; i++) { pbe_eq = &phwi_context->be_eq[i]; blk_iopoll_disable(&pbe_eq->iopoll); - beiscsi_process_cq(pbe_eq); + beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC); blk_iopoll_enable(&pbe_eq->iopoll); } } diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a665e6a..9a86044 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -895,32 +895,21 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) static irqreturn_t be_isr_msix(int irq, void *dev_id) { struct beiscsi_hba *phba; - struct be_eq_entry *eqe = NULL; struct be_queue_info *eq; - struct be_queue_info *cq; - unsigned int num_eq_processed; struct be_eq_obj *pbe_eq; pbe_eq = dev_id; eq = &pbe_eq->q; - cq = pbe_eq->cq; - eqe = queue_tail_node(eq); phba = pbe_eq->phba; - num_eq_processed = 0; - while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] - & EQE_VALID_MASK) { - if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) - blk_iopoll_sched(&pbe_eq->iopoll); - - AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); - queue_tail_inc(eq); - eqe = queue_tail_node(eq); - num_eq_processed++; - } - - if (num_eq_processed) - hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); + /* disable interrupt till iopoll completes */ + hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1); + if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) + blk_iopoll_sched(&pbe_eq->iopoll); + else + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO, + "BM_%d: received event while polling eq %d cq %d\n", + eq->id, pbe_eq->cq->id); return IRQ_HANDLED; } @@ -998,6 +987,7 @@ static irqreturn_t be_isr(int irq, void *dev_id) return IRQ_NONE; } + static int beiscsi_init_irqs(struct beiscsi_hba *phba) { struct pci_dev *pcidev = phba->pcidev; @@ -1072,7 +1062,7 @@ free_msix_irqs: void hwi_ring_cq_db(struct beiscsi_hba *phba, unsigned int id, unsigned int num_processed, - unsigned char rearm, unsigned char event) + unsigned char rearm) { u32 val = 0; @@ -2044,7 +2034,7 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) if (num_processed >= 32) { hwi_ring_cq_db(phba, mcc_cq->id, - num_processed, 0, 0); + num_processed, 0); num_processed = 0; } if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) { @@ -2062,24 +2052,25 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) } if (num_processed > 0) - hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0); + hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1); } /** * beiscsi_process_cq()- Process the Completion Queue * @pbe_eq: Event Q on which the Completion has come + * @budget: Max number of events to processed * * return * Number of Completion Entries processed. **/ -unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) +unsigned int beiscsi_process_cq(struct be_eq_obj
RE: [PATCH 10/15] be2iscsi: Add FW config validation
It stands for Dual ULP Aware. Will add a comment explaining that. Thanks, JB -Original Message- From: Hannes Reinecke [mailto:h...@suse.de] Sent: Friday, December 18, 2015 2:34 PM To: Jitendra Bhivare; linux-scsi@vger.kernel.org; micha...@cs.wisc.edu Subject: Re: [PATCH 10/15] be2iscsi: Add FW config validation On 12/15/2015 04:55 PM, Jitendra Bhivare wrote: > From: Jitendra > > System crash in I+T card personality > > Fix to add validation for ULP in initiator mode, physical port number, > and supported queue, icd, cid counts. > > Signed-off-by: Jitendra > --- > drivers/scsi/be2iscsi/be_main.c |2 +- > drivers/scsi/be2iscsi/be_main.h |2 + > drivers/scsi/be2iscsi/be_mgmt.c | 188 +-- > 3 files changed, 123 insertions(+), 69 deletions(-) > > diff --git a/drivers/scsi/be2iscsi/be_main.c > b/drivers/scsi/be2iscsi/be_main.c index 8967e05..a665e6a 100644 > --- a/drivers/scsi/be2iscsi/be_main.c > +++ b/drivers/scsi/be2iscsi/be_main.c > @@ -5670,6 +5670,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, > goto free_port; > } > mgmt_get_port_name(&phba->ctrl, phba); > + beiscsi_get_params(phba); > > if (enable_msix) > find_num_cpus(phba); > @@ -5687,7 +5688,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, > } > > phba->shost->max_id = phba->params.cxns_per_ctrl; > - beiscsi_get_params(phba); > phba->shost->can_queue = phba->params.ios_per_ctrl; > ret = beiscsi_init_port(phba); > if (ret < 0) { > diff --git a/drivers/scsi/be2iscsi/be_main.h > b/drivers/scsi/be2iscsi/be_main.h index c09082a..f89861b 100644 > --- a/drivers/scsi/be2iscsi/be_main.h > +++ b/drivers/scsi/be2iscsi/be_main.h > @@ -397,7 +397,9 @@ struct beiscsi_hba { >* group together since they are used most frequently >* for cid to cri conversion >*/ > +#define BEISCSI_PHYS_PORT_MAX4 > unsigned int phys_port; > + /* valid values of phys_port id are 0, 1, 2, 3 */ > unsigned int eqid_count; > unsigned int cqid_count; > unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT]; > diff --git a/drivers/scsi/be2iscsi/be_mgmt.c > b/drivers/scsi/be2iscsi/be_mgmt.c index ad7aa75..15f7ad7 100644 > --- a/drivers/scsi/be2iscsi/be_mgmt.c > +++ b/drivers/scsi/be2iscsi/be_mgmt.c > @@ -373,90 +373,142 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, > struct beiscsi_hba *phba) > { > struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); > - struct be_fw_cfg *req = embedded_payload(wrb); > - int status = 0; > + struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); > + uint32_t cid_count, icd_count; > + int status = -EINVAL; > + uint8_t ulp_num = 0; > > mutex_lock(&ctrl->mbox_lock); > memset(wrb, 0, sizeof(*wrb)); > + be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); > > - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); > - > - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, > + be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, > OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, > EMBED_MBX_MAX_PAYLOAD_SIZE); > - status = be_mbox_notify(ctrl); > - if (!status) { > - uint8_t ulp_num = 0; > - struct be_fw_cfg *pfw_cfg; > - pfw_cfg = req; > > - if (!is_chip_be2_be3r(phba)) { > - phba->fw_config.eqid_count = pfw_cfg->eqid_count; > - phba->fw_config.cqid_count = pfw_cfg->cqid_count; > + if (be_mbox_notify(ctrl)) { > + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, > + "BG_%d : Failed in mgmt_get_fw_config\n"); > + goto fail_init; > + } > > - beiscsi_log(phba, KERN_INFO, > - BEISCSI_LOG_INIT, > - "BG_%d : EQ_Count : %d CQ_Count : %d\n", > - phba->fw_config.eqid_count, > + /* FW response formats depend on port id */ > + phba->fw_config.phys_port = pfw_cfg->phys_port; > + if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { > + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, > + "BG_%d : invalid physical port id %d\n", > + phba->fw_config.phys_port); > + goto fail_init; > + } > + &g
RE: [PATCH 10/15] be2iscsi: Add FW config validation
Yes, the faults are not being used, it just adds to the confusion, we just intend to get the link state change - UP or DOWN. -Original Message- From: Hannes Reinecke [mailto:h...@suse.de] Sent: Friday, December 18, 2015 2:34 PM To: Jitendra Bhivare; linux-scsi@vger.kernel.org; micha...@cs.wisc.edu Subject: Re: [PATCH 10/15] be2iscsi: Add FW config validation On 12/15/2015 04:55 PM, Jitendra Bhivare wrote: > From: Jitendra > > System crash in I+T card personality > > Fix to add validation for ULP in initiator mode, physical port number, > and supported queue, icd, cid counts. > > Signed-off-by: Jitendra > --- > drivers/scsi/be2iscsi/be_main.c |2 +- > drivers/scsi/be2iscsi/be_main.h |2 + > drivers/scsi/be2iscsi/be_mgmt.c | 188 +-- > 3 files changed, 123 insertions(+), 69 deletions(-) > > diff --git a/drivers/scsi/be2iscsi/be_main.c > b/drivers/scsi/be2iscsi/be_main.c index 8967e05..a665e6a 100644 > --- a/drivers/scsi/be2iscsi/be_main.c > +++ b/drivers/scsi/be2iscsi/be_main.c > @@ -5670,6 +5670,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, > goto free_port; > } > mgmt_get_port_name(&phba->ctrl, phba); > + beiscsi_get_params(phba); > > if (enable_msix) > find_num_cpus(phba); > @@ -5687,7 +5688,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, > } > > phba->shost->max_id = phba->params.cxns_per_ctrl; > - beiscsi_get_params(phba); > phba->shost->can_queue = phba->params.ios_per_ctrl; > ret = beiscsi_init_port(phba); > if (ret < 0) { > diff --git a/drivers/scsi/be2iscsi/be_main.h > b/drivers/scsi/be2iscsi/be_main.h index c09082a..f89861b 100644 > --- a/drivers/scsi/be2iscsi/be_main.h > +++ b/drivers/scsi/be2iscsi/be_main.h > @@ -397,7 +397,9 @@ struct beiscsi_hba { >* group together since they are used most frequently >* for cid to cri conversion >*/ > +#define BEISCSI_PHYS_PORT_MAX4 > unsigned int phys_port; > + /* valid values of phys_port id are 0, 1, 2, 3 */ > unsigned int eqid_count; > unsigned int cqid_count; > unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT]; > diff --git a/drivers/scsi/be2iscsi/be_mgmt.c > b/drivers/scsi/be2iscsi/be_mgmt.c index ad7aa75..15f7ad7 100644 > --- a/drivers/scsi/be2iscsi/be_mgmt.c > +++ b/drivers/scsi/be2iscsi/be_mgmt.c > @@ -373,90 +373,142 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, > struct beiscsi_hba *phba) > { > struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); > - struct be_fw_cfg *req = embedded_payload(wrb); > - int status = 0; > + struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); > + uint32_t cid_count, icd_count; > + int status = -EINVAL; > + uint8_t ulp_num = 0; > > mutex_lock(&ctrl->mbox_lock); > memset(wrb, 0, sizeof(*wrb)); > + be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); > > - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); > - > - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, > + be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, > OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, > EMBED_MBX_MAX_PAYLOAD_SIZE); > - status = be_mbox_notify(ctrl); > - if (!status) { > - uint8_t ulp_num = 0; > - struct be_fw_cfg *pfw_cfg; > - pfw_cfg = req; > > - if (!is_chip_be2_be3r(phba)) { > - phba->fw_config.eqid_count = pfw_cfg->eqid_count; > - phba->fw_config.cqid_count = pfw_cfg->cqid_count; > + if (be_mbox_notify(ctrl)) { > + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, > + "BG_%d : Failed in mgmt_get_fw_config\n"); > + goto fail_init; > + } > > - beiscsi_log(phba, KERN_INFO, > - BEISCSI_LOG_INIT, > - "BG_%d : EQ_Count : %d CQ_Count : %d\n", > - phba->fw_config.eqid_count, > + /* FW response formats depend on port id */ > + phba->fw_config.phys_port = pfw_cfg->phys_port; > + if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { > + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, > + "BG_%d : invalid physical port id %d\n", > + phba->fw_config.phys_port); > + goto fail_
RE: [PATCH 03/15] be2iscsi: Fix to use atomic operations for tag_state
Yep, there is a need for barrier when setting MCC_TAG_STATE_TIMEOUT. I am sorry, was under the assumption that lock prefix would be used for that atomic operation as well. Thanks, JB -Original Message- From: Mike Christie [mailto:micha...@cs.wisc.edu] Sent: Sunday, December 20, 2015 3:44 PM To: Jitendra Bhivare; linux-scsi@vger.kernel.org Subject: Re: [PATCH 03/15] be2iscsi: Fix to use atomic operations for tag_state On 12/20/15 3:01 AM, Mike Christie wrote: > On 12/20/2015 01:44 AM, Mike Christie wrote: > >>> diff --git a/drivers/scsi/be2iscsi/be_cmds.c >>> b/drivers/scsi/be2iscsi/be_cmds.c index 6fabded..21c806f 100644 >>> --- a/drivers/scsi/be2iscsi/be_cmds.c >>> +++ b/drivers/scsi/be2iscsi/be_cmds.c >>> @@ -164,9 +164,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, >>> } >>> >>> /* Set MBX Tag state to Active */ >>> - mutex_lock(&phba->ctrl.mbox_lock); >>> - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; >>> - mutex_unlock(&phba->ctrl.mbox_lock); >>> + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, >>> + MCC_TAG_STATE_RUNNING); >>> > > > Is it possible for be_mcc_compl_process_isr to run before we have set > the state to MCC_TAG_STATE_RUNNING, so the > wait_event_interruptible_timeout call timesout? > > >>> /* wait for the mccq completion */ >>> rc = wait_event_interruptible_timeout( @@ -178,9 +177,8 @@ int >>> beiscsi_mccq_compl(struct beiscsi_hba *phba, >>> if (rc <= 0) { >>> struct be_dma_mem *tag_mem; >>> /* Set MBX Tag state to timeout */ >>> - mutex_lock(&phba->ctrl.mbox_lock); >>> - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; >>> - mutex_unlock(&phba->ctrl.mbox_lock); >>> + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, >>> + MCC_TAG_STATE_TIMEOUT); >>> >>> /* Store resource addr to be freed later */ >>> tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; >>> @@ -199,9 +197,8 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, >>> } else { >>> rc = 0; >>> /* Set MBX Tag state to completed */ >>> - mutex_lock(&phba->ctrl.mbox_lock); >>> - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; >>> - mutex_unlock(&phba->ctrl.mbox_lock); >>> + atomic_set(&phba->ctrl.ptag_state[tag].tag_state, >>> + MCC_TAG_STATE_COMPLETED); >>> } >>> >>> mcc_tag_response = phba->ctrl.mcc_numtag[tag]; @@ -373,9 +370,11 >>> @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, >>> ctrl->mcc_numtag[tag] |= (extd_status & 0x00FF) << 8; >>> ctrl->mcc_numtag[tag] |= (compl_status & 0x00FF); >>> >>> - if (ctrl->ptag_state[tag].tag_state == MCC_TAG_STATE_RUNNING) { >>> + if (atomic_read(&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) { >>> + } else if (atomic_read(&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; >>> >>> @@ -390,9 +389,8 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, >>> tag_mem->va, tag_mem->dma); >>> >>> /* Change tag state */ >>> - mutex_lock(&phba->ctrl.mbox_lock); >>> - ctrl->ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; >>> - mutex_unlock(&phba->ctrl.mbox_lock); >>> + atomic_set(&ctrl->ptag_state[tag].tag_state, >>> + MCC_TAG_STATE_COMPLETED); >>> >>> /* Free MCC Tag */ >>> free_mcc_tag(ctrl, tag); >>> >> >> I think if you only need to get and set a u8 then you can just use a >> u8 since the operation will be atomic. No need for a atomic_t. > > I think you can ignore this. I think you would need some barriers in > there too and it might be more complicated for no gain. > Ughhh. Sorry. The atomic_ops.txt doc says atomic_read/atomic_set use still needs barriers, so I guess they do not do anything for you and a u8 is ok. The memory-barrier.txt doc says wake_up/wait calls have barriers if the wake_up path is hit, so you are ok there. However, besides the timeout issue in the previous mail, can beiscsi_mccq_compl set the tag_mem_state to MCC_TAG_STATE_TIMEOUT and be_mcc_compl_process_isr does not see the tag_mem values updated? -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 02/17] be2iscsi: Fix mbox synchronization replacing spinlock with mutex
This is second part of actual fix for soft lockup. All mbox cmds issued using BMBX and MCC are synchronized using mutex mbox_lock instead of spin_lock. Used mutex_lock_interruptible where ever possible. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be.h | 2 +- drivers/scsi/be2iscsi/be_cmds.c | 73 ++-- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/be2iscsi/be_mgmt.c | 105 +--- 4 files changed, 94 insertions(+), 88 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 77f992e..cf19bce 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -124,7 +124,7 @@ struct be_ctrl_info { struct pci_dev *pdev; /* Mbox used for cmd request/response */ - spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ + struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ struct be_dma_mem mbox_mem; /* Mbox mem is adjusted to align to 16 bytes. The allocated addr * is stored for freeing purpose */ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index cd50e3c..6fabded 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -164,9 +164,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } /* Set MBX Tag state to Active */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( @@ -178,9 +178,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, if (rc <= 0) { struct be_dma_mem *tag_mem; /* Set MBX Tag state to timeout */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* Store resource addr to be freed later */ tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; @@ -199,9 +199,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } else { rc = 0; /* Set MBX Tag state to completed */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); } mcc_tag_response = phba->ctrl.mcc_numtag[tag]; @@ -390,9 +390,9 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, tag_mem->va, tag_mem->dma); /* Change tag state */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); ctrl->ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* Free MCC Tag */ free_mcc_tag(ctrl, tag); @@ -831,7 +831,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem = &eq->dma_mem; int status; - spin_lock(&ctrl->mbox_lock); + mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -858,7 +858,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, eq->id = le16_to_cpu(resp->eq_id); eq->created = true; } - spin_unlock(&ctrl->mbox_lock); + mutex_unlock(&ctrl->mbox_lock); return status; } @@ -879,7 +879,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) int status; u8 *endian_check; - spin_lock(&ctrl->mbox_lock); + mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); endian_check = (u8 *) wrb; @@ -898,7 +898,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BC_%d : be_cmd_fw_initialize Failed\n"); - spin_unlock(&ctrl->mbox_lock); + mutex_unlock(&ctrl->mbox_lock); return status; } @@ -919,7 +919,7 @@ int be_cmd_fw_uninit(struct be_ctrl_info *ctrl) int status; u8 *endian_check; - spin_lock(&ctrl->mbox_lock); + m
[PATCH v2 03/17] be2iscsi: Fix to use atomic bit operations for tag_state
beiscsi_mccq_compl sets MCC_TAG_STATE_TIMEOUT before setting up tag_mem_state. be_mcc_compl_process_isr checks for MCC_TAG_STATE_TIMEOUT first then accesses tag_mem_state which might be still getting populated in the process context. Fix: Set MCC_TAG_STATE_TIMEOUT after tag_mem_state is populated. Removed MCC_TAG_STATE_COMPLETED. When posted its in running state and the running state is cleared in be_mcc_compl_process_isr. be_mcc_notify now takes tag argument to set it to running state. Use bit operations for tag_state. Use barriers before setting the state. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be.h | 7 ++- drivers/scsi/be2iscsi/be_cmds.c | 111 drivers/scsi/be2iscsi/be_cmds.h | 4 +- drivers/scsi/be2iscsi/be_mgmt.c | 38 -- 4 files changed, 83 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index cf19bce..629c53d 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -110,10 +110,9 @@ struct be_mcc_obj { }; 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; + unsigned long tag_state; +#define MCC_TAG_STATE_RUNNING 1 +#define MCC_TAG_STATE_TIMEOUT 2 struct be_dma_mem tag_mem_state; }; diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 6fabded..1913e9e 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -104,13 +104,16 @@ int be_chk_reset_complete(struct beiscsi_hba *phba) return 0; } -void be_mcc_notify(struct beiscsi_hba *phba) +void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) { struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; u32 val = 0; + set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); val |= mccq->id & DB_MCCQ_RING_ID_MASK; val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; + /* ring doorbell after all of request and state is written */ + wmb(); iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); } @@ -122,6 +125,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; phba->ctrl.mcc_numtag[tag] = 0; + phba->ctrl.ptag_state[tag].tag_state = 0; } if (tag) { phba->ctrl.mcc_tag_available--; @@ -163,26 +167,25 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, return -EPERM; } - /* Set MBX Tag state to Active */ - mutex_lock(&phba->ctrl.mbox_lock); - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; - mutex_unlock(&phba->ctrl.mbox_lock); - /* 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 MBOX cmd timeout expired, tag and resource allocated +* for cmd is not freed until FW returns completion. +*/ if (rc <= 0) { struct be_dma_mem *tag_mem; - /* Set MBX Tag state to timeout */ - mutex_lock(&phba->ctrl.mbox_lock); - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; - mutex_unlock(&phba->ctrl.mbox_lock); - /* Store resource addr to be freed later */ + /** +* PCI/DMA memory allocated and posted in non-embedded mode +* will have mbx_cmd_mem != NULL. +* Save virtual and bus addresses for the command so that it +* can be freed later. +**/ tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; if (mbx_cmd_mem) { tag_mem->size = mbx_cmd_mem->size; @@ -191,19 +194,19 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } else tag_mem->size = 0; + /* first make tag_mem_state visible to all */ + wmb(); + set_bit(MCC_TAG_STATE_TIMEOUT, + &phba->ctrl.ptag_state[tag].tag_state); + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | BEISCSI_LOG_EH | BEISCSI_LOG_CONFIG, "BC_%d : MBX Cmd Completion timed out\n"); return -EBUSY; - } else { - rc = 0; - /* Set MBX Ta
[PATCH v2 00/17] be2iscsi: driver update 11.0.0.0
This patch is generated against for-next branch. Jitendra Bhivare (17): be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx be2iscsi: Fix mbox synchronization replacing spinlock with mutex be2iscsi: Fix to synchronize tag allocation using spin_lock be2iscsi: Set mbox timeout to 30s be2iscsi: Added return value check for mgmt_get_all_if_id be2iscsi: Fix to remove shutdown entry point be2iscsi: Fix VLAN support for IPv6 network be2iscsi: Fix to handle misconfigured optics events be2iscsi: Fix return value for MCC completion be2iscsi: Fix IOPOLL implementation be2iscsi: Fix WRB leak in login/logout path be2iscsi: Update the driver version be2iscsi: Fix to use atomic bit operations for tag_state be2iscsi: Add FW config validation scsi_transport_iscsi: Add 25G and 40G speed definition be2iscsi: Fix to process 25G link speed info from FW be2iscsi: Fix async link event processing drivers/scsi/be2iscsi/be.h | 9 +- drivers/scsi/be2iscsi/be_cmds.c | 453 +++- drivers/scsi/be2iscsi/be_cmds.h | 118 +- drivers/scsi/be2iscsi/be_iscsi.c| 54 ++--- drivers/scsi/be2iscsi/be_main.c | 210 + drivers/scsi/be2iscsi/be_main.h | 23 +- drivers/scsi/be2iscsi/be_mgmt.c | 425 - drivers/scsi/be2iscsi/be_mgmt.h | 2 + drivers/scsi/scsi_transport_iscsi.c | 2 + include/scsi/iscsi_if.h | 2 + 10 files changed, 720 insertions(+), 578 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 01/17] be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx
We are taking mbox_lock spinlock which disables pre-emption before we poll for mbox completion. Waiting there with spinlock held in excess of 20s will cause soft lockup. Actual fix is to change mbox_lock to mutex. The changes are done in phases. This is the first part. 1. Changed mgmt_get_all_if_id to use MCC where after posting lock is released. 2. Changed be_mbox_db_ready_wait to busy wait for 12s max and removed wait_event_timeout. Added error handling code for IO reads. OPCODE_COMMON_QUERY_FIRMWARE_CONFIG mbox command takes 8s time when unreachable boot targets configured. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 60 - drivers/scsi/be2iscsi/be_mgmt.c | 32 +++--- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 2778089..cd50e3c 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -587,47 +587,42 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define BEISCSI_MBX_RDY_BIT_TIMEOUT4000/* 4sec */ +#define BEISCSI_MBX_RDY_BIT_TIMEOUT12000 /* 12sec */ void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; - bool read_flag = false; - int ret = 0, i; u32 ready; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q); - if (beiscsi_error(phba)) - return -EIO; + /* +* This BMBX busy wait path is used during init only. +* For the commands executed during init, 5s should suffice. +*/ + timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); + do { + if (beiscsi_error(phba)) + return -EIO; - timeout = jiffies + (HZ * 110); + ready = ioread32(db); + if (ready == 0x) + return -EIO; - do { - for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) { - ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; - if (ready) { - read_flag = true; - break; - } - mdelay(1); - } + ready &= MPU_MAILBOX_DB_RDY_MASK; + if (ready) + return 0; - if (!read_flag) { - wait_event_timeout(rdybit_check_q, - (read_flag != true), - HZ * 5); - } - } while ((time_before(jiffies, timeout)) && !read_flag); + if (time_after(jiffies, timeout)) + break; + mdelay(1); + } while (!ready); - if (!read_flag) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : FW Timed Out\n"); - phba->fw_timeout = true; - beiscsi_ue_detect(phba); - ret = -EBUSY; - } + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : FW Timed Out\n"); - return ret; + phba->fw_timeout = true; + beiscsi_ue_detect(phba); + + return -EBUSY; } /* @@ -674,6 +669,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) if (status) return status; + /* RDY is set; small delay before CQE read. */ + udelay(1); + if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index aea3e6b..7b54b23 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -809,27 +809,39 @@ int mgmt_open_connection(struct beiscsi_hba *phba, unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) { struct be_ctrl_info *ctrl = &phba->ctrl; - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb); - struct be_cmd_get_all_if_id_req *pbe_allid = req; + struct be_mcc_wrb *wrb; + struct be_cmd_get_all_if_id_req *req; + struct be_cmd_get_all_if_id_req *pbe_allid; + unsigned int tag; int status = 0; - memset(wrb, 0, sizeof(*wrb)); - spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); +
[PATCH v2 11/17] be2iscsi: Fix return value for MCC completion
Change return value of completed MCC EBUSY to EINVAL. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 533060e..dbe62c0 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -323,7 +323,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, if (resp_hdr->response_length) return 0; } - return -EBUSY; + return -EINVAL; } return 0; } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 10/17] be2iscsi: Add FW config validation
System crash in I+T card personality Fix to add validation for ULP in initiator mode, physical port number, and supported queue, icd, cid counts. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/be2iscsi/be_main.h | 2 + drivers/scsi/be2iscsi/be_mgmt.c | 188 ++-- 3 files changed, 125 insertions(+), 67 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 8967e05..a665e6a 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5670,6 +5670,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto free_port; } mgmt_get_port_name(&phba->ctrl, phba); + beiscsi_get_params(phba); if (enable_msix) find_num_cpus(phba); @@ -5687,7 +5688,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, } phba->shost->max_id = phba->params.cxns_per_ctrl; - beiscsi_get_params(phba); phba->shost->can_queue = phba->params.ios_per_ctrl; ret = beiscsi_init_port(phba); if (ret < 0) { diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c09082a..f89861b 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -397,7 +397,9 @@ struct beiscsi_hba { * group together since they are used most frequently * for cid to cri conversion */ +#define BEISCSI_PHYS_PORT_MAX 4 unsigned int phys_port; + /* valid values of phys_port id are 0, 1, 2, 3 */ unsigned int eqid_count; unsigned int cqid_count; unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT]; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 10a8364..60140e2 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -373,90 +373,146 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) { struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_fw_cfg *req = embedded_payload(wrb); - int status = 0; + struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); + uint32_t cid_count, icd_count; + int status = -EINVAL; + uint8_t ulp_num = 0; mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); + be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); - - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, EMBED_MBX_MAX_PAYLOAD_SIZE); - status = be_mbox_notify(ctrl); - if (!status) { - uint8_t ulp_num = 0; - struct be_fw_cfg *pfw_cfg; - pfw_cfg = req; - if (!is_chip_be2_be3r(phba)) { - phba->fw_config.eqid_count = pfw_cfg->eqid_count; - phba->fw_config.cqid_count = pfw_cfg->cqid_count; + if (be_mbox_notify(ctrl)) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : Failed in mgmt_get_fw_config\n"); + goto fail_init; + } - beiscsi_log(phba, KERN_INFO, - BEISCSI_LOG_INIT, - "BG_%d : EQ_Count : %d CQ_Count : %d\n", - phba->fw_config.eqid_count, + /* FW response formats depend on port id */ + phba->fw_config.phys_port = pfw_cfg->phys_port; + if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : invalid physical port id %d\n", + phba->fw_config.phys_port); + goto fail_init; + } + + /* populate and check FW config against min and max values */ + if (!is_chip_be2_be3r(phba)) { + phba->fw_config.eqid_count = pfw_cfg->eqid_count; + phba->fw_config.cqid_count = pfw_cfg->cqid_count; + if (phba->fw_config.eqid_count == 0 || + phba->fw_config.eqid_count > 2048) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : invalid EQ count %d\n", + phba->fw_config.eqid_count); + goto fail_init; + } + if (phba->fw_config.cqid_count == 0 || + phba->fw_config.c
[PATCH v2 04/17] be2iscsi: Fix to synchronize tag allocation using spin_lock
alloc_mcc_tag/free_mcc_tag is now done under mcc_lock spin_lock Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 1913e9e..db03149 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -121,6 +121,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) { unsigned int tag = 0; + spin_lock(&phba->ctrl.mcc_lock); if (phba->ctrl.mcc_tag_available) { tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; @@ -134,6 +135,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) else phba->ctrl.mcc_alloc_index++; } + spin_unlock(&phba->ctrl.mcc_lock); return tag; } @@ -254,7 +256,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { - spin_lock(&ctrl->mbox_lock); + spin_lock(&ctrl->mcc_lock); tag = tag & 0x00FF; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) @@ -262,7 +264,7 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) else ctrl->mcc_free_index++; ctrl->mcc_tag_available++; - spin_unlock(&ctrl->mbox_lock); + spin_unlock(&ctrl->mcc_lock); } bool is_link_state_evt(u32 trailer) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 09/17] be2iscsi: Fix to handle misconfigured optics events
Log messages for misconfigured transceivers reported by FW. Register async events that driver handles using MCC_CREATE_EXT ioctl. Errors messages for faulted/uncertified/unqualified optics are logged. Added IOCTL to get port_name to be displayed in error message. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 164 +--- drivers/scsi/be2iscsi/be_cmds.h | 47 ++-- drivers/scsi/be2iscsi/be_main.c | 19 + drivers/scsi/be2iscsi/be_main.h | 10 ++- drivers/scsi/be2iscsi/be_mgmt.c | 42 ++ drivers/scsi/be2iscsi/be_mgmt.h | 2 + 6 files changed, 199 insertions(+), 85 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 66a1fc3..533060e 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -267,26 +267,6 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) spin_unlock(&ctrl->mcc_lock); } -bool is_link_state_evt(u32 trailer) -{ - return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_LINK_STATE); -} - -static bool is_iscsi_evt(u32 trailer) -{ - return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_ISCSI; -} - -static int iscsi_evt_type(u32 trailer) -{ - return (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & -ASYNC_TRAILER_EVENT_TYPE_MASK; -} - static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) { if (compl->flags != 0) { @@ -425,7 +405,7 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -void beiscsi_async_link_state_process(struct beiscsi_hba *phba, +static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, struct be_async_event_link_state *evt) { if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || @@ -453,6 +433,100 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, } } +static char *beiscsi_port_misconf_event_msg[] = { + "Physical Link is functional.", + "Optics faulted/incorrectly installed/not installed - Reseat optics, if issue not resolved, replace.", + "Optics of two types installed - Remove one optic or install matching pair of optics.", + "Incompatible optics - Replace with compatible optics for card to function.", + "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", + "Uncertified optics - Replace with Avago Certified optics to enable link operation." +}; + +static void beiscsi_process_async_sli(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) +{ + struct be_async_event_sli *async_sli; + u8 evt_type, state, old_state, le; + char *sev = KERN_WARNING; + char *msg = NULL; + + evt_type = compl->flags >> ASYNC_TRAILER_EVENT_TYPE_SHIFT; + evt_type &= ASYNC_TRAILER_EVENT_TYPE_MASK; + + /* processing only MISCONFIGURED physical port event */ + if (evt_type != ASYNC_SLI_EVENT_TYPE_MISCONFIGURED) + return; + + async_sli = (struct be_async_event_sli *)compl; + state = async_sli->event_data1 >> +(phba->fw_config.phys_port * 8) & 0xff; + le = async_sli->event_data2 >> +(phba->fw_config.phys_port * 8) & 0xff; + + old_state = phba->optic_state; + phba->optic_state = state; + + if (state >= ARRAY_SIZE(beiscsi_port_misconf_event_msg)) { + /* fw is reporting a state we don't know, log and return */ + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Port %c: Unrecognized optic state 0x%x\n", + phba->port_name, async_sli->event_data1); + return; + } + + if (ASYNC_SLI_LINK_EFFECT_VALID(le)) { + /* log link effect for unqualified-4, uncertified-5 optics */ + if (state > 3) + msg = (ASYNC_SLI_LINK_EFFECT_STATE(le)) ? + " Link is non-operational." : + " Link is operational."; + /* 1 - info */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 1) + sev = KERN_INFO; + /* 2 - error */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 2) + sev = KERN_ERR; + } + + if (old_state != phba->optic_state) + __beiscsi_log(phba, sev, "BC_%d : Port %c: %s%s\n", +
[PATCH v2 14/17] be2iscsi: Fix to process 25G link speed info from FW
Async link event provides port_speed info. Cache the port_speed info and use the same to report in ISCSI_HOST_PARAM_PORT_SPEED query. Removed link status query IOCTL used to do the same. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 1 + drivers/scsi/be2iscsi/be_cmds.h | 35 ++- drivers/scsi/be2iscsi/be_iscsi.c | 39 +-- drivers/scsi/be2iscsi/be_main.h | 1 + drivers/scsi/be2iscsi/be_mgmt.c | 28 5 files changed, 21 insertions(+), 83 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 14a1c71..ce82f4d 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -408,6 +408,7 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, struct be_async_event_link_state *evt) { + phba->port_speed = evt->port_speed; if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && (evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) { diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 724974e..a194066 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -153,12 +153,21 @@ struct be_async_event_link_state { u8 physical_port; u8 port_link_status; u8 port_duplex; +/* BE2ISCSI_LINK_SPEED_ZERO0x00 - no link */ +#define BE2ISCSI_LINK_SPEED_10MBPS 0x01 +#define BE2ISCSI_LINK_SPEED_100MBPS0x02 +#define BE2ISCSI_LINK_SPEED_1GBPS 0x03 +#define BE2ISCSI_LINK_SPEED_10GBPS 0x04 +#define BE2ISCSI_LINK_SPEED_25GBPS 0x06 +#define BE2ISCSI_LINK_SPEED_40GBPS 0x07 u8 port_speed; #define BEISCSI_PHY_LINK_FAULT_NONE0x00 #define BEISCSI_PHY_LINK_FAULT_LOCAL 0x01 #define BEISCSI_PHY_LINK_FAULT_REMOTE 0x02 u8 port_fault; - u8 rsvd0[7]; + u8 event_reason; + u16 qos_link_speed; + u32 event_tag; struct be_async_event_trailer trailer; } __packed; @@ -711,29 +720,6 @@ struct be_cmd_hba_name { u8 initiator_alias[BEISCSI_ALIAS_LEN]; } __packed; -struct be_cmd_ntwk_link_status_req { - struct be_cmd_req_hdr hdr; - u32 rsvd0; -} __packed; - -/*** Port Speed Values ***/ -#define BE2ISCSI_LINK_SPEED_ZERO 0x00 -#define BE2ISCSI_LINK_SPEED_10MBPS 0x01 -#define BE2ISCSI_LINK_SPEED_100MBPS0x02 -#define BE2ISCSI_LINK_SPEED_1GBPS 0x03 -#define BE2ISCSI_LINK_SPEED_10GBPS 0x04 -struct be_cmd_ntwk_link_status_resp { - struct be_cmd_resp_hdr hdr; - u8 phys_port; - u8 mac_duplex; - u8 mac_speed; - u8 mac_fault; - u8 mgmt_mac_duplex; - u8 mgmt_mac_speed; - u16 qos_link_speed; - u32 logical_link_speed; -} __packed; - int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, struct be_queue_info *eq, int eq_delay); @@ -752,7 +738,6 @@ int be_poll_mcc(struct be_ctrl_info *ctrl); int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); unsigned int be_cmd_get_initname(struct beiscsi_hba *phba); -unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba); void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 3545721..a3bc5e4 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -766,34 +766,13 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) * beiscsi_get_port_speed - Get the Port Speed from Adapter * @shost : pointer to scsi_host structure * - * returns Success/Failure */ -static int beiscsi_get_port_speed(struct Scsi_Host *shost) +static void beiscsi_get_port_speed(struct Scsi_Host *shost) { - int rc; - unsigned int tag; - struct be_mcc_wrb *wrb; - struct be_cmd_ntwk_link_status_resp *resp; struct beiscsi_hba *phba = iscsi_host_priv(shost); struct iscsi_cls_host *ihost = shost->shost_data; - tag = be_cmd_get_port_speed(phba); - if (!tag) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BS_%d : Getting Port Speed Failed\n"); - -return -EBUSY; - } - rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL); - if (rc) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BS_%d : Port Speed MBX Failed\n"); - return rc; - } - resp = embedded_payload(wrb); - - switch (resp->mac_speed) { + switch (phba->port_speed) { case BE2ISCSI_LINK_SPEED_10MBPS:
[PATCH v2 17/17] be2iscsi: Update the driver version
Driver version: 11.0.0.0 Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 41c708c..16a6fd0 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -36,7 +36,7 @@ #include #define DRV_NAME "be2iscsi" -#define BUILD_STR "10.6.0.1" +#define BUILD_STR "11.0.0.0" #define BE_NAME"Emulex OneConnect" \ "Open-iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 13/17] scsi_transport_iscsi: Add 25G and 40G speed definition
iscsi_port_speed and iscsi_port_speed_names have new entries for 25Gbps and 40Gbps link speeds. Signed-off-by: Jitendra Bhivare --- drivers/scsi/scsi_transport_iscsi.c | 2 ++ include/scsi/iscsi_if.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index e4b3d8f..4414816 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -4308,6 +4308,8 @@ static const struct { {ISCSI_PORT_SPEED_100MBPS, "100 Mbps" }, {ISCSI_PORT_SPEED_1GBPS,"1 Gbps" }, {ISCSI_PORT_SPEED_10GBPS, "10 Gbps" }, + {ISCSI_PORT_SPEED_25GBPS, "25 Gbps" }, + {ISCSI_PORT_SPEED_40GBPS, "40 Gbps" }, }; char *iscsi_get_port_speed_name(struct Scsi_Host *shost) diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 95ed942..d66c070 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -724,6 +724,8 @@ enum iscsi_port_speed { ISCSI_PORT_SPEED_100MBPS= 0x4, ISCSI_PORT_SPEED_1GBPS = 0x8, ISCSI_PORT_SPEED_10GBPS = 0x10, + ISCSI_PORT_SPEED_25GBPS = 0x20, + ISCSI_PORT_SPEED_40GBPS = 0x40, }; /* iSCSI port state */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 08/17] be2iscsi: Fix VLAN support for IPv6 network
Configuring VLAN parameters through IPv6 interface was not supported in driver. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_iscsi.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 188d83f..c89a025 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -466,6 +466,10 @@ beiscsi_set_ipv6(struct Scsi_Host *shost, ret = mgmt_set_ip(phba, iface_param, NULL, ISCSI_BOOTPROTO_STATIC); break; + case ISCSI_NET_PARAM_VLAN_ENABLED: + case ISCSI_NET_PARAM_VLAN_TAG: + ret = beiscsi_set_vlan_tag(shost, iface_param); + break; default: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : Param %d not supported\n", -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 12/17] be2iscsi: Fix IOPOLL implementation
OS not responding when running 2 port traffic on 72 CPUs system. be2iscsi IRQs gets affined to CPU0 when irqbalancer is disabled. be_iopoll processing completions in BLOCK_IOPOLL_SOFTIRQ hogged CPU0. 1. Use budget to exit the polling loop. beiscsi_process_cq didn't honour it. 2. Rearming of EQ is done only after iopoll completes. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 2 +- drivers/scsi/be2iscsi/be_iscsi.c | 2 +- drivers/scsi/be2iscsi/be_main.c | 91 ++-- drivers/scsi/be2iscsi/be_main.h | 5 ++- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index dbe62c0..14a1c71 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -546,7 +546,7 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) } if (num) - hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1, 0); + hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1); spin_unlock_bh(&phba->ctrl.mcc_cq_lock); return status; diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index c89a025..3545721 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1298,7 +1298,7 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba) for (i = 0; i < phba->num_cpus; i++) { pbe_eq = &phwi_context->be_eq[i]; blk_iopoll_disable(&pbe_eq->iopoll); - beiscsi_process_cq(pbe_eq); + beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC); blk_iopoll_enable(&pbe_eq->iopoll); } } diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a665e6a..9a86044 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -895,32 +895,21 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) static irqreturn_t be_isr_msix(int irq, void *dev_id) { struct beiscsi_hba *phba; - struct be_eq_entry *eqe = NULL; struct be_queue_info *eq; - struct be_queue_info *cq; - unsigned int num_eq_processed; struct be_eq_obj *pbe_eq; pbe_eq = dev_id; eq = &pbe_eq->q; - cq = pbe_eq->cq; - eqe = queue_tail_node(eq); phba = pbe_eq->phba; - num_eq_processed = 0; - while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] - & EQE_VALID_MASK) { - if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) - blk_iopoll_sched(&pbe_eq->iopoll); - - AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); - queue_tail_inc(eq); - eqe = queue_tail_node(eq); - num_eq_processed++; - } - - if (num_eq_processed) - hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); + /* disable interrupt till iopoll completes */ + hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1); + if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) + blk_iopoll_sched(&pbe_eq->iopoll); + else + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO, + "BM_%d: received event while polling eq %d cq %d\n", + eq->id, pbe_eq->cq->id); return IRQ_HANDLED; } @@ -998,6 +987,7 @@ static irqreturn_t be_isr(int irq, void *dev_id) return IRQ_NONE; } + static int beiscsi_init_irqs(struct beiscsi_hba *phba) { struct pci_dev *pcidev = phba->pcidev; @@ -1072,7 +1062,7 @@ free_msix_irqs: void hwi_ring_cq_db(struct beiscsi_hba *phba, unsigned int id, unsigned int num_processed, - unsigned char rearm, unsigned char event) + unsigned char rearm) { u32 val = 0; @@ -2044,7 +2034,7 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) if (num_processed >= 32) { hwi_ring_cq_db(phba, mcc_cq->id, - num_processed, 0, 0); + num_processed, 0); num_processed = 0; } if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) { @@ -2062,24 +2052,25 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) } if (num_processed > 0) - hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0); + hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1); } /** * beiscsi_process_cq()- Process the Completion Queue * @pbe_eq: Event Q on which the Completion has come + * @budget: Max number of events to processed * * return
[PATCH v2 07/17] be2iscsi: Fix to remove shutdown entry point
Null pointer dereference in shutdown path after taking dump. Shutdown path is not needed as FW comes up clean every time during probe after issuing FUNCTION reset MBOX command. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 17 +++-- drivers/scsi/be2iscsi/be_cmds.h | 2 +- drivers/scsi/be2iscsi/be_main.c | 24 drivers/scsi/be2iscsi/be_main.h | 3 +-- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index f93ab6d..66a1fc3 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -417,22 +417,11 @@ static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) } /** - * be2iscsi_fail_session(): Closing session with appropriate error + * beiscsi_fail_session(): Closing session with appropriate error * @cls_session: ptr to session - * - * Depending on adapter state appropriate error flag is passed. **/ -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session) +void beiscsi_fail_session(struct iscsi_cls_session *cls_session) { - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct beiscsi_hba *phba = iscsi_host_priv(shost); - uint32_t iscsi_err_flag; - - if (phba->state & BE_ADAPTER_STATE_SHUTDOWN) - iscsi_err_flag = ISCSI_ERR_INVALID_HOST; - else - iscsi_err_flag = ISCSI_ERR_CONN_FAILED; - iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } @@ -450,7 +439,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, evt->physical_port); iscsi_host_for_each_session(phba->shost, - be2iscsi_fail_session); + beiscsi_fail_session); } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 1883d32..f988164 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -1367,5 +1367,5 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, u8 subsystem, u8 opcode, int cmd_len); -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session); +void beiscsi_fail_session(struct iscsi_cls_session *cls_session); #endif /* !BEISCSI_CMDS_H */ diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 61ce86b..2f3e118 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5315,7 +5315,6 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba, static void beiscsi_remove(struct pci_dev *pcidev) { - struct beiscsi_hba *phba = NULL; phba = pci_get_drvdata(pcidev); @@ -5325,9 +5324,9 @@ static void beiscsi_remove(struct pci_dev *pcidev) } beiscsi_destroy_def_ifaces(phba); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); iscsi_boot_destroy_kset(phba->boot_kset); iscsi_host_remove(phba->shost); + beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); pci_disable_pcie_error_reporting(pcidev); @@ -5336,23 +5335,6 @@ static void beiscsi_remove(struct pci_dev *pcidev) pci_disable_device(pcidev); } -static void beiscsi_shutdown(struct pci_dev *pcidev) -{ - - struct beiscsi_hba *phba = NULL; - - phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); - if (!phba) { - dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n"); - return; - } - - phba->state = BE_ADAPTER_STATE_SHUTDOWN; - iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); - pci_disable_device(pcidev); -} - static void beiscsi_msix_enable(struct beiscsi_hba *phba) { int i, status; @@ -5673,6 +5655,9 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto hba_free; } + /* +* 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, @@ -5861,7 +5846,6 @@ static struct pci_driver beiscsi_pci_driver = { .name = DRV_NAME, .probe = beiscsi_dev_probe, .remove = beiscsi_remove, - .shutdown = beiscsi_shutdown, .id_table = beiscsi_pci_id_table, .err_handler = &beiscsi_eeh_handlers }; diff --git a
[PATCH v2 06/17] be2iscsi: Added return value check for mgmt_get_all_if_id
Use of mutex_lock_interruptible can return -EINTR, handle and log the error. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_iscsi.c | 7 --- drivers/scsi/be2iscsi/be_mgmt.c | 10 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index b7087ba..188d83f 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -367,13 +367,14 @@ beiscsi_set_vlan_tag(struct Scsi_Host *shost, struct iscsi_iface_param_info *iface_param) { struct beiscsi_hba *phba = iscsi_host_priv(shost); - int ret = 0; + int ret; /* Get the Interface Handle */ - if (mgmt_get_all_if_id(phba)) { + ret = mgmt_get_all_if_id(phba); + if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : Getting Interface Handle Failed\n"); - return -EIO; + return ret; } switch (iface_param->param) { diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 6ef5285..9268a70 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1024,8 +1024,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba, uint32_t ip_type; int rc; - if (mgmt_get_all_if_id(phba)) - return -EIO; + rc = mgmt_get_all_if_id(phba); + if (rc) + return rc; ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? BE2_IPV6 : BE2_IPV4 ; @@ -1194,8 +1195,9 @@ int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); int rc; - if (mgmt_get_all_if_id(phba)) - return -EIO; + rc = mgmt_get_all_if_id(phba); + if (rc) + return rc; do { rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 15/17] be2iscsi: Fix async link event processing
Use only port_link_status only to determine link state change. Only bit 0 is used to get the state. Remove code for processing port_fault. Fixed get_nic_conf structure definition. Removed rsvd[23] field in be_cmd_get_nic_conf_resp. Moved defintions of struct field values below the field. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 48 +++- drivers/scsi/be2iscsi/be_cmds.h | 32 +-- drivers/scsi/be2iscsi/be_iscsi.c | 2 +- 3 files changed, 34 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index ce82f4d..34c33d4 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -405,32 +405,31 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, - struct be_async_event_link_state *evt) +static void beiscsi_process_async_link(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) { - phba->port_speed = evt->port_speed; - if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) { - phba->state = BE_ADAPTER_LINK_DOWN; + struct be_async_event_link_state *evt; - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link Down on Port %d\n", - evt->physical_port); + evt = (struct be_async_event_link_state *)compl; - iscsi_host_for_each_session(phba->shost, - beiscsi_fail_session); - } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { + phba->port_speed = evt->port_speed; + /** +* Check logical link status in ASYNC event. +* This has been newly introduced in SKH-R Firmware 10.0.338.45. +**/ + if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { phba->state = BE_ADAPTER_LINK_UP | BE_ADAPTER_CHECK_BOOT; phba->get_boot = BE_GET_BOOT_RETRIES; - - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link UP on Port %d\n", - evt->physical_port); + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Up on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + } else { + phba->state = BE_ADAPTER_LINK_DOWN; + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Down on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + iscsi_host_for_each_session(phba->shost, + beiscsi_fail_session); } } @@ -507,8 +506,7 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, evt_code &= ASYNC_TRAILER_EVENT_CODE_MASK; switch (evt_code) { case ASYNC_EVENT_CODE_LINK_STATE: - beiscsi_async_link_state_process(phba, - (struct be_async_event_link_state *)compl); + beiscsi_process_async_link(phba, compl); break; case ASYNC_EVENT_CODE_ISCSI: phba->state |= BE_ADAPTER_CHECK_BOOT; @@ -524,8 +522,8 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, } beiscsi_log(phba, sev, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : ASYNC Event: status 0x%08x flags 0x%08x\n", - compl->status, compl->flags); + "BC_%d : ASYNC Event %x: status 0x%08x flags 0x%08x\n", + evt_code, compl->status, compl->flags); } int beiscsi_process_mcc(struct beiscsi_hba *phba) diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index a194066..7caf585 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -142,7 +142,6 @@ struct be_async_event_trailer { enum { ASYNC_EVENT_LINK_DOWN = 0x0, ASYNC_EVENT_LINK_UP = 0x1, - ASYNC_EVENT_LOGICAL = 0x2 }; /** @@ -152,7 +151,15 @@ enum { struct be_async_event_link_state { u8 physical_port; u8 port_link_status; +/** + * AS
[PATCH v2 05/17] be2iscsi: Set mbox timeout to 30s
FW recommended timeout for all mbox command is 30s. Use msleep instead mdelay to relinquish CPU when polling for mbox completion. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index db03149..f93ab6d 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -590,7 +590,8 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba, unsigned int tag) **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define BEISCSI_MBX_RDY_BIT_TIMEOUT12000 /* 12sec */ + /* wait 30s for generic non-flash MBOX operation */ +#define BEISCSI_MBX_RDY_BIT_TIMEOUT3 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; @@ -615,7 +616,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) if (time_after(jiffies, timeout)) break; - mdelay(1); + msleep(20); } while (!ready); beiscsi_log(phba, KERN_ERR, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 16/17] be2iscsi: Fix WRB leak in login/logout path
Login/Logout loop was hanging after few hours. /var/log/message showed that alloc_wrb_handle() function was not able to allocate any new WRB. Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not send nopout Sep 11 11:25:22 Jhelum10 kernel: scsi host10: BM_4989 : Alloc of WRB_HANDLE Failedfor the CID : 384 Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not allocate pdu for mgmt task. Driver allocates WRB to pass login negotiated parameters information to FW in beiscsi_offload_connection(). This allocated WRB was not freed so there was WRB_Leak happening. Put WRB used for posting the login-negotiated parameters back in pool. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_main.c | 72 - 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 9a86044..d8cdb4e 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1184,6 +1184,22 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->io_sgl_free_index++; } +static inline struct wrb_handle * +beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, + unsigned int wrbs_per_cxn) +{ + struct wrb_handle *pwrb_handle; + + pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; + pwrb_context->wrb_handles_available--; + if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) + pwrb_context->alloc_index = 0; + else + pwrb_context->alloc_index++; + + return pwrb_handle; +} + /** * alloc_wrb_handle - To allocate a wrb handle * @phba: The hba pointer @@ -1193,30 +1209,30 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) * This happens under session_lock until submission to chip */ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, -struct hwi_wrb_context **pcontext) + struct hwi_wrb_context **pcontext) { struct hwi_wrb_context *pwrb_context; struct hwi_controller *phwi_ctrlr; - struct wrb_handle *pwrb_handle; uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); phwi_ctrlr = phba->phwi_ctrlr; pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; - if (pwrb_context->wrb_handles_available >= 2) { - pwrb_handle = pwrb_context->pwrb_handle_base[ - pwrb_context->alloc_index]; - pwrb_context->wrb_handles_available--; - if (pwrb_context->alloc_index == - (phba->params.wrbs_per_cxn - 1)) - pwrb_context->alloc_index = 0; - else - pwrb_context->alloc_index++; + /* return the context address */ + *pcontext = pwrb_context; + return beiscsi_get_wrb_handle(pwrb_context, phba->params.wrbs_per_cxn); +} - /* Return the context address */ - *pcontext = pwrb_context; - } else - pwrb_handle = NULL; - return pwrb_handle; +static inline void +beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, + struct wrb_handle *pwrb_handle, + unsigned int wrbs_per_cxn) +{ + pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; + pwrb_context->wrb_handles_available++; + if (pwrb_context->free_index == (wrbs_per_cxn - 1)) + pwrb_context->free_index = 0; + else + pwrb_context->free_index++; } /** @@ -1231,13 +1247,9 @@ static void free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, struct wrb_handle *pwrb_handle) { - pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; - pwrb_context->wrb_handles_available++; - if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1)) - pwrb_context->free_index = 0; - else - pwrb_context->free_index++; - + beiscsi_put_wrb_handle(pwrb_context, + pwrb_handle, + phba->params.wrbs_per_cxn); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, "BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x" @@ -4715,6 +4727,20 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; iowrite32(doorbell, phba->db_va + beiscsi_conn->doorbell_offset); + + /* +* There is no completion
RE: [PATCH v2 17/17] be2iscsi: Update the driver version
Please ignore patch v2 set sending v3 shortly. -Original Message- From: Jitendra Bhivare [mailto:jitendra.bhiv...@avagotech.com] Sent: Tuesday, December 22, 2015 10:46 PM To: linux-scsi@vger.kernel.org; micha...@cs.wisc.edu Cc: Jitendra Bhivare Subject: [PATCH v2 17/17] be2iscsi: Update the driver version Driver version: 11.0.0.0 Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 41c708c..16a6fd0 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -36,7 +36,7 @@ #include #define DRV_NAME "be2iscsi" -#define BUILD_STR "10.6.0.1" +#define BUILD_STR "11.0.0.0" #define BE_NAME"Emulex OneConnect" \ "Open-iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 02/17] be2iscsi: Fix mbox synchronization replacing spinlock with mutex
This is second part of actual fix for soft lockup. All mbox cmds issued using BMBX and MCC are synchronized using mutex mbox_lock instead of spin_lock. Used mutex_lock_interruptible where ever possible. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be.h | 2 +- drivers/scsi/be2iscsi/be_cmds.c | 73 ++-- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/be2iscsi/be_mgmt.c | 105 +--- 4 files changed, 94 insertions(+), 88 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index 77f992e..cf19bce 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -124,7 +124,7 @@ struct be_ctrl_info { struct pci_dev *pdev; /* Mbox used for cmd request/response */ - spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ + struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ struct be_dma_mem mbox_mem; /* Mbox mem is adjusted to align to 16 bytes. The allocated addr * is stored for freeing purpose */ diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index cd50e3c..6fabded 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -164,9 +164,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } /* Set MBX Tag state to Active */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* wait for the mccq completion */ rc = wait_event_interruptible_timeout( @@ -178,9 +178,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, if (rc <= 0) { struct be_dma_mem *tag_mem; /* Set MBX Tag state to timeout */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* Store resource addr to be freed later */ tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; @@ -199,9 +199,9 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } else { rc = 0; /* Set MBX Tag state to completed */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); } mcc_tag_response = phba->ctrl.mcc_numtag[tag]; @@ -390,9 +390,9 @@ int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, tag_mem->va, tag_mem->dma); /* Change tag state */ - spin_lock(&phba->ctrl.mbox_lock); + mutex_lock(&phba->ctrl.mbox_lock); ctrl->ptag_state[tag].tag_state = MCC_TAG_STATE_COMPLETED; - spin_unlock(&phba->ctrl.mbox_lock); + mutex_unlock(&phba->ctrl.mbox_lock); /* Free MCC Tag */ free_mcc_tag(ctrl, tag); @@ -831,7 +831,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem = &eq->dma_mem; int status; - spin_lock(&ctrl->mbox_lock); + mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -858,7 +858,7 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, eq->id = le16_to_cpu(resp->eq_id); eq->created = true; } - spin_unlock(&ctrl->mbox_lock); + mutex_unlock(&ctrl->mbox_lock); return status; } @@ -879,7 +879,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) int status; u8 *endian_check; - spin_lock(&ctrl->mbox_lock); + mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); endian_check = (u8 *) wrb; @@ -898,7 +898,7 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, "BC_%d : be_cmd_fw_initialize Failed\n"); - spin_unlock(&ctrl->mbox_lock); + mutex_unlock(&ctrl->mbox_lock); return status; } @@ -919,7 +919,7 @@ int be_cmd_fw_uninit(struct be_ctrl_info *ctrl) int status; u8 *endian_check; - spin_lock(&ctrl->mbox_lock); + m
[PATCH v3 03/17] be2iscsi: Fix to use atomic bit operations for tag_state
beiscsi_mccq_compl sets MCC_TAG_STATE_TIMEOUT before setting up tag_mem_state. be_mcc_compl_process_isr checks for MCC_TAG_STATE_TIMEOUT first then accesses tag_mem_state which might be still getting populated in the process context. Fix: Set MCC_TAG_STATE_TIMEOUT after tag_mem_state is populated. Removed MCC_TAG_STATE_COMPLETED. When posted its in running state and the running state is cleared in be_mcc_compl_process_isr. be_mcc_notify now takes tag argument to set it to running state. Use bit operations for tag_state. Use barriers before setting the state. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be.h | 7 ++- drivers/scsi/be2iscsi/be_cmds.c | 111 drivers/scsi/be2iscsi/be_cmds.h | 4 +- drivers/scsi/be2iscsi/be_mgmt.c | 39 -- 4 files changed, 84 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index cf19bce..629c53d 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h @@ -110,10 +110,9 @@ struct be_mcc_obj { }; 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; + unsigned long tag_state; +#define MCC_TAG_STATE_RUNNING 1 +#define MCC_TAG_STATE_TIMEOUT 2 struct be_dma_mem tag_mem_state; }; diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 6fabded..1913e9e 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -104,13 +104,16 @@ int be_chk_reset_complete(struct beiscsi_hba *phba) return 0; } -void be_mcc_notify(struct beiscsi_hba *phba) +void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) { struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; u32 val = 0; + set_bit(MCC_TAG_STATE_RUNNING, &phba->ctrl.ptag_state[tag].tag_state); val |= mccq->id & DB_MCCQ_RING_ID_MASK; val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; + /* ring doorbell after all of request and state is written */ + wmb(); iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); } @@ -122,6 +125,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; phba->ctrl.mcc_numtag[tag] = 0; + phba->ctrl.ptag_state[tag].tag_state = 0; } if (tag) { phba->ctrl.mcc_tag_available--; @@ -163,26 +167,25 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, return -EPERM; } - /* Set MBX Tag state to Active */ - mutex_lock(&phba->ctrl.mbox_lock); - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_RUNNING; - mutex_unlock(&phba->ctrl.mbox_lock); - /* 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 MBOX cmd timeout expired, tag and resource allocated +* for cmd is not freed until FW returns completion. +*/ if (rc <= 0) { struct be_dma_mem *tag_mem; - /* Set MBX Tag state to timeout */ - mutex_lock(&phba->ctrl.mbox_lock); - phba->ctrl.ptag_state[tag].tag_state = MCC_TAG_STATE_TIMEOUT; - mutex_unlock(&phba->ctrl.mbox_lock); - /* Store resource addr to be freed later */ + /** +* PCI/DMA memory allocated and posted in non-embedded mode +* will have mbx_cmd_mem != NULL. +* Save virtual and bus addresses for the command so that it +* can be freed later. +**/ tag_mem = &phba->ctrl.ptag_state[tag].tag_mem_state; if (mbx_cmd_mem) { tag_mem->size = mbx_cmd_mem->size; @@ -191,19 +194,19 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, } else tag_mem->size = 0; + /* first make tag_mem_state visible to all */ + wmb(); + set_bit(MCC_TAG_STATE_TIMEOUT, + &phba->ctrl.ptag_state[tag].tag_state); + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | BEISCSI_LOG_EH | BEISCSI_LOG_CONFIG, "BC_%d : MBX Cmd Completion timed out\n"); return -EBUSY; - } else { - rc = 0; - /* Set MBX Ta
[PATCH v3 01/17] be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx
We are taking mbox_lock spinlock which disables pre-emption before we poll for mbox completion. Waiting there with spinlock held in excess of 20s will cause soft lockup. Actual fix is to change mbox_lock to mutex. The changes are done in phases. This is the first part. 1. Changed mgmt_get_all_if_id to use MCC where after posting lock is released. 2. Changed be_mbox_db_ready_wait to busy wait for 12s max and removed wait_event_timeout. Added error handling code for IO reads. OPCODE_COMMON_QUERY_FIRMWARE_CONFIG mbox command takes 8s time when unreachable boot targets configured. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 60 - drivers/scsi/be2iscsi/be_mgmt.c | 32 +++--- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 2778089..cd50e3c 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -587,47 +587,42 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba) **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define BEISCSI_MBX_RDY_BIT_TIMEOUT4000/* 4sec */ +#define BEISCSI_MBX_RDY_BIT_TIMEOUT12000 /* 12sec */ void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; - bool read_flag = false; - int ret = 0, i; u32 ready; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q); - if (beiscsi_error(phba)) - return -EIO; + /* +* This BMBX busy wait path is used during init only. +* For the commands executed during init, 5s should suffice. +*/ + timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); + do { + if (beiscsi_error(phba)) + return -EIO; - timeout = jiffies + (HZ * 110); + ready = ioread32(db); + if (ready == 0x) + return -EIO; - do { - for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) { - ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; - if (ready) { - read_flag = true; - break; - } - mdelay(1); - } + ready &= MPU_MAILBOX_DB_RDY_MASK; + if (ready) + return 0; - if (!read_flag) { - wait_event_timeout(rdybit_check_q, - (read_flag != true), - HZ * 5); - } - } while ((time_before(jiffies, timeout)) && !read_flag); + if (time_after(jiffies, timeout)) + break; + mdelay(1); + } while (!ready); - if (!read_flag) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : FW Timed Out\n"); - phba->fw_timeout = true; - beiscsi_ue_detect(phba); - ret = -EBUSY; - } + beiscsi_log(phba, KERN_ERR, + BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, + "BC_%d : FW Timed Out\n"); - return ret; + phba->fw_timeout = true; + beiscsi_ue_detect(phba); + + return -EBUSY; } /* @@ -674,6 +669,9 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) if (status) return status; + /* RDY is set; small delay before CQE read. */ + udelay(1); + if (be_mcc_compl_is_new(compl)) { status = be_mcc_compl_process(ctrl, &mbox->compl); be_mcc_compl_use(compl); diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index aea3e6b..7b54b23 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -809,27 +809,39 @@ int mgmt_open_connection(struct beiscsi_hba *phba, unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) { struct be_ctrl_info *ctrl = &phba->ctrl; - struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb); - struct be_cmd_get_all_if_id_req *pbe_allid = req; + struct be_mcc_wrb *wrb; + struct be_cmd_get_all_if_id_req *req; + struct be_cmd_get_all_if_id_req *pbe_allid; + unsigned int tag; int status = 0; - memset(wrb, 0, sizeof(*wrb)); - spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); +
[PATCH v3 00/17] be2iscsi: driver update 11.0.0.0
This patch is generated against for-next branch. Jitendra Bhivare (17): be2iscsi: Fix soft lockup in mgmt_get_all_if_id path using bmbx be2iscsi: Fix mbox synchronization replacing spinlock with mutex be2iscsi: Fix to use atomic bit operations for tag_state be2iscsi: Fix to synchronize tag allocation using spin_lock be2iscsi: Set mbox timeout to 30s be2iscsi: Added return value check for mgmt_get_all_if_id be2iscsi: Fix to remove shutdown entry point be2iscsi: Fix VLAN support for IPv6 network be2iscsi: Fix to handle misconfigured optics events be2iscsi: Add FW config validation be2iscsi: Fix return value for MCC completion be2iscsi: Fix IOPOLL implementation scsi_transport_iscsi: Add 25G and 40G speed definition be2iscsi: Fix to process 25G link speed info from FW be2iscsi: Fix async link event processing be2iscsi: Fix WRB leak in login/logout path be2iscsi: Update the driver version drivers/scsi/be2iscsi/be.h | 9 +- drivers/scsi/be2iscsi/be_cmds.c | 453 +++- drivers/scsi/be2iscsi/be_cmds.h | 118 +- drivers/scsi/be2iscsi/be_iscsi.c| 54 ++--- drivers/scsi/be2iscsi/be_main.c | 210 + drivers/scsi/be2iscsi/be_main.h | 23 +- drivers/scsi/be2iscsi/be_mgmt.c | 426 - drivers/scsi/be2iscsi/be_mgmt.h | 2 + drivers/scsi/scsi_transport_iscsi.c | 2 + include/scsi/iscsi_if.h | 2 + 10 files changed, 721 insertions(+), 578 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 04/17] be2iscsi: Fix to synchronize tag allocation using spin_lock
alloc_mcc_tag/free_mcc_tag is now done under mcc_lock spin_lock Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 1913e9e..502c9b6 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -121,6 +121,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) { unsigned int tag = 0; + spin_lock_bh(&phba->ctrl.mcc_lock); if (phba->ctrl.mcc_tag_available) { tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; @@ -134,6 +135,7 @@ unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) else phba->ctrl.mcc_alloc_index++; } + spin_unlock_bh(&phba->ctrl.mcc_lock); return tag; } @@ -254,7 +256,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) { - spin_lock(&ctrl->mbox_lock); + spin_lock_bh(&ctrl->mcc_lock); tag = tag & 0x00FF; ctrl->mcc_tag[ctrl->mcc_free_index] = tag; if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) @@ -262,7 +264,7 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) else ctrl->mcc_free_index++; ctrl->mcc_tag_available++; - spin_unlock(&ctrl->mbox_lock); + spin_unlock_bh(&ctrl->mcc_lock); } bool is_link_state_evt(u32 trailer) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 05/17] be2iscsi: Set mbox timeout to 30s
FW recommended timeout for all mbox command is 30s. Use msleep instead mdelay to relinquish CPU when polling for mbox completion. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 502c9b6..034b868 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -590,7 +590,8 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba, unsigned int tag) **/ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) { -#define BEISCSI_MBX_RDY_BIT_TIMEOUT12000 /* 12sec */ + /* wait 30s for generic non-flash MBOX operation */ +#define BEISCSI_MBX_RDY_BIT_TIMEOUT3 void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); unsigned long timeout; @@ -615,7 +616,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) if (time_after(jiffies, timeout)) break; - mdelay(1); + msleep(20); } while (!ready); beiscsi_log(phba, KERN_ERR, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 17/17] be2iscsi: Update the driver version
Driver version: 11.0.0.0 Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 41c708c..16a6fd0 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -36,7 +36,7 @@ #include #define DRV_NAME "be2iscsi" -#define BUILD_STR "10.6.0.1" +#define BUILD_STR "11.0.0.0" #define BE_NAME"Emulex OneConnect" \ "Open-iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 13/17] scsi_transport_iscsi: Add 25G and 40G speed definition
iscsi_port_speed and iscsi_port_speed_names have new entries for 25Gbps and 40Gbps link speeds. Signed-off-by: Jitendra Bhivare --- drivers/scsi/scsi_transport_iscsi.c | 2 ++ include/scsi/iscsi_if.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index e4b3d8f..4414816 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -4308,6 +4308,8 @@ static const struct { {ISCSI_PORT_SPEED_100MBPS, "100 Mbps" }, {ISCSI_PORT_SPEED_1GBPS,"1 Gbps" }, {ISCSI_PORT_SPEED_10GBPS, "10 Gbps" }, + {ISCSI_PORT_SPEED_25GBPS, "25 Gbps" }, + {ISCSI_PORT_SPEED_40GBPS, "40 Gbps" }, }; char *iscsi_get_port_speed_name(struct Scsi_Host *shost) diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h index 95ed942..d66c070 100644 --- a/include/scsi/iscsi_if.h +++ b/include/scsi/iscsi_if.h @@ -724,6 +724,8 @@ enum iscsi_port_speed { ISCSI_PORT_SPEED_100MBPS= 0x4, ISCSI_PORT_SPEED_1GBPS = 0x8, ISCSI_PORT_SPEED_10GBPS = 0x10, + ISCSI_PORT_SPEED_25GBPS = 0x20, + ISCSI_PORT_SPEED_40GBPS = 0x40, }; /* iSCSI port state */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 15/17] be2iscsi: Fix async link event processing
Use only port_link_status only to determine link state change. Only bit 0 is used to get the state. Remove code for processing port_fault. Fixed get_nic_conf structure definition. Removed rsvd[23] field in be_cmd_get_nic_conf_resp. Moved defintions of struct field values below the field. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 48 +++- drivers/scsi/be2iscsi/be_cmds.h | 32 +-- drivers/scsi/be2iscsi/be_iscsi.c | 2 +- 3 files changed, 34 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index cd14d26..a3dcd66 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -405,32 +405,31 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, - struct be_async_event_link_state *evt) +static void beiscsi_process_async_link(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) { - phba->port_speed = evt->port_speed; - if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) { - phba->state = BE_ADAPTER_LINK_DOWN; + struct be_async_event_link_state *evt; - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link Down on Port %d\n", - evt->physical_port); + evt = (struct be_async_event_link_state *)compl; - iscsi_host_for_each_session(phba->shost, - beiscsi_fail_session); - } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || - ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && -(evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { + phba->port_speed = evt->port_speed; + /** +* Check logical link status in ASYNC event. +* This has been newly introduced in SKH-R Firmware 10.0.338.45. +**/ + if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { phba->state = BE_ADAPTER_LINK_UP | BE_ADAPTER_CHECK_BOOT; phba->get_boot = BE_GET_BOOT_RETRIES; - - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, - "BC_%d : Link UP on Port %d\n", - evt->physical_port); + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Up on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + } else { + phba->state = BE_ADAPTER_LINK_DOWN; + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Link Down on Port %d tag 0x%x\n", + evt->physical_port, evt->event_tag); + iscsi_host_for_each_session(phba->shost, + beiscsi_fail_session); } } @@ -507,8 +506,7 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, evt_code &= ASYNC_TRAILER_EVENT_CODE_MASK; switch (evt_code) { case ASYNC_EVENT_CODE_LINK_STATE: - beiscsi_async_link_state_process(phba, - (struct be_async_event_link_state *)compl); + beiscsi_process_async_link(phba, compl); break; case ASYNC_EVENT_CODE_ISCSI: phba->state |= BE_ADAPTER_CHECK_BOOT; @@ -524,8 +522,8 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, } beiscsi_log(phba, sev, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BC_%d : ASYNC Event: status 0x%08x flags 0x%08x\n", - compl->status, compl->flags); + "BC_%d : ASYNC Event %x: status 0x%08x flags 0x%08x\n", + evt_code, compl->status, compl->flags); } int beiscsi_process_mcc(struct beiscsi_hba *phba) diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index a194066..7caf585 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -142,7 +142,6 @@ struct be_async_event_trailer { enum { ASYNC_EVENT_LINK_DOWN = 0x0, ASYNC_EVENT_LINK_UP = 0x1, - ASYNC_EVENT_LOGICAL = 0x2 }; /** @@ -152,7 +151,15 @@ enum { struct be_async_event_link_state { u8 physical_port; u8 port_link_status; +/** + * AS
[PATCH v3 16/17] be2iscsi: Fix WRB leak in login/logout path
Login/Logout loop was hanging after few hours. /var/log/message showed that alloc_wrb_handle() function was not able to allocate any new WRB. Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not send nopout Sep 11 11:25:22 Jhelum10 kernel: scsi host10: BM_4989 : Alloc of WRB_HANDLE Failedfor the CID : 384 Sep 11 11:25:22 Jhelum10 kernel: connection32513:0: Could not allocate pdu for mgmt task. Driver allocates WRB to pass login negotiated parameters information to FW in beiscsi_offload_connection(). This allocated WRB was not freed so there was WRB_Leak happening. Put WRB used for posting the login-negotiated parameters back in pool. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_main.c | 72 - 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 9a86044..d8cdb4e 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1184,6 +1184,22 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) phba->io_sgl_free_index++; } +static inline struct wrb_handle * +beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, + unsigned int wrbs_per_cxn) +{ + struct wrb_handle *pwrb_handle; + + pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; + pwrb_context->wrb_handles_available--; + if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) + pwrb_context->alloc_index = 0; + else + pwrb_context->alloc_index++; + + return pwrb_handle; +} + /** * alloc_wrb_handle - To allocate a wrb handle * @phba: The hba pointer @@ -1193,30 +1209,30 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) * This happens under session_lock until submission to chip */ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, -struct hwi_wrb_context **pcontext) + struct hwi_wrb_context **pcontext) { struct hwi_wrb_context *pwrb_context; struct hwi_controller *phwi_ctrlr; - struct wrb_handle *pwrb_handle; uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); phwi_ctrlr = phba->phwi_ctrlr; pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; - if (pwrb_context->wrb_handles_available >= 2) { - pwrb_handle = pwrb_context->pwrb_handle_base[ - pwrb_context->alloc_index]; - pwrb_context->wrb_handles_available--; - if (pwrb_context->alloc_index == - (phba->params.wrbs_per_cxn - 1)) - pwrb_context->alloc_index = 0; - else - pwrb_context->alloc_index++; + /* return the context address */ + *pcontext = pwrb_context; + return beiscsi_get_wrb_handle(pwrb_context, phba->params.wrbs_per_cxn); +} - /* Return the context address */ - *pcontext = pwrb_context; - } else - pwrb_handle = NULL; - return pwrb_handle; +static inline void +beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context, + struct wrb_handle *pwrb_handle, + unsigned int wrbs_per_cxn) +{ + pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; + pwrb_context->wrb_handles_available++; + if (pwrb_context->free_index == (wrbs_per_cxn - 1)) + pwrb_context->free_index = 0; + else + pwrb_context->free_index++; } /** @@ -1231,13 +1247,9 @@ static void free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, struct wrb_handle *pwrb_handle) { - pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle; - pwrb_context->wrb_handles_available++; - if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1)) - pwrb_context->free_index = 0; - else - pwrb_context->free_index++; - + beiscsi_put_wrb_handle(pwrb_context, + pwrb_handle, + phba->params.wrbs_per_cxn); beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, "BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x" @@ -4715,6 +4727,20 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; iowrite32(doorbell, phba->db_va + beiscsi_conn->doorbell_offset); + + /* +* There is no completion
[PATCH v3 09/17] be2iscsi: Fix to handle misconfigured optics events
Log messages for misconfigured transceivers reported by FW. Register async events that driver handles using MCC_CREATE_EXT ioctl. Errors messages for faulted/uncertified/unqualified optics are logged. Added IOCTL to get port_name to be displayed in error message. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 164 +--- drivers/scsi/be2iscsi/be_cmds.h | 47 ++-- drivers/scsi/be2iscsi/be_main.c | 19 + drivers/scsi/be2iscsi/be_main.h | 10 ++- drivers/scsi/be2iscsi/be_mgmt.c | 42 ++ drivers/scsi/be2iscsi/be_mgmt.h | 2 + 6 files changed, 199 insertions(+), 85 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 705215e..d69fb0a 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -267,26 +267,6 @@ void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) spin_unlock_bh(&ctrl->mcc_lock); } -bool is_link_state_evt(u32 trailer) -{ - return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_LINK_STATE); -} - -static bool is_iscsi_evt(u32 trailer) -{ - return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & - ASYNC_TRAILER_EVENT_CODE_MASK) == - ASYNC_EVENT_CODE_ISCSI; -} - -static int iscsi_evt_type(u32 trailer) -{ - return (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & -ASYNC_TRAILER_EVENT_TYPE_MASK; -} - static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) { if (compl->flags != 0) { @@ -425,7 +405,7 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } -void beiscsi_async_link_state_process(struct beiscsi_hba *phba, +static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, struct be_async_event_link_state *evt) { if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || @@ -453,6 +433,100 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, } } +static char *beiscsi_port_misconf_event_msg[] = { + "Physical Link is functional.", + "Optics faulted/incorrectly installed/not installed - Reseat optics, if issue not resolved, replace.", + "Optics of two types installed - Remove one optic or install matching pair of optics.", + "Incompatible optics - Replace with compatible optics for card to function.", + "Unqualified optics - Replace with Avago optics for Warranty and Technical Support.", + "Uncertified optics - Replace with Avago Certified optics to enable link operation." +}; + +static void beiscsi_process_async_sli(struct beiscsi_hba *phba, + struct be_mcc_compl *compl) +{ + struct be_async_event_sli *async_sli; + u8 evt_type, state, old_state, le; + char *sev = KERN_WARNING; + char *msg = NULL; + + evt_type = compl->flags >> ASYNC_TRAILER_EVENT_TYPE_SHIFT; + evt_type &= ASYNC_TRAILER_EVENT_TYPE_MASK; + + /* processing only MISCONFIGURED physical port event */ + if (evt_type != ASYNC_SLI_EVENT_TYPE_MISCONFIGURED) + return; + + async_sli = (struct be_async_event_sli *)compl; + state = async_sli->event_data1 >> +(phba->fw_config.phys_port * 8) & 0xff; + le = async_sli->event_data2 >> +(phba->fw_config.phys_port * 8) & 0xff; + + old_state = phba->optic_state; + phba->optic_state = state; + + if (state >= ARRAY_SIZE(beiscsi_port_misconf_event_msg)) { + /* fw is reporting a state we don't know, log and return */ + __beiscsi_log(phba, KERN_ERR, + "BC_%d : Port %c: Unrecognized optic state 0x%x\n", + phba->port_name, async_sli->event_data1); + return; + } + + if (ASYNC_SLI_LINK_EFFECT_VALID(le)) { + /* log link effect for unqualified-4, uncertified-5 optics */ + if (state > 3) + msg = (ASYNC_SLI_LINK_EFFECT_STATE(le)) ? + " Link is non-operational." : + " Link is operational."; + /* 1 - info */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 1) + sev = KERN_INFO; + /* 2 - error */ + if (ASYNC_SLI_LINK_EFFECT_SEV(le) == 2) + sev = KERN_ERR; + } + + if (old_state != phba->optic_state) + __beiscsi_log(phba, sev, "BC_%d : Port %c: %s%s\n", +
[PATCH v3 11/17] be2iscsi: Fix return value for MCC completion
Change return value of completed MCC EBUSY to EINVAL. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index d69fb0a..1e6a1b6 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -323,7 +323,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, if (resp_hdr->response_length) return 0; } - return -EBUSY; + return -EINVAL; } return 0; } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 07/17] be2iscsi: Fix to remove shutdown entry point
Null pointer dereference in shutdown path after taking dump. Shutdown path is not needed as FW comes up clean every time during probe after issuing FUNCTION reset MBOX command. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 17 +++-- drivers/scsi/be2iscsi/be_cmds.h | 2 +- drivers/scsi/be2iscsi/be_main.c | 24 drivers/scsi/be2iscsi/be_main.h | 3 +-- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 034b868..705215e 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -417,22 +417,11 @@ static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) } /** - * be2iscsi_fail_session(): Closing session with appropriate error + * beiscsi_fail_session(): Closing session with appropriate error * @cls_session: ptr to session - * - * Depending on adapter state appropriate error flag is passed. **/ -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session) +void beiscsi_fail_session(struct iscsi_cls_session *cls_session) { - struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); - struct beiscsi_hba *phba = iscsi_host_priv(shost); - uint32_t iscsi_err_flag; - - if (phba->state & BE_ADAPTER_STATE_SHUTDOWN) - iscsi_err_flag = ISCSI_ERR_INVALID_HOST; - else - iscsi_err_flag = ISCSI_ERR_CONN_FAILED; - iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); } @@ -450,7 +439,7 @@ void beiscsi_async_link_state_process(struct beiscsi_hba *phba, evt->physical_port); iscsi_host_for_each_session(phba->shost, - be2iscsi_fail_session); + beiscsi_fail_session); } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 1883d32..f988164 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -1367,5 +1367,5 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, u8 subsystem, u8 opcode, int cmd_len); -void be2iscsi_fail_session(struct iscsi_cls_session *cls_session); +void beiscsi_fail_session(struct iscsi_cls_session *cls_session); #endif /* !BEISCSI_CMDS_H */ diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 61ce86b..2f3e118 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5315,7 +5315,6 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba, static void beiscsi_remove(struct pci_dev *pcidev) { - struct beiscsi_hba *phba = NULL; phba = pci_get_drvdata(pcidev); @@ -5325,9 +5324,9 @@ static void beiscsi_remove(struct pci_dev *pcidev) } beiscsi_destroy_def_ifaces(phba); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); iscsi_boot_destroy_kset(phba->boot_kset); iscsi_host_remove(phba->shost); + beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); pci_disable_pcie_error_reporting(pcidev); @@ -5336,23 +5335,6 @@ static void beiscsi_remove(struct pci_dev *pcidev) pci_disable_device(pcidev); } -static void beiscsi_shutdown(struct pci_dev *pcidev) -{ - - struct beiscsi_hba *phba = NULL; - - phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); - if (!phba) { - dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n"); - return; - } - - phba->state = BE_ADAPTER_STATE_SHUTDOWN; - iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session); - beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); - pci_disable_device(pcidev); -} - static void beiscsi_msix_enable(struct beiscsi_hba *phba) { int i, status; @@ -5673,6 +5655,9 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto hba_free; } + /* +* 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, @@ -5861,7 +5846,6 @@ static struct pci_driver beiscsi_pci_driver = { .name = DRV_NAME, .probe = beiscsi_dev_probe, .remove = beiscsi_remove, - .shutdown = beiscsi_shutdown, .id_table = beiscsi_pci_id_table, .err_handler = &beiscsi_eeh_handlers }; diff --git a
[PATCH v3 10/17] be2iscsi: Add FW config validation
System crash in I+T card personality Fix to add validation for ULP in initiator mode, physical port number, and supported queue, icd, cid counts. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/be2iscsi/be_main.h | 2 + drivers/scsi/be2iscsi/be_mgmt.c | 188 ++-- 3 files changed, 125 insertions(+), 67 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 8967e05..a665e6a 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5670,6 +5670,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, goto free_port; } mgmt_get_port_name(&phba->ctrl, phba); + beiscsi_get_params(phba); if (enable_msix) find_num_cpus(phba); @@ -5687,7 +5688,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, } phba->shost->max_id = phba->params.cxns_per_ctrl; - beiscsi_get_params(phba); phba->shost->can_queue = phba->params.ios_per_ctrl; ret = beiscsi_init_port(phba); if (ret < 0) { diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c09082a..f89861b 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -397,7 +397,9 @@ struct beiscsi_hba { * group together since they are used most frequently * for cid to cri conversion */ +#define BEISCSI_PHYS_PORT_MAX 4 unsigned int phys_port; + /* valid values of phys_port id are 0, 1, 2, 3 */ unsigned int eqid_count; unsigned int cqid_count; unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT]; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 5aae153..3eea8b8 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -373,90 +373,146 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) { struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); - struct be_fw_cfg *req = embedded_payload(wrb); - int status = 0; + struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); + uint32_t cid_count, icd_count; + int status = -EINVAL; + uint8_t ulp_num = 0; mutex_lock(&ctrl->mbox_lock); memset(wrb, 0, sizeof(*wrb)); + be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); - - be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, EMBED_MBX_MAX_PAYLOAD_SIZE); - status = be_mbox_notify(ctrl); - if (!status) { - uint8_t ulp_num = 0; - struct be_fw_cfg *pfw_cfg; - pfw_cfg = req; - if (!is_chip_be2_be3r(phba)) { - phba->fw_config.eqid_count = pfw_cfg->eqid_count; - phba->fw_config.cqid_count = pfw_cfg->cqid_count; + if (be_mbox_notify(ctrl)) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : Failed in mgmt_get_fw_config\n"); + goto fail_init; + } - beiscsi_log(phba, KERN_INFO, - BEISCSI_LOG_INIT, - "BG_%d : EQ_Count : %d CQ_Count : %d\n", - phba->fw_config.eqid_count, + /* FW response formats depend on port id */ + phba->fw_config.phys_port = pfw_cfg->phys_port; + if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : invalid physical port id %d\n", + phba->fw_config.phys_port); + goto fail_init; + } + + /* populate and check FW config against min and max values */ + if (!is_chip_be2_be3r(phba)) { + phba->fw_config.eqid_count = pfw_cfg->eqid_count; + phba->fw_config.cqid_count = pfw_cfg->cqid_count; + if (phba->fw_config.eqid_count == 0 || + phba->fw_config.eqid_count > 2048) { + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, + "BG_%d : invalid EQ count %d\n", + phba->fw_config.eqid_count); + goto fail_init; + } + if (phba->fw_config.cqid_count == 0 || + phba->fw_config.c
[PATCH v3 14/17] be2iscsi: Fix to process 25G link speed info from FW
Async link event provides port_speed info. Cache the port_speed info and use the same to report in ISCSI_HOST_PARAM_PORT_SPEED query. Removed link status query IOCTL used to do the same. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_cmds.c | 1 + drivers/scsi/be2iscsi/be_cmds.h | 35 ++- drivers/scsi/be2iscsi/be_iscsi.c | 39 +-- drivers/scsi/be2iscsi/be_main.h | 1 + drivers/scsi/be2iscsi/be_mgmt.c | 28 5 files changed, 21 insertions(+), 83 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index b294e54..cd14d26 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -408,6 +408,7 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) static void beiscsi_async_link_state_process(struct beiscsi_hba *phba, struct be_async_event_link_state *evt) { + phba->port_speed = evt->port_speed; if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && (evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) { diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 724974e..a194066 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -153,12 +153,21 @@ struct be_async_event_link_state { u8 physical_port; u8 port_link_status; u8 port_duplex; +/* BE2ISCSI_LINK_SPEED_ZERO0x00 - no link */ +#define BE2ISCSI_LINK_SPEED_10MBPS 0x01 +#define BE2ISCSI_LINK_SPEED_100MBPS0x02 +#define BE2ISCSI_LINK_SPEED_1GBPS 0x03 +#define BE2ISCSI_LINK_SPEED_10GBPS 0x04 +#define BE2ISCSI_LINK_SPEED_25GBPS 0x06 +#define BE2ISCSI_LINK_SPEED_40GBPS 0x07 u8 port_speed; #define BEISCSI_PHY_LINK_FAULT_NONE0x00 #define BEISCSI_PHY_LINK_FAULT_LOCAL 0x01 #define BEISCSI_PHY_LINK_FAULT_REMOTE 0x02 u8 port_fault; - u8 rsvd0[7]; + u8 event_reason; + u16 qos_link_speed; + u32 event_tag; struct be_async_event_trailer trailer; } __packed; @@ -711,29 +720,6 @@ struct be_cmd_hba_name { u8 initiator_alias[BEISCSI_ALIAS_LEN]; } __packed; -struct be_cmd_ntwk_link_status_req { - struct be_cmd_req_hdr hdr; - u32 rsvd0; -} __packed; - -/*** Port Speed Values ***/ -#define BE2ISCSI_LINK_SPEED_ZERO 0x00 -#define BE2ISCSI_LINK_SPEED_10MBPS 0x01 -#define BE2ISCSI_LINK_SPEED_100MBPS0x02 -#define BE2ISCSI_LINK_SPEED_1GBPS 0x03 -#define BE2ISCSI_LINK_SPEED_10GBPS 0x04 -struct be_cmd_ntwk_link_status_resp { - struct be_cmd_resp_hdr hdr; - u8 phys_port; - u8 mac_duplex; - u8 mac_speed; - u8 mac_fault; - u8 mgmt_mac_duplex; - u8 mgmt_mac_speed; - u16 qos_link_speed; - u32 logical_link_speed; -} __packed; - int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, struct be_queue_info *eq, int eq_delay); @@ -752,7 +738,6 @@ int be_poll_mcc(struct be_ctrl_info *ctrl); int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); unsigned int be_cmd_get_initname(struct beiscsi_hba *phba); -unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba); void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 3545721..a3bc5e4 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -766,34 +766,13 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) * beiscsi_get_port_speed - Get the Port Speed from Adapter * @shost : pointer to scsi_host structure * - * returns Success/Failure */ -static int beiscsi_get_port_speed(struct Scsi_Host *shost) +static void beiscsi_get_port_speed(struct Scsi_Host *shost) { - int rc; - unsigned int tag; - struct be_mcc_wrb *wrb; - struct be_cmd_ntwk_link_status_resp *resp; struct beiscsi_hba *phba = iscsi_host_priv(shost); struct iscsi_cls_host *ihost = shost->shost_data; - tag = be_cmd_get_port_speed(phba); - if (!tag) { - beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, - "BS_%d : Getting Port Speed Failed\n"); - -return -EBUSY; - } - rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL); - if (rc) { - beiscsi_log(phba, KERN_ERR, - BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, - "BS_%d : Port Speed MBX Failed\n"); - return rc; - } - resp = embedded_payload(wrb); - - switch (resp->mac_speed) { + switch (phba->port_speed) { case BE2ISCSI_LINK_SPEED_10MBPS:
[PATCH v3 06/17] be2iscsi: Added return value check for mgmt_get_all_if_id
Use of mutex_lock_interruptible can return -EINTR, handle and log the error. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_iscsi.c | 7 --- drivers/scsi/be2iscsi/be_mgmt.c | 10 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index b7087ba..188d83f 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -367,13 +367,14 @@ beiscsi_set_vlan_tag(struct Scsi_Host *shost, struct iscsi_iface_param_info *iface_param) { struct beiscsi_hba *phba = iscsi_host_priv(shost); - int ret = 0; + int ret; /* Get the Interface Handle */ - if (mgmt_get_all_if_id(phba)) { + ret = mgmt_get_all_if_id(phba); + if (ret) { beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : Getting Interface Handle Failed\n"); - return -EIO; + return ret; } switch (iface_param->param) { diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 7f3f8268..7aa7a3c 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1025,8 +1025,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba, uint32_t ip_type; int rc; - if (mgmt_get_all_if_id(phba)) - return -EIO; + rc = mgmt_get_all_if_id(phba); + if (rc) + return rc; ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? BE2_IPV6 : BE2_IPV4 ; @@ -1195,8 +1196,9 @@ int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); int rc; - if (mgmt_get_all_if_id(phba)) - return -EIO; + rc = mgmt_get_all_if_id(phba); + if (rc) + return rc; do { rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 08/17] be2iscsi: Fix VLAN support for IPv6 network
Configuring VLAN parameters through IPv6 interface was not supported in driver. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_iscsi.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 188d83f..c89a025 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -466,6 +466,10 @@ beiscsi_set_ipv6(struct Scsi_Host *shost, ret = mgmt_set_ip(phba, iface_param, NULL, ISCSI_BOOTPROTO_STATIC); break; + case ISCSI_NET_PARAM_VLAN_ENABLED: + case ISCSI_NET_PARAM_VLAN_TAG: + ret = beiscsi_set_vlan_tag(shost, iface_param); + break; default: beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, "BS_%d : Param %d not supported\n", -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 12/17] be2iscsi: Fix IOPOLL implementation
OS not responding when running 2 port traffic on 72 CPUs system. be2iscsi IRQs gets affined to CPU0 when irqbalancer is disabled. be_iopoll processing completions in BLOCK_IOPOLL_SOFTIRQ hogged CPU0. 1. Use budget to exit the polling loop. beiscsi_process_cq didn't honour it. 2. Rearming of EQ is done only after iopoll completes. Signed-off-by: Jitendra Bhivare Reviewed-by: Hannes Reinecke --- drivers/scsi/be2iscsi/be_cmds.c | 2 +- drivers/scsi/be2iscsi/be_iscsi.c | 2 +- drivers/scsi/be2iscsi/be_main.c | 91 ++-- drivers/scsi/be2iscsi/be_main.h | 5 ++- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 1e6a1b6..b294e54 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c @@ -546,7 +546,7 @@ int beiscsi_process_mcc(struct beiscsi_hba *phba) } if (num) - hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1, 0); + hwi_ring_cq_db(phba, phba->ctrl.mcc_obj.cq.id, num, 1); spin_unlock_bh(&phba->ctrl.mcc_cq_lock); return status; diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index c89a025..3545721 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1298,7 +1298,7 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba) for (i = 0; i < phba->num_cpus; i++) { pbe_eq = &phwi_context->be_eq[i]; blk_iopoll_disable(&pbe_eq->iopoll); - beiscsi_process_cq(pbe_eq); + beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC); blk_iopoll_enable(&pbe_eq->iopoll); } } diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index a665e6a..9a86044 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -895,32 +895,21 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) static irqreturn_t be_isr_msix(int irq, void *dev_id) { struct beiscsi_hba *phba; - struct be_eq_entry *eqe = NULL; struct be_queue_info *eq; - struct be_queue_info *cq; - unsigned int num_eq_processed; struct be_eq_obj *pbe_eq; pbe_eq = dev_id; eq = &pbe_eq->q; - cq = pbe_eq->cq; - eqe = queue_tail_node(eq); phba = pbe_eq->phba; - num_eq_processed = 0; - while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] - & EQE_VALID_MASK) { - if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) - blk_iopoll_sched(&pbe_eq->iopoll); - - AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); - queue_tail_inc(eq); - eqe = queue_tail_node(eq); - num_eq_processed++; - } - - if (num_eq_processed) - hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); + /* disable interrupt till iopoll completes */ + hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1); + if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) + blk_iopoll_sched(&pbe_eq->iopoll); + else + beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_IO, + "BM_%d: received event while polling eq %d cq %d\n", + eq->id, pbe_eq->cq->id); return IRQ_HANDLED; } @@ -998,6 +987,7 @@ static irqreturn_t be_isr(int irq, void *dev_id) return IRQ_NONE; } + static int beiscsi_init_irqs(struct beiscsi_hba *phba) { struct pci_dev *pcidev = phba->pcidev; @@ -1072,7 +1062,7 @@ free_msix_irqs: void hwi_ring_cq_db(struct beiscsi_hba *phba, unsigned int id, unsigned int num_processed, - unsigned char rearm, unsigned char event) + unsigned char rearm) { u32 val = 0; @@ -2044,7 +2034,7 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) if (num_processed >= 32) { hwi_ring_cq_db(phba, mcc_cq->id, - num_processed, 0, 0); + num_processed, 0); num_processed = 0; } if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) { @@ -2062,24 +2052,25 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba) } if (num_processed > 0) - hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0); + hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1); } /** * beiscsi_process_cq()- Process the Completion Queue * @pbe_eq: Event Q on which the Completion has come + * @budget: Max number of events to processed * * return
[PATCH 05/28] be2iscsi: Set and return right iface v4/v6 states
ipv4_iface and ipv6_iface fields need to be set to NULL when destroyed. Before creation these are checked. Use these to report correct states. Signed-off-by: Jitendra Bhivare --- drivers/scsi/be2iscsi/be_iscsi.c | 31 +-- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index ab696ec..eab0f4f 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -292,10 +292,14 @@ void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) { - if (phba->ipv6_iface) + if (phba->ipv6_iface) { iscsi_destroy_iface(phba->ipv6_iface); - if (phba->ipv4_iface) + phba->ipv6_iface = NULL; + } + if (phba->ipv4_iface) { iscsi_destroy_iface(phba->ipv4_iface); + phba->ipv4_iface = NULL; + } } static int @@ -406,6 +410,14 @@ beiscsi_set_ipv4(struct Scsi_Host *shost, /* Check the param */ switch (iface_param->param) { + case ISCSI_NET_PARAM_IFACE_ENABLE: + if (iface_param->value[0] == ISCSI_IFACE_ENABLE) + ret = beiscsi_create_ipv4_iface(phba); + else { + iscsi_destroy_iface(phba->ipv4_iface); + phba->ipv4_iface = NULL; + } + break; case ISCSI_NET_PARAM_IPV4_GW: ret = mgmt_set_gateway(phba, iface_param); break; @@ -421,12 +433,6 @@ beiscsi_set_ipv4(struct Scsi_Host *shost, "BS_%d : Invalid BOOTPROTO: %d\n", iface_param->value[0]); break; - case ISCSI_NET_PARAM_IFACE_ENABLE: - if (iface_param->value[0] == ISCSI_IFACE_ENABLE) - ret = beiscsi_create_ipv4_iface(phba); - else - iscsi_destroy_iface(phba->ipv4_iface); - break; case ISCSI_NET_PARAM_IPV4_SUBNET: case ISCSI_NET_PARAM_IPV4_ADDR: ret = beiscsi_set_static_ip(shost, iface_param, @@ -459,7 +465,7 @@ beiscsi_set_ipv6(struct Scsi_Host *shost, ret = beiscsi_create_ipv6_iface(phba); else { iscsi_destroy_iface(phba->ipv6_iface); - ret = 0; + phba->ipv6_iface = NULL; } break; case ISCSI_NET_PARAM_IPV6_ADDR: @@ -620,7 +626,12 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface, len = be2iscsi_get_if_param(phba, iface, param, buf); break; case ISCSI_NET_PARAM_IFACE_ENABLE: - len = sprintf(buf, "enable\n"); + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + len = sprintf(buf, "%s\n", + phba->ipv4_iface ? "enable" : "disable"); + else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) + len = sprintf(buf, "%s\n", + phba->ipv6_iface ? "enable" : "disable"); break; case ISCSI_NET_PARAM_IPV4_GW: memset(&gateway, 0, sizeof(gateway)); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html