diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 181 |
1 files changed, 118 insertions, 63 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index a94fb9f8bb44..5c7858e735c9 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -995,6 +995,11 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) spin_unlock(&phba->scsi_buf_list_put_lock); } spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, iflag); + + if (lpfc_ndlp_check_qdepth(phba, ndlp) && lpfc_cmd) { + atomic_inc(&ndlp->cmd_pending); + lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH; + } return lpfc_cmd; } /** @@ -1044,6 +1049,11 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, iflag); if (!found) return NULL; + + if (lpfc_ndlp_check_qdepth(phba, ndlp) && lpfc_cmd) { + atomic_inc(&ndlp->cmd_pending); + lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH; + } return lpfc_cmd; } /** @@ -1134,7 +1144,10 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) static void lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) { + if ((psb->flags & LPFC_SBUF_BUMP_QDEPTH) && psb->ndlp) + atomic_dec(&psb->ndlp->cmd_pending); + psb->flags &= ~LPFC_SBUF_BUMP_QDEPTH; phba->lpfc_release_scsi_buf(phba, psb); } @@ -3017,8 +3030,8 @@ out: if (err_type == BGS_GUARD_ERR_MASK) { scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x1); - cmd->result = DRIVER_SENSE << 24 - | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; phba->bg_guard_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9069 BLKGRD: LBA %lx grd_tag error %x != %x\n", @@ -3028,8 +3041,8 @@ out: } else if (err_type == BGS_REFTAG_ERR_MASK) { scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x3); - cmd->result = DRIVER_SENSE << 24 - | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; phba->bg_reftag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, @@ -3040,8 +3053,8 @@ out: } else if (err_type == BGS_APPTAG_ERR_MASK) { scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x2); - cmd->result = DRIVER_SENSE << 24 - | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; phba->bg_apptag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, @@ -3096,7 +3109,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, spin_unlock(&_dump_buf_lock); if (lpfc_bgs_get_invalid_prof(bgstat)) { - cmd->result = ScsiResult(DID_ERROR, 0); + cmd->result = DID_ERROR << 16; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9072 BLKGRD: Invalid BG Profile in cmd" " 0x%x lba 0x%llx blk cnt 0x%x " @@ -3108,7 +3121,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, } if (lpfc_bgs_get_uninit_dif_block(bgstat)) { - cmd->result = ScsiResult(DID_ERROR, 0); + cmd->result = DID_ERROR << 16; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9073 BLKGRD: Invalid BG PDIF Block in cmd" " 0x%x lba 0x%llx blk cnt 0x%x " @@ -3124,8 +3137,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x1); - cmd->result = DRIVER_SENSE << 24 - | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; phba->bg_guard_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, "9055 BLKGRD: Guard Tag error in cmd" @@ -3140,8 +3153,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x3); - cmd->result = DRIVER_SENSE << 24 - | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; phba->bg_reftag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, @@ -3157,8 +3170,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 0x10, 0x2); - cmd->result = DRIVER_SENSE << 24 - | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; phba->bg_apptag_err_cnt++; lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, @@ -3311,12 +3324,13 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) } /* * Setup the first Payload BDE. For FCoE we just key off - * Performance Hints, for FC we utilize fcp_embed_pbde. + * Performance Hints, for FC we use lpfc_enable_pbde. + * We populate words 13-15 of IOCB/WQE. */ if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) || - phba->fcp_embed_pbde) { + phba->cfg_enable_pbde) { bde = (struct ulp_bde64 *) - &(iocb_cmd->unsli3.sli3Words[5]); + &(iocb_cmd->unsli3.sli3Words[5]); bde->addrLow = first_data_sgl->addr_lo; bde->addrHigh = first_data_sgl->addr_hi; bde->tus.f.bdeSize = @@ -3330,6 +3344,13 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) sgl->word2 = le32_to_cpu(sgl->word2); bf_set(lpfc_sli4_sge_last, sgl, 1); sgl->word2 = cpu_to_le32(sgl->word2); + + if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) || + phba->cfg_enable_pbde) { + bde = (struct ulp_bde64 *) + &(iocb_cmd->unsli3.sli3Words[5]); + memset(bde, 0, (sizeof(uint32_t) * 3)); + } } /* @@ -3866,7 +3887,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, } out: - cmnd->result = ScsiResult(host_status, scsi_status); + cmnd->result = host_status << 16 | scsi_status; lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, rsp_iocb); } @@ -4019,7 +4040,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, break; case IOSTAT_NPORT_BSY: case IOSTAT_FABRIC_BSY: - cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0); + cmd->result = DID_TRANSPORT_DISRUPTED << 16; fast_path_evt = lpfc_alloc_fast_evt(phba); if (!fast_path_evt) break; @@ -4053,14 +4074,14 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR || lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) { - cmd->result = ScsiResult(DID_NO_CONNECT, 0); + cmd->result = DID_NO_CONNECT << 16; break; } if (lpfc_cmd->result == IOERR_INVALID_RPI || lpfc_cmd->result == IOERR_NO_RESOURCES || lpfc_cmd->result == IOERR_ABORT_REQUESTED || lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) { - cmd->result = ScsiResult(DID_REQUEUE, 0); + cmd->result = DID_REQUEUE << 16; break; } if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || @@ -4094,16 +4115,16 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, } /* else: fall through */ default: - cmd->result = ScsiResult(DID_ERROR, 0); + cmd->result = DID_ERROR << 16; break; } if (!pnode || !NLP_CHK_NODE_ACT(pnode) || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) - cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, - SAM_STAT_BUSY); + cmd->result = DID_TRANSPORT_DISRUPTED << 16 | + SAM_STAT_BUSY; } else - cmd->result = ScsiResult(DID_OK, 0); + cmd->result = DID_OK << 16; if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) { uint32_t *lp = (uint32_t *)cmd->sense_buffer; @@ -4122,7 +4143,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) { spin_lock_irqsave(shost->host_lock, flags); if (pnode && NLP_CHK_NODE_ACT(pnode)) { - atomic_dec(&pnode->cmd_pending); if (pnode->cmd_qdepth > atomic_read(&pnode->cmd_pending) && (atomic_read(&pnode->cmd_pending) > @@ -4135,8 +4155,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, pnode->last_change_time = jiffies; } spin_unlock_irqrestore(shost->host_lock, flags); - } else if (pnode && NLP_CHK_NODE_ACT(pnode)) { - atomic_dec(&pnode->cmd_pending); } lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); @@ -4530,6 +4548,11 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) int err; rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + + /* sanity check on references */ + if (unlikely(!rdata) || unlikely(!rport)) + goto out_fail_command; + err = fc_remote_port_chkready(rport); if (err) { cmnd->result = err; @@ -4555,33 +4578,36 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) */ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) goto out_tgt_busy; - if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) { - lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR, - "3377 Target Queue Full, scsi Id:%d Qdepth:%d" - " Pending command:%d" - " WWNN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, " - " WWPN:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - ndlp->nlp_sid, ndlp->cmd_qdepth, - atomic_read(&ndlp->cmd_pending), - ndlp->nlp_nodename.u.wwn[0], - ndlp->nlp_nodename.u.wwn[1], - ndlp->nlp_nodename.u.wwn[2], - ndlp->nlp_nodename.u.wwn[3], - ndlp->nlp_nodename.u.wwn[4], - ndlp->nlp_nodename.u.wwn[5], - ndlp->nlp_nodename.u.wwn[6], - ndlp->nlp_nodename.u.wwn[7], - ndlp->nlp_portname.u.wwn[0], - ndlp->nlp_portname.u.wwn[1], - ndlp->nlp_portname.u.wwn[2], - ndlp->nlp_portname.u.wwn[3], - ndlp->nlp_portname.u.wwn[4], - ndlp->nlp_portname.u.wwn[5], - ndlp->nlp_portname.u.wwn[6], - ndlp->nlp_portname.u.wwn[7]); - goto out_tgt_busy; + if (lpfc_ndlp_check_qdepth(phba, ndlp)) { + if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP_ERROR, + "3377 Target Queue Full, scsi Id:%d " + "Qdepth:%d Pending command:%d" + " WWNN:%02x:%02x:%02x:%02x:" + "%02x:%02x:%02x:%02x, " + " WWPN:%02x:%02x:%02x:%02x:" + "%02x:%02x:%02x:%02x", + ndlp->nlp_sid, ndlp->cmd_qdepth, + atomic_read(&ndlp->cmd_pending), + ndlp->nlp_nodename.u.wwn[0], + ndlp->nlp_nodename.u.wwn[1], + ndlp->nlp_nodename.u.wwn[2], + ndlp->nlp_nodename.u.wwn[3], + ndlp->nlp_nodename.u.wwn[4], + ndlp->nlp_nodename.u.wwn[5], + ndlp->nlp_nodename.u.wwn[6], + ndlp->nlp_nodename.u.wwn[7], + ndlp->nlp_portname.u.wwn[0], + ndlp->nlp_portname.u.wwn[1], + ndlp->nlp_portname.u.wwn[2], + ndlp->nlp_portname.u.wwn[3], + ndlp->nlp_portname.u.wwn[4], + ndlp->nlp_portname.u.wwn[5], + ndlp->nlp_portname.u.wwn[6], + ndlp->nlp_portname.u.wwn[7]); + goto out_tgt_busy; + } } - atomic_inc(&ndlp->cmd_pending); lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp); if (lpfc_cmd == NULL) { @@ -4599,6 +4625,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) */ lpfc_cmd->pCmd = cmnd; lpfc_cmd->rdata = rdata; + lpfc_cmd->ndlp = ndlp; lpfc_cmd->timeout = 0; lpfc_cmd->start_time = jiffies; cmnd->host_scribble = (unsigned char *)lpfc_cmd; @@ -4681,7 +4708,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); lpfc_release_scsi_buf(phba, lpfc_cmd); out_host_busy: - atomic_dec(&ndlp->cmd_pending); return SCSI_MLQUEUE_HOST_BUSY; out_tgt_busy: @@ -4714,7 +4740,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) struct lpfc_scsi_buf *lpfc_cmd; IOCB_t *cmd, *icmd; int ret = SUCCESS, status = 0; - struct lpfc_sli_ring *pring_s4; + struct lpfc_sli_ring *pring_s4 = NULL; int ret_val; unsigned long flags; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); @@ -4744,8 +4770,25 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) } iocb = &lpfc_cmd->cur_iocbq; + if (phba->sli_rev == LPFC_SLI_REV4) { + if (!(phba->cfg_fof) || + (!(iocb->iocb_flag & LPFC_IO_FOF))) { + pring_s4 = + phba->sli4_hba.fcp_wq[iocb->hba_wqidx]->pring; + } else { + iocb->hba_wqidx = 0; + pring_s4 = phba->sli4_hba.oas_wq->pring; + } + if (!pring_s4) { + ret = FAILED; + goto out_unlock; + } + spin_lock(&pring_s4->ring_lock); + } /* the command is in process of being cancelled */ if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) { + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3169 SCSI Layer abort requested I/O has been " @@ -4759,6 +4802,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) * see the completion before the eh fired. Just return SUCCESS. */ if (lpfc_cmd->pCmd != cmnd) { + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3170 SCSI Layer abort requested I/O has been " "completed by LLD.\n"); @@ -4771,6 +4816,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "3389 SCSI Layer I/O Abort Request is pending\n"); + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); spin_unlock_irqrestore(&phba->hbalock, flags); goto wait_for_cmpl; } @@ -4778,6 +4825,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) abtsiocb = __lpfc_sli_get_iocbq(phba); if (abtsiocb == NULL) { ret = FAILED; + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock(&pring_s4->ring_lock); goto out_unlock; } @@ -4815,14 +4864,9 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; abtsiocb->vport = vport; + lpfc_cmd->waitq = &waitq; if (phba->sli_rev == LPFC_SLI_REV4) { - pring_s4 = lpfc_sli4_calc_ring(phba, abtsiocb); - if (pring_s4 == NULL) { - ret = FAILED; - goto out_unlock; - } /* Note: both hbalock and ring_lock must be set here */ - spin_lock(&pring_s4->ring_lock); ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, abtsiocb, 0); spin_unlock(&pring_s4->ring_lock); @@ -4835,6 +4879,17 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) if (ret_val == IOCB_ERROR) { + if (phba->sli_rev == LPFC_SLI_REV4) + spin_lock_irqsave(&pring_s4->ring_lock, flags); + else + spin_lock_irqsave(&phba->hbalock, flags); + /* Indicate the IO is not being aborted by the driver. */ + iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; + lpfc_cmd->waitq = NULL; + if (phba->sli_rev == LPFC_SLI_REV4) + spin_unlock_irqrestore(&pring_s4->ring_lock, flags); + else + spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_sli_release_iocbq(phba, abtsiocb); ret = FAILED; goto out; @@ -4845,7 +4900,6 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) &phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ); wait_for_cmpl: - lpfc_cmd->waitq = &waitq; /* Wait for abort to complete */ wait_event_timeout(waitq, (lpfc_cmd->pCmd != cmnd), @@ -5006,6 +5060,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo; lpfc_cmd->rdata = rdata; lpfc_cmd->pCmd = cmnd; + lpfc_cmd->ndlp = pnode; status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id, task_mgmt_cmd); |