diff options
author | James Smart <james.smart@emulex.com> | 2013-04-17 20:14:38 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-02 15:37:45 -0400 |
commit | 16a3a20842f3df93f4ccb82b8f374be16280a337 (patch) | |
tree | 6291b5e85a7cac6b0d888dca3ed2a49ef5984de2 | |
parent | 96b04db9f2c16e77c31ef0e17e143da1e0cbfd78 (diff) |
[SCSI] lpfc 8.3.39: Fixed VPI allocation issues after firmware dump is performed
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 14 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 25 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.h | 1 |
5 files changed, 51 insertions, 3 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 326e05a65a73..2ce2ebcc8f17 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -2796,7 +2796,19 @@ void | |||
2796 | lpfc_issue_init_vpi(struct lpfc_vport *vport) | 2796 | lpfc_issue_init_vpi(struct lpfc_vport *vport) |
2797 | { | 2797 | { |
2798 | LPFC_MBOXQ_t *mboxq; | 2798 | LPFC_MBOXQ_t *mboxq; |
2799 | int rc; | 2799 | int rc, vpi; |
2800 | |||
2801 | if ((vport->port_type != LPFC_PHYSICAL_PORT) && (!vport->vpi)) { | ||
2802 | vpi = lpfc_alloc_vpi(vport->phba); | ||
2803 | if (!vpi) { | ||
2804 | lpfc_printf_vlog(vport, KERN_ERR, | ||
2805 | LOG_MBOX, | ||
2806 | "3303 Failed to obtain vport vpi\n"); | ||
2807 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
2808 | return; | ||
2809 | } | ||
2810 | vport->vpi = vpi; | ||
2811 | } | ||
2800 | 2812 | ||
2801 | mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL); | 2813 | mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL); |
2802 | if (!mboxq) { | 2814 | if (!mboxq) { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 5da297290262..8edef6c4d57a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -2633,6 +2633,7 @@ lpfc_online(struct lpfc_hba *phba) | |||
2633 | struct lpfc_vport *vport; | 2633 | struct lpfc_vport *vport; |
2634 | struct lpfc_vport **vports; | 2634 | struct lpfc_vport **vports; |
2635 | int i; | 2635 | int i; |
2636 | bool vpis_cleared = false; | ||
2636 | 2637 | ||
2637 | if (!phba) | 2638 | if (!phba) |
2638 | return 0; | 2639 | return 0; |
@@ -2656,6 +2657,10 @@ lpfc_online(struct lpfc_hba *phba) | |||
2656 | lpfc_unblock_mgmt_io(phba); | 2657 | lpfc_unblock_mgmt_io(phba); |
2657 | return 1; | 2658 | return 1; |
2658 | } | 2659 | } |
2660 | spin_lock_irq(&phba->hbalock); | ||
2661 | if (!phba->sli4_hba.max_cfg_param.vpi_used) | ||
2662 | vpis_cleared = true; | ||
2663 | spin_unlock_irq(&phba->hbalock); | ||
2659 | } else { | 2664 | } else { |
2660 | if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */ | 2665 | if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */ |
2661 | lpfc_unblock_mgmt_io(phba); | 2666 | lpfc_unblock_mgmt_io(phba); |
@@ -2672,8 +2677,13 @@ lpfc_online(struct lpfc_hba *phba) | |||
2672 | vports[i]->fc_flag &= ~FC_OFFLINE_MODE; | 2677 | vports[i]->fc_flag &= ~FC_OFFLINE_MODE; |
2673 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) | 2678 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) |
2674 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 2679 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
2675 | if (phba->sli_rev == LPFC_SLI_REV4) | 2680 | if (phba->sli_rev == LPFC_SLI_REV4) { |
2676 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | 2681 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; |
2682 | if ((vpis_cleared) && | ||
2683 | (vports[i]->port_type != | ||
2684 | LPFC_PHYSICAL_PORT)) | ||
2685 | vports[i]->vpi = 0; | ||
2686 | } | ||
2677 | spin_unlock_irq(shost->host_lock); | 2687 | spin_unlock_irq(shost->host_lock); |
2678 | } | 2688 | } |
2679 | lpfc_destroy_vport_work_array(phba, vports); | 2689 | lpfc_destroy_vport_work_array(phba, vports); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 35dd17eb0f27..96fe1ef24689 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -5511,6 +5511,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) | |||
5511 | list_del_init(&rsrc_blk->list); | 5511 | list_del_init(&rsrc_blk->list); |
5512 | kfree(rsrc_blk); | 5512 | kfree(rsrc_blk); |
5513 | } | 5513 | } |
5514 | phba->sli4_hba.max_cfg_param.vpi_used = 0; | ||
5514 | break; | 5515 | break; |
5515 | case LPFC_RSC_TYPE_FCOE_XRI: | 5516 | case LPFC_RSC_TYPE_FCOE_XRI: |
5516 | kfree(phba->sli4_hba.xri_bmask); | 5517 | kfree(phba->sli4_hba.xri_bmask); |
@@ -5811,6 +5812,7 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) | |||
5811 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); | 5812 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); |
5812 | } else { | 5813 | } else { |
5813 | kfree(phba->vpi_bmask); | 5814 | kfree(phba->vpi_bmask); |
5815 | phba->sli4_hba.max_cfg_param.vpi_used = 0; | ||
5814 | kfree(phba->vpi_ids); | 5816 | kfree(phba->vpi_ids); |
5815 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | 5817 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); |
5816 | kfree(phba->sli4_hba.xri_bmask); | 5818 | kfree(phba->sli4_hba.xri_bmask); |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 0fe188e66000..e28e431564b0 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -80,7 +80,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport, | |||
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | static int | 83 | int |
84 | lpfc_alloc_vpi(struct lpfc_hba *phba) | 84 | lpfc_alloc_vpi(struct lpfc_hba *phba) |
85 | { | 85 | { |
86 | unsigned long vpi; | 86 | unsigned long vpi; |
@@ -568,6 +568,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
568 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; | 568 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; |
569 | struct lpfc_hba *phba = vport->phba; | 569 | struct lpfc_hba *phba = vport->phba; |
570 | long timeout; | 570 | long timeout; |
571 | bool ns_ndlp_referenced = false; | ||
571 | 572 | ||
572 | if (vport->port_type == LPFC_PHYSICAL_PORT) { | 573 | if (vport->port_type == LPFC_PHYSICAL_PORT) { |
573 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | 574 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, |
@@ -628,6 +629,18 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
628 | 629 | ||
629 | lpfc_debugfs_terminate(vport); | 630 | lpfc_debugfs_terminate(vport); |
630 | 631 | ||
632 | /* | ||
633 | * The call to fc_remove_host might release the NameServer ndlp. Since | ||
634 | * we might need to use the ndlp to send the DA_ID CT command, | ||
635 | * increment the reference for the NameServer ndlp to prevent it from | ||
636 | * being released. | ||
637 | */ | ||
638 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | ||
639 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { | ||
640 | lpfc_nlp_get(ndlp); | ||
641 | ns_ndlp_referenced = true; | ||
642 | } | ||
643 | |||
631 | /* Remove FC host and then SCSI host with the vport */ | 644 | /* Remove FC host and then SCSI host with the vport */ |
632 | fc_remove_host(lpfc_shost_from_vport(vport)); | 645 | fc_remove_host(lpfc_shost_from_vport(vport)); |
633 | scsi_remove_host(lpfc_shost_from_vport(vport)); | 646 | scsi_remove_host(lpfc_shost_from_vport(vport)); |
@@ -734,6 +747,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
734 | lpfc_discovery_wait(vport); | 747 | lpfc_discovery_wait(vport); |
735 | 748 | ||
736 | skip_logo: | 749 | skip_logo: |
750 | |||
751 | /* | ||
752 | * If the NameServer ndlp has been incremented to allow the DA_ID CT | ||
753 | * command to be sent, decrement the ndlp now. | ||
754 | */ | ||
755 | if (ns_ndlp_referenced) { | ||
756 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | ||
757 | lpfc_nlp_put(ndlp); | ||
758 | } | ||
759 | |||
737 | lpfc_cleanup(vport); | 760 | lpfc_cleanup(vport); |
738 | lpfc_sli_host_down(vport); | 761 | lpfc_sli_host_down(vport); |
739 | 762 | ||
diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h index 90828340acea..6b2c94eb8134 100644 --- a/drivers/scsi/lpfc/lpfc_vport.h +++ b/drivers/scsi/lpfc/lpfc_vport.h | |||
@@ -90,6 +90,7 @@ int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *); | |||
90 | int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint); | 90 | int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint); |
91 | struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *); | 91 | struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *); |
92 | void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **); | 92 | void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **); |
93 | int lpfc_alloc_vpi(struct lpfc_hba *phba); | ||
93 | 94 | ||
94 | /* | 95 | /* |
95 | * queuecommand VPORT-specific return codes. Specified in the host byte code. | 96 | * queuecommand VPORT-specific return codes. Specified in the host byte code. |