diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
| -rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 49 | 
1 files changed, 40 insertions, 9 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 483fb74bc59..b16bb2c9978 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -620,23 +620,40 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,  	uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);  	struct lpfc_scsi_buf *psb, *next_psb;  	unsigned long iflag = 0; +	struct lpfc_iocbq *iocbq; +	int i; -	spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock, iflag); +	spin_lock_irqsave(&phba->hbalock, iflag); +	spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock);  	list_for_each_entry_safe(psb, next_psb,  		&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {  		if (psb->cur_iocbq.sli4_xritag == xri) {  			list_del(&psb->list);  			psb->exch_busy = 0;  			psb->status = IOSTAT_SUCCESS; -			spin_unlock_irqrestore( -				&phba->sli4_hba.abts_scsi_buf_list_lock, -				iflag); +			spin_unlock( +				&phba->sli4_hba.abts_scsi_buf_list_lock); +			spin_unlock_irqrestore(&phba->hbalock, iflag);  			lpfc_release_scsi_buf_s4(phba, psb);  			return;  		}  	} -	spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock, -				iflag); +	spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock); +	for (i = 1; i <= phba->sli.last_iotag; i++) { +		iocbq = phba->sli.iocbq_lookup[i]; + +		if (!(iocbq->iocb_flag &  LPFC_IO_FCP) || +			(iocbq->iocb_flag & LPFC_IO_LIBDFC)) +			continue; +		if (iocbq->sli4_xritag != xri) +			continue; +		psb = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); +		psb->exch_busy = 0; +		spin_unlock_irqrestore(&phba->hbalock, iflag); +		return; + +	} +	spin_unlock_irqrestore(&phba->hbalock, iflag);  }  /** @@ -1006,6 +1023,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)  	struct scatterlist *sgel = NULL;  	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;  	struct ulp_bde64 *bpl = lpfc_cmd->fcp_bpl; +	struct lpfc_iocbq *iocbq = &lpfc_cmd->cur_iocbq;  	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;  	struct ulp_bde64 *data_bde = iocb_cmd->unsli3.fcp_ext.dbde;  	dma_addr_t physaddr; @@ -1056,6 +1074,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)  			physaddr = sg_dma_address(sgel);  			if (phba->sli_rev == 3 &&  			    !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && +			    !(iocbq->iocb_flag & DSS_SECURITY_OP) &&  			    nseg <= LPFC_EXT_DATA_BDE_COUNT) {  				data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;  				data_bde->tus.f.bdeSize = sg_dma_len(sgel); @@ -1082,7 +1101,8 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)  	 * explicitly reinitialized since all iocb memory resources are reused.  	 */  	if (phba->sli_rev == 3 && -	    !(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) { +	    !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && +	    !(iocbq->iocb_flag & DSS_SECURITY_OP)) {  		if (num_bde > LPFC_EXT_DATA_BDE_COUNT) {  			/*  			 * The extended IOCB format can only fit 3 BDE or a BPL. @@ -1107,6 +1127,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)  	} else {  		iocb_cmd->un.fcpi64.bdl.bdeSize =  			((num_bde + 2) * sizeof(struct ulp_bde64)); +		iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1);  	}  	fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); @@ -2079,8 +2100,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,  	if (resp_info & RSP_LEN_VALID) {  		rsplen = be32_to_cpu(fcprsp->rspRspLen); -		if ((rsplen != 0 && rsplen != 4 && rsplen != 8) || -		    (fcprsp->rspInfo3 != RSP_NO_FAILURE)) { +		if (rsplen != 0 && rsplen != 4 && rsplen != 8) {  			lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,  				 "2719 Invalid response length: "  				 "tgt x%x lun x%x cmnd x%x rsplen x%x\n", @@ -2090,6 +2110,17 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,  			host_status = DID_ERROR;  			goto out;  		} +		if (fcprsp->rspInfo3 != RSP_NO_FAILURE) { +			lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, +				 "2757 Protocol failure detected during " +				 "processing of FCP I/O op: " +				 "tgt x%x lun x%x cmnd x%x rspInfo3 x%x\n", +				 cmnd->device->id, +				 cmnd->device->lun, cmnd->cmnd[0], +				 fcprsp->rspInfo3); +			host_status = DID_ERROR; +			goto out; +		}  	}  	if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) {  |