summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_els.c
diff options
context:
space:
mode:
authorDick Kennedy <dick.kennedy@broadcom.com>2017-08-23 16:55:36 -0700
committerMartin K. Petersen <martin.petersen@oracle.com>2017-08-24 22:29:37 -0400
commit8db1c2b3e7fa1b1a75a8dddc77bf516acfc03e8a (patch)
treeabcc2c44dd265322c93a03af0f8c46b45bc79b03 /drivers/scsi/lpfc/lpfc_els.c
parentcd22d6057c0cf1d6753a11c19c1cb62ca3f8fb29 (diff)
scsi: lpfc: Fix handling of FCP and NVME FC4 types in Pt2Pt topology
After link bounce in a NVME Pt2Pt config, the driver managed to map the same nport twice, resulting in multiple device nodes for the same namespace. In Pt2Pt, the driver must send PRLI's for both (scsi) FCP and NVME rather than using fabric aids. The driver was inconsistent on handling various PRLI completions, especially rejects, which had reject codes cross the different protocol PRLI completions. Fixed to perform the following: if nvmet mode (fc port can only be a nvme target) - rejects all unsolicitly FCP PRLI's. Never issues a FCP PRLI. The multiple protocol PRLI's are sent simultaneously. However, driver will now only state transition after both PRLI's are complete. New flags were added to aid tracking the responses from the different PRLI's. Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <james.smart@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 2dae501dc323..19af0e6e7667 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1966,6 +1966,7 @@ int
lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
{
struct lpfc_hba *phba = vport->phba;
+ struct Scsi_Host *shost;
struct serv_parm *sp;
struct lpfc_nodelist *ndlp;
struct lpfc_iocbq *elsiocb;
@@ -1984,6 +1985,11 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
if (!elsiocb)
return 1;
+ shost = lpfc_shost_from_vport(vport);
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag &= ~NLP_FCP_PRLI_RJT;
+ spin_unlock_irq(shost->host_lock);
+
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
/* For PLOGI request, remainder of payload is service parameters */
@@ -3442,6 +3448,21 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
goto out_retry;
}
break;
+ case LSRJT_CMD_UNSUPPORTED:
+ /* lpfc nvmet returns this type of LS_RJT when it
+ * receives an FCP PRLI because lpfc nvmet only
+ * support NVME. ELS request is terminated for FCP4
+ * on this rport.
+ */
+ if (stat.un.b.lsRjtRsnCodeExp ==
+ LSEXP_REQ_UNSUPPORTED && cmd == ELS_CMD_PRLI) {
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag |= NLP_FCP_PRLI_RJT;
+ spin_unlock_irq(shost->host_lock);
+ retry = 0;
+ goto out_retry;
+ }
+ break;
}
break;
@@ -8007,6 +8028,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
rjt_exp = LSEXP_NOTHING_MORE;
break;
}
+
+ /* NVMET accepts NVME PRLI only. Reject FCP PRLI */
+ if (cmd == ELS_CMD_PRLI && phba->nvmet_support) {
+ rjt_err = LSRJT_CMD_UNSUPPORTED;
+ rjt_exp = LSEXP_REQ_UNSUPPORTED;
+ break;
+ }
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
break;
case ELS_CMD_LIRR: