diff options
author | James Smart <jsmart2021@gmail.com> | 2017-02-12 16:52:31 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-02-22 18:41:43 -0500 |
commit | a0f2d3ef374fd8d2f51b8cc1ea723014b1aa2c9b (patch) | |
tree | 615bf6656716b5a582561c4a7cdf77644e932f3a | |
parent | 895427bd012ce5814fc9888c7c0ee9de44761833 (diff) |
scsi: lpfc: NVME Initiator: Merge into FC discovery
NVME Initiator: Merge into FC discovery
Adds NVME PRLI support and Nameserver registrations and Queries for NVME
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 357 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 19 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 280 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 169 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 69 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw4.h | 43 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 177 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 3 |
10 files changed, 851 insertions, 279 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 77ad757ca231..81c47d1aebb2 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -123,6 +123,8 @@ struct perf_prof { | |||
123 | uint16_t wqidx[40]; | 123 | uint16_t wqidx[40]; |
124 | }; | 124 | }; |
125 | 125 | ||
126 | #define LPFC_FC4_TYPE_BITMASK 0x00000100 | ||
127 | |||
126 | /* Provide DMA memory definitions the driver uses per port instance. */ | 128 | /* Provide DMA memory definitions the driver uses per port instance. */ |
127 | struct lpfc_dmabuf { | 129 | struct lpfc_dmabuf { |
128 | struct list_head list; | 130 | struct list_head list; |
@@ -390,7 +392,8 @@ struct lpfc_vport { | |||
390 | int32_t stopped; /* HBA has not been restarted since last ERATT */ | 392 | int32_t stopped; /* HBA has not been restarted since last ERATT */ |
391 | uint8_t fc_linkspeed; /* Link speed after last READ_LA */ | 393 | uint8_t fc_linkspeed; /* Link speed after last READ_LA */ |
392 | 394 | ||
393 | uint32_t num_disc_nodes; /*in addition to hba_state */ | 395 | uint32_t num_disc_nodes; /* in addition to hba_state */ |
396 | uint32_t gidft_inp; /* cnt of outstanding GID_FTs */ | ||
394 | 397 | ||
395 | uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */ | 398 | uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */ |
396 | uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */ | 399 | uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */ |
@@ -443,7 +446,6 @@ struct lpfc_vport { | |||
443 | uint32_t cfg_max_scsicmpl_time; | 446 | uint32_t cfg_max_scsicmpl_time; |
444 | uint32_t cfg_tgt_queue_depth; | 447 | uint32_t cfg_tgt_queue_depth; |
445 | uint32_t cfg_first_burst_size; | 448 | uint32_t cfg_first_burst_size; |
446 | |||
447 | uint32_t dev_loss_tmo_changed; | 449 | uint32_t dev_loss_tmo_changed; |
448 | 450 | ||
449 | struct fc_vport *fc_vport; | 451 | struct fc_vport *fc_vport; |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 4ac03b16d17f..afb25369bc3b 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -40,8 +40,9 @@ | |||
40 | #include "lpfc_sli4.h" | 40 | #include "lpfc_sli4.h" |
41 | #include "lpfc_nl.h" | 41 | #include "lpfc_nl.h" |
42 | #include "lpfc_disc.h" | 42 | #include "lpfc_disc.h" |
43 | #include "lpfc_scsi.h" | ||
44 | #include "lpfc.h" | 43 | #include "lpfc.h" |
44 | #include "lpfc_scsi.h" | ||
45 | #include "lpfc_nvme.h" | ||
45 | #include "lpfc_logmsg.h" | 46 | #include "lpfc_logmsg.h" |
46 | #include "lpfc_crtn.h" | 47 | #include "lpfc_crtn.h" |
47 | #include "lpfc_version.h" | 48 | #include "lpfc_version.h" |
@@ -453,8 +454,73 @@ lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) { | |||
453 | return NULL; | 454 | return NULL; |
454 | } | 455 | } |
455 | 456 | ||
457 | static void | ||
458 | lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) | ||
459 | { | ||
460 | struct lpfc_nodelist *ndlp; | ||
461 | |||
462 | if ((vport->port_type != LPFC_NPIV_PORT) || | ||
463 | !(vport->ct_flags & FC_CT_RFF_ID) || !vport->cfg_restrict_login) { | ||
464 | |||
465 | ndlp = lpfc_setup_disc_node(vport, Did); | ||
466 | |||
467 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { | ||
468 | /* By default, the driver expects to support FCP FC4 */ | ||
469 | if (fc4_type == FC_TYPE_FCP) | ||
470 | ndlp->nlp_fc4_type |= NLP_FC4_FCP; | ||
471 | |||
472 | if (fc4_type == FC_TYPE_NVME) | ||
473 | ndlp->nlp_fc4_type |= NLP_FC4_NVME; | ||
474 | |||
475 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | ||
476 | "0238 Process x%06x NameServer Rsp " | ||
477 | "Data: x%x x%x x%x x%x\n", Did, | ||
478 | ndlp->nlp_flag, ndlp->nlp_fc4_type, | ||
479 | vport->fc_flag, | ||
480 | vport->fc_rscn_id_cnt); | ||
481 | } else | ||
482 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | ||
483 | "0239 Skip x%06x NameServer Rsp " | ||
484 | "Data: x%x x%x\n", Did, | ||
485 | vport->fc_flag, | ||
486 | vport->fc_rscn_id_cnt); | ||
487 | |||
488 | } else { | ||
489 | if (!(vport->fc_flag & FC_RSCN_MODE) || | ||
490 | lpfc_rscn_payload_check(vport, Did)) { | ||
491 | /* | ||
492 | * This NPortID was previously a FCP target, | ||
493 | * Don't even bother to send GFF_ID. | ||
494 | */ | ||
495 | ndlp = lpfc_findnode_did(vport, Did); | ||
496 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) | ||
497 | ndlp->nlp_fc4_type = fc4_type; | ||
498 | |||
499 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { | ||
500 | ndlp->nlp_fc4_type = fc4_type; | ||
501 | |||
502 | if (ndlp->nlp_type & NLP_FCP_TARGET) | ||
503 | lpfc_setup_disc_node(vport, Did); | ||
504 | |||
505 | else if (lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID, | ||
506 | 0, Did) == 0) | ||
507 | vport->num_disc_nodes++; | ||
508 | |||
509 | else | ||
510 | lpfc_setup_disc_node(vport, Did); | ||
511 | } | ||
512 | } else | ||
513 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | ||
514 | "0245 Skip x%06x NameServer Rsp " | ||
515 | "Data: x%x x%x\n", Did, | ||
516 | vport->fc_flag, | ||
517 | vport->fc_rscn_id_cnt); | ||
518 | } | ||
519 | } | ||
520 | |||
456 | static int | 521 | static int |
457 | lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | 522 | lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint8_t fc4_type, |
523 | uint32_t Size) | ||
458 | { | 524 | { |
459 | struct lpfc_hba *phba = vport->phba; | 525 | struct lpfc_hba *phba = vport->phba; |
460 | struct lpfc_sli_ct_request *Response = | 526 | struct lpfc_sli_ct_request *Response = |
@@ -499,97 +565,12 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
499 | */ | 565 | */ |
500 | if ((Did != vport->fc_myDID) && | 566 | if ((Did != vport->fc_myDID) && |
501 | ((lpfc_find_vport_by_did(phba, Did) == NULL) || | 567 | ((lpfc_find_vport_by_did(phba, Did) == NULL) || |
502 | vport->cfg_peer_port_login)) { | 568 | vport->cfg_peer_port_login)) |
503 | if ((vport->port_type != LPFC_NPIV_PORT) || | 569 | lpfc_prep_node_fc4type(vport, Did, fc4_type); |
504 | (!(vport->ct_flags & FC_CT_RFF_ID)) || | 570 | |
505 | (!vport->cfg_restrict_login)) { | ||
506 | ndlp = lpfc_setup_disc_node(vport, Did); | ||
507 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { | ||
508 | lpfc_debugfs_disc_trc(vport, | ||
509 | LPFC_DISC_TRC_CT, | ||
510 | "Parse GID_FTrsp: " | ||
511 | "did:x%x flg:x%x x%x", | ||
512 | Did, ndlp->nlp_flag, | ||
513 | vport->fc_flag); | ||
514 | |||
515 | lpfc_printf_vlog(vport, | ||
516 | KERN_INFO, | ||
517 | LOG_DISCOVERY, | ||
518 | "0238 Process " | ||
519 | "x%x NameServer Rsp" | ||
520 | "Data: x%x x%x x%x\n", | ||
521 | Did, ndlp->nlp_flag, | ||
522 | vport->fc_flag, | ||
523 | vport->fc_rscn_id_cnt); | ||
524 | } else { | ||
525 | lpfc_debugfs_disc_trc(vport, | ||
526 | LPFC_DISC_TRC_CT, | ||
527 | "Skip1 GID_FTrsp: " | ||
528 | "did:x%x flg:x%x cnt:%d", | ||
529 | Did, vport->fc_flag, | ||
530 | vport->fc_rscn_id_cnt); | ||
531 | |||
532 | lpfc_printf_vlog(vport, | ||
533 | KERN_INFO, | ||
534 | LOG_DISCOVERY, | ||
535 | "0239 Skip x%x " | ||
536 | "NameServer Rsp Data: " | ||
537 | "x%x x%x\n", | ||
538 | Did, vport->fc_flag, | ||
539 | vport->fc_rscn_id_cnt); | ||
540 | } | ||
541 | |||
542 | } else { | ||
543 | if (!(vport->fc_flag & FC_RSCN_MODE) || | ||
544 | (lpfc_rscn_payload_check(vport, Did))) { | ||
545 | lpfc_debugfs_disc_trc(vport, | ||
546 | LPFC_DISC_TRC_CT, | ||
547 | "Query GID_FTrsp: " | ||
548 | "did:x%x flg:x%x cnt:%d", | ||
549 | Did, vport->fc_flag, | ||
550 | vport->fc_rscn_id_cnt); | ||
551 | |||
552 | /* This NPortID was previously | ||
553 | * a FCP target, * Don't even | ||
554 | * bother to send GFF_ID. | ||
555 | */ | ||
556 | ndlp = lpfc_findnode_did(vport, | ||
557 | Did); | ||
558 | if (ndlp && | ||
559 | NLP_CHK_NODE_ACT(ndlp) | ||
560 | && (ndlp->nlp_type & | ||
561 | NLP_FCP_TARGET)) | ||
562 | lpfc_setup_disc_node | ||
563 | (vport, Did); | ||
564 | else if (lpfc_ns_cmd(vport, | ||
565 | SLI_CTNS_GFF_ID, | ||
566 | 0, Did) == 0) | ||
567 | vport->num_disc_nodes++; | ||
568 | else | ||
569 | lpfc_setup_disc_node | ||
570 | (vport, Did); | ||
571 | } | ||
572 | else { | ||
573 | lpfc_debugfs_disc_trc(vport, | ||
574 | LPFC_DISC_TRC_CT, | ||
575 | "Skip2 GID_FTrsp: " | ||
576 | "did:x%x flg:x%x cnt:%d", | ||
577 | Did, vport->fc_flag, | ||
578 | vport->fc_rscn_id_cnt); | ||
579 | |||
580 | lpfc_printf_vlog(vport, | ||
581 | KERN_INFO, | ||
582 | LOG_DISCOVERY, | ||
583 | "0245 Skip x%x " | ||
584 | "NameServer Rsp Data: " | ||
585 | "x%x x%x\n", | ||
586 | Did, vport->fc_flag, | ||
587 | vport->fc_rscn_id_cnt); | ||
588 | } | ||
589 | } | ||
590 | } | ||
591 | if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY))) | 571 | if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY))) |
592 | goto nsout1; | 572 | goto nsout1; |
573 | |||
593 | Cnt -= sizeof(uint32_t); | 574 | Cnt -= sizeof(uint32_t); |
594 | } | 575 | } |
595 | ctptr = NULL; | 576 | ctptr = NULL; |
@@ -609,16 +590,18 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
609 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 590 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
610 | IOCB_t *irsp; | 591 | IOCB_t *irsp; |
611 | struct lpfc_dmabuf *outp; | 592 | struct lpfc_dmabuf *outp; |
593 | struct lpfc_dmabuf *inp; | ||
612 | struct lpfc_sli_ct_request *CTrsp; | 594 | struct lpfc_sli_ct_request *CTrsp; |
595 | struct lpfc_sli_ct_request *CTreq; | ||
613 | struct lpfc_nodelist *ndlp; | 596 | struct lpfc_nodelist *ndlp; |
614 | int rc; | 597 | int rc, type; |
615 | 598 | ||
616 | /* First save ndlp, before we overwrite it */ | 599 | /* First save ndlp, before we overwrite it */ |
617 | ndlp = cmdiocb->context_un.ndlp; | 600 | ndlp = cmdiocb->context_un.ndlp; |
618 | 601 | ||
619 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 602 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
620 | cmdiocb->context_un.rsp_iocb = rspiocb; | 603 | cmdiocb->context_un.rsp_iocb = rspiocb; |
621 | 604 | inp = (struct lpfc_dmabuf *) cmdiocb->context1; | |
622 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | 605 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; |
623 | irsp = &rspiocb->iocb; | 606 | irsp = &rspiocb->iocb; |
624 | 607 | ||
@@ -656,9 +639,14 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
656 | IOERR_NO_RESOURCES) | 639 | IOERR_NO_RESOURCES) |
657 | vport->fc_ns_retry++; | 640 | vport->fc_ns_retry++; |
658 | 641 | ||
642 | type = lpfc_get_gidft_type(vport, cmdiocb); | ||
643 | if (type == 0) | ||
644 | goto out; | ||
645 | |||
659 | /* CT command is being retried */ | 646 | /* CT command is being retried */ |
647 | vport->gidft_inp--; | ||
660 | rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, | 648 | rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, |
661 | vport->fc_ns_retry, 0); | 649 | vport->fc_ns_retry, type); |
662 | if (rc == 0) | 650 | if (rc == 0) |
663 | goto out; | 651 | goto out; |
664 | } | 652 | } |
@@ -670,13 +658,18 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
670 | irsp->ulpStatus, vport->fc_ns_retry); | 658 | irsp->ulpStatus, vport->fc_ns_retry); |
671 | } else { | 659 | } else { |
672 | /* Good status, continue checking */ | 660 | /* Good status, continue checking */ |
661 | CTreq = (struct lpfc_sli_ct_request *) inp->virt; | ||
673 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | 662 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; |
674 | if (CTrsp->CommandResponse.bits.CmdRsp == | 663 | if (CTrsp->CommandResponse.bits.CmdRsp == |
675 | cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) { | 664 | cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) { |
676 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 665 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
677 | "0208 NameServer Rsp Data: x%x\n", | 666 | "0208 NameServer Rsp Data: x%x x%x\n", |
678 | vport->fc_flag); | 667 | vport->fc_flag, |
679 | lpfc_ns_rsp(vport, outp, | 668 | CTreq->un.gid.Fc4Type); |
669 | |||
670 | lpfc_ns_rsp(vport, | ||
671 | outp, | ||
672 | CTreq->un.gid.Fc4Type, | ||
680 | (uint32_t) (irsp->un.genreq64.bdl.bdeSize)); | 673 | (uint32_t) (irsp->un.genreq64.bdl.bdeSize)); |
681 | } else if (CTrsp->CommandResponse.bits.CmdRsp == | 674 | } else if (CTrsp->CommandResponse.bits.CmdRsp == |
682 | be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { | 675 | be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { |
@@ -731,9 +724,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
731 | (uint32_t) CTrsp->ReasonCode, | 724 | (uint32_t) CTrsp->ReasonCode, |
732 | (uint32_t) CTrsp->Explanation); | 725 | (uint32_t) CTrsp->Explanation); |
733 | } | 726 | } |
727 | vport->gidft_inp--; | ||
734 | } | 728 | } |
735 | /* Link up / RSCN discovery */ | 729 | /* Link up / RSCN discovery */ |
736 | if (vport->num_disc_nodes == 0) { | 730 | if ((vport->num_disc_nodes == 0) && |
731 | (vport->gidft_inp == 0)) { | ||
737 | /* | 732 | /* |
738 | * The driver has cycled through all Nports in the RSCN payload. | 733 | * The driver has cycled through all Nports in the RSCN payload. |
739 | * Complete the handling by cleaning up and marking the | 734 | * Complete the handling by cleaning up and marking the |
@@ -881,6 +876,56 @@ out: | |||
881 | return; | 876 | return; |
882 | } | 877 | } |
883 | 878 | ||
879 | static void | ||
880 | lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | ||
881 | struct lpfc_iocbq *rspiocb) | ||
882 | { | ||
883 | struct lpfc_vport *vport = cmdiocb->vport; | ||
884 | IOCB_t *irsp = &rspiocb->iocb; | ||
885 | struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *)cmdiocb->context1; | ||
886 | struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *)cmdiocb->context2; | ||
887 | struct lpfc_sli_ct_request *CTrsp; | ||
888 | int did; | ||
889 | struct lpfc_nodelist *ndlp; | ||
890 | uint32_t fc4_data_0, fc4_data_1; | ||
891 | |||
892 | did = ((struct lpfc_sli_ct_request *)inp->virt)->un.gft.PortId; | ||
893 | did = be32_to_cpu(did); | ||
894 | |||
895 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { | ||
896 | /* Good status, continue checking */ | ||
897 | CTrsp = (struct lpfc_sli_ct_request *)outp->virt; | ||
898 | fc4_data_0 = be32_to_cpu(CTrsp->un.gft_acc.fc4_types[0]); | ||
899 | fc4_data_1 = be32_to_cpu(CTrsp->un.gft_acc.fc4_types[1]); | ||
900 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | ||
901 | "3062 DID x%06x GFT Wd0 x%08x Wd1 x%08x\n", | ||
902 | did, fc4_data_0, fc4_data_1); | ||
903 | |||
904 | ndlp = lpfc_findnode_did(vport, did); | ||
905 | if (ndlp) { | ||
906 | /* The bitmask value for FCP and NVME FCP types is | ||
907 | * the same because they are 32 bits distant from | ||
908 | * each other in word0 and word0. | ||
909 | */ | ||
910 | if (fc4_data_0 & LPFC_FC4_TYPE_BITMASK) | ||
911 | ndlp->nlp_fc4_type |= NLP_FC4_FCP; | ||
912 | if (fc4_data_1 & LPFC_FC4_TYPE_BITMASK) | ||
913 | ndlp->nlp_fc4_type |= NLP_FC4_NVME; | ||
914 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | ||
915 | "3064 Setting ndlp %p, DID x%06x with " | ||
916 | "FC4 x%08x, Data: x%08x x%08x\n", | ||
917 | ndlp, did, ndlp->nlp_fc4_type, | ||
918 | FC_TYPE_FCP, FC_TYPE_NVME); | ||
919 | } | ||
920 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | ||
921 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); | ||
922 | lpfc_issue_els_prli(vport, ndlp, 0); | ||
923 | } else | ||
924 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | ||
925 | "3065 GFT_ID failed x%08x\n", irsp->ulpStatus); | ||
926 | |||
927 | lpfc_ct_free_iocb(phba, cmdiocb); | ||
928 | } | ||
884 | 929 | ||
885 | static void | 930 | static void |
886 | lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 931 | lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
@@ -1071,31 +1116,27 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1071 | return; | 1116 | return; |
1072 | } | 1117 | } |
1073 | 1118 | ||
1119 | /* | ||
1120 | * Although the symbolic port name is thought to be an integer | ||
1121 | * as of January 18, 2016, leave it as a string until more of | ||
1122 | * the record state becomes defined. | ||
1123 | */ | ||
1074 | int | 1124 | int |
1075 | lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol, | 1125 | lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol, |
1076 | size_t size) | 1126 | size_t size) |
1077 | { | 1127 | { |
1078 | int n; | 1128 | int n; |
1079 | uint8_t *wwn = vport->phba->wwpn; | ||
1080 | |||
1081 | n = snprintf(symbol, size, | ||
1082 | "Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", | ||
1083 | wwn[0], wwn[1], wwn[2], wwn[3], | ||
1084 | wwn[4], wwn[5], wwn[6], wwn[7]); | ||
1085 | 1129 | ||
1086 | if (vport->port_type == LPFC_PHYSICAL_PORT) | 1130 | /* |
1087 | return n; | 1131 | * Use the lpfc board number as the Symbolic Port |
1088 | 1132 | * Name object. NPIV is not in play so this integer | |
1089 | if (n < size) | 1133 | * value is sufficient and unique per FC-ID. |
1090 | n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi); | 1134 | */ |
1091 | 1135 | n = snprintf(symbol, size, "%d", vport->phba->brd_no); | |
1092 | if (n < size && | ||
1093 | strlen(vport->fc_vport->symbolic_name)) | ||
1094 | n += snprintf(symbol + n, size - n, " VName-%s", | ||
1095 | vport->fc_vport->symbolic_name); | ||
1096 | return n; | 1136 | return n; |
1097 | } | 1137 | } |
1098 | 1138 | ||
1139 | |||
1099 | int | 1140 | int |
1100 | lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, | 1141 | lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, |
1101 | size_t size) | 1142 | size_t size) |
@@ -1106,24 +1147,26 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, | |||
1106 | lpfc_decode_firmware_rev(vport->phba, fwrev, 0); | 1147 | lpfc_decode_firmware_rev(vport->phba, fwrev, 0); |
1107 | 1148 | ||
1108 | n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName); | 1149 | n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName); |
1109 | |||
1110 | if (size < n) | 1150 | if (size < n) |
1111 | return n; | 1151 | return n; |
1112 | n += snprintf(symbol + n, size - n, " FV%s", fwrev); | ||
1113 | 1152 | ||
1153 | n += snprintf(symbol + n, size - n, " FV%s", fwrev); | ||
1114 | if (size < n) | 1154 | if (size < n) |
1115 | return n; | 1155 | return n; |
1116 | n += snprintf(symbol + n, size - n, " DV%s", lpfc_release_version); | ||
1117 | 1156 | ||
1157 | n += snprintf(symbol + n, size - n, " DV%s.", | ||
1158 | lpfc_release_version); | ||
1118 | if (size < n) | 1159 | if (size < n) |
1119 | return n; | 1160 | return n; |
1120 | n += snprintf(symbol + n, size - n, " HN:%s", init_utsname()->nodename); | ||
1121 | 1161 | ||
1122 | /* Note :- OS name is "Linux" */ | 1162 | n += snprintf(symbol + n, size - n, " HN:%s.", |
1163 | init_utsname()->nodename); | ||
1123 | if (size < n) | 1164 | if (size < n) |
1124 | return n; | 1165 | return n; |
1125 | n += snprintf(symbol + n, size - n, " OS:%s", init_utsname()->sysname); | ||
1126 | 1166 | ||
1167 | /* Note :- OS name is "Linux" */ | ||
1168 | n += snprintf(symbol + n, size - n, " OS:%s\n", | ||
1169 | init_utsname()->sysname); | ||
1127 | return n; | 1170 | return n; |
1128 | } | 1171 | } |
1129 | 1172 | ||
@@ -1148,6 +1191,27 @@ lpfc_find_map_node(struct lpfc_vport *vport) | |||
1148 | } | 1191 | } |
1149 | 1192 | ||
1150 | /* | 1193 | /* |
1194 | * This routine will return the FC4 Type associated with the CT | ||
1195 | * GID_FT command. | ||
1196 | */ | ||
1197 | int | ||
1198 | lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb) | ||
1199 | { | ||
1200 | struct lpfc_sli_ct_request *CtReq; | ||
1201 | struct lpfc_dmabuf *mp; | ||
1202 | uint32_t type; | ||
1203 | |||
1204 | mp = cmdiocb->context1; | ||
1205 | if (mp == NULL) | ||
1206 | return 0; | ||
1207 | CtReq = (struct lpfc_sli_ct_request *)mp->virt; | ||
1208 | type = (uint32_t)CtReq->un.gid.Fc4Type; | ||
1209 | if ((type != SLI_CTPT_FCP) && (type != SLI_CTPT_NVME)) | ||
1210 | return 0; | ||
1211 | return type; | ||
1212 | } | ||
1213 | |||
1214 | /* | ||
1151 | * lpfc_ns_cmd | 1215 | * lpfc_ns_cmd |
1152 | * Description: | 1216 | * Description: |
1153 | * Issue Cmd to NameServer | 1217 | * Issue Cmd to NameServer |
@@ -1207,8 +1271,9 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1207 | 1271 | ||
1208 | /* NameServer Req */ | 1272 | /* NameServer Req */ |
1209 | lpfc_printf_vlog(vport, KERN_INFO ,LOG_DISCOVERY, | 1273 | lpfc_printf_vlog(vport, KERN_INFO ,LOG_DISCOVERY, |
1210 | "0236 NameServer Req Data: x%x x%x x%x\n", | 1274 | "0236 NameServer Req Data: x%x x%x x%x x%x\n", |
1211 | cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt); | 1275 | cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt, |
1276 | context); | ||
1212 | 1277 | ||
1213 | bpl = (struct ulp_bde64 *) bmp->virt; | 1278 | bpl = (struct ulp_bde64 *) bmp->virt; |
1214 | memset(bpl, 0, sizeof(struct ulp_bde64)); | 1279 | memset(bpl, 0, sizeof(struct ulp_bde64)); |
@@ -1219,6 +1284,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1219 | bpl->tus.f.bdeSize = GID_REQUEST_SZ; | 1284 | bpl->tus.f.bdeSize = GID_REQUEST_SZ; |
1220 | else if (cmdcode == SLI_CTNS_GFF_ID) | 1285 | else if (cmdcode == SLI_CTNS_GFF_ID) |
1221 | bpl->tus.f.bdeSize = GFF_REQUEST_SZ; | 1286 | bpl->tus.f.bdeSize = GFF_REQUEST_SZ; |
1287 | else if (cmdcode == SLI_CTNS_GFT_ID) | ||
1288 | bpl->tus.f.bdeSize = GFT_REQUEST_SZ; | ||
1222 | else if (cmdcode == SLI_CTNS_RFT_ID) | 1289 | else if (cmdcode == SLI_CTNS_RFT_ID) |
1223 | bpl->tus.f.bdeSize = RFT_REQUEST_SZ; | 1290 | bpl->tus.f.bdeSize = RFT_REQUEST_SZ; |
1224 | else if (cmdcode == SLI_CTNS_RNN_ID) | 1291 | else if (cmdcode == SLI_CTNS_RNN_ID) |
@@ -1246,7 +1313,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1246 | case SLI_CTNS_GID_FT: | 1313 | case SLI_CTNS_GID_FT: |
1247 | CtReq->CommandResponse.bits.CmdRsp = | 1314 | CtReq->CommandResponse.bits.CmdRsp = |
1248 | cpu_to_be16(SLI_CTNS_GID_FT); | 1315 | cpu_to_be16(SLI_CTNS_GID_FT); |
1249 | CtReq->un.gid.Fc4Type = SLI_CTPT_FCP; | 1316 | CtReq->un.gid.Fc4Type = context; |
1317 | |||
1250 | if (vport->port_state < LPFC_NS_QRY) | 1318 | if (vport->port_state < LPFC_NS_QRY) |
1251 | vport->port_state = LPFC_NS_QRY; | 1319 | vport->port_state = LPFC_NS_QRY; |
1252 | lpfc_set_disctmo(vport); | 1320 | lpfc_set_disctmo(vport); |
@@ -1261,12 +1329,32 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1261 | cmpl = lpfc_cmpl_ct_cmd_gff_id; | 1329 | cmpl = lpfc_cmpl_ct_cmd_gff_id; |
1262 | break; | 1330 | break; |
1263 | 1331 | ||
1332 | case SLI_CTNS_GFT_ID: | ||
1333 | CtReq->CommandResponse.bits.CmdRsp = | ||
1334 | cpu_to_be16(SLI_CTNS_GFT_ID); | ||
1335 | CtReq->un.gft.PortId = cpu_to_be32(context); | ||
1336 | cmpl = lpfc_cmpl_ct_cmd_gft_id; | ||
1337 | break; | ||
1338 | |||
1264 | case SLI_CTNS_RFT_ID: | 1339 | case SLI_CTNS_RFT_ID: |
1265 | vport->ct_flags &= ~FC_CT_RFT_ID; | 1340 | vport->ct_flags &= ~FC_CT_RFT_ID; |
1266 | CtReq->CommandResponse.bits.CmdRsp = | 1341 | CtReq->CommandResponse.bits.CmdRsp = |
1267 | cpu_to_be16(SLI_CTNS_RFT_ID); | 1342 | cpu_to_be16(SLI_CTNS_RFT_ID); |
1268 | CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID); | 1343 | CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID); |
1269 | CtReq->un.rft.fcpReg = 1; | 1344 | |
1345 | /* Register FC4 FCP type if enabled. */ | ||
1346 | if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
1347 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_FCP)) | ||
1348 | CtReq->un.rft.fcpReg = 1; | ||
1349 | |||
1350 | /* Register NVME type if enabled. Defined LE and swapped. | ||
1351 | * rsvd[0] is used as word1 because of the hard-coded | ||
1352 | * word0 usage in the ct_request data structure. | ||
1353 | */ | ||
1354 | if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
1355 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) | ||
1356 | CtReq->un.rft.rsvd[0] = cpu_to_be32(0x00000100); | ||
1357 | |||
1270 | cmpl = lpfc_cmpl_ct_cmd_rft_id; | 1358 | cmpl = lpfc_cmpl_ct_cmd_rft_id; |
1271 | break; | 1359 | break; |
1272 | 1360 | ||
@@ -1316,7 +1404,25 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1316 | cpu_to_be16(SLI_CTNS_RFF_ID); | 1404 | cpu_to_be16(SLI_CTNS_RFF_ID); |
1317 | CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID); | 1405 | CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID); |
1318 | CtReq->un.rff.fbits = FC4_FEATURE_INIT; | 1406 | CtReq->un.rff.fbits = FC4_FEATURE_INIT; |
1319 | CtReq->un.rff.type_code = FC_TYPE_FCP; | 1407 | |
1408 | /* The driver always supports FC_TYPE_FCP. However, the | ||
1409 | * caller can specify NVME (type x28) as well. But only | ||
1410 | * these that FC4 type is supported. | ||
1411 | */ | ||
1412 | if (((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
1413 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) && | ||
1414 | (context == FC_TYPE_NVME)) { | ||
1415 | /* todo: init: revise localport nvme attributes */ | ||
1416 | CtReq->un.rff.type_code = context; | ||
1417 | |||
1418 | } else if (((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
1419 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_FCP)) && | ||
1420 | (context == FC_TYPE_FCP)) | ||
1421 | CtReq->un.rff.type_code = context; | ||
1422 | |||
1423 | else | ||
1424 | goto ns_cmd_free_bmpvirt; | ||
1425 | |||
1320 | cmpl = lpfc_cmpl_ct_cmd_rff_id; | 1426 | cmpl = lpfc_cmpl_ct_cmd_rff_id; |
1321 | break; | 1427 | break; |
1322 | } | 1428 | } |
@@ -1337,6 +1443,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1337 | */ | 1443 | */ |
1338 | lpfc_nlp_put(ndlp); | 1444 | lpfc_nlp_put(ndlp); |
1339 | 1445 | ||
1446 | ns_cmd_free_bmpvirt: | ||
1340 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 1447 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
1341 | ns_cmd_free_bmp: | 1448 | ns_cmd_free_bmp: |
1342 | kfree(bmp); | 1449 | kfree(bmp); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 361f5b3d9d93..13cc1d19b336 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -86,6 +86,17 @@ struct lpfc_nodelist { | |||
86 | #define NLP_FABRIC 0x4 /* entry rep a Fabric entity */ | 86 | #define NLP_FABRIC 0x4 /* entry rep a Fabric entity */ |
87 | #define NLP_FCP_TARGET 0x8 /* entry is an FCP target */ | 87 | #define NLP_FCP_TARGET 0x8 /* entry is an FCP target */ |
88 | #define NLP_FCP_INITIATOR 0x10 /* entry is an FCP Initiator */ | 88 | #define NLP_FCP_INITIATOR 0x10 /* entry is an FCP Initiator */ |
89 | #define NLP_NVME_TARGET 0x20 /* entry is a NVME Target */ | ||
90 | #define NLP_NVME_INITIATOR 0x40 /* entry is a NVME Initiator */ | ||
91 | |||
92 | uint16_t nlp_fc4_type; /* FC types node supports. */ | ||
93 | /* Assigned from GID_FF, only | ||
94 | * FCP (0x8) and NVME (0x28) | ||
95 | * supported. | ||
96 | */ | ||
97 | #define NLP_FC4_NONE 0x0 | ||
98 | #define NLP_FC4_FCP 0x1 /* FC4 Type FCP (value x8)) */ | ||
99 | #define NLP_FC4_NVME 0x2 /* FC4 TYPE NVME (value x28) */ | ||
89 | 100 | ||
90 | uint16_t nlp_rpi; | 101 | uint16_t nlp_rpi; |
91 | uint16_t nlp_state; /* state transition indicator */ | 102 | uint16_t nlp_state; /* state transition indicator */ |
@@ -107,8 +118,8 @@ struct lpfc_nodelist { | |||
107 | 118 | ||
108 | struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */ | 119 | struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */ |
109 | struct lpfc_hba *phba; | 120 | struct lpfc_hba *phba; |
110 | struct fc_rport *rport; /* Corresponding FC transport | 121 | struct fc_rport *rport; /* scsi_transport_fc port structure */ |
111 | port structure */ | 122 | struct lpfc_nvme_rport *nrport; /* nvme transport rport struct. */ |
112 | struct lpfc_vport *vport; | 123 | struct lpfc_vport *vport; |
113 | struct lpfc_work_evt els_retry_evt; | 124 | struct lpfc_work_evt els_retry_evt; |
114 | struct lpfc_work_evt dev_loss_evt; | 125 | struct lpfc_work_evt dev_loss_evt; |
@@ -118,6 +129,10 @@ struct lpfc_nodelist { | |||
118 | unsigned long last_change_time; | 129 | unsigned long last_change_time; |
119 | unsigned long *active_rrqs_xri_bitmap; | 130 | unsigned long *active_rrqs_xri_bitmap; |
120 | struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ | 131 | struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ |
132 | uint32_t fc4_prli_sent; | ||
133 | uint32_t upcall_flags; | ||
134 | uint32_t nvme_fb_size; /* NVME target's supported byte cnt */ | ||
135 | #define NVME_FB_BIT_SHIFT 9 /* PRLI Rsp first burst in 512B units. */ | ||
121 | }; | 136 | }; |
122 | struct lpfc_node_rrq { | 137 | struct lpfc_node_rrq { |
123 | struct list_head list; | 138 | struct list_head list; |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 7be235457540..e164eed25e3d 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
30 | #include <scsi/scsi_transport_fc.h> | 30 | #include <scsi/scsi_transport_fc.h> |
31 | 31 | ||
32 | |||
33 | #include "lpfc_hw4.h" | 32 | #include "lpfc_hw4.h" |
34 | #include "lpfc_hw.h" | 33 | #include "lpfc_hw.h" |
35 | #include "lpfc_sli.h" | 34 | #include "lpfc_sli.h" |
@@ -1513,7 +1512,7 @@ static struct lpfc_nodelist * | |||
1513 | lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, | 1512 | lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, |
1514 | struct lpfc_nodelist *ndlp) | 1513 | struct lpfc_nodelist *ndlp) |
1515 | { | 1514 | { |
1516 | struct lpfc_vport *vport = ndlp->vport; | 1515 | struct lpfc_vport *vport = ndlp->vport; |
1517 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1516 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1518 | struct lpfc_nodelist *new_ndlp; | 1517 | struct lpfc_nodelist *new_ndlp; |
1519 | struct lpfc_rport_data *rdata; | 1518 | struct lpfc_rport_data *rdata; |
@@ -1868,10 +1867,12 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1868 | 1867 | ||
1869 | /* PLOGI completes to NPort <nlp_DID> */ | 1868 | /* PLOGI completes to NPort <nlp_DID> */ |
1870 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 1869 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
1871 | "0102 PLOGI completes to NPort x%x " | 1870 | "0102 PLOGI completes to NPort x%06x " |
1872 | "Data: x%x x%x x%x x%x x%x\n", | 1871 | "Data: x%x x%x x%x x%x x%x\n", |
1873 | ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], | 1872 | ndlp->nlp_DID, ndlp->nlp_fc4_type, |
1874 | irsp->ulpTimeout, disc, vport->num_disc_nodes); | 1873 | irsp->ulpStatus, irsp->un.ulpWord[4], |
1874 | disc, vport->num_disc_nodes); | ||
1875 | |||
1875 | /* Check to see if link went down during discovery */ | 1876 | /* Check to see if link went down during discovery */ |
1876 | if (lpfc_els_chk_latt(vport)) { | 1877 | if (lpfc_els_chk_latt(vport)) { |
1877 | spin_lock_irq(shost->host_lock); | 1878 | spin_lock_irq(shost->host_lock); |
@@ -2000,7 +2001,6 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) | |||
2000 | sp->cmn.fcphHigh = FC_PH3; | 2001 | sp->cmn.fcphHigh = FC_PH3; |
2001 | 2002 | ||
2002 | sp->cmn.valid_vendor_ver_level = 0; | 2003 | sp->cmn.valid_vendor_ver_level = 0; |
2003 | memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); | ||
2004 | 2004 | ||
2005 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | 2005 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
2006 | "Issue PLOGI: did:x%x", | 2006 | "Issue PLOGI: did:x%x", |
@@ -2052,14 +2052,17 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2052 | "PRLI cmpl: status:x%x/x%x did:x%x", | 2052 | "PRLI cmpl: status:x%x/x%x did:x%x", |
2053 | irsp->ulpStatus, irsp->un.ulpWord[4], | 2053 | irsp->ulpStatus, irsp->un.ulpWord[4], |
2054 | ndlp->nlp_DID); | 2054 | ndlp->nlp_DID); |
2055 | |||
2056 | /* Ddriver supports multiple FC4 types. Counters matter. */ | ||
2057 | vport->fc_prli_sent--; | ||
2058 | |||
2055 | /* PRLI completes to NPort <nlp_DID> */ | 2059 | /* PRLI completes to NPort <nlp_DID> */ |
2056 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 2060 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
2057 | "0103 PRLI completes to NPort x%x " | 2061 | "0103 PRLI completes to NPort x%06x " |
2058 | "Data: x%x x%x x%x x%x\n", | 2062 | "Data: x%x x%x x%x x%x\n", |
2059 | ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], | 2063 | ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], |
2060 | irsp->ulpTimeout, vport->num_disc_nodes); | 2064 | vport->num_disc_nodes, ndlp->fc4_prli_sent); |
2061 | 2065 | ||
2062 | vport->fc_prli_sent--; | ||
2063 | /* Check to see if link went down during discovery */ | 2066 | /* Check to see if link went down during discovery */ |
2064 | if (lpfc_els_chk_latt(vport)) | 2067 | if (lpfc_els_chk_latt(vport)) |
2065 | goto out; | 2068 | goto out; |
@@ -2068,6 +2071,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2068 | /* Check for retry */ | 2071 | /* Check for retry */ |
2069 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { | 2072 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { |
2070 | /* ELS command is being retried */ | 2073 | /* ELS command is being retried */ |
2074 | ndlp->fc4_prli_sent--; | ||
2071 | goto out; | 2075 | goto out; |
2072 | } | 2076 | } |
2073 | /* PRLI failed */ | 2077 | /* PRLI failed */ |
@@ -2082,9 +2086,14 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2082 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 2086 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
2083 | NLP_EVT_CMPL_PRLI); | 2087 | NLP_EVT_CMPL_PRLI); |
2084 | } else | 2088 | } else |
2085 | /* Good status, call state machine */ | 2089 | /* Good status, call state machine. However, if another |
2090 | * PRLI is outstanding, don't call the state machine | ||
2091 | * because final disposition to Mapped or Unmapped is | ||
2092 | * completed there. | ||
2093 | */ | ||
2086 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, | 2094 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
2087 | NLP_EVT_CMPL_PRLI); | 2095 | NLP_EVT_CMPL_PRLI); |
2096 | |||
2088 | out: | 2097 | out: |
2089 | lpfc_els_free_iocb(phba, cmdiocb); | 2098 | lpfc_els_free_iocb(phba, cmdiocb); |
2090 | return; | 2099 | return; |
@@ -2118,42 +2127,94 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2118 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2127 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2119 | struct lpfc_hba *phba = vport->phba; | 2128 | struct lpfc_hba *phba = vport->phba; |
2120 | PRLI *npr; | 2129 | PRLI *npr; |
2130 | struct lpfc_nvme_prli *npr_nvme; | ||
2121 | struct lpfc_iocbq *elsiocb; | 2131 | struct lpfc_iocbq *elsiocb; |
2122 | uint8_t *pcmd; | 2132 | uint8_t *pcmd; |
2123 | uint16_t cmdsize; | 2133 | uint16_t cmdsize; |
2124 | 2134 | u32 local_nlp_type, elscmd; | |
2125 | cmdsize = (sizeof(uint32_t) + sizeof(PRLI)); | 2135 | |
2136 | local_nlp_type = ndlp->nlp_fc4_type; | ||
2137 | |||
2138 | send_next_prli: | ||
2139 | if (local_nlp_type & NLP_FC4_FCP) { | ||
2140 | /* Payload is 4 + 16 = 20 x14 bytes. */ | ||
2141 | cmdsize = (sizeof(uint32_t) + sizeof(PRLI)); | ||
2142 | elscmd = ELS_CMD_PRLI; | ||
2143 | } else if (local_nlp_type & NLP_FC4_NVME) { | ||
2144 | /* Payload is 4 + 20 = 24 x18 bytes. */ | ||
2145 | cmdsize = (sizeof(uint32_t) + sizeof(struct lpfc_nvme_prli)); | ||
2146 | elscmd = ELS_CMD_NVMEPRLI; | ||
2147 | } else { | ||
2148 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | ||
2149 | "3083 Unknown FC_TYPE x%x ndlp x%06x\n", | ||
2150 | ndlp->nlp_fc4_type, ndlp->nlp_DID); | ||
2151 | return 1; | ||
2152 | } | ||
2126 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, | 2153 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
2127 | ndlp->nlp_DID, ELS_CMD_PRLI); | 2154 | ndlp->nlp_DID, elscmd); |
2128 | if (!elsiocb) | 2155 | if (!elsiocb) |
2129 | return 1; | 2156 | return 1; |
2130 | 2157 | ||
2131 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 2158 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
2132 | 2159 | ||
2133 | /* For PRLI request, remainder of payload is service parameters */ | 2160 | /* For PRLI request, remainder of payload is service parameters */ |
2134 | memset(pcmd, 0, (sizeof(PRLI) + sizeof(uint32_t))); | 2161 | memset(pcmd, 0, cmdsize); |
2135 | *((uint32_t *) (pcmd)) = ELS_CMD_PRLI; | ||
2136 | pcmd += sizeof(uint32_t); | ||
2137 | 2162 | ||
2138 | /* For PRLI, remainder of payload is PRLI parameter page */ | 2163 | if (local_nlp_type & NLP_FC4_FCP) { |
2139 | npr = (PRLI *) pcmd; | 2164 | /* Remainder of payload is FCP PRLI parameter page. |
2140 | /* | 2165 | * Note: this data structure is defined as |
2141 | * If our firmware version is 3.20 or later, | 2166 | * BE/LE in the structure definition so no |
2142 | * set the following bits for FC-TAPE support. | 2167 | * byte swap call is made. |
2143 | */ | 2168 | */ |
2144 | if (phba->vpd.rev.feaLevelHigh >= 0x02) { | 2169 | *((uint32_t *)(pcmd)) = ELS_CMD_PRLI; |
2145 | npr->ConfmComplAllowed = 1; | 2170 | pcmd += sizeof(uint32_t); |
2146 | npr->Retry = 1; | 2171 | npr = (PRLI *)pcmd; |
2147 | npr->TaskRetryIdReq = 1; | ||
2148 | } | ||
2149 | npr->estabImagePair = 1; | ||
2150 | npr->readXferRdyDis = 1; | ||
2151 | if (vport->cfg_first_burst_size) | ||
2152 | npr->writeXferRdyDis = 1; | ||
2153 | 2172 | ||
2154 | /* For FCP support */ | 2173 | /* |
2155 | npr->prliType = PRLI_FCP_TYPE; | 2174 | * If our firmware version is 3.20 or later, |
2156 | npr->initiatorFunc = 1; | 2175 | * set the following bits for FC-TAPE support. |
2176 | */ | ||
2177 | if (phba->vpd.rev.feaLevelHigh >= 0x02) { | ||
2178 | npr->ConfmComplAllowed = 1; | ||
2179 | npr->Retry = 1; | ||
2180 | npr->TaskRetryIdReq = 1; | ||
2181 | } | ||
2182 | npr->estabImagePair = 1; | ||
2183 | npr->readXferRdyDis = 1; | ||
2184 | if (vport->cfg_first_burst_size) | ||
2185 | npr->writeXferRdyDis = 1; | ||
2186 | |||
2187 | /* For FCP support */ | ||
2188 | npr->prliType = PRLI_FCP_TYPE; | ||
2189 | npr->initiatorFunc = 1; | ||
2190 | elsiocb->iocb_flag |= LPFC_PRLI_FCP_REQ; | ||
2191 | |||
2192 | /* Remove FCP type - processed. */ | ||
2193 | local_nlp_type &= ~NLP_FC4_FCP; | ||
2194 | } else if (local_nlp_type & NLP_FC4_NVME) { | ||
2195 | /* Remainder of payload is NVME PRLI parameter page. | ||
2196 | * This data structure is the newer definition that | ||
2197 | * uses bf macros so a byte swap is required. | ||
2198 | */ | ||
2199 | *((uint32_t *)(pcmd)) = ELS_CMD_NVMEPRLI; | ||
2200 | pcmd += sizeof(uint32_t); | ||
2201 | npr_nvme = (struct lpfc_nvme_prli *)pcmd; | ||
2202 | bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE); | ||
2203 | bf_set(prli_estabImagePair, npr_nvme, 0); /* Should be 0 */ | ||
2204 | |||
2205 | /* Only initiators request first burst. */ | ||
2206 | if ((phba->cfg_nvme_enable_fb) && | ||
2207 | !phba->nvmet_support) | ||
2208 | bf_set(prli_fba, npr_nvme, 1); | ||
2209 | |||
2210 | bf_set(prli_init, npr_nvme, 1); | ||
2211 | npr_nvme->word1 = cpu_to_be32(npr_nvme->word1); | ||
2212 | npr_nvme->word4 = cpu_to_be32(npr_nvme->word4); | ||
2213 | elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ; | ||
2214 | |||
2215 | /* Remove NVME type - processed. */ | ||
2216 | local_nlp_type &= ~NLP_FC4_NVME; | ||
2217 | } | ||
2157 | 2218 | ||
2158 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | 2219 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
2159 | "Issue PRLI: did:x%x", | 2220 | "Issue PRLI: did:x%x", |
@@ -2172,7 +2233,20 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
2172 | lpfc_els_free_iocb(phba, elsiocb); | 2233 | lpfc_els_free_iocb(phba, elsiocb); |
2173 | return 1; | 2234 | return 1; |
2174 | } | 2235 | } |
2236 | |||
2237 | /* The vport counters are used for lpfc_scan_finished, but | ||
2238 | * the ndlp is used to track outstanding PRLIs for different | ||
2239 | * FC4 types. | ||
2240 | */ | ||
2175 | vport->fc_prli_sent++; | 2241 | vport->fc_prli_sent++; |
2242 | ndlp->fc4_prli_sent++; | ||
2243 | |||
2244 | /* The driver supports 2 FC4 types. Make sure | ||
2245 | * a PRLI is issued for all types before exiting. | ||
2246 | */ | ||
2247 | if (local_nlp_type & (NLP_FC4_FCP | NLP_FC4_NVME)) | ||
2248 | goto send_next_prli; | ||
2249 | |||
2176 | return 0; | 2250 | return 0; |
2177 | } | 2251 | } |
2178 | 2252 | ||
@@ -2543,6 +2617,9 @@ out: | |||
2543 | if ((vport->fc_flag & FC_PT2PT) && | 2617 | if ((vport->fc_flag & FC_PT2PT) && |
2544 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { | 2618 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { |
2545 | phba->pport->fc_myDID = 0; | 2619 | phba->pport->fc_myDID = 0; |
2620 | |||
2621 | /* todo: init: revise localport nvme attributes */ | ||
2622 | |||
2546 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 2623 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
2547 | if (mbox) { | 2624 | if (mbox) { |
2548 | lpfc_config_link(phba, mbox); | 2625 | lpfc_config_link(phba, mbox); |
@@ -3055,6 +3132,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
3055 | } | 3132 | } |
3056 | break; | 3133 | break; |
3057 | case ELS_CMD_PRLI: | 3134 | case ELS_CMD_PRLI: |
3135 | case ELS_CMD_NVMEPRLI: | ||
3058 | if (!lpfc_issue_els_prli(vport, ndlp, retry)) { | 3136 | if (!lpfc_issue_els_prli(vport, ndlp, retry)) { |
3059 | ndlp->nlp_prev_state = ndlp->nlp_state; | 3137 | ndlp->nlp_prev_state = ndlp->nlp_state; |
3060 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); | 3138 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); |
@@ -3245,7 +3323,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3245 | break; | 3323 | break; |
3246 | } | 3324 | } |
3247 | if ((cmd == ELS_CMD_PLOGI) || | 3325 | if ((cmd == ELS_CMD_PLOGI) || |
3248 | (cmd == ELS_CMD_PRLI)) { | 3326 | (cmd == ELS_CMD_PRLI) || |
3327 | (cmd == ELS_CMD_NVMEPRLI)) { | ||
3249 | delay = 1000; | 3328 | delay = 1000; |
3250 | maxretry = lpfc_max_els_tries + 1; | 3329 | maxretry = lpfc_max_els_tries + 1; |
3251 | retry = 1; | 3330 | retry = 1; |
@@ -3265,7 +3344,8 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3265 | 3344 | ||
3266 | case LSRJT_LOGICAL_BSY: | 3345 | case LSRJT_LOGICAL_BSY: |
3267 | if ((cmd == ELS_CMD_PLOGI) || | 3346 | if ((cmd == ELS_CMD_PLOGI) || |
3268 | (cmd == ELS_CMD_PRLI)) { | 3347 | (cmd == ELS_CMD_PRLI) || |
3348 | (cmd == ELS_CMD_NVMEPRLI)) { | ||
3269 | delay = 1000; | 3349 | delay = 1000; |
3270 | maxretry = 48; | 3350 | maxretry = 48; |
3271 | } else if (cmd == ELS_CMD_FDISC) { | 3351 | } else if (cmd == ELS_CMD_FDISC) { |
@@ -3399,7 +3479,8 @@ out_retry: | |||
3399 | spin_unlock_irq(shost->host_lock); | 3479 | spin_unlock_irq(shost->host_lock); |
3400 | 3480 | ||
3401 | ndlp->nlp_prev_state = ndlp->nlp_state; | 3481 | ndlp->nlp_prev_state = ndlp->nlp_state; |
3402 | if (cmd == ELS_CMD_PRLI) | 3482 | if ((cmd == ELS_CMD_PRLI) || |
3483 | (cmd == ELS_CMD_NVMEPRLI)) | ||
3403 | lpfc_nlp_set_state(vport, ndlp, | 3484 | lpfc_nlp_set_state(vport, ndlp, |
3404 | NLP_STE_PRLI_ISSUE); | 3485 | NLP_STE_PRLI_ISSUE); |
3405 | else | 3486 | else |
@@ -3430,6 +3511,7 @@ out_retry: | |||
3430 | lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry); | 3511 | lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry); |
3431 | return 1; | 3512 | return 1; |
3432 | case ELS_CMD_PRLI: | 3513 | case ELS_CMD_PRLI: |
3514 | case ELS_CMD_NVMEPRLI: | ||
3433 | ndlp->nlp_prev_state = ndlp->nlp_state; | 3515 | ndlp->nlp_prev_state = ndlp->nlp_state; |
3434 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); | 3516 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); |
3435 | lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry); | 3517 | lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry); |
@@ -3990,14 +4072,10 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, | |||
3990 | sizeof(struct lpfc_name)); | 4072 | sizeof(struct lpfc_name)); |
3991 | memcpy(&sp->nodeName, &vport->fc_sparam.nodeName, | 4073 | memcpy(&sp->nodeName, &vport->fc_sparam.nodeName, |
3992 | sizeof(struct lpfc_name)); | 4074 | sizeof(struct lpfc_name)); |
3993 | } else { | 4075 | } else |
3994 | memcpy(pcmd, &vport->fc_sparam, | 4076 | memcpy(pcmd, &vport->fc_sparam, |
3995 | sizeof(struct serv_parm)); | 4077 | sizeof(struct serv_parm)); |
3996 | 4078 | ||
3997 | sp->cmn.valid_vendor_ver_level = 0; | ||
3998 | memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion)); | ||
3999 | } | ||
4000 | |||
4001 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | 4079 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, |
4002 | "Issue ACC FLOGI/PLOGI: did:x%x flg:x%x", | 4080 | "Issue ACC FLOGI/PLOGI: did:x%x flg:x%x", |
4003 | ndlp->nlp_DID, ndlp->nlp_flag, 0); | 4081 | ndlp->nlp_DID, ndlp->nlp_flag, 0); |
@@ -4231,17 +4309,43 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, | |||
4231 | { | 4309 | { |
4232 | struct lpfc_hba *phba = vport->phba; | 4310 | struct lpfc_hba *phba = vport->phba; |
4233 | PRLI *npr; | 4311 | PRLI *npr; |
4312 | struct lpfc_nvme_prli *npr_nvme; | ||
4234 | lpfc_vpd_t *vpd; | 4313 | lpfc_vpd_t *vpd; |
4235 | IOCB_t *icmd; | 4314 | IOCB_t *icmd; |
4236 | IOCB_t *oldcmd; | 4315 | IOCB_t *oldcmd; |
4237 | struct lpfc_iocbq *elsiocb; | 4316 | struct lpfc_iocbq *elsiocb; |
4238 | uint8_t *pcmd; | 4317 | uint8_t *pcmd; |
4239 | uint16_t cmdsize; | 4318 | uint16_t cmdsize; |
4319 | uint32_t prli_fc4_req, *req_payload; | ||
4320 | struct lpfc_dmabuf *req_buf; | ||
4240 | int rc; | 4321 | int rc; |
4322 | u32 elsrspcmd; | ||
4323 | |||
4324 | /* Need the incoming PRLI payload to determine if the ACC is for an | ||
4325 | * FC4 or NVME PRLI type. The PRLI type is at word 1. | ||
4326 | */ | ||
4327 | req_buf = (struct lpfc_dmabuf *)oldiocb->context2; | ||
4328 | req_payload = (((uint32_t *)req_buf->virt) + 1); | ||
4329 | |||
4330 | /* PRLI type payload is at byte 3 for FCP or NVME. */ | ||
4331 | prli_fc4_req = be32_to_cpu(*req_payload); | ||
4332 | prli_fc4_req = (prli_fc4_req >> 24) & 0xff; | ||
4333 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
4334 | "6127 PRLI_ACC: Req Type x%x, Word1 x%08x\n", | ||
4335 | prli_fc4_req, *((uint32_t *)req_payload)); | ||
4336 | |||
4337 | if (prli_fc4_req == PRLI_FCP_TYPE) { | ||
4338 | cmdsize = sizeof(uint32_t) + sizeof(PRLI); | ||
4339 | elsrspcmd = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)); | ||
4340 | } else if (prli_fc4_req & PRLI_NVME_TYPE) { | ||
4341 | cmdsize = sizeof(uint32_t) + sizeof(struct lpfc_nvme_prli); | ||
4342 | elsrspcmd = (ELS_CMD_ACC | (ELS_CMD_NVMEPRLI & ~ELS_RSP_MASK)); | ||
4343 | } else { | ||
4344 | return 1; | ||
4345 | } | ||
4241 | 4346 | ||
4242 | cmdsize = sizeof(uint32_t) + sizeof(PRLI); | ||
4243 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, | 4347 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, |
4244 | ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); | 4348 | ndlp->nlp_DID, elsrspcmd); |
4245 | if (!elsiocb) | 4349 | if (!elsiocb) |
4246 | return 1; | 4350 | return 1; |
4247 | 4351 | ||
@@ -4258,33 +4362,56 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, | |||
4258 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, | 4362 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
4259 | ndlp->nlp_rpi); | 4363 | ndlp->nlp_rpi); |
4260 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 4364 | pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
4365 | memset(pcmd, 0, cmdsize); | ||
4261 | 4366 | ||
4262 | *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)); | 4367 | *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)); |
4263 | pcmd += sizeof(uint32_t); | 4368 | pcmd += sizeof(uint32_t); |
4264 | 4369 | ||
4265 | /* For PRLI, remainder of payload is PRLI parameter page */ | 4370 | /* For PRLI, remainder of payload is PRLI parameter page */ |
4266 | memset(pcmd, 0, sizeof(PRLI)); | ||
4267 | |||
4268 | npr = (PRLI *) pcmd; | ||
4269 | vpd = &phba->vpd; | 4371 | vpd = &phba->vpd; |
4270 | /* | ||
4271 | * If the remote port is a target and our firmware version is 3.20 or | ||
4272 | * later, set the following bits for FC-TAPE support. | ||
4273 | */ | ||
4274 | if ((ndlp->nlp_type & NLP_FCP_TARGET) && | ||
4275 | (vpd->rev.feaLevelHigh >= 0x02)) { | ||
4276 | npr->ConfmComplAllowed = 1; | ||
4277 | npr->Retry = 1; | ||
4278 | npr->TaskRetryIdReq = 1; | ||
4279 | } | ||
4280 | |||
4281 | npr->acceptRspCode = PRLI_REQ_EXECUTED; | ||
4282 | npr->estabImagePair = 1; | ||
4283 | npr->readXferRdyDis = 1; | ||
4284 | npr->ConfmComplAllowed = 1; | ||
4285 | 4372 | ||
4286 | npr->prliType = PRLI_FCP_TYPE; | 4373 | if (prli_fc4_req == PRLI_FCP_TYPE) { |
4287 | npr->initiatorFunc = 1; | 4374 | /* |
4375 | * If the remote port is a target and our firmware version | ||
4376 | * is 3.20 or later, set the following bits for FC-TAPE | ||
4377 | * support. | ||
4378 | */ | ||
4379 | npr = (PRLI *) pcmd; | ||
4380 | if ((ndlp->nlp_type & NLP_FCP_TARGET) && | ||
4381 | (vpd->rev.feaLevelHigh >= 0x02)) { | ||
4382 | npr->ConfmComplAllowed = 1; | ||
4383 | npr->Retry = 1; | ||
4384 | npr->TaskRetryIdReq = 1; | ||
4385 | } | ||
4386 | npr->acceptRspCode = PRLI_REQ_EXECUTED; | ||
4387 | npr->estabImagePair = 1; | ||
4388 | npr->readXferRdyDis = 1; | ||
4389 | npr->ConfmComplAllowed = 1; | ||
4390 | npr->prliType = PRLI_FCP_TYPE; | ||
4391 | npr->initiatorFunc = 1; | ||
4392 | } else if (prli_fc4_req & PRLI_NVME_TYPE) { | ||
4393 | /* Respond with an NVME PRLI Type */ | ||
4394 | npr_nvme = (struct lpfc_nvme_prli *) pcmd; | ||
4395 | bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE); | ||
4396 | bf_set(prli_estabImagePair, npr_nvme, 0); /* Should be 0 */ | ||
4397 | bf_set(prli_acc_rsp_code, npr_nvme, PRLI_REQ_EXECUTED); | ||
4398 | bf_set(prli_init, npr_nvme, 1); | ||
4399 | |||
4400 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, | ||
4401 | "6015 NVME issue PRLI ACC word1 x%08x " | ||
4402 | "word4 x%08x word5 x%08x flag x%x, " | ||
4403 | "fcp_info x%x nlp_type x%x\n", | ||
4404 | npr_nvme->word1, npr_nvme->word4, | ||
4405 | npr_nvme->word5, ndlp->nlp_flag, | ||
4406 | ndlp->nlp_fcp_info, ndlp->nlp_type); | ||
4407 | npr_nvme->word1 = cpu_to_be32(npr_nvme->word1); | ||
4408 | npr_nvme->word4 = cpu_to_be32(npr_nvme->word4); | ||
4409 | npr_nvme->word5 = cpu_to_be32(npr_nvme->word5); | ||
4410 | } else | ||
4411 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | ||
4412 | "6128 Unknown FC_TYPE x%x x%x ndlp x%06x\n", | ||
4413 | prli_fc4_req, ndlp->nlp_fc4_type, | ||
4414 | ndlp->nlp_DID); | ||
4288 | 4415 | ||
4289 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, | 4416 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, |
4290 | "Issue ACC PRLI: did:x%x flg:x%x", | 4417 | "Issue ACC PRLI: did:x%x flg:x%x", |
@@ -4411,7 +4538,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, | |||
4411 | **/ | 4538 | **/ |
4412 | static void | 4539 | static void |
4413 | lpfc_els_clear_rrq(struct lpfc_vport *vport, | 4540 | lpfc_els_clear_rrq(struct lpfc_vport *vport, |
4414 | struct lpfc_iocbq *iocb, struct lpfc_nodelist *ndlp) | 4541 | struct lpfc_iocbq *iocb, struct lpfc_nodelist *ndlp) |
4415 | { | 4542 | { |
4416 | struct lpfc_hba *phba = vport->phba; | 4543 | struct lpfc_hba *phba = vport->phba; |
4417 | uint8_t *pcmd; | 4544 | uint8_t *pcmd; |
@@ -4909,7 +5036,7 @@ lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc, | |||
4909 | memcpy(desc->opd_info.vendor_name, &page_a0[SSF_VENDOR_NAME], 16); | 5036 | memcpy(desc->opd_info.vendor_name, &page_a0[SSF_VENDOR_NAME], 16); |
4910 | memcpy(desc->opd_info.model_number, &page_a0[SSF_VENDOR_PN], 16); | 5037 | memcpy(desc->opd_info.model_number, &page_a0[SSF_VENDOR_PN], 16); |
4911 | memcpy(desc->opd_info.serial_number, &page_a0[SSF_VENDOR_SN], 16); | 5038 | memcpy(desc->opd_info.serial_number, &page_a0[SSF_VENDOR_SN], 16); |
4912 | memcpy(desc->opd_info.revision, &page_a0[SSF_VENDOR_REV], 2); | 5039 | memcpy(desc->opd_info.revision, &page_a0[SSF_VENDOR_REV], 4); |
4913 | memcpy(desc->opd_info.date, &page_a0[SSF_DATE_CODE], 8); | 5040 | memcpy(desc->opd_info.date, &page_a0[SSF_DATE_CODE], 8); |
4914 | desc->length = cpu_to_be32(sizeof(desc->opd_info)); | 5041 | desc->length = cpu_to_be32(sizeof(desc->opd_info)); |
4915 | return sizeof(struct fc_rdp_opd_sfp_desc); | 5042 | return sizeof(struct fc_rdp_opd_sfp_desc); |
@@ -5004,7 +5131,7 @@ lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc, | |||
5004 | memcpy(desc->port_names.wwnn, phba->wwnn, | 5131 | memcpy(desc->port_names.wwnn, phba->wwnn, |
5005 | sizeof(desc->port_names.wwnn)); | 5132 | sizeof(desc->port_names.wwnn)); |
5006 | 5133 | ||
5007 | memcpy(desc->port_names.wwpn, &phba->wwpn, | 5134 | memcpy(desc->port_names.wwpn, phba->wwpn, |
5008 | sizeof(desc->port_names.wwpn)); | 5135 | sizeof(desc->port_names.wwpn)); |
5009 | 5136 | ||
5010 | desc->length = cpu_to_be32(sizeof(desc->port_names)); | 5137 | desc->length = cpu_to_be32(sizeof(desc->port_names)); |
@@ -5233,9 +5360,8 @@ lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
5233 | struct ls_rjt stat; | 5360 | struct ls_rjt stat; |
5234 | 5361 | ||
5235 | if (phba->sli_rev < LPFC_SLI_REV4 || | 5362 | if (phba->sli_rev < LPFC_SLI_REV4 || |
5236 | (bf_get(lpfc_sli_intf_if_type, | 5363 | bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != |
5237 | &phba->sli4_hba.sli_intf) != | 5364 | LPFC_SLI_INTF_IF_TYPE_2) { |
5238 | LPFC_SLI_INTF_IF_TYPE_2)) { | ||
5239 | rjt_err = LSRJT_UNABLE_TPC; | 5365 | rjt_err = LSRJT_UNABLE_TPC; |
5240 | rjt_expl = LSEXP_REQ_UNSUPPORTED; | 5366 | rjt_expl = LSEXP_REQ_UNSUPPORTED; |
5241 | goto error; | 5367 | goto error; |
@@ -5976,9 +6102,11 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) | |||
5976 | if (ndlp && NLP_CHK_NODE_ACT(ndlp) | 6102 | if (ndlp && NLP_CHK_NODE_ACT(ndlp) |
5977 | && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { | 6103 | && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
5978 | /* Good ndlp, issue CT Request to NameServer */ | 6104 | /* Good ndlp, issue CT Request to NameServer */ |
5979 | if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0) | 6105 | vport->gidft_inp = 0; |
6106 | if (lpfc_issue_gidft(vport) == 0) | ||
5980 | /* Wait for NameServer query cmpl before we can | 6107 | /* Wait for NameServer query cmpl before we can |
5981 | continue */ | 6108 | * continue |
6109 | */ | ||
5982 | return 1; | 6110 | return 1; |
5983 | } else { | 6111 | } else { |
5984 | /* If login to NameServer does not exist, issue one */ | 6112 | /* If login to NameServer does not exist, issue one */ |
@@ -6082,7 +6210,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
6082 | 6210 | ||
6083 | (void) lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1); | 6211 | (void) lpfc_check_sparm(vport, ndlp, sp, CLASS3, 1); |
6084 | 6212 | ||
6085 | |||
6086 | /* | 6213 | /* |
6087 | * If our portname is greater than the remote portname, | 6214 | * If our portname is greater than the remote portname, |
6088 | * then we initiate Nport login. | 6215 | * then we initiate Nport login. |
@@ -7779,6 +7906,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
7779 | lpfc_els_rcv_fan(vport, elsiocb, ndlp); | 7906 | lpfc_els_rcv_fan(vport, elsiocb, ndlp); |
7780 | break; | 7907 | break; |
7781 | case ELS_CMD_PRLI: | 7908 | case ELS_CMD_PRLI: |
7909 | case ELS_CMD_NVMEPRLI: | ||
7782 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 7910 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
7783 | "RCV PRLI: did:x%x/ste:x%x flg:x%x", | 7911 | "RCV PRLI: did:x%x/ste:x%x flg:x%x", |
7784 | did, vport->port_state, ndlp->nlp_flag); | 7912 | did, vport->port_state, ndlp->nlp_flag); |
@@ -8883,8 +9011,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
8883 | break; | 9011 | break; |
8884 | } | 9012 | } |
8885 | 9013 | ||
8886 | if (atomic_read(&phba->fabric_iocb_count) == 0) | 9014 | BUG_ON(atomic_read(&phba->fabric_iocb_count) == 0); |
8887 | BUG(); | ||
8888 | 9015 | ||
8889 | cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl; | 9016 | cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl; |
8890 | cmdiocb->fabric_iocb_cmpl = NULL; | 9017 | cmdiocb->fabric_iocb_cmpl = NULL; |
@@ -8929,8 +9056,7 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) | |||
8929 | int ready; | 9056 | int ready; |
8930 | int ret; | 9057 | int ret; |
8931 | 9058 | ||
8932 | if (atomic_read(&phba->fabric_iocb_count) > 1) | 9059 | BUG_ON(atomic_read(&phba->fabric_iocb_count) > 1); |
8933 | BUG(); | ||
8934 | 9060 | ||
8935 | spin_lock_irqsave(&phba->hbalock, iflags); | 9061 | spin_lock_irqsave(&phba->hbalock, iflags); |
8936 | ready = atomic_read(&phba->fabric_iocb_count) == 0 && | 9062 | ready = atomic_read(&phba->fabric_iocb_count) == 0 && |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index ede831d1f467..6e64c8e8e44f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -31,6 +31,9 @@ | |||
31 | #include <scsi/scsi_device.h> | 31 | #include <scsi/scsi_device.h> |
32 | #include <scsi/scsi_host.h> | 32 | #include <scsi/scsi_host.h> |
33 | #include <scsi/scsi_transport_fc.h> | 33 | #include <scsi/scsi_transport_fc.h> |
34 | #include <scsi/fc/fc_fs.h> | ||
35 | |||
36 | #include <linux/nvme-fc-driver.h> | ||
34 | 37 | ||
35 | #include "lpfc_hw4.h" | 38 | #include "lpfc_hw4.h" |
36 | #include "lpfc_hw.h" | 39 | #include "lpfc_hw.h" |
@@ -38,8 +41,9 @@ | |||
38 | #include "lpfc_disc.h" | 41 | #include "lpfc_disc.h" |
39 | #include "lpfc_sli.h" | 42 | #include "lpfc_sli.h" |
40 | #include "lpfc_sli4.h" | 43 | #include "lpfc_sli4.h" |
41 | #include "lpfc_scsi.h" | ||
42 | #include "lpfc.h" | 44 | #include "lpfc.h" |
45 | #include "lpfc_scsi.h" | ||
46 | #include "lpfc_nvme.h" | ||
43 | #include "lpfc_logmsg.h" | 47 | #include "lpfc_logmsg.h" |
44 | #include "lpfc_crtn.h" | 48 | #include "lpfc_crtn.h" |
45 | #include "lpfc_vport.h" | 49 | #include "lpfc_vport.h" |
@@ -853,9 +857,12 @@ lpfc_port_link_failure(struct lpfc_vport *vport) | |||
853 | void | 857 | void |
854 | lpfc_linkdown_port(struct lpfc_vport *vport) | 858 | lpfc_linkdown_port(struct lpfc_vport *vport) |
855 | { | 859 | { |
860 | struct lpfc_hba *phba = vport->phba; | ||
856 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 861 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
857 | 862 | ||
858 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKDOWN, 0); | 863 | if (phba->cfg_enable_fc4_type != LPFC_ENABLE_NVME) |
864 | fc_host_post_event(shost, fc_get_event_number(), | ||
865 | FCH_EVT_LINKDOWN, 0); | ||
859 | 866 | ||
860 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, | 867 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
861 | "Link Down: state:x%x rtry:x%x flg:x%x", | 868 | "Link Down: state:x%x rtry:x%x flg:x%x", |
@@ -981,7 +988,9 @@ lpfc_linkup_port(struct lpfc_vport *vport) | |||
981 | (vport != phba->pport)) | 988 | (vport != phba->pport)) |
982 | return; | 989 | return; |
983 | 990 | ||
984 | fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_LINKUP, 0); | 991 | if (phba->cfg_enable_fc4_type != LPFC_ENABLE_NVME) |
992 | fc_host_post_event(shost, fc_get_event_number(), | ||
993 | FCH_EVT_LINKUP, 0); | ||
985 | 994 | ||
986 | spin_lock_irq(shost->host_lock); | 995 | spin_lock_irq(shost->host_lock); |
987 | vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY | | 996 | vport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI | FC_ABORT_DISCOVERY | |
@@ -3570,6 +3579,8 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3570 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 3579 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
3571 | spin_unlock_irq(shost->host_lock); | 3580 | spin_unlock_irq(shost->host_lock); |
3572 | vport->fc_myDID = 0; | 3581 | vport->fc_myDID = 0; |
3582 | |||
3583 | /* todo: init: revise localport nvme attributes */ | ||
3573 | goto out; | 3584 | goto out; |
3574 | } | 3585 | } |
3575 | 3586 | ||
@@ -3819,6 +3830,52 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3819 | return; | 3830 | return; |
3820 | } | 3831 | } |
3821 | 3832 | ||
3833 | /* | ||
3834 | * This routine will issue a GID_FT for each FC4 Type supported | ||
3835 | * by the driver. ALL GID_FTs must complete before discovery is started. | ||
3836 | */ | ||
3837 | int | ||
3838 | lpfc_issue_gidft(struct lpfc_vport *vport) | ||
3839 | { | ||
3840 | struct lpfc_hba *phba = vport->phba; | ||
3841 | |||
3842 | /* Good status, issue CT Request to NameServer */ | ||
3843 | if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
3844 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_FCP)) { | ||
3845 | if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, SLI_CTPT_FCP)) { | ||
3846 | /* Cannot issue NameServer FCP Query, so finish up | ||
3847 | * discovery | ||
3848 | */ | ||
3849 | lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, | ||
3850 | "0604 %s FC TYPE %x %s\n", | ||
3851 | "Failed to issue GID_FT to ", | ||
3852 | FC_TYPE_FCP, | ||
3853 | "Finishing discovery."); | ||
3854 | return 0; | ||
3855 | } | ||
3856 | vport->gidft_inp++; | ||
3857 | } | ||
3858 | |||
3859 | if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
3860 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { | ||
3861 | if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, SLI_CTPT_NVME)) { | ||
3862 | /* Cannot issue NameServer NVME Query, so finish up | ||
3863 | * discovery | ||
3864 | */ | ||
3865 | lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI, | ||
3866 | "0605 %s FC_TYPE %x %s %d\n", | ||
3867 | "Failed to issue GID_FT to ", | ||
3868 | FC_TYPE_NVME, | ||
3869 | "Finishing discovery: gidftinp ", | ||
3870 | vport->gidft_inp); | ||
3871 | if (vport->gidft_inp == 0) | ||
3872 | return 0; | ||
3873 | } else | ||
3874 | vport->gidft_inp++; | ||
3875 | } | ||
3876 | return vport->gidft_inp; | ||
3877 | } | ||
3878 | |||
3822 | /* | 3879 | /* |
3823 | * This routine handles processing a NameServer REG_LOGIN mailbox | 3880 | * This routine handles processing a NameServer REG_LOGIN mailbox |
3824 | * command upon completion. It is setup in the LPFC_MBOXQ | 3881 | * command upon completion. It is setup in the LPFC_MBOXQ |
@@ -3835,12 +3892,14 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3835 | 3892 | ||
3836 | pmb->context1 = NULL; | 3893 | pmb->context1 = NULL; |
3837 | pmb->context2 = NULL; | 3894 | pmb->context2 = NULL; |
3895 | vport->gidft_inp = 0; | ||
3838 | 3896 | ||
3839 | if (mb->mbxStatus) { | 3897 | if (mb->mbxStatus) { |
3840 | out: | ||
3841 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 3898 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
3842 | "0260 Register NameServer error: 0x%x\n", | 3899 | "0260 Register NameServer error: 0x%x\n", |
3843 | mb->mbxStatus); | 3900 | mb->mbxStatus); |
3901 | |||
3902 | out: | ||
3844 | /* decrement the node reference count held for this | 3903 | /* decrement the node reference count held for this |
3845 | * callback function. | 3904 | * callback function. |
3846 | */ | 3905 | */ |
@@ -3884,20 +3943,28 @@ out: | |||
3884 | lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0); | 3943 | lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0); |
3885 | lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0); | 3944 | lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0); |
3886 | lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0); | 3945 | lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0); |
3887 | lpfc_ns_cmd(vport, SLI_CTNS_RFF_ID, 0, 0); | 3946 | |
3947 | if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
3948 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_FCP)) | ||
3949 | lpfc_ns_cmd(vport, SLI_CTNS_RFF_ID, 0, FC_TYPE_FCP); | ||
3950 | |||
3951 | if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
3952 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) | ||
3953 | lpfc_ns_cmd(vport, SLI_CTNS_RFF_ID, 0, FC_TYPE_NVME); | ||
3888 | 3954 | ||
3889 | /* Issue SCR just before NameServer GID_FT Query */ | 3955 | /* Issue SCR just before NameServer GID_FT Query */ |
3890 | lpfc_issue_els_scr(vport, SCR_DID, 0); | 3956 | lpfc_issue_els_scr(vport, SCR_DID, 0); |
3891 | } | 3957 | } |
3892 | 3958 | ||
3893 | vport->fc_ns_retry = 0; | 3959 | vport->fc_ns_retry = 0; |
3894 | /* Good status, issue CT Request to NameServer */ | 3960 | if (lpfc_issue_gidft(vport) == 0) |
3895 | if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0)) { | ||
3896 | /* Cannot issue NameServer Query, so finish up discovery */ | ||
3897 | goto out; | 3961 | goto out; |
3898 | } | ||
3899 | 3962 | ||
3900 | /* decrement the node reference count held for this | 3963 | /* |
3964 | * At this point in time we may need to wait for multiple | ||
3965 | * SLI_CTNS_GID_FT CT commands to complete before we start discovery. | ||
3966 | * | ||
3967 | * decrement the node reference count held for this | ||
3901 | * callback function. | 3968 | * callback function. |
3902 | */ | 3969 | */ |
3903 | lpfc_nlp_put(ndlp); | 3970 | lpfc_nlp_put(ndlp); |
@@ -3990,6 +4057,10 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp) | |||
3990 | { | 4057 | { |
3991 | struct fc_rport *rport = ndlp->rport; | 4058 | struct fc_rport *rport = ndlp->rport; |
3992 | struct lpfc_vport *vport = ndlp->vport; | 4059 | struct lpfc_vport *vport = ndlp->vport; |
4060 | struct lpfc_hba *phba = vport->phba; | ||
4061 | |||
4062 | if (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME) | ||
4063 | return; | ||
3993 | 4064 | ||
3994 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | 4065 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, |
3995 | "rport delete: did:x%x flg:x%x type x%x", | 4066 | "rport delete: did:x%x flg:x%x type x%x", |
@@ -4047,6 +4118,7 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4047 | int old_state, int new_state) | 4118 | int old_state, int new_state) |
4048 | { | 4119 | { |
4049 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 4120 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
4121 | struct lpfc_hba *phba = vport->phba; | ||
4050 | 4122 | ||
4051 | if (new_state == NLP_STE_UNMAPPED_NODE) { | 4123 | if (new_state == NLP_STE_UNMAPPED_NODE) { |
4052 | ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; | 4124 | ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; |
@@ -4057,23 +4129,51 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4057 | if (new_state == NLP_STE_NPR_NODE) | 4129 | if (new_state == NLP_STE_NPR_NODE) |
4058 | ndlp->nlp_flag &= ~NLP_RCV_PLOGI; | 4130 | ndlp->nlp_flag &= ~NLP_RCV_PLOGI; |
4059 | 4131 | ||
4060 | /* Transport interface */ | 4132 | /* FCP and NVME Transport interface */ |
4061 | if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE || | 4133 | if ((old_state == NLP_STE_MAPPED_NODE || |
4062 | old_state == NLP_STE_UNMAPPED_NODE)) { | 4134 | old_state == NLP_STE_UNMAPPED_NODE)) { |
4063 | vport->phba->nport_event_cnt++; | 4135 | if (ndlp->rport) { |
4064 | lpfc_unregister_remote_port(ndlp); | 4136 | vport->phba->nport_event_cnt++; |
4137 | lpfc_unregister_remote_port(ndlp); | ||
4138 | } | ||
4139 | |||
4140 | /* Notify the NVME transport of this rport's loss */ | ||
4141 | if (((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
4142 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) && | ||
4143 | (vport->phba->nvmet_support == 0) && | ||
4144 | ((ndlp->nlp_fc4_type & NLP_FC4_NVME) || | ||
4145 | (ndlp->nlp_DID == Fabric_DID))) { | ||
4146 | vport->phba->nport_event_cnt++; | ||
4147 | /* todo: init: unregister rport from nvme */ | ||
4148 | } | ||
4065 | } | 4149 | } |
4066 | 4150 | ||
4151 | /* FCP and NVME Transport interfaces */ | ||
4152 | |||
4067 | if (new_state == NLP_STE_MAPPED_NODE || | 4153 | if (new_state == NLP_STE_MAPPED_NODE || |
4068 | new_state == NLP_STE_UNMAPPED_NODE) { | 4154 | new_state == NLP_STE_UNMAPPED_NODE) { |
4069 | vport->phba->nport_event_cnt++; | 4155 | if ((ndlp->nlp_fc4_type & NLP_FC4_FCP) || |
4070 | /* | 4156 | (ndlp->nlp_DID == Fabric_DID)) { |
4071 | * Tell the fc transport about the port, if we haven't | 4157 | vport->phba->nport_event_cnt++; |
4072 | * already. If we have, and it's a scsi entity, be | 4158 | /* |
4073 | * sure to unblock any attached scsi devices | 4159 | * Tell the fc transport about the port, if we haven't |
4074 | */ | 4160 | * already. If we have, and it's a scsi entity, be |
4075 | lpfc_register_remote_port(vport, ndlp); | 4161 | */ |
4162 | lpfc_register_remote_port(vport, ndlp); | ||
4163 | } | ||
4164 | /* Notify the NVME transport of this new rport. */ | ||
4165 | if (ndlp->nlp_fc4_type & NLP_FC4_NVME) { | ||
4166 | if (vport->phba->nvmet_support == 0) { | ||
4167 | /* Register this rport with the transport. | ||
4168 | * Initiators take the NDLP ref count in | ||
4169 | * the register. | ||
4170 | */ | ||
4171 | vport->phba->nport_event_cnt++; | ||
4172 | /* todo: init: register rport with nvme */ | ||
4173 | } | ||
4174 | } | ||
4076 | } | 4175 | } |
4176 | |||
4077 | if ((new_state == NLP_STE_MAPPED_NODE) && | 4177 | if ((new_state == NLP_STE_MAPPED_NODE) && |
4078 | (vport->stat_data_enabled)) { | 4178 | (vport->stat_data_enabled)) { |
4079 | /* | 4179 | /* |
@@ -4091,12 +4191,13 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4091 | "0x%x\n", ndlp->nlp_DID); | 4191 | "0x%x\n", ndlp->nlp_DID); |
4092 | } | 4192 | } |
4093 | /* | 4193 | /* |
4094 | * if we added to Mapped list, but the remote port | 4194 | * If the node just added to Mapped list was an FCP target, |
4095 | * registration failed or assigned a target id outside | 4195 | * but the remote port registration failed or assigned a target |
4096 | * our presentable range - move the node to the | 4196 | * id outside the presentable range - move the node to the |
4097 | * Unmapped List | 4197 | * Unmapped List. |
4098 | */ | 4198 | */ |
4099 | if (new_state == NLP_STE_MAPPED_NODE && | 4199 | if ((new_state == NLP_STE_MAPPED_NODE) && |
4200 | (ndlp->nlp_type & NLP_FCP_TARGET) && | ||
4100 | (!ndlp->rport || | 4201 | (!ndlp->rport || |
4101 | ndlp->rport->scsi_target_id == -1 || | 4202 | ndlp->rport->scsi_target_id == -1 || |
4102 | ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) { | 4203 | ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) { |
@@ -4230,6 +4331,7 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4230 | ndlp->vport = vport; | 4331 | ndlp->vport = vport; |
4231 | ndlp->phba = vport->phba; | 4332 | ndlp->phba = vport->phba; |
4232 | ndlp->nlp_sid = NLP_NO_SID; | 4333 | ndlp->nlp_sid = NLP_NO_SID; |
4334 | ndlp->nlp_fc4_type = NLP_FC4_NONE; | ||
4233 | kref_init(&ndlp->kref); | 4335 | kref_init(&ndlp->kref); |
4234 | NLP_INT_NODE_ACT(ndlp); | 4336 | NLP_INT_NODE_ACT(ndlp); |
4235 | atomic_set(&ndlp->cmd_pending, 0); | 4337 | atomic_set(&ndlp->cmd_pending, 0); |
@@ -5369,12 +5471,13 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
5369 | switch (vport->port_state) { | 5471 | switch (vport->port_state) { |
5370 | 5472 | ||
5371 | case LPFC_LOCAL_CFG_LINK: | 5473 | case LPFC_LOCAL_CFG_LINK: |
5372 | /* port_state is identically LPFC_LOCAL_CFG_LINK while waiting for | 5474 | /* |
5373 | * FAN | 5475 | * port_state is identically LPFC_LOCAL_CFG_LINK while |
5374 | */ | 5476 | * waiting for FAN timeout |
5375 | /* FAN timeout */ | 5477 | */ |
5376 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY, | 5478 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY, |
5377 | "0221 FAN timeout\n"); | 5479 | "0221 FAN timeout\n"); |
5480 | |||
5378 | /* Start discovery by sending FLOGI, clean up old rpis */ | 5481 | /* Start discovery by sending FLOGI, clean up old rpis */ |
5379 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, | 5482 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, |
5380 | nlp_listp) { | 5483 | nlp_listp) { |
@@ -5445,8 +5548,8 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) | |||
5445 | if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { | 5548 | if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { |
5446 | /* Try it one more time */ | 5549 | /* Try it one more time */ |
5447 | vport->fc_ns_retry++; | 5550 | vport->fc_ns_retry++; |
5448 | rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, | 5551 | vport->gidft_inp = 0; |
5449 | vport->fc_ns_retry, 0); | 5552 | rc = lpfc_issue_gidft(vport); |
5450 | if (rc == 0) | 5553 | if (rc == 0) |
5451 | break; | 5554 | break; |
5452 | } | 5555 | } |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 28247c99b4f2..883e6d2a7bc7 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -90,8 +90,10 @@ union CtCommandResponse { | |||
90 | uint32_t word; | 90 | uint32_t word; |
91 | }; | 91 | }; |
92 | 92 | ||
93 | #define FC4_FEATURE_INIT 0x2 | 93 | /* FC4 Feature bits for RFF_ID */ |
94 | #define FC4_FEATURE_TARGET 0x1 | 94 | #define FC4_FEATURE_TARGET 0x1 |
95 | #define FC4_FEATURE_INIT 0x2 | ||
96 | #define FC4_FEATURE_NVME_DISC 0x4 | ||
95 | 97 | ||
96 | struct lpfc_sli_ct_request { | 98 | struct lpfc_sli_ct_request { |
97 | /* Structure is in Big Endian format */ | 99 | /* Structure is in Big Endian format */ |
@@ -115,6 +117,16 @@ struct lpfc_sli_ct_request { | |||
115 | uint8_t AreaScope; | 117 | uint8_t AreaScope; |
116 | uint8_t Fc4Type; /* for GID_FT requests */ | 118 | uint8_t Fc4Type; /* for GID_FT requests */ |
117 | } gid; | 119 | } gid; |
120 | struct gid_ff { | ||
121 | uint8_t Flags; | ||
122 | uint8_t DomainScope; | ||
123 | uint8_t AreaScope; | ||
124 | uint8_t rsvd1; | ||
125 | uint8_t rsvd2; | ||
126 | uint8_t rsvd3; | ||
127 | uint8_t Fc4FBits; | ||
128 | uint8_t Fc4Type; | ||
129 | } gid_ff; | ||
118 | struct rft { | 130 | struct rft { |
119 | uint32_t PortId; /* For RFT_ID requests */ | 131 | uint32_t PortId; /* For RFT_ID requests */ |
120 | 132 | ||
@@ -159,6 +171,12 @@ struct lpfc_sli_ct_request { | |||
159 | struct gff_acc { | 171 | struct gff_acc { |
160 | uint8_t fbits[128]; | 172 | uint8_t fbits[128]; |
161 | } gff_acc; | 173 | } gff_acc; |
174 | struct gft { | ||
175 | uint32_t PortId; | ||
176 | } gft; | ||
177 | struct gft_acc { | ||
178 | uint32_t fc4_types[8]; | ||
179 | } gft_acc; | ||
162 | #define FCP_TYPE_FEATURE_OFFSET 7 | 180 | #define FCP_TYPE_FEATURE_OFFSET 7 |
163 | struct rff { | 181 | struct rff { |
164 | uint32_t PortId; | 182 | uint32_t PortId; |
@@ -174,8 +192,12 @@ struct lpfc_sli_ct_request { | |||
174 | #define SLI_CT_REVISION 1 | 192 | #define SLI_CT_REVISION 1 |
175 | #define GID_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ | 193 | #define GID_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ |
176 | sizeof(struct gid)) | 194 | sizeof(struct gid)) |
195 | #define GIDFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ | ||
196 | sizeof(struct gid_ff)) | ||
177 | #define GFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ | 197 | #define GFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ |
178 | sizeof(struct gff)) | 198 | sizeof(struct gff)) |
199 | #define GFT_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ | ||
200 | sizeof(struct gft)) | ||
179 | #define RFT_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ | 201 | #define RFT_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ |
180 | sizeof(struct rft)) | 202 | sizeof(struct rft)) |
181 | #define RFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ | 203 | #define RFF_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ |
@@ -271,6 +293,7 @@ struct lpfc_sli_ct_request { | |||
271 | #define SLI_CTNS_GNN_IP 0x0153 | 293 | #define SLI_CTNS_GNN_IP 0x0153 |
272 | #define SLI_CTNS_GIPA_IP 0x0156 | 294 | #define SLI_CTNS_GIPA_IP 0x0156 |
273 | #define SLI_CTNS_GID_FT 0x0171 | 295 | #define SLI_CTNS_GID_FT 0x0171 |
296 | #define SLI_CTNS_GID_FF 0x01F1 | ||
274 | #define SLI_CTNS_GID_PT 0x01A1 | 297 | #define SLI_CTNS_GID_PT 0x01A1 |
275 | #define SLI_CTNS_RPN_ID 0x0212 | 298 | #define SLI_CTNS_RPN_ID 0x0212 |
276 | #define SLI_CTNS_RNN_ID 0x0213 | 299 | #define SLI_CTNS_RNN_ID 0x0213 |
@@ -288,15 +311,16 @@ struct lpfc_sli_ct_request { | |||
288 | * Port Types | 311 | * Port Types |
289 | */ | 312 | */ |
290 | 313 | ||
291 | #define SLI_CTPT_N_PORT 0x01 | 314 | #define SLI_CTPT_N_PORT 0x01 |
292 | #define SLI_CTPT_NL_PORT 0x02 | 315 | #define SLI_CTPT_NL_PORT 0x02 |
293 | #define SLI_CTPT_FNL_PORT 0x03 | 316 | #define SLI_CTPT_FNL_PORT 0x03 |
294 | #define SLI_CTPT_IP 0x04 | 317 | #define SLI_CTPT_IP 0x04 |
295 | #define SLI_CTPT_FCP 0x08 | 318 | #define SLI_CTPT_FCP 0x08 |
296 | #define SLI_CTPT_NX_PORT 0x7F | 319 | #define SLI_CTPT_NVME 0x28 |
297 | #define SLI_CTPT_F_PORT 0x81 | 320 | #define SLI_CTPT_NX_PORT 0x7F |
298 | #define SLI_CTPT_FL_PORT 0x82 | 321 | #define SLI_CTPT_F_PORT 0x81 |
299 | #define SLI_CTPT_E_PORT 0x84 | 322 | #define SLI_CTPT_FL_PORT 0x82 |
323 | #define SLI_CTPT_E_PORT 0x84 | ||
300 | 324 | ||
301 | #define SLI_CT_LAST_ENTRY 0x80000000 | 325 | #define SLI_CT_LAST_ENTRY 0x80000000 |
302 | 326 | ||
@@ -337,6 +361,7 @@ struct lpfc_name { | |||
337 | uint8_t IEEE[6]; /* FC IEEE address */ | 361 | uint8_t IEEE[6]; /* FC IEEE address */ |
338 | } s; | 362 | } s; |
339 | uint8_t wwn[8]; | 363 | uint8_t wwn[8]; |
364 | uint64_t name; | ||
340 | } u; | 365 | } u; |
341 | }; | 366 | }; |
342 | 367 | ||
@@ -549,6 +574,7 @@ struct fc_vft_header { | |||
549 | #define ELS_CMD_REC 0x13000000 | 574 | #define ELS_CMD_REC 0x13000000 |
550 | #define ELS_CMD_RDP 0x18000000 | 575 | #define ELS_CMD_RDP 0x18000000 |
551 | #define ELS_CMD_PRLI 0x20100014 | 576 | #define ELS_CMD_PRLI 0x20100014 |
577 | #define ELS_CMD_NVMEPRLI 0x20140018 | ||
552 | #define ELS_CMD_PRLO 0x21100014 | 578 | #define ELS_CMD_PRLO 0x21100014 |
553 | #define ELS_CMD_PRLO_ACC 0x02100014 | 579 | #define ELS_CMD_PRLO_ACC 0x02100014 |
554 | #define ELS_CMD_PDISC 0x50000000 | 580 | #define ELS_CMD_PDISC 0x50000000 |
@@ -588,6 +614,7 @@ struct fc_vft_header { | |||
588 | #define ELS_CMD_REC 0x13 | 614 | #define ELS_CMD_REC 0x13 |
589 | #define ELS_CMD_RDP 0x18 | 615 | #define ELS_CMD_RDP 0x18 |
590 | #define ELS_CMD_PRLI 0x14001020 | 616 | #define ELS_CMD_PRLI 0x14001020 |
617 | #define ELS_CMD_NVMEPRLI 0x18001420 | ||
591 | #define ELS_CMD_PRLO 0x14001021 | 618 | #define ELS_CMD_PRLO 0x14001021 |
592 | #define ELS_CMD_PRLO_ACC 0x14001002 | 619 | #define ELS_CMD_PRLO_ACC 0x14001002 |
593 | #define ELS_CMD_PDISC 0x50 | 620 | #define ELS_CMD_PDISC 0x50 |
@@ -684,6 +711,7 @@ typedef struct _PRLI { /* Structure is in Big Endian format */ | |||
684 | uint8_t prliType; /* FC Parm Word 0, bit 24:31 */ | 711 | uint8_t prliType; /* FC Parm Word 0, bit 24:31 */ |
685 | 712 | ||
686 | #define PRLI_FCP_TYPE 0x08 | 713 | #define PRLI_FCP_TYPE 0x08 |
714 | #define PRLI_NVME_TYPE 0x28 | ||
687 | uint8_t word0Reserved1; /* FC Parm Word 0, bit 16:23 */ | 715 | uint8_t word0Reserved1; /* FC Parm Word 0, bit 16:23 */ |
688 | 716 | ||
689 | #ifdef __BIG_ENDIAN_BITFIELD | 717 | #ifdef __BIG_ENDIAN_BITFIELD |
@@ -1243,8 +1271,7 @@ struct fc_rdp_opd_sfp_info { | |||
1243 | uint8_t vendor_name[16]; | 1271 | uint8_t vendor_name[16]; |
1244 | uint8_t model_number[16]; | 1272 | uint8_t model_number[16]; |
1245 | uint8_t serial_number[16]; | 1273 | uint8_t serial_number[16]; |
1246 | uint8_t revision[2]; | 1274 | uint8_t revision[4]; |
1247 | uint8_t reserved[2]; | ||
1248 | uint8_t date[8]; | 1275 | uint8_t date[8]; |
1249 | }; | 1276 | }; |
1250 | 1277 | ||
@@ -1263,14 +1290,14 @@ struct fc_rdp_req_frame { | |||
1263 | 1290 | ||
1264 | 1291 | ||
1265 | struct fc_rdp_res_frame { | 1292 | struct fc_rdp_res_frame { |
1266 | uint32_t reply_sequence; /* FC word0 LS_ACC or LS_RJT */ | 1293 | uint32_t reply_sequence; /* FC word0 LS_ACC or LS_RJT */ |
1267 | uint32_t length; /* FC Word 1 */ | 1294 | uint32_t length; /* FC Word 1 */ |
1268 | struct fc_rdp_link_service_desc link_service_desc; /* Word 2 -4 */ | 1295 | struct fc_rdp_link_service_desc link_service_desc; /* Word 2 -4 */ |
1269 | struct fc_rdp_sfp_desc sfp_desc; /* Word 5 -9 */ | 1296 | struct fc_rdp_sfp_desc sfp_desc; /* Word 5 -9 */ |
1270 | struct fc_rdp_port_speed_desc portspeed_desc; /* Word 10-12 */ | 1297 | struct fc_rdp_port_speed_desc portspeed_desc; /* Word 10 -12 */ |
1271 | struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13-21 */ | 1298 | struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13 -21 */ |
1272 | struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22-27 */ | 1299 | struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22 -27 */ |
1273 | struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28-33 */ | 1300 | struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28 -33 */ |
1274 | struct fc_fec_rdp_desc fec_desc; /* FC word 34-37*/ | 1301 | struct fc_fec_rdp_desc fec_desc; /* FC word 34-37*/ |
1275 | struct fc_rdp_bbc_desc bbc_desc; /* FC Word 38-42*/ | 1302 | struct fc_rdp_bbc_desc bbc_desc; /* FC Word 38-42*/ |
1276 | struct fc_rdp_oed_sfp_desc oed_temp_desc; /* FC Word 43-47*/ | 1303 | struct fc_rdp_oed_sfp_desc oed_temp_desc; /* FC Word 43-47*/ |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index c3277c5312c9..fcc083cc00e0 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -3922,6 +3922,49 @@ struct gen_req64_wqe { | |||
3922 | uint32_t max_response_payload_len; | 3922 | uint32_t max_response_payload_len; |
3923 | }; | 3923 | }; |
3924 | 3924 | ||
3925 | /* Define NVME PRLI request to fabric. NVME is a | ||
3926 | * fabric-only protocol. | ||
3927 | * Updated to red-lined v1.08 on Sept 16, 2016 | ||
3928 | */ | ||
3929 | struct lpfc_nvme_prli { | ||
3930 | uint32_t word1; | ||
3931 | /* The Response Code is defined in the FCP PRLI lpfc_hw.h */ | ||
3932 | #define prli_acc_rsp_code_SHIFT 8 | ||
3933 | #define prli_acc_rsp_code_MASK 0x0000000f | ||
3934 | #define prli_acc_rsp_code_WORD word1 | ||
3935 | #define prli_estabImagePair_SHIFT 13 | ||
3936 | #define prli_estabImagePair_MASK 0x00000001 | ||
3937 | #define prli_estabImagePair_WORD word1 | ||
3938 | #define prli_type_code_ext_SHIFT 16 | ||
3939 | #define prli_type_code_ext_MASK 0x000000ff | ||
3940 | #define prli_type_code_ext_WORD word1 | ||
3941 | #define prli_type_code_SHIFT 24 | ||
3942 | #define prli_type_code_MASK 0x000000ff | ||
3943 | #define prli_type_code_WORD word1 | ||
3944 | uint32_t word_rsvd2; | ||
3945 | uint32_t word_rsvd3; | ||
3946 | uint32_t word4; | ||
3947 | #define prli_fba_SHIFT 0 | ||
3948 | #define prli_fba_MASK 0x00000001 | ||
3949 | #define prli_fba_WORD word4 | ||
3950 | #define prli_disc_SHIFT 3 | ||
3951 | #define prli_disc_MASK 0x00000001 | ||
3952 | #define prli_disc_WORD word4 | ||
3953 | #define prli_tgt_SHIFT 4 | ||
3954 | #define prli_tgt_MASK 0x00000001 | ||
3955 | #define prli_tgt_WORD word4 | ||
3956 | #define prli_init_SHIFT 5 | ||
3957 | #define prli_init_MASK 0x00000001 | ||
3958 | #define prli_init_WORD word4 | ||
3959 | #define prli_recov_SHIFT 8 | ||
3960 | #define prli_recov_MASK 0x00000001 | ||
3961 | #define prli_recov_WORD word4 | ||
3962 | uint32_t word5; | ||
3963 | #define prli_fb_sz_SHIFT 0 | ||
3964 | #define prli_fb_sz_MASK 0x0000ffff | ||
3965 | #define prli_fb_sz_WORD word5 | ||
3966 | }; | ||
3967 | |||
3925 | struct create_xri_wqe { | 3968 | struct create_xri_wqe { |
3926 | uint32_t rsrvd[5]; /* words 0-4 */ | 3969 | uint32_t rsrvd[5]; /* words 0-4 */ |
3927 | struct wqe_did wqe_dest; /* word 5 */ | 3970 | struct wqe_did wqe_dest; /* word 5 */ |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 57087ba4834f..e609afaa472a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -2667,6 +2667,13 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
2667 | lpfc_disc_state_machine(vport, ndlp, NULL, | 2667 | lpfc_disc_state_machine(vport, ndlp, NULL, |
2668 | NLP_EVT_DEVICE_RECOVERY); | 2668 | NLP_EVT_DEVICE_RECOVERY); |
2669 | 2669 | ||
2670 | if (ndlp->nlp_fc4_type & NLP_FC4_NVME) { | ||
2671 | /* Remove the NVME transport reference now and | ||
2672 | * continue to remove the node. | ||
2673 | */ | ||
2674 | lpfc_nlp_put(ndlp); | ||
2675 | } | ||
2676 | |||
2670 | lpfc_disc_state_machine(vport, ndlp, NULL, | 2677 | lpfc_disc_state_machine(vport, ndlp, NULL, |
2671 | NLP_EVT_DEVICE_RM); | 2678 | NLP_EVT_DEVICE_RM); |
2672 | } | 2679 | } |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 835ea9f78219..65e7b2433ee7 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <scsi/scsi_device.h> | 28 | #include <scsi/scsi_device.h> |
29 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
30 | #include <scsi/scsi_transport_fc.h> | 30 | #include <scsi/scsi_transport_fc.h> |
31 | #include <scsi/fc/fc_fs.h> | ||
32 | |||
33 | #include <linux/nvme-fc-driver.h> | ||
31 | 34 | ||
32 | #include "lpfc_hw4.h" | 35 | #include "lpfc_hw4.h" |
33 | #include "lpfc_hw.h" | 36 | #include "lpfc_hw.h" |
@@ -35,8 +38,9 @@ | |||
35 | #include "lpfc_sli4.h" | 38 | #include "lpfc_sli4.h" |
36 | #include "lpfc_nl.h" | 39 | #include "lpfc_nl.h" |
37 | #include "lpfc_disc.h" | 40 | #include "lpfc_disc.h" |
38 | #include "lpfc_scsi.h" | ||
39 | #include "lpfc.h" | 41 | #include "lpfc.h" |
42 | #include "lpfc_scsi.h" | ||
43 | #include "lpfc_nvme.h" | ||
40 | #include "lpfc_logmsg.h" | 44 | #include "lpfc_logmsg.h" |
41 | #include "lpfc_crtn.h" | 45 | #include "lpfc_crtn.h" |
42 | #include "lpfc_vport.h" | 46 | #include "lpfc_vport.h" |
@@ -708,6 +712,7 @@ static void | |||
708 | lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 712 | lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
709 | struct lpfc_iocbq *cmdiocb) | 713 | struct lpfc_iocbq *cmdiocb) |
710 | { | 714 | { |
715 | struct lpfc_hba *phba = vport->phba; | ||
711 | struct lpfc_dmabuf *pcmd; | 716 | struct lpfc_dmabuf *pcmd; |
712 | uint32_t *lp; | 717 | uint32_t *lp; |
713 | PRLI *npr; | 718 | PRLI *npr; |
@@ -721,11 +726,19 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
721 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); | 726 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); |
722 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; | 727 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; |
723 | ndlp->nlp_flag &= ~NLP_FIRSTBURST; | 728 | ndlp->nlp_flag &= ~NLP_FIRSTBURST; |
724 | if (npr->prliType == PRLI_FCP_TYPE) { | 729 | if ((npr->prliType == PRLI_FCP_TYPE) || |
725 | if (npr->initiatorFunc) | 730 | (npr->prliType == PRLI_NVME_TYPE)) { |
726 | ndlp->nlp_type |= NLP_FCP_INITIATOR; | 731 | if (npr->initiatorFunc) { |
732 | if (npr->prliType == PRLI_FCP_TYPE) | ||
733 | ndlp->nlp_type |= NLP_FCP_INITIATOR; | ||
734 | if (npr->prliType == PRLI_NVME_TYPE) | ||
735 | ndlp->nlp_type |= NLP_NVME_INITIATOR; | ||
736 | } | ||
727 | if (npr->targetFunc) { | 737 | if (npr->targetFunc) { |
728 | ndlp->nlp_type |= NLP_FCP_TARGET; | 738 | if (npr->prliType == PRLI_FCP_TYPE) |
739 | ndlp->nlp_type |= NLP_FCP_TARGET; | ||
740 | if (npr->prliType == PRLI_NVME_TYPE) | ||
741 | ndlp->nlp_type |= NLP_NVME_TARGET; | ||
729 | if (npr->writeXferRdyDis) | 742 | if (npr->writeXferRdyDis) |
730 | ndlp->nlp_flag |= NLP_FIRSTBURST; | 743 | ndlp->nlp_flag |= NLP_FIRSTBURST; |
731 | } | 744 | } |
@@ -744,7 +757,8 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
744 | "rport rolechg: role:x%x did:x%x flg:x%x", | 757 | "rport rolechg: role:x%x did:x%x flg:x%x", |
745 | roles, ndlp->nlp_DID, ndlp->nlp_flag); | 758 | roles, ndlp->nlp_DID, ndlp->nlp_flag); |
746 | 759 | ||
747 | fc_remote_port_rolechg(rport, roles); | 760 | if (phba->cfg_enable_fc4_type != LPFC_ENABLE_NVME) |
761 | fc_remote_port_rolechg(rport, roles); | ||
748 | } | 762 | } |
749 | } | 763 | } |
750 | 764 | ||
@@ -1491,7 +1505,9 @@ lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport, | |||
1491 | { | 1505 | { |
1492 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1506 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1493 | 1507 | ||
1508 | /* Initiator mode. */ | ||
1494 | lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); | 1509 | lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); |
1510 | |||
1495 | return ndlp->nlp_state; | 1511 | return ndlp->nlp_state; |
1496 | } | 1512 | } |
1497 | 1513 | ||
@@ -1574,9 +1590,11 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
1574 | uint32_t evt) | 1590 | uint32_t evt) |
1575 | { | 1591 | { |
1576 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1592 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1593 | struct lpfc_hba *phba = vport->phba; | ||
1577 | LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg; | 1594 | LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg; |
1578 | MAILBOX_t *mb = &pmb->u.mb; | 1595 | MAILBOX_t *mb = &pmb->u.mb; |
1579 | uint32_t did = mb->un.varWords[1]; | 1596 | uint32_t did = mb->un.varWords[1]; |
1597 | int rc = 0; | ||
1580 | 1598 | ||
1581 | if (mb->mbxStatus) { | 1599 | if (mb->mbxStatus) { |
1582 | /* RegLogin failed */ | 1600 | /* RegLogin failed */ |
@@ -1611,19 +1629,52 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
1611 | } | 1629 | } |
1612 | 1630 | ||
1613 | /* SLI4 ports have preallocated logical rpis. */ | 1631 | /* SLI4 ports have preallocated logical rpis. */ |
1614 | if (vport->phba->sli_rev < LPFC_SLI_REV4) | 1632 | if (phba->sli_rev < LPFC_SLI_REV4) |
1615 | ndlp->nlp_rpi = mb->un.varWords[0]; | 1633 | ndlp->nlp_rpi = mb->un.varWords[0]; |
1616 | 1634 | ||
1617 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 1635 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
1618 | 1636 | ||
1619 | /* Only if we are not a fabric nport do we issue PRLI */ | 1637 | /* Only if we are not a fabric nport do we issue PRLI */ |
1620 | if (!(ndlp->nlp_type & NLP_FABRIC)) { | 1638 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
1639 | "3066 RegLogin Complete on x%x x%x x%x\n", | ||
1640 | did, ndlp->nlp_type, ndlp->nlp_fc4_type); | ||
1641 | if (!(ndlp->nlp_type & NLP_FABRIC) && | ||
1642 | (phba->nvmet_support == 0)) { | ||
1643 | /* The driver supports FCP and NVME concurrently. If the | ||
1644 | * ndlp's nlp_fc4_type is still zero, the driver doesn't | ||
1645 | * know what PRLI to send yet. Figure that out now and | ||
1646 | * call PRLI depending on the outcome. | ||
1647 | */ | ||
1648 | if (vport->fc_flag & FC_PT2PT) { | ||
1649 | /* If we are pt2pt, there is no Fabric to determine | ||
1650 | * the FC4 type of the remote nport. So if NVME | ||
1651 | * is configured try it. | ||
1652 | */ | ||
1653 | ndlp->nlp_fc4_type |= NLP_FC4_FCP; | ||
1654 | if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || | ||
1655 | (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { | ||
1656 | ndlp->nlp_fc4_type |= NLP_FC4_NVME; | ||
1657 | /* We need to update the localport also */ | ||
1658 | /* todo: init: revise localport nvme | ||
1659 | * attributes | ||
1660 | */ | ||
1661 | } | ||
1662 | |||
1663 | } else if (ndlp->nlp_fc4_type == 0) { | ||
1664 | rc = lpfc_ns_cmd(vport, SLI_CTNS_GFT_ID, | ||
1665 | 0, ndlp->nlp_DID); | ||
1666 | return ndlp->nlp_state; | ||
1667 | } | ||
1668 | |||
1621 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1669 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1622 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); | 1670 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); |
1623 | lpfc_issue_els_prli(vport, ndlp, 0); | 1671 | lpfc_issue_els_prli(vport, ndlp, 0); |
1624 | } else { | 1672 | } else { |
1625 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1673 | /* Only Fabric ports should transition */ |
1626 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 1674 | if (ndlp->nlp_type & NLP_FABRIC) { |
1675 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | ||
1676 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | ||
1677 | } | ||
1627 | } | 1678 | } |
1628 | return ndlp->nlp_state; | 1679 | return ndlp->nlp_state; |
1629 | } | 1680 | } |
@@ -1664,7 +1715,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, | |||
1664 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1715 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1665 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | 1716 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1666 | spin_lock_irq(shost->host_lock); | 1717 | spin_lock_irq(shost->host_lock); |
1667 | ndlp->nlp_flag |= NLP_IGNR_REG_CMPL; | 1718 | |
1668 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1719 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1669 | spin_unlock_irq(shost->host_lock); | 1720 | spin_unlock_irq(shost->host_lock); |
1670 | lpfc_disc_set_adisc(vport, ndlp); | 1721 | lpfc_disc_set_adisc(vport, ndlp); |
@@ -1740,10 +1791,23 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1740 | struct lpfc_hba *phba = vport->phba; | 1791 | struct lpfc_hba *phba = vport->phba; |
1741 | IOCB_t *irsp; | 1792 | IOCB_t *irsp; |
1742 | PRLI *npr; | 1793 | PRLI *npr; |
1794 | struct lpfc_nvme_prli *nvpr; | ||
1795 | void *temp_ptr; | ||
1743 | 1796 | ||
1744 | cmdiocb = (struct lpfc_iocbq *) arg; | 1797 | cmdiocb = (struct lpfc_iocbq *) arg; |
1745 | rspiocb = cmdiocb->context_un.rsp_iocb; | 1798 | rspiocb = cmdiocb->context_un.rsp_iocb; |
1746 | npr = (PRLI *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb); | 1799 | |
1800 | /* A solicited PRLI is either FCP or NVME. The PRLI cmd/rsp | ||
1801 | * format is different so NULL the two PRLI types so that the | ||
1802 | * driver correctly gets the correct context. | ||
1803 | */ | ||
1804 | npr = NULL; | ||
1805 | nvpr = NULL; | ||
1806 | temp_ptr = lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb); | ||
1807 | if (cmdiocb->iocb_flag & LPFC_PRLI_FCP_REQ) | ||
1808 | npr = (PRLI *) temp_ptr; | ||
1809 | else if (cmdiocb->iocb_flag & LPFC_PRLI_NVME_REQ) | ||
1810 | nvpr = (struct lpfc_nvme_prli *) temp_ptr; | ||
1747 | 1811 | ||
1748 | irsp = &rspiocb->iocb; | 1812 | irsp = &rspiocb->iocb; |
1749 | if (irsp->ulpStatus) { | 1813 | if (irsp->ulpStatus) { |
@@ -1751,7 +1815,21 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1751 | vport->cfg_restrict_login) { | 1815 | vport->cfg_restrict_login) { |
1752 | goto out; | 1816 | goto out; |
1753 | } | 1817 | } |
1818 | |||
1819 | /* The LS Req had some error. Don't let this be a | ||
1820 | * target. | ||
1821 | */ | ||
1822 | if ((ndlp->fc4_prli_sent == 1) && | ||
1823 | (ndlp->nlp_state == NLP_STE_PRLI_ISSUE) && | ||
1824 | (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_FCP_INITIATOR))) | ||
1825 | /* The FCP PRLI completed successfully but | ||
1826 | * the NVME PRLI failed. Since they are sent in | ||
1827 | * succession, allow the FCP to complete. | ||
1828 | */ | ||
1829 | goto out_err; | ||
1830 | |||
1754 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1831 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1832 | ndlp->nlp_type |= NLP_FCP_INITIATOR; | ||
1755 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 1833 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
1756 | return ndlp->nlp_state; | 1834 | return ndlp->nlp_state; |
1757 | } | 1835 | } |
@@ -1759,9 +1837,16 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1759 | /* Check out PRLI rsp */ | 1837 | /* Check out PRLI rsp */ |
1760 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); | 1838 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); |
1761 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; | 1839 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; |
1840 | |||
1841 | /* NVME or FCP first burst must be negotiated for each PRLI. */ | ||
1762 | ndlp->nlp_flag &= ~NLP_FIRSTBURST; | 1842 | ndlp->nlp_flag &= ~NLP_FIRSTBURST; |
1763 | if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) && | 1843 | ndlp->nvme_fb_size = 0; |
1844 | if (npr && (npr->acceptRspCode == PRLI_REQ_EXECUTED) && | ||
1764 | (npr->prliType == PRLI_FCP_TYPE)) { | 1845 | (npr->prliType == PRLI_FCP_TYPE)) { |
1846 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, | ||
1847 | "6028 FCP NPR PRLI Cmpl Init %d Target %d\n", | ||
1848 | npr->initiatorFunc, | ||
1849 | npr->targetFunc); | ||
1765 | if (npr->initiatorFunc) | 1850 | if (npr->initiatorFunc) |
1766 | ndlp->nlp_type |= NLP_FCP_INITIATOR; | 1851 | ndlp->nlp_type |= NLP_FCP_INITIATOR; |
1767 | if (npr->targetFunc) { | 1852 | if (npr->targetFunc) { |
@@ -1771,6 +1856,49 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1771 | } | 1856 | } |
1772 | if (npr->Retry) | 1857 | if (npr->Retry) |
1773 | ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; | 1858 | ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; |
1859 | |||
1860 | /* PRLI completed. Decrement count. */ | ||
1861 | ndlp->fc4_prli_sent--; | ||
1862 | } else if (nvpr && | ||
1863 | (bf_get_be32(prli_acc_rsp_code, nvpr) == | ||
1864 | PRLI_REQ_EXECUTED) && | ||
1865 | (bf_get_be32(prli_type_code, nvpr) == | ||
1866 | PRLI_NVME_TYPE)) { | ||
1867 | |||
1868 | /* Complete setting up the remote ndlp personality. */ | ||
1869 | if (bf_get_be32(prli_init, nvpr)) | ||
1870 | ndlp->nlp_type |= NLP_NVME_INITIATOR; | ||
1871 | |||
1872 | /* Target driver cannot solicit NVME FB. */ | ||
1873 | if (bf_get_be32(prli_tgt, nvpr)) { | ||
1874 | ndlp->nlp_type |= NLP_NVME_TARGET; | ||
1875 | if ((bf_get_be32(prli_fba, nvpr) == 1) && | ||
1876 | (bf_get_be32(prli_fb_sz, nvpr) > 0) && | ||
1877 | (phba->cfg_nvme_enable_fb) && | ||
1878 | (!phba->nvmet_support)) { | ||
1879 | /* Both sides support FB. The target's first | ||
1880 | * burst size is a 512 byte encoded value. | ||
1881 | */ | ||
1882 | ndlp->nlp_flag |= NLP_FIRSTBURST; | ||
1883 | ndlp->nvme_fb_size = bf_get_be32(prli_fb_sz, | ||
1884 | nvpr); | ||
1885 | } | ||
1886 | } | ||
1887 | |||
1888 | if (bf_get_be32(prli_recov, nvpr)) | ||
1889 | ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; | ||
1890 | |||
1891 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, | ||
1892 | "6029 NVME PRLI Cmpl w1 x%08x " | ||
1893 | "w4 x%08x w5 x%08x flag x%x, " | ||
1894 | "fcp_info x%x nlp_type x%x\n", | ||
1895 | be32_to_cpu(nvpr->word1), | ||
1896 | be32_to_cpu(nvpr->word4), | ||
1897 | be32_to_cpu(nvpr->word5), | ||
1898 | ndlp->nlp_flag, ndlp->nlp_fcp_info, | ||
1899 | ndlp->nlp_type); | ||
1900 | /* PRLI completed. Decrement count. */ | ||
1901 | ndlp->fc4_prli_sent--; | ||
1774 | } | 1902 | } |
1775 | if (!(ndlp->nlp_type & NLP_FCP_TARGET) && | 1903 | if (!(ndlp->nlp_type & NLP_FCP_TARGET) && |
1776 | (vport->port_type == LPFC_NPIV_PORT) && | 1904 | (vport->port_type == LPFC_NPIV_PORT) && |
@@ -1786,11 +1914,24 @@ out: | |||
1786 | return ndlp->nlp_state; | 1914 | return ndlp->nlp_state; |
1787 | } | 1915 | } |
1788 | 1916 | ||
1789 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1917 | out_err: |
1790 | if (ndlp->nlp_type & NLP_FCP_TARGET) | 1918 | /* The ndlp state cannot move to MAPPED or UNMAPPED before all PRLIs |
1791 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); | 1919 | * are complete. |
1792 | else | 1920 | */ |
1793 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 1921 | if (ndlp->fc4_prli_sent == 0) { |
1922 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | ||
1923 | if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) | ||
1924 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); | ||
1925 | else | ||
1926 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | ||
1927 | } else | ||
1928 | lpfc_printf_vlog(vport, | ||
1929 | KERN_INFO, LOG_ELS, | ||
1930 | "3067 PRLI's still outstanding " | ||
1931 | "on x%06x - count %d, Pend Node Mode " | ||
1932 | "transition...\n", | ||
1933 | ndlp->nlp_DID, ndlp->fc4_prli_sent); | ||
1934 | |||
1794 | return ndlp->nlp_state; | 1935 | return ndlp->nlp_state; |
1795 | } | 1936 | } |
1796 | 1937 | ||
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c327fc7b1a54..6ba2b3412337 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -5333,7 +5333,8 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) | |||
5333 | continue; | 5333 | continue; |
5334 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && | 5334 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && |
5335 | ndlp->nlp_sid == i && | 5335 | ndlp->nlp_sid == i && |
5336 | ndlp->rport) { | 5336 | ndlp->rport && |
5337 | ndlp->nlp_type & NLP_FCP_TARGET) { | ||
5337 | match = 1; | 5338 | match = 1; |
5338 | break; | 5339 | break; |
5339 | } | 5340 | } |