|
@@ -2079,6 +2079,128 @@ out:
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * lpfc_create_static_vport - Read HBA config region to create static vports.
|
|
|
+ * @phba: pointer to lpfc hba data structure.
|
|
|
+ *
|
|
|
+ * This routine issue a DUMP mailbox command for config region 22 to get
|
|
|
+ * the list of static vports to be created. The function create vports
|
|
|
+ * based on the information returned from the HBA.
|
|
|
+ **/
|
|
|
+void
|
|
|
+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;
|
|
|
+ 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;
|
|
|
+
|
|
|
+ pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
|
|
+ if (!pmb) {
|
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
|
|
+ "0542 lpfc_create_static_vport failed to"
|
|
|
+ " allocate mailbox memory\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ mb = &pmb->u.mb;
|
|
|
+
|
|
|
+ vport_info = kzalloc(sizeof(struct static_vport_info), GFP_KERNEL);
|
|
|
+ if (!vport_info) {
|
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
|
|
+ "0543 lpfc_create_static_vport failed to"
|
|
|
+ " allocate vport_info\n");
|
|
|
+ mempool_free(pmb, phba->mbox_mem_pool);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ vport_buff = (uint8_t *) vport_info;
|
|
|
+ do {
|
|
|
+ lpfc_dump_static_vport(phba, pmb, offset);
|
|
|
+ pmb->vport = phba->pport;
|
|
|
+ rc = lpfc_sli_issue_mbox_wait(phba, pmb, LPFC_MBOX_TMO);
|
|
|
+
|
|
|
+ if ((rc != MBX_SUCCESS) || mb->mbxStatus) {
|
|
|
+ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
|
|
|
+ "0544 lpfc_create_static_vport failed to"
|
|
|
+ " issue dump mailbox command ret 0x%x "
|
|
|
+ "status 0x%x\n",
|
|
|
+ rc, mb->mbxStatus);
|
|
|
+ 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;
|
|
|
+
|
|
|
+ } while (mb->un.varDmp.word_cnt &&
|
|
|
+ offset < sizeof(struct static_vport_info));
|
|
|
+
|
|
|
+
|
|
|
+ if ((le32_to_cpu(vport_info->signature) != VPORT_INFO_SIG) ||
|
|
|
+ ((le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK)
|
|
|
+ != VPORT_INFO_REV)) {
|
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
|
|
+ "0545 lpfc_create_static_vport bad"
|
|
|
+ " information header 0x%x 0x%x\n",
|
|
|
+ le32_to_cpu(vport_info->signature),
|
|
|
+ le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK);
|
|
|
+
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ shost = lpfc_shost_from_vport(phba->pport);
|
|
|
+
|
|
|
+ for (i = 0; i < MAX_STATIC_VPORT_COUNT; i++) {
|
|
|
+ memset(&vport_id, 0, sizeof(vport_id));
|
|
|
+ vport_id.port_name = wwn_to_u64(vport_info->vport_list[i].wwpn);
|
|
|
+ vport_id.node_name = wwn_to_u64(vport_info->vport_list[i].wwnn);
|
|
|
+ if (!vport_id.port_name || !vport_id.node_name)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR;
|
|
|
+ vport_id.vport_type = FC_PORTTYPE_NPIV;
|
|
|
+ vport_id.disable = false;
|
|
|
+ new_fc_vport = fc_vport_create(shost, 0, &vport_id);
|
|
|
+
|
|
|
+ if (!new_fc_vport) {
|
|
|
+ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
|
|
|
+ "0546 lpfc_create_static_vport failed to"
|
|
|
+ " create vport \n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ vport = *(struct lpfc_vport **)new_fc_vport->dd_data;
|
|
|
+ vport->vport_flag |= STATIC_VPORT;
|
|
|
+ }
|
|
|
+
|
|
|
+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)
|
|
|
+ mempool_free(pmb, phba->mbox_mem_pool);
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This routine handles processing a Fabric REG_LOGIN mailbox
|
|
|
* command upon completion. It is setup in the LPFC_MBOXQ
|
|
@@ -2089,16 +2211,17 @@ void
|
|
|
lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
{
|
|
|
struct lpfc_vport *vport = pmb->vport;
|
|
|
- MAILBOX_t *mb = &pmb->mb;
|
|
|
+ MAILBOX_t *mb = &pmb->u.mb;
|
|
|
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
|
|
|
struct lpfc_nodelist *ndlp;
|
|
|
- struct lpfc_vport **vports;
|
|
|
- int i;
|
|
|
|
|
|
ndlp = (struct lpfc_nodelist *) pmb->context2;
|
|
|
pmb->context1 = NULL;
|
|
|
pmb->context2 = NULL;
|
|
|
if (mb->mbxStatus) {
|
|
|
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
|
|
|
+ "0258 Register Fabric login error: 0x%x\n",
|
|
|
+ mb->mbxStatus);
|
|
|
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
|
|
kfree(mp);
|
|
|
mempool_free(pmb, phba->mbox_mem_pool);
|
|
@@ -2117,9 +2240,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
}
|
|
|
|
|
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
|
|
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
|
|
|
- "0258 Register Fabric login error: 0x%x\n",
|
|
|
- mb->mbxStatus);
|
|
|
/* Decrement the reference count to ndlp after the reference
|
|
|
* to the ndlp are done.
|
|
|
*/
|
|
@@ -2128,34 +2248,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
}
|
|
|
|
|
|
ndlp->nlp_rpi = mb->un.varWords[0];
|
|
|
+ ndlp->nlp_flag |= NLP_RPI_VALID;
|
|
|
ndlp->nlp_type |= NLP_FABRIC;
|
|
|
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
|
|
|
|
|
|
if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
|
|
|
- vports = lpfc_create_vport_work_array(phba);
|
|
|
- if (vports != NULL)
|
|
|
- for(i = 0;
|
|
|
- i <= phba->max_vpi && vports[i] != NULL;
|
|
|
- i++) {
|
|
|
- if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
|
|
|
- continue;
|
|
|
- if (phba->fc_topology == TOPOLOGY_LOOP) {
|
|
|
- lpfc_vport_set_state(vports[i],
|
|
|
- FC_VPORT_LINKDOWN);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (phba->link_flag & LS_NPIV_FAB_SUPPORTED)
|
|
|
- lpfc_initial_fdisc(vports[i]);
|
|
|
- else {
|
|
|
- lpfc_vport_set_state(vports[i],
|
|
|
- FC_VPORT_NO_FABRIC_SUPP);
|
|
|
- lpfc_printf_vlog(vport, KERN_ERR,
|
|
|
- LOG_ELS,
|
|
|
- "0259 No NPIV "
|
|
|
- "Fabric support\n");
|
|
|
- }
|
|
|
- }
|
|
|
- lpfc_destroy_vport_work_array(phba, vports);
|
|
|
+ lpfc_start_fdiscs(phba);
|
|
|
lpfc_do_scr_ns_plogi(phba, vport);
|
|
|
}
|
|
|
|
|
@@ -2179,13 +2277,16 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
void
|
|
|
lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
{
|
|
|
- MAILBOX_t *mb = &pmb->mb;
|
|
|
+ MAILBOX_t *mb = &pmb->u.mb;
|
|
|
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
|
|
|
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
|
|
|
struct lpfc_vport *vport = pmb->vport;
|
|
|
|
|
|
if (mb->mbxStatus) {
|
|
|
out:
|
|
|
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
|
|
+ "0260 Register NameServer error: 0x%x\n",
|
|
|
+ mb->mbxStatus);
|
|
|
/* decrement the node reference count held for this
|
|
|
* callback function.
|
|
|
*/
|
|
@@ -2209,15 +2310,13 @@ out:
|
|
|
return;
|
|
|
}
|
|
|
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
|
|
|
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
|
|
- "0260 Register NameServer error: 0x%x\n",
|
|
|
- mb->mbxStatus);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
pmb->context1 = NULL;
|
|
|
|
|
|
ndlp->nlp_rpi = mb->un.varWords[0];
|
|
|
+ ndlp->nlp_flag |= NLP_RPI_VALID;
|
|
|
ndlp->nlp_type |= NLP_FABRIC;
|
|
|
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
|
|
|
|
|
@@ -2718,7 +2817,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba,
|
|
|
if (pring->ringno == LPFC_ELS_RING) {
|
|
|
switch (icmd->ulpCommand) {
|
|
|
case CMD_GEN_REQUEST64_CR:
|
|
|
- if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi)
|
|
|
+ if (iocb->context_un.ndlp == ndlp)
|
|
|
return 1;
|
|
|
case CMD_ELS_REQUEST64_CR:
|
|
|
if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID)
|
|
@@ -2765,7 +2864,7 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
|
|
|
*/
|
|
|
psli = &phba->sli;
|
|
|
rpi = ndlp->nlp_rpi;
|
|
|
- if (rpi) {
|
|
|
+ if (ndlp->nlp_flag & NLP_RPI_VALID) {
|
|
|
/* Now process each ring */
|
|
|
for (i = 0; i < psli->num_rings; i++) {
|
|
|
pring = &psli->ring[i];
|
|
@@ -2813,7 +2912,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|
|
LPFC_MBOXQ_t *mbox;
|
|
|
int rc;
|
|
|
|
|
|
- if (ndlp->nlp_rpi) {
|
|
|
+ if (ndlp->nlp_flag & NLP_RPI_VALID) {
|
|
|
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
|
|
if (mbox) {
|
|
|
lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox);
|
|
@@ -2825,6 +2924,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|
|
}
|
|
|
lpfc_no_rpi(phba, ndlp);
|
|
|
ndlp->nlp_rpi = 0;
|
|
|
+ ndlp->nlp_flag &= ~NLP_RPI_VALID;
|
|
|
return 1;
|
|
|
}
|
|
|
return 0;
|
|
@@ -2972,13 +3072,14 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
|
|
int rc;
|
|
|
|
|
|
lpfc_cancel_retry_delay_tmo(vport, ndlp);
|
|
|
- if (ndlp->nlp_flag & NLP_DEFER_RM && !ndlp->nlp_rpi) {
|
|
|
+ if ((ndlp->nlp_flag & NLP_DEFER_RM) &&
|
|
|
+ !(ndlp->nlp_flag & NLP_RPI_VALID)) {
|
|
|
/* For this case we need to cleanup the default rpi
|
|
|
* allocated by the firmware.
|
|
|
*/
|
|
|
if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))
|
|
|
!= NULL) {
|
|
|
- rc = lpfc_reg_login(phba, vport->vpi, ndlp->nlp_DID,
|
|
|
+ rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID,
|
|
|
(uint8_t *) &vport->fc_sparam, mbox, 0);
|
|
|
if (rc) {
|
|
|
mempool_free(mbox, phba->mbox_mem_pool);
|
|
@@ -3713,6 +3814,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|
|
pmb->context1 = NULL;
|
|
|
|
|
|
ndlp->nlp_rpi = mb->un.varWords[0];
|
|
|
+ ndlp->nlp_flag |= NLP_RPI_VALID;
|
|
|
ndlp->nlp_type |= NLP_FABRIC;
|
|
|
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
|
|
|
|