[SCSI] lpfc 8.3.21: RRQ Implementation fixes
[deliverable/linux.git] / drivers / scsi / lpfc / lpfc_scsi.c
index af5498d735e2a42e0656c0c976a754f2cf91c8a3..d482dfc951f3466d5ffd99e072f3cf23db31b2bd 100644 (file)
@@ -608,6 +608,32 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
        return bcnt;
 }
 
+/**
+ * lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport
+ * @vport: pointer to lpfc vport data structure.
+ *
+ * This routine is invoked by the vport cleanup for deletions and the cleanup
+ * for an ndlp on removal.
+ **/
+void
+lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
+{
+       struct lpfc_hba *phba = vport->phba;
+       struct lpfc_scsi_buf *psb, *next_psb;
+       unsigned long iflag = 0;
+
+       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->rdata && psb->rdata->pnode
+                       && psb->rdata->pnode->vport == vport)
+                       psb->rdata = NULL;
+       }
+       spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock);
+       spin_unlock_irqrestore(&phba->hbalock, iflag);
+}
+
 /**
  * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort
  * @phba: pointer to lpfc hba data structure.
@@ -640,7 +666,11 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
                        psb->status = IOSTAT_SUCCESS;
                        spin_unlock(
                                &phba->sli4_hba.abts_scsi_buf_list_lock);
-                       ndlp = psb->rdata->pnode;
+                       if (psb->rdata && psb->rdata->pnode)
+                               ndlp = psb->rdata->pnode;
+                       else
+                               ndlp = NULL;
+
                        rrq_empty = list_empty(&phba->active_rrq_list);
                        spin_unlock_irqrestore(&phba->hbalock, iflag);
                        if (ndlp)
@@ -964,36 +994,29 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 static struct lpfc_scsi_buf*
 lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
-       struct  lpfc_scsi_buf *lpfc_cmd = NULL;
-       struct  lpfc_scsi_buf *start_lpfc_cmd = NULL;
-       struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+       struct lpfc_scsi_buf *lpfc_cmd ;
        unsigned long iflag = 0;
        int found = 0;
 
        spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-       list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
-       spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
-       while (!found && lpfc_cmd) {
+       list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
+                                                       list) {
                if (lpfc_test_rrq_active(phba, ndlp,
-                                        lpfc_cmd->cur_iocbq.sli4_xritag)) {
-                       lpfc_release_scsi_buf_s4(phba, lpfc_cmd);
-                       spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-                       list_remove_head(scsi_buf_list, lpfc_cmd,
-                                        struct lpfc_scsi_buf, list);
-                       spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
-                                                iflag);
-                       if (lpfc_cmd == start_lpfc_cmd) {
-                               lpfc_cmd = NULL;
-                               break;
-                       } else
-                               continue;
-               }
+                                        lpfc_cmd->cur_iocbq.sli4_xritag))
+                       continue;
+               list_del(&lpfc_cmd->list);
                found = 1;
                lpfc_cmd->seg_cnt = 0;
                lpfc_cmd->nonsg_phys = 0;
                lpfc_cmd->prot_seg_cnt = 0;
+               break;
        }
-       return  lpfc_cmd;
+       spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
+                                                iflag);
+       if (!found)
+               return NULL;
+       else
+               return  lpfc_cmd;
 }
 /**
  * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
@@ -2484,6 +2507,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                        lpfc_worker_wake_up(phba);
                        break;
                case IOSTAT_LOCAL_REJECT:
+               case IOSTAT_REMOTE_STOP:
                        if (lpfc_cmd->result == IOERR_INVALID_RPI ||
                            lpfc_cmd->result == IOERR_NO_RESOURCES ||
                            lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
@@ -2510,6 +2534,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
                                                        "on unprotected cmd\n");
                                }
                        }
+                       if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP)
+                               && (phba->sli_rev == LPFC_SLI_REV4)
+                               && (pnode && NLP_CHK_NODE_ACT(pnode))) {
+                               /* This IO was aborted by the target, we don't
+                                * know the rxid and because we did not send the
+                                * ABTS we cannot generate and RRQ.
+                                */
+                               lpfc_set_rrq_active(phba, pnode,
+                                               lpfc_cmd->cur_iocbq.sli4_xritag,
+                                               0, 0);
+                       }
 
                /* else: fall through */
                default:
This page took 0.026983 seconds and 5 git commands to generate.