Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/sfxge/common/siena_nvram.c
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/*- | /*- | ||||
* Copyright 2009 Solarflare Communications Inc. All rights reserved. | * Copyright (c) 2009-2015 Solarflare Communications Inc. | ||||
* All rights reserved. | |||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions are met: | ||||
* 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 AUTHOR AND CONTRIBUTORS ``AS IS AND | * 1. Redistributions of source code must retain the above copyright notice, | ||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | * this list of conditions and the following disclaimer. | ||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | * this list of conditions and the following disclaimer in the documentation | ||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | * and/or other materials provided with the distribution. | ||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | * | ||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
* SUCH DAMAGE. | * 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. | |||||
* | |||||
* 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. | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "efsys.h" | #include "efsys.h" | ||||
#include "efx.h" | #include "efx.h" | ||||
#include "efx_types.h" | #include "efx_types.h" | ||||
#include "efx_regs.h" | #include "efx_regs.h" | ||||
#include "efx_impl.h" | #include "efx_impl.h" | ||||
#if EFSYS_OPT_SIENA | #if EFSYS_OPT_SIENA | ||||
#if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM | #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_partn_size( | siena_nvram_partn_size( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn, | __in unsigned int partn, | ||||
__out size_t *sizep) | __out size_t *sizep) | ||||
{ | { | ||||
efx_mcdi_req_t req; | |||||
uint8_t payload[MAX(MC_CMD_NVRAM_INFO_IN_LEN, | |||||
MC_CMD_NVRAM_INFO_OUT_LEN)]; | |||||
int rc; | int rc; | ||||
if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) { | if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) { | ||||
rc = ENOTSUP; | rc = ENOTSUP; | ||||
goto fail1; | goto fail1; | ||||
} | } | ||||
req.emr_cmd = MC_CMD_NVRAM_INFO; | if ((rc = efx_mcdi_nvram_info(enp, partn, sizep, NULL, NULL)) != 0) { | ||||
req.emr_in_buf = payload; | |||||
req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN; | |||||
req.emr_out_buf = payload; | |||||
req.emr_out_length = MC_CMD_NVRAM_INFO_OUT_LEN; | |||||
MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn); | |||||
efx_mcdi_execute(enp, &req); | |||||
if (req.emr_rc != 0) { | |||||
rc = req.emr_rc; | |||||
goto fail2; | goto fail2; | ||||
} | } | ||||
if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) { | |||||
rc = EMSGSIZE; | |||||
goto fail3; | |||||
} | |||||
*sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE); | |||||
return (0); | return (0); | ||||
fail3: | |||||
EFSYS_PROBE(fail3); | |||||
fail2: | fail2: | ||||
EFSYS_PROBE(fail2); | EFSYS_PROBE(fail2); | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_partn_lock( | siena_nvram_partn_lock( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn) | __in unsigned int partn) | ||||
{ | { | ||||
efx_mcdi_req_t req; | |||||
uint8_t payload[MC_CMD_NVRAM_UPDATE_START_IN_LEN]; | |||||
int rc; | int rc; | ||||
req.emr_cmd = MC_CMD_NVRAM_UPDATE_START; | if ((rc = efx_mcdi_nvram_update_start(enp, partn)) != 0) { | ||||
req.emr_in_buf = payload; | |||||
req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_IN_LEN; | |||||
EFX_STATIC_ASSERT(MC_CMD_NVRAM_UPDATE_START_OUT_LEN == 0); | |||||
req.emr_out_buf = NULL; | |||||
req.emr_out_length = 0; | |||||
MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_IN_TYPE, partn); | |||||
efx_mcdi_execute(enp, &req); | |||||
if (req.emr_rc != 0) { | |||||
rc = req.emr_rc; | |||||
goto fail1; | goto fail1; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_partn_read( | siena_nvram_partn_read( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn, | __in unsigned int partn, | ||||
__in unsigned int offset, | __in unsigned int offset, | ||||
__out_bcount(size) caddr_t data, | __out_bcount(size) caddr_t data, | ||||
__in size_t size) | __in size_t size) | ||||
{ | { | ||||
efx_mcdi_req_t req; | |||||
uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN, | |||||
MC_CMD_NVRAM_READ_OUT_LEN(SIENA_NVRAM_CHUNK))]; | |||||
size_t chunk; | size_t chunk; | ||||
int rc; | int rc; | ||||
while (size > 0) { | while (size > 0) { | ||||
chunk = MIN(size, SIENA_NVRAM_CHUNK); | chunk = MIN(size, SIENA_NVRAM_CHUNK); | ||||
req.emr_cmd = MC_CMD_NVRAM_READ; | if ((rc = efx_mcdi_nvram_read(enp, partn, offset, | ||||
req.emr_in_buf = payload; | data, chunk)) != 0) { | ||||
req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN; | |||||
req.emr_out_buf = payload; | |||||
req.emr_out_length = | |||||
MC_CMD_NVRAM_READ_OUT_LEN(SIENA_NVRAM_CHUNK); | |||||
MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn); | |||||
MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset); | |||||
MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, chunk); | |||||
efx_mcdi_execute(enp, &req); | |||||
if (req.emr_rc != 0) { | |||||
rc = req.emr_rc; | |||||
goto fail1; | goto fail1; | ||||
} | } | ||||
if (req.emr_out_length_used < | |||||
MC_CMD_NVRAM_READ_OUT_LEN(chunk)) { | |||||
rc = EMSGSIZE; | |||||
goto fail2; | |||||
} | |||||
memcpy(data, | |||||
MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER), | |||||
chunk); | |||||
size -= chunk; | size -= chunk; | ||||
data += chunk; | data += chunk; | ||||
offset += chunk; | offset += chunk; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail2: | |||||
EFSYS_PROBE(fail2); | |||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_partn_erase( | siena_nvram_partn_erase( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn, | __in unsigned int partn, | ||||
__in unsigned int offset, | __in unsigned int offset, | ||||
__in size_t size) | __in size_t size) | ||||
{ | { | ||||
efx_mcdi_req_t req; | |||||
uint8_t payload[MC_CMD_NVRAM_ERASE_IN_LEN]; | |||||
int rc; | int rc; | ||||
req.emr_cmd = MC_CMD_NVRAM_ERASE; | if ((rc = efx_mcdi_nvram_erase(enp, partn, offset, size)) != 0) { | ||||
req.emr_in_buf = payload; | |||||
req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN; | |||||
EFX_STATIC_ASSERT(MC_CMD_NVRAM_ERASE_OUT_LEN == 0); | |||||
req.emr_out_buf = NULL; | |||||
req.emr_out_length = 0; | |||||
MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn); | |||||
MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset); | |||||
MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size); | |||||
efx_mcdi_execute(enp, &req); | |||||
if (req.emr_rc != 0) { | |||||
rc = req.emr_rc; | |||||
goto fail1; | goto fail1; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_partn_write( | siena_nvram_partn_write( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn, | __in unsigned int partn, | ||||
__in unsigned int offset, | __in unsigned int offset, | ||||
__out_bcount(size) caddr_t data, | __out_bcount(size) caddr_t data, | ||||
__in size_t size) | __in size_t size) | ||||
{ | { | ||||
efx_mcdi_req_t req; | |||||
uint8_t payload[MC_CMD_NVRAM_WRITE_IN_LEN(SIENA_NVRAM_CHUNK)]; | |||||
size_t chunk; | size_t chunk; | ||||
int rc; | int rc; | ||||
while (size > 0) { | while (size > 0) { | ||||
chunk = MIN(size, SIENA_NVRAM_CHUNK); | chunk = MIN(size, SIENA_NVRAM_CHUNK); | ||||
req.emr_cmd = MC_CMD_NVRAM_WRITE; | if ((rc = efx_mcdi_nvram_write(enp, partn, offset, | ||||
req.emr_in_buf = payload; | data, chunk)) != 0) { | ||||
req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(chunk); | |||||
EFX_STATIC_ASSERT(MC_CMD_NVRAM_WRITE_OUT_LEN == 0); | |||||
req.emr_out_buf = NULL; | |||||
req.emr_out_length = 0; | |||||
MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn); | |||||
MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset); | |||||
MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, chunk); | |||||
memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER), | |||||
data, chunk); | |||||
efx_mcdi_execute(enp, &req); | |||||
if (req.emr_rc != 0) { | |||||
rc = req.emr_rc; | |||||
goto fail1; | goto fail1; | ||||
} | } | ||||
size -= chunk; | size -= chunk; | ||||
data += chunk; | data += chunk; | ||||
offset += chunk; | offset += chunk; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
void | void | ||||
siena_nvram_partn_unlock( | siena_nvram_partn_unlock( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn) | __in unsigned int partn) | ||||
{ | { | ||||
efx_mcdi_req_t req; | boolean_t reboot; | ||||
uint8_t payload[MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN]; | |||||
uint32_t reboot; | |||||
int rc; | int rc; | ||||
req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH; | |||||
req.emr_in_buf = payload; | |||||
req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN; | |||||
EFX_STATIC_ASSERT(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN == 0); | |||||
req.emr_out_buf = NULL; | |||||
req.emr_out_length = 0; | |||||
/* | /* | ||||
* Reboot into the new image only for PHYs. The driver has to | * Reboot into the new image only for PHYs. The driver has to | ||||
* explicitly cope with an MC reboot after a firmware update. | * explicitly cope with an MC reboot after a firmware update. | ||||
*/ | */ | ||||
reboot = (partn == MC_CMD_NVRAM_TYPE_PHY_PORT0 || | reboot = (partn == MC_CMD_NVRAM_TYPE_PHY_PORT0 || | ||||
partn == MC_CMD_NVRAM_TYPE_PHY_PORT1 || | partn == MC_CMD_NVRAM_TYPE_PHY_PORT1 || | ||||
partn == MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO); | partn == MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO); | ||||
MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_TYPE, partn); | if ((rc = efx_mcdi_nvram_update_finish(enp, partn, reboot)) != 0) { | ||||
MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_IN_REBOOT, reboot); | |||||
efx_mcdi_execute(enp, &req); | |||||
if (req.emr_rc != 0) { | |||||
rc = req.emr_rc; | |||||
goto fail1; | goto fail1; | ||||
} | } | ||||
return; | return; | ||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
} | } | ||||
Show All 24 Lines | static siena_parttbl_entry_t siena_parttbl[] = { | ||||
{MC_CMD_NVRAM_TYPE_FPGA, 1, EFX_NVRAM_FPGA}, | {MC_CMD_NVRAM_TYPE_FPGA, 1, EFX_NVRAM_FPGA}, | ||||
{MC_CMD_NVRAM_TYPE_FPGA, 2, EFX_NVRAM_FPGA}, | {MC_CMD_NVRAM_TYPE_FPGA, 2, EFX_NVRAM_FPGA}, | ||||
{MC_CMD_NVRAM_TYPE_FPGA_BACKUP, 1, EFX_NVRAM_FPGA_BACKUP}, | {MC_CMD_NVRAM_TYPE_FPGA_BACKUP, 1, EFX_NVRAM_FPGA_BACKUP}, | ||||
{MC_CMD_NVRAM_TYPE_FPGA_BACKUP, 2, EFX_NVRAM_FPGA_BACKUP}, | {MC_CMD_NVRAM_TYPE_FPGA_BACKUP, 2, EFX_NVRAM_FPGA_BACKUP}, | ||||
{MC_CMD_NVRAM_TYPE_FC_FW, 1, EFX_NVRAM_FCFW}, | {MC_CMD_NVRAM_TYPE_FC_FW, 1, EFX_NVRAM_FCFW}, | ||||
{MC_CMD_NVRAM_TYPE_FC_FW, 2, EFX_NVRAM_FCFW}, | {MC_CMD_NVRAM_TYPE_FC_FW, 2, EFX_NVRAM_FCFW}, | ||||
{MC_CMD_NVRAM_TYPE_CPLD, 1, EFX_NVRAM_CPLD}, | {MC_CMD_NVRAM_TYPE_CPLD, 1, EFX_NVRAM_CPLD}, | ||||
{MC_CMD_NVRAM_TYPE_CPLD, 2, EFX_NVRAM_CPLD}, | {MC_CMD_NVRAM_TYPE_CPLD, 2, EFX_NVRAM_CPLD}, | ||||
{0, 0, 0}, | |||||
}; | }; | ||||
static __checkReturn siena_parttbl_entry_t * | static __checkReturn siena_parttbl_entry_t * | ||||
siena_parttbl_entry( | siena_parttbl_entry( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in efx_nvram_type_t type) | __in efx_nvram_type_t type) | ||||
{ | { | ||||
efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip); | efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); | ||||
siena_parttbl_entry_t *entry; | siena_parttbl_entry_t *entry; | ||||
unsigned int i; | |||||
EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); | EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES); | ||||
for (entry = siena_parttbl; entry->port > 0; ++entry) { | for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) { | ||||
entry = &siena_parttbl[i]; | |||||
if (entry->port == emip->emi_port && entry->nvtype == type) | if (entry->port == emip->emi_port && entry->nvtype == type) | ||||
return (entry); | return (entry); | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#if EFSYS_OPT_DIAG | #if EFSYS_OPT_DIAG | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_test( | siena_nvram_test( | ||||
__in efx_nic_t *enp) | __in efx_nic_t *enp) | ||||
{ | { | ||||
efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip); | efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip); | ||||
siena_parttbl_entry_t *entry; | siena_parttbl_entry_t *entry; | ||||
efx_mcdi_req_t req; | unsigned int i; | ||||
uint8_t payload[MAX(MC_CMD_NVRAM_TEST_IN_LEN, | |||||
MC_CMD_NVRAM_TEST_OUT_LEN)]; | |||||
int result; | |||||
int rc; | int rc; | ||||
req.emr_cmd = MC_CMD_NVRAM_TEST; | |||||
req.emr_in_buf = payload; | |||||
req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN; | |||||
req.emr_out_buf = payload; | |||||
req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN; | |||||
/* | /* | ||||
* Iterate over the list of supported partition types | * Iterate over the list of supported partition types | ||||
* applicable to *this* port | * applicable to *this* port | ||||
*/ | */ | ||||
for (entry = siena_parttbl; entry->port > 0; ++entry) { | for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) { | ||||
entry = &siena_parttbl[i]; | |||||
if (entry->port != emip->emi_port || | if (entry->port != emip->emi_port || | ||||
!(enp->en_u.siena.enu_partn_mask & (1 << entry->partn))) | !(enp->en_u.siena.enu_partn_mask & (1 << entry->partn))) | ||||
continue; | continue; | ||||
MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, entry->partn); | if ((rc = efx_mcdi_nvram_test(enp, entry->partn)) != 0) { | ||||
efx_mcdi_execute(enp, &req); | |||||
if (req.emr_rc != 0) { | |||||
rc = req.emr_rc; | |||||
goto fail1; | goto fail1; | ||||
} | } | ||||
if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) { | |||||
rc = EMSGSIZE; | |||||
goto fail2; | |||||
} | } | ||||
result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT); | |||||
if (result == MC_CMD_NVRAM_TEST_FAIL) { | |||||
EFSYS_PROBE1(nvram_test_failure, int, entry->partn); | |||||
rc = (EINVAL); | |||||
goto fail3; | |||||
} | |||||
} | |||||
return (0); | return (0); | ||||
fail3: | |||||
EFSYS_PROBE(fail3); | |||||
fail2: | |||||
EFSYS_PROBE(fail2); | |||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
#endif /* EFSYS_OPT_DIAG */ | #endif /* EFSYS_OPT_DIAG */ | ||||
Show All 33 Lines | #define SIENA_DYNAMIC_CFG_SIZE(_nitems) \ | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_get_dynamic_cfg( | siena_nvram_get_dynamic_cfg( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn, | __in unsigned int partn, | ||||
__in boolean_t vpd, | __in boolean_t vpd, | ||||
__out siena_mc_dynamic_config_hdr_t **dcfgp, | __out siena_mc_dynamic_config_hdr_t **dcfgp, | ||||
__out size_t *sizep) | __out size_t *sizep) | ||||
{ | { | ||||
siena_mc_dynamic_config_hdr_t *dcfg; | siena_mc_dynamic_config_hdr_t *dcfg = NULL; | ||||
size_t size; | size_t size; | ||||
uint8_t cksum; | uint8_t cksum; | ||||
unsigned int vpd_offset; | unsigned int vpd_offset; | ||||
unsigned int vpd_length; | unsigned int vpd_length; | ||||
unsigned int hdr_length; | unsigned int hdr_length; | ||||
unsigned int nversions; | unsigned int nversions; | ||||
unsigned int pos; | unsigned int pos; | ||||
unsigned int region; | unsigned int region; | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | done: | ||||
*sizep = size; | *sizep = size; | ||||
return (0); | return (0); | ||||
fail4: | fail4: | ||||
EFSYS_PROBE(fail4); | EFSYS_PROBE(fail4); | ||||
fail3: | fail3: | ||||
EFSYS_PROBE(fail3); | EFSYS_PROBE(fail3); | ||||
fail2: | |||||
EFSYS_PROBE(fail2); | |||||
EFSYS_KMEM_FREE(enp->en_esip, size, dcfg); | EFSYS_KMEM_FREE(enp->en_esip, size, dcfg); | ||||
fail2: | |||||
EFSYS_PROBE(fail2); | |||||
fail1: | fail1: | ||||
EFSYS_PROBE1(fail1, int, rc); | EFSYS_PROBE1(fail1, int, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
static __checkReturn int | __checkReturn int | ||||
siena_nvram_get_subtype( | siena_nvram_get_subtype( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in unsigned int partn, | __in unsigned int partn, | ||||
__out uint32_t *subtypep) | __out uint32_t *subtypep) | ||||
{ | { | ||||
efx_mcdi_req_t req; | efx_mcdi_req_t req; | ||||
uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMAX]; | uint8_t payload[MAX(MC_CMD_GET_BOARD_CFG_IN_LEN, | ||||
MC_CMD_GET_BOARD_CFG_OUT_LENMAX)]; | |||||
efx_word_t *fw_list; | efx_word_t *fw_list; | ||||
int rc; | int rc; | ||||
(void) memset(payload, 0, sizeof (payload)); | |||||
req.emr_cmd = MC_CMD_GET_BOARD_CFG; | req.emr_cmd = MC_CMD_GET_BOARD_CFG; | ||||
EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0); | req.emr_in_buf = payload; | ||||
req.emr_in_buf = NULL; | req.emr_in_length = MC_CMD_GET_BOARD_CFG_IN_LEN; | ||||
req.emr_in_length = 0; | req.emr_out_buf = payload; | ||||
req.emr_out_buf = outbuf; | req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMAX; | ||||
req.emr_out_length = sizeof (outbuf); | |||||
efx_mcdi_execute(enp, &req); | efx_mcdi_execute(enp, &req); | ||||
if (req.emr_rc != 0) { | if (req.emr_rc != 0) { | ||||
rc = req.emr_rc; | rc = req.emr_rc; | ||||
goto fail1; | goto fail1; | ||||
} | } | ||||
Show All 31 Lines | siena_nvram_get_version( | ||||
__in efx_nvram_type_t type, | __in efx_nvram_type_t type, | ||||
__out uint32_t *subtypep, | __out uint32_t *subtypep, | ||||
__out_ecount(4) uint16_t version[4]) | __out_ecount(4) uint16_t version[4]) | ||||
{ | { | ||||
siena_mc_dynamic_config_hdr_t *dcfg; | siena_mc_dynamic_config_hdr_t *dcfg; | ||||
siena_parttbl_entry_t *entry; | siena_parttbl_entry_t *entry; | ||||
unsigned int dcfg_partn; | unsigned int dcfg_partn; | ||||
unsigned int partn; | unsigned int partn; | ||||
unsigned int i; | |||||
int rc; | int rc; | ||||
if ((entry = siena_parttbl_entry(enp, type)) == NULL) { | if ((entry = siena_parttbl_entry(enp, type)) == NULL) { | ||||
rc = ENOTSUP; | rc = ENOTSUP; | ||||
goto fail1; | goto fail1; | ||||
} | } | ||||
partn = entry->partn; | partn = entry->partn; | ||||
if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) { | if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) { | ||||
rc = ENOTSUP; | rc = ENOTSUP; | ||||
goto fail2; | goto fail2; | ||||
} | } | ||||
if ((rc = siena_nvram_get_subtype(enp, partn, subtypep)) != 0) | if ((rc = siena_nvram_get_subtype(enp, partn, subtypep)) != 0) | ||||
goto fail3; | goto fail3; | ||||
/* | /* | ||||
* Some partitions are accessible from both ports (for instance BOOTROM) | * Some partitions are accessible from both ports (for instance BOOTROM) | ||||
* Find the highest version reported by all dcfg structures on ports | * Find the highest version reported by all dcfg structures on ports | ||||
* that have access to this partition. | * that have access to this partition. | ||||
*/ | */ | ||||
version[0] = version[1] = version[2] = version[3] = 0; | version[0] = version[1] = version[2] = version[3] = 0; | ||||
for (entry = siena_parttbl; entry->port > 0; ++entry) { | for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) { | ||||
unsigned int nitems; | unsigned int nitems; | ||||
uint16_t temp[4]; | uint16_t temp[4]; | ||||
size_t length; | size_t length; | ||||
entry = &siena_parttbl[i]; | |||||
if (entry->partn != partn) | if (entry->partn != partn) | ||||
continue; | continue; | ||||
dcfg_partn = (entry->port == 1) | dcfg_partn = (entry->port == 1) | ||||
? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 | ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 | ||||
: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1; | : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1; | ||||
/* | /* | ||||
* Ingore missing partitions on port 2, assuming they're due | * Ingore missing partitions on port 2, assuming they're due | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | siena_nvram_rw_finish( | ||||
if ((entry = siena_parttbl_entry(enp, type)) != NULL) | if ((entry = siena_parttbl_entry(enp, type)) != NULL) | ||||
siena_nvram_partn_unlock(enp, entry->partn); | siena_nvram_partn_unlock(enp, entry->partn); | ||||
} | } | ||||
__checkReturn int | __checkReturn int | ||||
siena_nvram_set_version( | siena_nvram_set_version( | ||||
__in efx_nic_t *enp, | __in efx_nic_t *enp, | ||||
__in efx_nvram_type_t type, | __in efx_nvram_type_t type, | ||||
__out uint16_t version[4]) | __in_ecount(4) uint16_t version[4]) | ||||
{ | { | ||||
siena_mc_dynamic_config_hdr_t *dcfg = NULL; | siena_mc_dynamic_config_hdr_t *dcfg = NULL; | ||||
siena_parttbl_entry_t *entry; | siena_parttbl_entry_t *entry; | ||||
unsigned int dcfg_partn; | unsigned int dcfg_partn; | ||||
size_t partn_size; | size_t partn_size; | ||||
unsigned int hdr_length; | unsigned int hdr_length; | ||||
unsigned int vpd_length; | unsigned int vpd_length; | ||||
unsigned int vpd_offset; | unsigned int vpd_offset; | ||||
▲ Show 20 Lines • Show All 125 Lines • Show Last 20 Lines |