[SCSI] lpfc 8.3.4: NPIV vport fixes

NPIV vport fixes

- Fixed static vport creation on SLI4 HBAs
- Fixed vport create sending init_vpi before REG_VFI
- Fix unable to create vports on SLI4 HBA's Port2

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
James Smart 2009-07-19 10:01:26 -04:00 committed by James Bottomley
parent 32b9793fe6
commit 1c6834a7e8
7 changed files with 167 additions and 55 deletions

View File

@ -312,6 +312,7 @@ struct lpfc_vport {
#define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */ #define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */
#define FC_VPORT_NEEDS_REG_VPI 0x80000 /* Needs to have its vpi registered */ #define FC_VPORT_NEEDS_REG_VPI 0x80000 /* Needs to have its vpi registered */
#define FC_RSCN_DEFERRED 0x100000 /* A deferred RSCN being processed */ #define FC_RSCN_DEFERRED 0x100000 /* A deferred RSCN being processed */
#define FC_VPORT_NEEDS_INIT_VPI 0x200000 /* Need to INIT_VPI before FDISC */
uint32_t ct_flags; uint32_t ct_flags;
#define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ #define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */

View File

@ -25,7 +25,7 @@ void lpfc_down_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_sli_read_link_ste(struct lpfc_hba *); void lpfc_sli_read_link_ste(struct lpfc_hba *);
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t); void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t);
void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); int lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
int lpfc_dump_fcoe_param(struct lpfc_hba *, struct lpfcMboxq *); int lpfc_dump_fcoe_param(struct lpfc_hba *, struct lpfcMboxq *);
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
@ -184,7 +184,7 @@ int lpfc_mbox_dev_check(struct lpfc_hba *);
int lpfc_mbox_tmo_val(struct lpfc_hba *, int); int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *); void lpfc_init_vfi(struct lpfcMboxq *, struct lpfc_vport *);
void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t); void lpfc_reg_vfi(struct lpfcMboxq *, struct lpfc_vport *, dma_addr_t);
void lpfc_init_vpi(struct lpfcMboxq *, uint16_t); void lpfc_init_vpi(struct lpfc_hba *, struct lpfcMboxq *, uint16_t);
void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t); void lpfc_unreg_vfi(struct lpfcMboxq *, uint16_t);
void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *); void lpfc_reg_fcfi(struct lpfc_hba *, struct lpfcMboxq *);
void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t); void lpfc_unreg_fcfi(struct lpfcMboxq *, uint16_t);

View File

