aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_nportdisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c99
1 files changed, 94 insertions, 5 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index e331204a4d5..b90820a699f 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -493,6 +493,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
493 struct lpfc_iocbq *cmdiocb, uint32_t els_cmd) 493 struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
494{ 494{
495 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 495 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
496 struct lpfc_hba *phba = vport->phba;
497 struct lpfc_vport **vports;
498 int i, active_vlink_present = 0 ;
496 499
497 /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */ 500 /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
498 /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary 501 /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
@@ -505,15 +508,44 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
505 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); 508 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
506 else 509 else
507 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); 510 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
508 if ((ndlp->nlp_DID == Fabric_DID) && 511 if (ndlp->nlp_DID == Fabric_DID) {
509 vport->port_type == LPFC_NPIV_PORT) { 512 if (vport->port_state <= LPFC_FDISC)
513 goto out;
510 lpfc_linkdown_port(vport); 514 lpfc_linkdown_port(vport);
511 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
512 spin_lock_irq(shost->host_lock); 515 spin_lock_irq(shost->host_lock);
513 ndlp->nlp_flag |= NLP_DELAY_TMO; 516 vport->fc_flag |= FC_VPORT_LOGO_RCVD;
514 spin_unlock_irq(shost->host_lock); 517 spin_unlock_irq(shost->host_lock);
518 vports = lpfc_create_vport_work_array(phba);
519 if (vports) {
520 for (i = 0; i <= phba->max_vports && vports[i] != NULL;
521 i++) {
522 if ((!(vports[i]->fc_flag &
523 FC_VPORT_LOGO_RCVD)) &&
524 (vports[i]->port_state > LPFC_FDISC)) {
525 active_vlink_present = 1;
526 break;
527 }
528 }
529 lpfc_destroy_vport_work_array(phba, vports);
530 }
515 531
516 ndlp->nlp_last_elscmd = ELS_CMD_FDISC; 532 if (active_vlink_present) {
533 /*
534 * If there are other active VLinks present,
535 * re-instantiate the Vlink using FDISC.
536 */
537 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
538 spin_lock_irq(shost->host_lock);
539 ndlp->nlp_flag |= NLP_DELAY_TMO;
540 spin_unlock_irq(shost->host_lock);
541 ndlp->nlp_last_elscmd = ELS_CMD_FDISC;
542 vport->port_state = LPFC_FDISC;
543 } else {
544 spin_lock_irq(shost->host_lock);
545 phba->pport->fc_flag &= ~FC_LOGO_RCVD_DID_CHNG;
546 spin_unlock_irq(shost->host_lock);
547 lpfc_retry_pport_discovery(phba);
548 }
517 } else if ((!(ndlp->nlp_type & NLP_FABRIC) && 549 } else if ((!(ndlp->nlp_type & NLP_FABRIC) &&
518 ((ndlp->nlp_type & NLP_FCP_TARGET) || 550 ((ndlp->nlp_type & NLP_FCP_TARGET) ||
519 !(ndlp->nlp_type & NLP_FCP_INITIATOR))) || 551 !(ndlp->nlp_type & NLP_FCP_INITIATOR))) ||
@@ -526,6 +558,7 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
526 558
527 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; 559 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
528 } 560 }
561out:
529 ndlp->nlp_prev_state = ndlp->nlp_state; 562 ndlp->nlp_prev_state = ndlp->nlp_state;
530 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); 563 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
531 564
@@ -604,11 +637,55 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
604 lpfc_unreg_rpi(vport, ndlp); 637 lpfc_unreg_rpi(vport, ndlp);
605 return 0; 638 return 0;
606} 639}
640/**
641 * lpfc_release_rpi - Release a RPI by issueing unreg_login mailbox cmd.
642 * @phba : Pointer to lpfc_hba structure.
643 * @vport: Pointer to lpfc_vport structure.
644 * @rpi : rpi to be release.
645 *
646 * This function will send a unreg_login mailbox command to the firmware
647 * to release a rpi.
648 **/
649void
650lpfc_release_rpi(struct lpfc_hba *phba,
651 struct lpfc_vport *vport,
652 uint16_t rpi)
653{
654 LPFC_MBOXQ_t *pmb;
655 int rc;
656
657 pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
658 GFP_KERNEL);
659 if (!pmb)
660 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
661 "2796 mailbox memory allocation failed \n");
662 else {
663 lpfc_unreg_login(phba, vport->vpi, rpi, pmb);
664 pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
665 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
666 if (rc == MBX_NOT_FINISHED)
667 mempool_free(pmb, phba->mbox_mem_pool);
668 }
669}
607 670
608static uint32_t 671static uint32_t
609lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, 672lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
610 void *arg, uint32_t evt) 673 void *arg, uint32_t evt)
611{ 674{
675 struct lpfc_hba *phba;
676 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
677 MAILBOX_t *mb;
678 uint16_t rpi;
679
680 phba = vport->phba;
681 /* Release the RPI if reglogin completing */
682 if (!(phba->pport->load_flag & FC_UNLOADING) &&
683 (evt == NLP_EVT_CMPL_REG_LOGIN) &&
684 (!pmb->u.mb.mbxStatus)) {
685 mb = &pmb->u.mb;
686 rpi = pmb->u.mb.un.varWords[0];
687 lpfc_release_rpi(phba, vport, rpi);
688 }
612 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, 689 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
613 "0271 Illegal State Transition: node x%x " 690 "0271 Illegal State Transition: node x%x "
614 "event x%x, state x%x Data: x%x x%x\n", 691 "event x%x, state x%x Data: x%x x%x\n",
@@ -944,6 +1021,18 @@ static uint32_t
944lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport, 1021lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport,
945 struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) 1022 struct lpfc_nodelist *ndlp, void *arg, uint32_t evt)
946{ 1023{
1024 struct lpfc_hba *phba;
1025 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
1026 MAILBOX_t *mb = &pmb->u.mb;
1027 uint16_t rpi;
1028
1029 phba = vport->phba;
1030 /* Release the RPI */
1031 if (!(phba->pport->load_flag & FC_UNLOADING) &&
1032 !mb->mbxStatus) {
1033 rpi = pmb->u.mb.un.varWords[0];
1034 lpfc_release_rpi(phba, vport, rpi);
1035 }
947 return ndlp->nlp_state; 1036 return ndlp->nlp_state;
948} 1037}
949 1038