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 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) { 500*e919b7ecSAndrew 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 5155abce2b9SAndrew Rybchenko 516e948693eSPhilip Paeps void 517e948693eSPhilip Paeps efx_nvram_fini( 518e948693eSPhilip Paeps __in efx_nic_t *enp) 519e948693eSPhilip Paeps { 520e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 521e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 522e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 523e948693eSPhilip Paeps 5243d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 525e948693eSPhilip Paeps 526e948693eSPhilip Paeps enp->en_envop = NULL; 527e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_NVRAM; 528e948693eSPhilip Paeps } 529e948693eSPhilip Paeps 530e948693eSPhilip Paeps #endif /* EFSYS_OPT_NVRAM */ 5313c838a9fSAndrew Rybchenko 5323c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 5333c838a9fSAndrew Rybchenko 5343c838a9fSAndrew Rybchenko /* 5353c838a9fSAndrew Rybchenko * Internal MCDI request handling 5363c838a9fSAndrew Rybchenko */ 5373c838a9fSAndrew Rybchenko 538460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5393c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions( 5403c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5413c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 5423c838a9fSAndrew Rybchenko __in size_t size, 5433c838a9fSAndrew Rybchenko __out unsigned int *npartnp) 5443c838a9fSAndrew Rybchenko { 5453c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 5463c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 5473c838a9fSAndrew Rybchenko MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 5483c838a9fSAndrew Rybchenko unsigned int npartn; 549460cb568SAndrew Rybchenko efx_rc_t rc; 5503c838a9fSAndrew Rybchenko 5513c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 5523c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 5533c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5543c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 5553c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5563c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 5573c838a9fSAndrew Rybchenko 5583c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 5593c838a9fSAndrew Rybchenko 5603c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 5613c838a9fSAndrew Rybchenko rc = req.emr_rc; 5623c838a9fSAndrew Rybchenko goto fail1; 5633c838a9fSAndrew Rybchenko } 5643c838a9fSAndrew Rybchenko 5653c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 5663c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5673c838a9fSAndrew Rybchenko goto fail2; 5683c838a9fSAndrew Rybchenko } 5693c838a9fSAndrew Rybchenko npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 5703c838a9fSAndrew Rybchenko 5713c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 5723c838a9fSAndrew Rybchenko rc = ENOENT; 5733c838a9fSAndrew Rybchenko goto fail3; 5743c838a9fSAndrew Rybchenko } 5753c838a9fSAndrew Rybchenko 5763c838a9fSAndrew Rybchenko if (size < npartn * sizeof (uint32_t)) { 5773c838a9fSAndrew Rybchenko rc = ENOSPC; 5783c838a9fSAndrew Rybchenko goto fail3; 5793c838a9fSAndrew Rybchenko } 5803c838a9fSAndrew Rybchenko 5813c838a9fSAndrew Rybchenko *npartnp = npartn; 5823c838a9fSAndrew Rybchenko 5833c838a9fSAndrew Rybchenko memcpy(data, 5843c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 5853c838a9fSAndrew Rybchenko (npartn * sizeof (uint32_t))); 5863c838a9fSAndrew Rybchenko 5873c838a9fSAndrew Rybchenko return (0); 5883c838a9fSAndrew Rybchenko 5893c838a9fSAndrew Rybchenko fail3: 5903c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 5913c838a9fSAndrew Rybchenko fail2: 5923c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 5933c838a9fSAndrew Rybchenko fail1: 594460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5953c838a9fSAndrew Rybchenko 5963c838a9fSAndrew Rybchenko return (rc); 5973c838a9fSAndrew Rybchenko } 5983c838a9fSAndrew Rybchenko 599460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6003c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata( 6013c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6023c838a9fSAndrew Rybchenko __in uint32_t partn, 6033c838a9fSAndrew Rybchenko __out uint32_t *subtypep, 6043c838a9fSAndrew Rybchenko __out_ecount(4) uint16_t version[4], 6053c838a9fSAndrew Rybchenko __out_bcount_opt(size) char *descp, 6063c838a9fSAndrew Rybchenko __in size_t size) 6073c838a9fSAndrew Rybchenko { 6083c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 6093c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 6103c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 611460cb568SAndrew Rybchenko efx_rc_t rc; 6123c838a9fSAndrew Rybchenko 6133c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 6143c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_METADATA; 6153c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 6163c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 6173c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 6183c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 6193c838a9fSAndrew Rybchenko 6203c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 6213c838a9fSAndrew Rybchenko 622e7144483SAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 6233c838a9fSAndrew Rybchenko 6243c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6253c838a9fSAndrew Rybchenko rc = req.emr_rc; 6263c838a9fSAndrew Rybchenko goto fail1; 6273c838a9fSAndrew Rybchenko } 6283c838a9fSAndrew Rybchenko 6293c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 6303c838a9fSAndrew Rybchenko rc = EMSGSIZE; 6313c838a9fSAndrew Rybchenko goto fail2; 6323c838a9fSAndrew Rybchenko } 6333c838a9fSAndrew Rybchenko 6343c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6353c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 6363c838a9fSAndrew Rybchenko *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 6373c838a9fSAndrew Rybchenko } else { 6383c838a9fSAndrew Rybchenko *subtypep = 0; 6393c838a9fSAndrew Rybchenko } 6403c838a9fSAndrew Rybchenko 6413c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6423c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_VERSION_VALID)) { 6433c838a9fSAndrew Rybchenko version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 6443c838a9fSAndrew Rybchenko version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 6453c838a9fSAndrew Rybchenko version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 6463c838a9fSAndrew Rybchenko version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 6473c838a9fSAndrew Rybchenko } else { 6483c838a9fSAndrew Rybchenko version[0] = version[1] = version[2] = version[3] = 0; 6493c838a9fSAndrew Rybchenko } 6503c838a9fSAndrew Rybchenko 6513c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6523c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 6533c838a9fSAndrew Rybchenko /* Return optional descrition string */ 6543c838a9fSAndrew Rybchenko if ((descp != NULL) && (size > 0)) { 6553c838a9fSAndrew Rybchenko size_t desclen; 6563c838a9fSAndrew Rybchenko 6573c838a9fSAndrew Rybchenko descp[0] = '\0'; 6583c838a9fSAndrew Rybchenko desclen = (req.emr_out_length_used 6593c838a9fSAndrew Rybchenko - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 6603c838a9fSAndrew Rybchenko 6613c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(desclen, <=, 6623c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 6633c838a9fSAndrew Rybchenko 6643c838a9fSAndrew Rybchenko if (size < desclen) { 6653c838a9fSAndrew Rybchenko rc = ENOSPC; 6663c838a9fSAndrew Rybchenko goto fail3; 6673c838a9fSAndrew Rybchenko } 6683c838a9fSAndrew Rybchenko 6693c838a9fSAndrew Rybchenko memcpy(descp, MCDI_OUT2(req, char, 6703c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION), 6713c838a9fSAndrew Rybchenko desclen); 6723c838a9fSAndrew Rybchenko 6733c838a9fSAndrew Rybchenko /* Ensure string is NUL terminated */ 6743c838a9fSAndrew Rybchenko descp[desclen] = '\0'; 6753c838a9fSAndrew Rybchenko } 6763c838a9fSAndrew Rybchenko } 6773c838a9fSAndrew Rybchenko 6783c838a9fSAndrew Rybchenko return (0); 6793c838a9fSAndrew Rybchenko 6803c838a9fSAndrew Rybchenko fail3: 6813c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 6823c838a9fSAndrew Rybchenko fail2: 6833c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 6843c838a9fSAndrew Rybchenko fail1: 685460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 6863c838a9fSAndrew Rybchenko 6873c838a9fSAndrew Rybchenko return (rc); 6883c838a9fSAndrew Rybchenko } 6893c838a9fSAndrew Rybchenko 690460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6913c838a9fSAndrew Rybchenko efx_mcdi_nvram_info( 6923c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6933c838a9fSAndrew Rybchenko __in uint32_t partn, 6943c838a9fSAndrew Rybchenko __out_opt size_t *sizep, 6953c838a9fSAndrew Rybchenko __out_opt uint32_t *addressp, 6969cb71b16SAndrew Rybchenko __out_opt uint32_t *erase_sizep, 6979cb71b16SAndrew Rybchenko __out_opt uint32_t *write_sizep) 6983c838a9fSAndrew Rybchenko { 6993c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 7009cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN)]; 7013c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 702460cb568SAndrew Rybchenko efx_rc_t rc; 7033c838a9fSAndrew Rybchenko 7043c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7053c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_INFO; 7063c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 7073c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 7083c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7099cb71b16SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN; 7103c838a9fSAndrew Rybchenko 7113c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 7123c838a9fSAndrew Rybchenko 7133c838a9fSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 7143c838a9fSAndrew Rybchenko 7153c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7163c838a9fSAndrew Rybchenko rc = req.emr_rc; 7173c838a9fSAndrew Rybchenko goto fail1; 7183c838a9fSAndrew Rybchenko } 7193c838a9fSAndrew Rybchenko 7203c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 7213c838a9fSAndrew Rybchenko rc = EMSGSIZE; 7223c838a9fSAndrew Rybchenko goto fail2; 7233c838a9fSAndrew Rybchenko } 7243c838a9fSAndrew Rybchenko 7253c838a9fSAndrew Rybchenko if (sizep) 7263c838a9fSAndrew Rybchenko *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 7273c838a9fSAndrew Rybchenko 7283c838a9fSAndrew Rybchenko if (addressp) 7293c838a9fSAndrew Rybchenko *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 7303c838a9fSAndrew Rybchenko 7313c838a9fSAndrew Rybchenko if (erase_sizep) 7323c838a9fSAndrew Rybchenko *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 7333c838a9fSAndrew Rybchenko 7349cb71b16SAndrew Rybchenko if (write_sizep) { 7359cb71b16SAndrew Rybchenko *write_sizep = 7369cb71b16SAndrew Rybchenko (req.emr_out_length_used < 7379cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN) ? 7389cb71b16SAndrew Rybchenko 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE); 7399cb71b16SAndrew Rybchenko } 7409cb71b16SAndrew Rybchenko 7413c838a9fSAndrew Rybchenko return (0); 7423c838a9fSAndrew Rybchenko 7433c838a9fSAndrew Rybchenko fail2: 7443c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 7453c838a9fSAndrew Rybchenko fail1: 746460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7473c838a9fSAndrew Rybchenko 7483c838a9fSAndrew Rybchenko return (rc); 7493c838a9fSAndrew Rybchenko } 7503c838a9fSAndrew Rybchenko 751e9c123a5SAndrew Rybchenko /* 752e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified 753e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 754e9c123a5SAndrew Rybchenko */ 755460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7563c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start( 7573c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7583c838a9fSAndrew Rybchenko __in uint32_t partn) 7593c838a9fSAndrew Rybchenko { 760e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN, 7613c838a9fSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_START_OUT_LEN)]; 7623c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 763460cb568SAndrew Rybchenko efx_rc_t rc; 7643c838a9fSAndrew Rybchenko 7653c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7663c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 7673c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 768e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN; 7693c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7703c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 7713c838a9fSAndrew Rybchenko 772e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn); 773e9c123a5SAndrew Rybchenko 774e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS, 775e9c123a5SAndrew Rybchenko NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 7763c838a9fSAndrew Rybchenko 7773c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7783c838a9fSAndrew Rybchenko 7793c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7803c838a9fSAndrew Rybchenko rc = req.emr_rc; 7813c838a9fSAndrew Rybchenko goto fail1; 7823c838a9fSAndrew Rybchenko } 7833c838a9fSAndrew Rybchenko 7843c838a9fSAndrew Rybchenko return (0); 7853c838a9fSAndrew Rybchenko 7863c838a9fSAndrew Rybchenko fail1: 787460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7883c838a9fSAndrew Rybchenko 7893c838a9fSAndrew Rybchenko return (rc); 7903c838a9fSAndrew Rybchenko } 7913c838a9fSAndrew Rybchenko 792460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7933c838a9fSAndrew Rybchenko efx_mcdi_nvram_read( 7943c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7953c838a9fSAndrew Rybchenko __in uint32_t partn, 7963c838a9fSAndrew Rybchenko __in uint32_t offset, 7973c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 7989ad7e03fSAndrew Rybchenko __in size_t size, 7999ad7e03fSAndrew Rybchenko __in uint32_t mode) 8003c838a9fSAndrew Rybchenko { 8013c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 8029ad7e03fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN, 8033c838a9fSAndrew Rybchenko MC_CMD_NVRAM_READ_OUT_LENMAX)]; 804460cb568SAndrew Rybchenko efx_rc_t rc; 8053c838a9fSAndrew Rybchenko 8063c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 8073c838a9fSAndrew Rybchenko rc = EINVAL; 8083c838a9fSAndrew Rybchenko goto fail1; 8093c838a9fSAndrew Rybchenko } 8103c838a9fSAndrew Rybchenko 8113c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8123c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_READ; 8133c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8149ad7e03fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN; 8153c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8163c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 8173c838a9fSAndrew Rybchenko 8189ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn); 8199ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset); 8209ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size); 8219ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode); 8223c838a9fSAndrew Rybchenko 8233c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8243c838a9fSAndrew Rybchenko 8253c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8263c838a9fSAndrew Rybchenko rc = req.emr_rc; 8273c838a9fSAndrew Rybchenko goto fail1; 8283c838a9fSAndrew Rybchenko } 8293c838a9fSAndrew Rybchenko 8303c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 8313c838a9fSAndrew Rybchenko rc = EMSGSIZE; 8323c838a9fSAndrew Rybchenko goto fail2; 8333c838a9fSAndrew Rybchenko } 8343c838a9fSAndrew Rybchenko 8353c838a9fSAndrew Rybchenko memcpy(data, 8363c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 8373c838a9fSAndrew Rybchenko size); 8383c838a9fSAndrew Rybchenko 8393c838a9fSAndrew Rybchenko return (0); 8403c838a9fSAndrew Rybchenko 8413c838a9fSAndrew Rybchenko fail2: 8423c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 8433c838a9fSAndrew Rybchenko fail1: 844460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8453c838a9fSAndrew Rybchenko 8463c838a9fSAndrew Rybchenko return (rc); 8473c838a9fSAndrew Rybchenko } 8483c838a9fSAndrew Rybchenko 849460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8503c838a9fSAndrew Rybchenko efx_mcdi_nvram_erase( 8513c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8523c838a9fSAndrew Rybchenko __in uint32_t partn, 8533c838a9fSAndrew Rybchenko __in uint32_t offset, 8543c838a9fSAndrew Rybchenko __in size_t size) 8553c838a9fSAndrew Rybchenko { 8563c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 8573c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 8583c838a9fSAndrew Rybchenko MC_CMD_NVRAM_ERASE_OUT_LEN)]; 859460cb568SAndrew Rybchenko efx_rc_t rc; 8603c838a9fSAndrew Rybchenko 8613c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8623c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_ERASE; 8633c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8643c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 8653c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8663c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 8673c838a9fSAndrew Rybchenko 8683c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 8693c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 8703c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 8713c838a9fSAndrew Rybchenko 8723c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8733c838a9fSAndrew Rybchenko 8743c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8753c838a9fSAndrew Rybchenko rc = req.emr_rc; 8763c838a9fSAndrew Rybchenko goto fail1; 8773c838a9fSAndrew Rybchenko } 8783c838a9fSAndrew Rybchenko 8793c838a9fSAndrew Rybchenko return (0); 8803c838a9fSAndrew Rybchenko 8813c838a9fSAndrew Rybchenko fail1: 882460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8833c838a9fSAndrew Rybchenko 8843c838a9fSAndrew Rybchenko return (rc); 8853c838a9fSAndrew Rybchenko } 8863c838a9fSAndrew Rybchenko 88757396b7aSAndrew Rybchenko /* 88857396b7aSAndrew Rybchenko * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 88957396b7aSAndrew Rybchenko * Sienna and EF10 based boards. However EF10 based boards support the use 89057396b7aSAndrew Rybchenko * of this command with payloads up to the maximum MCDI V2 payload length. 89157396b7aSAndrew Rybchenko */ 892460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8933c838a9fSAndrew Rybchenko efx_mcdi_nvram_write( 8943c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8953c838a9fSAndrew Rybchenko __in uint32_t partn, 8963c838a9fSAndrew Rybchenko __in uint32_t offset, 897dbcc3c8fSAndrew Rybchenko __in_bcount(size) caddr_t data, 8983c838a9fSAndrew Rybchenko __in size_t size) 8993c838a9fSAndrew Rybchenko { 9003c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 90157396b7aSAndrew Rybchenko uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1, 90257396b7aSAndrew Rybchenko MCDI_CTL_SDU_LEN_MAX_V2)]; 903460cb568SAndrew Rybchenko efx_rc_t rc; 90457396b7aSAndrew Rybchenko size_t max_data_size; 9053c838a9fSAndrew Rybchenko 90657396b7aSAndrew Rybchenko max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length 90757396b7aSAndrew Rybchenko - MC_CMD_NVRAM_WRITE_IN_LEN(0); 90857396b7aSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0); 90957396b7aSAndrew Rybchenko EFSYS_ASSERT3U(max_data_size, <, 91057396b7aSAndrew Rybchenko enp->en_nic_cfg.enc_mcdi_max_payload_length); 91157396b7aSAndrew Rybchenko 91257396b7aSAndrew Rybchenko if (size > max_data_size) { 9133c838a9fSAndrew Rybchenko rc = EINVAL; 9143c838a9fSAndrew Rybchenko goto fail1; 9153c838a9fSAndrew Rybchenko } 9163c838a9fSAndrew Rybchenko 9173c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 9183c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_WRITE; 9193c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 9203c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 9213c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 9223c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 9233c838a9fSAndrew Rybchenko 9243c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 9253c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 9263c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 9273c838a9fSAndrew Rybchenko 9283c838a9fSAndrew Rybchenko memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 9293c838a9fSAndrew Rybchenko data, size); 9303c838a9fSAndrew Rybchenko 9313c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9323c838a9fSAndrew Rybchenko 9333c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9343c838a9fSAndrew Rybchenko rc = req.emr_rc; 9353c838a9fSAndrew Rybchenko goto fail2; 9363c838a9fSAndrew Rybchenko } 9373c838a9fSAndrew Rybchenko 9383c838a9fSAndrew Rybchenko return (0); 9393c838a9fSAndrew Rybchenko 9403c838a9fSAndrew Rybchenko fail2: 9413c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 9423c838a9fSAndrew Rybchenko fail1: 943460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9443c838a9fSAndrew Rybchenko 9453c838a9fSAndrew Rybchenko return (rc); 9463c838a9fSAndrew Rybchenko } 9473c838a9fSAndrew Rybchenko 948e9c123a5SAndrew Rybchenko 949e9c123a5SAndrew Rybchenko /* 950e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified 951e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 952e9c123a5SAndrew Rybchenko */ 953460cb568SAndrew Rybchenko __checkReturn efx_rc_t 9543c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish( 9553c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 9563c838a9fSAndrew Rybchenko __in uint32_t partn, 957e9c123a5SAndrew Rybchenko __in boolean_t reboot, 958a21b2f20SAndrew Rybchenko __out_opt uint32_t *verify_resultp) 9593c838a9fSAndrew Rybchenko { 960e9c123a5SAndrew Rybchenko const efx_nic_cfg_t *encp = &enp->en_nic_cfg; 9613c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 962e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN, 963e9c123a5SAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)]; 964a21b2f20SAndrew Rybchenko uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; 965460cb568SAndrew Rybchenko efx_rc_t rc; 9663c838a9fSAndrew Rybchenko 9673c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 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; 10333c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 10343c838a9fSAndrew Rybchenko MC_CMD_NVRAM_TEST_OUT_LEN)]; 10353c838a9fSAndrew Rybchenko int result; 1036460cb568SAndrew Rybchenko efx_rc_t rc; 10373c838a9fSAndrew Rybchenko 10383c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 10393c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_TEST; 10403c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 10413c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 10423c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 10433c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 10443c838a9fSAndrew Rybchenko 10453c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 10463c838a9fSAndrew Rybchenko 10473c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 10483c838a9fSAndrew Rybchenko 10493c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 10503c838a9fSAndrew Rybchenko rc = req.emr_rc; 10513c838a9fSAndrew Rybchenko goto fail1; 10523c838a9fSAndrew Rybchenko } 10533c838a9fSAndrew Rybchenko 10543c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 10553c838a9fSAndrew Rybchenko rc = EMSGSIZE; 10563c838a9fSAndrew Rybchenko goto fail2; 10573c838a9fSAndrew Rybchenko } 10583c838a9fSAndrew Rybchenko 10593c838a9fSAndrew Rybchenko result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 10603c838a9fSAndrew Rybchenko if (result == MC_CMD_NVRAM_TEST_FAIL) { 10613c838a9fSAndrew Rybchenko 10623c838a9fSAndrew Rybchenko EFSYS_PROBE1(nvram_test_failure, int, partn); 10633c838a9fSAndrew Rybchenko 10643c838a9fSAndrew Rybchenko rc = (EINVAL); 10653c838a9fSAndrew Rybchenko goto fail3; 10663c838a9fSAndrew Rybchenko } 10673c838a9fSAndrew Rybchenko 10683c838a9fSAndrew Rybchenko return (0); 10693c838a9fSAndrew Rybchenko 10703c838a9fSAndrew Rybchenko fail3: 10713c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 10723c838a9fSAndrew Rybchenko fail2: 10733c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 10743c838a9fSAndrew Rybchenko fail1: 1075460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 10763c838a9fSAndrew Rybchenko 10773c838a9fSAndrew Rybchenko return (rc); 10783c838a9fSAndrew Rybchenko } 10793c838a9fSAndrew Rybchenko 10803c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 10813c838a9fSAndrew Rybchenko 10823c838a9fSAndrew Rybchenko 10833c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 1084