@ -1633,6 +1633,39 @@ out:
return; return;
} }
/**
* lpfc_init_vpi_cmpl - Completion handler for init_vpi mbox command.
* @phba: pointer to lpfc hba data structure.
* @mboxq: pointer to mailbox data structure.
*
* This function handles completion of init vpi mailbox command.
*/
static void
lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
{
struct lpfc_vport *vport = mboxq->vport;
if (mboxq->u.mb.mbxStatus) {
lpfc_printf_vlog(vport, KERN_ERR,
LOG_MBOX,
"2609 Init VPI mailbox failed 0x%x\n",
mboxq->u.mb.mbxStatus);
mempool_free(mboxq, phba->mbox_mem_pool);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
return;
}
vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI;
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
lpfc_initial_fdisc(vport);
else {
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
lpfc_printf_vlog(vport, KERN_ERR,
LOG_ELS,
"2606 No NPIV Fabric support\n");
}
return;
}
/** /**
* lpfc_start_fdiscs - send fdiscs for each vports on this port. * lpfc_start_fdiscs - send fdiscs for each vports on this port.
* @phba: pointer to lpfc hba data structure. * @phba: pointer to lpfc hba data structure.
@ -1645,6 +1678,8 @@ lpfc_start_fdiscs(struct lpfc_hba *phba)
{ {
struct lpfc_vport **vports; struct lpfc_vport **vports;
int i; int i;
LPFC_MBOXQ_t *mboxq;
int rc;
vports = lpfc_create_vport_work_array(phba); vports = lpfc_create_vport_work_array(phba);
if (vports != NULL) { if (vports != NULL) {
@ -1662,6 +1697,29 @@ lpfc_start_fdiscs(struct lpfc_hba *phba)
FC_VPORT_LINKDOWN); FC_VPORT_LINKDOWN);
continue; continue;
} }
if (vports[i]->fc_flag & FC_VPORT_NEEDS_INIT_VPI) {
mboxq = mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!mboxq) {
lpfc_printf_vlog(vports[i], KERN_ERR,
LOG_MBOX, "2607 Failed to allocate "
"init_vpi mailbox\n");
continue;
}
lpfc_init_vpi(phba, mboxq, vports[i]->vpi);
mboxq->vport = vports[i];
mboxq->mbox_cmpl = lpfc_init_vpi_cmpl;
rc = lpfc_sli_issue_mbox(phba, mboxq,
MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
lpfc_printf_vlog(vports[i], KERN_ERR,
LOG_MBOX, "2608 Failed to issue "
"init_vpi mailbox\n");
mempool_free(mboxq,
phba->mbox_mem_pool);
}
continue;
}
if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
lpfc_initial_fdisc(vports[i]); lpfc_initial_fdisc(vports[i]);
else { else {
@ -2242,13 +2300,15 @@ lpfc_create_static_vport(struct lpfc_hba *phba)
LPFC_MBOXQ_t *pmb = NULL; LPFC_MBOXQ_t *pmb = NULL;
MAILBOX_t *mb; MAILBOX_t *mb;
struct static_vport_info *vport_info; struct static_vport_info *vport_info;
int rc, i; int rc = 0, i;
struct fc_vport_identifiers vport_id; struct fc_vport_identifiers vport_id;
struct fc_vport *new_fc_vport; struct fc_vport *new_fc_vport;
struct Scsi_Host *shost; struct Scsi_Host *shost;
struct lpfc_vport *vport; struct lpfc_vport *vport;
uint16_t offset = 0; uint16_t offset = 0;
uint8_t *vport_buff; uint8_t *vport_buff;
struct lpfc_dmabuf *mp;
uint32_t byte_count = 0;
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) { if (!pmb) {
@ -2271,7 +2331,9 @@ lpfc_create_static_vport(struct lpfc_hba *phba)
vport_buff = (uint8_t *) vport_info; vport_buff = (uint8_t *) vport_info;
do { do {
lpfc_dump_static_vport(phba, pmb, offset); if (lpfc_dump_static_vport(phba, pmb, offset))
goto out;
pmb->vport = phba->pport; pmb->vport = phba->pport;
rc = lpfc_sli_issue_mbox_wait(phba, pmb, LPFC_MBOX_TMO); rc = lpfc_sli_issue_mbox_wait(phba, pmb, LPFC_MBOX_TMO);
@ -2284,17 +2346,30 @@ lpfc_create_static_vport(struct lpfc_hba *phba)
goto out; goto out;
} }
if (mb->un.varDmp.word_cnt > if (phba->sli_rev == LPFC_SLI_REV4) {
sizeof(struct static_vport_info) - offset) byte_count = pmb->u.mqe.un.mb_words[5];
mb->un.varDmp.word_cnt = mp = (struct lpfc_dmabuf *) pmb->context2;
sizeof(struct static_vport_info) - offset; if (byte_count > sizeof(struct static_vport_info) -
offset)
byte_count = sizeof(struct static_vport_info)
- offset;
memcpy(vport_buff + offset, mp->virt, byte_count);
offset += byte_count;
} else {
if (mb->un.varDmp.word_cnt >
sizeof(struct static_vport_info) - offset)
mb->un.varDmp.word_cnt =
sizeof(struct static_vport_info)
- offset;
byte_count = mb->un.varDmp.word_cnt;
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
vport_buff + offset,
byte_count);
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, offset += byte_count;
vport_buff + offset, }
mb->un.varDmp.word_cnt);
offset += mb->un.varDmp.word_cnt;
} while (mb->un.varDmp.word_cnt && } while (byte_count &&
offset < sizeof(struct static_vport_info)); offset < sizeof(struct static_vport_info));
@ -2336,16 +2411,15 @@ lpfc_create_static_vport(struct lpfc_hba *phba)
} }
out: out:
/*
* If this is timed out command, setting NULL to context2 tell SLI
* layer not to use this buffer.
*/
spin_lock_irq(&phba->hbalock);
pmb->context2 = NULL;
spin_unlock_irq(&phba->hbalock);
kfree(vport_info); kfree(vport_info);
if (rc != MBX_TIMEOUT) if (rc != MBX_TIMEOUT) {
if (pmb->context2) {
mp = (struct lpfc_dmabuf *) pmb->context2;
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
}
mempool_free(pmb, phba->mbox_mem_pool); mempool_free(pmb, phba->mbox_mem_pool);
}
return; return;
} }

