1e948693eSPhilip Paeps /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 62de9775adSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 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 81de9775adSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 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 113e948693eSPhilip Paeps default: 114e948693eSPhilip Paeps EFSYS_ASSERT(0); 115e948693eSPhilip Paeps rc = ENOTSUP; 116e948693eSPhilip Paeps goto fail1; 117e948693eSPhilip Paeps } 118e948693eSPhilip Paeps 119e948693eSPhilip Paeps enp->en_envop = envop; 120e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_NVRAM; 121e948693eSPhilip Paeps 1223d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 1233d670ff5SAndrew Rybchenko 124e948693eSPhilip Paeps return (0); 125e948693eSPhilip Paeps 126e948693eSPhilip Paeps fail1: 127460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 128e948693eSPhilip Paeps 129e948693eSPhilip Paeps return (rc); 130e948693eSPhilip Paeps } 131e948693eSPhilip Paeps 132e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 133e948693eSPhilip Paeps 134460cb568SAndrew Rybchenko __checkReturn efx_rc_t 135e948693eSPhilip Paeps efx_nvram_test( 136e948693eSPhilip Paeps __in efx_nic_t *enp) 137e948693eSPhilip Paeps { 138ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 139460cb568SAndrew Rybchenko efx_rc_t rc; 140e948693eSPhilip Paeps 141e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 142e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 143e948693eSPhilip Paeps 144e948693eSPhilip Paeps if ((rc = envop->envo_test(enp)) != 0) 145e948693eSPhilip Paeps goto fail1; 146e948693eSPhilip Paeps 147e948693eSPhilip Paeps return (0); 148e948693eSPhilip Paeps 149e948693eSPhilip Paeps fail1: 150460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 151e948693eSPhilip Paeps 152e948693eSPhilip Paeps return (rc); 153e948693eSPhilip Paeps } 154e948693eSPhilip Paeps 155e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 156e948693eSPhilip Paeps 157460cb568SAndrew Rybchenko __checkReturn efx_rc_t 158e948693eSPhilip Paeps efx_nvram_size( 159e948693eSPhilip Paeps __in efx_nic_t *enp, 160e948693eSPhilip Paeps __in efx_nvram_type_t type, 161e948693eSPhilip Paeps __out size_t *sizep) 162e948693eSPhilip Paeps { 163ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 16456bd83b0SAndrew Rybchenko uint32_t partn; 165460cb568SAndrew Rybchenko efx_rc_t rc; 166e948693eSPhilip Paeps 167e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 168e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 169e948693eSPhilip Paeps 17056bd83b0SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 171e948693eSPhilip Paeps goto fail1; 172e948693eSPhilip Paeps 17356bd83b0SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0) 17456bd83b0SAndrew Rybchenko goto fail2; 17556bd83b0SAndrew Rybchenko 176e948693eSPhilip Paeps return (0); 177e948693eSPhilip Paeps 17856bd83b0SAndrew Rybchenko fail2: 17956bd83b0SAndrew Rybchenko EFSYS_PROBE(fail2); 180e948693eSPhilip Paeps fail1: 181460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 18256bd83b0SAndrew Rybchenko *sizep = 0; 183e948693eSPhilip Paeps 184e948693eSPhilip Paeps return (rc); 185e948693eSPhilip Paeps } 186e948693eSPhilip Paeps 187460cb568SAndrew Rybchenko __checkReturn efx_rc_t 188e948693eSPhilip Paeps efx_nvram_get_version( 189e948693eSPhilip Paeps __in efx_nic_t *enp, 190e948693eSPhilip Paeps __in efx_nvram_type_t type, 191e948693eSPhilip Paeps __out uint32_t *subtypep, 192e948693eSPhilip Paeps __out_ecount(4) uint16_t version[4]) 193e948693eSPhilip Paeps { 194ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 19592187119SAndrew Rybchenko uint32_t partn; 196460cb568SAndrew Rybchenko efx_rc_t rc; 197e948693eSPhilip Paeps 198e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 199e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 200e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 201e948693eSPhilip Paeps 20292187119SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 203e948693eSPhilip Paeps goto fail1; 204e948693eSPhilip Paeps 20592187119SAndrew Rybchenko if ((rc = envop->envo_partn_get_version(enp, partn, 20692187119SAndrew Rybchenko subtypep, version)) != 0) 20792187119SAndrew Rybchenko goto fail2; 20892187119SAndrew Rybchenko 209e948693eSPhilip Paeps return (0); 210e948693eSPhilip Paeps 21192187119SAndrew Rybchenko fail2: 21292187119SAndrew Rybchenko EFSYS_PROBE(fail2); 213e948693eSPhilip Paeps fail1: 214460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 215e948693eSPhilip Paeps 216e948693eSPhilip Paeps return (rc); 217e948693eSPhilip Paeps } 218e948693eSPhilip Paeps 219460cb568SAndrew Rybchenko __checkReturn efx_rc_t 220e948693eSPhilip Paeps efx_nvram_rw_start( 221e948693eSPhilip Paeps __in efx_nic_t *enp, 222e948693eSPhilip Paeps __in efx_nvram_type_t type, 223e948693eSPhilip Paeps __out_opt size_t *chunk_sizep) 224e948693eSPhilip Paeps { 225ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2265d846e87SAndrew Rybchenko uint32_t partn; 227460cb568SAndrew Rybchenko efx_rc_t rc; 228e948693eSPhilip Paeps 229e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 230e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 231e948693eSPhilip Paeps 2325d846e87SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 233e948693eSPhilip Paeps goto fail1; 234e948693eSPhilip Paeps 2353d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 2363d670ff5SAndrew Rybchenko 2375d846e87SAndrew Rybchenko if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) 2385d846e87SAndrew Rybchenko goto fail2; 2395d846e87SAndrew Rybchenko 2403d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = partn; 241e948693eSPhilip Paeps 242e948693eSPhilip Paeps return (0); 243e948693eSPhilip Paeps 2445d846e87SAndrew Rybchenko fail2: 2455d846e87SAndrew Rybchenko EFSYS_PROBE(fail2); 246e948693eSPhilip Paeps fail1: 247460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 248e948693eSPhilip Paeps 249e948693eSPhilip Paeps return (rc); 250e948693eSPhilip Paeps } 251e948693eSPhilip Paeps 252460cb568SAndrew Rybchenko __checkReturn efx_rc_t 253e948693eSPhilip Paeps efx_nvram_read_chunk( 254e948693eSPhilip Paeps __in efx_nic_t *enp, 255e948693eSPhilip Paeps __in efx_nvram_type_t type, 256e948693eSPhilip Paeps __in unsigned int offset, 257e948693eSPhilip Paeps __out_bcount(size) caddr_t data, 258e948693eSPhilip Paeps __in size_t size) 259e948693eSPhilip Paeps { 260ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2610afdf29cSAndrew Rybchenko uint32_t partn; 262460cb568SAndrew Rybchenko efx_rc_t rc; 263e948693eSPhilip Paeps 264e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 265e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 266e948693eSPhilip Paeps 2670afdf29cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 268e948693eSPhilip Paeps goto fail1; 269e948693eSPhilip Paeps 2703d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 2713d670ff5SAndrew Rybchenko 2720afdf29cSAndrew Rybchenko if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) 2730afdf29cSAndrew Rybchenko goto fail2; 2740afdf29cSAndrew Rybchenko 275e948693eSPhilip Paeps return (0); 276e948693eSPhilip Paeps 2770afdf29cSAndrew Rybchenko fail2: 2780afdf29cSAndrew Rybchenko EFSYS_PROBE(fail2); 279e948693eSPhilip Paeps fail1: 280460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 281e948693eSPhilip Paeps 282e948693eSPhilip Paeps return (rc); 283e948693eSPhilip Paeps } 284e948693eSPhilip Paeps 285ede1a3edSAndrew Rybchenko /* 286ede1a3edSAndrew Rybchenko * Read from the backup (writeable) store of an A/B partition. 287ede1a3edSAndrew Rybchenko * For non A/B partitions, there is only a single store, and so this 288ede1a3edSAndrew Rybchenko * function has the same behaviour as efx_nvram_read_chunk(). 289ede1a3edSAndrew Rybchenko */ 290ede1a3edSAndrew Rybchenko __checkReturn efx_rc_t 291ede1a3edSAndrew Rybchenko efx_nvram_read_backup( 292ede1a3edSAndrew Rybchenko __in efx_nic_t *enp, 293ede1a3edSAndrew Rybchenko __in efx_nvram_type_t type, 294ede1a3edSAndrew Rybchenko __in unsigned int offset, 295ede1a3edSAndrew Rybchenko __out_bcount(size) caddr_t data, 296ede1a3edSAndrew Rybchenko __in size_t size) 297ede1a3edSAndrew Rybchenko { 298ede1a3edSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 299ede1a3edSAndrew Rybchenko uint32_t partn; 300ede1a3edSAndrew Rybchenko efx_rc_t rc; 301ede1a3edSAndrew Rybchenko 302ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 303ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 304ede1a3edSAndrew Rybchenko 305ede1a3edSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 306ede1a3edSAndrew Rybchenko goto fail1; 307ede1a3edSAndrew Rybchenko 308ede1a3edSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 309ede1a3edSAndrew Rybchenko 310ede1a3edSAndrew Rybchenko if ((rc = envop->envo_partn_read_backup(enp, partn, offset, 311ede1a3edSAndrew Rybchenko data, size)) != 0) 312ede1a3edSAndrew Rybchenko goto fail2; 313ede1a3edSAndrew Rybchenko 314ede1a3edSAndrew Rybchenko return (0); 315ede1a3edSAndrew Rybchenko 316ede1a3edSAndrew Rybchenko fail2: 317ede1a3edSAndrew Rybchenko EFSYS_PROBE(fail2); 318ede1a3edSAndrew Rybchenko fail1: 319ede1a3edSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 320ede1a3edSAndrew Rybchenko 321ede1a3edSAndrew Rybchenko return (rc); 322ede1a3edSAndrew Rybchenko } 323ede1a3edSAndrew Rybchenko 324460cb568SAndrew Rybchenko __checkReturn efx_rc_t 325e948693eSPhilip Paeps efx_nvram_erase( 326e948693eSPhilip Paeps __in efx_nic_t *enp, 327e948693eSPhilip Paeps __in efx_nvram_type_t type) 328e948693eSPhilip Paeps { 329ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 330b60ff840SAndrew Rybchenko unsigned int offset = 0; 331b60ff840SAndrew Rybchenko size_t size = 0; 332b60ff840SAndrew Rybchenko uint32_t partn; 333460cb568SAndrew Rybchenko efx_rc_t rc; 334e948693eSPhilip Paeps 335e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 336e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 337e948693eSPhilip Paeps 338b60ff840SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 339e948693eSPhilip Paeps goto fail1; 340e948693eSPhilip Paeps 3413d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 3423d670ff5SAndrew Rybchenko 343b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0) 344b60ff840SAndrew Rybchenko goto fail2; 345b60ff840SAndrew Rybchenko 346b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0) 347b60ff840SAndrew Rybchenko goto fail3; 348b60ff840SAndrew Rybchenko 349e948693eSPhilip Paeps return (0); 350e948693eSPhilip Paeps 351b60ff840SAndrew Rybchenko fail3: 352b60ff840SAndrew Rybchenko EFSYS_PROBE(fail3); 353b60ff840SAndrew Rybchenko fail2: 354b60ff840SAndrew Rybchenko EFSYS_PROBE(fail2); 355e948693eSPhilip Paeps fail1: 356460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 357e948693eSPhilip Paeps 358e948693eSPhilip Paeps return (rc); 359e948693eSPhilip Paeps } 360e948693eSPhilip Paeps 361460cb568SAndrew Rybchenko __checkReturn efx_rc_t 362e948693eSPhilip Paeps efx_nvram_write_chunk( 363e948693eSPhilip Paeps __in efx_nic_t *enp, 364e948693eSPhilip Paeps __in efx_nvram_type_t type, 365e948693eSPhilip Paeps __in unsigned int offset, 366e948693eSPhilip Paeps __in_bcount(size) caddr_t data, 367e948693eSPhilip Paeps __in size_t size) 368e948693eSPhilip Paeps { 369ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 370134c4c4aSAndrew Rybchenko uint32_t partn; 371460cb568SAndrew Rybchenko efx_rc_t rc; 372e948693eSPhilip Paeps 373e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 374e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 375e948693eSPhilip Paeps 376134c4c4aSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 377e948693eSPhilip Paeps goto fail1; 378e948693eSPhilip Paeps 3793d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 3803d670ff5SAndrew Rybchenko 381134c4c4aSAndrew Rybchenko if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0) 382134c4c4aSAndrew Rybchenko goto fail2; 383134c4c4aSAndrew Rybchenko 384e948693eSPhilip Paeps return (0); 385e948693eSPhilip Paeps 386134c4c4aSAndrew Rybchenko fail2: 387134c4c4aSAndrew Rybchenko EFSYS_PROBE(fail2); 388e948693eSPhilip Paeps fail1: 389460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 390e948693eSPhilip Paeps 391e948693eSPhilip Paeps return (rc); 392e948693eSPhilip Paeps } 393e948693eSPhilip Paeps 394e9c123a5SAndrew Rybchenko __checkReturn efx_rc_t 395e948693eSPhilip Paeps efx_nvram_rw_finish( 396e948693eSPhilip Paeps __in efx_nic_t *enp, 397d5106d05SAndrew Rybchenko __in efx_nvram_type_t type, 398d5106d05SAndrew Rybchenko __out_opt uint32_t *verify_resultp) 399e948693eSPhilip Paeps { 400ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 401eb9703daSAndrew Rybchenko uint32_t partn; 402d5106d05SAndrew Rybchenko uint32_t verify_result = 0; 403e9c123a5SAndrew Rybchenko efx_rc_t rc; 404e948693eSPhilip Paeps 405e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 406e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 407e948693eSPhilip Paeps 408e9c123a5SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 409e9c123a5SAndrew Rybchenko goto fail1; 410e9c123a5SAndrew Rybchenko 4113d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 4123d670ff5SAndrew Rybchenko 413a21b2f20SAndrew Rybchenko if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0) 414e9c123a5SAndrew Rybchenko goto fail2; 415e948693eSPhilip Paeps 4163d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 417e9c123a5SAndrew Rybchenko 418d5106d05SAndrew Rybchenko if (verify_resultp != NULL) 419d5106d05SAndrew Rybchenko *verify_resultp = verify_result; 420d5106d05SAndrew Rybchenko 421e9c123a5SAndrew Rybchenko return (0); 422e9c123a5SAndrew Rybchenko 423e9c123a5SAndrew Rybchenko fail2: 424e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 4253d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 426e9c123a5SAndrew Rybchenko 427e9c123a5SAndrew Rybchenko fail1: 428e9c123a5SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 429e9c123a5SAndrew Rybchenko 430d5106d05SAndrew Rybchenko /* Always report verification result */ 431d5106d05SAndrew Rybchenko if (verify_resultp != NULL) 432d5106d05SAndrew Rybchenko *verify_resultp = verify_result; 433d5106d05SAndrew Rybchenko 434e9c123a5SAndrew Rybchenko return (rc); 435e948693eSPhilip Paeps } 436e948693eSPhilip Paeps 437460cb568SAndrew Rybchenko __checkReturn efx_rc_t 438e948693eSPhilip Paeps efx_nvram_set_version( 439e948693eSPhilip Paeps __in efx_nic_t *enp, 440e948693eSPhilip Paeps __in efx_nvram_type_t type, 4413c838a9fSAndrew Rybchenko __in_ecount(4) uint16_t version[4]) 442e948693eSPhilip Paeps { 443ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4446d0b856cSAndrew Rybchenko uint32_t partn; 445460cb568SAndrew Rybchenko efx_rc_t rc; 446e948693eSPhilip Paeps 447e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 448e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 449e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 450e948693eSPhilip Paeps 4516d0b856cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 452e948693eSPhilip Paeps goto fail1; 453e948693eSPhilip Paeps 4543d670ff5SAndrew Rybchenko /* 4553d670ff5SAndrew Rybchenko * The Siena implementation of envo_set_version() will attempt to 4563d670ff5SAndrew Rybchenko * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition. 4573d670ff5SAndrew Rybchenko * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 4583d670ff5SAndrew Rybchenko */ 4593d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 4603d670ff5SAndrew Rybchenko 4616d0b856cSAndrew Rybchenko if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0) 4626d0b856cSAndrew Rybchenko goto fail2; 4636d0b856cSAndrew Rybchenko 464e948693eSPhilip Paeps return (0); 465e948693eSPhilip Paeps 4666d0b856cSAndrew Rybchenko fail2: 4676d0b856cSAndrew Rybchenko EFSYS_PROBE(fail2); 468e948693eSPhilip Paeps fail1: 469460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 470e948693eSPhilip Paeps 471e948693eSPhilip Paeps return (rc); 472e948693eSPhilip Paeps } 473e948693eSPhilip Paeps 4745abce2b9SAndrew Rybchenko /* Validate buffer contents (before writing to flash) */ 4755abce2b9SAndrew Rybchenko __checkReturn efx_rc_t 4765abce2b9SAndrew Rybchenko efx_nvram_validate( 4775abce2b9SAndrew Rybchenko __in efx_nic_t *enp, 4785abce2b9SAndrew Rybchenko __in efx_nvram_type_t type, 4795abce2b9SAndrew Rybchenko __in_bcount(partn_size) caddr_t partn_data, 4805abce2b9SAndrew Rybchenko __in size_t partn_size) 4815abce2b9SAndrew Rybchenko { 482ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4835abce2b9SAndrew Rybchenko uint32_t partn; 4845abce2b9SAndrew Rybchenko efx_rc_t rc; 4855abce2b9SAndrew Rybchenko 4865abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4875abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 4885abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 4895abce2b9SAndrew Rybchenko 4905abce2b9SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 4915abce2b9SAndrew Rybchenko goto fail1; 4925abce2b9SAndrew Rybchenko 4936a869fecSAndrew Rybchenko if (envop->envo_buffer_validate != NULL) { 4946a869fecSAndrew Rybchenko if ((rc = envop->envo_buffer_validate(enp, partn, 4956a869fecSAndrew Rybchenko partn_data, partn_size)) != 0) 4965abce2b9SAndrew Rybchenko goto fail2; 4976a869fecSAndrew Rybchenko } 4985abce2b9SAndrew Rybchenko 4995abce2b9SAndrew Rybchenko return (0); 5005abce2b9SAndrew Rybchenko 5015abce2b9SAndrew Rybchenko fail2: 5025abce2b9SAndrew Rybchenko EFSYS_PROBE(fail2); 5035abce2b9SAndrew Rybchenko fail1: 5045abce2b9SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5055abce2b9SAndrew Rybchenko 5065abce2b9SAndrew Rybchenko return (rc); 5075abce2b9SAndrew Rybchenko } 5085abce2b9SAndrew Rybchenko 5095abce2b9SAndrew Rybchenko 510e948693eSPhilip Paeps void 511e948693eSPhilip Paeps efx_nvram_fini( 512e948693eSPhilip Paeps __in efx_nic_t *enp) 513e948693eSPhilip Paeps { 514e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 515e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 516e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 517e948693eSPhilip Paeps 5183d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 519e948693eSPhilip Paeps 520e948693eSPhilip Paeps enp->en_envop = NULL; 521e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_NVRAM; 522e948693eSPhilip Paeps } 523e948693eSPhilip Paeps 524e948693eSPhilip Paeps #endif /* EFSYS_OPT_NVRAM */ 5253c838a9fSAndrew Rybchenko 5263c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 5273c838a9fSAndrew Rybchenko 5283c838a9fSAndrew Rybchenko /* 5293c838a9fSAndrew Rybchenko * Internal MCDI request handling 5303c838a9fSAndrew Rybchenko */ 5313c838a9fSAndrew Rybchenko 532460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5333c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions( 5343c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5353c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 5363c838a9fSAndrew Rybchenko __in size_t size, 5373c838a9fSAndrew Rybchenko __out unsigned int *npartnp) 5383c838a9fSAndrew Rybchenko { 5393c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 5403c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 5413c838a9fSAndrew Rybchenko MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 5423c838a9fSAndrew Rybchenko unsigned int npartn; 543460cb568SAndrew Rybchenko efx_rc_t rc; 5443c838a9fSAndrew Rybchenko 5453c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 5463c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 5473c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5483c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 5493c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5503c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 5513c838a9fSAndrew Rybchenko 5523c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 5533c838a9fSAndrew Rybchenko 5543c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 5553c838a9fSAndrew Rybchenko rc = req.emr_rc; 5563c838a9fSAndrew Rybchenko goto fail1; 5573c838a9fSAndrew Rybchenko } 5583c838a9fSAndrew Rybchenko 5593c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 5603c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5613c838a9fSAndrew Rybchenko goto fail2; 5623c838a9fSAndrew Rybchenko } 5633c838a9fSAndrew Rybchenko npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 5643c838a9fSAndrew Rybchenko 5653c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 5663c838a9fSAndrew Rybchenko rc = ENOENT; 5673c838a9fSAndrew Rybchenko goto fail3; 5683c838a9fSAndrew Rybchenko } 5693c838a9fSAndrew Rybchenko 5703c838a9fSAndrew Rybchenko if (size < npartn * sizeof (uint32_t)) { 5713c838a9fSAndrew Rybchenko rc = ENOSPC; 5723c838a9fSAndrew Rybchenko goto fail3; 5733c838a9fSAndrew Rybchenko } 5743c838a9fSAndrew Rybchenko 5753c838a9fSAndrew Rybchenko *npartnp = npartn; 5763c838a9fSAndrew Rybchenko 5773c838a9fSAndrew Rybchenko memcpy(data, 5783c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 5793c838a9fSAndrew Rybchenko (npartn * sizeof (uint32_t))); 5803c838a9fSAndrew Rybchenko 5813c838a9fSAndrew Rybchenko return (0); 5823c838a9fSAndrew Rybchenko 5833c838a9fSAndrew Rybchenko fail3: 5843c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 5853c838a9fSAndrew Rybchenko fail2: 5863c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 5873c838a9fSAndrew Rybchenko fail1: 588460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5893c838a9fSAndrew Rybchenko 5903c838a9fSAndrew Rybchenko return (rc); 5913c838a9fSAndrew Rybchenko } 5923c838a9fSAndrew Rybchenko 593460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5943c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata( 5953c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5963c838a9fSAndrew Rybchenko __in uint32_t partn, 5973c838a9fSAndrew Rybchenko __out uint32_t *subtypep, 5983c838a9fSAndrew Rybchenko __out_ecount(4) uint16_t version[4], 5993c838a9fSAndrew Rybchenko __out_bcount_opt(size) char *descp, 6003c838a9fSAndrew Rybchenko __in size_t size) 6013c838a9fSAndrew Rybchenko { 6023c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 6033c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 6043c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 605460cb568SAndrew Rybchenko efx_rc_t rc; 6063c838a9fSAndrew Rybchenko 6073c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 6083c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_METADATA; 6093c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 6103c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 6113c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 6123c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 6133c838a9fSAndrew Rybchenko 6143c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 6153c838a9fSAndrew Rybchenko 616*e7144483SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 6173c838a9fSAndrew Rybchenko 6183c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6193c838a9fSAndrew Rybchenko rc = req.emr_rc; 6203c838a9fSAndrew Rybchenko goto fail1; 6213c838a9fSAndrew Rybchenko } 6223c838a9fSAndrew Rybchenko 6233c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 6243c838a9fSAndrew Rybchenko rc = EMSGSIZE; 6253c838a9fSAndrew Rybchenko goto fail2; 6263c838a9fSAndrew Rybchenko } 6273c838a9fSAndrew Rybchenko 6283c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6293c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 6303c838a9fSAndrew Rybchenko *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 6313c838a9fSAndrew Rybchenko } else { 6323c838a9fSAndrew Rybchenko *subtypep = 0; 6333c838a9fSAndrew Rybchenko } 6343c838a9fSAndrew Rybchenko 6353c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6363c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_VERSION_VALID)) { 6373c838a9fSAndrew Rybchenko version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 6383c838a9fSAndrew Rybchenko version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 6393c838a9fSAndrew Rybchenko version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 6403c838a9fSAndrew Rybchenko version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 6413c838a9fSAndrew Rybchenko } else { 6423c838a9fSAndrew Rybchenko version[0] = version[1] = version[2] = version[3] = 0; 6433c838a9fSAndrew Rybchenko } 6443c838a9fSAndrew Rybchenko 6453c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6463c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 6473c838a9fSAndrew Rybchenko /* Return optional descrition string */ 6483c838a9fSAndrew Rybchenko if ((descp != NULL) && (size > 0)) { 6493c838a9fSAndrew Rybchenko size_t desclen; 6503c838a9fSAndrew Rybchenko 6513c838a9fSAndrew Rybchenko descp[0] = '\0'; 6523c838a9fSAndrew Rybchenko desclen = (req.emr_out_length_used 6533c838a9fSAndrew Rybchenko - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 6543c838a9fSAndrew Rybchenko 6553c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(desclen, <=, 6563c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 6573c838a9fSAndrew Rybchenko 6583c838a9fSAndrew Rybchenko if (size < desclen) { 6593c838a9fSAndrew Rybchenko rc = ENOSPC; 6603c838a9fSAndrew Rybchenko goto fail3; 6613c838a9fSAndrew Rybchenko } 6623c838a9fSAndrew Rybchenko 6633c838a9fSAndrew Rybchenko memcpy(descp, MCDI_OUT2(req, char, 6643c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION), 6653c838a9fSAndrew Rybchenko desclen); 6663c838a9fSAndrew Rybchenko 6673c838a9fSAndrew Rybchenko /* Ensure string is NUL terminated */ 6683c838a9fSAndrew Rybchenko descp[desclen] = '\0'; 6693c838a9fSAndrew Rybchenko } 6703c838a9fSAndrew Rybchenko } 6713c838a9fSAndrew Rybchenko 6723c838a9fSAndrew Rybchenko return (0); 6733c838a9fSAndrew Rybchenko 6743c838a9fSAndrew Rybchenko fail3: 6753c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 6763c838a9fSAndrew Rybchenko fail2: 6773c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 6783c838a9fSAndrew Rybchenko fail1: 679460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 6803c838a9fSAndrew Rybchenko 6813c838a9fSAndrew Rybchenko return (rc); 6823c838a9fSAndrew Rybchenko } 6833c838a9fSAndrew Rybchenko 684460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6853c838a9fSAndrew Rybchenko efx_mcdi_nvram_info( 6863c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6873c838a9fSAndrew Rybchenko __in uint32_t partn, 6883c838a9fSAndrew Rybchenko __out_opt size_t *sizep, 6893c838a9fSAndrew Rybchenko __out_opt uint32_t *addressp, 6909cb71b16SAndrew Rybchenko __out_opt uint32_t *erase_sizep, 6919cb71b16SAndrew Rybchenko __out_opt uint32_t *write_sizep) 6923c838a9fSAndrew Rybchenko { 6933c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 6949cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN)]; 6953c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 696460cb568SAndrew Rybchenko efx_rc_t rc; 6973c838a9fSAndrew Rybchenko 6983c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 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 7503c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start( 7513c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7523c838a9fSAndrew Rybchenko __in uint32_t partn) 7533c838a9fSAndrew Rybchenko { 754e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN, 7553c838a9fSAndrew 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 (void) memset(payload, 0, sizeof (payload)); 7603c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 7613c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 762e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN; 7633c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7643c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 7653c838a9fSAndrew Rybchenko 766e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn); 767e9c123a5SAndrew Rybchenko 768e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS, 769e9c123a5SAndrew Rybchenko NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 7703c838a9fSAndrew Rybchenko 7713c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7723c838a9fSAndrew Rybchenko 7733c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7743c838a9fSAndrew Rybchenko rc = req.emr_rc; 7753c838a9fSAndrew Rybchenko goto fail1; 7763c838a9fSAndrew Rybchenko } 7773c838a9fSAndrew Rybchenko 7783c838a9fSAndrew Rybchenko return (0); 7793c838a9fSAndrew Rybchenko 7803c838a9fSAndrew Rybchenko fail1: 781460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7823c838a9fSAndrew Rybchenko 7833c838a9fSAndrew Rybchenko return (rc); 7843c838a9fSAndrew Rybchenko } 7853c838a9fSAndrew Rybchenko 786460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7873c838a9fSAndrew Rybchenko efx_mcdi_nvram_read( 7883c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7893c838a9fSAndrew Rybchenko __in uint32_t partn, 7903c838a9fSAndrew Rybchenko __in uint32_t offset, 7913c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 7929ad7e03fSAndrew Rybchenko __in size_t size, 7939ad7e03fSAndrew Rybchenko __in uint32_t mode) 7943c838a9fSAndrew Rybchenko { 7953c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 7969ad7e03fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN, 7973c838a9fSAndrew Rybchenko MC_CMD_NVRAM_READ_OUT_LENMAX)]; 798460cb568SAndrew Rybchenko efx_rc_t rc; 7993c838a9fSAndrew Rybchenko 8003c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 8013c838a9fSAndrew Rybchenko rc = EINVAL; 8023c838a9fSAndrew Rybchenko goto fail1; 8033c838a9fSAndrew Rybchenko } 8043c838a9fSAndrew Rybchenko 8053c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 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; 8513c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 8523c838a9fSAndrew Rybchenko MC_CMD_NVRAM_ERASE_OUT_LEN)]; 853460cb568SAndrew Rybchenko efx_rc_t rc; 8543c838a9fSAndrew Rybchenko 8553c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8563c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_ERASE; 8573c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8583c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 8593c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8603c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 8613c838a9fSAndrew Rybchenko 8623c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 8633c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 8643c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 8653c838a9fSAndrew Rybchenko 8663c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8673c838a9fSAndrew Rybchenko 8683c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8693c838a9fSAndrew Rybchenko rc = req.emr_rc; 8703c838a9fSAndrew Rybchenko goto fail1; 8713c838a9fSAndrew Rybchenko } 8723c838a9fSAndrew Rybchenko 8733c838a9fSAndrew Rybchenko return (0); 8743c838a9fSAndrew Rybchenko 8753c838a9fSAndrew Rybchenko fail1: 876460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8773c838a9fSAndrew Rybchenko 8783c838a9fSAndrew Rybchenko return (rc); 8793c838a9fSAndrew Rybchenko } 8803c838a9fSAndrew Rybchenko 88157396b7aSAndrew Rybchenko /* 88257396b7aSAndrew Rybchenko * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 88357396b7aSAndrew Rybchenko * Sienna and EF10 based boards. However EF10 based boards support the use 88457396b7aSAndrew Rybchenko * of this command with payloads up to the maximum MCDI V2 payload length. 88557396b7aSAndrew Rybchenko */ 886460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8873c838a9fSAndrew Rybchenko efx_mcdi_nvram_write( 8883c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8893c838a9fSAndrew Rybchenko __in uint32_t partn, 8903c838a9fSAndrew Rybchenko __in uint32_t offset, 8913c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 8923c838a9fSAndrew Rybchenko __in size_t size) 8933c838a9fSAndrew Rybchenko { 8943c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 89557396b7aSAndrew Rybchenko uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1, 89657396b7aSAndrew Rybchenko MCDI_CTL_SDU_LEN_MAX_V2)]; 897460cb568SAndrew Rybchenko efx_rc_t rc; 89857396b7aSAndrew Rybchenko size_t max_data_size; 8993c838a9fSAndrew Rybchenko 90057396b7aSAndrew Rybchenko max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length 90157396b7aSAndrew Rybchenko - MC_CMD_NVRAM_WRITE_IN_LEN(0); 90257396b7aSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0); 90357396b7aSAndrew Rybchenko EFSYS_ASSERT3U(max_data_size, <, 90457396b7aSAndrew Rybchenko enp->en_nic_cfg.enc_mcdi_max_payload_length); 90557396b7aSAndrew Rybchenko 90657396b7aSAndrew Rybchenko if (size > max_data_size) { 9073c838a9fSAndrew Rybchenko rc = EINVAL; 9083c838a9fSAndrew Rybchenko goto fail1; 9093c838a9fSAndrew Rybchenko } 9103c838a9fSAndrew Rybchenko 9113c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 9123c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_WRITE; 9133c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 9143c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 9153c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 9163c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 9173c838a9fSAndrew Rybchenko 9183c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 9193c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 9203c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 9213c838a9fSAndrew Rybchenko 9223c838a9fSAndrew Rybchenko memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 9233c838a9fSAndrew Rybchenko data, size); 9243c838a9fSAndrew Rybchenko 9253c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9263c838a9fSAndrew Rybchenko 9273c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9283c838a9fSAndrew Rybchenko rc = req.emr_rc; 9293c838a9fSAndrew Rybchenko goto fail2; 9303c838a9fSAndrew Rybchenko } 9313c838a9fSAndrew Rybchenko 9323c838a9fSAndrew Rybchenko return (0); 9333c838a9fSAndrew Rybchenko 9343c838a9fSAndrew Rybchenko fail2: 9353c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 9363c838a9fSAndrew Rybchenko fail1: 937460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9383c838a9fSAndrew Rybchenko 9393c838a9fSAndrew Rybchenko return (rc); 9403c838a9fSAndrew Rybchenko } 9413c838a9fSAndrew Rybchenko 942e9c123a5SAndrew Rybchenko 943e9c123a5SAndrew Rybchenko /* 944e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified 945e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 946e9c123a5SAndrew Rybchenko */ 947460cb568SAndrew Rybchenko __checkReturn efx_rc_t 9483c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish( 9493c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 9503c838a9fSAndrew Rybchenko __in uint32_t partn, 951e9c123a5SAndrew Rybchenko __in boolean_t reboot, 952a21b2f20SAndrew Rybchenko __out_opt uint32_t *verify_resultp) 9533c838a9fSAndrew Rybchenko { 954e9c123a5SAndrew Rybchenko const efx_nic_cfg_t *encp = &enp->en_nic_cfg; 9553c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 956e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN, 957e9c123a5SAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)]; 958a21b2f20SAndrew Rybchenko uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; 959460cb568SAndrew Rybchenko efx_rc_t rc; 9603c838a9fSAndrew Rybchenko 9613c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 9623c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 9633c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 964e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN; 9653c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 966e9c123a5SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN; 9673c838a9fSAndrew Rybchenko 968e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn); 969e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot); 970e9c123a5SAndrew Rybchenko 971e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS, 972e9c123a5SAndrew Rybchenko NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 9733c838a9fSAndrew Rybchenko 9743c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9753c838a9fSAndrew Rybchenko 9763c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9773c838a9fSAndrew Rybchenko rc = req.emr_rc; 9783c838a9fSAndrew Rybchenko goto fail1; 9793c838a9fSAndrew Rybchenko } 9803c838a9fSAndrew Rybchenko 981f0d3455bSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { 982a21b2f20SAndrew Rybchenko verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; 983348d3529SAndrew Rybchenko if (encp->enc_nvram_update_verify_result_supported) { 984348d3529SAndrew Rybchenko /* Result of update verification is missing */ 985e9c123a5SAndrew Rybchenko rc = EMSGSIZE; 986e9c123a5SAndrew Rybchenko goto fail2; 987e9c123a5SAndrew Rybchenko } 988f0d3455bSAndrew Rybchenko } else { 989a21b2f20SAndrew Rybchenko verify_result = 990e9c123a5SAndrew Rybchenko MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE); 991f0d3455bSAndrew Rybchenko } 992e9c123a5SAndrew Rybchenko 993348d3529SAndrew Rybchenko if ((encp->enc_nvram_update_verify_result_supported) && 994a21b2f20SAndrew Rybchenko (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) { 995348d3529SAndrew Rybchenko /* Update verification failed */ 996e9c123a5SAndrew Rybchenko rc = EINVAL; 997e9c123a5SAndrew Rybchenko goto fail3; 998e9c123a5SAndrew Rybchenko } 999e9c123a5SAndrew Rybchenko 1000a21b2f20SAndrew Rybchenko if (verify_resultp != NULL) 1001a21b2f20SAndrew Rybchenko *verify_resultp = verify_result; 1002e9c123a5SAndrew Rybchenko 10033c838a9fSAndrew Rybchenko return (0); 10043c838a9fSAndrew Rybchenko 1005e9c123a5SAndrew Rybchenko fail3: 1006e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail3); 1007e9c123a5SAndrew Rybchenko fail2: 1008e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 10093c838a9fSAndrew Rybchenko fail1: 1010460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 10113c838a9fSAndrew Rybchenko 1012e9c123a5SAndrew Rybchenko /* Always report verification result */ 1013a21b2f20SAndrew Rybchenko if (verify_resultp != NULL) 1014a21b2f20SAndrew Rybchenko *verify_resultp = verify_result; 1015e9c123a5SAndrew Rybchenko 10163c838a9fSAndrew Rybchenko return (rc); 10173c838a9fSAndrew Rybchenko } 10183c838a9fSAndrew Rybchenko 10193c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 10203c838a9fSAndrew Rybchenko 1021460cb568SAndrew Rybchenko __checkReturn efx_rc_t 10223c838a9fSAndrew Rybchenko efx_mcdi_nvram_test( 10233c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 10243c838a9fSAndrew Rybchenko __in uint32_t partn) 10253c838a9fSAndrew Rybchenko { 10263c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 10273c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 10283c838a9fSAndrew Rybchenko MC_CMD_NVRAM_TEST_OUT_LEN)]; 10293c838a9fSAndrew Rybchenko int result; 1030460cb568SAndrew Rybchenko efx_rc_t rc; 10313c838a9fSAndrew Rybchenko 10323c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 10333c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_TEST; 10343c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 10353c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 10363c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 10373c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 10383c838a9fSAndrew Rybchenko 10393c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 10403c838a9fSAndrew Rybchenko 10413c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 10423c838a9fSAndrew Rybchenko 10433c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 10443c838a9fSAndrew Rybchenko rc = req.emr_rc; 10453c838a9fSAndrew Rybchenko goto fail1; 10463c838a9fSAndrew Rybchenko } 10473c838a9fSAndrew Rybchenko 10483c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 10493c838a9fSAndrew Rybchenko rc = EMSGSIZE; 10503c838a9fSAndrew Rybchenko goto fail2; 10513c838a9fSAndrew Rybchenko } 10523c838a9fSAndrew Rybchenko 10533c838a9fSAndrew Rybchenko result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 10543c838a9fSAndrew Rybchenko if (result == MC_CMD_NVRAM_TEST_FAIL) { 10553c838a9fSAndrew Rybchenko 10563c838a9fSAndrew Rybchenko EFSYS_PROBE1(nvram_test_failure, int, partn); 10573c838a9fSAndrew Rybchenko 10583c838a9fSAndrew Rybchenko rc = (EINVAL); 10593c838a9fSAndrew Rybchenko goto fail3; 10603c838a9fSAndrew Rybchenko } 10613c838a9fSAndrew Rybchenko 10623c838a9fSAndrew Rybchenko return (0); 10633c838a9fSAndrew Rybchenko 10643c838a9fSAndrew Rybchenko fail3: 10653c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 10663c838a9fSAndrew Rybchenko fail2: 10673c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 10683c838a9fSAndrew Rybchenko fail1: 1069460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 10703c838a9fSAndrew Rybchenko 10713c838a9fSAndrew Rybchenko return (rc); 10723c838a9fSAndrew Rybchenko } 10733c838a9fSAndrew Rybchenko 10743c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 10753c838a9fSAndrew Rybchenko 10763c838a9fSAndrew Rybchenko 10773c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 1078