1e948693eSPhilip Paeps /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 4929c7febSAndrew Rybchenko * Copyright (c) 2009-2016 Solarflare Communications Inc. 53c838a9fSAndrew Rybchenko * All rights reserved. 6e948693eSPhilip Paeps * 7e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without 83c838a9fSAndrew Rybchenko * modification, are permitted provided that the following conditions are met: 9e948693eSPhilip Paeps * 103c838a9fSAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice, 113c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer. 123c838a9fSAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice, 133c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation 143c838a9fSAndrew Rybchenko * and/or other materials provided with the distribution. 153c838a9fSAndrew Rybchenko * 163c838a9fSAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 173c838a9fSAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 183c838a9fSAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 193c838a9fSAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 203c838a9fSAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 213c838a9fSAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 223c838a9fSAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 233c838a9fSAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 243c838a9fSAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 253c838a9fSAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 263c838a9fSAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273c838a9fSAndrew Rybchenko * 283c838a9fSAndrew Rybchenko * The views and conclusions contained in the software and documentation are 293c838a9fSAndrew Rybchenko * those of the authors and should not be interpreted as representing official 303c838a9fSAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project. 31e948693eSPhilip Paeps */ 32e948693eSPhilip Paeps 335dee87d7SPhilip Paeps #include <sys/cdefs.h> 345dee87d7SPhilip Paeps __FBSDID("$FreeBSD$"); 355dee87d7SPhilip Paeps 36e948693eSPhilip Paeps #include "efx.h" 37e948693eSPhilip Paeps #include "efx_impl.h" 38e948693eSPhilip Paeps 39e948693eSPhilip Paeps #if EFSYS_OPT_NVRAM 40e948693eSPhilip Paeps 41e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 42e948693eSPhilip Paeps 43ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_siena_ops = { 44e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 45e948693eSPhilip Paeps siena_nvram_test, /* envo_test */ 46e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 47bce88e31SAndrew Rybchenko siena_nvram_type_to_partn, /* envo_type_to_partn */ 4856bd83b0SAndrew Rybchenko siena_nvram_partn_size, /* envo_partn_size */ 495d846e87SAndrew Rybchenko siena_nvram_partn_rw_start, /* envo_partn_rw_start */ 500afdf29cSAndrew Rybchenko siena_nvram_partn_read, /* envo_partn_read */ 51b60ff840SAndrew Rybchenko siena_nvram_partn_erase, /* envo_partn_erase */ 52134c4c4aSAndrew Rybchenko siena_nvram_partn_write, /* envo_partn_write */ 53eb9703daSAndrew Rybchenko siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 5492187119SAndrew Rybchenko siena_nvram_partn_get_version, /* envo_partn_get_version */ 556d0b856cSAndrew Rybchenko siena_nvram_partn_set_version, /* envo_partn_set_version */ 565abce2b9SAndrew Rybchenko NULL, /* envo_partn_validate */ 57e948693eSPhilip Paeps }; 58e948693eSPhilip Paeps 59e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 60e948693eSPhilip Paeps 61de9775adSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 623c838a9fSAndrew Rybchenko 63ec831f7fSAndrew Rybchenko static const efx_nvram_ops_t __efx_nvram_ef10_ops = { 643c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 65de9775adSAndrew Rybchenko ef10_nvram_test, /* envo_test */ 663c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 67bce88e31SAndrew Rybchenko ef10_nvram_type_to_partn, /* envo_type_to_partn */ 6856bd83b0SAndrew Rybchenko ef10_nvram_partn_size, /* envo_partn_size */ 695d846e87SAndrew Rybchenko ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ 700afdf29cSAndrew Rybchenko ef10_nvram_partn_read, /* envo_partn_read */ 71b60ff840SAndrew Rybchenko ef10_nvram_partn_erase, /* envo_partn_erase */ 72134c4c4aSAndrew Rybchenko ef10_nvram_partn_write, /* envo_partn_write */ 73eb9703daSAndrew Rybchenko ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */ 7492187119SAndrew Rybchenko ef10_nvram_partn_get_version, /* envo_partn_get_version */ 756d0b856cSAndrew Rybchenko ef10_nvram_partn_set_version, /* envo_partn_set_version */ 765abce2b9SAndrew Rybchenko ef10_nvram_buffer_validate, /* envo_buffer_validate */ 773c838a9fSAndrew Rybchenko }; 783c838a9fSAndrew Rybchenko 79de9775adSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 803c838a9fSAndrew Rybchenko 81460cb568SAndrew Rybchenko __checkReturn efx_rc_t 82e948693eSPhilip Paeps efx_nvram_init( 83e948693eSPhilip Paeps __in efx_nic_t *enp) 84e948693eSPhilip Paeps { 85ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop; 86460cb568SAndrew Rybchenko efx_rc_t rc; 87e948693eSPhilip Paeps 88e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 89e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 90e948693eSPhilip Paeps EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM)); 91e948693eSPhilip Paeps 92e948693eSPhilip Paeps switch (enp->en_family) { 93e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 94e948693eSPhilip Paeps case EFX_FAMILY_SIENA: 95ec831f7fSAndrew Rybchenko envop = &__efx_nvram_siena_ops; 96e948693eSPhilip Paeps break; 97e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 98e948693eSPhilip Paeps 993c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 1003c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 101ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops; 1023c838a9fSAndrew Rybchenko break; 1033c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 1043c838a9fSAndrew Rybchenko 105de9775adSAndrew Rybchenko #if EFSYS_OPT_MEDFORD 106de9775adSAndrew Rybchenko case EFX_FAMILY_MEDFORD: 107ec831f7fSAndrew Rybchenko envop = &__efx_nvram_ef10_ops; 108de9775adSAndrew Rybchenko break; 109de9775adSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */ 110de9775adSAndrew Rybchenko 111e948693eSPhilip Paeps default: 112e948693eSPhilip Paeps EFSYS_ASSERT(0); 113e948693eSPhilip Paeps rc = ENOTSUP; 114e948693eSPhilip Paeps goto fail1; 115e948693eSPhilip Paeps } 116e948693eSPhilip Paeps 117e948693eSPhilip Paeps enp->en_envop = envop; 118e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_NVRAM; 119e948693eSPhilip Paeps 1203d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 1213d670ff5SAndrew Rybchenko 122e948693eSPhilip Paeps return (0); 123e948693eSPhilip Paeps 124e948693eSPhilip Paeps fail1: 125460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 126e948693eSPhilip Paeps 127e948693eSPhilip Paeps return (rc); 128e948693eSPhilip Paeps } 129e948693eSPhilip Paeps 130e948693eSPhilip Paeps #if EFSYS_OPT_DIAG 131e948693eSPhilip Paeps 132460cb568SAndrew Rybchenko __checkReturn efx_rc_t 133e948693eSPhilip Paeps efx_nvram_test( 134e948693eSPhilip Paeps __in efx_nic_t *enp) 135e948693eSPhilip Paeps { 136ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 137460cb568SAndrew Rybchenko efx_rc_t rc; 138e948693eSPhilip Paeps 139e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 140e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 141e948693eSPhilip Paeps 142e948693eSPhilip Paeps if ((rc = envop->envo_test(enp)) != 0) 143e948693eSPhilip Paeps goto fail1; 144e948693eSPhilip Paeps 145e948693eSPhilip Paeps return (0); 146e948693eSPhilip Paeps 147e948693eSPhilip Paeps fail1: 148460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 149e948693eSPhilip Paeps 150e948693eSPhilip Paeps return (rc); 151e948693eSPhilip Paeps } 152e948693eSPhilip Paeps 153e948693eSPhilip Paeps #endif /* EFSYS_OPT_DIAG */ 154e948693eSPhilip Paeps 155460cb568SAndrew Rybchenko __checkReturn efx_rc_t 156e948693eSPhilip Paeps efx_nvram_size( 157e948693eSPhilip Paeps __in efx_nic_t *enp, 158e948693eSPhilip Paeps __in efx_nvram_type_t type, 159e948693eSPhilip Paeps __out size_t *sizep) 160e948693eSPhilip Paeps { 161ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 16256bd83b0SAndrew Rybchenko uint32_t partn; 163460cb568SAndrew Rybchenko efx_rc_t rc; 164e948693eSPhilip Paeps 165e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 166e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 167e948693eSPhilip Paeps 168e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 169e948693eSPhilip Paeps 17056bd83b0SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 171e948693eSPhilip Paeps goto fail1; 172e948693eSPhilip Paeps 17356bd83b0SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0) 17456bd83b0SAndrew Rybchenko goto fail2; 17556bd83b0SAndrew Rybchenko 176e948693eSPhilip Paeps return (0); 177e948693eSPhilip Paeps 17856bd83b0SAndrew Rybchenko fail2: 17956bd83b0SAndrew Rybchenko EFSYS_PROBE(fail2); 180e948693eSPhilip Paeps fail1: 181460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 18256bd83b0SAndrew Rybchenko *sizep = 0; 183e948693eSPhilip Paeps 184e948693eSPhilip Paeps return (rc); 185e948693eSPhilip Paeps } 186e948693eSPhilip Paeps 187460cb568SAndrew Rybchenko __checkReturn efx_rc_t 188e948693eSPhilip Paeps efx_nvram_get_version( 189e948693eSPhilip Paeps __in efx_nic_t *enp, 190e948693eSPhilip Paeps __in efx_nvram_type_t type, 191e948693eSPhilip Paeps __out uint32_t *subtypep, 192e948693eSPhilip Paeps __out_ecount(4) uint16_t version[4]) 193e948693eSPhilip Paeps { 194ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 19592187119SAndrew Rybchenko uint32_t partn; 196460cb568SAndrew Rybchenko efx_rc_t rc; 197e948693eSPhilip Paeps 198e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 199e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 200e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 201e948693eSPhilip Paeps 202e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 203e948693eSPhilip Paeps 20492187119SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 205e948693eSPhilip Paeps goto fail1; 206e948693eSPhilip Paeps 20792187119SAndrew Rybchenko if ((rc = envop->envo_partn_get_version(enp, partn, 20892187119SAndrew Rybchenko subtypep, version)) != 0) 20992187119SAndrew Rybchenko goto fail2; 21092187119SAndrew Rybchenko 211e948693eSPhilip Paeps return (0); 212e948693eSPhilip Paeps 21392187119SAndrew Rybchenko fail2: 21492187119SAndrew Rybchenko EFSYS_PROBE(fail2); 215e948693eSPhilip Paeps fail1: 216460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 217e948693eSPhilip Paeps 218e948693eSPhilip Paeps return (rc); 219e948693eSPhilip Paeps } 220e948693eSPhilip Paeps 221460cb568SAndrew Rybchenko __checkReturn efx_rc_t 222e948693eSPhilip Paeps efx_nvram_rw_start( 223e948693eSPhilip Paeps __in efx_nic_t *enp, 224e948693eSPhilip Paeps __in efx_nvram_type_t type, 225e948693eSPhilip Paeps __out_opt size_t *chunk_sizep) 226e948693eSPhilip Paeps { 227ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2285d846e87SAndrew Rybchenko uint32_t partn; 229460cb568SAndrew Rybchenko efx_rc_t rc; 230e948693eSPhilip Paeps 231e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 232e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 233e948693eSPhilip Paeps 234e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 235e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 236e948693eSPhilip Paeps 2375d846e87SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 238e948693eSPhilip Paeps goto fail1; 239e948693eSPhilip Paeps 2403d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 2413d670ff5SAndrew Rybchenko 2425d846e87SAndrew Rybchenko if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) 2435d846e87SAndrew Rybchenko goto fail2; 2445d846e87SAndrew Rybchenko 2453d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = partn; 246e948693eSPhilip Paeps 247e948693eSPhilip Paeps return (0); 248e948693eSPhilip Paeps 2495d846e87SAndrew Rybchenko fail2: 2505d846e87SAndrew Rybchenko EFSYS_PROBE(fail2); 251e948693eSPhilip Paeps fail1: 252460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 253e948693eSPhilip Paeps 254e948693eSPhilip Paeps return (rc); 255e948693eSPhilip Paeps } 256e948693eSPhilip Paeps 257460cb568SAndrew Rybchenko __checkReturn efx_rc_t 258e948693eSPhilip Paeps efx_nvram_read_chunk( 259e948693eSPhilip Paeps __in efx_nic_t *enp, 260e948693eSPhilip Paeps __in efx_nvram_type_t type, 261e948693eSPhilip Paeps __in unsigned int offset, 262e948693eSPhilip Paeps __out_bcount(size) caddr_t data, 263e948693eSPhilip Paeps __in size_t size) 264e948693eSPhilip Paeps { 265ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 2660afdf29cSAndrew Rybchenko uint32_t partn; 267460cb568SAndrew Rybchenko efx_rc_t rc; 268e948693eSPhilip Paeps 269e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 270e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 271e948693eSPhilip Paeps 272e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 273e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 274e948693eSPhilip Paeps 2750afdf29cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 276e948693eSPhilip Paeps goto fail1; 277e948693eSPhilip Paeps 2783d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 2793d670ff5SAndrew Rybchenko 2800afdf29cSAndrew Rybchenko if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) 2810afdf29cSAndrew Rybchenko goto fail2; 2820afdf29cSAndrew Rybchenko 283e948693eSPhilip Paeps return (0); 284e948693eSPhilip Paeps 2850afdf29cSAndrew Rybchenko fail2: 2860afdf29cSAndrew Rybchenko EFSYS_PROBE(fail2); 287e948693eSPhilip Paeps fail1: 288460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 289e948693eSPhilip Paeps 290e948693eSPhilip Paeps return (rc); 291e948693eSPhilip Paeps } 292e948693eSPhilip Paeps 293460cb568SAndrew Rybchenko __checkReturn efx_rc_t 294e948693eSPhilip Paeps efx_nvram_erase( 295e948693eSPhilip Paeps __in efx_nic_t *enp, 296e948693eSPhilip Paeps __in efx_nvram_type_t type) 297e948693eSPhilip Paeps { 298ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 299b60ff840SAndrew Rybchenko unsigned int offset = 0; 300b60ff840SAndrew Rybchenko size_t size = 0; 301b60ff840SAndrew Rybchenko uint32_t partn; 302460cb568SAndrew Rybchenko efx_rc_t rc; 303e948693eSPhilip Paeps 304e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 305e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 306e948693eSPhilip Paeps 307e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 308e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 309e948693eSPhilip Paeps 310b60ff840SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 311e948693eSPhilip Paeps goto fail1; 312e948693eSPhilip Paeps 3133d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 3143d670ff5SAndrew Rybchenko 315b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0) 316b60ff840SAndrew Rybchenko goto fail2; 317b60ff840SAndrew Rybchenko 318b60ff840SAndrew Rybchenko if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0) 319b60ff840SAndrew Rybchenko goto fail3; 320b60ff840SAndrew Rybchenko 321e948693eSPhilip Paeps return (0); 322e948693eSPhilip Paeps 323b60ff840SAndrew Rybchenko fail3: 324b60ff840SAndrew Rybchenko EFSYS_PROBE(fail3); 325b60ff840SAndrew Rybchenko fail2: 326b60ff840SAndrew Rybchenko EFSYS_PROBE(fail2); 327e948693eSPhilip Paeps fail1: 328460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 329e948693eSPhilip Paeps 330e948693eSPhilip Paeps return (rc); 331e948693eSPhilip Paeps } 332e948693eSPhilip Paeps 333460cb568SAndrew Rybchenko __checkReturn efx_rc_t 334e948693eSPhilip Paeps efx_nvram_write_chunk( 335e948693eSPhilip Paeps __in efx_nic_t *enp, 336e948693eSPhilip Paeps __in efx_nvram_type_t type, 337e948693eSPhilip Paeps __in unsigned int offset, 338e948693eSPhilip Paeps __in_bcount(size) caddr_t data, 339e948693eSPhilip Paeps __in size_t size) 340e948693eSPhilip Paeps { 341ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 342134c4c4aSAndrew Rybchenko uint32_t partn; 343460cb568SAndrew Rybchenko efx_rc_t rc; 344e948693eSPhilip Paeps 345e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 346e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 347e948693eSPhilip Paeps 348e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 349e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 350e948693eSPhilip Paeps 351134c4c4aSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 352e948693eSPhilip Paeps goto fail1; 353e948693eSPhilip Paeps 3543d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 3553d670ff5SAndrew Rybchenko 356134c4c4aSAndrew Rybchenko if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0) 357134c4c4aSAndrew Rybchenko goto fail2; 358134c4c4aSAndrew Rybchenko 359e948693eSPhilip Paeps return (0); 360e948693eSPhilip Paeps 361134c4c4aSAndrew Rybchenko fail2: 362134c4c4aSAndrew Rybchenko EFSYS_PROBE(fail2); 363e948693eSPhilip Paeps fail1: 364460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 365e948693eSPhilip Paeps 366e948693eSPhilip Paeps return (rc); 367e948693eSPhilip Paeps } 368e948693eSPhilip Paeps 369e9c123a5SAndrew Rybchenko __checkReturn efx_rc_t 370e948693eSPhilip Paeps efx_nvram_rw_finish( 371e948693eSPhilip Paeps __in efx_nic_t *enp, 372d5106d05SAndrew Rybchenko __in efx_nvram_type_t type, 373d5106d05SAndrew Rybchenko __out_opt uint32_t *verify_resultp) 374e948693eSPhilip Paeps { 375ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 376eb9703daSAndrew Rybchenko uint32_t partn; 377d5106d05SAndrew Rybchenko uint32_t verify_result = 0; 378e9c123a5SAndrew Rybchenko efx_rc_t rc; 379e948693eSPhilip Paeps 380e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 381e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 382e948693eSPhilip Paeps 383e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 384e948693eSPhilip Paeps EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); 385e948693eSPhilip Paeps 386e9c123a5SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 387e9c123a5SAndrew Rybchenko goto fail1; 388e9c123a5SAndrew Rybchenko 3893d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); 3903d670ff5SAndrew Rybchenko 391a21b2f20SAndrew Rybchenko if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0) 392e9c123a5SAndrew Rybchenko goto fail2; 393e948693eSPhilip Paeps 3943d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 395e9c123a5SAndrew Rybchenko 396d5106d05SAndrew Rybchenko if (verify_resultp != NULL) 397d5106d05SAndrew Rybchenko *verify_resultp = verify_result; 398d5106d05SAndrew Rybchenko 399e9c123a5SAndrew Rybchenko return (0); 400e9c123a5SAndrew Rybchenko 401e9c123a5SAndrew Rybchenko fail2: 402e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 4033d670ff5SAndrew Rybchenko enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; 404e9c123a5SAndrew Rybchenko 405e9c123a5SAndrew Rybchenko fail1: 406e9c123a5SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 407e9c123a5SAndrew Rybchenko 408d5106d05SAndrew Rybchenko /* Always report verification result */ 409d5106d05SAndrew Rybchenko if (verify_resultp != NULL) 410d5106d05SAndrew Rybchenko *verify_resultp = verify_result; 411d5106d05SAndrew Rybchenko 412e9c123a5SAndrew Rybchenko return (rc); 413e948693eSPhilip Paeps } 414e948693eSPhilip Paeps 415460cb568SAndrew Rybchenko __checkReturn efx_rc_t 416e948693eSPhilip Paeps efx_nvram_set_version( 417e948693eSPhilip Paeps __in efx_nic_t *enp, 418e948693eSPhilip Paeps __in efx_nvram_type_t type, 4193c838a9fSAndrew Rybchenko __in_ecount(4) uint16_t version[4]) 420e948693eSPhilip Paeps { 421ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4226d0b856cSAndrew Rybchenko uint32_t partn; 423460cb568SAndrew Rybchenko efx_rc_t rc; 424e948693eSPhilip Paeps 425e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 426e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 427e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 428e948693eSPhilip Paeps 429e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 430e948693eSPhilip Paeps 4316d0b856cSAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 432e948693eSPhilip Paeps goto fail1; 433e948693eSPhilip Paeps 4343d670ff5SAndrew Rybchenko /* 4353d670ff5SAndrew Rybchenko * The Siena implementation of envo_set_version() will attempt to 4363d670ff5SAndrew Rybchenko * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition. 4373d670ff5SAndrew Rybchenko * Therefore, you can't have already acquired the NVRAM_UPDATE lock. 4383d670ff5SAndrew Rybchenko */ 4393d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 4403d670ff5SAndrew Rybchenko 4416d0b856cSAndrew Rybchenko if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0) 4426d0b856cSAndrew Rybchenko goto fail2; 4436d0b856cSAndrew Rybchenko 444e948693eSPhilip Paeps return (0); 445e948693eSPhilip Paeps 4466d0b856cSAndrew Rybchenko fail2: 4476d0b856cSAndrew Rybchenko EFSYS_PROBE(fail2); 448e948693eSPhilip Paeps fail1: 449460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 450e948693eSPhilip Paeps 451e948693eSPhilip Paeps return (rc); 452e948693eSPhilip Paeps } 453e948693eSPhilip Paeps 4545abce2b9SAndrew Rybchenko /* Validate buffer contents (before writing to flash) */ 4555abce2b9SAndrew Rybchenko __checkReturn efx_rc_t 4565abce2b9SAndrew Rybchenko efx_nvram_validate( 4575abce2b9SAndrew Rybchenko __in efx_nic_t *enp, 4585abce2b9SAndrew Rybchenko __in efx_nvram_type_t type, 4595abce2b9SAndrew Rybchenko __in_bcount(partn_size) caddr_t partn_data, 4605abce2b9SAndrew Rybchenko __in size_t partn_size) 4615abce2b9SAndrew Rybchenko { 462ec831f7fSAndrew Rybchenko const efx_nvram_ops_t *envop = enp->en_envop; 4635abce2b9SAndrew Rybchenko uint32_t partn; 4645abce2b9SAndrew Rybchenko efx_rc_t rc; 4655abce2b9SAndrew Rybchenko 4665abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4675abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 4685abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 4695abce2b9SAndrew Rybchenko 4705abce2b9SAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); 4715abce2b9SAndrew Rybchenko 4725abce2b9SAndrew Rybchenko 4735abce2b9SAndrew Rybchenko if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) 4745abce2b9SAndrew Rybchenko goto fail1; 4755abce2b9SAndrew Rybchenko 476*6a869fecSAndrew Rybchenko if (envop->envo_buffer_validate != NULL) { 477*6a869fecSAndrew Rybchenko if ((rc = envop->envo_buffer_validate(enp, partn, 478*6a869fecSAndrew Rybchenko partn_data, partn_size)) != 0) 4795abce2b9SAndrew Rybchenko goto fail2; 480*6a869fecSAndrew Rybchenko } 4815abce2b9SAndrew Rybchenko 4825abce2b9SAndrew Rybchenko return (0); 4835abce2b9SAndrew Rybchenko 4845abce2b9SAndrew Rybchenko fail2: 4855abce2b9SAndrew Rybchenko EFSYS_PROBE(fail2); 4865abce2b9SAndrew Rybchenko fail1: 4875abce2b9SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4885abce2b9SAndrew Rybchenko 4895abce2b9SAndrew Rybchenko return (rc); 4905abce2b9SAndrew Rybchenko } 4915abce2b9SAndrew Rybchenko 4925abce2b9SAndrew Rybchenko 493e948693eSPhilip Paeps void 494e948693eSPhilip Paeps efx_nvram_fini( 495e948693eSPhilip Paeps __in efx_nic_t *enp) 496e948693eSPhilip Paeps { 497e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 498e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 499e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); 500e948693eSPhilip Paeps 5013d670ff5SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); 502e948693eSPhilip Paeps 503e948693eSPhilip Paeps enp->en_envop = NULL; 504e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_NVRAM; 505e948693eSPhilip Paeps } 506e948693eSPhilip Paeps 507e948693eSPhilip Paeps #endif /* EFSYS_OPT_NVRAM */ 5083c838a9fSAndrew Rybchenko 5093c838a9fSAndrew Rybchenko #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD 5103c838a9fSAndrew Rybchenko 5113c838a9fSAndrew Rybchenko /* 5123c838a9fSAndrew Rybchenko * Internal MCDI request handling 5133c838a9fSAndrew Rybchenko */ 5143c838a9fSAndrew Rybchenko 515460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5163c838a9fSAndrew Rybchenko efx_mcdi_nvram_partitions( 5173c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5183c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 5193c838a9fSAndrew Rybchenko __in size_t size, 5203c838a9fSAndrew Rybchenko __out unsigned int *npartnp) 5213c838a9fSAndrew Rybchenko { 5223c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 5233c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_PARTITIONS_IN_LEN, 5243c838a9fSAndrew Rybchenko MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX)]; 5253c838a9fSAndrew Rybchenko unsigned int npartn; 526460cb568SAndrew Rybchenko efx_rc_t rc; 5273c838a9fSAndrew Rybchenko 5283c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 5293c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_PARTITIONS; 5303c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5313c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN; 5323c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5333c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX; 5343c838a9fSAndrew Rybchenko 5353c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 5363c838a9fSAndrew Rybchenko 5373c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 5383c838a9fSAndrew Rybchenko rc = req.emr_rc; 5393c838a9fSAndrew Rybchenko goto fail1; 5403c838a9fSAndrew Rybchenko } 5413c838a9fSAndrew Rybchenko 5423c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) { 5433c838a9fSAndrew Rybchenko rc = EMSGSIZE; 5443c838a9fSAndrew Rybchenko goto fail2; 5453c838a9fSAndrew Rybchenko } 5463c838a9fSAndrew Rybchenko npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS); 5473c838a9fSAndrew Rybchenko 5483c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) { 5493c838a9fSAndrew Rybchenko rc = ENOENT; 5503c838a9fSAndrew Rybchenko goto fail3; 5513c838a9fSAndrew Rybchenko } 5523c838a9fSAndrew Rybchenko 5533c838a9fSAndrew Rybchenko if (size < npartn * sizeof (uint32_t)) { 5543c838a9fSAndrew Rybchenko rc = ENOSPC; 5553c838a9fSAndrew Rybchenko goto fail3; 5563c838a9fSAndrew Rybchenko } 5573c838a9fSAndrew Rybchenko 5583c838a9fSAndrew Rybchenko *npartnp = npartn; 5593c838a9fSAndrew Rybchenko 5603c838a9fSAndrew Rybchenko memcpy(data, 5613c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID), 5623c838a9fSAndrew Rybchenko (npartn * sizeof (uint32_t))); 5633c838a9fSAndrew Rybchenko 5643c838a9fSAndrew Rybchenko return (0); 5653c838a9fSAndrew Rybchenko 5663c838a9fSAndrew Rybchenko fail3: 5673c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 5683c838a9fSAndrew Rybchenko fail2: 5693c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 5703c838a9fSAndrew Rybchenko fail1: 571460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5723c838a9fSAndrew Rybchenko 5733c838a9fSAndrew Rybchenko return (rc); 5743c838a9fSAndrew Rybchenko } 5753c838a9fSAndrew Rybchenko 576460cb568SAndrew Rybchenko __checkReturn efx_rc_t 5773c838a9fSAndrew Rybchenko efx_mcdi_nvram_metadata( 5783c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 5793c838a9fSAndrew Rybchenko __in uint32_t partn, 5803c838a9fSAndrew Rybchenko __out uint32_t *subtypep, 5813c838a9fSAndrew Rybchenko __out_ecount(4) uint16_t version[4], 5823c838a9fSAndrew Rybchenko __out_bcount_opt(size) char *descp, 5833c838a9fSAndrew Rybchenko __in size_t size) 5843c838a9fSAndrew Rybchenko { 5853c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 5863c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_METADATA_IN_LEN, 5873c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_LENMAX)]; 588460cb568SAndrew Rybchenko efx_rc_t rc; 5893c838a9fSAndrew Rybchenko 5903c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 5913c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_METADATA; 5923c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 5933c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN; 5943c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 5953c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX; 5963c838a9fSAndrew Rybchenko 5973c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); 5983c838a9fSAndrew Rybchenko 5993c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 6003c838a9fSAndrew Rybchenko 6013c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6023c838a9fSAndrew Rybchenko rc = req.emr_rc; 6033c838a9fSAndrew Rybchenko goto fail1; 6043c838a9fSAndrew Rybchenko } 6053c838a9fSAndrew Rybchenko 6063c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) { 6073c838a9fSAndrew Rybchenko rc = EMSGSIZE; 6083c838a9fSAndrew Rybchenko goto fail2; 6093c838a9fSAndrew Rybchenko } 6103c838a9fSAndrew Rybchenko 6113c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6123c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_SUBTYPE_VALID)) { 6133c838a9fSAndrew Rybchenko *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE); 6143c838a9fSAndrew Rybchenko } else { 6153c838a9fSAndrew Rybchenko *subtypep = 0; 6163c838a9fSAndrew Rybchenko } 6173c838a9fSAndrew Rybchenko 6183c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6193c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_VERSION_VALID)) { 6203c838a9fSAndrew Rybchenko version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W); 6213c838a9fSAndrew Rybchenko version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X); 6223c838a9fSAndrew Rybchenko version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y); 6233c838a9fSAndrew Rybchenko version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z); 6243c838a9fSAndrew Rybchenko } else { 6253c838a9fSAndrew Rybchenko version[0] = version[1] = version[2] = version[3] = 0; 6263c838a9fSAndrew Rybchenko } 6273c838a9fSAndrew Rybchenko 6283c838a9fSAndrew Rybchenko if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS, 6293c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION_VALID)) { 6303c838a9fSAndrew Rybchenko /* Return optional descrition string */ 6313c838a9fSAndrew Rybchenko if ((descp != NULL) && (size > 0)) { 6323c838a9fSAndrew Rybchenko size_t desclen; 6333c838a9fSAndrew Rybchenko 6343c838a9fSAndrew Rybchenko descp[0] = '\0'; 6353c838a9fSAndrew Rybchenko desclen = (req.emr_out_length_used 6363c838a9fSAndrew Rybchenko - MC_CMD_NVRAM_METADATA_OUT_LEN(0)); 6373c838a9fSAndrew Rybchenko 6383c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(desclen, <=, 6393c838a9fSAndrew Rybchenko MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM); 6403c838a9fSAndrew Rybchenko 6413c838a9fSAndrew Rybchenko if (size < desclen) { 6423c838a9fSAndrew Rybchenko rc = ENOSPC; 6433c838a9fSAndrew Rybchenko goto fail3; 6443c838a9fSAndrew Rybchenko } 6453c838a9fSAndrew Rybchenko 6463c838a9fSAndrew Rybchenko memcpy(descp, MCDI_OUT2(req, char, 6473c838a9fSAndrew Rybchenko NVRAM_METADATA_OUT_DESCRIPTION), 6483c838a9fSAndrew Rybchenko desclen); 6493c838a9fSAndrew Rybchenko 6503c838a9fSAndrew Rybchenko /* Ensure string is NUL terminated */ 6513c838a9fSAndrew Rybchenko descp[desclen] = '\0'; 6523c838a9fSAndrew Rybchenko } 6533c838a9fSAndrew Rybchenko } 6543c838a9fSAndrew Rybchenko 6553c838a9fSAndrew Rybchenko return (0); 6563c838a9fSAndrew Rybchenko 6573c838a9fSAndrew Rybchenko fail3: 6583c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 6593c838a9fSAndrew Rybchenko fail2: 6603c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 6613c838a9fSAndrew Rybchenko fail1: 662460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 6633c838a9fSAndrew Rybchenko 6643c838a9fSAndrew Rybchenko return (rc); 6653c838a9fSAndrew Rybchenko } 6663c838a9fSAndrew Rybchenko 667460cb568SAndrew Rybchenko __checkReturn efx_rc_t 6683c838a9fSAndrew Rybchenko efx_mcdi_nvram_info( 6693c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 6703c838a9fSAndrew Rybchenko __in uint32_t partn, 6713c838a9fSAndrew Rybchenko __out_opt size_t *sizep, 6723c838a9fSAndrew Rybchenko __out_opt uint32_t *addressp, 6739cb71b16SAndrew Rybchenko __out_opt uint32_t *erase_sizep, 6749cb71b16SAndrew Rybchenko __out_opt uint32_t *write_sizep) 6753c838a9fSAndrew Rybchenko { 6763c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, 6779cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN)]; 6783c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 679460cb568SAndrew Rybchenko efx_rc_t rc; 6803c838a9fSAndrew Rybchenko 6813c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 6823c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_INFO; 6833c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 6843c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; 6853c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 6869cb71b16SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN; 6873c838a9fSAndrew Rybchenko 6883c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); 6893c838a9fSAndrew Rybchenko 6903c838a9fSAndrew Rybchenko efx_mcdi_execute_quiet(enp, &req); 6913c838a9fSAndrew Rybchenko 6923c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 6933c838a9fSAndrew Rybchenko rc = req.emr_rc; 6943c838a9fSAndrew Rybchenko goto fail1; 6953c838a9fSAndrew Rybchenko } 6963c838a9fSAndrew Rybchenko 6973c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { 6983c838a9fSAndrew Rybchenko rc = EMSGSIZE; 6993c838a9fSAndrew Rybchenko goto fail2; 7003c838a9fSAndrew Rybchenko } 7013c838a9fSAndrew Rybchenko 7023c838a9fSAndrew Rybchenko if (sizep) 7033c838a9fSAndrew Rybchenko *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); 7043c838a9fSAndrew Rybchenko 7053c838a9fSAndrew Rybchenko if (addressp) 7063c838a9fSAndrew Rybchenko *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR); 7073c838a9fSAndrew Rybchenko 7083c838a9fSAndrew Rybchenko if (erase_sizep) 7093c838a9fSAndrew Rybchenko *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE); 7103c838a9fSAndrew Rybchenko 7119cb71b16SAndrew Rybchenko if (write_sizep) { 7129cb71b16SAndrew Rybchenko *write_sizep = 7139cb71b16SAndrew Rybchenko (req.emr_out_length_used < 7149cb71b16SAndrew Rybchenko MC_CMD_NVRAM_INFO_V2_OUT_LEN) ? 7159cb71b16SAndrew Rybchenko 0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE); 7169cb71b16SAndrew Rybchenko } 7179cb71b16SAndrew Rybchenko 7183c838a9fSAndrew Rybchenko return (0); 7193c838a9fSAndrew Rybchenko 7203c838a9fSAndrew Rybchenko fail2: 7213c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 7223c838a9fSAndrew Rybchenko fail1: 723460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7243c838a9fSAndrew Rybchenko 7253c838a9fSAndrew Rybchenko return (rc); 7263c838a9fSAndrew Rybchenko } 7273c838a9fSAndrew Rybchenko 728e9c123a5SAndrew Rybchenko /* 729e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified 730e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 731e9c123a5SAndrew Rybchenko */ 732460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7333c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_start( 7343c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7353c838a9fSAndrew Rybchenko __in uint32_t partn) 7363c838a9fSAndrew Rybchenko { 737e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN, 7383c838a9fSAndrew Rybchenko MC_CMD_NVRAM_UPDATE_START_OUT_LEN)]; 7393c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 740460cb568SAndrew Rybchenko efx_rc_t rc; 7413c838a9fSAndrew Rybchenko 7423c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7433c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; 7443c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 745e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN; 7463c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7473c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN; 7483c838a9fSAndrew Rybchenko 749e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn); 750e9c123a5SAndrew Rybchenko 751e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS, 752e9c123a5SAndrew Rybchenko NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 7533c838a9fSAndrew Rybchenko 7543c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 7553c838a9fSAndrew Rybchenko 7563c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 7573c838a9fSAndrew Rybchenko rc = req.emr_rc; 7583c838a9fSAndrew Rybchenko goto fail1; 7593c838a9fSAndrew Rybchenko } 7603c838a9fSAndrew Rybchenko 7613c838a9fSAndrew Rybchenko return (0); 7623c838a9fSAndrew Rybchenko 7633c838a9fSAndrew Rybchenko fail1: 764460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 7653c838a9fSAndrew Rybchenko 7663c838a9fSAndrew Rybchenko return (rc); 7673c838a9fSAndrew Rybchenko } 7683c838a9fSAndrew Rybchenko 769460cb568SAndrew Rybchenko __checkReturn efx_rc_t 7703c838a9fSAndrew Rybchenko efx_mcdi_nvram_read( 7713c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 7723c838a9fSAndrew Rybchenko __in uint32_t partn, 7733c838a9fSAndrew Rybchenko __in uint32_t offset, 7743c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 7759ad7e03fSAndrew Rybchenko __in size_t size, 7769ad7e03fSAndrew Rybchenko __in uint32_t mode) 7773c838a9fSAndrew Rybchenko { 7783c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 7799ad7e03fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN, 7803c838a9fSAndrew Rybchenko MC_CMD_NVRAM_READ_OUT_LENMAX)]; 781460cb568SAndrew Rybchenko efx_rc_t rc; 7823c838a9fSAndrew Rybchenko 7833c838a9fSAndrew Rybchenko if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) { 7843c838a9fSAndrew Rybchenko rc = EINVAL; 7853c838a9fSAndrew Rybchenko goto fail1; 7863c838a9fSAndrew Rybchenko } 7873c838a9fSAndrew Rybchenko 7883c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 7893c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_READ; 7903c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 7919ad7e03fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN; 7923c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 7933c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX; 7943c838a9fSAndrew Rybchenko 7959ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn); 7969ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset); 7979ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size); 7989ad7e03fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode); 7993c838a9fSAndrew Rybchenko 8003c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8013c838a9fSAndrew Rybchenko 8023c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8033c838a9fSAndrew Rybchenko rc = req.emr_rc; 8043c838a9fSAndrew Rybchenko goto fail1; 8053c838a9fSAndrew Rybchenko } 8063c838a9fSAndrew Rybchenko 8073c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) { 8083c838a9fSAndrew Rybchenko rc = EMSGSIZE; 8093c838a9fSAndrew Rybchenko goto fail2; 8103c838a9fSAndrew Rybchenko } 8113c838a9fSAndrew Rybchenko 8123c838a9fSAndrew Rybchenko memcpy(data, 8133c838a9fSAndrew Rybchenko MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), 8143c838a9fSAndrew Rybchenko size); 8153c838a9fSAndrew Rybchenko 8163c838a9fSAndrew Rybchenko return (0); 8173c838a9fSAndrew Rybchenko 8183c838a9fSAndrew Rybchenko fail2: 8193c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 8203c838a9fSAndrew Rybchenko fail1: 821460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8223c838a9fSAndrew Rybchenko 8233c838a9fSAndrew Rybchenko return (rc); 8243c838a9fSAndrew Rybchenko } 8253c838a9fSAndrew Rybchenko 826460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8273c838a9fSAndrew Rybchenko efx_mcdi_nvram_erase( 8283c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8293c838a9fSAndrew Rybchenko __in uint32_t partn, 8303c838a9fSAndrew Rybchenko __in uint32_t offset, 8313c838a9fSAndrew Rybchenko __in size_t size) 8323c838a9fSAndrew Rybchenko { 8333c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 8343c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_ERASE_IN_LEN, 8353c838a9fSAndrew Rybchenko MC_CMD_NVRAM_ERASE_OUT_LEN)]; 836460cb568SAndrew Rybchenko efx_rc_t rc; 8373c838a9fSAndrew Rybchenko 8383c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8393c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_ERASE; 8403c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8413c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; 8423c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8433c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN; 8443c838a9fSAndrew Rybchenko 8453c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); 8463c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); 8473c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); 8483c838a9fSAndrew Rybchenko 8493c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 8503c838a9fSAndrew Rybchenko 8513c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 8523c838a9fSAndrew Rybchenko rc = req.emr_rc; 8533c838a9fSAndrew Rybchenko goto fail1; 8543c838a9fSAndrew Rybchenko } 8553c838a9fSAndrew Rybchenko 8563c838a9fSAndrew Rybchenko return (0); 8573c838a9fSAndrew Rybchenko 8583c838a9fSAndrew Rybchenko fail1: 859460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8603c838a9fSAndrew Rybchenko 8613c838a9fSAndrew Rybchenko return (rc); 8623c838a9fSAndrew Rybchenko } 8633c838a9fSAndrew Rybchenko 86457396b7aSAndrew Rybchenko /* 86557396b7aSAndrew Rybchenko * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both 86657396b7aSAndrew Rybchenko * Sienna and EF10 based boards. However EF10 based boards support the use 86757396b7aSAndrew Rybchenko * of this command with payloads up to the maximum MCDI V2 payload length. 86857396b7aSAndrew Rybchenko */ 869460cb568SAndrew Rybchenko __checkReturn efx_rc_t 8703c838a9fSAndrew Rybchenko efx_mcdi_nvram_write( 8713c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 8723c838a9fSAndrew Rybchenko __in uint32_t partn, 8733c838a9fSAndrew Rybchenko __in uint32_t offset, 8743c838a9fSAndrew Rybchenko __out_bcount(size) caddr_t data, 8753c838a9fSAndrew Rybchenko __in size_t size) 8763c838a9fSAndrew Rybchenko { 8773c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 87857396b7aSAndrew Rybchenko uint8_t payload[MAX(MCDI_CTL_SDU_LEN_MAX_V1, 87957396b7aSAndrew Rybchenko MCDI_CTL_SDU_LEN_MAX_V2)]; 880460cb568SAndrew Rybchenko efx_rc_t rc; 88157396b7aSAndrew Rybchenko size_t max_data_size; 8823c838a9fSAndrew Rybchenko 88357396b7aSAndrew Rybchenko max_data_size = enp->en_nic_cfg.enc_mcdi_max_payload_length 88457396b7aSAndrew Rybchenko - MC_CMD_NVRAM_WRITE_IN_LEN(0); 88557396b7aSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_nic_cfg.enc_mcdi_max_payload_length, >, 0); 88657396b7aSAndrew Rybchenko EFSYS_ASSERT3U(max_data_size, <, 88757396b7aSAndrew Rybchenko enp->en_nic_cfg.enc_mcdi_max_payload_length); 88857396b7aSAndrew Rybchenko 88957396b7aSAndrew Rybchenko if (size > max_data_size) { 8903c838a9fSAndrew Rybchenko rc = EINVAL; 8913c838a9fSAndrew Rybchenko goto fail1; 8923c838a9fSAndrew Rybchenko } 8933c838a9fSAndrew Rybchenko 8943c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 8953c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_WRITE; 8963c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 8973c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size); 8983c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 8993c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN; 9003c838a9fSAndrew Rybchenko 9013c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); 9023c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); 9033c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size); 9043c838a9fSAndrew Rybchenko 9053c838a9fSAndrew Rybchenko memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), 9063c838a9fSAndrew Rybchenko data, size); 9073c838a9fSAndrew Rybchenko 9083c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9093c838a9fSAndrew Rybchenko 9103c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9113c838a9fSAndrew Rybchenko rc = req.emr_rc; 9123c838a9fSAndrew Rybchenko goto fail2; 9133c838a9fSAndrew Rybchenko } 9143c838a9fSAndrew Rybchenko 9153c838a9fSAndrew Rybchenko return (0); 9163c838a9fSAndrew Rybchenko 9173c838a9fSAndrew Rybchenko fail2: 9183c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 9193c838a9fSAndrew Rybchenko fail1: 920460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9213c838a9fSAndrew Rybchenko 9223c838a9fSAndrew Rybchenko return (rc); 9233c838a9fSAndrew Rybchenko } 9243c838a9fSAndrew Rybchenko 925e9c123a5SAndrew Rybchenko 926e9c123a5SAndrew Rybchenko /* 927e9c123a5SAndrew Rybchenko * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified 928e9c123a5SAndrew Rybchenko * NVRAM updates. Older firmware will ignore the flags field in the request. 929e9c123a5SAndrew Rybchenko */ 930460cb568SAndrew Rybchenko __checkReturn efx_rc_t 9313c838a9fSAndrew Rybchenko efx_mcdi_nvram_update_finish( 9323c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 9333c838a9fSAndrew Rybchenko __in uint32_t partn, 934e9c123a5SAndrew Rybchenko __in boolean_t reboot, 935a21b2f20SAndrew Rybchenko __out_opt uint32_t *verify_resultp) 9363c838a9fSAndrew Rybchenko { 937e9c123a5SAndrew Rybchenko const efx_nic_cfg_t *encp = &enp->en_nic_cfg; 9383c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 939e9c123a5SAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN, 940e9c123a5SAndrew Rybchenko MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)]; 941a21b2f20SAndrew Rybchenko uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; 942460cb568SAndrew Rybchenko efx_rc_t rc; 9433c838a9fSAndrew Rybchenko 9443c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 9453c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; 9463c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 947e9c123a5SAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN; 9483c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 949e9c123a5SAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN; 9503c838a9fSAndrew Rybchenko 951e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn); 952e9c123a5SAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot); 953e9c123a5SAndrew Rybchenko 954e9c123a5SAndrew Rybchenko MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS, 955e9c123a5SAndrew Rybchenko NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1); 9563c838a9fSAndrew Rybchenko 9573c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 9583c838a9fSAndrew Rybchenko 9593c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 9603c838a9fSAndrew Rybchenko rc = req.emr_rc; 9613c838a9fSAndrew Rybchenko goto fail1; 9623c838a9fSAndrew Rybchenko } 9633c838a9fSAndrew Rybchenko 964f0d3455bSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { 965a21b2f20SAndrew Rybchenko verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; 966348d3529SAndrew Rybchenko if (encp->enc_nvram_update_verify_result_supported) { 967348d3529SAndrew Rybchenko /* Result of update verification is missing */ 968e9c123a5SAndrew Rybchenko rc = EMSGSIZE; 969e9c123a5SAndrew Rybchenko goto fail2; 970e9c123a5SAndrew Rybchenko } 971f0d3455bSAndrew Rybchenko } else { 972a21b2f20SAndrew Rybchenko verify_result = 973e9c123a5SAndrew Rybchenko MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE); 974f0d3455bSAndrew Rybchenko } 975e9c123a5SAndrew Rybchenko 976348d3529SAndrew Rybchenko if ((encp->enc_nvram_update_verify_result_supported) && 977a21b2f20SAndrew Rybchenko (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) { 978348d3529SAndrew Rybchenko /* Update verification failed */ 979e9c123a5SAndrew Rybchenko rc = EINVAL; 980e9c123a5SAndrew Rybchenko goto fail3; 981e9c123a5SAndrew Rybchenko } 982e9c123a5SAndrew Rybchenko 983a21b2f20SAndrew Rybchenko if (verify_resultp != NULL) 984a21b2f20SAndrew Rybchenko *verify_resultp = verify_result; 985e9c123a5SAndrew Rybchenko 9863c838a9fSAndrew Rybchenko return (0); 9873c838a9fSAndrew Rybchenko 988e9c123a5SAndrew Rybchenko fail3: 989e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail3); 990e9c123a5SAndrew Rybchenko fail2: 991e9c123a5SAndrew Rybchenko EFSYS_PROBE(fail2); 9923c838a9fSAndrew Rybchenko fail1: 993460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9943c838a9fSAndrew Rybchenko 995e9c123a5SAndrew Rybchenko /* Always report verification result */ 996a21b2f20SAndrew Rybchenko if (verify_resultp != NULL) 997a21b2f20SAndrew Rybchenko *verify_resultp = verify_result; 998e9c123a5SAndrew Rybchenko 9993c838a9fSAndrew Rybchenko return (rc); 10003c838a9fSAndrew Rybchenko } 10013c838a9fSAndrew Rybchenko 10023c838a9fSAndrew Rybchenko #if EFSYS_OPT_DIAG 10033c838a9fSAndrew Rybchenko 1004460cb568SAndrew Rybchenko __checkReturn efx_rc_t 10053c838a9fSAndrew Rybchenko efx_mcdi_nvram_test( 10063c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 10073c838a9fSAndrew Rybchenko __in uint32_t partn) 10083c838a9fSAndrew Rybchenko { 10093c838a9fSAndrew Rybchenko efx_mcdi_req_t req; 10103c838a9fSAndrew Rybchenko uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, 10113c838a9fSAndrew Rybchenko MC_CMD_NVRAM_TEST_OUT_LEN)]; 10123c838a9fSAndrew Rybchenko int result; 1013460cb568SAndrew Rybchenko efx_rc_t rc; 10143c838a9fSAndrew Rybchenko 10153c838a9fSAndrew Rybchenko (void) memset(payload, 0, sizeof (payload)); 10163c838a9fSAndrew Rybchenko req.emr_cmd = MC_CMD_NVRAM_TEST; 10173c838a9fSAndrew Rybchenko req.emr_in_buf = payload; 10183c838a9fSAndrew Rybchenko req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; 10193c838a9fSAndrew Rybchenko req.emr_out_buf = payload; 10203c838a9fSAndrew Rybchenko req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; 10213c838a9fSAndrew Rybchenko 10223c838a9fSAndrew Rybchenko MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn); 10233c838a9fSAndrew Rybchenko 10243c838a9fSAndrew Rybchenko efx_mcdi_execute(enp, &req); 10253c838a9fSAndrew Rybchenko 10263c838a9fSAndrew Rybchenko if (req.emr_rc != 0) { 10273c838a9fSAndrew Rybchenko rc = req.emr_rc; 10283c838a9fSAndrew Rybchenko goto fail1; 10293c838a9fSAndrew Rybchenko } 10303c838a9fSAndrew Rybchenko 10313c838a9fSAndrew Rybchenko if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { 10323c838a9fSAndrew Rybchenko rc = EMSGSIZE; 10333c838a9fSAndrew Rybchenko goto fail2; 10343c838a9fSAndrew Rybchenko } 10353c838a9fSAndrew Rybchenko 10363c838a9fSAndrew Rybchenko result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); 10373c838a9fSAndrew Rybchenko if (result == MC_CMD_NVRAM_TEST_FAIL) { 10383c838a9fSAndrew Rybchenko 10393c838a9fSAndrew Rybchenko EFSYS_PROBE1(nvram_test_failure, int, partn); 10403c838a9fSAndrew Rybchenko 10413c838a9fSAndrew Rybchenko rc = (EINVAL); 10423c838a9fSAndrew Rybchenko goto fail3; 10433c838a9fSAndrew Rybchenko } 10443c838a9fSAndrew Rybchenko 10453c838a9fSAndrew Rybchenko return (0); 10463c838a9fSAndrew Rybchenko 10473c838a9fSAndrew Rybchenko fail3: 10483c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 10493c838a9fSAndrew Rybchenko fail2: 10503c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 10513c838a9fSAndrew Rybchenko fail1: 1052460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 10533c838a9fSAndrew Rybchenko 10543c838a9fSAndrew Rybchenko return (rc); 10553c838a9fSAndrew Rybchenko } 10563c838a9fSAndrew Rybchenko 10573c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_DIAG */ 10583c838a9fSAndrew Rybchenko 10593c838a9fSAndrew Rybchenko 10603c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */ 1061