xref: /freebsd/sys/dev/sfxge/common/efx_nvram.c (revision 5abce2b9194ac1afcc3e7eb0671a6c209e75cfab)
1e948693eSPhilip Paeps /*-
23c838a9fSAndrew Rybchenko  * Copyright (c) 2009-2015 Solarflare Communications Inc.
33c838a9fSAndrew Rybchenko  * All rights reserved.
4e948693eSPhilip Paeps  *
5e948693eSPhilip Paeps  * Redistribution and use in source and binary forms, with or without
63c838a9fSAndrew Rybchenko  * modification, are permitted provided that the following conditions are met:
7e948693eSPhilip Paeps  *
83c838a9fSAndrew Rybchenko  * 1. Redistributions of source code must retain the above copyright notice,
93c838a9fSAndrew Rybchenko  *    this list of conditions and the following disclaimer.
103c838a9fSAndrew Rybchenko  * 2. Redistributions in binary form must reproduce the above copyright notice,
113c838a9fSAndrew Rybchenko  *    this list of conditions and the following disclaimer in the documentation
123c838a9fSAndrew Rybchenko  *    and/or other materials provided with the distribution.
133c838a9fSAndrew Rybchenko  *
143c838a9fSAndrew Rybchenko  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
153c838a9fSAndrew Rybchenko  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
163c838a9fSAndrew Rybchenko  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
173c838a9fSAndrew Rybchenko  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
183c838a9fSAndrew Rybchenko  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
193c838a9fSAndrew Rybchenko  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
203c838a9fSAndrew Rybchenko  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
213c838a9fSAndrew Rybchenko  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
223c838a9fSAndrew Rybchenko  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
233c838a9fSAndrew Rybchenko  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
243c838a9fSAndrew Rybchenko  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
253c838a9fSAndrew Rybchenko  *
263c838a9fSAndrew Rybchenko  * The views and conclusions contained in the software and documentation are
273c838a9fSAndrew Rybchenko  * those of the authors and should not be interpreted as representing official
283c838a9fSAndrew Rybchenko  * policies, either expressed or implied, of the FreeBSD Project.
29e948693eSPhilip Paeps  */
30e948693eSPhilip Paeps 
315dee87d7SPhilip Paeps #include <sys/cdefs.h>
325dee87d7SPhilip Paeps __FBSDID("$FreeBSD$");
335dee87d7SPhilip Paeps 
34e948693eSPhilip Paeps #include "efx.h"
35e948693eSPhilip Paeps #include "efx_impl.h"
36e948693eSPhilip Paeps 
37e948693eSPhilip Paeps #if EFSYS_OPT_NVRAM
38e948693eSPhilip Paeps 
39e948693eSPhilip Paeps #if EFSYS_OPT_FALCON
40e948693eSPhilip Paeps 
413c838a9fSAndrew Rybchenko static efx_nvram_ops_t	__efx_nvram_falcon_ops = {
42e948693eSPhilip Paeps #if EFSYS_OPT_DIAG
43e948693eSPhilip Paeps 	falcon_nvram_test,		/* envo_test */
44e948693eSPhilip Paeps #endif	/* EFSYS_OPT_DIAG */
45bce88e31SAndrew Rybchenko 	falcon_nvram_type_to_partn,	/* envo_type_to_partn */
4656bd83b0SAndrew Rybchenko 	falcon_nvram_partn_size,	/* envo_partn_size */
475d846e87SAndrew Rybchenko 	falcon_nvram_partn_rw_start,	/* envo_partn_rw_start */
480afdf29cSAndrew Rybchenko 	falcon_nvram_partn_read,	/* envo_partn_read */
49b60ff840SAndrew Rybchenko 	falcon_nvram_partn_erase,	/* envo_partn_erase */
50134c4c4aSAndrew Rybchenko 	falcon_nvram_partn_write,	/* envo_partn_write */
51eb9703daSAndrew Rybchenko 	falcon_nvram_partn_rw_finish,	/* envo_partn_rw_finish */
5292187119SAndrew Rybchenko 	falcon_nvram_partn_get_version,	/* envo_partn_get_version */
536d0b856cSAndrew Rybchenko 	falcon_nvram_partn_set_version,	/* envo_partn_set_version */
54*5abce2b9SAndrew Rybchenko 	NULL,				/* envo_partn_validate */
55e948693eSPhilip Paeps };
56e948693eSPhilip Paeps 
57e948693eSPhilip Paeps #endif	/* EFSYS_OPT_FALCON */
58e948693eSPhilip Paeps 
59e948693eSPhilip Paeps #if EFSYS_OPT_SIENA
60e948693eSPhilip Paeps 
613c838a9fSAndrew Rybchenko static efx_nvram_ops_t	__efx_nvram_siena_ops = {
62e948693eSPhilip Paeps #if EFSYS_OPT_DIAG
63e948693eSPhilip Paeps 	siena_nvram_test,		/* envo_test */
64e948693eSPhilip Paeps #endif	/* EFSYS_OPT_DIAG */
65bce88e31SAndrew Rybchenko 	siena_nvram_type_to_partn,	/* envo_type_to_partn */
6656bd83b0SAndrew Rybchenko 	siena_nvram_partn_size,		/* envo_partn_size */
675d846e87SAndrew Rybchenko 	siena_nvram_partn_rw_start,	/* envo_partn_rw_start */
680afdf29cSAndrew Rybchenko 	siena_nvram_partn_read,		/* envo_partn_read */
69b60ff840SAndrew Rybchenko 	siena_nvram_partn_erase,	/* envo_partn_erase */
70134c4c4aSAndrew Rybchenko 	siena_nvram_partn_write,	/* envo_partn_write */
71eb9703daSAndrew Rybchenko 	siena_nvram_partn_rw_finish,	/* envo_partn_rw_finish */
7292187119SAndrew Rybchenko 	siena_nvram_partn_get_version,	/* envo_partn_get_version */
736d0b856cSAndrew Rybchenko 	siena_nvram_partn_set_version,	/* envo_partn_set_version */
74*5abce2b9SAndrew Rybchenko 	NULL,				/* envo_partn_validate */
75e948693eSPhilip Paeps };
76e948693eSPhilip Paeps 
77e948693eSPhilip Paeps #endif	/* EFSYS_OPT_SIENA */
78e948693eSPhilip Paeps 
79de9775adSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
803c838a9fSAndrew Rybchenko 
81de9775adSAndrew Rybchenko static efx_nvram_ops_t	__efx_nvram_ef10_ops = {
823c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG
83de9775adSAndrew Rybchenko 	ef10_nvram_test,		/* envo_test */
843c838a9fSAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
85bce88e31SAndrew Rybchenko 	ef10_nvram_type_to_partn,	/* envo_type_to_partn */
8656bd83b0SAndrew Rybchenko 	ef10_nvram_partn_size,		/* envo_partn_size */
875d846e87SAndrew Rybchenko 	ef10_nvram_partn_rw_start,	/* envo_partn_rw_start */
880afdf29cSAndrew Rybchenko 	ef10_nvram_partn_read,		/* envo_partn_read */
89b60ff840SAndrew Rybchenko 	ef10_nvram_partn_erase,		/* envo_partn_erase */
90134c4c4aSAndrew Rybchenko 	ef10_nvram_partn_write,		/* envo_partn_write */
91eb9703daSAndrew Rybchenko 	ef10_nvram_partn_rw_finish,	/* envo_partn_rw_finish */
9292187119SAndrew Rybchenko 	ef10_nvram_partn_get_version,	/* envo_partn_get_version */
936d0b856cSAndrew Rybchenko 	ef10_nvram_partn_set_version,	/* envo_partn_set_version */
94*5abce2b9SAndrew Rybchenko 	ef10_nvram_buffer_validate,	/* envo_buffer_validate */
953c838a9fSAndrew Rybchenko };
963c838a9fSAndrew Rybchenko 
97de9775adSAndrew Rybchenko #endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
983c838a9fSAndrew Rybchenko 
99460cb568SAndrew Rybchenko 	__checkReturn	efx_rc_t
100e948693eSPhilip Paeps efx_nvram_init(
101e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
102e948693eSPhilip Paeps {
103e948693eSPhilip Paeps 	efx_nvram_ops_t *envop;
104460cb568SAndrew Rybchenko 	efx_rc_t rc;
105e948693eSPhilip Paeps 
106e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
107e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
108e948693eSPhilip Paeps 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
109e948693eSPhilip Paeps 
110e948693eSPhilip Paeps 	switch (enp->en_family) {
111e948693eSPhilip Paeps #if EFSYS_OPT_FALCON
112e948693eSPhilip Paeps 	case EFX_FAMILY_FALCON:
113e948693eSPhilip Paeps 		envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
114e948693eSPhilip Paeps 		break;
115e948693eSPhilip Paeps #endif	/* EFSYS_OPT_FALCON */
116e948693eSPhilip Paeps 
117e948693eSPhilip Paeps #if EFSYS_OPT_SIENA
118e948693eSPhilip Paeps 	case EFX_FAMILY_SIENA:
119e948693eSPhilip Paeps 		envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
120e948693eSPhilip Paeps 		break;
121e948693eSPhilip Paeps #endif	/* EFSYS_OPT_SIENA */
122e948693eSPhilip Paeps 
1233c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
1243c838a9fSAndrew Rybchenko 	case EFX_FAMILY_HUNTINGTON:
125de9775adSAndrew Rybchenko 		envop = (efx_nvram_ops_t *)&__efx_nvram_ef10_ops;
1263c838a9fSAndrew Rybchenko 		break;
1273c838a9fSAndrew Rybchenko #endif	/* EFSYS_OPT_HUNTINGTON */
1283c838a9fSAndrew Rybchenko 
129de9775adSAndrew Rybchenko #if EFSYS_OPT_MEDFORD
130de9775adSAndrew Rybchenko 	case EFX_FAMILY_MEDFORD:
131de9775adSAndrew Rybchenko 		envop = (efx_nvram_ops_t *)&__efx_nvram_ef10_ops;
132de9775adSAndrew Rybchenko 		break;
133de9775adSAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD */
134de9775adSAndrew Rybchenko 
135e948693eSPhilip Paeps 	default:
136e948693eSPhilip Paeps 		EFSYS_ASSERT(0);
137e948693eSPhilip Paeps 		rc = ENOTSUP;
138e948693eSPhilip Paeps 		goto fail1;
139e948693eSPhilip Paeps 	}
140e948693eSPhilip Paeps 
141e948693eSPhilip Paeps 	enp->en_envop = envop;
142e948693eSPhilip Paeps 	enp->en_mod_flags |= EFX_MOD_NVRAM;
143e948693eSPhilip Paeps 
144e948693eSPhilip Paeps 	return (0);
145e948693eSPhilip Paeps 
146e948693eSPhilip Paeps fail1:
147460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
148e948693eSPhilip Paeps 
149e948693eSPhilip Paeps 	return (rc);
150e948693eSPhilip Paeps }
151e948693eSPhilip Paeps 
152e948693eSPhilip Paeps #if EFSYS_OPT_DIAG
153e948693eSPhilip Paeps 
154460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
155e948693eSPhilip Paeps efx_nvram_test(
156e948693eSPhilip Paeps 	__in			efx_nic_t *enp)
157e948693eSPhilip Paeps {
158e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
159460cb568SAndrew Rybchenko 	efx_rc_t rc;
160e948693eSPhilip Paeps 
161e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
162e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
163e948693eSPhilip Paeps 
164e948693eSPhilip Paeps 	if ((rc = envop->envo_test(enp)) != 0)
165e948693eSPhilip Paeps 		goto fail1;
166e948693eSPhilip Paeps 
167e948693eSPhilip Paeps 	return (0);
168e948693eSPhilip Paeps 
169e948693eSPhilip Paeps fail1:
170460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
171e948693eSPhilip Paeps 
172e948693eSPhilip Paeps 	return (rc);
173e948693eSPhilip Paeps }
174e948693eSPhilip Paeps 
175e948693eSPhilip Paeps #endif	/* EFSYS_OPT_DIAG */
176e948693eSPhilip Paeps 
177460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
178e948693eSPhilip Paeps efx_nvram_size(
179e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
180e948693eSPhilip Paeps 	__in			efx_nvram_type_t type,
181e948693eSPhilip Paeps 	__out			size_t *sizep)
182e948693eSPhilip Paeps {
183e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
18456bd83b0SAndrew Rybchenko 	uint32_t partn;
185460cb568SAndrew Rybchenko 	efx_rc_t rc;
186e948693eSPhilip Paeps 
187e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
188e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
189e948693eSPhilip Paeps 
190e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
191e948693eSPhilip Paeps 
19256bd83b0SAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
193e948693eSPhilip Paeps 		goto fail1;
194e948693eSPhilip Paeps 
19556bd83b0SAndrew Rybchenko 	if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
19656bd83b0SAndrew Rybchenko 		goto fail2;
19756bd83b0SAndrew Rybchenko 
198e948693eSPhilip Paeps 	return (0);
199e948693eSPhilip Paeps 
20056bd83b0SAndrew Rybchenko fail2:
20156bd83b0SAndrew Rybchenko 	EFSYS_PROBE(fail2);
202e948693eSPhilip Paeps fail1:
203460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
20456bd83b0SAndrew Rybchenko 	*sizep = 0;
205e948693eSPhilip Paeps 
206e948693eSPhilip Paeps 	return (rc);
207e948693eSPhilip Paeps }
208e948693eSPhilip Paeps 
209460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
210e948693eSPhilip Paeps efx_nvram_get_version(
211e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
212e948693eSPhilip Paeps 	__in			efx_nvram_type_t type,
213e948693eSPhilip Paeps 	__out			uint32_t *subtypep,
214e948693eSPhilip Paeps 	__out_ecount(4)		uint16_t version[4])
215e948693eSPhilip Paeps {
216e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
21792187119SAndrew Rybchenko 	uint32_t partn;
218460cb568SAndrew Rybchenko 	efx_rc_t rc;
219e948693eSPhilip Paeps 
220e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
221e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
222e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
223e948693eSPhilip Paeps 
224e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
225e948693eSPhilip Paeps 
22692187119SAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
227e948693eSPhilip Paeps 		goto fail1;
228e948693eSPhilip Paeps 
22992187119SAndrew Rybchenko 	if ((rc = envop->envo_partn_get_version(enp, partn,
23092187119SAndrew Rybchenko 		    subtypep, version)) != 0)
23192187119SAndrew Rybchenko 		goto fail2;
23292187119SAndrew Rybchenko 
233e948693eSPhilip Paeps 	return (0);
234e948693eSPhilip Paeps 
23592187119SAndrew Rybchenko fail2:
23692187119SAndrew Rybchenko 	EFSYS_PROBE(fail2);
237e948693eSPhilip Paeps fail1:
238460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
239e948693eSPhilip Paeps 
240e948693eSPhilip Paeps 	return (rc);
241e948693eSPhilip Paeps }
242e948693eSPhilip Paeps 
243460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
244e948693eSPhilip Paeps efx_nvram_rw_start(
245e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
246e948693eSPhilip Paeps 	__in			efx_nvram_type_t type,
247e948693eSPhilip Paeps 	__out_opt		size_t *chunk_sizep)
248e948693eSPhilip Paeps {
249e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
2505d846e87SAndrew Rybchenko 	uint32_t partn;
251460cb568SAndrew Rybchenko 	efx_rc_t rc;
252e948693eSPhilip Paeps 
253e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
254e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
255e948693eSPhilip Paeps 
256e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
257e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
258e948693eSPhilip Paeps 
259e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
260e948693eSPhilip Paeps 
2615d846e87SAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
262e948693eSPhilip Paeps 		goto fail1;
263e948693eSPhilip Paeps 
2645d846e87SAndrew Rybchenko 	if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
2655d846e87SAndrew Rybchenko 		goto fail2;
2665d846e87SAndrew Rybchenko 
267e948693eSPhilip Paeps 	enp->en_nvram_locked = type;
268e948693eSPhilip Paeps 
269e948693eSPhilip Paeps 	return (0);
270e948693eSPhilip Paeps 
2715d846e87SAndrew Rybchenko fail2:
2725d846e87SAndrew Rybchenko 	EFSYS_PROBE(fail2);
273e948693eSPhilip Paeps fail1:
274460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
275e948693eSPhilip Paeps 
276e948693eSPhilip Paeps 	return (rc);
277e948693eSPhilip Paeps }
278e948693eSPhilip Paeps 
279460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
280e948693eSPhilip Paeps efx_nvram_read_chunk(
281e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
282e948693eSPhilip Paeps 	__in			efx_nvram_type_t type,
283e948693eSPhilip Paeps 	__in			unsigned int offset,
284e948693eSPhilip Paeps 	__out_bcount(size)	caddr_t data,
285e948693eSPhilip Paeps 	__in			size_t size)
286e948693eSPhilip Paeps {
287e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
2880afdf29cSAndrew Rybchenko 	uint32_t partn;
289460cb568SAndrew Rybchenko 	efx_rc_t rc;
290e948693eSPhilip Paeps 
291e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
292e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
293e948693eSPhilip Paeps 
294e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
295e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
296e948693eSPhilip Paeps 
297e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
298e948693eSPhilip Paeps 
2990afdf29cSAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
300e948693eSPhilip Paeps 		goto fail1;
301e948693eSPhilip Paeps 
3020afdf29cSAndrew Rybchenko 	if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
3030afdf29cSAndrew Rybchenko 		goto fail2;
3040afdf29cSAndrew Rybchenko 
305e948693eSPhilip Paeps 	return (0);
306e948693eSPhilip Paeps 
3070afdf29cSAndrew Rybchenko fail2:
3080afdf29cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
309e948693eSPhilip Paeps fail1:
310460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
311e948693eSPhilip Paeps 
312e948693eSPhilip Paeps 	return (rc);
313e948693eSPhilip Paeps }
314e948693eSPhilip Paeps 
315460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
316e948693eSPhilip Paeps efx_nvram_erase(
317e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
318e948693eSPhilip Paeps 	__in			efx_nvram_type_t type)
319e948693eSPhilip Paeps {
320e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
321b60ff840SAndrew Rybchenko 	unsigned int offset = 0;
322b60ff840SAndrew Rybchenko 	size_t size = 0;
323b60ff840SAndrew Rybchenko 	uint32_t partn;
324460cb568SAndrew Rybchenko 	efx_rc_t rc;
325e948693eSPhilip Paeps 
326e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
327e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
328e948693eSPhilip Paeps 
329e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
330e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
331e948693eSPhilip Paeps 
332e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
333e948693eSPhilip Paeps 
334b60ff840SAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
335e948693eSPhilip Paeps 		goto fail1;
336e948693eSPhilip Paeps 
337b60ff840SAndrew Rybchenko 	if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
338b60ff840SAndrew Rybchenko 		goto fail2;
339b60ff840SAndrew Rybchenko 
340b60ff840SAndrew Rybchenko 	if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
341b60ff840SAndrew Rybchenko 		goto fail3;
342b60ff840SAndrew Rybchenko 
343e948693eSPhilip Paeps 	return (0);
344e948693eSPhilip Paeps 
345b60ff840SAndrew Rybchenko fail3:
346b60ff840SAndrew Rybchenko 	EFSYS_PROBE(fail3);
347b60ff840SAndrew Rybchenko fail2:
348b60ff840SAndrew Rybchenko 	EFSYS_PROBE(fail2);
349e948693eSPhilip Paeps fail1:
350460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
351e948693eSPhilip Paeps 
352e948693eSPhilip Paeps 	return (rc);
353e948693eSPhilip Paeps }
354e948693eSPhilip Paeps 
355460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
356e948693eSPhilip Paeps efx_nvram_write_chunk(
357e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
358e948693eSPhilip Paeps 	__in			efx_nvram_type_t type,
359e948693eSPhilip Paeps 	__in			unsigned int offset,
360e948693eSPhilip Paeps 	__in_bcount(size)	caddr_t data,
361e948693eSPhilip Paeps 	__in			size_t size)
362e948693eSPhilip Paeps {
363e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
364134c4c4aSAndrew Rybchenko 	uint32_t partn;
365460cb568SAndrew Rybchenko 	efx_rc_t rc;
366e948693eSPhilip Paeps 
367e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
368e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
369e948693eSPhilip Paeps 
370e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
371e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
372e948693eSPhilip Paeps 
373e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
374e948693eSPhilip Paeps 
375134c4c4aSAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
376e948693eSPhilip Paeps 		goto fail1;
377e948693eSPhilip Paeps 
378134c4c4aSAndrew Rybchenko 	if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
379134c4c4aSAndrew Rybchenko 		goto fail2;
380134c4c4aSAndrew Rybchenko 
381e948693eSPhilip Paeps 	return (0);
382e948693eSPhilip Paeps 
383134c4c4aSAndrew Rybchenko fail2:
384134c4c4aSAndrew Rybchenko 	EFSYS_PROBE(fail2);
385e948693eSPhilip Paeps fail1:
386460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
387e948693eSPhilip Paeps 
388e948693eSPhilip Paeps 	return (rc);
389e948693eSPhilip Paeps }
390e948693eSPhilip Paeps 
391e948693eSPhilip Paeps 				void
392e948693eSPhilip Paeps efx_nvram_rw_finish(
393e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
394e948693eSPhilip Paeps 	__in			efx_nvram_type_t type)
395e948693eSPhilip Paeps {
396e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
397eb9703daSAndrew Rybchenko 	uint32_t partn;
398e948693eSPhilip Paeps 
399e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
400e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
401e948693eSPhilip Paeps 
402e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
403e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
404e948693eSPhilip Paeps 
405e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
406e948693eSPhilip Paeps 
407eb9703daSAndrew Rybchenko 	if (envop->envo_type_to_partn(enp, type, &partn) == 0)
408eb9703daSAndrew Rybchenko 		envop->envo_partn_rw_finish(enp, partn);
409e948693eSPhilip Paeps 
410e948693eSPhilip Paeps 	enp->en_nvram_locked = EFX_NVRAM_INVALID;
411e948693eSPhilip Paeps }
412e948693eSPhilip Paeps 
413460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
414e948693eSPhilip Paeps efx_nvram_set_version(
415e948693eSPhilip Paeps 	__in			efx_nic_t *enp,
416e948693eSPhilip Paeps 	__in			efx_nvram_type_t type,
4173c838a9fSAndrew Rybchenko 	__in_ecount(4)		uint16_t version[4])
418e948693eSPhilip Paeps {
419e948693eSPhilip Paeps 	efx_nvram_ops_t *envop = enp->en_envop;
4206d0b856cSAndrew Rybchenko 	uint32_t partn;
421460cb568SAndrew Rybchenko 	efx_rc_t rc;
422e948693eSPhilip Paeps 
423e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
424e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
425e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
426e948693eSPhilip Paeps 
427e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
428e948693eSPhilip Paeps 
429e948693eSPhilip Paeps 	/*
430e948693eSPhilip Paeps 	 * The Siena implementation of envo_set_version() will attempt to
431e948693eSPhilip Paeps 	 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
432e948693eSPhilip Paeps 	 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
433e948693eSPhilip Paeps 	 */
434e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
435e948693eSPhilip Paeps 
4366d0b856cSAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
437e948693eSPhilip Paeps 		goto fail1;
438e948693eSPhilip Paeps 
4396d0b856cSAndrew Rybchenko 	if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
4406d0b856cSAndrew Rybchenko 		goto fail2;
4416d0b856cSAndrew Rybchenko 
442e948693eSPhilip Paeps 	return (0);
443e948693eSPhilip Paeps 
4446d0b856cSAndrew Rybchenko fail2:
4456d0b856cSAndrew Rybchenko 	EFSYS_PROBE(fail2);
446e948693eSPhilip Paeps fail1:
447460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
448e948693eSPhilip Paeps 
449e948693eSPhilip Paeps 	return (rc);
450e948693eSPhilip Paeps }
451e948693eSPhilip Paeps 
452*5abce2b9SAndrew Rybchenko /* Validate buffer contents (before writing to flash) */
453*5abce2b9SAndrew Rybchenko 	__checkReturn		efx_rc_t
454*5abce2b9SAndrew Rybchenko efx_nvram_validate(
455*5abce2b9SAndrew Rybchenko 	__in			efx_nic_t *enp,
456*5abce2b9SAndrew Rybchenko 	__in			efx_nvram_type_t type,
457*5abce2b9SAndrew Rybchenko 	__in_bcount(partn_size)	caddr_t partn_data,
458*5abce2b9SAndrew Rybchenko 	__in			size_t partn_size)
459*5abce2b9SAndrew Rybchenko {
460*5abce2b9SAndrew Rybchenko 	efx_nvram_ops_t *envop = enp->en_envop;
461*5abce2b9SAndrew Rybchenko 	uint32_t partn;
462*5abce2b9SAndrew Rybchenko 	efx_rc_t rc;
463*5abce2b9SAndrew Rybchenko 
464*5abce2b9SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
465*5abce2b9SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
466*5abce2b9SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
467*5abce2b9SAndrew Rybchenko 
468*5abce2b9SAndrew Rybchenko 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
469*5abce2b9SAndrew Rybchenko 
470*5abce2b9SAndrew Rybchenko 
471*5abce2b9SAndrew Rybchenko 	if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
472*5abce2b9SAndrew Rybchenko 		goto fail1;
473*5abce2b9SAndrew Rybchenko 
474*5abce2b9SAndrew Rybchenko 	if (envop->envo_type_to_partn != NULL &&
475*5abce2b9SAndrew Rybchenko 	    ((rc = envop->envo_buffer_validate(enp, partn,
476*5abce2b9SAndrew Rybchenko 	    partn_data, partn_size)) != 0))
477*5abce2b9SAndrew Rybchenko 		goto fail2;
478*5abce2b9SAndrew Rybchenko 
479*5abce2b9SAndrew Rybchenko 	return (0);
480*5abce2b9SAndrew Rybchenko 
481*5abce2b9SAndrew Rybchenko fail2:
482*5abce2b9SAndrew Rybchenko 	EFSYS_PROBE(fail2);
483*5abce2b9SAndrew Rybchenko fail1:
484*5abce2b9SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
485*5abce2b9SAndrew Rybchenko 
486*5abce2b9SAndrew Rybchenko 	return (rc);
487*5abce2b9SAndrew Rybchenko }
488*5abce2b9SAndrew Rybchenko 
489*5abce2b9SAndrew Rybchenko 
490e948693eSPhilip Paeps void
491e948693eSPhilip Paeps efx_nvram_fini(
492e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
493e948693eSPhilip Paeps {
494e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
495e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
496e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
497e948693eSPhilip Paeps 
498e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
499e948693eSPhilip Paeps 
500e948693eSPhilip Paeps 	enp->en_envop = NULL;
501e948693eSPhilip Paeps 	enp->en_mod_flags &= ~EFX_MOD_NVRAM;
502e948693eSPhilip Paeps }
503e948693eSPhilip Paeps 
504e948693eSPhilip Paeps #endif	/* EFSYS_OPT_NVRAM */
5053c838a9fSAndrew Rybchenko 
5063c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
5073c838a9fSAndrew Rybchenko 
5083c838a9fSAndrew Rybchenko /*
5093c838a9fSAndrew Rybchenko  * Internal MCDI request handling
5103c838a9fSAndrew Rybchenko  */
5113c838a9fSAndrew Rybchenko 
512460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
5133c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions(
5143c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
5153c838a9fSAndrew Rybchenko 	__out_bcount(size)	caddr_t data,
5163c838a9fSAndrew Rybchenko 	__in			size_t size,
5173c838a9fSAndrew Rybchenko 	__out			unsigned int *npartnp)
5183c838a9fSAndrew Rybchenko {
5193c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
5203c838a9fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN,
5213c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)];
5223c838a9fSAndrew Rybchenko 	unsigned int npartn;
523460cb568SAndrew Rybchenko 	efx_rc_t rc;
5243c838a9fSAndrew Rybchenko 
5253c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
5263c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
5273c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
5283c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
5293c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
5303c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
5313c838a9fSAndrew Rybchenko 
5323c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
5333c838a9fSAndrew Rybchenko 
5343c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
5353c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
5363c838a9fSAndrew Rybchenko 		goto fail1;
5373c838a9fSAndrew Rybchenko 	}
5383c838a9fSAndrew Rybchenko 
5393c838a9fSAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
5403c838a9fSAndrew Rybchenko 		rc = EMSGSIZE;
5413c838a9fSAndrew Rybchenko 		goto fail2;
5423c838a9fSAndrew Rybchenko 	}
5433c838a9fSAndrew Rybchenko 	npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
5443c838a9fSAndrew Rybchenko 
5453c838a9fSAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
5463c838a9fSAndrew Rybchenko 		rc = ENOENT;
5473c838a9fSAndrew Rybchenko 		goto fail3;
5483c838a9fSAndrew Rybchenko 	}
5493c838a9fSAndrew Rybchenko 
5503c838a9fSAndrew Rybchenko 	if (size < npartn * sizeof (uint32_t)) {
5513c838a9fSAndrew Rybchenko 		rc = ENOSPC;
5523c838a9fSAndrew Rybchenko 		goto fail3;
5533c838a9fSAndrew Rybchenko 	}
5543c838a9fSAndrew Rybchenko 
5553c838a9fSAndrew Rybchenko 	*npartnp = npartn;
5563c838a9fSAndrew Rybchenko 
5573c838a9fSAndrew Rybchenko 	memcpy(data,
5583c838a9fSAndrew Rybchenko 	    MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
5593c838a9fSAndrew Rybchenko 	    (npartn * sizeof (uint32_t)));
5603c838a9fSAndrew Rybchenko 
5613c838a9fSAndrew Rybchenko 	return (0);
5623c838a9fSAndrew Rybchenko 
5633c838a9fSAndrew Rybchenko fail3:
5643c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail3);
5653c838a9fSAndrew Rybchenko fail2:
5663c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
5673c838a9fSAndrew Rybchenko fail1:
568460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
5693c838a9fSAndrew Rybchenko 
5703c838a9fSAndrew Rybchenko 	return (rc);
5713c838a9fSAndrew Rybchenko }
5723c838a9fSAndrew Rybchenko 
573460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
5743c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata(
5753c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
5763c838a9fSAndrew Rybchenko 	__in			uint32_t partn,
5773c838a9fSAndrew Rybchenko 	__out			uint32_t *subtypep,
5783c838a9fSAndrew Rybchenko 	__out_ecount(4)		uint16_t version[4],
5793c838a9fSAndrew Rybchenko 	__out_bcount_opt(size)	char *descp,
5803c838a9fSAndrew Rybchenko 	__in			size_t size)
5813c838a9fSAndrew Rybchenko {
5823c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
5833c838a9fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN,
5843c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_METADATA_OUT_LENMAX)];
585460cb568SAndrew Rybchenko 	efx_rc_t rc;
5863c838a9fSAndrew Rybchenko 
5873c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
5883c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_METADATA;
5893c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
5903c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
5913c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
5923c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
5933c838a9fSAndrew Rybchenko 
5943c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
5953c838a9fSAndrew Rybchenko 
5963c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
5973c838a9fSAndrew Rybchenko 
5983c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
5993c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
6003c838a9fSAndrew Rybchenko 		goto fail1;
6013c838a9fSAndrew Rybchenko 	}
6023c838a9fSAndrew Rybchenko 
6033c838a9fSAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
6043c838a9fSAndrew Rybchenko 		rc = EMSGSIZE;
6053c838a9fSAndrew Rybchenko 		goto fail2;
6063c838a9fSAndrew Rybchenko 	}
6073c838a9fSAndrew Rybchenko 
6083c838a9fSAndrew Rybchenko 	if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
6093c838a9fSAndrew Rybchenko 		NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
6103c838a9fSAndrew Rybchenko 		*subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
6113c838a9fSAndrew Rybchenko 	} else {
6123c838a9fSAndrew Rybchenko 		*subtypep = 0;
6133c838a9fSAndrew Rybchenko 	}
6143c838a9fSAndrew Rybchenko 
6153c838a9fSAndrew Rybchenko 	if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
6163c838a9fSAndrew Rybchenko 		NVRAM_METADATA_OUT_VERSION_VALID)) {
6173c838a9fSAndrew Rybchenko 		version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
6183c838a9fSAndrew Rybchenko 		version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
6193c838a9fSAndrew Rybchenko 		version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
6203c838a9fSAndrew Rybchenko 		version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
6213c838a9fSAndrew Rybchenko 	} else {
6223c838a9fSAndrew Rybchenko 		version[0] = version[1] = version[2] = version[3] = 0;
6233c838a9fSAndrew Rybchenko 	}
6243c838a9fSAndrew Rybchenko 
6253c838a9fSAndrew Rybchenko 	if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
6263c838a9fSAndrew Rybchenko 		NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
6273c838a9fSAndrew Rybchenko 		/* Return optional descrition string */
6283c838a9fSAndrew Rybchenko 		if ((descp != NULL) && (size > 0)) {
6293c838a9fSAndrew Rybchenko 			size_t desclen;
6303c838a9fSAndrew Rybchenko 
6313c838a9fSAndrew Rybchenko 			descp[0] = '\0';
6323c838a9fSAndrew Rybchenko 			desclen = (req.emr_out_length_used
6333c838a9fSAndrew Rybchenko 			    - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
6343c838a9fSAndrew Rybchenko 
6353c838a9fSAndrew Rybchenko 			EFSYS_ASSERT3U(desclen, <=,
6363c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
6373c838a9fSAndrew Rybchenko 
6383c838a9fSAndrew Rybchenko 			if (size < desclen) {
6393c838a9fSAndrew Rybchenko 				rc = ENOSPC;
6403c838a9fSAndrew Rybchenko 				goto fail3;
6413c838a9fSAndrew Rybchenko 			}
6423c838a9fSAndrew Rybchenko 
6433c838a9fSAndrew Rybchenko 			memcpy(descp, MCDI_OUT2(req, char,
6443c838a9fSAndrew Rybchenko 				NVRAM_METADATA_OUT_DESCRIPTION),
6453c838a9fSAndrew Rybchenko 			    desclen);
6463c838a9fSAndrew Rybchenko 
6473c838a9fSAndrew Rybchenko 			/* Ensure string is NUL terminated */
6483c838a9fSAndrew Rybchenko 			descp[desclen] = '\0';
6493c838a9fSAndrew Rybchenko 		}
6503c838a9fSAndrew Rybchenko 	}
6513c838a9fSAndrew Rybchenko 
6523c838a9fSAndrew Rybchenko 	return (0);
6533c838a9fSAndrew Rybchenko 
6543c838a9fSAndrew Rybchenko fail3:
6553c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail3);
6563c838a9fSAndrew Rybchenko fail2:
6573c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
6583c838a9fSAndrew Rybchenko fail1:
659460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
6603c838a9fSAndrew Rybchenko 
6613c838a9fSAndrew Rybchenko 	return (rc);
6623c838a9fSAndrew Rybchenko }
6633c838a9fSAndrew Rybchenko 
664460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
6653c838a9fSAndrew Rybchenko efx_mcdi_nvram_info(
6663c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
6673c838a9fSAndrew Rybchenko 	__in			uint32_t partn,
6683c838a9fSAndrew Rybchenko 	__out_opt		size_t *sizep,
6693c838a9fSAndrew Rybchenko 	__out_opt		uint32_t *addressp,
6709cb71b16SAndrew Rybchenko 	__out_opt		uint32_t *erase_sizep,
6719cb71b16SAndrew Rybchenko 	__out_opt		uint32_t *write_sizep)
6723c838a9fSAndrew Rybchenko {
6733c838a9fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN,
6749cb71b16SAndrew Rybchenko 			    MC_CMD_NVRAM_INFO_V2_OUT_LEN)];
6753c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
676460cb568SAndrew Rybchenko 	efx_rc_t rc;
6773c838a9fSAndrew Rybchenko 
6783c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
6793c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_INFO;
6803c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
6813c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
6823c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
6839cb71b16SAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
6843c838a9fSAndrew Rybchenko 
6853c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
6863c838a9fSAndrew Rybchenko 
6873c838a9fSAndrew Rybchenko 	efx_mcdi_execute_quiet(enp, &req);
6883c838a9fSAndrew Rybchenko 
6893c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
6903c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
6913c838a9fSAndrew Rybchenko 		goto fail1;
6923c838a9fSAndrew Rybchenko 	}
6933c838a9fSAndrew Rybchenko 
6943c838a9fSAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
6953c838a9fSAndrew Rybchenko 		rc = EMSGSIZE;
6963c838a9fSAndrew Rybchenko 		goto fail2;
6973c838a9fSAndrew Rybchenko 	}
6983c838a9fSAndrew Rybchenko 
6993c838a9fSAndrew Rybchenko 	if (sizep)
7003c838a9fSAndrew Rybchenko 		*sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
7013c838a9fSAndrew Rybchenko 
7023c838a9fSAndrew Rybchenko 	if (addressp)
7033c838a9fSAndrew Rybchenko 		*addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
7043c838a9fSAndrew Rybchenko 
7053c838a9fSAndrew Rybchenko 	if (erase_sizep)
7063c838a9fSAndrew Rybchenko 		*erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
7073c838a9fSAndrew Rybchenko 
7089cb71b16SAndrew Rybchenko 	if (write_sizep) {
7099cb71b16SAndrew Rybchenko 		*write_sizep =
7109cb71b16SAndrew Rybchenko 			(req.emr_out_length_used <
7119cb71b16SAndrew Rybchenko 			    MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
7129cb71b16SAndrew Rybchenko 			0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
7139cb71b16SAndrew Rybchenko 	}
7149cb71b16SAndrew Rybchenko 
7153c838a9fSAndrew Rybchenko 	return (0);
7163c838a9fSAndrew Rybchenko 
7173c838a9fSAndrew Rybchenko fail2:
7183c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
7193c838a9fSAndrew Rybchenko fail1:
720460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
7213c838a9fSAndrew Rybchenko 
7223c838a9fSAndrew Rybchenko 	return (rc);
7233c838a9fSAndrew Rybchenko }
7243c838a9fSAndrew Rybchenko 
725460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
7263c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start(
7273c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
7283c838a9fSAndrew Rybchenko 	__in			uint32_t partn)
7293c838a9fSAndrew Rybchenko {
7303c838a9fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_IN_LEN,
7313c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_UPDATE_START_OUT_LEN)];
7323c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
733460cb568SAndrew Rybchenko 	efx_rc_t rc;
7343c838a9fSAndrew Rybchenko 
7353c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
7363c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
7373c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
7383c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN;
7393c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
7403c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
7413c838a9fSAndrew Rybchenko 
7423c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn);
7433c838a9fSAndrew Rybchenko 
7443c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
7453c838a9fSAndrew Rybchenko 
7463c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
7473c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
7483c838a9fSAndrew Rybchenko 		goto fail1;
7493c838a9fSAndrew Rybchenko 	}
7503c838a9fSAndrew Rybchenko 
7513c838a9fSAndrew Rybchenko 	return (0);
7523c838a9fSAndrew Rybchenko 
7533c838a9fSAndrew Rybchenko fail1:
754460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
7553c838a9fSAndrew Rybchenko 
7563c838a9fSAndrew Rybchenko 	return (rc);
7573c838a9fSAndrew Rybchenko }
7583c838a9fSAndrew Rybchenko 
759460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
7603c838a9fSAndrew Rybchenko efx_mcdi_nvram_read(
7613c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
7623c838a9fSAndrew Rybchenko 	__in			uint32_t partn,
7633c838a9fSAndrew Rybchenko 	__in			uint32_t offset,
7643c838a9fSAndrew Rybchenko 	__out_bcount(size)	caddr_t data,
7659ad7e03fSAndrew Rybchenko 	__in			size_t size,
7669ad7e03fSAndrew Rybchenko 	__in			uint32_t mode)
7673c838a9fSAndrew Rybchenko {
7683c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
7699ad7e03fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
7703c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_READ_OUT_LENMAX)];
771460cb568SAndrew Rybchenko 	efx_rc_t rc;
7723c838a9fSAndrew Rybchenko 
7733c838a9fSAndrew Rybchenko 	if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
7743c838a9fSAndrew Rybchenko 		rc = EINVAL;
7753c838a9fSAndrew Rybchenko 		goto fail1;
7763c838a9fSAndrew Rybchenko 	}
7773c838a9fSAndrew Rybchenko 
7783c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
7793c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_READ;
7803c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
7819ad7e03fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
7823c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
7833c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
7843c838a9fSAndrew Rybchenko 
7859ad7e03fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
7869ad7e03fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
7879ad7e03fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
7889ad7e03fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
7893c838a9fSAndrew Rybchenko 
7903c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
7913c838a9fSAndrew Rybchenko 
7923c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
7933c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
7943c838a9fSAndrew Rybchenko 		goto fail1;
7953c838a9fSAndrew Rybchenko 	}
7963c838a9fSAndrew Rybchenko 
7973c838a9fSAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
7983c838a9fSAndrew Rybchenko 		rc = EMSGSIZE;
7993c838a9fSAndrew Rybchenko 		goto fail2;
8003c838a9fSAndrew Rybchenko 	}
8013c838a9fSAndrew Rybchenko 
8023c838a9fSAndrew Rybchenko 	memcpy(data,
8033c838a9fSAndrew Rybchenko 	    MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
8043c838a9fSAndrew Rybchenko 	    size);
8053c838a9fSAndrew Rybchenko 
8063c838a9fSAndrew Rybchenko 	return (0);
8073c838a9fSAndrew Rybchenko 
8083c838a9fSAndrew Rybchenko fail2:
8093c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
8103c838a9fSAndrew Rybchenko fail1:
811460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
8123c838a9fSAndrew Rybchenko 
8133c838a9fSAndrew Rybchenko 	return (rc);
8143c838a9fSAndrew Rybchenko }
8153c838a9fSAndrew Rybchenko 
816460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
8173c838a9fSAndrew Rybchenko efx_mcdi_nvram_erase(
8183c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
8193c838a9fSAndrew Rybchenko 	__in			uint32_t partn,
8203c838a9fSAndrew Rybchenko 	__in			uint32_t offset,
8213c838a9fSAndrew Rybchenko 	__in			size_t size)
8223c838a9fSAndrew Rybchenko {
8233c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
8243c838a9fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN,
8253c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_ERASE_OUT_LEN)];
826460cb568SAndrew Rybchenko 	efx_rc_t rc;
8273c838a9fSAndrew Rybchenko 
8283c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
8293c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_ERASE;
8303c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
8313c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
8323c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
8333c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
8343c838a9fSAndrew Rybchenko 
8353c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
8363c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
8373c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
8383c838a9fSAndrew Rybchenko 
8393c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
8403c838a9fSAndrew Rybchenko 
8413c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
8423c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
8433c838a9fSAndrew Rybchenko 		goto fail1;
8443c838a9fSAndrew Rybchenko 	}
8453c838a9fSAndrew Rybchenko 
8463c838a9fSAndrew Rybchenko 	return (0);
8473c838a9fSAndrew Rybchenko 
8483c838a9fSAndrew Rybchenko fail1:
849460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
8503c838a9fSAndrew Rybchenko 
8513c838a9fSAndrew Rybchenko 	return (rc);
8523c838a9fSAndrew Rybchenko }
8533c838a9fSAndrew Rybchenko 
85457396b7aSAndrew Rybchenko /*
85557396b7aSAndrew Rybchenko  * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
85657396b7aSAndrew Rybchenko  * Sienna and EF10 based boards.  However EF10 based boards support the use
85757396b7aSAndrew Rybchenko  * of this command with payloads up to the maximum MCDI V2 payload length.
85857396b7aSAndrew Rybchenko  */
859460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
8603c838a9fSAndrew Rybchenko efx_mcdi_nvram_write(
8613c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
8623c838a9fSAndrew Rybchenko 	__in			uint32_t partn,
8633c838a9fSAndrew Rybchenko 	__in			uint32_t offset,
8643c838a9fSAndrew Rybchenko 	__out_bcount(size)	caddr_t data,
8653c838a9fSAndrew Rybchenko 	__in			size_t size)
8663c838a9fSAndrew Rybchenko {
8673c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
86857396b7aSAndrew Rybchenko 	uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1,
86957396b7aSAndrew Rybchenko 			    MCDI_CTL_SDU_LEN_MAX_V2)];
870460cb568SAndrew Rybchenko 	efx_rc_t rc;
87157396b7aSAndrew Rybchenko 	size_t max_data_size;
8723c838a9fSAndrew Rybchenko 
87357396b7aSAndrew Rybchenko 	max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length
87457396b7aSAndrew Rybchenko 	    - MC_CMD_NVRAM_WRITE_IN_LEN(0);
87557396b7aSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0);
87657396b7aSAndrew Rybchenko 	EFSYS_ASSERT3U(max_data_size, <,
87757396b7aSAndrew Rybchenko 		    enp->en_nic_cfg.enc_mcdi_max_payload_length);
87857396b7aSAndrew Rybchenko 
87957396b7aSAndrew Rybchenko 	if (size > max_data_size) {
8803c838a9fSAndrew Rybchenko 		rc = EINVAL;
8813c838a9fSAndrew Rybchenko 		goto fail1;
8823c838a9fSAndrew Rybchenko 	}
8833c838a9fSAndrew Rybchenko 
8843c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
8853c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_WRITE;
8863c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
8873c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
8883c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
8893c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
8903c838a9fSAndrew Rybchenko 
8913c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
8923c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
8933c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
8943c838a9fSAndrew Rybchenko 
8953c838a9fSAndrew Rybchenko 	memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
8963c838a9fSAndrew Rybchenko 	    data, size);
8973c838a9fSAndrew Rybchenko 
8983c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
8993c838a9fSAndrew Rybchenko 
9003c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
9013c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
9023c838a9fSAndrew Rybchenko 		goto fail2;
9033c838a9fSAndrew Rybchenko 	}
9043c838a9fSAndrew Rybchenko 
9053c838a9fSAndrew Rybchenko 	return (0);
9063c838a9fSAndrew Rybchenko 
9073c838a9fSAndrew Rybchenko fail2:
9083c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
9093c838a9fSAndrew Rybchenko fail1:
910460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
9113c838a9fSAndrew Rybchenko 
9123c838a9fSAndrew Rybchenko 	return (rc);
9133c838a9fSAndrew Rybchenko }
9143c838a9fSAndrew Rybchenko 
915460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
9163c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish(
9173c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
9183c838a9fSAndrew Rybchenko 	__in			uint32_t partn,
9193c838a9fSAndrew Rybchenko 	__in			boolean_t reboot)
9203c838a9fSAndrew Rybchenko {
9213c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
9223c838a9fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN,
9233c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN)];
924460cb568SAndrew Rybchenko 	efx_rc_t rc;
9253c838a9fSAndrew Rybchenko 
9263c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
9273c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
9283c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
9293c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN;
9303c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
9313c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN;
9323c838a9fSAndrew Rybchenko 
9333c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn);
9343c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot);
9353c838a9fSAndrew Rybchenko 
9363c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
9373c838a9fSAndrew Rybchenko 
9383c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
9393c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
9403c838a9fSAndrew Rybchenko 		goto fail1;
9413c838a9fSAndrew Rybchenko 	}
9423c838a9fSAndrew Rybchenko 
9433c838a9fSAndrew Rybchenko 	return (0);
9443c838a9fSAndrew Rybchenko 
9453c838a9fSAndrew Rybchenko fail1:
946460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
9473c838a9fSAndrew Rybchenko 
9483c838a9fSAndrew Rybchenko 	return (rc);
9493c838a9fSAndrew Rybchenko }
9503c838a9fSAndrew Rybchenko 
9513c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG
9523c838a9fSAndrew Rybchenko 
953460cb568SAndrew Rybchenko 	__checkReturn		efx_rc_t
9543c838a9fSAndrew Rybchenko efx_mcdi_nvram_test(
9553c838a9fSAndrew Rybchenko 	__in			efx_nic_t *enp,
9563c838a9fSAndrew Rybchenko 	__in			uint32_t partn)
9573c838a9fSAndrew Rybchenko {
9583c838a9fSAndrew Rybchenko 	efx_mcdi_req_t req;
9593c838a9fSAndrew Rybchenko 	uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN,
9603c838a9fSAndrew Rybchenko 			    MC_CMD_NVRAM_TEST_OUT_LEN)];
9613c838a9fSAndrew Rybchenko 	int result;
962460cb568SAndrew Rybchenko 	efx_rc_t rc;
9633c838a9fSAndrew Rybchenko 
9643c838a9fSAndrew Rybchenko 	(void) memset(payload, 0, sizeof (payload));
9653c838a9fSAndrew Rybchenko 	req.emr_cmd = MC_CMD_NVRAM_TEST;
9663c838a9fSAndrew Rybchenko 	req.emr_in_buf = payload;
9673c838a9fSAndrew Rybchenko 	req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
9683c838a9fSAndrew Rybchenko 	req.emr_out_buf = payload;
9693c838a9fSAndrew Rybchenko 	req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
9703c838a9fSAndrew Rybchenko 
9713c838a9fSAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
9723c838a9fSAndrew Rybchenko 
9733c838a9fSAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
9743c838a9fSAndrew Rybchenko 
9753c838a9fSAndrew Rybchenko 	if (req.emr_rc != 0) {
9763c838a9fSAndrew Rybchenko 		rc = req.emr_rc;
9773c838a9fSAndrew Rybchenko 		goto fail1;
9783c838a9fSAndrew Rybchenko 	}
9793c838a9fSAndrew Rybchenko 
9803c838a9fSAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
9813c838a9fSAndrew Rybchenko 		rc = EMSGSIZE;
9823c838a9fSAndrew Rybchenko 		goto fail2;
9833c838a9fSAndrew Rybchenko 	}
9843c838a9fSAndrew Rybchenko 
9853c838a9fSAndrew Rybchenko 	result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
9863c838a9fSAndrew Rybchenko 	if (result == MC_CMD_NVRAM_TEST_FAIL) {
9873c838a9fSAndrew Rybchenko 
9883c838a9fSAndrew Rybchenko 		EFSYS_PROBE1(nvram_test_failure, int, partn);
9893c838a9fSAndrew Rybchenko 
9903c838a9fSAndrew Rybchenko 		rc = (EINVAL);
9913c838a9fSAndrew Rybchenko 		goto fail3;
9923c838a9fSAndrew Rybchenko 	}
9933c838a9fSAndrew Rybchenko 
9943c838a9fSAndrew Rybchenko 	return (0);
9953c838a9fSAndrew Rybchenko 
9963c838a9fSAndrew Rybchenko fail3:
9973c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail3);
9983c838a9fSAndrew Rybchenko fail2:
9993c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
10003c838a9fSAndrew Rybchenko fail1:
1001460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
10023c838a9fSAndrew Rybchenko 
10033c838a9fSAndrew Rybchenko 	return (rc);
10043c838a9fSAndrew Rybchenko }
10053c838a9fSAndrew Rybchenko 
10063c838a9fSAndrew Rybchenko #endif	/* EFSYS_OPT_DIAG */
10073c838a9fSAndrew Rybchenko 
10083c838a9fSAndrew Rybchenko 
10093c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */
1010