From 1c6834a7e85715a4ac07c1cac25a1950040decb0 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 19 Jul 2009 10:01:26 -0400 Subject: [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 Signed-off-by: James Bottomley Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 114 ++++++++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 20 deletions(-) (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index cc4b6ba9e4d..491c53fd1ca 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1633,6 +1633,39 @@ out: 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. * @phba: pointer to lpfc hba data structure. @@ -1645,6 +1678,8 @@ lpfc_start_fdiscs(struct lpfc_hba *phba) { struct lpfc_vport **vports; int i; + LPFC_MBOXQ_t *mboxq; + int rc; vports = lpfc_create_vport_work_array(phba); if (vports != NULL) { @@ -1662,6 +1697,29 @@ lpfc_start_fdiscs(struct lpfc_hba *phba) FC_VPORT_LINKDOWN); 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) lpfc_initial_fdisc(vports[i]); else { @@ -2242,13 +2300,15 @@ lpfc_create_static_vport(struct lpfc_hba *phba) LPFC_MBOXQ_t *pmb = NULL; MAILBOX_t *mb; struct static_vport_info *vport_info; - int rc, i; + int rc = 0, i; struct fc_vport_identifiers vport_id; struct fc_vport *new_fc_vport; struct Scsi_Host *shost; struct lpfc_vport *vport; uint16_t offset = 0; uint8_t *vport_buff; + struct lpfc_dmabuf *mp; + uint32_t byte_count = 0; pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { @@ -2271,7 +2331,9 @@ lpfc_create_static_vport(struct lpfc_hba *phba) vport_buff = (uint8_t *) vport_info; do { - lpfc_dump_static_vport(phba, pmb, offset); + if (lpfc_dump_static_vport(phba, pmb, offset)) + goto out; + pmb->vport = phba->pport; 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; } - if (mb->un.varDmp.word_cnt > - sizeof(struct static_vport_info) - offset) - mb->un.varDmp.word_cnt = - sizeof(struct static_vport_info) - offset; - - lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, - vport_buff + offset, - mb->un.varDmp.word_cnt); - offset += mb->un.varDmp.word_cnt; + if (phba->sli_rev == LPFC_SLI_REV4) { + byte_count = pmb->u.mqe.un.mb_words[5]; + mp = (struct lpfc_dmabuf *) pmb->context2; + 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); + + offset += byte_count; + } - } while (mb->un.varDmp.word_cnt && + } while (byte_count && offset < sizeof(struct static_vport_info)); @@ -2336,16 +2411,15 @@ lpfc_create_static_vport(struct lpfc_hba *phba) } 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); - 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); + } return; } -- cgit v1.2.3