162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2021 Broadcom. All Rights Reserved. The term 462306a36Sopenharmony_ci * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include "efclib.h" 862306a36Sopenharmony_ci#include "../libefc_sli/sli4.h" 962306a36Sopenharmony_ci#include "efc_cmds.h" 1062306a36Sopenharmony_ci#include "efc_sm.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistatic void 1362306a36Sopenharmony_ciefc_nport_free_resources(struct efc_nport *nport, int evt, void *data) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct efc *efc = nport->efc; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci /* Clear the nport attached flag */ 1862306a36Sopenharmony_ci nport->attached = false; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci /* Free the service parameters buffer */ 2162306a36Sopenharmony_ci if (nport->dma.virt) { 2262306a36Sopenharmony_ci dma_free_coherent(&efc->pci->dev, nport->dma.size, 2362306a36Sopenharmony_ci nport->dma.virt, nport->dma.phys); 2462306a36Sopenharmony_ci memset(&nport->dma, 0, sizeof(struct efc_dma)); 2562306a36Sopenharmony_ci } 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci /* Free the SLI resources */ 2862306a36Sopenharmony_ci sli_resource_free(efc->sli, SLI4_RSRC_VPI, nport->indicator); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci efc_nport_cb(efc, evt, nport); 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic int 3462306a36Sopenharmony_ciefc_nport_get_mbox_status(struct efc_nport *nport, u8 *mqe, int status) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct efc *efc = nport->efc; 3762306a36Sopenharmony_ci struct sli4_mbox_command_header *hdr = 3862306a36Sopenharmony_ci (struct sli4_mbox_command_header *)mqe; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (status || le16_to_cpu(hdr->status)) { 4162306a36Sopenharmony_ci efc_log_debug(efc, "bad status vpi=%#x st=%x hdr=%x\n", 4262306a36Sopenharmony_ci nport->indicator, status, le16_to_cpu(hdr->status)); 4362306a36Sopenharmony_ci return -EIO; 4462306a36Sopenharmony_ci } 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic int 5062306a36Sopenharmony_ciefc_nport_free_unreg_vpi_cb(struct efc *efc, int status, u8 *mqe, void *arg) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci struct efc_nport *nport = arg; 5362306a36Sopenharmony_ci int evt = EFC_EVT_NPORT_FREE_OK; 5462306a36Sopenharmony_ci int rc; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci rc = efc_nport_get_mbox_status(nport, mqe, status); 5762306a36Sopenharmony_ci if (rc) 5862306a36Sopenharmony_ci evt = EFC_EVT_NPORT_FREE_FAIL; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci efc_nport_free_resources(nport, evt, mqe); 6162306a36Sopenharmony_ci return rc; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic void 6562306a36Sopenharmony_ciefc_nport_free_unreg_vpi(struct efc_nport *nport) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci struct efc *efc = nport->efc; 6862306a36Sopenharmony_ci int rc; 6962306a36Sopenharmony_ci u8 data[SLI4_BMBX_SIZE]; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci rc = sli_cmd_unreg_vpi(efc->sli, data, nport->indicator, 7262306a36Sopenharmony_ci SLI4_UNREG_TYPE_PORT); 7362306a36Sopenharmony_ci if (rc) { 7462306a36Sopenharmony_ci efc_log_err(efc, "UNREG_VPI format failure\n"); 7562306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_FAIL, data); 7662306a36Sopenharmony_ci return; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, data, 8062306a36Sopenharmony_ci efc_nport_free_unreg_vpi_cb, nport); 8162306a36Sopenharmony_ci if (rc) { 8262306a36Sopenharmony_ci efc_log_err(efc, "UNREG_VPI command failure\n"); 8362306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_FAIL, data); 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic void 8862306a36Sopenharmony_ciefc_nport_send_evt(struct efc_nport *nport, int evt, void *data) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci struct efc *efc = nport->efc; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* Now inform the registered callbacks */ 9362306a36Sopenharmony_ci efc_nport_cb(efc, evt, nport); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* Set the nport attached flag */ 9662306a36Sopenharmony_ci if (evt == EFC_EVT_NPORT_ATTACH_OK) 9762306a36Sopenharmony_ci nport->attached = true; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* If there is a pending free request, then handle it now */ 10062306a36Sopenharmony_ci if (nport->free_req_pending) 10162306a36Sopenharmony_ci efc_nport_free_unreg_vpi(nport); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic int 10562306a36Sopenharmony_ciefc_nport_alloc_init_vpi_cb(struct efc *efc, int status, u8 *mqe, void *arg) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct efc_nport *nport = arg; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (efc_nport_get_mbox_status(nport, mqe, status)) { 11062306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, mqe); 11162306a36Sopenharmony_ci return -EIO; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci efc_nport_send_evt(nport, EFC_EVT_NPORT_ALLOC_OK, mqe); 11562306a36Sopenharmony_ci return 0; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic void 11962306a36Sopenharmony_ciefc_nport_alloc_init_vpi(struct efc_nport *nport) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct efc *efc = nport->efc; 12262306a36Sopenharmony_ci u8 data[SLI4_BMBX_SIZE]; 12362306a36Sopenharmony_ci int rc; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /* If there is a pending free request, then handle it now */ 12662306a36Sopenharmony_ci if (nport->free_req_pending) { 12762306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_OK, data); 12862306a36Sopenharmony_ci return; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci rc = sli_cmd_init_vpi(efc->sli, data, 13262306a36Sopenharmony_ci nport->indicator, nport->domain->indicator); 13362306a36Sopenharmony_ci if (rc) { 13462306a36Sopenharmony_ci efc_log_err(efc, "INIT_VPI format failure\n"); 13562306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data); 13662306a36Sopenharmony_ci return; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, data, 14062306a36Sopenharmony_ci efc_nport_alloc_init_vpi_cb, nport); 14162306a36Sopenharmony_ci if (rc) { 14262306a36Sopenharmony_ci efc_log_err(efc, "INIT_VPI command failure\n"); 14362306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data); 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic int 14862306a36Sopenharmony_ciefc_nport_alloc_read_sparm64_cb(struct efc *efc, int status, u8 *mqe, void *arg) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct efc_nport *nport = arg; 15162306a36Sopenharmony_ci u8 *payload = NULL; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (efc_nport_get_mbox_status(nport, mqe, status)) { 15462306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, mqe); 15562306a36Sopenharmony_ci return -EIO; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci payload = nport->dma.virt; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci memcpy(&nport->sli_wwpn, payload + SLI4_READ_SPARM64_WWPN_OFFSET, 16162306a36Sopenharmony_ci sizeof(nport->sli_wwpn)); 16262306a36Sopenharmony_ci memcpy(&nport->sli_wwnn, payload + SLI4_READ_SPARM64_WWNN_OFFSET, 16362306a36Sopenharmony_ci sizeof(nport->sli_wwnn)); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci dma_free_coherent(&efc->pci->dev, nport->dma.size, nport->dma.virt, 16662306a36Sopenharmony_ci nport->dma.phys); 16762306a36Sopenharmony_ci memset(&nport->dma, 0, sizeof(struct efc_dma)); 16862306a36Sopenharmony_ci efc_nport_alloc_init_vpi(nport); 16962306a36Sopenharmony_ci return 0; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic void 17362306a36Sopenharmony_ciefc_nport_alloc_read_sparm64(struct efc *efc, struct efc_nport *nport) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci u8 data[SLI4_BMBX_SIZE]; 17662306a36Sopenharmony_ci int rc; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci /* Allocate memory for the service parameters */ 17962306a36Sopenharmony_ci nport->dma.size = EFC_SPARAM_DMA_SZ; 18062306a36Sopenharmony_ci nport->dma.virt = dma_alloc_coherent(&efc->pci->dev, 18162306a36Sopenharmony_ci nport->dma.size, &nport->dma.phys, 18262306a36Sopenharmony_ci GFP_KERNEL); 18362306a36Sopenharmony_ci if (!nport->dma.virt) { 18462306a36Sopenharmony_ci efc_log_err(efc, "Failed to allocate DMA memory\n"); 18562306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data); 18662306a36Sopenharmony_ci return; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci rc = sli_cmd_read_sparm64(efc->sli, data, 19062306a36Sopenharmony_ci &nport->dma, nport->indicator); 19162306a36Sopenharmony_ci if (rc) { 19262306a36Sopenharmony_ci efc_log_err(efc, "READ_SPARM64 format failure\n"); 19362306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data); 19462306a36Sopenharmony_ci return; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, data, 19862306a36Sopenharmony_ci efc_nport_alloc_read_sparm64_cb, nport); 19962306a36Sopenharmony_ci if (rc) { 20062306a36Sopenharmony_ci efc_log_err(efc, "READ_SPARM64 command failure\n"); 20162306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data); 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciint 20662306a36Sopenharmony_ciefc_cmd_nport_alloc(struct efc *efc, struct efc_nport *nport, 20762306a36Sopenharmony_ci struct efc_domain *domain, u8 *wwpn) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci u32 index; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci nport->indicator = U32_MAX; 21262306a36Sopenharmony_ci nport->free_req_pending = false; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (wwpn) 21562306a36Sopenharmony_ci memcpy(&nport->sli_wwpn, wwpn, sizeof(nport->sli_wwpn)); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* 21862306a36Sopenharmony_ci * allocate a VPI object for the port and stores it in the 21962306a36Sopenharmony_ci * indicator field of the port object. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci if (sli_resource_alloc(efc->sli, SLI4_RSRC_VPI, 22262306a36Sopenharmony_ci &nport->indicator, &index)) { 22362306a36Sopenharmony_ci efc_log_err(efc, "VPI allocation failure\n"); 22462306a36Sopenharmony_ci return -EIO; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (domain) { 22862306a36Sopenharmony_ci /* 22962306a36Sopenharmony_ci * If the WWPN is NULL, fetch the default 23062306a36Sopenharmony_ci * WWPN and WWNN before initializing the VPI 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ci if (!wwpn) 23362306a36Sopenharmony_ci efc_nport_alloc_read_sparm64(efc, nport); 23462306a36Sopenharmony_ci else 23562306a36Sopenharmony_ci efc_nport_alloc_init_vpi(nport); 23662306a36Sopenharmony_ci } else if (!wwpn) { 23762306a36Sopenharmony_ci /* domain NULL and wwpn non-NULL */ 23862306a36Sopenharmony_ci efc_log_err(efc, "need WWN for physical port\n"); 23962306a36Sopenharmony_ci sli_resource_free(efc->sli, SLI4_RSRC_VPI, nport->indicator); 24062306a36Sopenharmony_ci return -EIO; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return 0; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic int 24762306a36Sopenharmony_ciefc_nport_attach_reg_vpi_cb(struct efc *efc, int status, u8 *mqe, 24862306a36Sopenharmony_ci void *arg) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci struct efc_nport *nport = arg; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci nport->attaching = false; 25362306a36Sopenharmony_ci if (efc_nport_get_mbox_status(nport, mqe, status)) { 25462306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, mqe); 25562306a36Sopenharmony_ci return -EIO; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci efc_nport_send_evt(nport, EFC_EVT_NPORT_ATTACH_OK, mqe); 25962306a36Sopenharmony_ci return 0; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ciint 26362306a36Sopenharmony_ciefc_cmd_nport_attach(struct efc *efc, struct efc_nport *nport, u32 fc_id) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci u8 buf[SLI4_BMBX_SIZE]; 26662306a36Sopenharmony_ci int rc = 0; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci if (!nport) { 26962306a36Sopenharmony_ci efc_log_err(efc, "bad param(s) nport=%p\n", nport); 27062306a36Sopenharmony_ci return -EIO; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci nport->fc_id = fc_id; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* register previously-allocated VPI with the device */ 27662306a36Sopenharmony_ci rc = sli_cmd_reg_vpi(efc->sli, buf, nport->fc_id, 27762306a36Sopenharmony_ci nport->sli_wwpn, nport->indicator, 27862306a36Sopenharmony_ci nport->domain->indicator, false); 27962306a36Sopenharmony_ci if (rc) { 28062306a36Sopenharmony_ci efc_log_err(efc, "REG_VPI format failure\n"); 28162306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf); 28262306a36Sopenharmony_ci return rc; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, buf, 28662306a36Sopenharmony_ci efc_nport_attach_reg_vpi_cb, nport); 28762306a36Sopenharmony_ci if (rc) { 28862306a36Sopenharmony_ci efc_log_err(efc, "REG_VPI command failure\n"); 28962306a36Sopenharmony_ci efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf); 29062306a36Sopenharmony_ci } else { 29162306a36Sopenharmony_ci nport->attaching = true; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return rc; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciint 29862306a36Sopenharmony_ciefc_cmd_nport_free(struct efc *efc, struct efc_nport *nport) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci if (!nport) { 30162306a36Sopenharmony_ci efc_log_err(efc, "bad parameter(s) nport=%p\n", nport); 30262306a36Sopenharmony_ci return -EIO; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* Issue the UNREG_VPI command to free the assigned VPI context */ 30662306a36Sopenharmony_ci if (nport->attached) 30762306a36Sopenharmony_ci efc_nport_free_unreg_vpi(nport); 30862306a36Sopenharmony_ci else if (nport->attaching) 30962306a36Sopenharmony_ci nport->free_req_pending = true; 31062306a36Sopenharmony_ci else 31162306a36Sopenharmony_ci efc_sm_post_event(&nport->sm, EFC_EVT_NPORT_FREE_OK, NULL); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci return 0; 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic int 31762306a36Sopenharmony_ciefc_domain_get_mbox_status(struct efc_domain *domain, u8 *mqe, int status) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci struct efc *efc = domain->efc; 32062306a36Sopenharmony_ci struct sli4_mbox_command_header *hdr = 32162306a36Sopenharmony_ci (struct sli4_mbox_command_header *)mqe; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (status || le16_to_cpu(hdr->status)) { 32462306a36Sopenharmony_ci efc_log_debug(efc, "bad status vfi=%#x st=%x hdr=%x\n", 32562306a36Sopenharmony_ci domain->indicator, status, 32662306a36Sopenharmony_ci le16_to_cpu(hdr->status)); 32762306a36Sopenharmony_ci return -EIO; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci return 0; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic void 33462306a36Sopenharmony_ciefc_domain_free_resources(struct efc_domain *domain, int evt, void *data) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci struct efc *efc = domain->efc; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* Free the service parameters buffer */ 33962306a36Sopenharmony_ci if (domain->dma.virt) { 34062306a36Sopenharmony_ci dma_free_coherent(&efc->pci->dev, 34162306a36Sopenharmony_ci domain->dma.size, domain->dma.virt, 34262306a36Sopenharmony_ci domain->dma.phys); 34362306a36Sopenharmony_ci memset(&domain->dma, 0, sizeof(struct efc_dma)); 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* Free the SLI resources */ 34762306a36Sopenharmony_ci sli_resource_free(efc->sli, SLI4_RSRC_VFI, domain->indicator); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci efc_domain_cb(efc, evt, domain); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic void 35362306a36Sopenharmony_ciefc_domain_send_nport_evt(struct efc_domain *domain, 35462306a36Sopenharmony_ci int port_evt, int domain_evt, void *data) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci struct efc *efc = domain->efc; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* Send alloc/attach ok to the physical nport */ 35962306a36Sopenharmony_ci efc_nport_send_evt(domain->nport, port_evt, NULL); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* Now inform the registered callbacks */ 36262306a36Sopenharmony_ci efc_domain_cb(efc, domain_evt, domain); 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic int 36662306a36Sopenharmony_ciefc_domain_alloc_read_sparm64_cb(struct efc *efc, int status, u8 *mqe, 36762306a36Sopenharmony_ci void *arg) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct efc_domain *domain = arg; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if (efc_domain_get_mbox_status(domain, mqe, status)) { 37262306a36Sopenharmony_ci efc_domain_free_resources(domain, 37362306a36Sopenharmony_ci EFC_HW_DOMAIN_ALLOC_FAIL, mqe); 37462306a36Sopenharmony_ci return -EIO; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ALLOC_OK, 37862306a36Sopenharmony_ci EFC_HW_DOMAIN_ALLOC_OK, mqe); 37962306a36Sopenharmony_ci return 0; 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic void 38362306a36Sopenharmony_ciefc_domain_alloc_read_sparm64(struct efc_domain *domain) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci struct efc *efc = domain->efc; 38662306a36Sopenharmony_ci u8 data[SLI4_BMBX_SIZE]; 38762306a36Sopenharmony_ci int rc; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci rc = sli_cmd_read_sparm64(efc->sli, data, &domain->dma, 0); 39062306a36Sopenharmony_ci if (rc) { 39162306a36Sopenharmony_ci efc_log_err(efc, "READ_SPARM64 format failure\n"); 39262306a36Sopenharmony_ci efc_domain_free_resources(domain, 39362306a36Sopenharmony_ci EFC_HW_DOMAIN_ALLOC_FAIL, data); 39462306a36Sopenharmony_ci return; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, data, 39862306a36Sopenharmony_ci efc_domain_alloc_read_sparm64_cb, domain); 39962306a36Sopenharmony_ci if (rc) { 40062306a36Sopenharmony_ci efc_log_err(efc, "READ_SPARM64 command failure\n"); 40162306a36Sopenharmony_ci efc_domain_free_resources(domain, 40262306a36Sopenharmony_ci EFC_HW_DOMAIN_ALLOC_FAIL, data); 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic int 40762306a36Sopenharmony_ciefc_domain_alloc_init_vfi_cb(struct efc *efc, int status, u8 *mqe, 40862306a36Sopenharmony_ci void *arg) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci struct efc_domain *domain = arg; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (efc_domain_get_mbox_status(domain, mqe, status)) { 41362306a36Sopenharmony_ci efc_domain_free_resources(domain, 41462306a36Sopenharmony_ci EFC_HW_DOMAIN_ALLOC_FAIL, mqe); 41562306a36Sopenharmony_ci return -EIO; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci efc_domain_alloc_read_sparm64(domain); 41962306a36Sopenharmony_ci return 0; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic void 42362306a36Sopenharmony_ciefc_domain_alloc_init_vfi(struct efc_domain *domain) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct efc *efc = domain->efc; 42662306a36Sopenharmony_ci struct efc_nport *nport = domain->nport; 42762306a36Sopenharmony_ci u8 data[SLI4_BMBX_SIZE]; 42862306a36Sopenharmony_ci int rc; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci /* 43162306a36Sopenharmony_ci * For FC, the HW alread registered an FCFI. 43262306a36Sopenharmony_ci * Copy FCF information into the domain and jump to INIT_VFI. 43362306a36Sopenharmony_ci */ 43462306a36Sopenharmony_ci domain->fcf_indicator = efc->fcfi; 43562306a36Sopenharmony_ci rc = sli_cmd_init_vfi(efc->sli, data, domain->indicator, 43662306a36Sopenharmony_ci domain->fcf_indicator, nport->indicator); 43762306a36Sopenharmony_ci if (rc) { 43862306a36Sopenharmony_ci efc_log_err(efc, "INIT_VFI format failure\n"); 43962306a36Sopenharmony_ci efc_domain_free_resources(domain, 44062306a36Sopenharmony_ci EFC_HW_DOMAIN_ALLOC_FAIL, data); 44162306a36Sopenharmony_ci return; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci efc_log_err(efc, "%s issue mbox\n", __func__); 44562306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, data, 44662306a36Sopenharmony_ci efc_domain_alloc_init_vfi_cb, domain); 44762306a36Sopenharmony_ci if (rc) { 44862306a36Sopenharmony_ci efc_log_err(efc, "INIT_VFI command failure\n"); 44962306a36Sopenharmony_ci efc_domain_free_resources(domain, 45062306a36Sopenharmony_ci EFC_HW_DOMAIN_ALLOC_FAIL, data); 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ciint 45562306a36Sopenharmony_ciefc_cmd_domain_alloc(struct efc *efc, struct efc_domain *domain, u32 fcf) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci u32 index; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (!domain || !domain->nport) { 46062306a36Sopenharmony_ci efc_log_err(efc, "bad parameter(s) domain=%p nport=%p\n", 46162306a36Sopenharmony_ci domain, domain ? domain->nport : NULL); 46262306a36Sopenharmony_ci return -EIO; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci /* allocate memory for the service parameters */ 46662306a36Sopenharmony_ci domain->dma.size = EFC_SPARAM_DMA_SZ; 46762306a36Sopenharmony_ci domain->dma.virt = dma_alloc_coherent(&efc->pci->dev, 46862306a36Sopenharmony_ci domain->dma.size, 46962306a36Sopenharmony_ci &domain->dma.phys, GFP_KERNEL); 47062306a36Sopenharmony_ci if (!domain->dma.virt) { 47162306a36Sopenharmony_ci efc_log_err(efc, "Failed to allocate DMA memory\n"); 47262306a36Sopenharmony_ci return -EIO; 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci domain->fcf = fcf; 47662306a36Sopenharmony_ci domain->fcf_indicator = U32_MAX; 47762306a36Sopenharmony_ci domain->indicator = U32_MAX; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (sli_resource_alloc(efc->sli, SLI4_RSRC_VFI, &domain->indicator, 48062306a36Sopenharmony_ci &index)) { 48162306a36Sopenharmony_ci efc_log_err(efc, "VFI allocation failure\n"); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci dma_free_coherent(&efc->pci->dev, 48462306a36Sopenharmony_ci domain->dma.size, domain->dma.virt, 48562306a36Sopenharmony_ci domain->dma.phys); 48662306a36Sopenharmony_ci memset(&domain->dma, 0, sizeof(struct efc_dma)); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci return -EIO; 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci efc_domain_alloc_init_vfi(domain); 49262306a36Sopenharmony_ci return 0; 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistatic int 49662306a36Sopenharmony_ciefc_domain_attach_reg_vfi_cb(struct efc *efc, int status, u8 *mqe, 49762306a36Sopenharmony_ci void *arg) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci struct efc_domain *domain = arg; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (efc_domain_get_mbox_status(domain, mqe, status)) { 50262306a36Sopenharmony_ci efc_domain_free_resources(domain, 50362306a36Sopenharmony_ci EFC_HW_DOMAIN_ATTACH_FAIL, mqe); 50462306a36Sopenharmony_ci return -EIO; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ATTACH_OK, 50862306a36Sopenharmony_ci EFC_HW_DOMAIN_ATTACH_OK, mqe); 50962306a36Sopenharmony_ci return 0; 51062306a36Sopenharmony_ci} 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ciint 51362306a36Sopenharmony_ciefc_cmd_domain_attach(struct efc *efc, struct efc_domain *domain, u32 fc_id) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci u8 buf[SLI4_BMBX_SIZE]; 51662306a36Sopenharmony_ci int rc = 0; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci if (!domain) { 51962306a36Sopenharmony_ci efc_log_err(efc, "bad param(s) domain=%p\n", domain); 52062306a36Sopenharmony_ci return -EIO; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci domain->nport->fc_id = fc_id; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci rc = sli_cmd_reg_vfi(efc->sli, buf, SLI4_BMBX_SIZE, domain->indicator, 52662306a36Sopenharmony_ci domain->fcf_indicator, domain->dma, 52762306a36Sopenharmony_ci domain->nport->indicator, domain->nport->sli_wwpn, 52862306a36Sopenharmony_ci domain->nport->fc_id); 52962306a36Sopenharmony_ci if (rc) { 53062306a36Sopenharmony_ci efc_log_err(efc, "REG_VFI format failure\n"); 53162306a36Sopenharmony_ci goto cleanup; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, buf, 53562306a36Sopenharmony_ci efc_domain_attach_reg_vfi_cb, domain); 53662306a36Sopenharmony_ci if (rc) { 53762306a36Sopenharmony_ci efc_log_err(efc, "REG_VFI command failure\n"); 53862306a36Sopenharmony_ci goto cleanup; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci return rc; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cicleanup: 54462306a36Sopenharmony_ci efc_domain_free_resources(domain, EFC_HW_DOMAIN_ATTACH_FAIL, buf); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci return rc; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic int 55062306a36Sopenharmony_ciefc_domain_free_unreg_vfi_cb(struct efc *efc, int status, u8 *mqe, void *arg) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci struct efc_domain *domain = arg; 55362306a36Sopenharmony_ci int evt = EFC_HW_DOMAIN_FREE_OK; 55462306a36Sopenharmony_ci int rc; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci rc = efc_domain_get_mbox_status(domain, mqe, status); 55762306a36Sopenharmony_ci if (rc) { 55862306a36Sopenharmony_ci evt = EFC_HW_DOMAIN_FREE_FAIL; 55962306a36Sopenharmony_ci rc = -EIO; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci efc_domain_free_resources(domain, evt, mqe); 56362306a36Sopenharmony_ci return rc; 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic void 56762306a36Sopenharmony_ciefc_domain_free_unreg_vfi(struct efc_domain *domain) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci struct efc *efc = domain->efc; 57062306a36Sopenharmony_ci int rc; 57162306a36Sopenharmony_ci u8 data[SLI4_BMBX_SIZE]; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci rc = sli_cmd_unreg_vfi(efc->sli, data, domain->indicator, 57462306a36Sopenharmony_ci SLI4_UNREG_TYPE_DOMAIN); 57562306a36Sopenharmony_ci if (rc) { 57662306a36Sopenharmony_ci efc_log_err(efc, "UNREG_VFI format failure\n"); 57762306a36Sopenharmony_ci goto cleanup; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, data, 58162306a36Sopenharmony_ci efc_domain_free_unreg_vfi_cb, domain); 58262306a36Sopenharmony_ci if (rc) { 58362306a36Sopenharmony_ci efc_log_err(efc, "UNREG_VFI command failure\n"); 58462306a36Sopenharmony_ci goto cleanup; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci return; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_cicleanup: 59062306a36Sopenharmony_ci efc_domain_free_resources(domain, EFC_HW_DOMAIN_FREE_FAIL, data); 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ciint 59462306a36Sopenharmony_ciefc_cmd_domain_free(struct efc *efc, struct efc_domain *domain) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci if (!domain) { 59762306a36Sopenharmony_ci efc_log_err(efc, "bad parameter(s) domain=%p\n", domain); 59862306a36Sopenharmony_ci return -EIO; 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci efc_domain_free_unreg_vfi(domain); 60262306a36Sopenharmony_ci return 0; 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ciint 60662306a36Sopenharmony_ciefc_cmd_node_alloc(struct efc *efc, struct efc_remote_node *rnode, u32 fc_addr, 60762306a36Sopenharmony_ci struct efc_nport *nport) 60862306a36Sopenharmony_ci{ 60962306a36Sopenharmony_ci /* Check for invalid indicator */ 61062306a36Sopenharmony_ci if (rnode->indicator != U32_MAX) { 61162306a36Sopenharmony_ci efc_log_err(efc, 61262306a36Sopenharmony_ci "RPI allocation failure addr=%#x rpi=%#x\n", 61362306a36Sopenharmony_ci fc_addr, rnode->indicator); 61462306a36Sopenharmony_ci return -EIO; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci /* NULL SLI port indicates an unallocated remote node */ 61862306a36Sopenharmony_ci rnode->nport = NULL; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci if (sli_resource_alloc(efc->sli, SLI4_RSRC_RPI, 62162306a36Sopenharmony_ci &rnode->indicator, &rnode->index)) { 62262306a36Sopenharmony_ci efc_log_err(efc, "RPI allocation failure addr=%#x\n", 62362306a36Sopenharmony_ci fc_addr); 62462306a36Sopenharmony_ci return -EIO; 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci rnode->fc_id = fc_addr; 62862306a36Sopenharmony_ci rnode->nport = nport; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci return 0; 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic int 63462306a36Sopenharmony_ciefc_cmd_node_attach_cb(struct efc *efc, int status, u8 *mqe, void *arg) 63562306a36Sopenharmony_ci{ 63662306a36Sopenharmony_ci struct efc_remote_node *rnode = arg; 63762306a36Sopenharmony_ci struct sli4_mbox_command_header *hdr = 63862306a36Sopenharmony_ci (struct sli4_mbox_command_header *)mqe; 63962306a36Sopenharmony_ci int evt = 0; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci if (status || le16_to_cpu(hdr->status)) { 64262306a36Sopenharmony_ci efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status, 64362306a36Sopenharmony_ci le16_to_cpu(hdr->status)); 64462306a36Sopenharmony_ci rnode->attached = false; 64562306a36Sopenharmony_ci evt = EFC_EVT_NODE_ATTACH_FAIL; 64662306a36Sopenharmony_ci } else { 64762306a36Sopenharmony_ci rnode->attached = true; 64862306a36Sopenharmony_ci evt = EFC_EVT_NODE_ATTACH_OK; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci efc_remote_node_cb(efc, evt, rnode); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci return 0; 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ciint 65762306a36Sopenharmony_ciefc_cmd_node_attach(struct efc *efc, struct efc_remote_node *rnode, 65862306a36Sopenharmony_ci struct efc_dma *sparms) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci int rc = -EIO; 66162306a36Sopenharmony_ci u8 buf[SLI4_BMBX_SIZE]; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (!rnode || !sparms) { 66462306a36Sopenharmony_ci efc_log_err(efc, "bad parameter(s) rnode=%p sparms=%p\n", 66562306a36Sopenharmony_ci rnode, sparms); 66662306a36Sopenharmony_ci return -EIO; 66762306a36Sopenharmony_ci } 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci /* 67062306a36Sopenharmony_ci * If the attach count is non-zero, this RPI has already been reg'd. 67162306a36Sopenharmony_ci * Otherwise, register the RPI 67262306a36Sopenharmony_ci */ 67362306a36Sopenharmony_ci if (rnode->index == U32_MAX) { 67462306a36Sopenharmony_ci efc_log_err(efc, "bad parameter rnode->index invalid\n"); 67562306a36Sopenharmony_ci return -EIO; 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci /* Update a remote node object with the remote port's service params */ 67962306a36Sopenharmony_ci if (!sli_cmd_reg_rpi(efc->sli, buf, rnode->indicator, 68062306a36Sopenharmony_ci rnode->nport->indicator, rnode->fc_id, sparms, 0, 0)) 68162306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, buf, 68262306a36Sopenharmony_ci efc_cmd_node_attach_cb, rnode); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci return rc; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ciint 68862306a36Sopenharmony_ciefc_node_free_resources(struct efc *efc, struct efc_remote_node *rnode) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci int rc = 0; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci if (!rnode) { 69362306a36Sopenharmony_ci efc_log_err(efc, "bad parameter rnode=%p\n", rnode); 69462306a36Sopenharmony_ci return -EIO; 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci if (rnode->nport) { 69862306a36Sopenharmony_ci if (rnode->attached) { 69962306a36Sopenharmony_ci efc_log_err(efc, "rnode is still attached\n"); 70062306a36Sopenharmony_ci return -EIO; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci if (rnode->indicator != U32_MAX) { 70362306a36Sopenharmony_ci if (sli_resource_free(efc->sli, SLI4_RSRC_RPI, 70462306a36Sopenharmony_ci rnode->indicator)) { 70562306a36Sopenharmony_ci efc_log_err(efc, 70662306a36Sopenharmony_ci "RPI free fail RPI %d addr=%#x\n", 70762306a36Sopenharmony_ci rnode->indicator, rnode->fc_id); 70862306a36Sopenharmony_ci rc = -EIO; 70962306a36Sopenharmony_ci } else { 71062306a36Sopenharmony_ci rnode->indicator = U32_MAX; 71162306a36Sopenharmony_ci rnode->index = U32_MAX; 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci return rc; 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cistatic int 72062306a36Sopenharmony_ciefc_cmd_node_free_cb(struct efc *efc, int status, u8 *mqe, void *arg) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci struct efc_remote_node *rnode = arg; 72362306a36Sopenharmony_ci struct sli4_mbox_command_header *hdr = 72462306a36Sopenharmony_ci (struct sli4_mbox_command_header *)mqe; 72562306a36Sopenharmony_ci int evt = EFC_EVT_NODE_FREE_FAIL; 72662306a36Sopenharmony_ci int rc = 0; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (status || le16_to_cpu(hdr->status)) { 72962306a36Sopenharmony_ci efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status, 73062306a36Sopenharmony_ci le16_to_cpu(hdr->status)); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci /* 73362306a36Sopenharmony_ci * In certain cases, a non-zero MQE status is OK (all must be 73462306a36Sopenharmony_ci * true): 73562306a36Sopenharmony_ci * - node is attached 73662306a36Sopenharmony_ci * - status is 0x1400 73762306a36Sopenharmony_ci */ 73862306a36Sopenharmony_ci if (!rnode->attached || 73962306a36Sopenharmony_ci (le16_to_cpu(hdr->status) != SLI4_MBX_STATUS_RPI_NOT_REG)) 74062306a36Sopenharmony_ci rc = -EIO; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci if (!rc) { 74462306a36Sopenharmony_ci rnode->attached = false; 74562306a36Sopenharmony_ci evt = EFC_EVT_NODE_FREE_OK; 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci efc_remote_node_cb(efc, evt, rnode); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci return rc; 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ciint 75462306a36Sopenharmony_ciefc_cmd_node_detach(struct efc *efc, struct efc_remote_node *rnode) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci u8 buf[SLI4_BMBX_SIZE]; 75762306a36Sopenharmony_ci int rc = -EIO; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci if (!rnode) { 76062306a36Sopenharmony_ci efc_log_err(efc, "bad parameter rnode=%p\n", rnode); 76162306a36Sopenharmony_ci return -EIO; 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci if (rnode->nport) { 76562306a36Sopenharmony_ci if (!rnode->attached) 76662306a36Sopenharmony_ci return -EIO; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci rc = -EIO; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci if (!sli_cmd_unreg_rpi(efc->sli, buf, rnode->indicator, 77162306a36Sopenharmony_ci SLI4_RSRC_RPI, U32_MAX)) 77262306a36Sopenharmony_ci rc = efc->tt.issue_mbox_rqst(efc->base, buf, 77362306a36Sopenharmony_ci efc_cmd_node_free_cb, rnode); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci if (rc != 0) { 77662306a36Sopenharmony_ci efc_log_err(efc, "UNREG_RPI failed\n"); 77762306a36Sopenharmony_ci rc = -EIO; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci return rc; 78262306a36Sopenharmony_ci} 783