Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / lpfc / lpfc_scsi.c
index 483fb74bc5922697f4077635f04121bbaa38d293..b16bb2c9978bce87d1f819a6aa251b39741c7edb 100644 (file)
@@ -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) {