diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 4126fd87956f..b89f6cb641e6 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -648,33 +648,32 @@ lpfc_more_plogi(struct lpfc_hba * phba) | |||
648 | } | 648 | } |
649 | 649 | ||
650 | static struct lpfc_nodelist * | 650 | static struct lpfc_nodelist * |
651 | lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 651 | lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp, |
652 | struct lpfc_nodelist *ndlp) | 652 | struct lpfc_nodelist *ndlp) |
653 | { | 653 | { |
654 | struct lpfc_nodelist *new_ndlp; | 654 | struct lpfc_nodelist *new_ndlp; |
655 | struct lpfc_dmabuf *pcmd, *prsp; | ||
656 | uint32_t *lp; | 655 | uint32_t *lp; |
657 | struct serv_parm *sp; | 656 | struct serv_parm *sp; |
658 | uint8_t name[sizeof (struct lpfc_name)]; | 657 | uint8_t name[sizeof (struct lpfc_name)]; |
659 | uint32_t rc; | 658 | uint32_t rc; |
660 | 659 | ||
661 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
662 | prsp = (struct lpfc_dmabuf *) pcmd->list.next; | ||
663 | lp = (uint32_t *) prsp->virt; | 660 | lp = (uint32_t *) prsp->virt; |
664 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | 661 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); |
662 | memset(name, 0, sizeof (struct lpfc_name)); | ||
665 | 663 | ||
666 | /* Now we to find out if the NPort we are logging into, matches the WWPN | 664 | /* Now we to find out if the NPort we are logging into, matches the WWPN |
667 | * we have for that ndlp. If not, we have some work to do. | 665 | * we have for that ndlp. If not, we have some work to do. |
668 | */ | 666 | */ |
669 | new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName); | 667 | new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName); |
670 | 668 | ||
671 | memset(name, 0, sizeof (struct lpfc_name)); | 669 | if (new_ndlp == ndlp) |
672 | rc = memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)); | ||
673 | if (!rc || (new_ndlp == ndlp)) { | ||
674 | return ndlp; | 670 | return ndlp; |
675 | } | ||
676 | 671 | ||
677 | if (!new_ndlp) { | 672 | if (!new_ndlp) { |
673 | rc = | ||
674 | memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)); | ||
675 | if (!rc) | ||
676 | return ndlp; | ||
678 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); | 677 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); |
679 | if (!new_ndlp) | 678 | if (!new_ndlp) |
680 | return ndlp; | 679 | return ndlp; |
@@ -683,17 +682,21 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
683 | } | 682 | } |
684 | 683 | ||
685 | lpfc_unreg_rpi(phba, new_ndlp); | 684 | lpfc_unreg_rpi(phba, new_ndlp); |
686 | new_ndlp->nlp_prev_state = ndlp->nlp_state; | ||
687 | new_ndlp->nlp_DID = ndlp->nlp_DID; | 685 | new_ndlp->nlp_DID = ndlp->nlp_DID; |
688 | new_ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 686 | new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; |
689 | lpfc_nlp_list(phba, new_ndlp, NLP_PLOGI_LIST); | 687 | new_ndlp->nlp_state = ndlp->nlp_state; |
688 | lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK); | ||
690 | 689 | ||
691 | /* Move this back to NPR list */ | 690 | /* Move this back to NPR list */ |
692 | lpfc_unreg_rpi(phba, ndlp); | 691 | if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) { |
693 | ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ | 692 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
694 | ndlp->nlp_state = NLP_STE_NPR_NODE; | 693 | } |
695 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | 694 | else { |
696 | 695 | lpfc_unreg_rpi(phba, ndlp); | |
696 | ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ | ||
697 | ndlp->nlp_state = NLP_STE_NPR_NODE; | ||
698 | lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST); | ||
699 | } | ||
697 | return new_ndlp; | 700 | return new_ndlp; |
698 | } | 701 | } |
699 | 702 | ||
@@ -703,6 +706,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
703 | { | 706 | { |
704 | IOCB_t *irsp; | 707 | IOCB_t *irsp; |
705 | struct lpfc_nodelist *ndlp; | 708 | struct lpfc_nodelist *ndlp; |
709 | struct lpfc_dmabuf *prsp; | ||
706 | int disc, rc, did, type; | 710 | int disc, rc, did, type; |
707 | 711 | ||
708 | 712 | ||
@@ -769,7 +773,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
769 | } | 773 | } |
770 | } else { | 774 | } else { |
771 | /* Good status, call state machine */ | 775 | /* Good status, call state machine */ |
772 | ndlp = lpfc_plogi_confirm_nport(phba, cmdiocb, ndlp); | 776 | prsp = list_entry(((struct lpfc_dmabuf *) |
777 | cmdiocb->context2)->list.next, | ||
778 | struct lpfc_dmabuf, list); | ||
779 | ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp); | ||
773 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 780 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, |
774 | NLP_EVT_CMPL_PLOGI); | 781 | NLP_EVT_CMPL_PLOGI); |
775 | } | 782 | } |
@@ -3282,10 +3289,9 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3282 | } else | 3289 | } else |
3283 | lpfc_sli_release_iocbq(phba, piocb); | 3290 | lpfc_sli_release_iocbq(phba, piocb); |
3284 | } | 3291 | } |
3285 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) { | 3292 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) |
3286 | phba->els_tmofunc.expires = jiffies + HZ * timeout; | 3293 | mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout); |
3287 | add_timer(&phba->els_tmofunc); | 3294 | |
3288 | } | ||
3289 | spin_unlock_irq(phba->host->host_lock); | 3295 | spin_unlock_irq(phba->host->host_lock); |
3290 | } | 3296 | } |
3291 | 3297 | ||
@@ -3442,6 +3448,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3442 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { | 3448 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { |
3443 | ndlp->nlp_type |= NLP_FABRIC; | 3449 | ndlp->nlp_type |= NLP_FABRIC; |
3444 | } | 3450 | } |
3451 | ndlp->nlp_state = NLP_STE_UNUSED_NODE; | ||
3452 | lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST); | ||
3445 | } | 3453 | } |
3446 | 3454 | ||
3447 | phba->fc_stat.elsRcvFrame++; | 3455 | phba->fc_stat.elsRcvFrame++; |
@@ -3463,13 +3471,14 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3463 | rjt_err = 1; | 3471 | rjt_err = 1; |
3464 | break; | 3472 | break; |
3465 | } | 3473 | } |
3474 | ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp); | ||
3466 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI); | 3475 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI); |
3467 | break; | 3476 | break; |
3468 | case ELS_CMD_FLOGI: | 3477 | case ELS_CMD_FLOGI: |
3469 | phba->fc_stat.elsRcvFLOGI++; | 3478 | phba->fc_stat.elsRcvFLOGI++; |
3470 | lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode); | 3479 | lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode); |
3471 | if (newnode) { | 3480 | if (newnode) { |
3472 | mempool_free( ndlp, phba->nlp_mem_pool); | 3481 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
3473 | } | 3482 | } |
3474 | break; | 3483 | break; |
3475 | case ELS_CMD_LOGO: | 3484 | case ELS_CMD_LOGO: |
@@ -3492,7 +3501,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3492 | phba->fc_stat.elsRcvRSCN++; | 3501 | phba->fc_stat.elsRcvRSCN++; |
3493 | lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode); | 3502 | lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode); |
3494 | if (newnode) { | 3503 | if (newnode) { |
3495 | mempool_free( ndlp, phba->nlp_mem_pool); | 3504 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
3496 | } | 3505 | } |
3497 | break; | 3506 | break; |
3498 | case ELS_CMD_ADISC: | 3507 | case ELS_CMD_ADISC: |
@@ -3535,28 +3544,28 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3535 | phba->fc_stat.elsRcvLIRR++; | 3544 | phba->fc_stat.elsRcvLIRR++; |
3536 | lpfc_els_rcv_lirr(phba, elsiocb, ndlp); | 3545 | lpfc_els_rcv_lirr(phba, elsiocb, ndlp); |
3537 | if (newnode) { | 3546 | if (newnode) { |
3538 | mempool_free( ndlp, phba->nlp_mem_pool); | 3547 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
3539 | } | 3548 | } |
3540 | break; | 3549 | break; |
3541 | case ELS_CMD_RPS: | 3550 | case ELS_CMD_RPS: |
3542 | phba->fc_stat.elsRcvRPS++; | 3551 | phba->fc_stat.elsRcvRPS++; |
3543 | lpfc_els_rcv_rps(phba, elsiocb, ndlp); | 3552 | lpfc_els_rcv_rps(phba, elsiocb, ndlp); |
3544 | if (newnode) { | 3553 | if (newnode) { |
3545 | mempool_free( ndlp, phba->nlp_mem_pool); | 3554 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
3546 | } | 3555 | } |
3547 | break; | 3556 | break; |
3548 | case ELS_CMD_RPL: | 3557 | case ELS_CMD_RPL: |
3549 | phba->fc_stat.elsRcvRPL++; | 3558 | phba->fc_stat.elsRcvRPL++; |
3550 | lpfc_els_rcv_rpl(phba, elsiocb, ndlp); | 3559 | lpfc_els_rcv_rpl(phba, elsiocb, ndlp); |
3551 | if (newnode) { | 3560 | if (newnode) { |
3552 | mempool_free( ndlp, phba->nlp_mem_pool); | 3561 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
3553 | } | 3562 | } |
3554 | break; | 3563 | break; |
3555 | case ELS_CMD_RNID: | 3564 | case ELS_CMD_RNID: |
3556 | phba->fc_stat.elsRcvRNID++; | 3565 | phba->fc_stat.elsRcvRNID++; |
3557 | lpfc_els_rcv_rnid(phba, elsiocb, ndlp); | 3566 | lpfc_els_rcv_rnid(phba, elsiocb, ndlp); |
3558 | if (newnode) { | 3567 | if (newnode) { |
3559 | mempool_free( ndlp, phba->nlp_mem_pool); | 3568 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
3560 | } | 3569 | } |
3561 | break; | 3570 | break; |
3562 | default: | 3571 | default: |
@@ -3568,7 +3577,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3568 | "%d:0115 Unknown ELS command x%x received from " | 3577 | "%d:0115 Unknown ELS command x%x received from " |
3569 | "NPORT x%x\n", phba->brd_no, cmd, did); | 3578 | "NPORT x%x\n", phba->brd_no, cmd, did); |
3570 | if (newnode) { | 3579 | if (newnode) { |
3571 | mempool_free( ndlp, phba->nlp_mem_pool); | 3580 | lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); |
3572 | } | 3581 | } |
3573 | break; | 3582 | break; |
3574 | } | 3583 | } |