From: Jamie Wellnitz Date: Wed, 1 Mar 2006 00:25:38 +0000 (-0500) Subject: [SCSI] lpfc 8.1.2: Modify RSCN handling to unregister rpis on lost FCP_TARGETs immedi... X-Git-Tag: v2.6.17-rc1~1129^2~4^2~93 X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=50eba24f2e0576910a3e23dced769b7be7f3683e;p=linux-2.6-omap-h63xx.git [SCSI] lpfc 8.1.2: Modify RSCN handling to unregister rpis on lost FCP_TARGETs immediately Modify RSCN handling to unregister rpis on lost FCP_TARGETs immediately Signed-off-by: Jamie Wellnitz Signed-off-by: James Bottomley --- diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index eab087bf826..0c982bbc4c7 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -323,6 +323,7 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size) struct lpfc_sli_ct_request *Response = (struct lpfc_sli_ct_request *) mp->virt; struct lpfc_nodelist *ndlp = NULL; + struct lpfc_nodelist *next_ndlp; struct lpfc_dmabuf *mlast, *next_mp; uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType; uint32_t Did; @@ -391,8 +392,36 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size) nsout1: list_del(&head); - /* Here we are finished in the case RSCN */ + /* + * The driver has cycled through all Nports in the RSCN payload. + * Complete the handling by cleaning up and marking the + * current driver state. + */ if (phba->hba_state == LPFC_HBA_READY) { + + /* + * Switch ports that connect a loop of multiple targets need + * special consideration. The driver wants to unregister the + * rpi only on the target that was pulled from the loop. On + * RSCN, the driver wants to rediscover an NPort only if the + * driver flagged it as NLP_NPR_2B_DISC. Provided adisc is + * not enabled and the NPort is not capable of retransmissions + * (FC Tape) prevent timing races with the scsi error handler by + * unregistering the Nport's RPI. This action causes all + * outstanding IO to flush back to the midlayer. + */ + list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, + nlp_listp) { + if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC) && + (lpfc_rscn_payload_check(phba, ndlp->nlp_DID))) { + if ((phba->cfg_use_adisc == 0) && + !(ndlp->nlp_fcp_info & + NLP_FCP_2_DEVICE)) { + lpfc_unreg_rpi(phba, ndlp); + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + } + } + } lpfc_els_flush_rscn(phba); spin_lock_irq(phba->host->host_lock); phba->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */