1e948693eSPhilip Paeps /*- 2929c7febSAndrew Rybchenko * Copyright (c) 2009-2016 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_SIENA 40e948693eSPhilip Paeps 41ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_siena_ops = { 42e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 43e948693eSPhilip Paeps siena_nvram_test, /* envo_test */ 44e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 45bce88e31SAndrew Rybchenko siena_nvram_type_to_partn, /* envo_type_to_partn */ 4656bd83b0SAndrew Rybchenko siena_nvram_partn_size, /* envo_partn_size */ 475d846e87SAndrew Rybchenko siena_nvram_partn_rw_start, /* envo_partn_rw_start */ 480afdf29cSAndrew Rybchenko siena_nvram_partn_read, /* envo_partn_read */ 49b60ff840SAndrew Rybchenko siena_nvram_partn_erase, /* envo_partn_erase */ 50134c4c4aSAndrew Rybchenko siena_nvram_partn_write, /* envo_partn_write */ 51eb9703daSAndrew Rybchenko siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 5292187119SAndrew Rybchenko siena_nvram_partn_get_version, /* envo_partn_get_version */ 536d0b856cSAndrew Rybchenko siena_nvram_partn_set_version, /* envo_partn_set_version */ 545abce2b9SAndrew Rybchenko NULL, /* envo_partn_validate */ 55e948693eSPhilip Paeps }; 56e948693eSPhilip Paeps 57e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 58e948693eSPhilip Paeps 59de9775adSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 603c838a9fSAndrew Rybchenko 61ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_ef10_ops = { 623c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 63de9775adSAndrew Rybchenko ef10_nvram_test, /* envo_test */ 643c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 65bce88e31SAndrew Rybchenko ef10_nvram_type_to_partn, /* envo_type_to_partn */ 6656bd83b0SAndrew Rybchenko ef10_nvram_partn_size, /* envo_partn_size */ 675d846e87SAndrew Rybchenko ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ 680afdf29cSAndrew Rybchenko ef10_nvram_partn_read, /* envo_partn_read */ 69b60ff840SAndrew Rybchenko ef10_nvram_partn_erase, /* envo_partn_erase */ 70134c4c4aSAndrew Rybchenko ef10_nvram_partn_write, /* envo_partn_write */ 71eb9703daSAndrew Rybchenko ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 7292187119SAndrew Rybchenko ef10_nvram_partn_get_version, /* envo_partn_get_version */ 736d0b856cSAndrew Rybchenko ef10_nvram_partn_set_version, /* envo_partn_set_version */ 745abce2b9SAndrew Rybchenko ef10_nvram_buffer_validate, /* envo_buffer_validate */ 753c838a9fSAndrew Rybchenko }; 763c838a9fSAndrew Rybchenko 77de9775adSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 783c838a9fSAndrew Rybchenko 79460cb568SAndrew Rybchenko __checkReturn efx_rc_t 80e948693eSPhilip Paeps efx_nvram_init( 81e948693eSPhilip Paeps __in efx_nic_t *enp) 82e948693eSPhilip Paeps { 83ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop; 84460cb568SAndrew Rybchenko efx_rc_t rc; 85e948693eSPhilip Paeps 86e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 87e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 88e948693eSPhilip Paeps EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 89e948693eSPhilip Paeps 90e948693eSPhilip Paeps switch (enp->en_family) { 91e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 92e948693eSPhilip Paeps case EFX_FAMILY_SIENA: 93ec831f7fSAndrew Rybchenko envop = &__efx_nvram_siena_ops; 94e948693eSPhilip Paeps break; 95e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 96e948693eSPhilip Paeps 973c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 983c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 99ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops; 1003c838a9fSAndrew Rybchenko break; 1013c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 1023c838a9fSAndrew Rybchenko 103de9775adSAndrew Rybchenko #if EFSYS_OPT_MEDFORD 104de9775adSAndrew Rybchenko case EFX_FAMILY_MEDFORD: 105ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops; 106de9775adSAndrew Rybchenko break; 107de9775adSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */ 108de9775adSAndrew Rybchenko 109e948693eSPhilip Paeps default: 110e948693eSPhilip Paeps EFSYS_ASSERT(0); 111e948693eSPhilip Paeps rc = ENOTSUP; 112e948693eSPhilip Paeps goto fail1; 113e948693eSPhilip Paeps } 114e948693eSPhilip Paeps 115e948693eSPhilip Paeps enp->en_envop = envop; 116e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_NVRAM; 117e948693eSPhilip Paeps 118e948693eSPhilip Paeps return (0); 119e948693eSPhilip Paeps 120e948693eSPhilip Paeps fail1: 121460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 122e948693eSPhilip Paeps 123e948693eSPhilip Paeps return (rc); 124e948693eSPhilip Paeps } 125e948693eSPhilip Paeps 126e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 127e948693eSPhilip Paeps 128460cb568SAndrew Rybchenko __checkReturn efx_rc_t 129e948693eSPhilip Paeps efx_nvram_test( 130e948693eSPhilip Paeps __in efx_nic_t *enp) 131e948693eSPhilip Paeps { 132ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 133460cb568SAndrew Rybchenko efx_rc_t rc; 134e948693eSPhilip Paeps 135e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 136e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 137e948693eSPhilip Paeps 138e948693eSPhilip Paeps if ((rc = envop->envo_test(enp)) != 0) 139e948693eSPhilip Paeps goto fail1; 140e948693eSPhilip Paeps 141e948693eSPhilip Paeps return (0); 142e948693eSPhilip Paeps 143e948693eSPhilip Paeps fail1: 144460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 145e948693eSPhilip Paeps 146e948693eSPhilip Paeps return (rc); 147e948693eSPhilip Paeps } 148e948693eSPhilip Paeps 149e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 150e948693eSPhilip Paeps 151460cb568SAndrew Rybchenko __checkReturn efx_rc_t 152e948693eSPhilip Paeps efx_nvram_size( 153e948693eSPhilip Paeps __in efx_nic_t *enp, 154e948693eSPhilip Paeps __in efx_nvram_type_t type, 155e948693eSPhilip Paeps __out size_t *sizep) 156e948693eSPhilip Paeps { 157ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 15856bd83b0SAndrew Rybchenko uint32_t partn; 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 EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 165e948693eSPhilip Paeps 16656bd83b0SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 167e948693eSPhilip Paeps goto fail1; 168e948693eSPhilip Paeps 16956bd83b0SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0) 17056bd83b0SAndrew Rybchenko goto fail2; 17156bd83b0SAndrew Rybchenko 172e948693eSPhilip Paeps return (0); 173e948693eSPhilip Paeps 17456bd83b0SAndrew Rybchenko fail2: 17556bd83b0SAndrew Rybchenko EFSYS_PROBE(fail2); 176e948693eSPhilip Paeps fail1: 177460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 17856bd83b0SAndrew Rybchenko *sizep = 0; 179e948693eSPhilip Paeps 180e948693eSPhilip Paeps return (rc); 181e948693eSPhilip Paeps } 182e948693eSPhilip Paeps 183460cb568SAndrew Rybchenko __checkReturn efx_rc_t 184e948693eSPhilip Paeps efx_nvram_get_version( 185e948693eSPhilip Paeps __in efx_nic_t *enp, 186e948693eSPhilip Paeps __in efx_nvram_type_t type, 187e948693eSPhilip Paeps __out uint32_t *subtypep, 188e948693eSPhilip Paeps __out_ecount(4) uint16_t version[4]) 189e948693eSPhilip Paeps { 190ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 19192187119SAndrew Rybchenko uint32_t partn; 192460cb568SAndrew Rybchenko efx_rc_t rc; 193e948693eSPhilip Paeps 194e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 195e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 196e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 197e948693eSPhilip Paeps 198e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 199e948693eSPhilip Paeps 20092187119SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 201e948693eSPhilip Paeps goto fail1; 202e948693eSPhilip Paeps 20392187119SAndrew Rybchenko if ((rc = envop->envo_partn_get_version(enp, partn, 20492187119SAndrew Rybchenko subtypep, version)) != 0) 20592187119SAndrew Rybchenko goto fail2; 20692187119SAndrew Rybchenko 207e948693eSPhilip Paeps return (0); 208e948693eSPhilip Paeps 20992187119SAndrew Rybchenko fail2: 21092187119SAndrew Rybchenko EFSYS_PROBE(fail2); 211e948693eSPhilip Paeps fail1: 212460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 213e948693eSPhilip Paeps 214e948693eSPhilip Paeps return (rc); 215e948693eSPhilip Paeps } 216e948693eSPhilip Paeps 217460cb568SAndrew Rybchenko __checkReturn efx_rc_t 218e948693eSPhilip Paeps efx_nvram_rw_start( 219e948693eSPhilip Paeps __in efx_nic_t *enp, 220e948693eSPhilip Paeps __in efx_nvram_type_t type, 221e948693eSPhilip Paeps __out_opt size_t *chunk_sizep) 222e948693eSPhilip Paeps { 223ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2245d846e87SAndrew Rybchenko uint32_t partn; 225460cb568SAndrew Rybchenko efx_rc_t rc; 226e948693eSPhilip Paeps 227e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 228e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 229e948693eSPhilip Paeps 230e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 231e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 232e948693eSPhilip Paeps 233e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 234e948693eSPhilip Paeps 2355d846e87SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 236e948693eSPhilip Paeps goto fail1; 237e948693eSPhilip Paeps 2385d846e87SAndrew Rybchenko if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) 2395d846e87SAndrew Rybchenko goto fail2; 2405d846e87SAndrew Rybchenko 241e948693eSPhilip Paeps enp->en_nvram_locked = type; 242e948693eSPhilip Paeps 243e948693eSPhilip Paeps return (0); 244e948693eSPhilip Paeps 2455d846e87SAndrew Rybchenko fail2: 2465d846e87SAndrew Rybchenko EFSYS_PROBE(fail2); 247e948693eSPhilip Paeps fail1: 248460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 249e948693eSPhilip Paeps 250e948693eSPhilip Paeps return (rc); 251e948693eSPhilip Paeps } 252e948693eSPhilip Paeps 253460cb568SAndrew Rybchenko __checkReturn efx_rc_t 254e948693eSPhilip Paeps efx_nvram_read_chunk( 255e948693eSPhilip Paeps __in efx_nic_t *enp, 256e948693eSPhilip Paeps __in efx_nvram_type_t type, 257e948693eSPhilip Paeps __in unsigned int offset, 258e948693eSPhilip Paeps __out_bcount(size) caddr_t data, 259e948693eSPhilip Paeps __in size_t size) 260e948693eSPhilip Paeps { 261ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2620afdf29cSAndrew Rybchenko uint32_t partn; 263460cb568SAndrew Rybchenko efx_rc_t rc; 264e948693eSPhilip Paeps 265e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 266e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 267e948693eSPhilip Paeps 268e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 269e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 270e948693eSPhilip Paeps 271e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 272e948693eSPhilip Paeps 2730afdf29cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 274e948693eSPhilip Paeps goto fail1; 275e948693eSPhilip Paeps 2760afdf29cSAndrew Rybchenko if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) 2770afdf29cSAndrew Rybchenko goto fail2; 2780afdf29cSAndrew Rybchenko 279e948693eSPhilip Paeps return (0); 280e948693eSPhilip Paeps 2810afdf29cSAndrew Rybchenko fail2: 2820afdf29cSAndrew Rybchenko EFSYS_PROBE(fail2); 283e948693eSPhilip Paeps fail1: 284460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 285e948693eSPhilip Paeps 286e948693eSPhilip Paeps return (rc); 287e948693eSPhilip Paeps } 288e948693eSPhilip Paeps 289460cb568SAndrew Rybchenko __checkReturn efx_rc_t 290e948693eSPhilip Paeps efx_nvram_erase( 291e948693eSPhilip Paeps __in efx_nic_t *enp, 292e948693eSPhilip Paeps __in efx_nvram_type_t type) 293e948693eSPhilip Paeps { 294ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 295b60ff840SAndrew Rybchenko unsigned int offset = 0; 296b60ff840SAndrew Rybchenko size_t size = 0; 297b60ff840SAndrew Rybchenko uint32_t partn; 298460cb568SAndrew Rybchenko efx_rc_t rc; 299e948693eSPhilip Paeps 300e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 301e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 302e948693eSPhilip Paeps 303e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 304e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 305e948693eSPhilip Paeps 306e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 307e948693eSPhilip Paeps 308b60ff840SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 309e948693eSPhilip Paeps goto fail1; 310e948693eSPhilip Paeps 311b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0) 312b60ff840SAndrew Rybchenko goto fail2; 313b60ff840SAndrew Rybchenko 314b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0) 315b60ff840SAndrew Rybchenko goto fail3; 316b60ff840SAndrew Rybchenko 317e948693eSPhilip Paeps return (0); 318e948693eSPhilip Paeps 319b60ff840SAndrew Rybchenko fail3: 320b60ff840SAndrew Rybchenko EFSYS_PROBE(fail3); 321b60ff840SAndrew Rybchenko fail2: 322b60ff840SAndrew Rybchenko EFSYS_PROBE(fail2); 323e948693eSPhilip Paeps fail1: 324460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 325e948693eSPhilip Paeps 326e948693eSPhilip Paeps return (rc); 327e948693eSPhilip Paeps } 328e948693eSPhilip Paeps 329460cb568SAndrew Rybchenko __checkReturn efx_rc_t 330e948693eSPhilip Paeps efx_nvram_write_chunk( 331e948693eSPhilip Paeps __in efx_nic_t *enp, 332e948693eSPhilip Paeps __in efx_nvram_type_t type, 333e948693eSPhilip Paeps __in unsigned int offset, 334e948693eSPhilip Paeps __in_bcount(size) caddr_t data, 335e948693eSPhilip Paeps __in size_t size) 336e948693eSPhilip Paeps { 337ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 338134c4c4aSAndrew 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 344e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 345e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 346e948693eSPhilip Paeps 347e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 348e948693eSPhilip Paeps 349134c4c4aSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 350e948693eSPhilip Paeps goto fail1; 351e948693eSPhilip Paeps 352134c4c4aSAndrew Rybchenko if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0) 353134c4c4aSAndrew Rybchenko goto fail2; 354134c4c4aSAndrew Rybchenko 355e948693eSPhilip Paeps return (0); 356e948693eSPhilip Paeps 357134c4c4aSAndrew Rybchenko fail2: 358134c4c4aSAndrew Rybchenko EFSYS_PROBE(fail2); 359e948693eSPhilip Paeps fail1: 360460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 361e948693eSPhilip Paeps 362e948693eSPhilip Paeps return (rc); 363e948693eSPhilip Paeps } 364e948693eSPhilip Paeps 365*e9c123a5SAndrew Rybchenko __checkReturn efx_rc_t 366e948693eSPhilip Paeps efx_nvram_rw_finish( 367e948693eSPhilip Paeps __in efx_nic_t *enp, 368e948693eSPhilip Paeps __in efx_nvram_type_t type) 369e948693eSPhilip Paeps { 370ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 371eb9703daSAndrew Rybchenko uint32_t partn; 372*e9c123a5SAndrew Rybchenko efx_rc_t rc; 373e948693eSPhilip Paeps 374e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 375e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 376e948693eSPhilip Paeps 377e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 378e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 379e948693eSPhilip Paeps 380e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); 381e948693eSPhilip Paeps 382*e9c123a5SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 383*e9c123a5SAndrew Rybchenko goto fail1; 384*e9c123a5SAndrew Rybchenko 385*e9c123a5SAndrew Rybchenko if ((rc = envop->envo_partn_rw_finish(enp, partn)) != 0) 386*e9c123a5SAndrew Rybchenko goto fail2; 387e948693eSPhilip Paeps 388e948693eSPhilip Paeps enp->en_nvram_locked = EFX_NVRAM_INVALID; 389*e9c123a5SAndrew Rybchenko 390*e9c123a5SAndrew Rybchenko return (0); 391*e9c123a5SAndrew Rybchenko 392*e9c123a5SAndrew Rybchenko fail2: 393*e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 394*e9c123a5SAndrew Rybchenko enp->en_nvram_locked = EFX_NVRAM_INVALID; 395*e9c123a5SAndrew Rybchenko 396*e9c123a5SAndrew Rybchenko fail1: 397*e9c123a5SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 398*e9c123a5SAndrew Rybchenko 399*e9c123a5SAndrew Rybchenko return (rc); 400e948693eSPhilip Paeps } 401e948693eSPhilip Paeps 402460cb568SAndrew Rybchenko __checkReturn efx_rc_t 403e948693eSPhilip Paeps efx_nvram_set_version( 404e948693eSPhilip Paeps __in efx_nic_t *enp, 405e948693eSPhilip Paeps __in efx_nvram_type_t type, 4063c838a9fSAndrew Rybchenko __in_ecount(4) uint16_t version[4]) 407e948693eSPhilip Paeps { 408ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4096d0b856cSAndrew Rybchenko uint32_t partn; 410460cb568SAndrew Rybchenko efx_rc_t rc; 411e948693eSPhilip Paeps 412e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 413e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 414e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 415e948693eSPhilip Paeps 416e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 417e948693eSPhilip Paeps 418e948693eSPhilip Paeps /* 419e948693eSPhilip Paeps * The Siena implementation of envo_set_version() will attempt to 420e948693eSPhilip Paeps * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. 421e948693eSPhilip Paeps * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 422e948693eSPhilip Paeps */ 423e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 424e948693eSPhilip Paeps 4256d0b856cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 426e948693eSPhilip Paeps goto fail1; 427e948693eSPhilip Paeps 4286d0b856cSAndrew Rybchenko if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0) 4296d0b856cSAndrew Rybchenko goto fail2; 4306d0b856cSAndrew Rybchenko 431e948693eSPhilip Paeps return (0); 432e948693eSPhilip Paeps 4336d0b856cSAndrew Rybchenko fail2: 4346d0b856cSAndrew Rybchenko EFSYS_PROBE(fail2); 435e948693eSPhilip Paeps fail1: 436460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 437e948693eSPhilip Paeps 438e948693eSPhilip Paeps return (rc); 439e948693eSPhilip Paeps } 440e948693eSPhilip Paeps 4415abce2b9SAndrew Rybchenko /* Validate buffer contents (before writing to flash) */ 4425abce2b9SAndrew Rybchenko __checkReturn efx_rc_t 4435abce2b9SAndrew Rybchenko efx_nvram_validate( 4445abce2b9SAndrew Rybchenko __in efx_nic_t *enp, 4455abce2b9SAndrew Rybchenko __in efx_nvram_type_t type, 4465abce2b9SAndrew Rybchenko __in_bcount(partn_size) caddr_t partn_data, 4475abce2b9SAndrew Rybchenko __in size_t partn_size) 4485abce2b9SAndrew Rybchenko { 449ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4505abce2b9SAndrew Rybchenko uint32_t partn; 4515abce2b9SAndrew Rybchenko efx_rc_t rc; 4525abce2b9SAndrew Rybchenko 4535abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4545abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 4555abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 4565abce2b9SAndrew Rybchenko 4575abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 4585abce2b9SAndrew Rybchenko 4595abce2b9SAndrew Rybchenko 4605abce2b9SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 4615abce2b9SAndrew Rybchenko goto fail1; 4625abce2b9SAndrew Rybchenko 4635abce2b9SAndrew Rybchenko if (envop->envo_type_to_partn != NULL && 4645abce2b9SAndrew Rybchenko ((rc = envop->envo_buffer_validate(enp, partn, 4655abce2b9SAndrew Rybchenko partn_data, partn_size)) != 0)) 4665abce2b9SAndrew Rybchenko goto fail2; 4675abce2b9SAndrew Rybchenko 4685abce2b9SAndrew Rybchenko return (0); 4695abce2b9SAndrew Rybchenko 4705abce2b9SAndrew Rybchenko fail2: 4715abce2b9SAndrew Rybchenko EFSYS_PROBE(fail2); 4725abce2b9SAndrew Rybchenko fail1: 4735abce2b9SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4745abce2b9SAndrew Rybchenko 4755abce2b9SAndrew Rybchenko return (rc); 4765abce2b9SAndrew Rybchenko } 4775abce2b9SAndrew Rybchenko 4785abce2b9SAndrew Rybchenko 479e948693eSPhilip Paeps void 480e948693eSPhilip Paeps efx_nvram_fini( 481e948693eSPhilip Paeps __in efx_nic_t *enp) 482e948693eSPhilip Paeps { 483e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 484e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 485e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 486e948693eSPhilip Paeps 487e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); 488e948693eSPhilip Paeps 489e948693eSPhilip Paeps enp->en_envop = NULL; 490e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_NVRAM; 491e948693eSPhilip Paeps } 492e948693eSPhilip Paeps 493e948693eSPhilip Paeps #endif /* EFSYS_OPT_NVRAM */ 4943c838a9fSAndrew Rybchenko 4953c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 4963c838a9fSAndrew Rybchenko 4973c838a9fSAndrew Rybchenko /* 4983c838a9fSAndrew Rybchenko * Internal MCDI request handling 4993c838a9fSAndrew Rybchenko */ 5003c838a9fSAndrew Rybchenko 501460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5023c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions( 5033c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5043c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 5053c838a9fSAndrew Rybchenko __in size_t size, 5063c838a9fSAndrew Rybchenko __out unsigned int *npartnp) 5073c838a9fSAndrew Rybchenko { 5083c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 5093c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 5103c838a9fSAndrew Rybchenko MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 5113c838a9fSAndrew Rybchenko unsigned int npartn; 512460cb568SAndrew Rybchenko efx_rc_t rc; 5133c838a9fSAndrew Rybchenko 5143c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 5153c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 5163c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5173c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 5183c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5193c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 5203c838a9fSAndrew Rybchenko 5213c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 5223c838a9fSAndrew Rybchenko 5233c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 5243c838a9fSAndrew Rybchenko rc = req.emr_rc; 5253c838a9fSAndrew Rybchenko goto fail1; 5263c838a9fSAndrew Rybchenko } 5273c838a9fSAndrew Rybchenko 5283c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 5293c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5303c838a9fSAndrew Rybchenko goto fail2; 5313c838a9fSAndrew Rybchenko } 5323c838a9fSAndrew Rybchenko npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 5333c838a9fSAndrew Rybchenko 5343c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 5353c838a9fSAndrew Rybchenko rc = ENOENT; 5363c838a9fSAndrew Rybchenko goto fail3; 5373c838a9fSAndrew Rybchenko } 5383c838a9fSAndrew Rybchenko 5393c838a9fSAndrew Rybchenko if (size < npartn * sizeof (uint32_t)) { 5403c838a9fSAndrew Rybchenko rc = ENOSPC; 5413c838a9fSAndrew Rybchenko goto fail3; 5423c838a9fSAndrew Rybchenko } 5433c838a9fSAndrew Rybchenko 5443c838a9fSAndrew Rybchenko *npartnp = npartn; 5453c838a9fSAndrew Rybchenko 5463c838a9fSAndrew Rybchenko memcpy(data, 5473c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 5483c838a9fSAndrew Rybchenko (npartn * sizeof (uint32_t))); 5493c838a9fSAndrew Rybchenko 5503c838a9fSAndrew Rybchenko return (0); 5513c838a9fSAndrew Rybchenko 5523c838a9fSAndrew Rybchenko fail3: 5533c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 5543c838a9fSAndrew Rybchenko fail2: 5553c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 5563c838a9fSAndrew Rybchenko fail1: 557460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5583c838a9fSAndrew Rybchenko 5593c838a9fSAndrew Rybchenko return (rc); 5603c838a9fSAndrew Rybchenko } 5613c838a9fSAndrew Rybchenko 562460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5633c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata( 5643c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5653c838a9fSAndrew Rybchenko __in uint32_t partn, 5663c838a9fSAndrew Rybchenko __out uint32_t *subtypep, 5673c838a9fSAndrew Rybchenko __out_ecount(4) uint16_t version[4], 5683c838a9fSAndrew Rybchenko __out_bcount_opt(size) char *descp, 5693c838a9fSAndrew Rybchenko __in size_t size) 5703c838a9fSAndrew Rybchenko { 5713c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 5723c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 5733c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 574460cb568SAndrew Rybchenko efx_rc_t rc; 5753c838a9fSAndrew Rybchenko 5763c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 5773c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_METADATA; 5783c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5793c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 5803c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5813c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 5823c838a9fSAndrew Rybchenko 5833c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 5843c838a9fSAndrew Rybchenko 5853c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 5863c838a9fSAndrew Rybchenko 5873c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 5883c838a9fSAndrew Rybchenko rc = req.emr_rc; 5893c838a9fSAndrew Rybchenko goto fail1; 5903c838a9fSAndrew Rybchenko } 5913c838a9fSAndrew Rybchenko 5923c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 5933c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5943c838a9fSAndrew Rybchenko goto fail2; 5953c838a9fSAndrew Rybchenko } 5963c838a9fSAndrew Rybchenko 5973c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 5983c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 5993c838a9fSAndrew Rybchenko *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 6003c838a9fSAndrew Rybchenko } else { 6013c838a9fSAndrew Rybchenko *subtypep = 0; 6023c838a9fSAndrew Rybchenko } 6033c838a9fSAndrew Rybchenko 6043c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6053c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_VERSION_VALID)) { 6063c838a9fSAndrew Rybchenko version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 6073c838a9fSAndrew Rybchenko version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 6083c838a9fSAndrew Rybchenko version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 6093c838a9fSAndrew Rybchenko version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 6103c838a9fSAndrew Rybchenko } else { 6113c838a9fSAndrew Rybchenko version[0] = version[1] = version[2] = version[3] = 0; 6123c838a9fSAndrew Rybchenko } 6133c838a9fSAndrew Rybchenko 6143c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6153c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 6163c838a9fSAndrew Rybchenko /* Return optional descrition string */ 6173c838a9fSAndrew Rybchenko if ((descp != NULL) && (size > 0)) { 6183c838a9fSAndrew Rybchenko size_t desclen; 6193c838a9fSAndrew Rybchenko 6203c838a9fSAndrew Rybchenko descp[0] = '\0'; 6213c838a9fSAndrew Rybchenko desclen = (req.emr_out_length_used 6223c838a9fSAndrew Rybchenko - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 6233c838a9fSAndrew Rybchenko 6243c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(desclen, <=, 6253c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 6263c838a9fSAndrew Rybchenko 6273c838a9fSAndrew Rybchenko if (size < desclen) { 6283c838a9fSAndrew Rybchenko rc = ENOSPC; 6293c838a9fSAndrew Rybchenko goto fail3; 6303c838a9fSAndrew Rybchenko } 6313c838a9fSAndrew Rybchenko 6323c838a9fSAndrew Rybchenko memcpy(descp, MCDI_OUT2(req, char, 6333c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION), 6343c838a9fSAndrew Rybchenko desclen); 6353c838a9fSAndrew Rybchenko 6363c838a9fSAndrew Rybchenko /* Ensure string is NUL terminated */ 6373c838a9fSAndrew Rybchenko descp[desclen] = '\0'; 6383c838a9fSAndrew Rybchenko } 6393c838a9fSAndrew Rybchenko } 6403c838a9fSAndrew Rybchenko 6413c838a9fSAndrew Rybchenko return (0); 6423c838a9fSAndrew Rybchenko 6433c838a9fSAndrew Rybchenko fail3: 6443c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 6453c838a9fSAndrew Rybchenko fail2: 6463c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 6473c838a9fSAndrew Rybchenko fail1: 648460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 6493c838a9fSAndrew Rybchenko 6503c838a9fSAndrew Rybchenko return (rc); 6513c838a9fSAndrew Rybchenko } 6523c838a9fSAndrew Rybchenko 653460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6543c838a9fSAndrew Rybchenko efx_mcdi_nvram_info( 6553c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6563c838a9fSAndrew Rybchenko __in uint32_t partn, 6573c838a9fSAndrew Rybchenko __out_opt size_t *sizep, 6583c838a9fSAndrew Rybchenko __out_opt uint32_t *addressp, 6599cb71b16SAndrew Rybchenko __out_opt uint32_t *erase_sizep, 6609cb71b16SAndrew Rybchenko __out_opt uint32_t *write_sizep) 6613c838a9fSAndrew Rybchenko { 6623c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 6639cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN)]; 6643c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 665460cb568SAndrew Rybchenko efx_rc_t rc; 6663c838a9fSAndrew Rybchenko 6673c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 6683c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_INFO; 6693c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 6703c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 6713c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 6729cb71b16SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN; 6733c838a9fSAndrew Rybchenko 6743c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 6753c838a9fSAndrew Rybchenko 6763c838a9fSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 6773c838a9fSAndrew Rybchenko 6783c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6793c838a9fSAndrew Rybchenko rc = req.emr_rc; 6803c838a9fSAndrew Rybchenko goto fail1; 6813c838a9fSAndrew Rybchenko } 6823c838a9fSAndrew Rybchenko 6833c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 6843c838a9fSAndrew Rybchenko rc = EMSGSIZE; 6853c838a9fSAndrew Rybchenko goto fail2; 6863c838a9fSAndrew Rybchenko } 6873c838a9fSAndrew Rybchenko 6883c838a9fSAndrew Rybchenko if (sizep) 6893c838a9fSAndrew Rybchenko *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 6903c838a9fSAndrew Rybchenko 6913c838a9fSAndrew Rybchenko if (addressp) 6923c838a9fSAndrew Rybchenko *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 6933c838a9fSAndrew Rybchenko 6943c838a9fSAndrew Rybchenko if (erase_sizep) 6953c838a9fSAndrew Rybchenko *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 6963c838a9fSAndrew Rybchenko 6979cb71b16SAndrew Rybchenko if (write_sizep) { 6989cb71b16SAndrew Rybchenko *write_sizep = 6999cb71b16SAndrew Rybchenko (req.emr_out_length_used < 7009cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN) ? 7019cb71b16SAndrew Rybchenko 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE); 7029cb71b16SAndrew Rybchenko } 7039cb71b16SAndrew Rybchenko 7043c838a9fSAndrew Rybchenko return (0); 7053c838a9fSAndrew Rybchenko 7063c838a9fSAndrew Rybchenko fail2: 7073c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 7083c838a9fSAndrew Rybchenko fail1: 709460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7103c838a9fSAndrew Rybchenko 7113c838a9fSAndrew Rybchenko return (rc); 7123c838a9fSAndrew Rybchenko } 7133c838a9fSAndrew Rybchenko 714*e9c123a5SAndrew Rybchenko /* 715*e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified 716*e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 717*e9c123a5SAndrew Rybchenko */ 718460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7193c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start( 7203c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7213c838a9fSAndrew Rybchenko __in uint32_t partn) 7223c838a9fSAndrew Rybchenko { 723*e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN, 7243c838a9fSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_START_OUT_LEN)]; 7253c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 726460cb568SAndrew Rybchenko efx_rc_t rc; 7273c838a9fSAndrew Rybchenko 7283c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7293c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 7303c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 731*e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN; 7323c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7333c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 7343c838a9fSAndrew Rybchenko 735*e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn); 736*e9c123a5SAndrew Rybchenko 737*e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS, 738*e9c123a5SAndrew Rybchenko NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 7393c838a9fSAndrew Rybchenko 7403c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7413c838a9fSAndrew Rybchenko 7423c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7433c838a9fSAndrew Rybchenko rc = req.emr_rc; 7443c838a9fSAndrew Rybchenko goto fail1; 7453c838a9fSAndrew Rybchenko } 7463c838a9fSAndrew Rybchenko 7473c838a9fSAndrew Rybchenko return (0); 7483c838a9fSAndrew Rybchenko 7493c838a9fSAndrew Rybchenko fail1: 750460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7513c838a9fSAndrew Rybchenko 7523c838a9fSAndrew Rybchenko return (rc); 7533c838a9fSAndrew Rybchenko } 7543c838a9fSAndrew Rybchenko 755460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7563c838a9fSAndrew Rybchenko efx_mcdi_nvram_read( 7573c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7583c838a9fSAndrew Rybchenko __in uint32_t partn, 7593c838a9fSAndrew Rybchenko __in uint32_t offset, 7603c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 7619ad7e03fSAndrew Rybchenko __in size_t size, 7629ad7e03fSAndrew Rybchenko __in uint32_t mode) 7633c838a9fSAndrew Rybchenko { 7643c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 7659ad7e03fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN, 7663c838a9fSAndrew Rybchenko MC_CMD_NVRAM_READ_OUT_LENMAX)]; 767460cb568SAndrew Rybchenko efx_rc_t rc; 7683c838a9fSAndrew Rybchenko 7693c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 7703c838a9fSAndrew Rybchenko rc = EINVAL; 7713c838a9fSAndrew Rybchenko goto fail1; 7723c838a9fSAndrew Rybchenko } 7733c838a9fSAndrew Rybchenko 7743c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7753c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_READ; 7763c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 7779ad7e03fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN; 7783c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7793c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 7803c838a9fSAndrew Rybchenko 7819ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn); 7829ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset); 7839ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size); 7849ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode); 7853c838a9fSAndrew Rybchenko 7863c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7873c838a9fSAndrew Rybchenko 7883c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7893c838a9fSAndrew Rybchenko rc = req.emr_rc; 7903c838a9fSAndrew Rybchenko goto fail1; 7913c838a9fSAndrew Rybchenko } 7923c838a9fSAndrew Rybchenko 7933c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 7943c838a9fSAndrew Rybchenko rc = EMSGSIZE; 7953c838a9fSAndrew Rybchenko goto fail2; 7963c838a9fSAndrew Rybchenko } 7973c838a9fSAndrew Rybchenko 7983c838a9fSAndrew Rybchenko memcpy(data, 7993c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 8003c838a9fSAndrew Rybchenko size); 8013c838a9fSAndrew Rybchenko 8023c838a9fSAndrew Rybchenko return (0); 8033c838a9fSAndrew Rybchenko 8043c838a9fSAndrew Rybchenko fail2: 8053c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 8063c838a9fSAndrew Rybchenko fail1: 807460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8083c838a9fSAndrew Rybchenko 8093c838a9fSAndrew Rybchenko return (rc); 8103c838a9fSAndrew Rybchenko } 8113c838a9fSAndrew Rybchenko 812460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8133c838a9fSAndrew Rybchenko efx_mcdi_nvram_erase( 8143c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8153c838a9fSAndrew Rybchenko __in uint32_t partn, 8163c838a9fSAndrew Rybchenko __in uint32_t offset, 8173c838a9fSAndrew Rybchenko __in size_t size) 8183c838a9fSAndrew Rybchenko { 8193c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 8203c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 8213c838a9fSAndrew Rybchenko MC_CMD_NVRAM_ERASE_OUT_LEN)]; 822460cb568SAndrew Rybchenko efx_rc_t rc; 8233c838a9fSAndrew Rybchenko 8243c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8253c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_ERASE; 8263c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8273c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 8283c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8293c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 8303c838a9fSAndrew Rybchenko 8313c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 8323c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 8333c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 8343c838a9fSAndrew Rybchenko 8353c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8363c838a9fSAndrew Rybchenko 8373c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8383c838a9fSAndrew Rybchenko rc = req.emr_rc; 8393c838a9fSAndrew Rybchenko goto fail1; 8403c838a9fSAndrew Rybchenko } 8413c838a9fSAndrew Rybchenko 8423c838a9fSAndrew Rybchenko return (0); 8433c838a9fSAndrew Rybchenko 8443c838a9fSAndrew Rybchenko fail1: 845460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8463c838a9fSAndrew Rybchenko 8473c838a9fSAndrew Rybchenko return (rc); 8483c838a9fSAndrew Rybchenko } 8493c838a9fSAndrew Rybchenko 85057396b7aSAndrew Rybchenko /* 85157396b7aSAndrew Rybchenko * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 85257396b7aSAndrew Rybchenko * Sienna and EF10 based boards. However EF10 based boards support the use 85357396b7aSAndrew Rybchenko * of this command with payloads up to the maximum MCDI V2 payload length. 85457396b7aSAndrew Rybchenko */ 855460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8563c838a9fSAndrew Rybchenko efx_mcdi_nvram_write( 8573c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8583c838a9fSAndrew Rybchenko __in uint32_t partn, 8593c838a9fSAndrew Rybchenko __in uint32_t offset, 8603c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 8613c838a9fSAndrew Rybchenko __in size_t size) 8623c838a9fSAndrew Rybchenko { 8633c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 86457396b7aSAndrew Rybchenko uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1, 86557396b7aSAndrew Rybchenko MCDI_CTL_SDU_LEN_MAX_V2)]; 866460cb568SAndrew Rybchenko efx_rc_t rc; 86757396b7aSAndrew Rybchenko size_t max_data_size; 8683c838a9fSAndrew Rybchenko 86957396b7aSAndrew Rybchenko max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length 87057396b7aSAndrew Rybchenko - MC_CMD_NVRAM_WRITE_IN_LEN(0); 87157396b7aSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0); 87257396b7aSAndrew Rybchenko EFSYS_ASSERT3U(max_data_size, <, 87357396b7aSAndrew Rybchenko enp->en_nic_cfg.enc_mcdi_max_payload_length); 87457396b7aSAndrew Rybchenko 87557396b7aSAndrew Rybchenko if (size > max_data_size) { 8763c838a9fSAndrew Rybchenko rc = EINVAL; 8773c838a9fSAndrew Rybchenko goto fail1; 8783c838a9fSAndrew Rybchenko } 8793c838a9fSAndrew Rybchenko 8803c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8813c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_WRITE; 8823c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8833c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 8843c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8853c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 8863c838a9fSAndrew Rybchenko 8873c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 8883c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 8893c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 8903c838a9fSAndrew Rybchenko 8913c838a9fSAndrew Rybchenko memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 8923c838a9fSAndrew Rybchenko data, size); 8933c838a9fSAndrew Rybchenko 8943c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8953c838a9fSAndrew Rybchenko 8963c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8973c838a9fSAndrew Rybchenko rc = req.emr_rc; 8983c838a9fSAndrew Rybchenko goto fail2; 8993c838a9fSAndrew Rybchenko } 9003c838a9fSAndrew Rybchenko 9013c838a9fSAndrew Rybchenko return (0); 9023c838a9fSAndrew Rybchenko 9033c838a9fSAndrew Rybchenko fail2: 9043c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 9053c838a9fSAndrew Rybchenko fail1: 906460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9073c838a9fSAndrew Rybchenko 9083c838a9fSAndrew Rybchenko return (rc); 9093c838a9fSAndrew Rybchenko } 9103c838a9fSAndrew Rybchenko 911*e9c123a5SAndrew Rybchenko 912*e9c123a5SAndrew Rybchenko /* 913*e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified 914*e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 915*e9c123a5SAndrew Rybchenko */ 916460cb568SAndrew Rybchenko __checkReturn efx_rc_t 9173c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish( 9183c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 9193c838a9fSAndrew Rybchenko __in uint32_t partn, 920*e9c123a5SAndrew Rybchenko __in boolean_t reboot, 921*e9c123a5SAndrew Rybchenko __out_opt uint32_t *resultp) 9223c838a9fSAndrew Rybchenko { 923*e9c123a5SAndrew Rybchenko const efx_nic_cfg_t *encp = &enp->en_nic_cfg; 9243c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 925*e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN, 926*e9c123a5SAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)]; 927*e9c123a5SAndrew Rybchenko uint32_t result = 0; /* FIXME: use MC_CMD_NVRAM_VERIFY_RC_UNKNOWN */ 928460cb568SAndrew Rybchenko efx_rc_t rc; 9293c838a9fSAndrew Rybchenko 9303c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 9313c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 9323c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 933*e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN; 9343c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 935*e9c123a5SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN; 9363c838a9fSAndrew Rybchenko 937*e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn); 938*e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot); 939*e9c123a5SAndrew Rybchenko 940*e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS, 941*e9c123a5SAndrew Rybchenko NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 9423c838a9fSAndrew Rybchenko 9433c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9443c838a9fSAndrew Rybchenko 9453c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9463c838a9fSAndrew Rybchenko rc = req.emr_rc; 9473c838a9fSAndrew Rybchenko goto fail1; 9483c838a9fSAndrew Rybchenko } 9493c838a9fSAndrew Rybchenko 950*e9c123a5SAndrew Rybchenko if (encp->enc_fw_verified_nvram_update_required == B_FALSE) { 951*e9c123a5SAndrew Rybchenko /* Report success if verified updates are not supported. */ 952*e9c123a5SAndrew Rybchenko result = MC_CMD_NVRAM_VERIFY_RC_SUCCESS; 953*e9c123a5SAndrew Rybchenko } else { 954*e9c123a5SAndrew Rybchenko /* Firmware-verified NVRAM updates are required */ 955*e9c123a5SAndrew Rybchenko if (req.emr_out_length_used < 956*e9c123a5SAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { 957*e9c123a5SAndrew Rybchenko rc = EMSGSIZE; 958*e9c123a5SAndrew Rybchenko goto fail2; 959*e9c123a5SAndrew Rybchenko } 960*e9c123a5SAndrew Rybchenko result = 961*e9c123a5SAndrew Rybchenko MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE); 962*e9c123a5SAndrew Rybchenko 963*e9c123a5SAndrew Rybchenko if (result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) { 964*e9c123a5SAndrew Rybchenko /* Mandatory verification failed */ 965*e9c123a5SAndrew Rybchenko rc = EINVAL; 966*e9c123a5SAndrew Rybchenko goto fail3; 967*e9c123a5SAndrew Rybchenko } 968*e9c123a5SAndrew Rybchenko } 969*e9c123a5SAndrew Rybchenko 970*e9c123a5SAndrew Rybchenko if (resultp != NULL) 971*e9c123a5SAndrew Rybchenko *resultp = result; 972*e9c123a5SAndrew Rybchenko 9733c838a9fSAndrew Rybchenko return (0); 9743c838a9fSAndrew Rybchenko 975*e9c123a5SAndrew Rybchenko fail3: 976*e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail3); 977*e9c123a5SAndrew Rybchenko fail2: 978*e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 9793c838a9fSAndrew Rybchenko fail1: 980460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9813c838a9fSAndrew Rybchenko 982*e9c123a5SAndrew Rybchenko /* Always report verification result */ 983*e9c123a5SAndrew Rybchenko if (resultp != NULL) 984*e9c123a5SAndrew Rybchenko *resultp = result; 985*e9c123a5SAndrew Rybchenko 9863c838a9fSAndrew Rybchenko return (rc); 9873c838a9fSAndrew Rybchenko } 9883c838a9fSAndrew Rybchenko 9893c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 9903c838a9fSAndrew Rybchenko 991460cb568SAndrew Rybchenko __checkReturn efx_rc_t 9923c838a9fSAndrew Rybchenko efx_mcdi_nvram_test( 9933c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 9943c838a9fSAndrew Rybchenko __in uint32_t partn) 9953c838a9fSAndrew Rybchenko { 9963c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 9973c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 9983c838a9fSAndrew Rybchenko MC_CMD_NVRAM_TEST_OUT_LEN)]; 9993c838a9fSAndrew Rybchenko int result; 1000460cb568SAndrew Rybchenko efx_rc_t rc; 10013c838a9fSAndrew Rybchenko 10023c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 10033c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_TEST; 10043c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 10053c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 10063c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 10073c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 10083c838a9fSAndrew Rybchenko 10093c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 10103c838a9fSAndrew Rybchenko 10113c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 10123c838a9fSAndrew Rybchenko 10133c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 10143c838a9fSAndrew Rybchenko rc = req.emr_rc; 10153c838a9fSAndrew Rybchenko goto fail1; 10163c838a9fSAndrew Rybchenko } 10173c838a9fSAndrew Rybchenko 10183c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 10193c838a9fSAndrew Rybchenko rc = EMSGSIZE; 10203c838a9fSAndrew Rybchenko goto fail2; 10213c838a9fSAndrew Rybchenko } 10223c838a9fSAndrew Rybchenko 10233c838a9fSAndrew Rybchenko result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 10243c838a9fSAndrew Rybchenko if (result == MC_CMD_NVRAM_TEST_FAIL) { 10253c838a9fSAndrew Rybchenko 10263c838a9fSAndrew Rybchenko EFSYS_PROBE1(nvram_test_failure, int, partn); 10273c838a9fSAndrew Rybchenko 10283c838a9fSAndrew Rybchenko rc = (EINVAL); 10293c838a9fSAndrew Rybchenko goto fail3; 10303c838a9fSAndrew Rybchenko } 10313c838a9fSAndrew Rybchenko 10323c838a9fSAndrew Rybchenko return (0); 10333c838a9fSAndrew Rybchenko 10343c838a9fSAndrew Rybchenko fail3: 10353c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 10363c838a9fSAndrew Rybchenko fail2: 10373c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 10383c838a9fSAndrew Rybchenko fail1: 1039460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 10403c838a9fSAndrew Rybchenko 10413c838a9fSAndrew Rybchenko return (rc); 10423c838a9fSAndrew Rybchenko } 10433c838a9fSAndrew Rybchenko 10443c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 10453c838a9fSAndrew Rybchenko 10463c838a9fSAndrew Rybchenko 10473c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 1048