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> 345dee87d7SPhilip Paeps __FBSDID("$FreeBSD$"); 355dee87d7SPhilip Paeps 36e948693eSPhilip Paeps #include "efx.h" 37e948693eSPhilip Paeps #include "efx_impl.h" 38e948693eSPhilip Paeps 39e948693eSPhilip Paeps #if EFSYS_OPT_NVRAM 40e948693eSPhilip Paeps 41e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 42e948693eSPhilip Paeps 43ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_siena_ops = { 44e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 45e948693eSPhilip Paeps siena_nvram_test, /* envo_test */ 46e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 47bce88e31SAndrew Rybchenko siena_nvram_type_to_partn, /* envo_type_to_partn */ 4856bd83b0SAndrew Rybchenko siena_nvram_partn_size, /* envo_partn_size */ 495d846e87SAndrew Rybchenko siena_nvram_partn_rw_start, /* envo_partn_rw_start */ 500afdf29cSAndrew Rybchenko siena_nvram_partn_read, /* envo_partn_read */ 51ede1a3edSAndrew Rybchenko siena_nvram_partn_read, /* envo_partn_read_backup */ 52b60ff840SAndrew Rybchenko siena_nvram_partn_erase, /* envo_partn_erase */ 53134c4c4aSAndrew Rybchenko siena_nvram_partn_write, /* envo_partn_write */ 54eb9703daSAndrew Rybchenko siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 5592187119SAndrew Rybchenko siena_nvram_partn_get_version, /* envo_partn_get_version */ 566d0b856cSAndrew Rybchenko siena_nvram_partn_set_version, /* envo_partn_set_version */ 575abce2b9SAndrew Rybchenko NULL, /* envo_partn_validate */ 58e948693eSPhilip Paeps }; 59e948693eSPhilip Paeps 60e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 61e948693eSPhilip Paeps 62824c97edSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 633c838a9fSAndrew Rybchenko 64ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_ef10_ops = { 653c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 66de9775adSAndrew Rybchenko ef10_nvram_test, /* envo_test */ 673c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 68bce88e31SAndrew Rybchenko ef10_nvram_type_to_partn, /* envo_type_to_partn */ 6956bd83b0SAndrew Rybchenko ef10_nvram_partn_size, /* envo_partn_size */ 705d846e87SAndrew Rybchenko ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ 710afdf29cSAndrew Rybchenko ef10_nvram_partn_read, /* envo_partn_read */ 72ede1a3edSAndrew Rybchenko ef10_nvram_partn_read_backup, /* envo_partn_read_backup */ 73b60ff840SAndrew Rybchenko ef10_nvram_partn_erase, /* envo_partn_erase */ 74134c4c4aSAndrew Rybchenko ef10_nvram_partn_write, /* envo_partn_write */ 75eb9703daSAndrew Rybchenko ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 7692187119SAndrew Rybchenko ef10_nvram_partn_get_version, /* envo_partn_get_version */ 776d0b856cSAndrew Rybchenko ef10_nvram_partn_set_version, /* envo_partn_set_version */ 785abce2b9SAndrew Rybchenko ef10_nvram_buffer_validate, /* envo_buffer_validate */ 793c838a9fSAndrew Rybchenko }; 803c838a9fSAndrew Rybchenko 81824c97edSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 823c838a9fSAndrew Rybchenko 83460cb568SAndrew Rybchenko __checkReturn efx_rc_t 84e948693eSPhilip Paeps efx_nvram_init( 85e948693eSPhilip Paeps __in efx_nic_t *enp) 86e948693eSPhilip Paeps { 87ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop; 88460cb568SAndrew Rybchenko efx_rc_t rc; 89e948693eSPhilip Paeps 90e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 91e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 92e948693eSPhilip Paeps EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 93e948693eSPhilip Paeps 94e948693eSPhilip Paeps switch (enp->en_family) { 95e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 96e948693eSPhilip Paeps case EFX_FAMILY_SIENA: 97ec831f7fSAndrew Rybchenko envop = &__efx_nvram_siena_ops; 98e948693eSPhilip Paeps break; 99e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 100e948693eSPhilip Paeps 1013c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 1023c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 103ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops; 1043c838a9fSAndrew Rybchenko break; 1053c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 1063c838a9fSAndrew Rybchenko 107de9775adSAndrew Rybchenko #if EFSYS_OPT_MEDFORD 108de9775adSAndrew Rybchenko case EFX_FAMILY_MEDFORD: 109ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops; 110de9775adSAndrew Rybchenko break; 111de9775adSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */ 112de9775adSAndrew Rybchenko 113824c97edSAndrew Rybchenko #if EFSYS_OPT_MEDFORD2 114824c97edSAndrew Rybchenko case EFX_FAMILY_MEDFORD2: 115824c97edSAndrew Rybchenko envop = &__efx_nvram_ef10_ops; 116824c97edSAndrew Rybchenko break; 117824c97edSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */ 118824c97edSAndrew Rybchenko 119e948693eSPhilip Paeps default: 120e948693eSPhilip Paeps EFSYS_ASSERT(0); 121e948693eSPhilip Paeps rc = ENOTSUP; 122e948693eSPhilip Paeps goto fail1; 123e948693eSPhilip Paeps } 124e948693eSPhilip Paeps 125e948693eSPhilip Paeps enp->en_envop = envop; 126e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_NVRAM; 127e948693eSPhilip Paeps 1283d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 1293d670ff5SAndrew Rybchenko 130e948693eSPhilip Paeps return (0); 131e948693eSPhilip Paeps 132e948693eSPhilip Paeps fail1: 133460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 134e948693eSPhilip Paeps 135e948693eSPhilip Paeps return (rc); 136e948693eSPhilip Paeps } 137e948693eSPhilip Paeps 138e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 139e948693eSPhilip Paeps 140460cb568SAndrew Rybchenko __checkReturn efx_rc_t 141e948693eSPhilip Paeps efx_nvram_test( 142e948693eSPhilip Paeps __in efx_nic_t *enp) 143e948693eSPhilip Paeps { 144ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 145460cb568SAndrew Rybchenko efx_rc_t rc; 146e948693eSPhilip Paeps 147e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 148e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 149e948693eSPhilip Paeps 150e948693eSPhilip Paeps if ((rc = envop->envo_test(enp)) != 0) 151e948693eSPhilip Paeps goto fail1; 152e948693eSPhilip Paeps 153e948693eSPhilip Paeps return (0); 154e948693eSPhilip Paeps 155e948693eSPhilip Paeps fail1: 156460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 157e948693eSPhilip Paeps 158e948693eSPhilip Paeps return (rc); 159e948693eSPhilip Paeps } 160e948693eSPhilip Paeps 161e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 162e948693eSPhilip Paeps 163460cb568SAndrew Rybchenko __checkReturn efx_rc_t 164e948693eSPhilip Paeps efx_nvram_size( 165e948693eSPhilip Paeps __in efx_nic_t *enp, 166e948693eSPhilip Paeps __in efx_nvram_type_t type, 167e948693eSPhilip Paeps __out size_t *sizep) 168e948693eSPhilip Paeps { 169ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 17056bd83b0SAndrew Rybchenko uint32_t partn; 171460cb568SAndrew Rybchenko efx_rc_t rc; 172e948693eSPhilip Paeps 173e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 174e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 175e948693eSPhilip Paeps 17656bd83b0SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 177e948693eSPhilip Paeps goto fail1; 178e948693eSPhilip Paeps 17956bd83b0SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0) 18056bd83b0SAndrew Rybchenko goto fail2; 18156bd83b0SAndrew Rybchenko 182e948693eSPhilip Paeps return (0); 183e948693eSPhilip Paeps 18456bd83b0SAndrew Rybchenko fail2: 18556bd83b0SAndrew Rybchenko EFSYS_PROBE(fail2); 186e948693eSPhilip Paeps fail1: 187460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 18856bd83b0SAndrew Rybchenko *sizep = 0; 189e948693eSPhilip Paeps 190e948693eSPhilip Paeps return (rc); 191e948693eSPhilip Paeps } 192e948693eSPhilip Paeps 193460cb568SAndrew Rybchenko __checkReturn efx_rc_t 194e948693eSPhilip Paeps efx_nvram_get_version( 195e948693eSPhilip Paeps __in efx_nic_t *enp, 196e948693eSPhilip Paeps __in efx_nvram_type_t type, 197e948693eSPhilip Paeps __out uint32_t *subtypep, 198e948693eSPhilip Paeps __out_ecount(4) uint16_t version[4]) 199e948693eSPhilip Paeps { 200ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 20192187119SAndrew Rybchenko uint32_t partn; 202460cb568SAndrew Rybchenko efx_rc_t rc; 203e948693eSPhilip Paeps 204e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 205e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 206e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 207e948693eSPhilip Paeps 20892187119SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 209e948693eSPhilip Paeps goto fail1; 210e948693eSPhilip Paeps 21192187119SAndrew Rybchenko if ((rc = envop->envo_partn_get_version(enp, partn, 21292187119SAndrew Rybchenko subtypep, version)) != 0) 21392187119SAndrew Rybchenko goto fail2; 21492187119SAndrew Rybchenko 215e948693eSPhilip Paeps return (0); 216e948693eSPhilip Paeps 21792187119SAndrew Rybchenko fail2: 21892187119SAndrew Rybchenko EFSYS_PROBE(fail2); 219e948693eSPhilip Paeps fail1: 220460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 221e948693eSPhilip Paeps 222e948693eSPhilip Paeps return (rc); 223e948693eSPhilip Paeps } 224e948693eSPhilip Paeps 225460cb568SAndrew Rybchenko __checkReturn efx_rc_t 226e948693eSPhilip Paeps efx_nvram_rw_start( 227e948693eSPhilip Paeps __in efx_nic_t *enp, 228e948693eSPhilip Paeps __in efx_nvram_type_t type, 229e948693eSPhilip Paeps __out_opt size_t *chunk_sizep) 230e948693eSPhilip Paeps { 231ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2325d846e87SAndrew Rybchenko uint32_t partn; 233460cb568SAndrew Rybchenko efx_rc_t rc; 234e948693eSPhilip Paeps 235e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 236e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 237e948693eSPhilip Paeps 2385d846e87SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 239e948693eSPhilip Paeps goto fail1; 240e948693eSPhilip Paeps 2413d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 2423d670ff5SAndrew Rybchenko 2435d846e87SAndrew Rybchenko if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) 2445d846e87SAndrew Rybchenko goto fail2; 2455d846e87SAndrew Rybchenko 2463d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = partn; 247e948693eSPhilip Paeps 248e948693eSPhilip Paeps return (0); 249e948693eSPhilip Paeps 2505d846e87SAndrew Rybchenko fail2: 2515d846e87SAndrew Rybchenko EFSYS_PROBE(fail2); 252e948693eSPhilip Paeps fail1: 253460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 254e948693eSPhilip Paeps 255e948693eSPhilip Paeps return (rc); 256e948693eSPhilip Paeps } 257e948693eSPhilip Paeps 258460cb568SAndrew Rybchenko __checkReturn efx_rc_t 259e948693eSPhilip Paeps efx_nvram_read_chunk( 260e948693eSPhilip Paeps __in efx_nic_t *enp, 261e948693eSPhilip Paeps __in efx_nvram_type_t type, 262e948693eSPhilip Paeps __in unsigned int offset, 263e948693eSPhilip Paeps __out_bcount(size) caddr_t data, 264e948693eSPhilip Paeps __in size_t size) 265e948693eSPhilip Paeps { 266ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2670afdf29cSAndrew Rybchenko uint32_t partn; 268460cb568SAndrew Rybchenko efx_rc_t rc; 269e948693eSPhilip Paeps 270e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 271e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 272e948693eSPhilip Paeps 2730afdf29cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 274e948693eSPhilip Paeps goto fail1; 275e948693eSPhilip Paeps 2763d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 2773d670ff5SAndrew Rybchenko 2780afdf29cSAndrew Rybchenko if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) 2790afdf29cSAndrew Rybchenko goto fail2; 2800afdf29cSAndrew Rybchenko 281e948693eSPhilip Paeps return (0); 282e948693eSPhilip Paeps 2830afdf29cSAndrew Rybchenko fail2: 2840afdf29cSAndrew Rybchenko EFSYS_PROBE(fail2); 285e948693eSPhilip Paeps fail1: 286460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 287e948693eSPhilip Paeps 288e948693eSPhilip Paeps return (rc); 289e948693eSPhilip Paeps } 290e948693eSPhilip Paeps 291ede1a3edSAndrew Rybchenko /* 292ede1a3edSAndrew Rybchenko * Read from the backup (writeable) store of an A/B partition. 293ede1a3edSAndrew Rybchenko * For non A/B partitions, there is only a single store, and so this 294ede1a3edSAndrew Rybchenko * function has the same behaviour as efx_nvram_read_chunk(). 295ede1a3edSAndrew Rybchenko */ 296ede1a3edSAndrew Rybchenko __checkReturn efx_rc_t 297ede1a3edSAndrew Rybchenko efx_nvram_read_backup( 298ede1a3edSAndrew Rybchenko __in efx_nic_t *enp, 299ede1a3edSAndrew Rybchenko __in efx_nvram_type_t type, 300ede1a3edSAndrew Rybchenko __in unsigned int offset, 301ede1a3edSAndrew Rybchenko __out_bcount(size) caddr_t data, 302ede1a3edSAndrew Rybchenko __in size_t size) 303ede1a3edSAndrew Rybchenko { 304ede1a3edSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 305ede1a3edSAndrew Rybchenko uint32_t partn; 306ede1a3edSAndrew Rybchenko efx_rc_t rc; 307ede1a3edSAndrew Rybchenko 308ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 309ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 310ede1a3edSAndrew Rybchenko 311ede1a3edSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 312ede1a3edSAndrew Rybchenko goto fail1; 313ede1a3edSAndrew Rybchenko 314ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 315ede1a3edSAndrew Rybchenko 316ede1a3edSAndrew Rybchenko if ((rc = envop->envo_partn_read_backup(enp, partn, offset, 317ede1a3edSAndrew Rybchenko data, size)) != 0) 318ede1a3edSAndrew Rybchenko goto fail2; 319ede1a3edSAndrew Rybchenko 320ede1a3edSAndrew Rybchenko return (0); 321ede1a3edSAndrew Rybchenko 322ede1a3edSAndrew Rybchenko fail2: 323ede1a3edSAndrew Rybchenko EFSYS_PROBE(fail2); 324ede1a3edSAndrew Rybchenko fail1: 325ede1a3edSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 326ede1a3edSAndrew Rybchenko 327ede1a3edSAndrew Rybchenko return (rc); 328ede1a3edSAndrew Rybchenko } 329ede1a3edSAndrew Rybchenko 330460cb568SAndrew Rybchenko __checkReturn efx_rc_t 331e948693eSPhilip Paeps efx_nvram_erase( 332e948693eSPhilip Paeps __in efx_nic_t *enp, 333e948693eSPhilip Paeps __in efx_nvram_type_t type) 334e948693eSPhilip Paeps { 335ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 336b60ff840SAndrew Rybchenko unsigned int offset = 0; 337b60ff840SAndrew Rybchenko size_t size = 0; 338b60ff840SAndrew Rybchenko uint32_t partn; 339460cb568SAndrew Rybchenko efx_rc_t rc; 340e948693eSPhilip Paeps 341e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 342e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 343e948693eSPhilip Paeps 344b60ff840SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 345e948693eSPhilip Paeps goto fail1; 346e948693eSPhilip Paeps 3473d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 3483d670ff5SAndrew Rybchenko 349b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0) 350b60ff840SAndrew Rybchenko goto fail2; 351b60ff840SAndrew Rybchenko 352b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0) 353b60ff840SAndrew Rybchenko goto fail3; 354b60ff840SAndrew Rybchenko 355e948693eSPhilip Paeps return (0); 356e948693eSPhilip Paeps 357b60ff840SAndrew Rybchenko fail3: 358b60ff840SAndrew Rybchenko EFSYS_PROBE(fail3); 359b60ff840SAndrew Rybchenko fail2: 360b60ff840SAndrew Rybchenko EFSYS_PROBE(fail2); 361e948693eSPhilip Paeps fail1: 362460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 363e948693eSPhilip Paeps 364e948693eSPhilip Paeps return (rc); 365e948693eSPhilip Paeps } 366e948693eSPhilip Paeps 367460cb568SAndrew Rybchenko __checkReturn efx_rc_t 368e948693eSPhilip Paeps efx_nvram_write_chunk( 369e948693eSPhilip Paeps __in efx_nic_t *enp, 370e948693eSPhilip Paeps __in efx_nvram_type_t type, 371e948693eSPhilip Paeps __in unsigned int offset, 372e948693eSPhilip Paeps __in_bcount(size) caddr_t data, 373e948693eSPhilip Paeps __in size_t size) 374e948693eSPhilip Paeps { 375ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 376134c4c4aSAndrew Rybchenko uint32_t partn; 377460cb568SAndrew Rybchenko efx_rc_t rc; 378e948693eSPhilip Paeps 379e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 380e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 381e948693eSPhilip Paeps 382134c4c4aSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 383e948693eSPhilip Paeps goto fail1; 384e948693eSPhilip Paeps 3853d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 3863d670ff5SAndrew Rybchenko 387134c4c4aSAndrew Rybchenko if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0) 388134c4c4aSAndrew Rybchenko goto fail2; 389134c4c4aSAndrew Rybchenko 390e948693eSPhilip Paeps return (0); 391e948693eSPhilip Paeps 392134c4c4aSAndrew Rybchenko fail2: 393134c4c4aSAndrew Rybchenko EFSYS_PROBE(fail2); 394e948693eSPhilip Paeps fail1: 395460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 396e948693eSPhilip Paeps 397e948693eSPhilip Paeps return (rc); 398e948693eSPhilip Paeps } 399e948693eSPhilip Paeps 400e9c123a5SAndrew Rybchenko __checkReturn efx_rc_t 401e948693eSPhilip Paeps efx_nvram_rw_finish( 402e948693eSPhilip Paeps __in efx_nic_t *enp, 403d5106d05SAndrew Rybchenko __in efx_nvram_type_t type, 404d5106d05SAndrew Rybchenko __out_opt uint32_t *verify_resultp) 405e948693eSPhilip Paeps { 406ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 407eb9703daSAndrew Rybchenko uint32_t partn; 408d5106d05SAndrew Rybchenko uint32_t verify_result = 0; 409e9c123a5SAndrew Rybchenko efx_rc_t rc; 410e948693eSPhilip Paeps 411e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 412e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 413e948693eSPhilip Paeps 414e9c123a5SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 415e9c123a5SAndrew Rybchenko goto fail1; 416e9c123a5SAndrew Rybchenko 4173d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 4183d670ff5SAndrew Rybchenko 419a21b2f20SAndrew Rybchenko if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0) 420e9c123a5SAndrew Rybchenko goto fail2; 421e948693eSPhilip Paeps 4223d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 423e9c123a5SAndrew Rybchenko 424d5106d05SAndrew Rybchenko if (verify_resultp != NULL) 425d5106d05SAndrew Rybchenko *verify_resultp = verify_result; 426d5106d05SAndrew Rybchenko 427e9c123a5SAndrew Rybchenko return (0); 428e9c123a5SAndrew Rybchenko 429e9c123a5SAndrew Rybchenko fail2: 430e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 4313d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 432e9c123a5SAndrew Rybchenko 433e9c123a5SAndrew Rybchenko fail1: 434e9c123a5SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 435e9c123a5SAndrew Rybchenko 436d5106d05SAndrew Rybchenko /* Always report verification result */ 437d5106d05SAndrew Rybchenko if (verify_resultp != NULL) 438d5106d05SAndrew Rybchenko *verify_resultp = verify_result; 439d5106d05SAndrew Rybchenko 440e9c123a5SAndrew Rybchenko return (rc); 441e948693eSPhilip Paeps } 442e948693eSPhilip Paeps 443460cb568SAndrew Rybchenko __checkReturn efx_rc_t 444e948693eSPhilip Paeps efx_nvram_set_version( 445e948693eSPhilip Paeps __in efx_nic_t *enp, 446e948693eSPhilip Paeps __in efx_nvram_type_t type, 4473c838a9fSAndrew Rybchenko __in_ecount(4) uint16_t version[4]) 448e948693eSPhilip Paeps { 449ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4506d0b856cSAndrew Rybchenko uint32_t partn; 451460cb568SAndrew Rybchenko efx_rc_t rc; 452e948693eSPhilip Paeps 453e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 454e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 455e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 456e948693eSPhilip Paeps 4576d0b856cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 458e948693eSPhilip Paeps goto fail1; 459e948693eSPhilip Paeps 4603d670ff5SAndrew Rybchenko /* 4613d670ff5SAndrew Rybchenko * The Siena implementation of envo_set_version() will attempt to 4623d670ff5SAndrew Rybchenko * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition. 4633d670ff5SAndrew Rybchenko * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 4643d670ff5SAndrew Rybchenko */ 4653d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 4663d670ff5SAndrew Rybchenko 4676d0b856cSAndrew Rybchenko if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0) 4686d0b856cSAndrew Rybchenko goto fail2; 4696d0b856cSAndrew Rybchenko 470e948693eSPhilip Paeps return (0); 471e948693eSPhilip Paeps 4726d0b856cSAndrew Rybchenko fail2: 4736d0b856cSAndrew Rybchenko EFSYS_PROBE(fail2); 474e948693eSPhilip Paeps fail1: 475460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 476e948693eSPhilip Paeps 477e948693eSPhilip Paeps return (rc); 478e948693eSPhilip Paeps } 479e948693eSPhilip Paeps 4805abce2b9SAndrew Rybchenko /* Validate buffer contents (before writing to flash) */ 4815abce2b9SAndrew Rybchenko __checkReturn efx_rc_t 4825abce2b9SAndrew Rybchenko efx_nvram_validate( 4835abce2b9SAndrew Rybchenko __in efx_nic_t *enp, 4845abce2b9SAndrew Rybchenko __in efx_nvram_type_t type, 4855abce2b9SAndrew Rybchenko __in_bcount(partn_size) caddr_t partn_data, 4865abce2b9SAndrew Rybchenko __in size_t partn_size) 4875abce2b9SAndrew Rybchenko { 488ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4895abce2b9SAndrew Rybchenko uint32_t partn; 4905abce2b9SAndrew Rybchenko efx_rc_t rc; 4915abce2b9SAndrew Rybchenko 4925abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4935abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 4945abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 4955abce2b9SAndrew Rybchenko 4965abce2b9SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 4975abce2b9SAndrew Rybchenko goto fail1; 4985abce2b9SAndrew Rybchenko 4996a869fecSAndrew Rybchenko if (envop->envo_buffer_validate != NULL) { 500e919b7ecSAndrew Rybchenko if ((rc = envop->envo_buffer_validate(partn, 5016a869fecSAndrew Rybchenko partn_data, partn_size)) != 0) 5025abce2b9SAndrew Rybchenko goto fail2; 5036a869fecSAndrew Rybchenko } 5045abce2b9SAndrew Rybchenko 5055abce2b9SAndrew Rybchenko return (0); 5065abce2b9SAndrew Rybchenko 5075abce2b9SAndrew Rybchenko fail2: 5085abce2b9SAndrew Rybchenko EFSYS_PROBE(fail2); 5095abce2b9SAndrew Rybchenko fail1: 5105abce2b9SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5115abce2b9SAndrew Rybchenko 5125abce2b9SAndrew Rybchenko return (rc); 5135abce2b9SAndrew Rybchenko } 5145abce2b9SAndrew Rybchenko 515e948693eSPhilip Paeps void 516e948693eSPhilip Paeps efx_nvram_fini( 517e948693eSPhilip Paeps __in efx_nic_t *enp) 518e948693eSPhilip Paeps { 519e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 520e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 521e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 522e948693eSPhilip Paeps 5233d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 524e948693eSPhilip Paeps 525e948693eSPhilip Paeps enp->en_envop = NULL; 526e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_NVRAM; 527e948693eSPhilip Paeps } 528e948693eSPhilip Paeps 529e948693eSPhilip Paeps #endif /* EFSYS_OPT_NVRAM */ 5303c838a9fSAndrew Rybchenko 5313c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 5323c838a9fSAndrew Rybchenko 5333c838a9fSAndrew Rybchenko /* 5343c838a9fSAndrew Rybchenko * Internal MCDI request handling 5353c838a9fSAndrew Rybchenko */ 5363c838a9fSAndrew Rybchenko 537460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5383c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions( 5393c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5403c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 5413c838a9fSAndrew Rybchenko __in size_t size, 5423c838a9fSAndrew Rybchenko __out unsigned int *npartnp) 5433c838a9fSAndrew Rybchenko { 5443c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 545315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_PARTITIONS_IN_LEN, 546315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX); 5473c838a9fSAndrew Rybchenko unsigned int npartn; 548460cb568SAndrew Rybchenko efx_rc_t rc; 5493c838a9fSAndrew Rybchenko 5503c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 5513c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5523c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 5533c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5543c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 5553c838a9fSAndrew Rybchenko 5563c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 5573c838a9fSAndrew Rybchenko 5583c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 5593c838a9fSAndrew Rybchenko rc = req.emr_rc; 5603c838a9fSAndrew Rybchenko goto fail1; 5613c838a9fSAndrew Rybchenko } 5623c838a9fSAndrew Rybchenko 5633c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 5643c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5653c838a9fSAndrew Rybchenko goto fail2; 5663c838a9fSAndrew Rybchenko } 5673c838a9fSAndrew Rybchenko npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 5683c838a9fSAndrew Rybchenko 5693c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 5703c838a9fSAndrew Rybchenko rc = ENOENT; 5713c838a9fSAndrew Rybchenko goto fail3; 5723c838a9fSAndrew Rybchenko } 5733c838a9fSAndrew Rybchenko 5743c838a9fSAndrew Rybchenko if (size < npartn * sizeof (uint32_t)) { 5753c838a9fSAndrew Rybchenko rc = ENOSPC; 5763c838a9fSAndrew Rybchenko goto fail3; 5773c838a9fSAndrew Rybchenko } 5783c838a9fSAndrew Rybchenko 5793c838a9fSAndrew Rybchenko *npartnp = npartn; 5803c838a9fSAndrew Rybchenko 5813c838a9fSAndrew Rybchenko memcpy(data, 5823c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 5833c838a9fSAndrew Rybchenko (npartn * sizeof (uint32_t))); 5843c838a9fSAndrew Rybchenko 5853c838a9fSAndrew Rybchenko return (0); 5863c838a9fSAndrew Rybchenko 5873c838a9fSAndrew Rybchenko fail3: 5883c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 5893c838a9fSAndrew Rybchenko fail2: 5903c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 5913c838a9fSAndrew Rybchenko fail1: 592460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5933c838a9fSAndrew Rybchenko 5943c838a9fSAndrew Rybchenko return (rc); 5953c838a9fSAndrew Rybchenko } 5963c838a9fSAndrew Rybchenko 597460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5983c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata( 5993c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6003c838a9fSAndrew Rybchenko __in uint32_t partn, 6013c838a9fSAndrew Rybchenko __out uint32_t *subtypep, 6023c838a9fSAndrew Rybchenko __out_ecount(4) uint16_t version[4], 6033c838a9fSAndrew Rybchenko __out_bcount_opt(size) char *descp, 6043c838a9fSAndrew Rybchenko __in size_t size) 6053c838a9fSAndrew Rybchenko { 6063c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 607315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_METADATA_IN_LEN, 608315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_LENMAX); 609460cb568SAndrew Rybchenko efx_rc_t rc; 6103c838a9fSAndrew Rybchenko 6113c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_METADATA; 6123c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 6133c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 6143c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 6153c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 6163c838a9fSAndrew Rybchenko 6173c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 6183c838a9fSAndrew Rybchenko 619e7144483SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 6203c838a9fSAndrew Rybchenko 6213c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6223c838a9fSAndrew Rybchenko rc = req.emr_rc; 6233c838a9fSAndrew Rybchenko goto fail1; 6243c838a9fSAndrew Rybchenko } 6253c838a9fSAndrew Rybchenko 6263c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 6273c838a9fSAndrew Rybchenko rc = EMSGSIZE; 6283c838a9fSAndrew Rybchenko goto fail2; 6293c838a9fSAndrew Rybchenko } 6303c838a9fSAndrew Rybchenko 6313c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6323c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 6333c838a9fSAndrew Rybchenko *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 6343c838a9fSAndrew Rybchenko } else { 6353c838a9fSAndrew Rybchenko *subtypep = 0; 6363c838a9fSAndrew Rybchenko } 6373c838a9fSAndrew Rybchenko 6383c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6393c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_VERSION_VALID)) { 6403c838a9fSAndrew Rybchenko version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 6413c838a9fSAndrew Rybchenko version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 6423c838a9fSAndrew Rybchenko version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 6433c838a9fSAndrew Rybchenko version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 6443c838a9fSAndrew Rybchenko } else { 6453c838a9fSAndrew Rybchenko version[0] = version[1] = version[2] = version[3] = 0; 6463c838a9fSAndrew Rybchenko } 6473c838a9fSAndrew Rybchenko 6483c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6493c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 6503c838a9fSAndrew Rybchenko /* Return optional descrition string */ 6513c838a9fSAndrew Rybchenko if ((descp != NULL) && (size > 0)) { 6523c838a9fSAndrew Rybchenko size_t desclen; 6533c838a9fSAndrew Rybchenko 6543c838a9fSAndrew Rybchenko descp[0] = '\0'; 6553c838a9fSAndrew Rybchenko desclen = (req.emr_out_length_used 6563c838a9fSAndrew Rybchenko - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 6573c838a9fSAndrew Rybchenko 6583c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(desclen, <=, 6593c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 6603c838a9fSAndrew Rybchenko 6613c838a9fSAndrew Rybchenko if (size < desclen) { 6623c838a9fSAndrew Rybchenko rc = ENOSPC; 6633c838a9fSAndrew Rybchenko goto fail3; 6643c838a9fSAndrew Rybchenko } 6653c838a9fSAndrew Rybchenko 6663c838a9fSAndrew Rybchenko memcpy(descp, MCDI_OUT2(req, char, 6673c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION), 6683c838a9fSAndrew Rybchenko desclen); 6693c838a9fSAndrew Rybchenko 6703c838a9fSAndrew Rybchenko /* Ensure string is NUL terminated */ 6713c838a9fSAndrew Rybchenko descp[desclen] = '\0'; 6723c838a9fSAndrew Rybchenko } 6733c838a9fSAndrew Rybchenko } 6743c838a9fSAndrew Rybchenko 6753c838a9fSAndrew Rybchenko return (0); 6763c838a9fSAndrew Rybchenko 6773c838a9fSAndrew Rybchenko fail3: 6783c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 6793c838a9fSAndrew Rybchenko fail2: 6803c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 6813c838a9fSAndrew Rybchenko fail1: 682460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 6833c838a9fSAndrew Rybchenko 6843c838a9fSAndrew Rybchenko return (rc); 6853c838a9fSAndrew Rybchenko } 6863c838a9fSAndrew Rybchenko 687460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6883c838a9fSAndrew Rybchenko efx_mcdi_nvram_info( 6893c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6903c838a9fSAndrew Rybchenko __in uint32_t partn, 6913c838a9fSAndrew Rybchenko __out_opt size_t *sizep, 6923c838a9fSAndrew Rybchenko __out_opt uint32_t *addressp, 6939cb71b16SAndrew Rybchenko __out_opt uint32_t *erase_sizep, 6949cb71b16SAndrew Rybchenko __out_opt uint32_t *write_sizep) 6953c838a9fSAndrew Rybchenko { 696315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_INFO_IN_LEN, 697315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN); 6983c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 699460cb568SAndrew Rybchenko efx_rc_t rc; 7003c838a9fSAndrew Rybchenko 7013c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_INFO; 7023c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 7033c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 7043c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7059cb71b16SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN; 7063c838a9fSAndrew Rybchenko 7073c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 7083c838a9fSAndrew Rybchenko 7093c838a9fSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 7103c838a9fSAndrew Rybchenko 7113c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7123c838a9fSAndrew Rybchenko rc = req.emr_rc; 7133c838a9fSAndrew Rybchenko goto fail1; 7143c838a9fSAndrew Rybchenko } 7153c838a9fSAndrew Rybchenko 7163c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 7173c838a9fSAndrew Rybchenko rc = EMSGSIZE; 7183c838a9fSAndrew Rybchenko goto fail2; 7193c838a9fSAndrew Rybchenko } 7203c838a9fSAndrew Rybchenko 7213c838a9fSAndrew Rybchenko if (sizep) 7223c838a9fSAndrew Rybchenko *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 7233c838a9fSAndrew Rybchenko 7243c838a9fSAndrew Rybchenko if (addressp) 7253c838a9fSAndrew Rybchenko *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 7263c838a9fSAndrew Rybchenko 7273c838a9fSAndrew Rybchenko if (erase_sizep) 7283c838a9fSAndrew Rybchenko *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 7293c838a9fSAndrew Rybchenko 7309cb71b16SAndrew Rybchenko if (write_sizep) { 7319cb71b16SAndrew Rybchenko *write_sizep = 7329cb71b16SAndrew Rybchenko (req.emr_out_length_used < 7339cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN) ? 7349cb71b16SAndrew Rybchenko 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE); 7359cb71b16SAndrew Rybchenko } 7369cb71b16SAndrew Rybchenko 7373c838a9fSAndrew Rybchenko return (0); 7383c838a9fSAndrew Rybchenko 7393c838a9fSAndrew Rybchenko fail2: 7403c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 7413c838a9fSAndrew Rybchenko fail1: 742460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7433c838a9fSAndrew Rybchenko 7443c838a9fSAndrew Rybchenko return (rc); 7453c838a9fSAndrew Rybchenko } 7463c838a9fSAndrew Rybchenko 747e9c123a5SAndrew Rybchenko /* 748e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified 749e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 750e9c123a5SAndrew Rybchenko */ 751460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7523c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start( 7533c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7543c838a9fSAndrew Rybchenko __in uint32_t partn) 7553c838a9fSAndrew Rybchenko { 756315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN, 757315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_START_OUT_LEN); 7583c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 759460cb568SAndrew Rybchenko efx_rc_t rc; 7603c838a9fSAndrew Rybchenko 7613c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 7623c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 763e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN; 7643c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7653c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 7663c838a9fSAndrew Rybchenko 767e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn); 768e9c123a5SAndrew Rybchenko 769e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS, 770e9c123a5SAndrew Rybchenko NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 7713c838a9fSAndrew Rybchenko 7723c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7733c838a9fSAndrew Rybchenko 7743c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7753c838a9fSAndrew Rybchenko rc = req.emr_rc; 7763c838a9fSAndrew Rybchenko goto fail1; 7773c838a9fSAndrew Rybchenko } 7783c838a9fSAndrew Rybchenko 7793c838a9fSAndrew Rybchenko return (0); 7803c838a9fSAndrew Rybchenko 7813c838a9fSAndrew Rybchenko fail1: 782460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7833c838a9fSAndrew Rybchenko 7843c838a9fSAndrew Rybchenko return (rc); 7853c838a9fSAndrew Rybchenko } 7863c838a9fSAndrew Rybchenko 787460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7883c838a9fSAndrew Rybchenko efx_mcdi_nvram_read( 7893c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7903c838a9fSAndrew Rybchenko __in uint32_t partn, 7913c838a9fSAndrew Rybchenko __in uint32_t offset, 7923c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 7939ad7e03fSAndrew Rybchenko __in size_t size, 7949ad7e03fSAndrew Rybchenko __in uint32_t mode) 7953c838a9fSAndrew Rybchenko { 7963c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 797315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_READ_IN_V2_LEN, 798315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_READ_OUT_LENMAX); 799460cb568SAndrew Rybchenko efx_rc_t rc; 8003c838a9fSAndrew Rybchenko 8013c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 8023c838a9fSAndrew Rybchenko rc = EINVAL; 8033c838a9fSAndrew Rybchenko goto fail1; 8043c838a9fSAndrew Rybchenko } 8053c838a9fSAndrew Rybchenko 8063c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_READ; 8073c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8089ad7e03fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN; 8093c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8103c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 8113c838a9fSAndrew Rybchenko 8129ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn); 8139ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset); 8149ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size); 8159ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode); 8163c838a9fSAndrew Rybchenko 8173c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8183c838a9fSAndrew Rybchenko 8193c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8203c838a9fSAndrew Rybchenko rc = req.emr_rc; 8213c838a9fSAndrew Rybchenko goto fail1; 8223c838a9fSAndrew Rybchenko } 8233c838a9fSAndrew Rybchenko 8243c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 8253c838a9fSAndrew Rybchenko rc = EMSGSIZE; 8263c838a9fSAndrew Rybchenko goto fail2; 8273c838a9fSAndrew Rybchenko } 8283c838a9fSAndrew Rybchenko 8293c838a9fSAndrew Rybchenko memcpy(data, 8303c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 8313c838a9fSAndrew Rybchenko size); 8323c838a9fSAndrew Rybchenko 8333c838a9fSAndrew Rybchenko return (0); 8343c838a9fSAndrew Rybchenko 8353c838a9fSAndrew Rybchenko fail2: 8363c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 8373c838a9fSAndrew Rybchenko fail1: 838460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8393c838a9fSAndrew Rybchenko 8403c838a9fSAndrew Rybchenko return (rc); 8413c838a9fSAndrew Rybchenko } 8423c838a9fSAndrew Rybchenko 843460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8443c838a9fSAndrew Rybchenko efx_mcdi_nvram_erase( 8453c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8463c838a9fSAndrew Rybchenko __in uint32_t partn, 8473c838a9fSAndrew Rybchenko __in uint32_t offset, 8483c838a9fSAndrew Rybchenko __in size_t size) 8493c838a9fSAndrew Rybchenko { 8503c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 851315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_ERASE_IN_LEN, 852315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_ERASE_OUT_LEN); 853460cb568SAndrew Rybchenko efx_rc_t rc; 8543c838a9fSAndrew Rybchenko 8553c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_ERASE; 8563c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8573c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 8583c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8593c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 8603c838a9fSAndrew Rybchenko 8613c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 8623c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 8633c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 8643c838a9fSAndrew Rybchenko 8653c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8663c838a9fSAndrew Rybchenko 8673c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8683c838a9fSAndrew Rybchenko rc = req.emr_rc; 8693c838a9fSAndrew Rybchenko goto fail1; 8703c838a9fSAndrew Rybchenko } 8713c838a9fSAndrew Rybchenko 8723c838a9fSAndrew Rybchenko return (0); 8733c838a9fSAndrew Rybchenko 8743c838a9fSAndrew Rybchenko fail1: 875460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8763c838a9fSAndrew Rybchenko 8773c838a9fSAndrew Rybchenko return (rc); 8783c838a9fSAndrew Rybchenko } 8793c838a9fSAndrew Rybchenko 88057396b7aSAndrew Rybchenko /* 88157396b7aSAndrew Rybchenko * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 88257396b7aSAndrew Rybchenko * Sienna and EF10 based boards. However EF10 based boards support the use 88357396b7aSAndrew Rybchenko * of this command with payloads up to the maximum MCDI V2 payload length. 88457396b7aSAndrew Rybchenko */ 885460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8863c838a9fSAndrew Rybchenko efx_mcdi_nvram_write( 8873c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8883c838a9fSAndrew Rybchenko __in uint32_t partn, 8893c838a9fSAndrew Rybchenko __in uint32_t offset, 890dbcc3c8fSAndrew Rybchenko __in_bcount(size) caddr_t data, 8913c838a9fSAndrew Rybchenko __in size_t size) 8923c838a9fSAndrew Rybchenko { 8933c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 8946b231fecSAndrew Rybchenko uint8_t *payload; 895460cb568SAndrew Rybchenko efx_rc_t rc; 89657396b7aSAndrew Rybchenko size_t max_data_size; 8976b231fecSAndrew Rybchenko size_t payload_len = enp->en_nic_cfg.enc_mcdi_max_payload_length; 8983c838a9fSAndrew Rybchenko 8996b231fecSAndrew Rybchenko max_data_size = payload_len - MC_CMD_NVRAM_WRITE_IN_LEN(0); 9006b231fecSAndrew Rybchenko EFSYS_ASSERT3U(payload_len, >, 0); 9016b231fecSAndrew Rybchenko EFSYS_ASSERT3U(max_data_size, <, payload_len); 90257396b7aSAndrew Rybchenko 90357396b7aSAndrew Rybchenko if (size > max_data_size) { 9043c838a9fSAndrew Rybchenko rc = EINVAL; 9053c838a9fSAndrew Rybchenko goto fail1; 9063c838a9fSAndrew Rybchenko } 9073c838a9fSAndrew Rybchenko 9086b231fecSAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip, payload_len, payload); 9096b231fecSAndrew Rybchenko if (payload == NULL) { 9106b231fecSAndrew Rybchenko rc = ENOMEM; 9116b231fecSAndrew Rybchenko goto fail2; 9126b231fecSAndrew Rybchenko } 9136b231fecSAndrew Rybchenko 9146b231fecSAndrew Rybchenko (void) memset(payload, 0, payload_len); 9153c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_WRITE; 9163c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 9173c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 9183c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 9193c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 9203c838a9fSAndrew Rybchenko 9213c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 9223c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 9233c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 9243c838a9fSAndrew Rybchenko 9253c838a9fSAndrew Rybchenko memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 9263c838a9fSAndrew Rybchenko data, size); 9273c838a9fSAndrew Rybchenko 9283c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9293c838a9fSAndrew Rybchenko 9303c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9313c838a9fSAndrew Rybchenko rc = req.emr_rc; 9326b231fecSAndrew Rybchenko goto fail3; 9333c838a9fSAndrew Rybchenko } 9343c838a9fSAndrew Rybchenko 9356b231fecSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload); 9366b231fecSAndrew Rybchenko 9373c838a9fSAndrew Rybchenko return (0); 9383c838a9fSAndrew Rybchenko 9396b231fecSAndrew Rybchenko fail3: 9406b231fecSAndrew Rybchenko EFSYS_PROBE(fail3); 9416b231fecSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload); 9423c838a9fSAndrew Rybchenko fail2: 9433c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 9443c838a9fSAndrew Rybchenko fail1: 945460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9463c838a9fSAndrew Rybchenko 9473c838a9fSAndrew Rybchenko return (rc); 9483c838a9fSAndrew Rybchenko } 9493c838a9fSAndrew Rybchenko 950e9c123a5SAndrew Rybchenko /* 951e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified 952e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 953e9c123a5SAndrew Rybchenko */ 954460cb568SAndrew Rybchenko __checkReturn efx_rc_t 9553c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish( 9563c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 9573c838a9fSAndrew Rybchenko __in uint32_t partn, 958e9c123a5SAndrew Rybchenko __in boolean_t reboot, 959a21b2f20SAndrew Rybchenko __out_opt uint32_t *verify_resultp) 9603c838a9fSAndrew Rybchenko { 961e9c123a5SAndrew Rybchenko const efx_nic_cfg_t *encp = &enp->en_nic_cfg; 9623c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 963315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN, 964315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN); 965a21b2f20SAndrew Rybchenko uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; 966460cb568SAndrew Rybchenko efx_rc_t rc; 9673c838a9fSAndrew Rybchenko 9683c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 9693c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 970e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN; 9713c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 972e9c123a5SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN; 9733c838a9fSAndrew Rybchenko 974e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn); 975e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot); 976e9c123a5SAndrew Rybchenko 977e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS, 978e9c123a5SAndrew Rybchenko NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 9793c838a9fSAndrew Rybchenko 9803c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9813c838a9fSAndrew Rybchenko 9823c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9833c838a9fSAndrew Rybchenko rc = req.emr_rc; 9843c838a9fSAndrew Rybchenko goto fail1; 9853c838a9fSAndrew Rybchenko } 9863c838a9fSAndrew Rybchenko 987f0d3455bSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { 988a21b2f20SAndrew Rybchenko verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; 989348d3529SAndrew Rybchenko if (encp->enc_nvram_update_verify_result_supported) { 990348d3529SAndrew Rybchenko /* Result of update verification is missing */ 991e9c123a5SAndrew Rybchenko rc = EMSGSIZE; 992e9c123a5SAndrew Rybchenko goto fail2; 993e9c123a5SAndrew Rybchenko } 994f0d3455bSAndrew Rybchenko } else { 995a21b2f20SAndrew Rybchenko verify_result = 996e9c123a5SAndrew Rybchenko MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE); 997f0d3455bSAndrew Rybchenko } 998e9c123a5SAndrew Rybchenko 999348d3529SAndrew Rybchenko if ((encp->enc_nvram_update_verify_result_supported) && 1000a21b2f20SAndrew Rybchenko (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) { 1001348d3529SAndrew Rybchenko /* Update verification failed */ 1002e9c123a5SAndrew Rybchenko rc = EINVAL; 1003e9c123a5SAndrew Rybchenko goto fail3; 1004e9c123a5SAndrew Rybchenko } 1005e9c123a5SAndrew Rybchenko 1006a21b2f20SAndrew Rybchenko if (verify_resultp != NULL) 1007a21b2f20SAndrew Rybchenko *verify_resultp = verify_result; 1008e9c123a5SAndrew Rybchenko 10093c838a9fSAndrew Rybchenko return (0); 10103c838a9fSAndrew Rybchenko 1011e9c123a5SAndrew Rybchenko fail3: 1012e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail3); 1013e9c123a5SAndrew Rybchenko fail2: 1014e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 10153c838a9fSAndrew Rybchenko fail1: 1016460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 10173c838a9fSAndrew Rybchenko 1018e9c123a5SAndrew Rybchenko /* Always report verification result */ 1019a21b2f20SAndrew Rybchenko if (verify_resultp != NULL) 1020a21b2f20SAndrew Rybchenko *verify_resultp = verify_result; 1021e9c123a5SAndrew Rybchenko 10223c838a9fSAndrew Rybchenko return (rc); 10233c838a9fSAndrew Rybchenko } 10243c838a9fSAndrew Rybchenko 10253c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 10263c838a9fSAndrew Rybchenko 1027460cb568SAndrew Rybchenko __checkReturn efx_rc_t 10283c838a9fSAndrew Rybchenko efx_mcdi_nvram_test( 10293c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 10303c838a9fSAndrew Rybchenko __in uint32_t partn) 10313c838a9fSAndrew Rybchenko { 10323c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 1033315bbbaaSAndrew Rybchenko EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TEST_IN_LEN, 1034315bbbaaSAndrew Rybchenko MC_CMD_NVRAM_TEST_OUT_LEN); 10353c838a9fSAndrew Rybchenko int result; 1036460cb568SAndrew Rybchenko efx_rc_t rc; 10373c838a9fSAndrew Rybchenko 10383c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_TEST; 10393c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 10403c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 10413c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 10423c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 10433c838a9fSAndrew Rybchenko 10443c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 10453c838a9fSAndrew Rybchenko 10463c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 10473c838a9fSAndrew Rybchenko 10483c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 10493c838a9fSAndrew Rybchenko rc = req.emr_rc; 10503c838a9fSAndrew Rybchenko goto fail1; 10513c838a9fSAndrew Rybchenko } 10523c838a9fSAndrew Rybchenko 10533c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 10543c838a9fSAndrew Rybchenko rc = EMSGSIZE; 10553c838a9fSAndrew Rybchenko goto fail2; 10563c838a9fSAndrew Rybchenko } 10573c838a9fSAndrew Rybchenko 10583c838a9fSAndrew Rybchenko result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 10593c838a9fSAndrew Rybchenko if (result == MC_CMD_NVRAM_TEST_FAIL) { 10603c838a9fSAndrew Rybchenko EFSYS_PROBE1(nvram_test_failure, int, partn); 10613c838a9fSAndrew Rybchenko 10623c838a9fSAndrew Rybchenko rc = (EINVAL); 10633c838a9fSAndrew Rybchenko goto fail3; 10643c838a9fSAndrew Rybchenko } 10653c838a9fSAndrew Rybchenko 10663c838a9fSAndrew Rybchenko return (0); 10673c838a9fSAndrew Rybchenko 10683c838a9fSAndrew Rybchenko fail3: 10693c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 10703c838a9fSAndrew Rybchenko fail2: 10713c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 10723c838a9fSAndrew Rybchenko fail1: 1073460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 10743c838a9fSAndrew Rybchenko 10753c838a9fSAndrew Rybchenko return (rc); 10763c838a9fSAndrew Rybchenko } 10773c838a9fSAndrew Rybchenko 10783c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 10793c838a9fSAndrew Rybchenko 10803c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 1081