From: Rob Evers <revers@redhat.com> Date: Fri, 10 Jul 2009 14:17:21 -0400 Subject: [scsi] lpfc: update to version 8.2.0.48 Message-id: 20090710181250.4580.48268.sendpatchset@localhost.localdomain O-Subject: [RHEL5.4 PATCH 1/3 v3] lpfc: Update from version 8.2.0.46 to version 8.2.0.48 Bugzilla: 509010 RH-Acked-by: Tomas Henzl <thenzl@redhat.com> https://bugzilla.redhat.com/show_bug.cgi?id=509010 Description: Patchset updates lpfc driver from version 8.2.0.46 to 8.2.0.48.1p Resubmission of patchset to address a problem found during code review after posting to rh-kernel-list. Patch 3/3 is a patch to the original submission addressing the coding bug noticed during code review. 3/3 originated at Emulex. Patch 3/3 is the only difference from the original submission of this patch. From bz509010: * Wait for HBA POST completion before checking Online and UE registers * Remove cast when using pci_read_config_dword() to access LPFC_SLIREV_CONF_WORD * Fixed unsolicited CT commands crashing kernel * Fixed static vport creation on SLI4 HBAs * Fixed vport create not to send INIT_VPI before REG_VFI * Restore behavior of lpfc_device_reset_handler to issue target reset (CR 91267) * Remove duplicated SCSI netlink #defines from lpfc_auth_access.h * Fixed unsolicited CT commands not being responded to * Fixed send management command length * Fixed driver unable to discover targets with DHCHAP enabled (CR 91073) * Do not issue mailbox command when LPFC_HBA_ERROR with MBX_POLL mode * Fixed accumulated total length not being filled in on SLI4 unsolicited IOCBs * Fixed FCoE parameters in region 23 not being read correctly * Fixed SLI3 in-band remote management (CR 91042) Upstream Status: Bug fixes only, Upstream work is being implemented concurrently. Brew Build#: 1884893 Testing: Previously ran dt overnight without any errors on [1/1] Performance is in line with previous version of driver Re-running dt over the weekend with latest patches applied. diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 715afea..50a1ffc 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -439,6 +439,7 @@ struct lpfc_vport { #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_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; #define FC_CT_RFF_ID 0x1 /* RFF_ID accepted by switch */ @@ -817,6 +818,7 @@ struct lpfc_hba { struct pci_pool *lpfc_mbuf_pool; struct pci_pool *lpfc_hrb_pool; /* header receive buffer pool */ struct pci_pool *lpfc_drb_pool; /* data receive buffer pool */ + struct pci_pool *lpfc_hbq_pool; /* SLI3 hbq buffer pool */ struct lpfc_dma_pool lpfc_mbuf_safety_pool; mempool_t *mbox_mem_pool; diff --git a/drivers/scsi/lpfc/lpfc_auth_access.c b/drivers/scsi/lpfc/lpfc_auth_access.c index b9b602e..1e5346c 100644 --- a/drivers/scsi/lpfc/lpfc_auth_access.c +++ b/drivers/scsi/lpfc/lpfc_auth_access.c @@ -364,23 +364,18 @@ lpfc_fc_sc_schedule_notify_all(int message) unsigned long flags; spin_lock_irqsave(&fc_security_user_lock, flags); - list_for_each_entry(vport, &fc_security_user_list, sc_users) { - switch (message) { - case FC_NL_SC_REG: lpfc_fc_queue_security_work(vport, &vport->sc_online_work); break; - case FC_NL_SC_DEREG: lpfc_fc_queue_security_work(vport, &vport->sc_offline_work); break; } } - spin_unlock_irqrestore(&fc_security_user_lock, flags); } diff --git a/drivers/scsi/lpfc/lpfc_auth_access.h b/drivers/scsi/lpfc/lpfc_auth_access.h index 5078671..ebf9c6b 100644 --- a/drivers/scsi/lpfc/lpfc_auth_access.h +++ b/drivers/scsi/lpfc/lpfc_auth_access.h @@ -20,17 +20,6 @@ #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t) -/* scsi_nl_hdr->version value */ -#define SCSI_NL_VERSION 1 - -/* scsi_nl_hdr->magic value */ -#define SCSI_NL_MAGIC 0xA1B2 - -/* scsi_nl_hdr->transport value */ -#define SCSI_NL_TRANSPORT 0 -#define SCSI_NL_TRANSPORT_FC 1 -#define SCSI_NL_MAX_TRANSPORTS 2 - #define FC_NL_GROUP_CNT 0 /* Note: when specifying vendor_id to fc_host_post_vendor_event() diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index a9334e6..5f90157 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -32,7 +32,7 @@ void lpfc_dump_serdes_param(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_sli_read_serdes_param(struct lpfc_hba *); void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_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 *); void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index da9f81e..205ec03 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -593,10 +593,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } else { ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); - if (vport->vfi_state & LPFC_VFI_REGISTERED) { - lpfc_start_fdiscs(phba); - lpfc_do_scr_ns_plogi(phba, vport); - } else + if (vport->vfi_state & LPFC_VFI_REGISTERED) + lpfc_start_discovery(vport); + else lpfc_issue_reg_vfi(vport); } return 0; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index e66cfef..aa2a256 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1692,6 +1692,39 @@ out: } /** + * 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. * @@ -1703,6 +1736,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) { @@ -1720,6 +1755,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 { @@ -2294,12 +2352,14 @@ 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 Scsi_Host *shost; struct lpfc_vport *vport; uint16_t offset = 0; uint8_t *vport_buff, vname = '\0'; uint64_t wwpn, wwnn; + struct lpfc_dmabuf *mp; + uint32_t byte_count = 0; pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!pmb) { @@ -2322,7 +2382,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); @@ -2335,17 +2397,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)); @@ -2382,16 +2457,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; } @@ -4632,7 +4706,7 @@ lpfc_read_fcoe_param(struct lpfc_hba *phba, fcoe_param_hdr = (struct lpfc_fip_param_hdr *) buff; fcoe_param = (struct lpfc_fcoe_params *) - buff + sizeof(struct lpfc_fip_param_hdr); + (buff + sizeof(struct lpfc_fip_param_hdr)); if ((fcoe_param_hdr->parm_version != FIPP_VERSION) || (fcoe_param_hdr->length != FCOE_PARAM_LENGTH)) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index abfac84..34895f4 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2210,6 +2210,8 @@ lpfc_online(struct lpfc_hba *phba) vports[i]->fc_flag &= ~FC_OFFLINE_MODE; if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) 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); } lpfc_destroy_vport_work_array(phba, vports); @@ -4546,23 +4548,6 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) if (!phba->sli4_hba.STAregaddr) return -ENODEV; - /* With uncoverable error, log the error message and return error */ - onlnreg0 = readl(phba->sli4_hba.ONLINE0regaddr); - onlnreg1 = readl(phba->sli4_hba.ONLINE1regaddr); - if ((onlnreg0 != LPFC_ONLINE_NERR) || (onlnreg1 != LPFC_ONLINE_NERR)) { - uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr); - uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr); - if (uerrlo_reg.word0 || uerrhi_reg.word0) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "1422 HBA Unrecoverable error: " - "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, " - "online0_reg=0x%x, online1_reg=0x%x\n", - uerrlo_reg.word0, uerrhi_reg.word0, - onlnreg0, onlnreg1); - } - return -ENODEV; - } - /* Wait up to 30 seconds for the SLI Port POST done and ready */ for (i = 0; i < 3000; i++) { sta_reg.word0 = readl(phba->sli4_hba.STAregaddr); @@ -4602,6 +4587,23 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba) bf_get(lpfc_scratchpad_featurelevel1, &scratchpad), bf_get(lpfc_scratchpad_featurelevel2, &scratchpad)); + /* With uncoverable error, log the error message and return error */ + onlnreg0 = readl(phba->sli4_hba.ONLINE0regaddr); + onlnreg1 = readl(phba->sli4_hba.ONLINE1regaddr); + if ((onlnreg0 != LPFC_ONLINE_NERR) || (onlnreg1 != LPFC_ONLINE_NERR)) { + uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr); + uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr); + if (uerrlo_reg.word0 || uerrhi_reg.word0) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "1422 HBA Unrecoverable error: " + "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, " + "online0_reg=0x%x, online1_reg=0x%x\n", + uerrlo_reg.word0, uerrhi_reg.word0, + onlnreg0, onlnreg1); + } + return -ENODEV; + } + return port_error; } @@ -6801,6 +6803,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) struct lpfc_vport *vport = NULL; int error; uint32_t cfg_mode, intr_mode; + struct Scsi_Host *shost = NULL; /* Allocate memory for HBA structure */ phba = lpfc_hba_alloc(pdev); @@ -6873,6 +6876,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) /* Confiugre sysfs attributes */ vport = phba->pport; + shost = lpfc_shost_from_vport(vport); phba->dfc_host = lpfcdfc_host_add(pdev, lpfc_shost_from_vport(vport), phba); if (!phba->dfc_host) { @@ -6888,6 +6892,18 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_destroy_lpfcdfc_host; } + /* Add this shost to the security event list */ + if ((lpfc_get_security_enabled)(shost)) { + /* Triggers fcauthd to register if it is running */ + fc_host_post_event(shost, fc_get_event_number(), + FCH_EVT_PORT_ONLINE, shost->host_no); + spin_lock_irq(&fc_security_user_lock); + list_add_tail(&vport->sc_users, &fc_security_user_list); + spin_unlock_irq(&fc_security_user_lock); + if (fc_service_state == FC_SC_SERVICESTATE_ONLINE) + lpfc_fc_queue_security_work(vport, + &vport->sc_online_work); + } /* Now, trying to enable interrupt and bring up the device */ cfg_mode = phba->cfg_use_msi; while (1) { @@ -7365,6 +7381,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) int error; uint32_t cfg_mode, intr_mode; int mcnt; + struct Scsi_Host *shost = NULL; /* Allocate memory for HBA structure */ phba = lpfc_hba_alloc(pdev); @@ -7435,8 +7452,10 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Configure sysfs attributes */ vport = phba->pport; + shost = lpfc_shost_from_vport(vport); + phba->dfc_host = lpfcdfc_host_add(pdev, lpfc_shost_from_vport(vport), - phba); + phba); if (!phba->dfc_host) { lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC, "1262 Failed to allocate dfc_host \n"); @@ -7450,6 +7469,18 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_destroy_lpfcdfc_host; } + /* Add this shost to the security event list */ + if ((lpfc_get_security_enabled)(shost)) { + /* Triggers fcauthd to register if it is running */ + fc_host_post_event(shost, fc_get_event_number(), + FCH_EVT_PORT_ONLINE, shost->host_no); + spin_lock_irq(&fc_security_user_lock); + list_add_tail(&vport->sc_users, &fc_security_user_list); + spin_unlock_irq(&fc_security_user_lock); + if (fc_service_state == FC_SC_SERVICESTATE_ONLINE) + lpfc_fc_queue_security_work(vport, + &vport->sc_online_work); + } /* Now, trying to enable interrupt and bring up the device */ cfg_mode = phba->cfg_use_msi; while (true) { @@ -7497,12 +7528,20 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) /* Perform post initialization setup */ lpfc_post_init_setup(phba); + /* Check if there are static vports to be created. */ + lpfc_create_static_vport(phba); + return 0; out_disable_intr: lpfc_sli4_disable_intr(phba); out_free_sysfs_attr: lpfc_free_sysfs_attr(vport); + if ((lpfc_get_security_enabled)(shost)) { + spin_lock_irq(&fc_security_user_lock); + list_del(&vport->sc_users); + spin_unlock_irq(&fc_security_user_lock); + } out_destroy_lpfcdfc_host: lpfcdfc_host_del(phba->dfc_host); out_destroy_shost: @@ -7804,8 +7843,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) return -EPERM; } - if (pci_read_config_dword(pdev, LPFC_SLIREV_CONF_WORD, - (uint32_t *) &intf)) + if (pci_read_config_dword(pdev, LPFC_SLIREV_CONF_WORD, &intf.word0)) return -ENODEV; if ((bf_get(lpfc_sli_intf_valid, &intf) == LPFC_SLI_INTF_VALID) && diff --git a/drivers/scsi/lpfc/lpfc_ioctl.c b/drivers/scsi/lpfc/lpfc_ioctl.c index 76e216e..9f45bff 100644 --- a/drivers/scsi/lpfc/lpfc_ioctl.c +++ b/drivers/scsi/lpfc/lpfc_ioctl.c @@ -66,6 +66,11 @@ struct event_data { uint32_t len; }; +struct unsol_rcv_ct_ctx { + uint32_t ctxt_id; + uint32_t SID; + uint32_t oxid; +}; /* values for a_topology */ #define LNK_LOOP 0x1 @@ -93,6 +98,8 @@ struct lpfcdfc_host { struct lpfc_iocbq *); /* Threads waiting for async event */ struct list_head ev_waiters; + struct unsol_rcv_ct_ctx ct_ctx[64]; + uint32_t ctx_idx; uint32_t blocked; uint32_t ref_count; }; @@ -1764,6 +1771,8 @@ lpfc_issue_ct_rsp(struct lpfc_hba * phba, uint32_t tag, struct lpfc_iocbq *ctiocb; uint32_t num_entry; int rc = 0; + struct lpfc_nodelist *ndlp = NULL; + struct lpfcdfc_host *dfchba = lpfcdfc_host_from_hba(phba); psli = &phba->sli; num_entry = inp->flag; @@ -1795,7 +1804,23 @@ lpfc_issue_ct_rsp(struct lpfc_hba * phba, uint32_t tag, icmd->ulpBdeCount = 1; icmd->ulpLe = 1; icmd->ulpClass = CLASS3; - icmd->ulpContext = (ushort) tag; + if (phba->sli_rev == LPFC_SLI_REV4) { + icmd->ulpContext = dfchba->ct_ctx[tag].oxid; + ndlp = lpfc_findnode_did(phba->pport, dfchba->ct_ctx[tag].SID); + if (!ndlp) { + lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, + "1268 ndlp null for oxid %x SID %x\n", + icmd->ulpContext, + dfchba->ct_ctx[tag].SID); + lpfc_sli_release_iocbq(phba, ctiocb); + return IOCB_ERROR; + } + icmd->un.ulpWord[3] = ndlp->nlp_rpi; + dfchba->ct_ctx[tag].oxid = 0; + dfchba->ct_ctx[tag].SID = 0; + } else + icmd->ulpContext = (ushort) tag; + icmd->ulpTimeout = phba->fc_ratov * 2; /* Xmit CT response on exchange <xid> */ @@ -1806,6 +1831,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba * phba, uint32_t tag, ctiocb->iocb_cmpl = NULL; ctiocb->iocb_flag |= LPFC_IO_LIBDFC; ctiocb->vport = phba->pport; + ctiocb->context3 = bmp; rc = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, ctiocb, NULL, phba->fc_ratov * 2 + LPFC_DRVR_TIMEOUT); @@ -1850,6 +1876,8 @@ lpfcdfc_ct_unsol_event(struct lpfc_hba * phba, BUG_ON(&dfchba->node == &lpfcdfc_hosts); INIT_LIST_HEAD(&head); + list_add_tail(&head, &piocbq->list); + if (piocbq->iocb.ulpBdeCount == 0 || piocbq->iocb.un.cont64[0].tus.f.bdeSize == 0) goto error_unsol_ct_exit; @@ -1885,8 +1913,6 @@ lpfcdfc_ct_unsol_event(struct lpfc_hba * phba, mutex_unlock(&lpfcdfc_lock); - INIT_LIST_HEAD(&head); - list_add_tail(&head, &piocbq->list); if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { /* take accumulated byte count from the last iocbq */ iocbq = list_entry(head.prev, typeof(*iocbq), list); @@ -1988,7 +2014,16 @@ lpfcdfc_ct_unsol_event(struct lpfc_hba * phba, } mutex_lock(&lpfcdfc_lock); - evt_dat->immed_dat = piocbq->iocb.ulpContext; + if (phba->sli_rev == LPFC_SLI_REV4) { + evt_dat->immed_dat = dfchba->ctx_idx % 64; + dfchba->ctx_idx += dfchba->ctx_idx++ % 64; + dfchba->ct_ctx[evt_dat->immed_dat].oxid = + piocbq->iocb.ulpContext; + dfchba->ct_ctx[evt_dat->immed_dat].SID = + piocbq->iocb.un.rcvels.remoteID; + } else + evt_dat->immed_dat = piocbq->iocb.ulpContext; + evt_dat->type = FC_REG_CT_EVENT; list_add(&evt_dat->node, &evt->events_to_see); wake_up_interruptible(&evt->wq); diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 9e222ef..d58ce08 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -56,30 +56,51 @@ * This routine prepares the mailbox command for dumping list of static * vports to be created. **/ -void +int lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, uint16_t offset) { MAILBOX_t *mb; - void *ctx; + struct lpfc_dmabuf *mp; mb = &pmb->u.mb; - ctx = pmb->context2; /* Setup to dump vport info region */ memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); mb->mbxCommand = MBX_DUMP_MEMORY; - mb->un.varDmp.cv = 1; mb->un.varDmp.type = DMP_NV_PARAMS; mb->un.varDmp.entry_index = offset; 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; - 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; } /** diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index cecd2cc..6a94f40 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -110,17 +110,28 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) sizeof(struct lpfc_nodelist)); if (!phba->nlp_mem_pool) goto fail_free_mbox_pool; - phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool", + + if (phba->sli_rev == LPFC_SLI_REV4) { + phba->lpfc_hrb_pool = pci_pool_create("lpfc_hrb_pool", phba->pcidev, LPFC_HDR_BUF_SIZE, align, 0); - if (!phba->lpfc_hrb_pool) - goto fail_free_nlp_mem_pool; - phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool", + if (!phba->lpfc_hrb_pool) + goto fail_free_nlp_mem_pool; + + phba->lpfc_drb_pool = pci_pool_create("lpfc_drb_pool", phba->pcidev, LPFC_DATA_BUF_SIZE, align, 0); - if (!phba->lpfc_drb_pool) - goto fail_free_hbq_pool; - + if (!phba->lpfc_drb_pool) + goto fail_free_hrb_pool; + phba->lpfc_hbq_pool = NULL; + } else { + phba->lpfc_hbq_pool = pci_pool_create("lpfc_hbq_pool", + phba->pcidev, LPFC_BPL_SIZE, align, 0); + if (!phba->lpfc_hbq_pool) + goto fail_free_nlp_mem_pool; + phba->lpfc_hrb_pool = NULL; + phba->lpfc_drb_pool = NULL; + } /* vpi zero is reserved for the physical port so add 1 to max */ longs = ((phba->max_vpi + 1) + BITS_PER_LONG - 1) / BITS_PER_LONG; phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long), GFP_KERNEL); @@ -132,7 +143,7 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) fail_free_dbq_pool: pci_pool_destroy(phba->lpfc_drb_pool); phba->lpfc_drb_pool = NULL; - fail_free_hbq_pool: + fail_free_hrb_pool: pci_pool_destroy(phba->lpfc_hrb_pool); phba->lpfc_hrb_pool = NULL; fail_free_nlp_mem_pool: @@ -176,11 +187,17 @@ lpfc_mem_free(struct lpfc_hba *phba) /* Free HBQ pools */ lpfc_sli_hbqbuf_free_all(phba); - pci_pool_destroy(phba->lpfc_drb_pool); + if (phba->lpfc_drb_pool) + pci_pool_destroy(phba->lpfc_drb_pool); phba->lpfc_drb_pool = NULL; - pci_pool_destroy(phba->lpfc_hrb_pool); + if (phba->lpfc_hrb_pool) + pci_pool_destroy(phba->lpfc_hrb_pool); phba->lpfc_hrb_pool = NULL; + if (phba->lpfc_hbq_pool) + pci_pool_destroy(phba->lpfc_hbq_pool); + phba->lpfc_hbq_pool = NULL; + /* Free NLP memory pool */ mempool_destroy(phba->nlp_mem_pool); phba->nlp_mem_pool = NULL; @@ -380,7 +397,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba) if (!hbqbp) return NULL; - hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hrb_pool, GFP_KERNEL, + hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL, &hbqbp->dbuf.phys); if (!hbqbp->dbuf.virt) { kfree(hbqbp); @@ -405,7 +422,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba) void lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) { - pci_pool_free(phba->lpfc_hrb_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys); + pci_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys); kfree(hbqbp); return; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 57fd297..ffda039 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -2443,7 +2443,7 @@ lpfc_reset_flush_io_context(struct lpfc_vport *vport, uint16_t tgt_id, * lpfc_device_reset_handler - scsi_host_template eh_device_reset entry point * @cmnd: Pointer to scsi_cmnd data structure. * - * This routine does a device reset by sending a LUN_RESET task management + * This routine does a device reset by sending a TARGET_RESET task management * command. * * Return code : @@ -2472,7 +2472,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) } scsi_event.event_type = FC_REG_SCSI_EVENT; - scsi_event.subcategory = LPFC_EVENT_LUNRESET; + scsi_event.subcategory = LPFC_EVENT_TGTRESET; scsi_event.lun = lun_id; memcpy(scsi_event.wwpn, &pnode->nlp_portname, sizeof(struct lpfc_name)); memcpy(scsi_event.wwnn, &pnode->nlp_nodename, sizeof(struct lpfc_name)); @@ -2481,7 +2481,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); status = lpfc_send_taskmgmt(vport, rdata, tgt_id, lun_id, - FCP_LUN_RESET); + FCP_TARGET_RESET); lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "0713 SCSI layer issued Device Reset (%d, %d) " diff --git a/drivers/scsi/lpfc/lpfc_security.c b/drivers/scsi/lpfc/lpfc_security.c index 02ee122..fac81ae 100644 --- a/drivers/scsi/lpfc/lpfc_security.c +++ b/drivers/scsi/lpfc/lpfc_security.c @@ -118,7 +118,7 @@ lpfc_security_config(struct Scsi_Host *shost, int status, void *rsp) auth_rsp->u.dhchap_security_config.auth_mode; lpfc_printf_vlog(vport, KERN_INFO, LOG_SECURITY, "1025 Received security config local_wwpn:" - "%llX remote_wwpn:%llX \nmode:0x%x " + "%llX remote_wwpn:%llX mode:0x%x " "hash(%d):%x:%x:%x:%x bidir:0x%x " "dh_group(%d):%x:%x:%x:%x:%x:%x:%x:%x " "reauth_interval:0x%x\n", diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index d15f2dc..0862365 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -45,6 +45,9 @@ #include "lpfc_compat.h" #include "lpfc_debugfs.h" #include "lpfc_vport.h" +#include "lpfc_security.h" +#include "lpfc_auth_access.h" + /* There are only four IOCB completion types. */ typedef enum _lpfc_iocb_type { @@ -5335,6 +5338,18 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, unsigned long iflags; int rc; + rc = lpfc_mbox_dev_check(phba); + if (unlikely(rc)) { + lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, + "(%d):2544 Mailbox command x%x (x%x) " + "cannot issue Data: x%x x%x\n", + mboxq->vport ? mboxq->vport->vpi : 0, + mboxq->u.mb.mbxCommand, + lpfc_sli4_mbox_opcode_get(phba, mboxq), + psli->sli_flag, flag); + goto out_not_finished; + } + /* Detect polling mode and jump to a handler */ if (!phba->sli4_hba.intr_enable) { if (flag == MBX_POLL) @@ -5394,17 +5409,6 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, psli->sli_flag, flag); goto out_not_finished; } - rc = lpfc_mbox_dev_check(phba); - if (unlikely(rc)) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "(%d):2544 Mailbox command x%x (x%x) " - "cannot issue Data: x%x x%x\n", - mboxq->vport ? mboxq->vport->vpi : 0, - mboxq->u.mb.mbxCommand, - lpfc_sli4_mbox_opcode_get(phba, mboxq), - psli->sli_flag, flag); - goto out_not_finished; - } /* Put the mailbox command to the driver internal FIFO */ psli->slistat.mbox_busy++; @@ -5985,6 +5989,12 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); /* CCP CCPE PV PRI in word10 were set in the memcpy */ break; + case CMD_XMIT_SEQUENCE64_CX: + bf_set(lpfc_wqe_gen_context, &wqe->generic, + iocbq->iocb.un.ulpWord[3]); + wqe->generic.word3 = 0; + bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); + cmnd = CMD_XMIT_SEQUENCE64_CR; case CMD_XMIT_SEQUENCE64_CR: /* word3 iocb=io_tag32 wqe=payload_offset */ /* payload offset used for multilpe outstanding @@ -5995,6 +6005,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, /* word5 r_ctl/df_ctl memcpy */ bf_set(lpfc_wqe_gen_pu, &wqe->generic, 0); wqe->xmit_sequence.xmit_len = payload_len; + command_type = OTHER_COMMAND; break; case CMD_XMIT_BCAST64_CN: /* word3 iocb=iotag32 wqe=payload_len */ @@ -8441,8 +8452,11 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_iocbq *pIocbIn, wcqe->total_data_placed; else pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; - else + else { pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter; + pIocbIn->iocb.un.genreq64.bdl.bdeSize = wcqe->total_data_placed; + } + /* Load in additional WCQE parameters */ pIocbIn->sli4_info.hw_status = bf_get(lpfc_wcqe_c_hw_status, wcqe); pIocbIn->sli4_info.bfield = 0; @@ -9599,8 +9613,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint16_t imax) eq->host_index = 0; eq->hba_index = 0; - if (rc != MBX_TIMEOUT) - mempool_free(mbox, phba->mbox_mem_pool); + mempool_free(mbox, phba->mbox_mem_pool); return status; } @@ -9704,10 +9717,9 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response); cq->host_index = 0; cq->hba_index = 0; -out: - if (rc != MBX_TIMEOUT) - mempool_free(mbox, phba->mbox_mem_pool); +out: + mempool_free(mbox, phba->mbox_mem_pool); return status; } @@ -9812,8 +9824,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, /* link the mq onto the parent cq child list */ list_add_tail(&mq->list, &cq->child_list); out: - if (rc != MBX_TIMEOUT) - mempool_free(mbox, phba->mbox_mem_pool); + mempool_free(mbox, phba->mbox_mem_pool); return status; } @@ -9895,8 +9906,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, /* link the wq onto the parent cq child list */ list_add_tail(&wq->list, &cq->child_list); out: - if (rc != MBX_TIMEOUT) - mempool_free(mbox, phba->mbox_mem_pool); + mempool_free(mbox, phba->mbox_mem_pool); return status; } @@ -10070,8 +10080,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, list_add_tail(&drq->list, &cq->child_list); out: - if (rc != MBX_TIMEOUT) - mempool_free(mbox, phba->mbox_mem_pool); + mempool_free(mbox, phba->mbox_mem_pool); return status; } @@ -10126,8 +10135,7 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq) /* Remove eq from any list */ list_del_init(&eq->list); - if (rc != MBX_TIMEOUT) - mempool_free(mbox, eq->phba->mbox_mem_pool); + mempool_free(mbox, eq->phba->mbox_mem_pool); return status; } @@ -10180,8 +10188,7 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq) } /* Remove cq from any list */ list_del_init(&cq->list); - if (rc != MBX_TIMEOUT) - mempool_free(mbox, cq->phba->mbox_mem_pool); + mempool_free(mbox, cq->phba->mbox_mem_pool); return status; } @@ -10234,8 +10241,7 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq) } /* Remove mq from any list */ list_del_init(&mq->list); - if (rc != MBX_TIMEOUT) - mempool_free(mbox, mq->phba->mbox_mem_pool); + mempool_free(mbox, mq->phba->mbox_mem_pool); return status; } @@ -10287,8 +10293,7 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq) } /* Remove wq from any list */ list_del_init(&wq->list); - if (rc != MBX_TIMEOUT) - mempool_free(mbox, wq->phba->mbox_mem_pool); + mempool_free(mbox, wq->phba->mbox_mem_pool); return status; } @@ -10358,8 +10363,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq, } list_del_init(&hrq->list); list_del_init(&drq->list); - if (rc != MBX_TIMEOUT) - mempool_free(mbox, hrq->phba->mbox_mem_pool); + mempool_free(mbox, hrq->phba->mbox_mem_pool); return status; } @@ -11031,6 +11035,8 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) fc_hdr->fh_s_id[2]); /* Get an iocbq struct to fill in. */ first_iocbq = lpfc_sli_get_iocbq(vport->phba); + first_iocbq->vport = vport; + first_iocbq->iocb.unsli3.rcvsli3.acc_len = 0; if (first_iocbq) { /* Initialize the first IOCB. */ first_iocbq->iocb.ulpStatus = IOSTAT_SUCCESS; @@ -11045,6 +11051,8 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) first_iocbq->iocb.un.cont64[0].tus.f.bdeSize = LPFC_DATA_BUF_SIZE; first_iocbq->iocb.un.rcvels.remoteID = sid; + first_iocbq->iocb.unsli3.rcvsli3.acc_len += + bf_get(lpfc_rcqe_length, &seq_dmabuf->rcqe); } iocbq = first_iocbq; /* @@ -11061,6 +11069,8 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) iocbq->iocb.ulpBdeCount++; iocbq->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize = LPFC_DATA_BUF_SIZE; + first_iocbq->iocb.unsli3.rcvsli3.acc_len += + bf_get(lpfc_rcqe_length, &seq_dmabuf->rcqe); } else { iocbq = lpfc_sli_get_iocbq(vport->phba); if (!iocbq) { @@ -11078,6 +11088,8 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) iocbq->iocb.ulpBdeCount = 1; iocbq->iocb.un.cont64[0].tus.f.bdeSize = LPFC_DATA_BUF_SIZE; + first_iocbq->iocb.unsli3.rcvsli3.acc_len += + bf_get(lpfc_rcqe_length, &seq_dmabuf->rcqe); iocbq->iocb.un.rcvels.remoteID = sid; list_add_tail(&iocbq->list, &first_iocbq->list); } diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index d48d66b..e0ead14 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.2.0.46" +#define LPFC_DRIVER_VERSION "8.2.0.48" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 57d3d06..464a7d6 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -288,7 +288,6 @@ __lpfc_vport_create(struct Scsi_Host *shost, const uint8_t *wwnn, struct lpfc_vport **new_vport) { struct lpfc_nodelist *ndlp; - static uint8_t null_name[8] = { 0, 0, 0, 0, 0, 0, 0, 0, }; struct lpfc_vport *pport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = pport->phba; struct lpfc_vport *vport = NULL; @@ -318,22 +317,6 @@ __lpfc_vport_create(struct Scsi_Host *shost, const uint8_t *wwnn, 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 */ if ((instance = lpfc_get_instance()) < 0) { lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, @@ -372,8 +355,6 @@ __lpfc_vport_create(struct Scsi_Host *shost, const uint8_t *wwnn, goto error_out; } - memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8); - memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8); size = strnlen(vname, LPFC_VNAME_LEN); if (size) { vport->vname = kzalloc(size+1, GFP_KERNEL); @@ -388,9 +369,9 @@ __lpfc_vport_create(struct Scsi_Host *shost, const uint8_t *wwnn, } memcpy(vport->vname, vname, size+1); } - if (wwnn && memcmp(wwnn, null_name, 8)) + if (wwnn) memcpy(vport->fc_nodename.u.wwn, wwnn, 8); - if (wwpn && memcmp(wwpn, null_name, 8)) + if (wwpn) memcpy(vport->fc_portname.u.wwn, wwpn, 8); memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8); @@ -420,12 +401,12 @@ __lpfc_vport_create(struct Scsi_Host *shost, const uint8_t *wwnn, shost = lpfc_shost_from_vport(vport); if ((lpfc_get_security_enabled)(shost)){ + /* Triggers fcauthd to register if it is running */ + fc_host_post_event(shost, fc_get_event_number(), + FCH_EVT_PORT_ONLINE, shost->host_no); spin_lock_irq(&fc_security_user_lock); - list_add_tail(&vport->sc_users, &fc_security_user_list); - spin_unlock_irq(&fc_security_user_lock); - if (fc_service_state == FC_SC_SERVICESTATE_ONLINE) { lpfc_fc_queue_security_work(vport, &vport->sc_online_work); @@ -438,7 +419,34 @@ __lpfc_vport_create(struct Scsi_Host *shost, const uint8_t *wwnn, vport->port_type = LPFC_NPIV_PORT; *new_vport = 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) || + (pport->port_state < LPFC_FABRIC_CFG_LINK) || (phba->fc_topology == TOPOLOGY_LOOP)) { lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN); rc = VPORT_OK;