1e948693eSPhilip Paeps /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4929c7febSAndrew Rybchenko * Copyright (c) 2009-2016 Solarflare Communications Inc.
53c838a9fSAndrew Rybchenko * All rights reserved.
6e948693eSPhilip Paeps *
7e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without
83c838a9fSAndrew Rybchenko * modification, are permitted provided that the following conditions are met:
9e948693eSPhilip Paeps *
103c838a9fSAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice,
113c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer.
123c838a9fSAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice,
133c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation
143c838a9fSAndrew Rybchenko * and/or other materials provided with the distribution.
153c838a9fSAndrew Rybchenko *
163c838a9fSAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
173c838a9fSAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
183c838a9fSAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
193c838a9fSAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
203c838a9fSAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
213c838a9fSAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
223c838a9fSAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
233c838a9fSAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
243c838a9fSAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
253c838a9fSAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
263c838a9fSAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273c838a9fSAndrew Rybchenko *
283c838a9fSAndrew Rybchenko * The views and conclusions contained in the software and documentation are
293c838a9fSAndrew Rybchenko * those of the authors and should not be interpreted as representing official
303c838a9fSAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project.
31e948693eSPhilip Paeps */
32e948693eSPhilip Paeps
335dee87d7SPhilip Paeps #include <sys/cdefs.h>
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_SIENA
40e948693eSPhilip Paeps
41ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_siena_ops = {
42e948693eSPhilip Paeps #if EFSYS_OPT_DIAG
43e948693eSPhilip Paeps siena_nvram_test, /* envo_test */
44e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */
45bce88e31SAndrew Rybchenko siena_nvram_type_to_partn, /* envo_type_to_partn */
4656bd83b0SAndrew Rybchenko siena_nvram_partn_size, /* envo_partn_size */
475d846e87SAndrew Rybchenko siena_nvram_partn_rw_start, /* envo_partn_rw_start */
480afdf29cSAndrew Rybchenko siena_nvram_partn_read, /* envo_partn_read */
49ede1a3edSAndrew Rybchenko siena_nvram_partn_read, /* envo_partn_read_backup */
50b60ff840SAndrew Rybchenko siena_nvram_partn_erase, /* envo_partn_erase */
51134c4c4aSAndrew Rybchenko siena_nvram_partn_write, /* envo_partn_write */
52eb9703daSAndrew Rybchenko siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
5392187119SAndrew Rybchenko siena_nvram_partn_get_version, /* envo_partn_get_version */
546d0b856cSAndrew Rybchenko siena_nvram_partn_set_version, /* envo_partn_set_version */
555abce2b9SAndrew Rybchenko NULL, /* envo_partn_validate */
56e948693eSPhilip Paeps };
57e948693eSPhilip Paeps
58e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */
59e948693eSPhilip Paeps
60824c97edSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
613c838a9fSAndrew Rybchenko
62ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_ef10_ops = {
633c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG
64de9775adSAndrew Rybchenko ef10_nvram_test, /* envo_test */
653c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
66bce88e31SAndrew Rybchenko ef10_nvram_type_to_partn, /* envo_type_to_partn */
6756bd83b0SAndrew Rybchenko ef10_nvram_partn_size, /* envo_partn_size */
685d846e87SAndrew Rybchenko ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
690afdf29cSAndrew Rybchenko ef10_nvram_partn_read, /* envo_partn_read */
70ede1a3edSAndrew Rybchenko ef10_nvram_partn_read_backup, /* envo_partn_read_backup */
71b60ff840SAndrew Rybchenko ef10_nvram_partn_erase, /* envo_partn_erase */
72134c4c4aSAndrew Rybchenko ef10_nvram_partn_write, /* envo_partn_write */
73eb9703daSAndrew Rybchenko ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
7492187119SAndrew Rybchenko ef10_nvram_partn_get_version, /* envo_partn_get_version */
756d0b856cSAndrew Rybchenko ef10_nvram_partn_set_version, /* envo_partn_set_version */
765abce2b9SAndrew Rybchenko ef10_nvram_buffer_validate, /* envo_buffer_validate */
773c838a9fSAndrew Rybchenko };
783c838a9fSAndrew Rybchenko
79824c97edSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
803c838a9fSAndrew Rybchenko
81460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_init(__in efx_nic_t * enp)82e948693eSPhilip Paeps efx_nvram_init(
83e948693eSPhilip Paeps __in efx_nic_t *enp)
84e948693eSPhilip Paeps {
85ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop;
86460cb568SAndrew Rybchenko efx_rc_t rc;
87e948693eSPhilip Paeps
88e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
89e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
90e948693eSPhilip Paeps EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
91e948693eSPhilip Paeps
92e948693eSPhilip Paeps switch (enp->en_family) {
93e948693eSPhilip Paeps #if EFSYS_OPT_SIENA
94e948693eSPhilip Paeps case EFX_FAMILY_SIENA:
95ec831f7fSAndrew Rybchenko envop = &__efx_nvram_siena_ops;
96e948693eSPhilip Paeps break;
97e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */
98e948693eSPhilip Paeps
993c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
1003c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
101ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops;
1023c838a9fSAndrew Rybchenko break;
1033c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
1043c838a9fSAndrew Rybchenko
105de9775adSAndrew Rybchenko #if EFSYS_OPT_MEDFORD
106de9775adSAndrew Rybchenko case EFX_FAMILY_MEDFORD:
107ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops;
108de9775adSAndrew Rybchenko break;
109de9775adSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
110de9775adSAndrew Rybchenko
111824c97edSAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
112824c97edSAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
113824c97edSAndrew Rybchenko envop = &__efx_nvram_ef10_ops;
114824c97edSAndrew Rybchenko break;
115824c97edSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
116824c97edSAndrew Rybchenko
117e948693eSPhilip Paeps default:
118e948693eSPhilip Paeps EFSYS_ASSERT(0);
119e948693eSPhilip Paeps rc = ENOTSUP;
120e948693eSPhilip Paeps goto fail1;
121e948693eSPhilip Paeps }
122e948693eSPhilip Paeps
123e948693eSPhilip Paeps enp->en_envop = envop;
124e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_NVRAM;
125e948693eSPhilip Paeps
1263d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
1273d670ff5SAndrew Rybchenko
128e948693eSPhilip Paeps return (0);
129e948693eSPhilip Paeps
130e948693eSPhilip Paeps fail1:
131460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
132e948693eSPhilip Paeps
133e948693eSPhilip Paeps return (rc);
134e948693eSPhilip Paeps }
135e948693eSPhilip Paeps
136e948693eSPhilip Paeps #if EFSYS_OPT_DIAG
137e948693eSPhilip Paeps
138460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_test(__in efx_nic_t * enp)139e948693eSPhilip Paeps efx_nvram_test(
140e948693eSPhilip Paeps __in efx_nic_t *enp)
141e948693eSPhilip Paeps {
142ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
143460cb568SAndrew Rybchenko efx_rc_t rc;
144e948693eSPhilip Paeps
145e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
146e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
147e948693eSPhilip Paeps
148e948693eSPhilip Paeps if ((rc = envop->envo_test(enp)) != 0)
149e948693eSPhilip Paeps goto fail1;
150e948693eSPhilip Paeps
151e948693eSPhilip Paeps return (0);
152e948693eSPhilip Paeps
153e948693eSPhilip Paeps fail1:
154460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
155e948693eSPhilip Paeps
156e948693eSPhilip Paeps return (rc);
157e948693eSPhilip Paeps }
158e948693eSPhilip Paeps
159e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */
160e948693eSPhilip Paeps
161460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_size(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out size_t * sizep)162e948693eSPhilip Paeps efx_nvram_size(
163e948693eSPhilip Paeps __in efx_nic_t *enp,
164e948693eSPhilip Paeps __in efx_nvram_type_t type,
165e948693eSPhilip Paeps __out size_t *sizep)
166e948693eSPhilip Paeps {
167ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
16856bd83b0SAndrew Rybchenko uint32_t partn;
169460cb568SAndrew Rybchenko efx_rc_t rc;
170e948693eSPhilip Paeps
171e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
172e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
173e948693eSPhilip Paeps
17456bd83b0SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
175e948693eSPhilip Paeps goto fail1;
176e948693eSPhilip Paeps
17756bd83b0SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
17856bd83b0SAndrew Rybchenko goto fail2;
17956bd83b0SAndrew Rybchenko
180e948693eSPhilip Paeps return (0);
181e948693eSPhilip Paeps
18256bd83b0SAndrew Rybchenko fail2:
18356bd83b0SAndrew Rybchenko EFSYS_PROBE(fail2);
184e948693eSPhilip Paeps fail1:
185460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
18656bd83b0SAndrew Rybchenko *sizep = 0;
187e948693eSPhilip Paeps
188e948693eSPhilip Paeps return (rc);
189e948693eSPhilip Paeps }
190e948693eSPhilip Paeps
191460cb568SAndrew Rybchenko __checkReturn efx_rc_t
192e948693eSPhilip Paeps efx_nvram_get_version(
193e948693eSPhilip Paeps __in efx_nic_t *enp,
194e948693eSPhilip Paeps __in efx_nvram_type_t type,
195e948693eSPhilip Paeps __out uint32_t *subtypep,
196e948693eSPhilip Paeps __out_ecount(4) uint16_t version[4])
197e948693eSPhilip Paeps {
198ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
19992187119SAndrew Rybchenko uint32_t partn;
200460cb568SAndrew Rybchenko efx_rc_t rc;
201e948693eSPhilip Paeps
202e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
203e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
204e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
205e948693eSPhilip Paeps
20692187119SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
207e948693eSPhilip Paeps goto fail1;
208e948693eSPhilip Paeps
20992187119SAndrew Rybchenko if ((rc = envop->envo_partn_get_version(enp, partn,
21092187119SAndrew Rybchenko subtypep, version)) != 0)
21192187119SAndrew Rybchenko goto fail2;
21292187119SAndrew Rybchenko
213e948693eSPhilip Paeps return (0);
214e948693eSPhilip Paeps
21592187119SAndrew Rybchenko fail2:
21692187119SAndrew Rybchenko EFSYS_PROBE(fail2);
217e948693eSPhilip Paeps fail1:
218460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
219e948693eSPhilip Paeps
220e948693eSPhilip Paeps return (rc);
221e948693eSPhilip Paeps }
222e948693eSPhilip Paeps
223460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_rw_start(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out_opt size_t * chunk_sizep)224e948693eSPhilip Paeps efx_nvram_rw_start(
225e948693eSPhilip Paeps __in efx_nic_t *enp,
226e948693eSPhilip Paeps __in efx_nvram_type_t type,
227e948693eSPhilip Paeps __out_opt size_t *chunk_sizep)
228e948693eSPhilip Paeps {
229ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
2305d846e87SAndrew Rybchenko uint32_t partn;
231460cb568SAndrew Rybchenko efx_rc_t rc;
232e948693eSPhilip Paeps
233e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
234e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
235e948693eSPhilip Paeps
2365d846e87SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
237e948693eSPhilip Paeps goto fail1;
238e948693eSPhilip Paeps
2393d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
2403d670ff5SAndrew Rybchenko
2415d846e87SAndrew Rybchenko if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
2425d846e87SAndrew Rybchenko goto fail2;
2435d846e87SAndrew Rybchenko
2443d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = partn;
245e948693eSPhilip Paeps
246e948693eSPhilip Paeps return (0);
247e948693eSPhilip Paeps
2485d846e87SAndrew Rybchenko fail2:
2495d846e87SAndrew Rybchenko EFSYS_PROBE(fail2);
250e948693eSPhilip Paeps fail1:
251460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
252e948693eSPhilip Paeps
253e948693eSPhilip Paeps return (rc);
254e948693eSPhilip Paeps }
255e948693eSPhilip Paeps
256460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_read_chunk(__in efx_nic_t * enp,__in efx_nvram_type_t type,__in unsigned int offset,__out_bcount (size)caddr_t data,__in size_t size)257e948693eSPhilip Paeps efx_nvram_read_chunk(
258e948693eSPhilip Paeps __in efx_nic_t *enp,
259e948693eSPhilip Paeps __in efx_nvram_type_t type,
260e948693eSPhilip Paeps __in unsigned int offset,
261e948693eSPhilip Paeps __out_bcount(size) caddr_t data,
262e948693eSPhilip Paeps __in size_t size)
263e948693eSPhilip Paeps {
264ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
2650afdf29cSAndrew Rybchenko uint32_t partn;
266460cb568SAndrew Rybchenko efx_rc_t rc;
267e948693eSPhilip Paeps
268e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
269e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
270e948693eSPhilip Paeps
2710afdf29cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
272e948693eSPhilip Paeps goto fail1;
273e948693eSPhilip Paeps
2743d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
2753d670ff5SAndrew Rybchenko
2760afdf29cSAndrew Rybchenko if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
2770afdf29cSAndrew Rybchenko goto fail2;
2780afdf29cSAndrew Rybchenko
279e948693eSPhilip Paeps return (0);
280e948693eSPhilip Paeps
2810afdf29cSAndrew Rybchenko fail2:
2820afdf29cSAndrew Rybchenko EFSYS_PROBE(fail2);
283e948693eSPhilip Paeps fail1:
284460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
285e948693eSPhilip Paeps
286e948693eSPhilip Paeps return (rc);
287e948693eSPhilip Paeps }
288e948693eSPhilip Paeps
289ede1a3edSAndrew Rybchenko /*
290ede1a3edSAndrew Rybchenko * Read from the backup (writeable) store of an A/B partition.
291ede1a3edSAndrew Rybchenko * For non A/B partitions, there is only a single store, and so this
292ede1a3edSAndrew Rybchenko * function has the same behaviour as efx_nvram_read_chunk().
293ede1a3edSAndrew Rybchenko */
294ede1a3edSAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_read_backup(__in efx_nic_t * enp,__in efx_nvram_type_t type,__in unsigned int offset,__out_bcount (size)caddr_t data,__in size_t size)295ede1a3edSAndrew Rybchenko efx_nvram_read_backup(
296ede1a3edSAndrew Rybchenko __in efx_nic_t *enp,
297ede1a3edSAndrew Rybchenko __in efx_nvram_type_t type,
298ede1a3edSAndrew Rybchenko __in unsigned int offset,
299ede1a3edSAndrew Rybchenko __out_bcount(size) caddr_t data,
300ede1a3edSAndrew Rybchenko __in size_t size)
301ede1a3edSAndrew Rybchenko {
302ede1a3edSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
303ede1a3edSAndrew Rybchenko uint32_t partn;
304ede1a3edSAndrew Rybchenko efx_rc_t rc;
305ede1a3edSAndrew Rybchenko
306ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
307ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
308ede1a3edSAndrew Rybchenko
309ede1a3edSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
310ede1a3edSAndrew Rybchenko goto fail1;
311ede1a3edSAndrew Rybchenko
312ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
313ede1a3edSAndrew Rybchenko
314ede1a3edSAndrew Rybchenko if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
315ede1a3edSAndrew Rybchenko data, size)) != 0)
316ede1a3edSAndrew Rybchenko goto fail2;
317ede1a3edSAndrew Rybchenko
318ede1a3edSAndrew Rybchenko return (0);
319ede1a3edSAndrew Rybchenko
320ede1a3edSAndrew Rybchenko fail2:
321ede1a3edSAndrew Rybchenko EFSYS_PROBE(fail2);
322ede1a3edSAndrew Rybchenko fail1:
323ede1a3edSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
324ede1a3edSAndrew Rybchenko
325ede1a3edSAndrew Rybchenko return (rc);
326ede1a3edSAndrew Rybchenko }
327ede1a3edSAndrew Rybchenko
328460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_erase(__in efx_nic_t * enp,__in efx_nvram_type_t type)329e948693eSPhilip Paeps efx_nvram_erase(
330e948693eSPhilip Paeps __in efx_nic_t *enp,
331e948693eSPhilip Paeps __in efx_nvram_type_t type)
332e948693eSPhilip Paeps {
333ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
334b60ff840SAndrew Rybchenko unsigned int offset = 0;
335b60ff840SAndrew Rybchenko size_t size = 0;
336b60ff840SAndrew Rybchenko uint32_t partn;
337460cb568SAndrew Rybchenko efx_rc_t rc;
338e948693eSPhilip Paeps
339e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
340e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
341e948693eSPhilip Paeps
342b60ff840SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
343e948693eSPhilip Paeps goto fail1;
344e948693eSPhilip Paeps
3453d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
3463d670ff5SAndrew Rybchenko
347b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
348b60ff840SAndrew Rybchenko goto fail2;
349b60ff840SAndrew Rybchenko
350b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
351b60ff840SAndrew Rybchenko goto fail3;
352b60ff840SAndrew Rybchenko
353e948693eSPhilip Paeps return (0);
354e948693eSPhilip Paeps
355b60ff840SAndrew Rybchenko fail3:
356b60ff840SAndrew Rybchenko EFSYS_PROBE(fail3);
357b60ff840SAndrew Rybchenko fail2:
358b60ff840SAndrew Rybchenko EFSYS_PROBE(fail2);
359e948693eSPhilip Paeps fail1:
360460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
361e948693eSPhilip Paeps
362e948693eSPhilip Paeps return (rc);
363e948693eSPhilip Paeps }
364e948693eSPhilip Paeps
365460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_write_chunk(__in efx_nic_t * enp,__in efx_nvram_type_t type,__in unsigned int offset,__in_bcount (size)caddr_t data,__in size_t size)366e948693eSPhilip Paeps efx_nvram_write_chunk(
367e948693eSPhilip Paeps __in efx_nic_t *enp,
368e948693eSPhilip Paeps __in efx_nvram_type_t type,
369e948693eSPhilip Paeps __in unsigned int offset,
370e948693eSPhilip Paeps __in_bcount(size) caddr_t data,
371e948693eSPhilip Paeps __in size_t size)
372e948693eSPhilip Paeps {
373ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
374134c4c4aSAndrew Rybchenko uint32_t partn;
375460cb568SAndrew Rybchenko efx_rc_t rc;
376e948693eSPhilip Paeps
377e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
378e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
379e948693eSPhilip Paeps
380134c4c4aSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
381e948693eSPhilip Paeps goto fail1;
382e948693eSPhilip Paeps
3833d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
3843d670ff5SAndrew Rybchenko
385134c4c4aSAndrew Rybchenko if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
386134c4c4aSAndrew Rybchenko goto fail2;
387134c4c4aSAndrew Rybchenko
388e948693eSPhilip Paeps return (0);
389e948693eSPhilip Paeps
390134c4c4aSAndrew Rybchenko fail2:
391134c4c4aSAndrew Rybchenko EFSYS_PROBE(fail2);
392e948693eSPhilip Paeps fail1:
393460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
394e948693eSPhilip Paeps
395e948693eSPhilip Paeps return (rc);
396e948693eSPhilip Paeps }
397e948693eSPhilip Paeps
398e9c123a5SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_rw_finish(__in efx_nic_t * enp,__in efx_nvram_type_t type,__out_opt uint32_t * verify_resultp)399e948693eSPhilip Paeps efx_nvram_rw_finish(
400e948693eSPhilip Paeps __in efx_nic_t *enp,
401d5106d05SAndrew Rybchenko __in efx_nvram_type_t type,
402d5106d05SAndrew Rybchenko __out_opt uint32_t *verify_resultp)
403e948693eSPhilip Paeps {
404ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
405eb9703daSAndrew Rybchenko uint32_t partn;
406d5106d05SAndrew Rybchenko uint32_t verify_result = 0;
407e9c123a5SAndrew Rybchenko efx_rc_t rc;
408e948693eSPhilip Paeps
409e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
410e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
411e948693eSPhilip Paeps
412e9c123a5SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
413e9c123a5SAndrew Rybchenko goto fail1;
414e9c123a5SAndrew Rybchenko
4153d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
4163d670ff5SAndrew Rybchenko
417a21b2f20SAndrew Rybchenko if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
418e9c123a5SAndrew Rybchenko goto fail2;
419e948693eSPhilip Paeps
4203d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
421e9c123a5SAndrew Rybchenko
422d5106d05SAndrew Rybchenko if (verify_resultp != NULL)
423d5106d05SAndrew Rybchenko *verify_resultp = verify_result;
424d5106d05SAndrew Rybchenko
425e9c123a5SAndrew Rybchenko return (0);
426e9c123a5SAndrew Rybchenko
427e9c123a5SAndrew Rybchenko fail2:
428e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2);
4293d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
430e9c123a5SAndrew Rybchenko
431e9c123a5SAndrew Rybchenko fail1:
432e9c123a5SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
433e9c123a5SAndrew Rybchenko
434d5106d05SAndrew Rybchenko /* Always report verification result */
435d5106d05SAndrew Rybchenko if (verify_resultp != NULL)
436d5106d05SAndrew Rybchenko *verify_resultp = verify_result;
437d5106d05SAndrew Rybchenko
438e9c123a5SAndrew Rybchenko return (rc);
439e948693eSPhilip Paeps }
440e948693eSPhilip Paeps
441460cb568SAndrew Rybchenko __checkReturn efx_rc_t
442e948693eSPhilip Paeps efx_nvram_set_version(
443e948693eSPhilip Paeps __in efx_nic_t *enp,
444e948693eSPhilip Paeps __in efx_nvram_type_t type,
4453c838a9fSAndrew Rybchenko __in_ecount(4) uint16_t version[4])
446e948693eSPhilip Paeps {
447ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
4486d0b856cSAndrew Rybchenko uint32_t partn;
449460cb568SAndrew Rybchenko efx_rc_t rc;
450e948693eSPhilip Paeps
451e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
452e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
453e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
454e948693eSPhilip Paeps
4556d0b856cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
456e948693eSPhilip Paeps goto fail1;
457e948693eSPhilip Paeps
4583d670ff5SAndrew Rybchenko /*
4593d670ff5SAndrew Rybchenko * The Siena implementation of envo_set_version() will attempt to
4603d670ff5SAndrew Rybchenko * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
4613d670ff5SAndrew Rybchenko * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
4623d670ff5SAndrew Rybchenko */
4633d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
4643d670ff5SAndrew Rybchenko
4656d0b856cSAndrew Rybchenko if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
4666d0b856cSAndrew Rybchenko goto fail2;
4676d0b856cSAndrew Rybchenko
468e948693eSPhilip Paeps return (0);
469e948693eSPhilip Paeps
4706d0b856cSAndrew Rybchenko fail2:
4716d0b856cSAndrew Rybchenko EFSYS_PROBE(fail2);
472e948693eSPhilip Paeps fail1:
473460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
474e948693eSPhilip Paeps
475e948693eSPhilip Paeps return (rc);
476e948693eSPhilip Paeps }
477e948693eSPhilip Paeps
4785abce2b9SAndrew Rybchenko /* Validate buffer contents (before writing to flash) */
4795abce2b9SAndrew Rybchenko __checkReturn efx_rc_t
efx_nvram_validate(__in efx_nic_t * enp,__in efx_nvram_type_t type,__in_bcount (partn_size)caddr_t partn_data,__in size_t partn_size)4805abce2b9SAndrew Rybchenko efx_nvram_validate(
4815abce2b9SAndrew Rybchenko __in efx_nic_t *enp,
4825abce2b9SAndrew Rybchenko __in efx_nvram_type_t type,
4835abce2b9SAndrew Rybchenko __in_bcount(partn_size) caddr_t partn_data,
4845abce2b9SAndrew Rybchenko __in size_t partn_size)
4855abce2b9SAndrew Rybchenko {
486ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop;
4875abce2b9SAndrew Rybchenko uint32_t partn;
4885abce2b9SAndrew Rybchenko efx_rc_t rc;
4895abce2b9SAndrew Rybchenko
4905abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4915abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
4925abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
4935abce2b9SAndrew Rybchenko
4945abce2b9SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
4955abce2b9SAndrew Rybchenko goto fail1;
4965abce2b9SAndrew Rybchenko
4976a869fecSAndrew Rybchenko if (envop->envo_buffer_validate != NULL) {
498e919b7ecSAndrew Rybchenko if ((rc = envop->envo_buffer_validate(partn,
4996a869fecSAndrew Rybchenko partn_data, partn_size)) != 0)
5005abce2b9SAndrew Rybchenko goto fail2;
5016a869fecSAndrew Rybchenko }
5025abce2b9SAndrew Rybchenko
5035abce2b9SAndrew Rybchenko return (0);
5045abce2b9SAndrew Rybchenko
5055abce2b9SAndrew Rybchenko fail2:
5065abce2b9SAndrew Rybchenko EFSYS_PROBE(fail2);
5075abce2b9SAndrew Rybchenko fail1:
5085abce2b9SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5095abce2b9SAndrew Rybchenko
5105abce2b9SAndrew Rybchenko return (rc);
5115abce2b9SAndrew Rybchenko }
5125abce2b9SAndrew Rybchenko
513e948693eSPhilip Paeps void
efx_nvram_fini(__in efx_nic_t * enp)514e948693eSPhilip Paeps efx_nvram_fini(
515e948693eSPhilip Paeps __in efx_nic_t *enp)
516e948693eSPhilip Paeps {
517e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
518e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
519e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
520e948693eSPhilip Paeps
5213d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
522e948693eSPhilip Paeps
523e948693eSPhilip Paeps enp->en_envop = NULL;
524e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_NVRAM;
525e948693eSPhilip Paeps }
526e948693eSPhilip Paeps
527e948693eSPhilip Paeps #endif /* EFSYS_OPT_NVRAM */
5283c838a9fSAndrew Rybchenko
5293c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
5303c838a9fSAndrew Rybchenko
5313c838a9fSAndrew Rybchenko /*
5323c838a9fSAndrew Rybchenko * Internal MCDI request handling
5333c838a9fSAndrew Rybchenko */
5343c838a9fSAndrew Rybchenko
535460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_partitions(__in efx_nic_t * enp,__out_bcount (size)caddr_t data,__in size_t size,__out unsigned int * npartnp)5363c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions(
5373c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
5383c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data,
5393c838a9fSAndrew Rybchenko __in size_t size,
5403c838a9fSAndrew Rybchenko __out unsigned int *npartnp)
5413c838a9fSAndrew Rybchenko {
5423c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
543315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_PARTITIONS_IN_LEN,
544315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
5453c838a9fSAndrew Rybchenko unsigned int npartn;
546460cb568SAndrew Rybchenko efx_rc_t rc;
5473c838a9fSAndrew Rybchenko
5483c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
5493c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
5503c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
5513c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
5523c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
5533c838a9fSAndrew Rybchenko
5543c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
5553c838a9fSAndrew Rybchenko
5563c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
5573c838a9fSAndrew Rybchenko rc = req.emr_rc;
5583c838a9fSAndrew Rybchenko goto fail1;
5593c838a9fSAndrew Rybchenko }
5603c838a9fSAndrew Rybchenko
5613c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
5623c838a9fSAndrew Rybchenko rc = EMSGSIZE;
5633c838a9fSAndrew Rybchenko goto fail2;
5643c838a9fSAndrew Rybchenko }
5653c838a9fSAndrew Rybchenko npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
5663c838a9fSAndrew Rybchenko
5673c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
5683c838a9fSAndrew Rybchenko rc = ENOENT;
5693c838a9fSAndrew Rybchenko goto fail3;
5703c838a9fSAndrew Rybchenko }
5713c838a9fSAndrew Rybchenko
5723c838a9fSAndrew Rybchenko if (size < npartn * sizeof (uint32_t)) {
5733c838a9fSAndrew Rybchenko rc = ENOSPC;
5743c838a9fSAndrew Rybchenko goto fail3;
5753c838a9fSAndrew Rybchenko }
5763c838a9fSAndrew Rybchenko
5773c838a9fSAndrew Rybchenko *npartnp = npartn;
5783c838a9fSAndrew Rybchenko
5793c838a9fSAndrew Rybchenko memcpy(data,
5803c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
5813c838a9fSAndrew Rybchenko (npartn * sizeof (uint32_t)));
5823c838a9fSAndrew Rybchenko
5833c838a9fSAndrew Rybchenko return (0);
5843c838a9fSAndrew Rybchenko
5853c838a9fSAndrew Rybchenko fail3:
5863c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
5873c838a9fSAndrew Rybchenko fail2:
5883c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
5893c838a9fSAndrew Rybchenko fail1:
590460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5913c838a9fSAndrew Rybchenko
5923c838a9fSAndrew Rybchenko return (rc);
5933c838a9fSAndrew Rybchenko }
5943c838a9fSAndrew Rybchenko
595460cb568SAndrew Rybchenko __checkReturn efx_rc_t
5963c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata(
5973c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
5983c838a9fSAndrew Rybchenko __in uint32_t partn,
5993c838a9fSAndrew Rybchenko __out uint32_t *subtypep,
6003c838a9fSAndrew Rybchenko __out_ecount(4) uint16_t version[4],
6013c838a9fSAndrew Rybchenko __out_bcount_opt(size) char *descp,
6023c838a9fSAndrew Rybchenko __in size_t size)
6033c838a9fSAndrew Rybchenko {
6043c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
605315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_METADATA_IN_LEN,
606315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_LENMAX);
607460cb568SAndrew Rybchenko efx_rc_t rc;
6083c838a9fSAndrew Rybchenko
6093c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_METADATA;
6103c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
6113c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
6123c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
6133c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
6143c838a9fSAndrew Rybchenko
6153c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
6163c838a9fSAndrew Rybchenko
617e7144483SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
6183c838a9fSAndrew Rybchenko
6193c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
6203c838a9fSAndrew Rybchenko rc = req.emr_rc;
6213c838a9fSAndrew Rybchenko goto fail1;
6223c838a9fSAndrew Rybchenko }
6233c838a9fSAndrew Rybchenko
6243c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
6253c838a9fSAndrew Rybchenko rc = EMSGSIZE;
6263c838a9fSAndrew Rybchenko goto fail2;
6273c838a9fSAndrew Rybchenko }
6283c838a9fSAndrew Rybchenko
6293c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
6303c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
6313c838a9fSAndrew Rybchenko *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
6323c838a9fSAndrew Rybchenko } else {
6333c838a9fSAndrew Rybchenko *subtypep = 0;
6343c838a9fSAndrew Rybchenko }
6353c838a9fSAndrew Rybchenko
6363c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
6373c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_VERSION_VALID)) {
6383c838a9fSAndrew Rybchenko version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
6393c838a9fSAndrew Rybchenko version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
6403c838a9fSAndrew Rybchenko version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
6413c838a9fSAndrew Rybchenko version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
6423c838a9fSAndrew Rybchenko } else {
6433c838a9fSAndrew Rybchenko version[0] = version[1] = version[2] = version[3] = 0;
6443c838a9fSAndrew Rybchenko }
6453c838a9fSAndrew Rybchenko
6463c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
6473c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
6483c838a9fSAndrew Rybchenko /* Return optional descrition string */
6493c838a9fSAndrew Rybchenko if ((descp != NULL) && (size > 0)) {
6503c838a9fSAndrew Rybchenko size_t desclen;
6513c838a9fSAndrew Rybchenko
6523c838a9fSAndrew Rybchenko descp[0] = '\0';
6533c838a9fSAndrew Rybchenko desclen = (req.emr_out_length_used
6543c838a9fSAndrew Rybchenko - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
6553c838a9fSAndrew Rybchenko
6563c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(desclen, <=,
6573c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
6583c838a9fSAndrew Rybchenko
6593c838a9fSAndrew Rybchenko if (size < desclen) {
6603c838a9fSAndrew Rybchenko rc = ENOSPC;
6613c838a9fSAndrew Rybchenko goto fail3;
6623c838a9fSAndrew Rybchenko }
6633c838a9fSAndrew Rybchenko
6643c838a9fSAndrew Rybchenko memcpy(descp, MCDI_OUT2(req, char,
6653c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION),
6663c838a9fSAndrew Rybchenko desclen);
6673c838a9fSAndrew Rybchenko
6683c838a9fSAndrew Rybchenko /* Ensure string is NUL terminated */
6693c838a9fSAndrew Rybchenko descp[desclen] = '\0';
6703c838a9fSAndrew Rybchenko }
6713c838a9fSAndrew Rybchenko }
6723c838a9fSAndrew Rybchenko
6733c838a9fSAndrew Rybchenko return (0);
6743c838a9fSAndrew Rybchenko
6753c838a9fSAndrew Rybchenko fail3:
6763c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
6773c838a9fSAndrew Rybchenko fail2:
6783c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
6793c838a9fSAndrew Rybchenko fail1:
680460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
6813c838a9fSAndrew Rybchenko
6823c838a9fSAndrew Rybchenko return (rc);
6833c838a9fSAndrew Rybchenko }
6843c838a9fSAndrew Rybchenko
685460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_info(__in efx_nic_t * enp,__in uint32_t partn,__out_opt size_t * sizep,__out_opt uint32_t * addressp,__out_opt uint32_t * erase_sizep,__out_opt uint32_t * write_sizep)6863c838a9fSAndrew Rybchenko efx_mcdi_nvram_info(
6873c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
6883c838a9fSAndrew Rybchenko __in uint32_t partn,
6893c838a9fSAndrew Rybchenko __out_opt size_t *sizep,
6903c838a9fSAndrew Rybchenko __out_opt uint32_t *addressp,
6919cb71b16SAndrew Rybchenko __out_opt uint32_t *erase_sizep,
6929cb71b16SAndrew Rybchenko __out_opt uint32_t *write_sizep)
6933c838a9fSAndrew Rybchenko {
694315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_INFO_IN_LEN,
695315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN);
6963c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
697460cb568SAndrew Rybchenko efx_rc_t rc;
6983c838a9fSAndrew Rybchenko
6993c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_INFO;
7003c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
7013c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
7023c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
7039cb71b16SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
7043c838a9fSAndrew Rybchenko
7053c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
7063c838a9fSAndrew Rybchenko
7073c838a9fSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req);
7083c838a9fSAndrew Rybchenko
7093c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
7103c838a9fSAndrew Rybchenko rc = req.emr_rc;
7113c838a9fSAndrew Rybchenko goto fail1;
7123c838a9fSAndrew Rybchenko }
7133c838a9fSAndrew Rybchenko
7143c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
7153c838a9fSAndrew Rybchenko rc = EMSGSIZE;
7163c838a9fSAndrew Rybchenko goto fail2;
7173c838a9fSAndrew Rybchenko }
7183c838a9fSAndrew Rybchenko
7193c838a9fSAndrew Rybchenko if (sizep)
7203c838a9fSAndrew Rybchenko *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
7213c838a9fSAndrew Rybchenko
7223c838a9fSAndrew Rybchenko if (addressp)
7233c838a9fSAndrew Rybchenko *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
7243c838a9fSAndrew Rybchenko
7253c838a9fSAndrew Rybchenko if (erase_sizep)
7263c838a9fSAndrew Rybchenko *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
7273c838a9fSAndrew Rybchenko
7289cb71b16SAndrew Rybchenko if (write_sizep) {
7299cb71b16SAndrew Rybchenko *write_sizep =
7309cb71b16SAndrew Rybchenko (req.emr_out_length_used <
7319cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
7329cb71b16SAndrew Rybchenko 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
7339cb71b16SAndrew Rybchenko }
7349cb71b16SAndrew Rybchenko
7353c838a9fSAndrew Rybchenko return (0);
7363c838a9fSAndrew Rybchenko
7373c838a9fSAndrew Rybchenko fail2:
7383c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
7393c838a9fSAndrew Rybchenko fail1:
740460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
7413c838a9fSAndrew Rybchenko
7423c838a9fSAndrew Rybchenko return (rc);
7433c838a9fSAndrew Rybchenko }
7443c838a9fSAndrew Rybchenko
745e9c123a5SAndrew Rybchenko /*
746e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
747e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request.
748e9c123a5SAndrew Rybchenko */
749460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_update_start(__in efx_nic_t * enp,__in uint32_t partn)7503c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start(
7513c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
7523c838a9fSAndrew Rybchenko __in uint32_t partn)
7533c838a9fSAndrew Rybchenko {
754315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
755315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_START_OUT_LEN);
7563c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
757460cb568SAndrew Rybchenko efx_rc_t rc;
7583c838a9fSAndrew Rybchenko
7593c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
7603c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
761e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
7623c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
7633c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
7643c838a9fSAndrew Rybchenko
765e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
766e9c123a5SAndrew Rybchenko
767e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
768e9c123a5SAndrew Rybchenko NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
7693c838a9fSAndrew Rybchenko
7703c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
7713c838a9fSAndrew Rybchenko
7723c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
7733c838a9fSAndrew Rybchenko rc = req.emr_rc;
7743c838a9fSAndrew Rybchenko goto fail1;
7753c838a9fSAndrew Rybchenko }
7763c838a9fSAndrew Rybchenko
7773c838a9fSAndrew Rybchenko return (0);
7783c838a9fSAndrew Rybchenko
7793c838a9fSAndrew Rybchenko fail1:
780460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
7813c838a9fSAndrew Rybchenko
7823c838a9fSAndrew Rybchenko return (rc);
7833c838a9fSAndrew Rybchenko }
7843c838a9fSAndrew Rybchenko
785460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_read(__in efx_nic_t * enp,__in uint32_t partn,__in uint32_t offset,__out_bcount (size)caddr_t data,__in size_t size,__in uint32_t mode)7863c838a9fSAndrew Rybchenko efx_mcdi_nvram_read(
7873c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
7883c838a9fSAndrew Rybchenko __in uint32_t partn,
7893c838a9fSAndrew Rybchenko __in uint32_t offset,
7903c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data,
7919ad7e03fSAndrew Rybchenko __in size_t size,
7929ad7e03fSAndrew Rybchenko __in uint32_t mode)
7933c838a9fSAndrew Rybchenko {
7943c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
795315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_READ_IN_V2_LEN,
796315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_READ_OUT_LENMAX);
797460cb568SAndrew Rybchenko efx_rc_t rc;
7983c838a9fSAndrew Rybchenko
7993c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
8003c838a9fSAndrew Rybchenko rc = EINVAL;
8013c838a9fSAndrew Rybchenko goto fail1;
8023c838a9fSAndrew Rybchenko }
8033c838a9fSAndrew Rybchenko
8043c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_READ;
8053c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
8069ad7e03fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
8073c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
8083c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
8093c838a9fSAndrew Rybchenko
8109ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
8119ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
8129ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
8139ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
8143c838a9fSAndrew Rybchenko
8153c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
8163c838a9fSAndrew Rybchenko
8173c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
8183c838a9fSAndrew Rybchenko rc = req.emr_rc;
8193c838a9fSAndrew Rybchenko goto fail1;
8203c838a9fSAndrew Rybchenko }
8213c838a9fSAndrew Rybchenko
8223c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
8233c838a9fSAndrew Rybchenko rc = EMSGSIZE;
8243c838a9fSAndrew Rybchenko goto fail2;
8253c838a9fSAndrew Rybchenko }
8263c838a9fSAndrew Rybchenko
8273c838a9fSAndrew Rybchenko memcpy(data,
8283c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
8293c838a9fSAndrew Rybchenko size);
8303c838a9fSAndrew Rybchenko
8313c838a9fSAndrew Rybchenko return (0);
8323c838a9fSAndrew Rybchenko
8333c838a9fSAndrew Rybchenko fail2:
8343c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
8353c838a9fSAndrew Rybchenko fail1:
836460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
8373c838a9fSAndrew Rybchenko
8383c838a9fSAndrew Rybchenko return (rc);
8393c838a9fSAndrew Rybchenko }
8403c838a9fSAndrew Rybchenko
841460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_erase(__in efx_nic_t * enp,__in uint32_t partn,__in uint32_t offset,__in size_t size)8423c838a9fSAndrew Rybchenko efx_mcdi_nvram_erase(
8433c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
8443c838a9fSAndrew Rybchenko __in uint32_t partn,
8453c838a9fSAndrew Rybchenko __in uint32_t offset,
8463c838a9fSAndrew Rybchenko __in size_t size)
8473c838a9fSAndrew Rybchenko {
8483c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
849315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_ERASE_IN_LEN,
850315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_ERASE_OUT_LEN);
851460cb568SAndrew Rybchenko efx_rc_t rc;
8523c838a9fSAndrew Rybchenko
8533c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_ERASE;
8543c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
8553c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
8563c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
8573c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
8583c838a9fSAndrew Rybchenko
8593c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
8603c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
8613c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
8623c838a9fSAndrew Rybchenko
8633c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
8643c838a9fSAndrew Rybchenko
8653c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
8663c838a9fSAndrew Rybchenko rc = req.emr_rc;
8673c838a9fSAndrew Rybchenko goto fail1;
8683c838a9fSAndrew Rybchenko }
8693c838a9fSAndrew Rybchenko
8703c838a9fSAndrew Rybchenko return (0);
8713c838a9fSAndrew Rybchenko
8723c838a9fSAndrew Rybchenko fail1:
873460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
8743c838a9fSAndrew Rybchenko
8753c838a9fSAndrew Rybchenko return (rc);
8763c838a9fSAndrew Rybchenko }
8773c838a9fSAndrew Rybchenko
87857396b7aSAndrew Rybchenko /*
87957396b7aSAndrew Rybchenko * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
88057396b7aSAndrew Rybchenko * Sienna and EF10 based boards. However EF10 based boards support the use
88157396b7aSAndrew Rybchenko * of this command with payloads up to the maximum MCDI V2 payload length.
88257396b7aSAndrew Rybchenko */
883460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_write(__in efx_nic_t * enp,__in uint32_t partn,__in uint32_t offset,__in_bcount (size)caddr_t data,__in size_t size)8843c838a9fSAndrew Rybchenko efx_mcdi_nvram_write(
8853c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
8863c838a9fSAndrew Rybchenko __in uint32_t partn,
8873c838a9fSAndrew Rybchenko __in uint32_t offset,
888dbcc3c8fSAndrew Rybchenko __in_bcount(size) caddr_t data,
8893c838a9fSAndrew Rybchenko __in size_t size)
8903c838a9fSAndrew Rybchenko {
8913c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
8926b231fecSAndrew Rybchenko uint8_t *payload;
893460cb568SAndrew Rybchenko efx_rc_t rc;
89457396b7aSAndrew Rybchenko size_t max_data_size;
8956b231fecSAndrew Rybchenko size_t payload_len = enp->en_nic_cfg.enc_mcdi_max_payload_length;
8963c838a9fSAndrew Rybchenko
8976b231fecSAndrew Rybchenko max_data_size = payload_len - MC_CMD_NVRAM_WRITE_IN_LEN(0);
8986b231fecSAndrew Rybchenko EFSYS_ASSERT3U(payload_len, >, 0);
8996b231fecSAndrew Rybchenko EFSYS_ASSERT3U(max_data_size, <, payload_len);
90057396b7aSAndrew Rybchenko
90157396b7aSAndrew Rybchenko if (size > max_data_size) {
9023c838a9fSAndrew Rybchenko rc = EINVAL;
9033c838a9fSAndrew Rybchenko goto fail1;
9043c838a9fSAndrew Rybchenko }
9053c838a9fSAndrew Rybchenko
9066b231fecSAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip, payload_len, payload);
9076b231fecSAndrew Rybchenko if (payload == NULL) {
9086b231fecSAndrew Rybchenko rc = ENOMEM;
9096b231fecSAndrew Rybchenko goto fail2;
9106b231fecSAndrew Rybchenko }
9116b231fecSAndrew Rybchenko
9126b231fecSAndrew Rybchenko (void) memset(payload, 0, payload_len);
9133c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_WRITE;
9143c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
9153c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
9163c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
9173c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
9183c838a9fSAndrew Rybchenko
9193c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
9203c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
9213c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
9223c838a9fSAndrew Rybchenko
9233c838a9fSAndrew Rybchenko memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
9243c838a9fSAndrew Rybchenko data, size);
9253c838a9fSAndrew Rybchenko
9263c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
9273c838a9fSAndrew Rybchenko
9283c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
9293c838a9fSAndrew Rybchenko rc = req.emr_rc;
9306b231fecSAndrew Rybchenko goto fail3;
9313c838a9fSAndrew Rybchenko }
9323c838a9fSAndrew Rybchenko
9336b231fecSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
9346b231fecSAndrew Rybchenko
9353c838a9fSAndrew Rybchenko return (0);
9363c838a9fSAndrew Rybchenko
9376b231fecSAndrew Rybchenko fail3:
9386b231fecSAndrew Rybchenko EFSYS_PROBE(fail3);
9396b231fecSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
9403c838a9fSAndrew Rybchenko fail2:
9413c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
9423c838a9fSAndrew Rybchenko fail1:
943460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
9443c838a9fSAndrew Rybchenko
9453c838a9fSAndrew Rybchenko return (rc);
9463c838a9fSAndrew Rybchenko }
9473c838a9fSAndrew Rybchenko
948e9c123a5SAndrew Rybchenko /*
949e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
950e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request.
951e9c123a5SAndrew Rybchenko */
952460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_update_finish(__in efx_nic_t * enp,__in uint32_t partn,__in boolean_t reboot,__out_opt uint32_t * verify_resultp)9533c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish(
9543c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
9553c838a9fSAndrew Rybchenko __in uint32_t partn,
956e9c123a5SAndrew Rybchenko __in boolean_t reboot,
957a21b2f20SAndrew Rybchenko __out_opt uint32_t *verify_resultp)
9583c838a9fSAndrew Rybchenko {
959e9c123a5SAndrew Rybchenko const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
9603c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
961315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
962315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN);
963a21b2f20SAndrew Rybchenko uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
964460cb568SAndrew Rybchenko efx_rc_t rc;
9653c838a9fSAndrew Rybchenko
9663c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
9673c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
968e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
9693c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
970e9c123a5SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
9713c838a9fSAndrew Rybchenko
972e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
973e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
974e9c123a5SAndrew Rybchenko
975e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
976e9c123a5SAndrew Rybchenko NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
9773c838a9fSAndrew Rybchenko
9783c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
9793c838a9fSAndrew Rybchenko
9803c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
9813c838a9fSAndrew Rybchenko rc = req.emr_rc;
9823c838a9fSAndrew Rybchenko goto fail1;
9833c838a9fSAndrew Rybchenko }
9843c838a9fSAndrew Rybchenko
985f0d3455bSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
986a21b2f20SAndrew Rybchenko verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
987348d3529SAndrew Rybchenko if (encp->enc_nvram_update_verify_result_supported) {
988348d3529SAndrew Rybchenko /* Result of update verification is missing */
989e9c123a5SAndrew Rybchenko rc = EMSGSIZE;
990e9c123a5SAndrew Rybchenko goto fail2;
991e9c123a5SAndrew Rybchenko }
992f0d3455bSAndrew Rybchenko } else {
993a21b2f20SAndrew Rybchenko verify_result =
994e9c123a5SAndrew Rybchenko MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
995f0d3455bSAndrew Rybchenko }
996e9c123a5SAndrew Rybchenko
997348d3529SAndrew Rybchenko if ((encp->enc_nvram_update_verify_result_supported) &&
998a21b2f20SAndrew Rybchenko (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
999348d3529SAndrew Rybchenko /* Update verification failed */
1000e9c123a5SAndrew Rybchenko rc = EINVAL;
1001e9c123a5SAndrew Rybchenko goto fail3;
1002e9c123a5SAndrew Rybchenko }
1003e9c123a5SAndrew Rybchenko
1004a21b2f20SAndrew Rybchenko if (verify_resultp != NULL)
1005a21b2f20SAndrew Rybchenko *verify_resultp = verify_result;
1006e9c123a5SAndrew Rybchenko
10073c838a9fSAndrew Rybchenko return (0);
10083c838a9fSAndrew Rybchenko
1009e9c123a5SAndrew Rybchenko fail3:
1010e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail3);
1011e9c123a5SAndrew Rybchenko fail2:
1012e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2);
10133c838a9fSAndrew Rybchenko fail1:
1014460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
10153c838a9fSAndrew Rybchenko
1016e9c123a5SAndrew Rybchenko /* Always report verification result */
1017a21b2f20SAndrew Rybchenko if (verify_resultp != NULL)
1018a21b2f20SAndrew Rybchenko *verify_resultp = verify_result;
1019e9c123a5SAndrew Rybchenko
10203c838a9fSAndrew Rybchenko return (rc);
10213c838a9fSAndrew Rybchenko }
10223c838a9fSAndrew Rybchenko
10233c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG
10243c838a9fSAndrew Rybchenko
1025460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mcdi_nvram_test(__in efx_nic_t * enp,__in uint32_t partn)10263c838a9fSAndrew Rybchenko efx_mcdi_nvram_test(
10273c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
10283c838a9fSAndrew Rybchenko __in uint32_t partn)
10293c838a9fSAndrew Rybchenko {
10303c838a9fSAndrew Rybchenko efx_mcdi_req_t req;
1031315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TEST_IN_LEN,
1032315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_TEST_OUT_LEN);
10333c838a9fSAndrew Rybchenko int result;
1034460cb568SAndrew Rybchenko efx_rc_t rc;
10353c838a9fSAndrew Rybchenko
10363c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_TEST;
10373c838a9fSAndrew Rybchenko req.emr_in_buf = payload;
10383c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
10393c838a9fSAndrew Rybchenko req.emr_out_buf = payload;
10403c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
10413c838a9fSAndrew Rybchenko
10423c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
10433c838a9fSAndrew Rybchenko
10443c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req);
10453c838a9fSAndrew Rybchenko
10463c838a9fSAndrew Rybchenko if (req.emr_rc != 0) {
10473c838a9fSAndrew Rybchenko rc = req.emr_rc;
10483c838a9fSAndrew Rybchenko goto fail1;
10493c838a9fSAndrew Rybchenko }
10503c838a9fSAndrew Rybchenko
10513c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
10523c838a9fSAndrew Rybchenko rc = EMSGSIZE;
10533c838a9fSAndrew Rybchenko goto fail2;
10543c838a9fSAndrew Rybchenko }
10553c838a9fSAndrew Rybchenko
10563c838a9fSAndrew Rybchenko result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
10573c838a9fSAndrew Rybchenko if (result == MC_CMD_NVRAM_TEST_FAIL) {
10583c838a9fSAndrew Rybchenko EFSYS_PROBE1(nvram_test_failure, int, partn);
10593c838a9fSAndrew Rybchenko
10603c838a9fSAndrew Rybchenko rc = (EINVAL);
10613c838a9fSAndrew Rybchenko goto fail3;
10623c838a9fSAndrew Rybchenko }
10633c838a9fSAndrew Rybchenko
10643c838a9fSAndrew Rybchenko return (0);
10653c838a9fSAndrew Rybchenko
10663c838a9fSAndrew Rybchenko fail3:
10673c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
10683c838a9fSAndrew Rybchenko fail2:
10693c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
10703c838a9fSAndrew Rybchenko fail1:
1071460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
10723c838a9fSAndrew Rybchenko
10733c838a9fSAndrew Rybchenko return (rc);
10743c838a9fSAndrew Rybchenko }
10753c838a9fSAndrew Rybchenko
10763c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */
10773c838a9fSAndrew Rybchenko
10783c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */
1079