xref: /openbmc/linux/drivers/scsi/elx/libefc/efc_cmds.c (revision a3cbcadf)
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 
12 static void
13 efc_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 
33 static int
34 efc_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 
49 static int
50 efc_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 
64 static void
65 efc_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 
87 static void
88 efc_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 
104 static int
105 efc_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 
118 static void
119 efc_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 
147 static int
148 efc_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 
172 static void
173 efc_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_DMA);
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 
205 int
206 efc_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 
246 static int
247 efc_nport_attach_reg_vpi_cb(struct efc *efc, int status, u8 *mqe,
248 			    void *arg)
249 {
250 	struct efc_nport *nport = arg;
251 
252 	if (efc_nport_get_mbox_status(nport, mqe, status)) {
253 		efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, mqe);
254 		return -EIO;
255 	}
256 
257 	efc_nport_send_evt(nport, EFC_EVT_NPORT_ATTACH_OK, mqe);
258 	return 0;
259 }
260 
261 int
262 efc_cmd_nport_attach(struct efc *efc, struct efc_nport *nport, u32 fc_id)
263 {
264 	u8 buf[SLI4_BMBX_SIZE];
265 	int rc = 0;
266 
267 	if (!nport) {
268 		efc_log_err(efc, "bad param(s) nport=%p\n", nport);
269 		return -EIO;
270 	}
271 
272 	nport->fc_id = fc_id;
273 
274 	/* register previously-allocated VPI with the device */
275 	rc = sli_cmd_reg_vpi(efc->sli, buf, nport->fc_id,
276 			     nport->sli_wwpn, nport->indicator,
277 			    nport->domain->indicator, false);
278 	if (rc) {
279 		efc_log_err(efc, "REG_VPI format failure\n");
280 		efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf);
281 		return rc;
282 	}
283 
284 	rc = efc->tt.issue_mbox_rqst(efc->base, buf,
285 				     efc_nport_attach_reg_vpi_cb, nport);
286 	if (rc) {
287 		efc_log_err(efc, "REG_VPI command failure\n");
288 		efc_nport_free_resources(nport, EFC_EVT_NPORT_ATTACH_FAIL, buf);
289 	}
290 
291 	return rc;
292 }
293 
294 int
295 efc_cmd_nport_free(struct efc *efc, struct efc_nport *nport)
296 {
297 	if (!nport) {
298 		efc_log_err(efc, "bad parameter(s) nport=%p\n",	nport);
299 		return -EIO;
300 	}
301 
302 	/* Issue the UNREG_VPI command to free the assigned VPI context */
303 	if (nport->attached)
304 		efc_nport_free_unreg_vpi(nport);
305 	else
306 		nport->free_req_pending = true;
307 
308 	return 0;
309 }
310 
311 static int
312 efc_domain_get_mbox_status(struct efc_domain *domain, u8 *mqe, int status)
313 {
314 	struct efc *efc = domain->efc;
315 	struct sli4_mbox_command_header *hdr =
316 			(struct sli4_mbox_command_header *)mqe;
317 
318 	if (status || le16_to_cpu(hdr->status)) {
319 		efc_log_debug(efc, "bad status vfi=%#x st=%x hdr=%x\n",
320 			      domain->indicator, status,
321 			      le16_to_cpu(hdr->status));
322 		return -EIO;
323 	}
324 
325 	return 0;
326 }
327 
328 static void
329 efc_domain_free_resources(struct efc_domain *domain, int evt, void *data)
330 {
331 	struct efc *efc = domain->efc;
332 
333 	/* Free the service parameters buffer */
334 	if (domain->dma.virt) {
335 		dma_free_coherent(&efc->pci->dev,
336 				  domain->dma.size, domain->dma.virt,
337 				  domain->dma.phys);
338 		memset(&domain->dma, 0, sizeof(struct efc_dma));
339 	}
340 
341 	/* Free the SLI resources */
342 	sli_resource_free(efc->sli, SLI4_RSRC_VFI, domain->indicator);
343 
344 	efc_domain_cb(efc, evt, domain);
345 }
346 
347 static void
348 efc_domain_send_nport_evt(struct efc_domain *domain,
349 			  int port_evt, int domain_evt, void *data)
350 {
351 	struct efc *efc = domain->efc;
352 
353 	/* Send alloc/attach ok to the physical nport */
354 	efc_nport_send_evt(domain->nport, port_evt, NULL);
355 
356 	/* Now inform the registered callbacks */
357 	efc_domain_cb(efc, domain_evt, domain);
358 }
359 
360 static int
361 efc_domain_alloc_read_sparm64_cb(struct efc *efc, int status, u8 *mqe,
362 				 void *arg)
363 {
364 	struct efc_domain *domain = arg;
365 
366 	if (efc_domain_get_mbox_status(domain, mqe, status)) {
367 		efc_domain_free_resources(domain,
368 					  EFC_HW_DOMAIN_ALLOC_FAIL, mqe);
369 		return -EIO;
370 	}
371 
372 	efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ALLOC_OK,
373 				  EFC_HW_DOMAIN_ALLOC_OK, mqe);
374 	return 0;
375 }
376 
377 static void
378 efc_domain_alloc_read_sparm64(struct efc_domain *domain)
379 {
380 	struct efc *efc = domain->efc;
381 	u8 data[SLI4_BMBX_SIZE];
382 	int rc;
383 
384 	rc = sli_cmd_read_sparm64(efc->sli, data, &domain->dma, 0);
385 	if (rc) {
386 		efc_log_err(efc, "READ_SPARM64 format failure\n");
387 		efc_domain_free_resources(domain,
388 					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
389 		return;
390 	}
391 
392 	rc = efc->tt.issue_mbox_rqst(efc->base, data,
393 				     efc_domain_alloc_read_sparm64_cb, domain);
394 	if (rc) {
395 		efc_log_err(efc, "READ_SPARM64 command failure\n");
396 		efc_domain_free_resources(domain,
397 					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
398 	}
399 }
400 
401 static int
402 efc_domain_alloc_init_vfi_cb(struct efc *efc, int status, u8 *mqe,
403 			     void *arg)
404 {
405 	struct efc_domain *domain = arg;
406 
407 	if (efc_domain_get_mbox_status(domain, mqe, status)) {
408 		efc_domain_free_resources(domain,
409 					  EFC_HW_DOMAIN_ALLOC_FAIL, mqe);
410 		return -EIO;
411 	}
412 
413 	efc_domain_alloc_read_sparm64(domain);
414 	return 0;
415 }
416 
417 static void
418 efc_domain_alloc_init_vfi(struct efc_domain *domain)
419 {
420 	struct efc *efc = domain->efc;
421 	struct efc_nport *nport = domain->nport;
422 	u8 data[SLI4_BMBX_SIZE];
423 	int rc;
424 
425 	/*
426 	 * For FC, the HW alread registered an FCFI.
427 	 * Copy FCF information into the domain and jump to INIT_VFI.
428 	 */
429 	domain->fcf_indicator = efc->fcfi;
430 	rc = sli_cmd_init_vfi(efc->sli, data, domain->indicator,
431 			      domain->fcf_indicator, nport->indicator);
432 	if (rc) {
433 		efc_log_err(efc, "INIT_VFI format failure\n");
434 		efc_domain_free_resources(domain,
435 					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
436 		return;
437 	}
438 
439 	efc_log_err(efc, "%s issue mbox\n", __func__);
440 	rc = efc->tt.issue_mbox_rqst(efc->base, data,
441 				     efc_domain_alloc_init_vfi_cb, domain);
442 	if (rc) {
443 		efc_log_err(efc, "INIT_VFI command failure\n");
444 		efc_domain_free_resources(domain,
445 					  EFC_HW_DOMAIN_ALLOC_FAIL, data);
446 	}
447 }
448 
449 int
450 efc_cmd_domain_alloc(struct efc *efc, struct efc_domain *domain, u32 fcf)
451 {
452 	u32 index;
453 
454 	if (!domain || !domain->nport) {
455 		efc_log_err(efc, "bad parameter(s) domain=%p nport=%p\n",
456 			    domain, domain ? domain->nport : NULL);
457 		return -EIO;
458 	}
459 
460 	/* allocate memory for the service parameters */
461 	domain->dma.size = EFC_SPARAM_DMA_SZ;
462 	domain->dma.virt = dma_alloc_coherent(&efc->pci->dev,
463 					      domain->dma.size,
464 					      &domain->dma.phys, GFP_DMA);
465 	if (!domain->dma.virt) {
466 		efc_log_err(efc, "Failed to allocate DMA memory\n");
467 		return -EIO;
468 	}
469 
470 	domain->fcf = fcf;
471 	domain->fcf_indicator = U32_MAX;
472 	domain->indicator = U32_MAX;
473 
474 	if (sli_resource_alloc(efc->sli, SLI4_RSRC_VFI, &domain->indicator,
475 			       &index)) {
476 		efc_log_err(efc, "VFI allocation failure\n");
477 
478 		dma_free_coherent(&efc->pci->dev,
479 				  domain->dma.size, domain->dma.virt,
480 				  domain->dma.phys);
481 		memset(&domain->dma, 0, sizeof(struct efc_dma));
482 
483 		return -EIO;
484 	}
485 
486 	efc_domain_alloc_init_vfi(domain);
487 	return 0;
488 }
489 
490 static int
491 efc_domain_attach_reg_vfi_cb(struct efc *efc, int status, u8 *mqe,
492 			     void *arg)
493 {
494 	struct efc_domain *domain = arg;
495 
496 	if (efc_domain_get_mbox_status(domain, mqe, status)) {
497 		efc_domain_free_resources(domain,
498 					  EFC_HW_DOMAIN_ATTACH_FAIL, mqe);
499 		return -EIO;
500 	}
501 
502 	efc_domain_send_nport_evt(domain, EFC_EVT_NPORT_ATTACH_OK,
503 				  EFC_HW_DOMAIN_ATTACH_OK, mqe);
504 	return 0;
505 }
506 
507 int
508 efc_cmd_domain_attach(struct efc *efc, struct efc_domain *domain, u32 fc_id)
509 {
510 	u8 buf[SLI4_BMBX_SIZE];
511 	int rc = 0;
512 
513 	if (!domain) {
514 		efc_log_err(efc, "bad param(s) domain=%p\n", domain);
515 		return -EIO;
516 	}
517 
518 	domain->nport->fc_id = fc_id;
519 
520 	rc = sli_cmd_reg_vfi(efc->sli, buf, SLI4_BMBX_SIZE, domain->indicator,
521 			     domain->fcf_indicator, domain->dma,
522 			     domain->nport->indicator, domain->nport->sli_wwpn,
523 			     domain->nport->fc_id);
524 	if (rc) {
525 		efc_log_err(efc, "REG_VFI format failure\n");
526 		goto cleanup;
527 	}
528 
529 	rc = efc->tt.issue_mbox_rqst(efc->base, buf,
530 				     efc_domain_attach_reg_vfi_cb, domain);
531 	if (rc) {
532 		efc_log_err(efc, "REG_VFI command failure\n");
533 		goto cleanup;
534 	}
535 
536 	return rc;
537 
538 cleanup:
539 	efc_domain_free_resources(domain, EFC_HW_DOMAIN_ATTACH_FAIL, buf);
540 
541 	return rc;
542 }
543 
544 static int
545 efc_domain_free_unreg_vfi_cb(struct efc *efc, int status, u8 *mqe, void *arg)
546 {
547 	struct efc_domain *domain = arg;
548 	int evt = EFC_HW_DOMAIN_FREE_OK;
549 	int rc;
550 
551 	rc = efc_domain_get_mbox_status(domain, mqe, status);
552 	if (rc) {
553 		evt = EFC_HW_DOMAIN_FREE_FAIL;
554 		rc = -EIO;
555 	}
556 
557 	efc_domain_free_resources(domain, evt, mqe);
558 	return rc;
559 }
560 
561 static void
562 efc_domain_free_unreg_vfi(struct efc_domain *domain)
563 {
564 	struct efc *efc = domain->efc;
565 	int rc;
566 	u8 data[SLI4_BMBX_SIZE];
567 
568 	rc = sli_cmd_unreg_vfi(efc->sli, data, domain->indicator,
569 			       SLI4_UNREG_TYPE_DOMAIN);
570 	if (rc) {
571 		efc_log_err(efc, "UNREG_VFI format failure\n");
572 		goto cleanup;
573 	}
574 
575 	rc = efc->tt.issue_mbox_rqst(efc->base, data,
576 				     efc_domain_free_unreg_vfi_cb, domain);
577 	if (rc) {
578 		efc_log_err(efc, "UNREG_VFI command failure\n");
579 		goto cleanup;
580 	}
581 
582 	return;
583 
584 cleanup:
585 	efc_domain_free_resources(domain, EFC_HW_DOMAIN_FREE_FAIL, data);
586 }
587 
588 int
589 efc_cmd_domain_free(struct efc *efc, struct efc_domain *domain)
590 {
591 	if (!domain) {
592 		efc_log_err(efc, "bad parameter(s) domain=%p\n", domain);
593 		return -EIO;
594 	}
595 
596 	efc_domain_free_unreg_vfi(domain);
597 	return 0;
598 }
599 
600 int
601 efc_cmd_node_alloc(struct efc *efc, struct efc_remote_node *rnode, u32 fc_addr,
602 		   struct efc_nport *nport)
603 {
604 	/* Check for invalid indicator */
605 	if (rnode->indicator != U32_MAX) {
606 		efc_log_err(efc,
607 			    "RPI allocation failure addr=%#x rpi=%#x\n",
608 			    fc_addr, rnode->indicator);
609 		return -EIO;
610 	}
611 
612 	/* NULL SLI port indicates an unallocated remote node */
613 	rnode->nport = NULL;
614 
615 	if (sli_resource_alloc(efc->sli, SLI4_RSRC_RPI,
616 			       &rnode->indicator, &rnode->index)) {
617 		efc_log_err(efc, "RPI allocation failure addr=%#x\n",
618 			    fc_addr);
619 		return -EIO;
620 	}
621 
622 	rnode->fc_id = fc_addr;
623 	rnode->nport = nport;
624 
625 	return 0;
626 }
627 
628 static int
629 efc_cmd_node_attach_cb(struct efc *efc, int status, u8 *mqe, void *arg)
630 {
631 	struct efc_remote_node *rnode = arg;
632 	struct sli4_mbox_command_header *hdr =
633 				(struct sli4_mbox_command_header *)mqe;
634 	int evt = 0;
635 
636 	if (status || le16_to_cpu(hdr->status)) {
637 		efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status,
638 			      le16_to_cpu(hdr->status));
639 		rnode->attached = false;
640 		evt = EFC_EVT_NODE_ATTACH_FAIL;
641 	} else {
642 		rnode->attached = true;
643 		evt = EFC_EVT_NODE_ATTACH_OK;
644 	}
645 
646 	efc_remote_node_cb(efc, evt, rnode);
647 
648 	return 0;
649 }
650 
651 int
652 efc_cmd_node_attach(struct efc *efc, struct efc_remote_node *rnode,
653 		    struct efc_dma *sparms)
654 {
655 	int rc = -EIO;
656 	u8 buf[SLI4_BMBX_SIZE];
657 
658 	if (!rnode || !sparms) {
659 		efc_log_err(efc, "bad parameter(s) rnode=%p sparms=%p\n",
660 			    rnode, sparms);
661 		return -EIO;
662 	}
663 
664 	/*
665 	 * If the attach count is non-zero, this RPI has already been reg'd.
666 	 * Otherwise, register the RPI
667 	 */
668 	if (rnode->index == U32_MAX) {
669 		efc_log_err(efc, "bad parameter rnode->index invalid\n");
670 		return -EIO;
671 	}
672 
673 	/* Update a remote node object with the remote port's service params */
674 	if (!sli_cmd_reg_rpi(efc->sli, buf, rnode->indicator,
675 			     rnode->nport->indicator, rnode->fc_id, sparms, 0, 0))
676 		rc = efc->tt.issue_mbox_rqst(efc->base, buf,
677 					     efc_cmd_node_attach_cb, rnode);
678 
679 	return rc;
680 }
681 
682 int
683 efc_node_free_resources(struct efc *efc, struct efc_remote_node *rnode)
684 {
685 	int rc = 0;
686 
687 	if (!rnode) {
688 		efc_log_err(efc, "bad parameter rnode=%p\n", rnode);
689 		return -EIO;
690 	}
691 
692 	if (rnode->nport) {
693 		if (rnode->attached) {
694 			efc_log_err(efc, "rnode is still attached\n");
695 			return -EIO;
696 		}
697 		if (rnode->indicator != U32_MAX) {
698 			if (sli_resource_free(efc->sli, SLI4_RSRC_RPI,
699 					      rnode->indicator)) {
700 				efc_log_err(efc,
701 					    "RPI free fail RPI %d addr=%#x\n",
702 					    rnode->indicator, rnode->fc_id);
703 				rc = -EIO;
704 			} else {
705 				rnode->indicator = U32_MAX;
706 				rnode->index = U32_MAX;
707 			}
708 		}
709 	}
710 
711 	return rc;
712 }
713 
714 static int
715 efc_cmd_node_free_cb(struct efc *efc, int status, u8 *mqe, void *arg)
716 {
717 	struct efc_remote_node *rnode = arg;
718 	struct sli4_mbox_command_header *hdr =
719 				(struct sli4_mbox_command_header *)mqe;
720 	int evt = EFC_EVT_NODE_FREE_FAIL;
721 	int rc = 0;
722 
723 	if (status || le16_to_cpu(hdr->status)) {
724 		efc_log_debug(efc, "bad status cqe=%#x mqe=%#x\n", status,
725 			      le16_to_cpu(hdr->status));
726 
727 		/*
728 		 * In certain cases, a non-zero MQE status is OK (all must be
729 		 * true):
730 		 *   - node is attached
731 		 *   - status is 0x1400
732 		 */
733 		if (!rnode->attached ||
734 		    (le16_to_cpu(hdr->status) != SLI4_MBX_STATUS_RPI_NOT_REG))
735 			rc = -EIO;
736 	}
737 
738 	if (!rc) {
739 		rnode->attached = false;
740 		evt = EFC_EVT_NODE_FREE_OK;
741 	}
742 
743 	efc_remote_node_cb(efc, evt, rnode);
744 
745 	return rc;
746 }
747 
748 int
749 efc_cmd_node_detach(struct efc *efc, struct efc_remote_node *rnode)
750 {
751 	u8 buf[SLI4_BMBX_SIZE];
752 	int rc = -EIO;
753 
754 	if (!rnode) {
755 		efc_log_err(efc, "bad parameter rnode=%p\n", rnode);
756 		return -EIO;
757 	}
758 
759 	if (rnode->nport) {
760 		if (!rnode->attached)
761 			return -EIO;
762 
763 		rc = -EIO;
764 
765 		if (!sli_cmd_unreg_rpi(efc->sli, buf, rnode->indicator,
766 				       SLI4_RSRC_RPI, U32_MAX))
767 			rc = efc->tt.issue_mbox_rqst(efc->base, buf,
768 					efc_cmd_node_free_cb, rnode);
769 
770 		if (rc != 0) {
771 			efc_log_err(efc, "UNREG_RPI failed\n");
772 			rc = -EIO;
773 		}
774 	}
775 
776 	return rc;
777 }
778