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