diff options
author | James Smart <james.smart@emulex.com> | 2010-04-06 15:06:30 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-04-11 14:45:53 -0400 |
commit | 78730cfe0649bce86e64eafda9bdffa38f05d396 (patch) | |
tree | 7a0cbdf556602349b81db5962b5aec87bff68d8a /drivers/scsi/lpfc | |
parent | c74959370369cd870560777b7db7ec940565bb85 (diff) |
[SCSI] lpfc 8.3.12: Fix discovery issues
- Add code to prevent unreg_vpi mailbox command from failing.
- Add code to reset the HBA if unreg_vpi mailbox fails with busy status.
- Remove code that was clearing the nlp_type stored during rport discovery.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 15 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 20 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 56 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 15 |
7 files changed, 105 insertions, 5 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 5087c4211b4..fbc9baeb604 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -65,6 +65,7 @@ void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); | |||
65 | void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); | 65 | void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); |
66 | void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *); | 66 | void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *); |
67 | void lpfc_retry_pport_discovery(struct lpfc_hba *); | 67 | void lpfc_retry_pport_discovery(struct lpfc_hba *); |
68 | void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t); | ||
68 | 69 | ||
69 | void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); | 70 | void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *); |
70 | void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); | 71 | void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *); |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 2851d75ffc6..36257a68550 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -38,6 +38,7 @@ enum lpfc_work_type { | |||
38 | LPFC_EVT_ELS_RETRY, | 38 | LPFC_EVT_ELS_RETRY, |
39 | LPFC_EVT_DEV_LOSS, | 39 | LPFC_EVT_DEV_LOSS, |
40 | LPFC_EVT_FASTPATH_MGMT_EVT, | 40 | LPFC_EVT_FASTPATH_MGMT_EVT, |
41 | LPFC_EVT_RESET_HBA, | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | /* structure used to queue event to the discovery tasklet */ | 44 | /* structure used to queue event to the discovery tasklet */ |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 1de60ce6f29..c4c7f0ad746 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -584,6 +584,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
584 | spin_unlock_irq(shost->host_lock); | 584 | spin_unlock_irq(shost->host_lock); |
585 | lpfc_unreg_rpi(vport, np); | 585 | lpfc_unreg_rpi(vport, np); |
586 | } | 586 | } |
587 | lpfc_cleanup_pending_mbox(vport); | ||
587 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | 588 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { |
588 | lpfc_mbx_unreg_vpi(vport); | 589 | lpfc_mbx_unreg_vpi(vport); |
589 | spin_lock_irq(shost->host_lock); | 590 | spin_lock_irq(shost->host_lock); |
@@ -6316,6 +6317,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
6316 | spin_unlock_irq(shost->host_lock); | 6317 | spin_unlock_irq(shost->host_lock); |
6317 | lpfc_unreg_rpi(vport, np); | 6318 | lpfc_unreg_rpi(vport, np); |
6318 | } | 6319 | } |
6320 | lpfc_cleanup_pending_mbox(vport); | ||
6319 | lpfc_mbx_unreg_vpi(vport); | 6321 | lpfc_mbx_unreg_vpi(vport); |
6320 | spin_lock_irq(shost->host_lock); | 6322 | spin_lock_irq(shost->host_lock); |
6321 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 6323 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d2b55f05aa0..1f87b4fb8b5 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -475,6 +475,10 @@ lpfc_work_list_done(struct lpfc_hba *phba) | |||
475 | lpfc_send_fastpath_evt(phba, evtp); | 475 | lpfc_send_fastpath_evt(phba, evtp); |
476 | free_evt = 0; | 476 | free_evt = 0; |
477 | break; | 477 | break; |
478 | case LPFC_EVT_RESET_HBA: | ||
479 | if (!(phba->pport->load_flag & FC_UNLOADING)) | ||
480 | lpfc_reset_hba(phba); | ||
481 | break; | ||
478 | } | 482 | } |
479 | if (free_evt) | 483 | if (free_evt) |
480 | kfree(evtp); | 484 | kfree(evtp); |
@@ -2737,11 +2741,18 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2737 | switch (mb->mbxStatus) { | 2741 | switch (mb->mbxStatus) { |
2738 | case 0x0011: | 2742 | case 0x0011: |
2739 | case 0x0020: | 2743 | case 0x0020: |
2740 | case 0x9700: | ||
2741 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, | 2744 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, |
2742 | "0911 cmpl_unreg_vpi, mb status = 0x%x\n", | 2745 | "0911 cmpl_unreg_vpi, mb status = 0x%x\n", |
2743 | mb->mbxStatus); | 2746 | mb->mbxStatus); |
2744 | break; | 2747 | break; |
2748 | /* If VPI is busy, reset the HBA */ | ||
2749 | case 0x9700: | ||
2750 | lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, | ||
2751 | "2798 Unreg_vpi failed vpi 0x%x, mb status = 0x%x\n", | ||
2752 | vport->vpi, mb->mbxStatus); | ||
2753 | if (!(phba->pport->load_flag & FC_UNLOADING)) | ||
2754 | lpfc_workq_post_event(phba, NULL, NULL, | ||
2755 | LPFC_EVT_RESET_HBA); | ||
2745 | } | 2756 | } |
2746 | spin_lock_irq(shost->host_lock); | 2757 | spin_lock_irq(shost->host_lock); |
2747 | vport->vpi_state &= ~LPFC_VPI_REGISTERED; | 2758 | vport->vpi_state &= ~LPFC_VPI_REGISTERED; |
@@ -3233,7 +3244,6 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
3233 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 3244 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
3234 | 3245 | ||
3235 | if (new_state == NLP_STE_UNMAPPED_NODE) { | 3246 | if (new_state == NLP_STE_UNMAPPED_NODE) { |
3236 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); | ||
3237 | ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; | 3247 | ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; |
3238 | ndlp->nlp_type |= NLP_FC_NODE; | 3248 | ndlp->nlp_type |= NLP_FC_NODE; |
3239 | } | 3249 | } |
@@ -4991,6 +5001,7 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) | |||
4991 | ndlp = lpfc_findnode_did(vports[i], Fabric_DID); | 5001 | ndlp = lpfc_findnode_did(vports[i], Fabric_DID); |
4992 | if (ndlp) | 5002 | if (ndlp) |
4993 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); | 5003 | lpfc_cancel_retry_delay_tmo(vports[i], ndlp); |
5004 | lpfc_cleanup_pending_mbox(vports[i]); | ||
4994 | lpfc_mbx_unreg_vpi(vports[i]); | 5005 | lpfc_mbx_unreg_vpi(vports[i]); |
4995 | shost = lpfc_shost_from_vport(vports[i]); | 5006 | shost = lpfc_shost_from_vport(vports[i]); |
4996 | spin_lock_irq(shost->host_lock); | 5007 | spin_lock_irq(shost->host_lock); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 03681013d80..cd9697edf86 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -3227,12 +3227,26 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) | |||
3227 | 3227 | ||
3228 | if (!vport) | 3228 | if (!vport) |
3229 | return NULL; | 3229 | return NULL; |
3230 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | ||
3231 | if (!ndlp) | ||
3232 | return NULL; | ||
3233 | phba = vport->phba; | 3230 | phba = vport->phba; |
3234 | if (!phba) | 3231 | if (!phba) |
3235 | return NULL; | 3232 | return NULL; |
3233 | ndlp = lpfc_findnode_did(vport, Fabric_DID); | ||
3234 | if (!ndlp) { | ||
3235 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | ||
3236 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | ||
3237 | if (!ndlp) | ||
3238 | return 0; | ||
3239 | lpfc_nlp_init(vport, ndlp, Fabric_DID); | ||
3240 | /* Set the node type */ | ||
3241 | ndlp->nlp_type |= NLP_FABRIC; | ||
3242 | /* Put ndlp onto node list */ | ||
3243 | lpfc_enqueue_node(vport, ndlp); | ||
3244 | } else if (!NLP_CHK_NODE_ACT(ndlp)) { | ||
3245 | /* re-setup ndlp without removing from node list */ | ||
3246 | ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
3247 | if (!ndlp) | ||
3248 | return 0; | ||
3249 | } | ||
3236 | if (phba->pport->port_state <= LPFC_FLOGI) | 3250 | if (phba->pport->port_state <= LPFC_FLOGI) |
3237 | return NULL; | 3251 | return NULL; |
3238 | /* If virtual link is not yet instantiated ignore CVL */ | 3252 | /* If virtual link is not yet instantiated ignore CVL */ |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index e1086da6906..b90820a699f 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -637,11 +637,55 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
637 | lpfc_unreg_rpi(vport, ndlp); | 637 | lpfc_unreg_rpi(vport, ndlp); |
638 | return 0; | 638 | return 0; |
639 | } | 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 | **/ | ||
649 | void | ||
650 | lpfc_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 | } | ||
640 | 670 | ||
641 | static uint32_t | 671 | static uint32_t |
642 | lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 672 | lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
643 | void *arg, uint32_t evt) | 673 | void *arg, uint32_t evt) |
644 | { | 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 | } | ||
645 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, | 689 | lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, |
646 | "0271 Illegal State Transition: node x%x " | 690 | "0271 Illegal State Transition: node x%x " |
647 | "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", |
@@ -977,6 +1021,18 @@ static uint32_t | |||
977 | lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport, | 1021 | lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport, |
978 | struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) | 1022 | struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) |
979 | { | 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 | } | ||
980 | return ndlp->nlp_state; | 1036 | return ndlp->nlp_state; |
981 | } | 1037 | } |
982 | 1038 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1ab7937097a..7a61455140b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -12661,6 +12661,7 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) | |||
12661 | struct lpfc_hba *phba = vport->phba; | 12661 | struct lpfc_hba *phba = vport->phba; |
12662 | LPFC_MBOXQ_t *mb, *nextmb; | 12662 | LPFC_MBOXQ_t *mb, *nextmb; |
12663 | struct lpfc_dmabuf *mp; | 12663 | struct lpfc_dmabuf *mp; |
12664 | struct lpfc_nodelist *ndlp; | ||
12664 | 12665 | ||
12665 | spin_lock_irq(&phba->hbalock); | 12666 | spin_lock_irq(&phba->hbalock); |
12666 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { | 12667 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { |
@@ -12677,6 +12678,11 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) | |||
12677 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); | 12678 | __lpfc_mbuf_free(phba, mp->virt, mp->phys); |
12678 | kfree(mp); | 12679 | kfree(mp); |
12679 | } | 12680 | } |
12681 | ndlp = (struct lpfc_nodelist *) mb->context2; | ||
12682 | if (ndlp) { | ||
12683 | lpfc_nlp_put(ndlp); | ||
12684 | mb->context2 = NULL; | ||
12685 | } | ||
12680 | } | 12686 | } |
12681 | list_del(&mb->list); | 12687 | list_del(&mb->list); |
12682 | mempool_free(mb, phba->mbox_mem_pool); | 12688 | mempool_free(mb, phba->mbox_mem_pool); |
@@ -12686,6 +12692,15 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) | |||
12686 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) || | 12692 | if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) || |
12687 | (mb->u.mb.mbxCommand == MBX_REG_VPI)) | 12693 | (mb->u.mb.mbxCommand == MBX_REG_VPI)) |
12688 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 12694 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
12695 | if (mb->u.mb.mbxCommand == MBX_REG_LOGIN64) { | ||
12696 | ndlp = (struct lpfc_nodelist *) mb->context2; | ||
12697 | if (ndlp) { | ||
12698 | lpfc_nlp_put(ndlp); | ||
12699 | mb->context2 = NULL; | ||
12700 | } | ||
12701 | /* Unregister the RPI when mailbox complete */ | ||
12702 | mb->mbox_flag |= LPFC_MBX_IMED_UNREG; | ||
12703 | } | ||
12689 | } | 12704 | } |
12690 | spin_unlock_irq(&phba->hbalock); | 12705 | spin_unlock_irq(&phba->hbalock); |
12691 | } | 12706 | } |