diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 458 |
1 files changed, 275 insertions, 183 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c5614cfcc6e9..22f17087883c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -95,7 +95,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) return -ENOMEM; /* set consumption flag every once in a while */ if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL)) - bf_set(lpfc_wqe_gen_wqec, &wqe->generic, 1); + bf_set(wqe_wqec, &wqe->generic.wqe_com, 1); lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); @@ -1735,6 +1735,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) struct lpfc_vport *vport = pmb->vport; struct lpfc_dmabuf *mp; struct lpfc_nodelist *ndlp; + struct Scsi_Host *shost; uint16_t rpi, vpi; int rc; @@ -1746,7 +1747,8 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } if ((pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) && - (phba->sli_rev == LPFC_SLI_REV4)) + (phba->sli_rev == LPFC_SLI_REV4) && + (pmb->u.mb.un.varUnregLogin.rsvd1 == 0x0)) lpfc_sli4_free_rpi(phba, pmb->u.mb.un.varUnregLogin.rpi); /* @@ -1765,16 +1767,14 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) return; } - /* Unreg VPI, if the REG_VPI succeed after VLink failure */ if ((pmb->u.mb.mbxCommand == MBX_REG_VPI) && !(phba->pport->load_flag & FC_UNLOADING) && !pmb->u.mb.mbxStatus) { - lpfc_unreg_vpi(phba, pmb->u.mb.un.varRegVpi.vpi, pmb); - pmb->vport = vport; - pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); - if (rc != MBX_NOT_FINISHED) - return; + shost = lpfc_shost_from_vport(vport); + spin_lock_irq(shost->host_lock); + vport->vpi_state |= LPFC_VPI_REGISTERED; + vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; + spin_unlock_irq(shost->host_lock); } if (pmb->u.mb.mbxCommand == MBX_REG_LOGIN64) { @@ -5921,7 +5921,7 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, * lpfc_sli4_scmd_to_wqidx_distr - scsi command to SLI4 WQ index distribution * @phba: Pointer to HBA context object. * - * This routine performs a round robin SCSI command to SLI4 FCP WQ index + * This routine performs a roundrobin SCSI command to SLI4 FCP WQ index * distribution. This is called by __lpfc_sli_issue_iocb_s4() with the hbalock * held. * @@ -5965,7 +5965,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, uint16_t abrt_iotag; struct lpfc_iocbq *abrtiocbq; struct ulp_bde64 *bpl = NULL; - uint32_t els_id = ELS_ID_DEFAULT; + uint32_t els_id = LPFC_ELS_ID_DEFAULT; int numBdes, i; struct ulp_bde64 bde; @@ -5982,7 +5982,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe)); abort_tag = (uint32_t) iocbq->iotag; xritag = iocbq->sli4_xritag; - wqe->words[7] = 0; /* The ct field has moved so reset */ + wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */ /* words0-2 bpl convert bde */ if (iocbq->iocb.un.genreq64.bdl.bdeFlags == BUFF_TYPE_BLP_64) { numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize / @@ -6033,109 +6033,117 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, * contains the FCFI and remote N_Port_ID is * in word 5. */ - ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); - bf_set(lpfc_wqe_gen_context, &wqe->generic, - iocbq->iocb.ulpContext); - - bf_set(lpfc_wqe_gen_ct, &wqe->generic, ct); - bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); + bf_set(wqe_ctxt_tag, &wqe->els_req.wqe_com, + iocbq->iocb.ulpContext); + bf_set(wqe_ct, &wqe->els_req.wqe_com, ct); + bf_set(wqe_pu, &wqe->els_req.wqe_com, 0); /* CCP CCPE PV PRI in word10 were set in the memcpy */ - if (command_type == ELS_COMMAND_FIP) { els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK) >> LPFC_FIP_ELS_ID_SHIFT); } - bf_set(lpfc_wqe_gen_els_id, &wqe->generic, els_id); - + bf_set(wqe_els_id, &wqe->els_req.wqe_com, els_id); + bf_set(wqe_dbde, &wqe->els_req.wqe_com, 1); + bf_set(wqe_iod, &wqe->els_req.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_qosd, &wqe->els_req.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->els_req.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->els_req.wqe_com, 0); break; case CMD_XMIT_SEQUENCE64_CX: - bf_set(lpfc_wqe_gen_context, &wqe->generic, - iocbq->iocb.un.ulpWord[3]); - wqe->generic.word3 = 0; - bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); + bf_set(wqe_ctxt_tag, &wqe->xmit_sequence.wqe_com, + iocbq->iocb.un.ulpWord[3]); + bf_set(wqe_rcvoxid, &wqe->xmit_sequence.wqe_com, + iocbq->iocb.ulpContext); /* The entire sequence is transmitted for this IOCB */ xmit_len = total_len; cmnd = CMD_XMIT_SEQUENCE64_CR; case CMD_XMIT_SEQUENCE64_CR: - /* word3 iocb=io_tag32 wqe=payload_offset */ - /* payload offset used for multilpe outstanding - * sequences on the same exchange - */ - wqe->words[3] = 0; + /* word3 iocb=io_tag32 wqe=reserved */ + wqe->xmit_sequence.rsvd3 = 0; /* word4 relative_offset memcpy */ /* word5 r_ctl/df_ctl memcpy */ - bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); + bf_set(wqe_pu, &wqe->xmit_sequence.wqe_com, 0); + bf_set(wqe_dbde, &wqe->xmit_sequence.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_sequence.wqe_com, + LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->xmit_sequence.wqe_com, + LPFC_WQE_LENLOC_WORD12); + bf_set(wqe_ebde_cnt, &wqe->xmit_sequence.wqe_com, 0); wqe->xmit_sequence.xmit_len = xmit_len; command_type = OTHER_COMMAND; break; case CMD_XMIT_BCAST64_CN: - /* word3 iocb=iotag32 wqe=payload_len */ - wqe->words[3] = 0; /* no definition for this in wqe */ + /* word3 iocb=iotag32 wqe=seq_payload_len */ + wqe->xmit_bcast64.seq_payload_len = xmit_len; /* word4 iocb=rsvd wqe=rsvd */ /* word5 iocb=rctl/type/df_ctl wqe=rctl/type/df_ctl memcpy */ /* word6 iocb=ctxt_tag/io_tag wqe=ctxt_tag/xri */ - bf_set(lpfc_wqe_gen_ct, &wqe->generic, + bf_set(wqe_ct, &wqe->xmit_bcast64.wqe_com, ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); + bf_set(wqe_dbde, &wqe->xmit_bcast64.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_bcast64.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->xmit_bcast64.wqe_com, + LPFC_WQE_LENLOC_WORD3); + bf_set(wqe_ebde_cnt, &wqe->xmit_bcast64.wqe_com, 0); break; case CMD_FCP_IWRITE64_CR: command_type = FCP_COMMAND_DATA_OUT; - /* The struct for wqe fcp_iwrite has 3 fields that are somewhat - * confusing. - * word3 is payload_len: byte offset to the sgl entry for the - * fcp_command. - * word4 is total xfer len, same as the IOCB->ulpParameter. - * word5 is initial xfer len 0 = wait for xfer-ready - */ - - /* Always wait for xfer-ready before sending data */ - wqe->fcp_iwrite.initial_xfer_len = 0; - /* word 4 (xfer length) should have been set on the memcpy */ - - /* allow write to fall through to read */ + /* word3 iocb=iotag wqe=payload_offset_len */ + /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ + wqe->fcp_iwrite.payload_offset_len = + xmit_len + sizeof(struct fcp_rsp); + /* word4 iocb=parameter wqe=total_xfer_length memcpy */ + /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ + bf_set(wqe_erp, &wqe->fcp_iwrite.wqe_com, + iocbq->iocb.ulpFCP2Rcvy); + bf_set(wqe_lnk, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpXS); + /* Always open the exchange */ + bf_set(wqe_xc, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, + LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_ebde_cnt, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU); + break; case CMD_FCP_IREAD64_CR: - /* FCP_CMD is always the 1st sgl entry */ - wqe->fcp_iread.payload_len = + /* word3 iocb=iotag wqe=payload_offset_len */ + /* Add the FCP_CMD and FCP_RSP sizes to get the offset */ + wqe->fcp_iread.payload_offset_len = xmit_len + sizeof(struct fcp_rsp); - - /* word 4 (xfer length) should have been set on the memcpy */ - - bf_set(lpfc_wqe_gen_erp, &wqe->generic, - iocbq->iocb.ulpFCP2Rcvy); - bf_set(lpfc_wqe_gen_lnk, &wqe->generic, iocbq->iocb.ulpXS); - /* The XC bit and the XS bit are similar. The driver never - * tracked whether or not the exchange was previouslly open. - * XC = Exchange create, 0 is create. 1 is already open. - * XS = link cmd: 1 do not close the exchange after command. - * XS = 0 close exchange when command completes. - * The only time we would not set the XC bit is when the XS bit - * is set and we are sending our 2nd or greater command on - * this exchange. - */ + /* word4 iocb=parameter wqe=total_xfer_length memcpy */ + /* word5 iocb=initial_xfer_len wqe=initial_xfer_len memcpy */ + bf_set(wqe_erp, &wqe->fcp_iread.wqe_com, + iocbq->iocb.ulpFCP2Rcvy); + bf_set(wqe_lnk, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpXS); /* Always open the exchange */ bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0); - - wqe->words[10] &= 0xffff0000; /* zero out ebde count */ - bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU); - break; + bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, + LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_ebde_cnt, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU); + break; case CMD_FCP_ICMND64_CR: + /* word3 iocb=IO_TAG wqe=reserved */ + wqe->fcp_icmd.rsrvd3 = 0; + bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); /* Always open the exchange */ - bf_set(wqe_xc, &wqe->fcp_iread.wqe_com, 0); - - wqe->words[4] = 0; - wqe->words[10] &= 0xffff0000; /* zero out ebde count */ - bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); + bf_set(wqe_xc, &wqe->fcp_icmd.wqe_com, 0); + bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, + LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->fcp_icmd.wqe_com, 0); break; case CMD_GEN_REQUEST64_CR: - /* word3 command length is described as byte offset to the - * rsp_data. Would always be 16, sizeof(struct sli4_sge) - * sgl[0] = cmnd - * sgl[1] = rsp. - * - */ - wqe->gen_req.command_len = xmit_len; - /* Word4 parameter copied in the memcpy */ - /* Word5 [rctl, type, df_ctl, la] copied in memcpy */ + /* word3 iocb=IO_TAG wqe=request_payload_len */ + wqe->gen_req.request_payload_len = xmit_len; + /* word4 iocb=parameter wqe=relative_offset memcpy */ + /* word5 [rctl, type, df_ctl, la] copied in memcpy */ /* word6 context tag copied in memcpy */ if (iocbq->iocb.ulpCt_h || iocbq->iocb.ulpCt_l) { ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l); @@ -6144,31 +6152,39 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, ct, iocbq->iocb.ulpCommand); return IOCB_ERROR; } - bf_set(lpfc_wqe_gen_ct, &wqe->generic, 0); - bf_set(wqe_tmo, &wqe->gen_req.wqe_com, - iocbq->iocb.ulpTimeout); - - bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU); + bf_set(wqe_ct, &wqe->gen_req.wqe_com, 0); + bf_set(wqe_tmo, &wqe->gen_req.wqe_com, iocbq->iocb.ulpTimeout); + bf_set(wqe_pu, &wqe->gen_req.wqe_com, iocbq->iocb.ulpPU); + bf_set(wqe_dbde, &wqe->gen_req.wqe_com, 1); + bf_set(wqe_iod, &wqe->gen_req.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_qosd, &wqe->gen_req.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->gen_req.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_ebde_cnt, &wqe->gen_req.wqe_com, 0); command_type = OTHER_COMMAND; break; case CMD_XMIT_ELS_RSP64_CX: /* words0-2 BDE memcpy */ - /* word3 iocb=iotag32 wqe=rsvd */ - wqe->words[3] = 0; + /* word3 iocb=iotag32 wqe=response_payload_len */ + wqe->xmit_els_rsp.response_payload_len = xmit_len; /* word4 iocb=did wge=rsvd. */ - wqe->words[4] = 0; + wqe->xmit_els_rsp.rsvd4 = 0; /* word5 iocb=rsvd wge=did */ bf_set(wqe_els_did, &wqe->xmit_els_rsp.wqe_dest, iocbq->iocb.un.elsreq64.remoteID); - - bf_set(lpfc_wqe_gen_ct, &wqe->generic, - ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); - - bf_set(lpfc_wqe_gen_pu, &wqe->generic, iocbq->iocb.ulpPU); - bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); + bf_set(wqe_ct, &wqe->xmit_els_rsp.wqe_com, + ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); + bf_set(wqe_pu, &wqe->xmit_els_rsp.wqe_com, iocbq->iocb.ulpPU); + bf_set(wqe_rcvoxid, &wqe->xmit_els_rsp.wqe_com, + iocbq->iocb.ulpContext); if (!iocbq->iocb.ulpCt_h && iocbq->iocb.ulpCt_l) - bf_set(lpfc_wqe_gen_context, &wqe->generic, + bf_set(wqe_ctxt_tag, &wqe->xmit_els_rsp.wqe_com, iocbq->vport->vpi + phba->vpi_base); + bf_set(wqe_dbde, &wqe->xmit_els_rsp.wqe_com, 1); + bf_set(wqe_iod, &wqe->xmit_els_rsp.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_qosd, &wqe->xmit_els_rsp.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->xmit_els_rsp.wqe_com, + LPFC_WQE_LENLOC_WORD3); + bf_set(wqe_ebde_cnt, &wqe->xmit_els_rsp.wqe_com, 0); command_type = OTHER_COMMAND; break; case CMD_CLOSE_XRI_CN: @@ -6193,15 +6209,19 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, else bf_set(abort_cmd_ia, &wqe->abort_cmd, 0); bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); - wqe->words[5] = 0; - bf_set(lpfc_wqe_gen_ct, &wqe->generic, + /* word5 iocb=CONTEXT_TAG|IO_TAG wqe=reserved */ + wqe->abort_cmd.rsrvd5 = 0; + bf_set(wqe_ct, &wqe->abort_cmd.wqe_com, ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l)); abort_tag = iocbq->iocb.un.acxri.abortIoTag; /* * The abort handler will send us CMD_ABORT_XRI_CN or * CMD_CLOSE_XRI_CN and the fw only accepts CMD_ABORT_XRI_CX */ - bf_set(lpfc_wqe_gen_command, &wqe->generic, CMD_ABORT_XRI_CX); + bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX); + bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, + LPFC_WQE_LENLOC_NONE); cmnd = CMD_ABORT_XRI_CX; command_type = OTHER_COMMAND; xritag = 0; @@ -6235,18 +6255,14 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1); bf_set(wqe_ctxt_tag, &wqe->xmit_bls_rsp.wqe_com, iocbq->iocb.ulpContext); + bf_set(wqe_qosd, &wqe->xmit_bls_rsp.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->xmit_bls_rsp.wqe_com, + LPFC_WQE_LENLOC_NONE); /* Overwrite the pre-set comnd type with OTHER_COMMAND */ command_type = OTHER_COMMAND; break; case CMD_XRI_ABORTED_CX: case CMD_CREATE_XRI_CR: /* Do we expect to use this? */ - /* words0-2 are all 0's no bde */ - /* word3 and word4 are rsvrd */ - wqe->words[3] = 0; - wqe->words[4] = 0; - /* word5 iocb=rsvd wge=did */ - /* There is no remote port id in the IOCB? */ - /* Let this fall through and fail */ case CMD_IOCB_FCP_IBIDIR64_CR: /* bidirectional xfer */ case CMD_FCP_TSEND64_CX: /* Target mode send xfer-ready */ case CMD_FCP_TRSP64_CX: /* Target mode rcv */ @@ -6257,16 +6273,14 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.ulpCommand); return IOCB_ERROR; break; - } - bf_set(lpfc_wqe_gen_xri, &wqe->generic, xritag); - bf_set(lpfc_wqe_gen_request_tag, &wqe->generic, iocbq->iotag); - wqe->generic.abort_tag = abort_tag; - bf_set(lpfc_wqe_gen_cmd_type, &wqe->generic, command_type); - bf_set(lpfc_wqe_gen_command, &wqe->generic, cmnd); - bf_set(lpfc_wqe_gen_class, &wqe->generic, iocbq->iocb.ulpClass); - bf_set(lpfc_wqe_gen_cq_id, &wqe->generic, LPFC_WQE_CQ_ID_DEFAULT); - + bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag); + bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag); + wqe->generic.wqe_com.abort_tag = abort_tag; + bf_set(wqe_cmd_type, &wqe->generic.wqe_com, command_type); + bf_set(wqe_cmnd, &wqe->generic.wqe_com, cmnd); + bf_set(wqe_class, &wqe->generic.wqe_com, iocbq->iocb.ulpClass); + bf_set(wqe_cqid, &wqe->generic.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); return 0; } @@ -7257,25 +7271,26 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_sli_issue_abort_iotag - Abort function for a command iocb + * lpfc_sli_abort_iotag_issue - Issue abort for a command iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @cmdiocb: Pointer to driver command iocb object. * - * This function issues an abort iocb for the provided command - * iocb. This function is called with hbalock held. - * The function returns 0 when it fails due to memory allocation - * failure or when the command iocb is an abort request. + * This function issues an abort iocb for the provided command iocb down to + * the port. Other than the case the outstanding command iocb is an abort + * request, this function issues abort out unconditionally. This function is + * called with hbalock held. The function returns 0 when it fails due to + * memory allocation failure or when the command iocb is an abort request. **/ -int -lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, +static int +lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_iocbq *cmdiocb) { struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_iocbq *abtsiocbp; IOCB_t *icmd = NULL; IOCB_t *iabt = NULL; - int retval = IOCB_ERROR; + int retval; /* * There are certain command types we don't want to abort. And we @@ -7288,18 +7303,6 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) return 0; - /* If we're unloading, don't abort iocb on the ELS ring, but change the - * callback so that nothing happens when it finishes. - */ - if ((vport->load_flag & FC_UNLOADING) && - (pring->ringno == LPFC_ELS_RING)) { - if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; - else - cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; - goto abort_iotag_exit; - } - /* issue ABTS for this IOCB based on iotag */ abtsiocbp = __lpfc_sli_get_iocbq(phba); if (abtsiocbp == NULL) @@ -7344,6 +7347,63 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (retval) __lpfc_sli_release_iocbq(phba, abtsiocbp); + + /* + * Caller to this routine should check for IOCB_ERROR + * and handle it properly. This routine no longer removes + * iocb off txcmplq and call compl in case of IOCB_ERROR. + */ + return retval; +} + +/** + * lpfc_sli_issue_abort_iotag - Abort function for a command iocb + * @phba: Pointer to HBA context object. + * @pring: Pointer to driver SLI ring object. + * @cmdiocb: Pointer to driver command iocb object. + * + * This function issues an abort iocb for the provided command iocb. In case + * of unloading, the abort iocb will not be issued to commands on the ELS + * ring. Instead, the callback function shall be changed to those commands + * so that nothing happens when them finishes. This function is called with + * hbalock held. The function returns 0 when the command iocb is an abort + * request. + **/ +int +lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + struct lpfc_iocbq *cmdiocb) +{ + struct lpfc_vport *vport = cmdiocb->vport; + int retval = IOCB_ERROR; + IOCB_t *icmd = NULL; + + /* + * There are certain command types we don't want to abort. And we + * don't want to abort commands that are already in the process of + * being aborted. + */ + icmd = &cmdiocb->iocb; + if (icmd->ulpCommand == CMD_ABORT_XRI_CN || + icmd->ulpCommand == CMD_CLOSE_XRI_CN || + (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) + return 0; + + /* + * If we're unloading, don't abort iocb on the ELS ring, but change + * the callback so that nothing happens when it finishes. + */ + if ((vport->load_flag & FC_UNLOADING) && + (pring->ringno == LPFC_ELS_RING)) { + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; + else + cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; + goto abort_iotag_exit; + } + + /* Now, we try to issue the abort to the cmdiocb out */ + retval = lpfc_sli_abort_iotag_issue(phba, pring, cmdiocb); + abort_iotag_exit: /* * Caller to this routine should check for IOCB_ERROR @@ -7354,6 +7414,62 @@ abort_iotag_exit: } /** + * lpfc_sli_iocb_ring_abort - Unconditionally abort all iocbs on an iocb ring + * @phba: Pointer to HBA context object. + * @pring: Pointer to driver SLI ring object. + * + * This function aborts all iocbs in the given ring and frees all the iocb + * objects in txq. This function issues abort iocbs unconditionally for all + * the iocb commands in txcmplq. The iocbs in the txcmplq is not guaranteed + * to complete before the return of this function. The caller is not required + * to hold any locks. + **/ +static void +lpfc_sli_iocb_ring_abort(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) +{ + LIST_HEAD(completions); + struct lpfc_iocbq *iocb, *next_iocb; + + if (pring->ringno == LPFC_ELS_RING) + lpfc_fabric_abort_hba(phba); + + spin_lock_irq(&phba->hbalock); + + /* Take off all the iocbs on txq for cancelling */ + list_splice_init(&pring->txq, &completions); + pring->txq_cnt = 0; + + /* Next issue ABTS for everything on the txcmplq */ + list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) + lpfc_sli_abort_iotag_issue(phba, pring, iocb); + + spin_unlock_irq(&phba->hbalock); + + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); +} + +/** + * lpfc_sli_hba_iocb_abort - Abort all iocbs to an hba. + * @phba: pointer to lpfc HBA data structure. + * + * This routine will abort all pending and outstanding iocbs to an HBA. + **/ +void +lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba) +{ + struct lpfc_sli *psli = &phba->sli; + struct lpfc_sli_ring *pring; + int i; + + for (i = 0; i < psli->num_rings; i++) { + pring = &psli->ring[i]; + lpfc_sli_iocb_ring_abort(phba, pring); + } +} + +/** * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN * @iocbq: Pointer to driver iocb object. * @vport: Pointer to driver virtual port object. @@ -12242,13 +12358,15 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) /* Issue the mailbox command asynchronously */ mboxq->vport = phba->pport; mboxq->mbox_cmpl = lpfc_mbx_cmpl_fcf_scan_read_fcf_rec; + + spin_lock_irq(&phba->hbalock); + phba->hba_flag |= FCF_TS_INPROG; + spin_unlock_irq(&phba->hbalock); + rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) error = -EIO; else { - spin_lock_irq(&phba->hbalock); - phba->hba_flag |= FCF_DISC_INPROGRESS; - spin_unlock_irq(&phba->hbalock); /* Reset eligible FCF count for new scan */ if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) phba->fcf.eligible_fcf_cnt = 0; @@ -12258,21 +12376,21 @@ fail_fcf_scan: if (error) { if (mboxq) lpfc_sli4_mbox_cmd_free(phba, mboxq); - /* FCF scan failed, clear FCF_DISC_INPROGRESS flag */ + /* FCF scan failed, clear FCF_TS_INPROG flag */ spin_lock_irq(&phba->hbalock); - phba->hba_flag &= ~FCF_DISC_INPROGRESS; + phba->hba_flag &= ~FCF_TS_INPROG; spin_unlock_irq(&phba->hbalock); } return error; } /** - * lpfc_sli4_fcf_rr_read_fcf_rec - Read hba fcf record for round robin fcf. + * lpfc_sli4_fcf_rr_read_fcf_rec - Read hba fcf record for roundrobin fcf. * @phba: pointer to lpfc hba data structure. * @fcf_index: FCF table entry offset. * * This routine is invoked to read an FCF record indicated by @fcf_index - * and to use it for FLOGI round robin FCF failover. + * and to use it for FLOGI roundrobin FCF failover. * * Return 0 if the mailbox command is submitted sucessfully, none 0 * otherwise. @@ -12318,7 +12436,7 @@ fail_fcf_read: * @fcf_index: FCF table entry offset. * * This routine is invoked to read an FCF record indicated by @fcf_index to - * determine whether it's eligible for FLOGI round robin failover list. + * determine whether it's eligible for FLOGI roundrobin failover list. * * Return 0 if the mailbox command is submitted sucessfully, none 0 * otherwise. @@ -12364,7 +12482,7 @@ fail_fcf_read: * * This routine is to get the next eligible FCF record index in a round * robin fashion. If the next eligible FCF record index equals to the - * initial round robin FCF record index, LPFC_FCOE_FCF_NEXT_NONE (0xFFFF) + * initial roundrobin FCF record index, LPFC_FCOE_FCF_NEXT_NONE (0xFFFF) * shall be returned, otherwise, the next eligible FCF record's index * shall be returned. **/ @@ -12392,28 +12510,10 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) return LPFC_FCOE_FCF_NEXT_NONE; } - /* Check roundrobin failover index bmask stop condition */ - if (next_fcf_index == phba->fcf.fcf_rr_init_indx) { - if (!(phba->fcf.fcf_flag & FCF_REDISC_RRU)) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FIP, - "2847 Round robin failover FCF index " - "search hit stop condition:x%x\n", - next_fcf_index); - return LPFC_FCOE_FCF_NEXT_NONE; - } - /* The roundrobin failover index bmask updated, start over */ - lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2848 Round robin failover FCF index bmask " - "updated, start over\n"); - spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag &= ~FCF_REDISC_RRU; - spin_unlock_irq(&phba->hbalock); - return phba->fcf.fcf_rr_init_indx; - } - lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2845 Get next round robin failover " - "FCF index x%x\n", next_fcf_index); + "2845 Get next roundrobin failover FCF (x%x)\n", + next_fcf_index); + return next_fcf_index; } @@ -12422,7 +12522,7 @@ lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) * @phba: pointer to lpfc hba data structure. * * This routine sets the FCF record index in to the eligible bmask for - * round robin failover search. It checks to make sure that the index + * roundrobin failover search. It checks to make sure that the index * does not go beyond the range of the driver allocated bmask dimension * before setting the bit. * @@ -12434,22 +12534,16 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) { if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP, - "2610 HBA FCF index reached driver's " - "book keeping dimension: fcf_index:%d, " - "driver_bmask_max:%d\n", + "2610 FCF (x%x) reached driver's book " + "keeping dimension:x%x\n", fcf_index, LPFC_SLI4_FCF_TBL_INDX_MAX); return -EINVAL; } /* Set the eligible FCF record index bmask */ set_bit(fcf_index, phba->fcf.fcf_rr_bmask); - /* Set the roundrobin index bmask updated */ - spin_lock_irq(&phba->hbalock); - phba->fcf.fcf_flag |= FCF_REDISC_RRU; - spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2790 Set FCF index x%x to round robin failover " + "2790 Set FCF (x%x) to roundrobin FCF failover " "bmask\n", fcf_index); return 0; @@ -12460,7 +12554,7 @@ lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) * @phba: pointer to lpfc hba data structure. * * This routine clears the FCF record index from the eligible bmask for - * round robin failover search. It checks to make sure that the index + * roundrobin failover search. It checks to make sure that the index * does not go beyond the range of the driver allocated bmask dimension * before clearing the bit. **/ @@ -12469,9 +12563,8 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) { if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) { lpfc_printf_log(phba, KERN_ERR, LOG_FIP, - "2762 HBA FCF index goes beyond driver's " - "book keeping dimension: fcf_index:%d, " - "driver_bmask_max:%d\n", + "2762 FCF (x%x) reached driver's book " + "keeping dimension:x%x\n", fcf_index, LPFC_SLI4_FCF_TBL_INDX_MAX); return; } @@ -12479,7 +12572,7 @@ lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) clear_bit(fcf_index, phba->fcf.fcf_rr_bmask); lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2791 Clear FCF index x%x from round robin failover " + "2791 Clear FCF (x%x) from roundrobin failover " "bmask\n", fcf_index); } @@ -12530,8 +12623,7 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) } } else { lpfc_printf_log(phba, KERN_INFO, LOG_FIP, - "2775 Start FCF rediscovery quiescent period " - "wait timer before scaning FCF table\n"); + "2775 Start FCF rediscover quiescent timer\n"); /* * Start FCF rediscovery wait timer for pending FCF * before rescan FCF record table. |