cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

efc_cmds.c (18595B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
      4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
      5 */
      6
      7#include "efclib.h"
      8#include "../libefc_sli/sli4.h"
      9#include "efc_cmds.h"
     10#include "efc_sm.h"
     11
     12static void
     13efc_nport_free_resources(struct efc_nport *nport, int evt, void *data)
     14{
     15	struct efc *efc = nport->efc;
     16
     17	/* Clear the nport attached flag */
     18	nport->attached = false;
     19
     20	/* Free the service parameters buffer */
     21	if (nport->dma.virt) {
     22		dma_free_coherent(&efc->pci->dev, nport->dma.size,
     23				  nport->dma.virt, nport->dma.phys);
     24		memset(&nport->dma, 0, sizeof(struct efc_dma));
     25	}
     26
     27	/* Free the SLI resources */
     28	sli_resource_free(efc->sli, SLI4_RSRC_VPI, nport->indicator);
     29
     30	efc_nport_cb(efc, evt, nport);
     31}
     32
     33static int
     34efc_nport_get_mbox_status(struct efc_nport *nport, u8 *mqe, int status)
     35{
     36	struct efc *efc = nport->efc;
     37	struct sli4_mbox_command_header *hdr =
     38			(struct sli4_mbox_command_header *)mqe;
     39
     40	if (status || le16_to_cpu(hdr->status)) {
     41		efc_log_debug(efc, "bad status vpi=%#x st=%x hdr=%x\n",
     42			      nport->indicator, status, le16_to_cpu(hdr->status));
     43		return -EIO;
     44	}
     45
     46	return 0;
     47}
     48
     49static int
     50efc_nport_free_unreg_vpi_cb(struct efc *efc, int status, u8 *mqe, void *arg)
     51{
     52	struct efc_nport *nport = arg;
     53	int evt = EFC_EVT_NPORT_FREE_OK;
     54	int rc;
     55
     56	rc = efc_nport_get_mbox_status(nport, mqe, status);
     57	if (rc)
     58		evt = EFC_EVT_NPORT_FREE_FAIL;
     59
     60	efc_nport_free_resources(nport, evt, mqe);
     61	return rc;
     62}
     63
     64static void
     65efc_nport_free_unreg_vpi(struct efc_nport *nport)
     66{
     67	struct efc *efc = nport->efc;
     68	int rc;
     69	u8 data[SLI4_BMBX_SIZE];
     70
     71	rc = sli_cmd_unreg_vpi(efc->sli, data, nport->indicator,
     72			       SLI4_UNREG_TYPE_PORT);
     73	if (rc) {
     74		efc_log_err(efc, "UNREG_VPI format failure\n");
     75		efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_FAIL, data);
     76		return;
     77	}
     78
     79	rc = efc->tt.issue_mbox_rqst(efc->base, data,
     80				     efc_nport_free_unreg_vpi_cb, nport);
     81	if (rc) {
     82		efc_log_err(efc, "UNREG_VPI command failure\n");
     83		efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_FAIL, data);
     84	}
     85}
     86
     87static void
     88efc_nport_send_evt(struct efc_nport *nport, int evt, void *data)
     89{
     90	struct efc *efc = nport->efc;
     91
     92	/* Now inform the registered callbacks */
     93	efc_nport_cb(efc, evt, nport);
     94
     95	/* Set the nport attached flag */
     96	if (evt == EFC_EVT_NPORT_ATTACH_OK)
     97		nport->attached = true;
     98
     99	/* If there is a pending free request, then handle it now */
    100	if (nport->free_req_pending)
    101		efc_nport_free_unreg_vpi(nport);
    102}
    103
    104static int
    105efc_nport_alloc_init_vpi_cb(struct efc *efc, int status, u8 *mqe, void *arg)
    106{
    107	struct efc_nport *nport = arg;
    108
    109	if (efc_nport_get_mbox_status(nport, mqe, status)) {
    110		efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, mqe);
    111		return -EIO;
    112	}
    113
    114	efc_nport_send_evt(nport, EFC_EVT_NPORT_ALLOC_OK, mqe);
    115	return 0;
    116}
    117
    118static void
    119efc_nport_alloc_init_vpi(struct efc_nport *nport)
    120{
    121	struct efc *efc = nport->efc;
    122	u8 data[SLI4_BMBX_SIZE];
    123	int rc;
    124
    125	/* If there is a pending free request, then handle it now */
    126	if (nport->free_req_pending) {
    127		efc_nport_free_resources(nport, EFC_EVT_NPORT_FREE_OK, data);
    128		return;
    129	}
    130
    131	rc = sli_cmd_init_vpi(efc->sli, data,
    132			      nport->indicator, nport->domain->indicator);
    133	if (rc) {
    134		efc_log_err(efc, "INIT_VPI format failure\n");
    135		efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
    136		return;
    137	}
    138
    139	rc = efc->tt.issue_mbox_rqst(efc->base, data,
    140			efc_nport_alloc_init_vpi_cb, nport);
    141	if (rc) {
    142		efc_log_err(efc, "INIT_VPI command failure\n");
    143		efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
    144	}
    145}
    146
    147static int
    148efc_nport_alloc_read_sparm64_cb(struct efc *efc, int status, u8 *mqe, void *arg)
    149{
    150	struct efc_nport *nport = arg;
    151	u8 *payload = NULL;
    152
    153	if (efc_nport_get_mbox_status(nport, mqe, status)) {
    154		efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, mqe);
    155		return -EIO;
    156	}
    157
    158	payload = nport->dma.virt;
    159
    160	memcpy(&nport->sli_wwpn, payload + SLI4_READ_SPARM64_WWPN_OFFSET,
    161	       sizeof(nport->sli_wwpn));
    162	memcpy(&nport->sli_wwnn, payload + SLI4_READ_SPARM64_WWNN_OFFSET,
    163	       sizeof(nport->sli_wwnn));
    164
    165	dma_free_coherent(&efc->pci->dev, nport->dma.size, nport->dma.virt,
    166			  nport->dma.phys);
    167	memset(&nport->dma, 0, sizeof(struct efc_dma));
    168	efc_nport_alloc_init_vpi(nport);
    169	return 0;
    170}
    171
    172static void
    173efc_nport_alloc_read_sparm64(struct efc *efc, struct efc_nport *nport)
    174{
    175	u8 data[SLI4_BMBX_SIZE];
    176	int rc;
    177
    178	/* Allocate memory for the service parameters */
    179	nport->dma.size = EFC_SPARAM_DMA_SZ;
    180	nport->dma.virt = dma_alloc_coherent(&efc->pci->dev,
    181					     nport->dma.size, &nport->dma.phys,
    182					     GFP_KERNEL);
    183	if (!nport->dma.virt) {
    184		efc_log_err(efc, "Failed to allocate DMA memory\n");
    185		efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
    186		return;
    187	}
    188
    189	rc = sli_cmd_read_sparm64(efc->sli, data,
    190				  &nport->dma, nport->indicator);
    191	if (rc) {
    192		efc_log_err(efc, "READ_SPARM64 format failure\n");
    193		efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
    194		return;
    195	}
    196
    197	rc = efc->tt.issue_mbox_rqst(efc->base, data,
    198				     efc_nport_alloc_read_sparm64_cb, nport);
    199	if (rc) {
    200		efc_log_err(efc, "READ_SPARM64 command failure\n");
    201		efc_nport_free_resources(nport, EFC_EVT_NPORT_ALLOC_FAIL, data);
    202	}
    203}
    204
    205int
    206efc_cmd_nport_alloc(struct efc *efc, struct efc_nport *nport,
    207		    struct efc_domain *domain, u8 *wwpn)
    208{
    209	u32 index;
    210
    211	nport->indicator = U32_MAX;
    212	nport->free_req_pending = false;
    213
    214	if (wwpn)
    215		memcpy(&nport->sli_wwpn, wwpn, sizeof(nport->sli_wwpn));
    216
    217	/*
    218	 * allocate a VPI object for the port and stores it in the
    219	 * indicator field of the port object.
    220	 */
    221	if (sli_resource_alloc(efc->sli, SLI4_RSRC_VPI,
    222			       &nport->indicator, &index)) {
    223		efc_log_err(efc, "VPI allocation failure\n");
    224		return -EIO;
    225	}
    226
    227	if (domain) {
    228		/*
    229		 * If the WWPN is NULL, fetch the default
    230		 * WWPN and WWNN before initializing the VPI
    231		 */
    232		if (!wwpn)
    233			efc_nport_alloc_read_sparm64(efc, nport);
    234		else
    235			efc_nport_alloc_init_vpi(nport);
    236	} else if (!wwpn) {
    237		/* domain NULL and wwpn non-NULL */
    238		efc_log_err(efc, "need WWN for physical port\n");
    239		sli_resource_free(efc->sli, SLI4_RSRC_VPI, nport->indicator);
    240		return -EIO;
    241	}
    242
    243	return 0;
    244}
    245
    246static int
    247efc_nport_attach_reg_vpi_cb(struct efc *efc, int status, u8 *mqe,
    248			    void *arg)
    249{
    250	struct efc_nport *nport = arg;
    251
    252	nport->attaching = false;
    253	if (efc_nport_get_mbox_status(nport, mqe, status)) {
    254		efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, mqe);
    255		return -EIO;
    256	}
    257
    258	efc_nport_send_evt(nport, EFC_EVT_NPORT_ATTACH_OK, mqe);
    259	return 0;
    260}
    261
    262int
    263efc_cmd_nport_attach(struct efc *efc, struct efc_nport *nport, u32 fc_id)
    264{
    265	u8 buf[SLI4_BMBX_SIZE];
    266	int rc = 0;
    267
    268	if (!nport) {
    269		efc_log_err(efc, "bad param(s) nport=%p\n", nport);
    270		return -EIO;
    271	}
    272
    273	nport->fc_id = fc_id;
    274
    275	/* register previously-allocated VPI with the device */
    276	rc = sli_cmd_reg_vpi(efc->sli, buf, nport->fc_id,
    277			     nport->sli_wwpn, nport->indicator,
    278			    nport->domain->indicator, false);
    279	if (rc) {
    280		efc_log_err(efc, "REG_VPI format failure\n");
    281		efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf);
    282		return rc;
    283	}
    284
    285	rc = efc->tt.issue_mbox_rqst(efc->base, buf,
    286				     efc_nport_attach_reg_vpi_cb, nport);
    287	if (rc) {
    288		efc_log_err(efc, "REG_VPI command failure\n");
    289		efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf);
    290	} else {
    291		nport->attaching = true;
    292	}
    293
    294	return rc;
    295}
    296
    297int
    298efc_cmd_nport_free(struct efc *efc, struct efc_nport *nport)
    299{
    300	if (!nport) {
    301		efc_log_err(efc, "bad parameter(s) nport=%p\n",	nport);
    302		return -EIO;
    303	}
    304
    305	/* Issue the UNREG_VPI command to free the assigned VPI context */
    306	if (nport->attached)
    307		efc_nport_free_unreg_vpi(nport);
    308	else if (nport->attaching)
    309		nport->free_req_pending = true;
    310	else
    311		efc_sm_post_event(&nport->sm, EFC_EVT_NPORT_FREE_OK, NULL);
    312
    313	return 0;
    314}
    315
    316static int
    317efc_domain_get_mbox_status(struct efc_domain *domain, u8 *mqe, int status)
    318{
    319	struct efc *efc = domain->efc;
    320	struct sli4_mbox_command_header *hdr =
    321			(struct sli4_mbox_command_header *)mqe;
    322
    323	if (status || le16_to_cpu(hdr->status)) {
    324		efc_log_debug(efc, "bad status vfi=%#x st=%x hdr=%x\n",
    325			      domain->indicator, status,
    326			      le16_to_cpu(hdr->status));
    327		return -EIO;
    328	}
    329
    330	return 0;
    331}
    332
    333static void
    334efc_domain_free_resources(struct efc_domain *domain, int evt, void *data)
    335{
    336	struct efc *efc = domain->efc;
    337
    338	/* Free the service parameters buffer */
    339	if (domain->dma.virt) {
    340		dma_free_coherent(&efc->pci->dev,
    341				  domain->dma.size, domain->dma.virt,
    342				  domain->dma.phys);
    343		memset(&domain->dma, 0, sizeof(struct efc_dma));
    344	}
    345
    346	/* Free the SLI resources */
    347	sli_resource_free(efc->sli, SLI4_RSRC_VFI, domain->indicator);
    348
    349	efc_domain_cb(efc, evt, domain);
    350}
    351
    352static void
    353efc_domain_send_nport_evt(struct efc_domain *domain,
    354			  int port_evt, int domain_evt, void *data)
    355{
    356	struct efc *efc = domain->efc;
    357
    358	/* Send alloc/attach ok to the physical nport */
    359	efc_nport_send_evt(domain->nport, port_evt, NULL);
    360
    361	/* Now inform the registered callbacks */
    362	efc_domain_cb(efc, domain_evt, domain);
    363}
    364
    365static int
    366efc_domain_alloc_read_sparm64_cb(struct efc *efc, int status, u8 *mqe,
    367				 void *arg)
    368{
    369	struct efc_domain *domain = arg;
    370
    371	if (efc_domain_get_mbox_status(domain, mqe, status)) {
    372		efc_domain_free_resources(domain,
    373					  EFC_HW_DOMAIN_ALLOC_FAIL, mqe);
    374		return -EIO;
    375	}
    376
    377	efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ALLOC_OK,
    378				  EFC_HW_DOMAIN_ALLOC_OK, mqe);
    379	return 0;
    380}
    381
    382static void
    383efc_domain_alloc_read_sparm64(struct efc_domain *domain)
    384{
    385	struct efc *efc = domain->efc;
    386	u8 data[SLI4_BMBX_SIZE];
    387	int rc;
    388
    389	rc = sli_cmd_read_sparm64(efc->sli, data, &domain->dma, 0);
    390	if (rc) {
    391		efc_log_err(efc, "READ_SPARM64 format failure\n");
    392		efc_domain_free_resources(domain,
    393					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
    394		return;
    395	}
    396
    397	rc = efc->tt.issue_mbox_rqst(efc->base, data,
    398				     efc_domain_alloc_read_sparm64_cb, domain);
    399	if (rc) {
    400		efc_log_err(efc, "READ_SPARM64 command failure\n");
    401		efc_domain_free_resources(domain,
    402					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
    403	}
    404}
    405
    406static int
    407efc_domain_alloc_init_vfi_cb(struct efc *efc, int status, u8 *mqe,
    408			     void *arg)
    409{
    410	struct efc_domain *domain = arg;
    411
    412	if (efc_domain_get_mbox_status(domain, mqe, status)) {
    413		efc_domain_free_resources(domain,
    414					  EFC_HW_DOMAIN_ALLOC_FAIL, mqe);
    415		return -EIO;
    416	}
    417
    418	efc_domain_alloc_read_sparm64(domain);
    419	return 0;
    420}
    421
    422static void
    423efc_domain_alloc_init_vfi(struct efc_domain *domain)
    424{
    425	struct efc *efc = domain->efc;
    426	struct efc_nport *nport = domain->nport;
    427	u8 data[SLI4_BMBX_SIZE];
    428	int rc;
    429
    430	/*
    431	 * For FC, the HW alread registered an FCFI.
    432	 * Copy FCF information into the domain and jump to INIT_VFI.
    433	 */
    434	domain->fcf_indicator = efc->fcfi;
    435	rc = sli_cmd_init_vfi(efc->sli, data, domain->indicator,
    436			      domain->fcf_indicator, nport->indicator);
    437	if (rc) {
    438		efc_log_err(efc, "INIT_VFI format failure\n");
    439		efc_domain_free_resources(domain,
    440					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
    441		return;
    442	}
    443
    444	efc_log_err(efc, "%s issue mbox\n", __func__);
    445	rc = efc->tt.issue_mbox_rqst(efc->base, data,
    446				     efc_domain_alloc_init_vfi_cb, domain);
    447	if (rc) {
    448		efc_log_err(efc, "INIT_VFI command failure\n");
    449		efc_domain_free_resources(domain,
    450					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
    451	}
    452}
    453
    454int
    455efc_cmd_domain_alloc(struct efc *efc, struct efc_domain *domain, u32 fcf)
    456{
    457	u32 index;
    458
    459	if (!domain || !domain->nport) {
    460		efc_log_err(efc, "bad parameter(s) domain=%p nport=%p\n",
    461			    domain, domain ? domain->nport : NULL);
    462		return -EIO;
    463	}
    464
    465	/* allocate memory for the service parameters */
    466	domain->dma.size = EFC_SPARAM_DMA_SZ;
    467	domain->dma.virt = dma_alloc_coherent(&efc->pci->dev,
    468					      domain->dma.size,
    469					      &domain->dma.phys, GFP_KERNEL);
    470	if (!domain->dma.virt) {
    471		efc_log_err(efc, "Failed to allocate DMA memory\n");
    472		return -EIO;
    473	}
    474
    475	domain->fcf = fcf;
    476	domain->fcf_indicator = U32_MAX;
    477	domain->indicator = U32_MAX;
    478
    479	if (sli_resource_alloc(efc->sli, SLI4_RSRC_VFI, &domain->indicator,
    480			       &index)) {
    481		efc_log_err(efc, "VFI allocation failure\n");
    482
    483		dma_free_coherent(&efc->pci->dev,
    484				  domain->dma.size, domain->dma.virt,
    485				  domain->dma.phys);
    486		memset(&domain->dma, 0, sizeof(struct efc_dma));
    487
    488		return -EIO;
    489	}
    490
    491	efc_domain_alloc_init_vfi(domain);
    492	return 0;
    493}
    494
    495static int
    496efc_domain_attach_reg_vfi_cb(struct efc *efc, int status, u8 *mqe,
    497			     void *arg)
    498{
    499	struct efc_domain *domain = arg;
    500
    501	if (efc_domain_get_mbox_status(domain, mqe, status)) {
    502		efc_domain_free_resources(domain,
    503					  EFC_HW_DOMAIN_ATTACH_FAIL, mqe);
    504		return -EIO;
    505	}
    506
    507	efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ATTACH_OK,
    508				  EFC_HW_DOMAIN_ATTACH_OK, mqe);
    509	return 0;
    510}
    511
    512int
    513efc_cmd_domain_attach(struct efc *efc, struct efc_domain *domain, u32 fc_id)
    514{
    515	u8 buf[SLI4_BMBX_SIZE];
    516	int rc = 0;
    517
    518	if (!domain) {
    519		efc_log_err(efc, "bad param(s) domain=%p\n", domain);
    520		return -EIO;
    521	}
    522
    523	domain->nport->fc_id = fc_id;
    524
    525	rc = sli_cmd_reg_vfi(efc->sli, buf, SLI4_BMBX_SIZE, domain->indicator,
    526			     domain->fcf_indicator, domain->dma,
    527			     domain->nport->indicator, domain->nport->sli_wwpn,
    528			     domain->nport->fc_id);
    529	if (rc) {
    530		efc_log_err(efc, "REG_VFI format failure\n");
    531		goto cleanup;
    532	}
    533
    534	rc = efc->tt.issue_mbox_rqst(efc->base, buf,
    535				     efc_domain_attach_reg_vfi_cb, domain);
    536	if (rc) {
    537		efc_log_err(efc, "REG_VFI command failure\n");
    538		goto cleanup;
    539	}
    540
    541	return rc;
    542
    543cleanup:
    544	efc_domain_free_resources(domain, EFC_HW_DOMAIN_ATTACH_FAIL, buf);
    545
    546	return rc;
    547}
    548
    549static int
    550efc_domain_free_unreg_vfi_cb(struct efc *efc, int status, u8 *mqe, void *arg)
    551{
    552	struct efc_domain *domain = arg;
    553	int evt = EFC_HW_DOMAIN_FREE_OK;
    554	int rc;
    555
    556	rc = efc_domain_get_mbox_status(domain, mqe, status);
    557	if (rc) {
    558		evt = EFC_HW_DOMAIN_FREE_FAIL;
    559		rc = -EIO;
    560	}
    561
    562	efc_domain_free_resources(domain, evt, mqe);
    563	return rc;
    564}
    565
    566static void
    567efc_domain_free_unreg_vfi(struct efc_domain *domain)
    568{
    569	struct efc *efc = domain->efc;
    570	int rc;
    571	u8 data[SLI4_BMBX_SIZE];
    572
    573	rc = sli_cmd_unreg_vfi(efc->sli, data, domain->indicator,
    574			       SLI4_UNREG_TYPE_DOMAIN);
    575	if (rc) {
    576		efc_log_err(efc, "UNREG_VFI format failure\n");
    577		goto cleanup;
    578	}
    579
    580	rc = efc->tt.issue_mbox_rqst(efc->base, data,
    581				     efc_domain_free_unreg_vfi_cb, domain);
    582	if (rc) {
    583		efc_log_err(efc, "UNREG_VFI command failure\n");
    584		goto cleanup;
    585	}
    586
    587	return;
    588
    589cleanup:
    590	efc_domain_free_resources(domain, EFC_HW_DOMAIN_FREE_FAIL, data);
    591}
    592
    593int
    594efc_cmd_domain_free(struct efc *efc, struct efc_domain *domain)
    595{
    596	if (!domain) {
    597		efc_log_err(efc, "bad parameter(s) domain=%p\n", domain);
    598		return -EIO;
    599	}
    600
    601	efc_domain_free_unreg_vfi(domain);
    602	return 0;
    603}
    604
    605int
    606efc_cmd_node_alloc(struct efc *efc, struct efc_remote_node *rnode, u32 fc_addr,
    607		   struct efc_nport *nport)
    608{
    609	/* Check for invalid indicator */
    610	if (rnode->indicator != U32_MAX) {
    611		efc_log_err(efc,
    612			    "RPI allocation failure addr=%#x rpi=%#x\n",
    613			    fc_addr, rnode->indicator);
    614		return -EIO;
    615	}
    616
    617	/* NULL SLI port indicates an unallocated remote node */
    618	rnode->nport = NULL;
    619
    620	if (sli_resource_alloc(efc->sli, SLI4_RSRC_RPI,
    621			       &rnode->indicator, &rnode->index)) {
    622		efc_log_err(efc, "RPI allocation failure addr=%#x\n",
    623			    fc_addr);
    624		return -EIO;
    625	}
    626
    627	rnode->fc_id = fc_addr;
    628	rnode->nport = nport;
    629
    630	return 0;
    631}
    632
    633static int
    634efc_cmd_node_attach_cb(struct efc *efc, int status, u8 *mqe, void *arg)
    635{
    636	struct efc_remote_node *rnode = arg;
    637	struct sli4_mbox_command_header *hdr =
    638				(struct sli4_mbox_command_header *)mqe;
    639	int evt = 0;
    640
    641	if (status || le16_to_cpu(hdr->status)) {
    642		efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status,
    643			      le16_to_cpu(hdr->status));
    644		rnode->attached = false;
    645		evt = EFC_EVT_NODE_ATTACH_FAIL;
    646	} else {
    647		rnode->attached = true;
    648		evt = EFC_EVT_NODE_ATTACH_OK;
    649	}
    650
    651	efc_remote_node_cb(efc, evt, rnode);
    652
    653	return 0;
    654}
    655
    656int
    657efc_cmd_node_attach(struct efc *efc, struct efc_remote_node *rnode,
    658		    struct efc_dma *sparms)
    659{
    660	int rc = -EIO;
    661	u8 buf[SLI4_BMBX_SIZE];
    662
    663	if (!rnode || !sparms) {
    664		efc_log_err(efc, "bad parameter(s) rnode=%p sparms=%p\n",
    665			    rnode, sparms);
    666		return -EIO;
    667	}
    668
    669	/*
    670	 * If the attach count is non-zero, this RPI has already been reg'd.
    671	 * Otherwise, register the RPI
    672	 */
    673	if (rnode->index == U32_MAX) {
    674		efc_log_err(efc, "bad parameter rnode->index invalid\n");
    675		return -EIO;
    676	}
    677
    678	/* Update a remote node object with the remote port's service params */
    679	if (!sli_cmd_reg_rpi(efc->sli, buf, rnode->indicator,
    680			     rnode->nport->indicator, rnode->fc_id, sparms, 0, 0))
    681		rc = efc->tt.issue_mbox_rqst(efc->base, buf,
    682					     efc_cmd_node_attach_cb, rnode);
    683
    684	return rc;
    685}
    686
    687int
    688efc_node_free_resources(struct efc *efc, struct efc_remote_node *rnode)
    689{
    690	int rc = 0;
    691
    692	if (!rnode) {
    693		efc_log_err(efc, "bad parameter rnode=%p\n", rnode);
    694		return -EIO;
    695	}
    696
    697	if (rnode->nport) {
    698		if (rnode->attached) {
    699			efc_log_err(efc, "rnode is still attached\n");
    700			return -EIO;
    701		}
    702		if (rnode->indicator != U32_MAX) {
    703			if (sli_resource_free(efc->sli, SLI4_RSRC_RPI,
    704					      rnode->indicator)) {
    705				efc_log_err(efc,
    706					    "RPI free fail RPI %d addr=%#x\n",
    707					    rnode->indicator, rnode->fc_id);
    708				rc = -EIO;
    709			} else {
    710				rnode->indicator = U32_MAX;
    711				rnode->index = U32_MAX;
    712			}
    713		}
    714	}
    715
    716	return rc;
    717}
    718
    719static int
    720efc_cmd_node_free_cb(struct efc *efc, int status, u8 *mqe, void *arg)
    721{
    722	struct efc_remote_node *rnode = arg;
    723	struct sli4_mbox_command_header *hdr =
    724				(struct sli4_mbox_command_header *)mqe;
    725	int evt = EFC_EVT_NODE_FREE_FAIL;
    726	int rc = 0;
    727
    728	if (status || le16_to_cpu(hdr->status)) {
    729		efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status,
    730			      le16_to_cpu(hdr->status));
    731
    732		/*
    733		 * In certain cases, a non-zero MQE status is OK (all must be
    734		 * true):
    735		 *   - node is attached
    736		 *   - status is 0x1400
    737		 */
    738		if (!rnode->attached ||
    739		    (le16_to_cpu(hdr->status) != SLI4_MBX_STATUS_RPI_NOT_REG))
    740			rc = -EIO;
    741	}
    742
    743	if (!rc) {
    744		rnode->attached = false;
    745		evt = EFC_EVT_NODE_FREE_OK;
    746	}
    747
    748	efc_remote_node_cb(efc, evt, rnode);
    749
    750	return rc;
    751}
    752
    753int
    754efc_cmd_node_detach(struct efc *efc, struct efc_remote_node *rnode)
    755{
    756	u8 buf[SLI4_BMBX_SIZE];
    757	int rc = -EIO;
    758
    759	if (!rnode) {
    760		efc_log_err(efc, "bad parameter rnode=%p\n", rnode);
    761		return -EIO;
    762	}
    763
    764	if (rnode->nport) {
    765		if (!rnode->attached)
    766			return -EIO;
    767
    768		rc = -EIO;
    769
    770		if (!sli_cmd_unreg_rpi(efc->sli, buf, rnode->indicator,
    771				       SLI4_RSRC_RPI, U32_MAX))
    772			rc = efc->tt.issue_mbox_rqst(efc->base, buf,
    773					efc_cmd_node_free_cb, rnode);
    774
    775		if (rc != 0) {
    776			efc_log_err(efc, "UNREG_RPI failed\n");
    777			rc = -EIO;
    778		}
    779	}
    780
    781	return rc;
    782}