Commit 16a3a208 authored by James Smart's avatar James Smart Committed by James Bottomley

[SCSI] lpfc 8.3.39: Fixed VPI allocation issues after firmware dump is performed

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 96b04db9
...@@ -2796,7 +2796,19 @@ void ...@@ -2796,7 +2796,19 @@ void
lpfc_issue_init_vpi(struct lpfc_vport *vport) lpfc_issue_init_vpi(struct lpfc_vport *vport)
{ {
LPFC_MBOXQ_t *mboxq; LPFC_MBOXQ_t *mboxq;
int rc; int rc, vpi;
if ((vport->port_type != LPFC_PHYSICAL_PORT) && (!vport->vpi)) {
vpi = lpfc_alloc_vpi(vport->phba);
if (!vpi) {
lpfc_printf_vlog(vport, KERN_ERR,
LOG_MBOX,
"3303 Failed to obtain vport vpi\n");
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
return;
}
vport->vpi = vpi;
}
mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL); mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) { if (!mboxq) {
......
...@@ -2633,6 +2633,7 @@ lpfc_online(struct lpfc_hba *phba) ...@@ -2633,6 +2633,7 @@ lpfc_online(struct lpfc_hba *phba)
struct lpfc_vport *vport; struct lpfc_vport *vport;
struct lpfc_vport **vports; struct lpfc_vport **vports;
int i; int i;
bool vpis_cleared = false;
if (!phba) if (!phba)
return 0; return 0;
...@@ -2656,6 +2657,10 @@ lpfc_online(struct lpfc_hba *phba) ...@@ -2656,6 +2657,10 @@ lpfc_online(struct lpfc_hba *phba)
lpfc_unblock_mgmt_io(phba); lpfc_unblock_mgmt_io(phba);
return 1; return 1;
} }
spin_lock_irq(&phba->hbalock);
if (!phba->sli4_hba.max_cfg_param.vpi_used)
vpis_cleared = true;
spin_unlock_irq(&phba->hbalock);
} else { } else {
if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */ if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */
lpfc_unblock_mgmt_io(phba); lpfc_unblock_mgmt_io(phba);
...@@ -2672,8 +2677,13 @@ lpfc_online(struct lpfc_hba *phba) ...@@ -2672,8 +2677,13 @@ lpfc_online(struct lpfc_hba *phba)
vports[i]->fc_flag &= ~FC_OFFLINE_MODE; vports[i]->fc_flag &= ~FC_OFFLINE_MODE;
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
if (phba->sli_rev == LPFC_SLI_REV4) if (phba->sli_rev == LPFC_SLI_REV4) {
vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
if ((vpis_cleared) &&
(vports[i]->port_type !=
LPFC_PHYSICAL_PORT))
vports[i]->vpi = 0;
}
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
} }
lpfc_destroy_vport_work_array(phba, vports); lpfc_destroy_vport_work_array(phba, vports);
......
...@@ -5511,6 +5511,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) ...@@ -5511,6 +5511,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
list_del_init(&rsrc_blk->list); list_del_init(&rsrc_blk->list);
kfree(rsrc_blk); kfree(rsrc_blk);
} }
phba->sli4_hba.max_cfg_param.vpi_used = 0;
break; break;
case LPFC_RSC_TYPE_FCOE_XRI: case LPFC_RSC_TYPE_FCOE_XRI:
kfree(phba->sli4_hba.xri_bmask); kfree(phba->sli4_hba.xri_bmask);
...@@ -5811,6 +5812,7 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) ...@@ -5811,6 +5812,7 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI);
} else { } else {
kfree(phba->vpi_bmask); kfree(phba->vpi_bmask);
phba->sli4_hba.max_cfg_param.vpi_used = 0;
kfree(phba->vpi_ids); kfree(phba->vpi_ids);
bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
kfree(phba->sli4_hba.xri_bmask); kfree(phba->sli4_hba.xri_bmask);
......
...@@ -80,7 +80,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport, ...@@ -80,7 +80,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport,
} }
} }
static int int
lpfc_alloc_vpi(struct lpfc_hba *phba) lpfc_alloc_vpi(struct lpfc_hba *phba)
{ {
unsigned long vpi; unsigned long vpi;
...@@ -568,6 +568,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -568,6 +568,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
struct lpfc_hba *phba = vport->phba; struct lpfc_hba *phba = vport->phba;
long timeout; long timeout;
bool ns_ndlp_referenced = false;
if (vport->port_type == LPFC_PHYSICAL_PORT) { if (vport->port_type == LPFC_PHYSICAL_PORT) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
...@@ -628,6 +629,18 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -628,6 +629,18 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
lpfc_debugfs_terminate(vport); lpfc_debugfs_terminate(vport);
/*
* The call to fc_remove_host might release the NameServer ndlp. Since
* we might need to use the ndlp to send the DA_ID CT command,
* increment the reference for the NameServer ndlp to prevent it from
* being released.
*/
ndlp = lpfc_findnode_did(vport, NameServer_DID);
if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
lpfc_nlp_get(ndlp);
ns_ndlp_referenced = true;
}
/* Remove FC host and then SCSI host with the vport */ /* Remove FC host and then SCSI host with the vport */
fc_remove_host(lpfc_shost_from_vport(vport)); fc_remove_host(lpfc_shost_from_vport(vport));
scsi_remove_host(lpfc_shost_from_vport(vport)); scsi_remove_host(lpfc_shost_from_vport(vport));
...@@ -734,6 +747,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ...@@ -734,6 +747,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
lpfc_discovery_wait(vport); lpfc_discovery_wait(vport);
skip_logo: skip_logo:
/*
* If the NameServer ndlp has been incremented to allow the DA_ID CT
* command to be sent, decrement the ndlp now.
*/
if (ns_ndlp_referenced) {
ndlp = lpfc_findnode_did(vport, NameServer_DID);
lpfc_nlp_put(ndlp);
}
lpfc_cleanup(vport); lpfc_cleanup(vport);
lpfc_sli_host_down(vport); lpfc_sli_host_down(vport);
......
...@@ -90,6 +90,7 @@ int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *); ...@@ -90,6 +90,7 @@ int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint); int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *); struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *);
void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **); void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **);
int lpfc_alloc_vpi(struct lpfc_hba *phba);
/* /*
* queuecommand VPORT-specific return codes. Specified in the host byte code. * queuecommand VPORT-specific return codes. Specified in the host byte code.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment