diff options
Diffstat (limited to 'drivers/net/sfc/base/efx_nvram.c')
-rw-r--r-- | drivers/net/sfc/base/efx_nvram.c | 192 |
1 files changed, 98 insertions, 94 deletions
diff --git a/drivers/net/sfc/base/efx_nvram.c b/drivers/net/sfc/base/efx_nvram.c index 6ee2a71d..c2cc9ad3 100644 --- a/drivers/net/sfc/base/efx_nvram.c +++ b/drivers/net/sfc/base/efx_nvram.c @@ -1,31 +1,7 @@ -/* - * Copyright (c) 2009-2016 Solarflare Communications Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause * - * The views and conclusions contained in the software and documentation are - * those of the authors and should not be interpreted as representing official - * policies, either expressed or implied, of the FreeBSD Project. + * Copyright (c) 2009-2018 Solarflare Communications Inc. + * All rights reserved. */ #include "efx.h" @@ -43,6 +19,7 @@ static const efx_nvram_ops_t __efx_nvram_siena_ops = { siena_nvram_partn_size, /* envo_partn_size */ siena_nvram_partn_rw_start, /* envo_partn_rw_start */ siena_nvram_partn_read, /* envo_partn_read */ + siena_nvram_partn_read, /* envo_partn_read_backup */ siena_nvram_partn_erase, /* envo_partn_erase */ siena_nvram_partn_write, /* envo_partn_write */ siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */ @@ -63,6 +40,7 @@ static const efx_nvram_ops_t __efx_nvram_ef10_ops = { ef10_nvram_partn_size, /* envo_partn_size */ ef10_nvram_partn_rw_start, /* envo_partn_rw_start */ ef10_nvram_partn_read, /* envo_partn_read */ + ef10_nvram_partn_read_backup, /* envo_partn_read_backup */ ef10_nvram_partn_erase, /* envo_partn_erase */ ef10_nvram_partn_write, /* envo_partn_write */ ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */ @@ -112,6 +90,8 @@ efx_nvram_init( enp->en_envop = envop; enp->en_mod_flags |= EFX_MOD_NVRAM; + enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; + return (0); fail1: @@ -158,8 +138,6 @@ efx_nvram_size( EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; @@ -192,8 +170,6 @@ efx_nvram_get_version( EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; @@ -224,18 +200,15 @@ efx_nvram_rw_start( EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); - - EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); + if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0) goto fail2; - enp->en_nvram_locked = type; + enp->en_nvram_partn_locked = partn; return (0); @@ -262,15 +235,51 @@ efx_nvram_read_chunk( EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) + goto fail1; + + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); - EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); + if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) + goto fail2; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + +/* + * Read from the backup (writeable) store of an A/B partition. + * For non A/B partitions, there is only a single store, and so this + * function has the same behaviour as efx_nvram_read_chunk(). + */ + __checkReturn efx_rc_t +efx_nvram_read_backup( + __in efx_nic_t *enp, + __in efx_nvram_type_t type, + __in unsigned int offset, + __out_bcount(size) caddr_t data, + __in size_t size) +{ + const efx_nvram_ops_t *envop = enp->en_envop; + uint32_t partn; + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; - if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0) + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); + + if ((rc = envop->envo_partn_read_backup(enp, partn, offset, + data, size)) != 0) goto fail2; return (0); @@ -297,14 +306,11 @@ efx_nvram_erase( EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); - - EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); + if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0) goto fail2; @@ -338,14 +344,11 @@ efx_nvram_write_chunk( EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); - - EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); + if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0) goto fail2; @@ -362,37 +365,43 @@ fail1: __checkReturn efx_rc_t efx_nvram_rw_finish( __in efx_nic_t *enp, - __in efx_nvram_type_t type) + __in efx_nvram_type_t type, + __out_opt uint32_t *verify_resultp) { const efx_nvram_ops_t *envop = enp->en_envop; uint32_t partn; + uint32_t verify_result = 0; efx_rc_t rc; EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID); - - EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type); - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; - if ((rc = envop->envo_partn_rw_finish(enp, partn)) != 0) + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn); + + if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0) goto fail2; - enp->en_nvram_locked = EFX_NVRAM_INVALID; + enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; + + if (verify_resultp != NULL) + *verify_resultp = verify_result; return (0); fail2: EFSYS_PROBE(fail2); - enp->en_nvram_locked = EFX_NVRAM_INVALID; + enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID; fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); + /* Always report verification result */ + if (verify_resultp != NULL) + *verify_resultp = verify_result; + return (rc); } @@ -410,17 +419,15 @@ efx_nvram_set_version( EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); + if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) + goto fail1; /* * The Siena implementation of envo_set_version() will attempt to - * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector. + * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition. * Therefore, you can't have already acquired the NVRAM_UPDATE lock. */ - EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); - - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) - goto fail1; + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0) goto fail2; @@ -451,16 +458,14 @@ efx_nvram_validate( EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); - - if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0) goto fail1; - if (envop->envo_type_to_partn != NULL && - ((rc = envop->envo_buffer_validate(enp, partn, - partn_data, partn_size)) != 0)) - goto fail2; + if (envop->envo_buffer_validate != NULL) { + if ((rc = envop->envo_buffer_validate(enp, partn, + partn_data, partn_size)) != 0) + goto fail2; + } return (0); @@ -481,7 +486,7 @@ efx_nvram_fini( EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM); - EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID); + EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID); enp->en_envop = NULL; enp->en_mod_flags &= ~EFX_MOD_NVRAM; @@ -579,7 +584,7 @@ efx_mcdi_nvram_metadata( MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn); - efx_mcdi_execute(enp, &req); + efx_mcdi_execute_quiet(enp, &req); if (req.emr_rc != 0) { rc = req.emr_rc; @@ -915,13 +920,13 @@ efx_mcdi_nvram_update_finish( __in efx_nic_t *enp, __in uint32_t partn, __in boolean_t reboot, - __out_opt uint32_t *resultp) + __out_opt uint32_t *verify_resultp) { const efx_nic_cfg_t *encp = &enp->en_nic_cfg; efx_mcdi_req_t req; uint8_t payload[MAX(MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN, MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN)]; - uint32_t result = 0; /* FIXME: use MC_CMD_NVRAM_VERIFY_RC_UNKNOWN */ + uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; efx_rc_t rc; (void) memset(payload, 0, sizeof (payload)); @@ -944,28 +949,27 @@ efx_mcdi_nvram_update_finish( goto fail1; } - if (encp->enc_fw_verified_nvram_update_required == B_FALSE) { - /* Report success if verified updates are not supported. */ - result = MC_CMD_NVRAM_VERIFY_RC_SUCCESS; - } else { - /* Firmware-verified NVRAM updates are required */ - if (req.emr_out_length_used < - MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { + if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { + verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN; + if (encp->enc_nvram_update_verify_result_supported) { + /* Result of update verification is missing */ rc = EMSGSIZE; goto fail2; } - result = + } else { + verify_result = MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE); + } - if (result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) { - /* Mandatory verification failed */ - rc = EINVAL; - goto fail3; - } + if ((encp->enc_nvram_update_verify_result_supported) && + (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) { + /* Update verification failed */ + rc = EINVAL; + goto fail3; } - if (resultp != NULL) - *resultp = result; + if (verify_resultp != NULL) + *verify_resultp = verify_result; return (0); @@ -977,8 +981,8 @@ fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); /* Always report verification result */ - if (resultp != NULL) - *resultp = result; + if (verify_resultp != NULL) + *verify_resultp = verify_result; return (rc); } |