xref: /dpdk/drivers/common/sfc_efx/base/efx_evb.c (revision 672386c1e9e1f64f7aa3b1360ad22dc737ea8d72)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2018-2019 Solarflare Communications Inc.
5  */
6 
7 #include "efx.h"
8 #include "efx_impl.h"
9 
10 
11 #if EFSYS_OPT_EVB
12 
13 #if EFSYS_OPT_SIENA
14 static const efx_evb_ops_t	__efx_evb_dummy_ops = {
15 	NULL,		/* eeo_init */
16 	NULL,		/* eeo_fini */
17 	NULL,		/* eeo_vswitch_alloc */
18 	NULL,		/* eeo_vswitch_free */
19 	NULL,		/* eeo_vport_alloc */
20 	NULL,		/* eeo_vport_free */
21 	NULL,		/* eeo_vport_mac_addr_add */
22 	NULL,		/* eeo_vport_mac_addr_del */
23 	NULL,		/* eeo_vadaptor_alloc */
24 	NULL,		/* eeo_vadaptor_free */
25 	NULL,		/* eeo_vport_assign */
26 	NULL,		/* eeo_vport_reconfigure */
27 	NULL,		/* eeo_vport_stats */
28 };
29 #endif /* EFSYS_OPT_SIENA */
30 
31 #if EFX_OPTS_EF10()
32 static const efx_evb_ops_t	__efx_evb_ef10_ops = {
33 	ef10_evb_init,			/* eeo_init */
34 	ef10_evb_fini,			/* eeo_fini */
35 	ef10_evb_vswitch_alloc,		/* eeo_vswitch_alloc */
36 	ef10_evb_vswitch_free,		/* eeo_vswitch_free */
37 	ef10_evb_vport_alloc,		/* eeo_vport_alloc */
38 	ef10_evb_vport_free,		/* eeo_vport_free */
39 	ef10_evb_vport_mac_addr_add,	/* eeo_vport_mac_addr_add */
40 	ef10_evb_vport_mac_addr_del,	/* eeo_vport_mac_addr_del */
41 	ef10_evb_vadaptor_alloc,	/* eeo_vadaptor_alloc */
42 	ef10_evb_vadaptor_free,		/* eeo_vadaptor_free */
43 	ef10_evb_vport_assign,		/* eeo_vport_assign */
44 	ef10_evb_vport_reconfigure,	/* eeo_vport_reconfigure */
45 	ef10_evb_vport_stats,		/* eeo_vport_stats */
46 };
47 #endif /* EFX_OPTS_EF10() */
48 
49 #if EFSYS_OPT_RIVERHEAD
50 static const efx_evb_ops_t	__efx_evb_rhead_ops = {
51 	ef10_evb_init,			/* eeo_init */
52 	ef10_evb_fini,			/* eeo_fini */
53 	ef10_evb_vswitch_alloc,		/* eeo_vswitch_alloc */
54 	ef10_evb_vswitch_free,		/* eeo_vswitch_free */
55 	ef10_evb_vport_alloc,		/* eeo_vport_alloc */
56 	ef10_evb_vport_free,		/* eeo_vport_free */
57 	ef10_evb_vport_mac_addr_add,	/* eeo_vport_mac_addr_add */
58 	ef10_evb_vport_mac_addr_del,	/* eeo_vport_mac_addr_del */
59 	ef10_evb_vadaptor_alloc,	/* eeo_vadaptor_alloc */
60 	ef10_evb_vadaptor_free,		/* eeo_vadaptor_free */
61 	ef10_evb_vport_assign,		/* eeo_vport_assign */
62 	ef10_evb_vport_reconfigure,	/* eeo_vport_reconfigure */
63 	ef10_evb_vport_stats,		/* eeo_vport_stats */
64 };
65 #endif /* EFSYS_OPT_RIVERHEAD */
66 
67 	__checkReturn	efx_rc_t
efx_evb_init(__in efx_nic_t * enp)68 efx_evb_init(
69 	__in		efx_nic_t *enp)
70 {
71 	const efx_evb_ops_t *eeop;
72 	efx_rc_t rc;
73 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
74 
75 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
76 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
77 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EVB));
78 
79 	switch (enp->en_family) {
80 #if EFSYS_OPT_SIENA
81 	case EFX_FAMILY_SIENA:
82 		eeop = &__efx_evb_dummy_ops;
83 		break;
84 #endif /* EFSYS_OPT_SIENA */
85 
86 #if EFSYS_OPT_HUNTINGTON
87 	case EFX_FAMILY_HUNTINGTON:
88 		eeop = &__efx_evb_ef10_ops;
89 		break;
90 #endif /* EFSYS_OPT_HUNTINGTON */
91 
92 #if EFSYS_OPT_MEDFORD
93 	case EFX_FAMILY_MEDFORD:
94 		eeop = &__efx_evb_ef10_ops;
95 		break;
96 #endif /* EFSYS_OPT_MEDFORD */
97 
98 #if EFSYS_OPT_MEDFORD2
99 	case EFX_FAMILY_MEDFORD2:
100 		eeop = &__efx_evb_ef10_ops;
101 		break;
102 #endif /* EFSYS_OPT_MEDFORD2 */
103 
104 #if EFSYS_OPT_RIVERHEAD
105 	case EFX_FAMILY_RIVERHEAD:
106 		eeop = &__efx_evb_rhead_ops;
107 		break;
108 #endif /* EFSYS_OPT_RIVERHEAD */
109 
110 	default:
111 		EFSYS_ASSERT(0);
112 		rc = ENOTSUP;
113 		goto fail1;
114 	}
115 
116 	if (!encp->enc_datapath_cap_evb || !eeop->eeo_init) {
117 		rc = ENOTSUP;
118 		goto fail2;
119 	}
120 
121 	if ((rc = eeop->eeo_init(enp)) != 0)
122 		goto fail3;
123 
124 	enp->en_eeop = eeop;
125 	enp->en_mod_flags |= EFX_MOD_EVB;
126 	return (0);
127 
128 fail3:
129 	EFSYS_PROBE(fail3);
130 fail2:
131 	EFSYS_PROBE(fail2);
132 fail1:
133 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
134 
135 	return (rc);
136 }
137 
138 			void
efx_evb_fini(__in efx_nic_t * enp)139 efx_evb_fini(
140 	__in		efx_nic_t *enp)
141 {
142 	const efx_evb_ops_t *eeop = enp->en_eeop;
143 
144 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
145 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
146 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
147 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
148 
149 	if (eeop && eeop->eeo_fini)
150 		eeop->eeo_fini(enp);
151 
152 	enp->en_eeop = NULL;
153 	enp->en_mod_flags &= ~EFX_MOD_EVB;
154 }
155 
156 /*
157  * efx_is_zero_eth_addr returns TRUE if the passed MAC address has all bytes
158  * equal to zero. A vport is assigned a MAC address after creation and this
159  * function checks if that has happened. It is called in the clean-up function
160  * before calling eeo_vport_mac_addr_del to ensure that the vport actually had
161  * an allocated MAC address.
162  */
163 
164 __checkReturn				boolean_t
efx_is_zero_eth_addr(__in_bcount (EFX_MAC_ADDR_LEN)const uint8_t * addrp)165 efx_is_zero_eth_addr(
166 	__in_bcount(EFX_MAC_ADDR_LEN)	const uint8_t *addrp)
167 {
168 	return (!(addrp[0] | addrp[1] | addrp[2] |
169 		addrp[3] | addrp[4] | addrp[5]));
170 }
171 
172 static			void
efx_evb_free_vport(__in efx_nic_t * enp,__in efx_vswitch_id_t vswitch_id,__inout efx_vport_config_t * configp)173 efx_evb_free_vport(
174 	__in		efx_nic_t *enp,
175 	__in		efx_vswitch_id_t vswitch_id,
176 	__inout		efx_vport_config_t *configp)
177 {
178 	const efx_evb_ops_t *eeop = enp->en_eeop;
179 
180 	/* If any callback fails, continue clean-up with others functions */
181 	if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
182 		/* free vadaptor */
183 		if ((configp->evc_vport_id != EFX_VPORT_ID_INVALID) &&
184 		    (eeop->eeo_vadaptor_free(enp, vswitch_id,
185 		    configp->evc_vport_id) != 0)) {
186 			EFSYS_PROBE2(eeo_vadaptor_free,
187 			    uint16_t, configp->evc_function,
188 			    uint32_t, configp->evc_vport_id);
189 		}
190 	} else {
191 		if (configp->evc_vport_assigned == B_TRUE) {
192 			if (eeop->eeo_vport_assign(enp, vswitch_id,
193 			    EVB_PORT_ID_NULL,
194 			    configp->evc_function) != 0) {
195 				EFSYS_PROBE1(eeo_vport_assign,
196 				    uint16_t, configp->evc_function);
197 			}
198 			configp->evc_vport_assigned = B_FALSE;
199 		}
200 	}
201 
202 	/*
203 	 * Call eeo_vport_mac_addr_del after checking that this vport is
204 	 * actually allocated a MAC address in call to efx_evb_configure_vport
205 	 */
206 	if (!efx_is_zero_eth_addr(configp->evc_mac_addr)) {
207 		if (eeop->eeo_vport_mac_addr_del(enp, vswitch_id,
208 		    configp->evc_vport_id,
209 		    configp->evc_mac_addr) != 0) {
210 			EFSYS_PROBE1(eeo_vport_mac_addr_del,
211 			    uint16_t, configp->evc_function);
212 		}
213 		memset(configp->evc_mac_addr, 0x00, EFX_MAC_ADDR_LEN);
214 	}
215 
216 	if (configp->evc_vport_id != EFX_VPORT_ID_INVALID) {
217 		if (eeop->eeo_vport_free(enp, vswitch_id,
218 		    configp->evc_vport_id) != 0) {
219 			EFSYS_PROBE1(eeo_vport_free,
220 			    uint16_t, configp->evc_function);
221 		}
222 		configp->evc_vport_id = EFX_VPORT_ID_INVALID;
223 	}
224 }
225 
226 static					void
efx_evb_free_vports(__in efx_nic_t * enp,__in efx_vswitch_id_t vswitch_id,__in uint32_t num_vports,__inout_ecount (num_vports)efx_vport_config_t * vport_configp)227 efx_evb_free_vports(
228 	__in				efx_nic_t *enp,
229 	__in				efx_vswitch_id_t vswitch_id,
230 	__in				uint32_t num_vports,
231 	__inout_ecount(num_vports)	efx_vport_config_t *vport_configp)
232 {
233 	efx_vport_config_t *configp;
234 	uint32_t i;
235 
236 	if (vport_configp == NULL) {
237 		EFSYS_PROBE(null_vport_config);
238 		return;
239 	}
240 
241 	for (i = 0; i < num_vports; i++) {
242 		configp = vport_configp + i;
243 		efx_evb_free_vport(enp, vswitch_id, configp);
244 	}
245 }
246 
247 static	__checkReturn	efx_rc_t
efx_evb_configure_vport(__in efx_nic_t * enp,__in efx_vswitch_id_t vswitch_id,__in const efx_evb_ops_t * eeop,__inout efx_vport_config_t * configp)248 efx_evb_configure_vport(
249 	__in		efx_nic_t *enp,
250 	__in		efx_vswitch_id_t vswitch_id,
251 	__in		const efx_evb_ops_t *eeop,
252 	__inout		efx_vport_config_t *configp)
253 {
254 	efx_rc_t rc;
255 	efx_vport_id_t vport_id;
256 
257 	if ((rc = eeop->eeo_vport_alloc(enp, vswitch_id,
258 			EFX_VPORT_TYPE_NORMAL, configp->evc_vid,
259 			configp->evc_vlan_restrict, &vport_id)) != 0)
260 		goto fail1;
261 
262 	configp->evc_vport_id = vport_id;
263 
264 	if ((rc = eeop->eeo_vport_mac_addr_add(enp, vswitch_id,
265 			configp->evc_vport_id,
266 			configp->evc_mac_addr)) != 0)
267 		goto fail2;
268 
269 	if (EFX_VPORT_PCI_FUNCTION_IS_PF(configp)) {
270 		if ((rc = eeop->eeo_vadaptor_alloc(enp, vswitch_id,
271 				configp->evc_vport_id)) != 0)
272 			goto fail3;
273 	} else {
274 		if ((rc = eeop->eeo_vport_assign(enp, vswitch_id,
275 				configp->evc_vport_id,
276 				configp->evc_function)) != 0)
277 			goto fail4;
278 		configp->evc_vport_assigned = B_TRUE;
279 	}
280 
281 	return (0);
282 
283 fail4:
284 	EFSYS_PROBE(fail4);
285 fail3:
286 	EFSYS_PROBE(fail3);
287 fail2:
288 	EFSYS_PROBE(fail2);
289 fail1:
290 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
291 
292 	return (rc);
293 }
294 
295 	__checkReturn			efx_rc_t
efx_evb_vswitch_create(__in efx_nic_t * enp,__in uint32_t num_vports,__inout_ecount (num_vports)efx_vport_config_t * vport_configp,__deref_out efx_vswitch_t ** evpp)296 efx_evb_vswitch_create(
297 	__in				efx_nic_t *enp,
298 	__in				uint32_t num_vports,
299 	__inout_ecount(num_vports)	efx_vport_config_t *vport_configp,
300 	__deref_out			efx_vswitch_t **evpp)
301 {
302 	efx_vswitch_t *evp;
303 	efx_rc_t rc;
304 	efx_vswitch_id_t vswitch_id;
305 	efx_vport_config_t *configp;
306 	const efx_evb_ops_t *eeop = enp->en_eeop;
307 	uint32_t i;
308 
309 	/* vport_configp is a caller allocated array filled in with vports
310 	 * configuration. Index 0 carries the PF vport configuration and next
311 	 * num_vports - 1 indices carry VFs configuration.
312 	 */
313 	EFSYS_ASSERT((num_vports != 0) && (vport_configp != NULL) &&
314 		(evpp != NULL));
315 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
316 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
317 
318 	if ((eeop->eeo_vswitch_alloc == NULL) ||
319 	    (eeop->eeo_vport_alloc == NULL) ||
320 	    (eeop->eeo_vport_free == NULL) ||
321 	    (eeop->eeo_vport_mac_addr_add == NULL) ||
322 	    (eeop->eeo_vport_mac_addr_del == NULL) ||
323 	    (eeop->eeo_vadaptor_alloc == NULL) ||
324 	    (eeop->eeo_vadaptor_free == NULL) ||
325 	    (eeop->eeo_vport_assign == NULL) ||
326 	    (eeop->eeo_vswitch_free == NULL)) {
327 		rc = ENOTSUP;
328 		goto fail1;
329 	}
330 
331 	/* Allocate a vSwitch object */
332 	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_vswitch_t), evp);
333 
334 	if (evp == NULL) {
335 		rc = ENOMEM;
336 		goto fail2;
337 	}
338 
339 	if ((rc = eeop->eeo_vswitch_alloc(enp, &vswitch_id)) != 0)
340 		goto fail3;
341 
342 	evp->ev_enp = enp;
343 	evp->ev_num_vports = num_vports;
344 	evp->ev_evcp = vport_configp;
345 	evp->ev_vswitch_id = vswitch_id;
346 
347 	for (i = 0; i < num_vports; i++) {
348 		configp = vport_configp + i;
349 
350 		if ((rc = efx_evb_configure_vport(enp, vswitch_id, eeop,
351 				configp)) != 0)
352 			goto fail4;
353 	}
354 
355 	enp->en_vswitchp = evp;
356 	*evpp = evp;
357 	return (0);
358 
359 fail4:
360 	EFSYS_PROBE(fail4);
361 	efx_evb_free_vports(enp, vswitch_id, i + 1, vport_configp);
362 	/* Free the vSwitch */
363 	eeop->eeo_vswitch_free(enp, vswitch_id);
364 
365 fail3:
366 	EFSYS_PROBE(fail3);
367 	/* Free the vSwitch object */
368 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
369 
370 fail2:
371 	EFSYS_PROBE(fail2);
372 
373 fail1:
374 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
375 
376 	return (rc);
377 }
378 
379 	__checkReturn			efx_rc_t
efx_evb_vport_mac_set(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__in_bcount (EFX_MAC_ADDR_LEN)uint8_t * addrp)380 efx_evb_vport_mac_set(
381 	__in				efx_nic_t *enp,
382 	__in				efx_vswitch_t *evp,
383 	__in				efx_vport_id_t vport_id,
384 	__in_bcount(EFX_MAC_ADDR_LEN)	uint8_t *addrp)
385 {
386 	const efx_evb_ops_t *eeop = enp->en_eeop;
387 	efx_rc_t rc;
388 
389 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
390 
391 	if (eeop->eeo_vport_reconfigure == NULL) {
392 		rc = ENOTSUP;
393 		goto fail1;
394 	}
395 
396 	if (addrp == NULL) {
397 		rc = EINVAL;
398 		goto fail2;
399 	}
400 
401 	rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
402 		NULL, addrp, NULL);
403 	if (rc != 0)
404 		goto fail3;
405 
406 	return (0);
407 
408 fail3:
409 	EFSYS_PROBE(fail3);
410 fail2:
411 	EFSYS_PROBE(fail2);
412 fail1:
413 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
414 	return (rc);
415 }
416 
417 	__checkReturn	efx_rc_t
efx_evb_vport_vlan_set(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__in uint16_t vid)418 efx_evb_vport_vlan_set(
419 	__in		efx_nic_t *enp,
420 	__in		efx_vswitch_t *evp,
421 	__in		efx_vport_id_t vport_id,
422 	__in		uint16_t vid)
423 {
424 	const efx_evb_ops_t *eeop = enp->en_eeop;
425 	efx_rc_t rc;
426 
427 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
428 
429 	if (eeop->eeo_vport_reconfigure == NULL) {
430 		rc = ENOTSUP;
431 		goto fail1;
432 	}
433 
434 	rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
435 		&vid, NULL, NULL);
436 	if (rc != 0)
437 		goto fail2;
438 
439 	return (0);
440 
441 fail2:
442 	EFSYS_PROBE(fail2);
443 fail1:
444 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
445 	return (rc);
446 }
447 
448 	__checkReturn			efx_rc_t
efx_evb_vport_reset(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__in_bcount (EFX_MAC_ADDR_LEN)uint8_t * addrp,__in uint16_t vid,__out boolean_t * is_fn_resetp)449 efx_evb_vport_reset(
450 	__in				efx_nic_t *enp,
451 	__in				efx_vswitch_t *evp,
452 	__in				efx_vport_id_t vport_id,
453 	__in_bcount(EFX_MAC_ADDR_LEN)	uint8_t *addrp,
454 	__in				uint16_t vid,
455 	__out				boolean_t *is_fn_resetp)
456 {
457 	const efx_evb_ops_t *eeop = enp->en_eeop;
458 	efx_rc_t rc;
459 
460 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
461 
462 	if (eeop->eeo_vport_reconfigure == NULL) {
463 		rc = ENOTSUP;
464 		goto fail1;
465 	}
466 
467 	if (is_fn_resetp == NULL) {
468 		rc = EINVAL;
469 		goto fail2;
470 	}
471 
472 	rc = eeop->eeo_vport_reconfigure(enp, evp->ev_vswitch_id, vport_id,
473 		&vid, addrp, is_fn_resetp);
474 	if (rc != 0)
475 		goto fail3;
476 
477 	return (0);
478 
479 fail3:
480 	EFSYS_PROBE(fail3);
481 fail2:
482 	EFSYS_PROBE(fail2);
483 fail1:
484 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
485 	return (rc);
486 }
487 	__checkReturn	efx_rc_t
efx_evb_vswitch_destroy(__in efx_nic_t * enp,__in efx_vswitch_t * evp)488 efx_evb_vswitch_destroy(
489 	__in		efx_nic_t *enp,
490 	__in		efx_vswitch_t *evp)
491 {
492 	const efx_evb_ops_t *eeop = enp->en_eeop;
493 	efx_vswitch_id_t vswitch_id;
494 	efx_rc_t rc;
495 
496 	EFSYS_ASSERT(evp != NULL);
497 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
498 
499 	if ((eeop->eeo_vport_mac_addr_del == NULL) ||
500 	    (eeop->eeo_vadaptor_free == NULL) ||
501 	    (eeop->eeo_vport_assign == NULL) ||
502 	    (eeop->eeo_vport_free == NULL) ||
503 	    (eeop->eeo_vswitch_free == NULL)) {
504 		rc = ENOTSUP;
505 		goto fail1;
506 	}
507 
508 	vswitch_id  = evp->ev_vswitch_id;
509 	efx_evb_free_vports(enp, vswitch_id,
510 		evp->ev_num_vports, evp->ev_evcp);
511 
512 	/* Free the vSwitch object */
513 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_vswitch_t), evp);
514 	enp->en_vswitchp = NULL;
515 
516 	/* Free the vSwitch */
517 	if ((rc = eeop->eeo_vswitch_free(enp, vswitch_id)) != 0)
518 		goto fail2;
519 
520 	return (0);
521 
522 fail2:
523 	EFSYS_PROBE(fail2);
524 
525 fail1:
526 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
527 	return (rc);
528 }
529 
530 	__checkReturn	efx_rc_t
efx_evb_vport_stats(__in efx_nic_t * enp,__in efx_vswitch_t * evp,__in efx_vport_id_t vport_id,__out efsys_mem_t * stats_bufferp)531 efx_evb_vport_stats(
532 	__in		efx_nic_t *enp,
533 	__in		efx_vswitch_t *evp,
534 	__in		efx_vport_id_t vport_id,
535 	__out		efsys_mem_t *stats_bufferp)
536 {
537 	efx_rc_t rc;
538 	const efx_evb_ops_t *eeop = enp->en_eeop;
539 
540 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_EVB);
541 
542 	if (eeop->eeo_vport_stats == NULL) {
543 		rc = ENOTSUP;
544 		goto fail1;
545 	}
546 
547 	if (stats_bufferp == NULL) {
548 		rc = EINVAL;
549 		goto fail2;
550 	}
551 
552 	rc = eeop->eeo_vport_stats(enp, evp->ev_vswitch_id,
553 		vport_id, stats_bufferp);
554 	if (rc != 0)
555 		goto fail3;
556 
557 	return (0);
558 
559 fail3:
560 	EFSYS_PROBE(fail3);
561 fail2:
562 	EFSYS_PROBE(fail2);
563 fail1:
564 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
565 	return (rc);
566 }
567 
568 #endif
569