View File

@ -2155,6 +2155,8 @@ 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)
vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
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);
@ -7371,6 +7373,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
/* Perform post initialization setup */ /* Perform post initialization setup */
lpfc_post_init_setup(phba); lpfc_post_init_setup(phba);
/* Check if there are static vports to be created. */
lpfc_create_static_vport(phba);
return 0; return 0;
out_disable_intr: out_disable_intr:

View File

@ -52,30 +52,51 @@
* This routine prepares the mailbox command for dumping list of static * This routine prepares the mailbox command for dumping list of static
* vports to be created. * vports to be created.
**/ **/
void int
lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb,
uint16_t offset) uint16_t offset)
{ {
MAILBOX_t *mb; MAILBOX_t *mb;
void *ctx; struct lpfc_dmabuf *mp;
mb = &pmb->u.mb; mb = &pmb->u.mb;
ctx = pmb->context2;
/* Setup to dump vport info region */ /* Setup to dump vport info region */
memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
mb->mbxCommand = MBX_DUMP_MEMORY; mb->mbxCommand = MBX_DUMP_MEMORY;
mb->un.varDmp.cv = 1;
mb->un.varDmp.type = DMP_NV_PARAMS; mb->un.varDmp.type = DMP_NV_PARAMS;
mb->un.varDmp.entry_index = offset; mb->un.varDmp.entry_index = offset;
mb->un.varDmp.region_id = DMP_REGION_VPORT; mb->un.varDmp.region_id = DMP_REGION_VPORT;
mb->un.varDmp.word_cnt = DMP_RSP_SIZE/sizeof(uint32_t);
mb->un.varDmp.co = 0;
mb->un.varDmp.resp_offset = 0;
pmb->context2 = ctx;
mb->mbxOwner = OWN_HOST; mb->mbxOwner = OWN_HOST;
return; /* For SLI3 HBAs data is embedded in mailbox */
if (phba->sli_rev != LPFC_SLI_REV4) {
mb->un.varDmp.cv = 1;
mb->un.varDmp.word_cnt = DMP_RSP_SIZE/sizeof(uint32_t);
return 0;
}
/* For SLI4 HBAs driver need to allocate memory */
mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
if (mp)
mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
if (!mp || !mp->virt) {
kfree(mp);
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
"2605 lpfc_dump_static_vport: memory"
" allocation failed\n");
return 1;
}
memset(mp->virt, 0, LPFC_BPL_SIZE);
INIT_LIST_HEAD(&mp->list);
/* save address for completion */
pmb->context2 = (uint8_t *) mp;
mb->un.varWords[3] = putPaddrLow(mp->phys);
mb->un.varWords[4] = putPaddrHigh(mp->phys);
mb->un.varDmp.sli4_length = sizeof(struct static_vport_info);
return 0;
} }
/** /**
@ -1805,6 +1826,7 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
/** /**
* lpfc_init_vpi - Initialize the INIT_VPI mailbox command * lpfc_init_vpi - Initialize the INIT_VPI mailbox command
* @phba: pointer to the hba structure to init the VPI for.
* @mbox: pointer to lpfc mbox command to initialize. * @mbox: pointer to lpfc mbox command to initialize.
* @vpi: VPI to be initialized. * @vpi: VPI to be initialized.
* *
@ -1815,11 +1837,14 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
* successful virtual NPort login. * successful virtual NPort login.
**/ **/
void void
lpfc_init_vpi(struct lpfcMboxq *mbox, uint16_t vpi) lpfc_init_vpi(struct lpfc_hba *phba, struct lpfcMboxq *mbox, uint16_t vpi)
{ {
memset(mbox, 0, sizeof(*mbox)); memset(mbox, 0, sizeof(*mbox));
bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI); bf_set(lpfc_mqe_command, &mbox->u.mqe, MBX_INIT_VPI);
bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi, vpi); bf_set(lpfc_init_vpi_vpi, &mbox->u.mqe.un.init_vpi,
vpi + phba->vpi_base);
bf_set(lpfc_init_vpi_vfi, &mbox->u.mqe.un.init_vpi,
phba->pport->vfi + phba->vfi_base);
} }
/** /**

View File

@ -11341,7 +11341,7 @@ lpfc_sli4_init_vpi(struct lpfc_hba *phba, uint16_t vpi)
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) if (!mboxq)
return -ENOMEM; return -ENOMEM;
lpfc_init_vpi(mboxq, vpi); lpfc_init_vpi(phba, mboxq, vpi);
mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI); mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
if (rc != MBX_TIMEOUT) if (rc != MBX_TIMEOUT)

View File

@ -313,22 +313,6 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
goto error_out; goto error_out;
} }
/*
* In SLI4, the vpi must be activated before it can be used
* by the port.
*/
if (phba->sli_rev == LPFC_SLI_REV4) {
rc = lpfc_sli4_init_vpi(phba, vpi);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
"1838 Failed to INIT_VPI on vpi %d "
"status %d\n", vpi, rc);
rc = VPORT_NORESOURCES;
lpfc_free_vpi(phba, vpi);
goto error_out;
}
}
/* Assign an unused board number */ /* Assign an unused board number */
if ((instance = lpfc_get_instance()) < 0) { if ((instance = lpfc_get_instance()) < 0) {
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
@ -367,12 +351,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
goto error_out; goto error_out;
} }
memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8); u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8); u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
if (fc_vport->node_name != 0)
u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
if (fc_vport->port_name != 0)
u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8); memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8);
memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8); memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8);
@ -404,7 +384,34 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
*(struct lpfc_vport **)fc_vport->dd_data = vport; *(struct lpfc_vport **)fc_vport->dd_data = vport;
vport->fc_vport = fc_vport; vport->fc_vport = fc_vport;
/*
* In SLI4, the vpi must be activated before it can be used
* by the port.
*/
if ((phba->sli_rev == LPFC_SLI_REV4) &&
(pport->vfi_state & LPFC_VFI_REGISTERED)) {
rc = lpfc_sli4_init_vpi(phba, vpi);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
"1838 Failed to INIT_VPI on vpi %d "
"status %d\n", vpi, rc);
rc = VPORT_NORESOURCES;
lpfc_free_vpi(phba, vpi);
goto error_out;
}
} else if (phba->sli_rev == LPFC_SLI_REV4) {
/*
* Driver cannot INIT_VPI now. Set the flags to
* init_vpi when reg_vfi complete.
*/
vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
rc = VPORT_OK;
goto out;
}
if ((phba->link_state < LPFC_LINK_UP) || if ((phba->link_state < LPFC_LINK_UP) ||
(pport->port_state < LPFC_FABRIC_CFG_LINK) ||
(phba->fc_topology == TOPOLOGY_LOOP)) { (phba->fc_topology == TOPOLOGY_LOOP)) {
lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN); lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
rc = VPORT_OK; rc = VPORT_OK;