sfc: extend MTD support for newer hardware
The X2 family of NICs (based on the SFC9250) have additional MTD partitions for firmware and configuration. This includes partitions that are read-only. The NICs also have extended versions of the NVRAM interface, allowing more detailed status information to be returned. Signed-off-by: Bert Kenward <bkenward@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cea3bfb374
commit
5fb1beecea
@ -6041,10 +6041,11 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = {
|
||||
{ NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT3, 0, 3, "sfc_exp_rom_cfg" },
|
||||
{ NVRAM_PARTITION_TYPE_LICENSE, 0, 0, "sfc_license" },
|
||||
{ NVRAM_PARTITION_TYPE_PHY_MIN, 0xff, 0, "sfc_phy_fw" },
|
||||
/* MUM and SUC firmware share the same partition type */
|
||||
{ NVRAM_PARTITION_TYPE_MUM_FIRMWARE, 0, 0, "sfc_mumfw" },
|
||||
{ NVRAM_PARTITION_TYPE_EXPANSION_UEFI, 0, 0, "sfc_uefi" },
|
||||
{ NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" }
|
||||
{ NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS, 0, 0, "sfc_dynamic_cfg_dflt" },
|
||||
{ NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS, 0, 0, "sfc_exp_rom_cfg_dflt" },
|
||||
{ NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" },
|
||||
};
|
||||
|
||||
static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
|
||||
@ -6071,8 +6072,15 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
|
||||
rc = efx_mcdi_nvram_info(efx, type, &size, &erase_size, &protected);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (protected &&
|
||||
(type != NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS &&
|
||||
type != NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS))
|
||||
/* Hide protected partitions that don't provide defaults. */
|
||||
return -ENODEV;
|
||||
|
||||
if (protected)
|
||||
return -ENODEV; /* hide it */
|
||||
/* Protected partitions are read only. */
|
||||
erase_size = 0;
|
||||
|
||||
part->nvram_type = type;
|
||||
|
||||
|
@ -2074,22 +2074,26 @@ fail:
|
||||
|
||||
static int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
|
||||
{
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN);
|
||||
int rc;
|
||||
|
||||
MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
|
||||
MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_START_V2_IN_FLAGS,
|
||||
NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT,
|
||||
1);
|
||||
|
||||
BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
|
||||
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
|
||||
NULL, 0, NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
|
||||
loff_t offset, u8 *buffer, size_t length)
|
||||
{
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_V2_LEN);
|
||||
MCDI_DECLARE_BUF(outbuf,
|
||||
MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
|
||||
size_t outlen;
|
||||
@ -2098,6 +2102,8 @@ static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
|
||||
MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
|
||||
MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
|
||||
MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
|
||||
MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_V2_MODE,
|
||||
MC_CMD_NVRAM_READ_IN_V2_DEFAULT);
|
||||
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
|
||||
outbuf, sizeof(outbuf), &outlen);
|
||||
@ -2147,15 +2153,51 @@ static int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
|
||||
|
||||
static int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
|
||||
{
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
|
||||
int rc;
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN);
|
||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN);
|
||||
size_t outlen;
|
||||
int rc, rc2;
|
||||
|
||||
MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
|
||||
|
||||
BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
|
||||
/* Always set this flag. Old firmware ignores it */
|
||||
MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
|
||||
NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT,
|
||||
1);
|
||||
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
|
||||
NULL, 0, NULL);
|
||||
outbuf, sizeof(outbuf), &outlen);
|
||||
if (!rc && outlen >= MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
|
||||
rc2 = MCDI_DWORD(outbuf, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
|
||||
if (rc2 != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)
|
||||
netif_err(efx, drv, efx->net_dev,
|
||||
"NVRAM update failed verification with code 0x%x\n",
|
||||
rc2);
|
||||
switch (rc2) {
|
||||
case MC_CMD_NVRAM_VERIFY_RC_SUCCESS:
|
||||
break;
|
||||
case MC_CMD_NVRAM_VERIFY_RC_CMS_CHECK_FAILED:
|
||||
case MC_CMD_NVRAM_VERIFY_RC_MESSAGE_DIGEST_CHECK_FAILED:
|
||||
case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHECK_FAILED:
|
||||
case MC_CMD_NVRAM_VERIFY_RC_TRUSTED_APPROVERS_CHECK_FAILED:
|
||||
case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHAIN_CHECK_FAILED:
|
||||
rc = -EIO;
|
||||
break;
|
||||
case MC_CMD_NVRAM_VERIFY_RC_INVALID_CMS_FORMAT:
|
||||
case MC_CMD_NVRAM_VERIFY_RC_BAD_MESSAGE_DIGEST:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
case MC_CMD_NVRAM_VERIFY_RC_NO_VALID_SIGNATURES:
|
||||
case MC_CMD_NVRAM_VERIFY_RC_NO_TRUSTED_APPROVERS:
|
||||
case MC_CMD_NVRAM_VERIFY_RC_NO_SIGNATURE_MATCH:
|
||||
rc = -EPERM;
|
||||
break;
|
||||
default:
|
||||
netif_err(efx, drv, efx->net_dev,
|
||||
"Unknown response to NVRAM_UPDATE_FINISH\n");
|
||||
rc = -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,9 @@ int efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts,
|
||||
|
||||
part->mtd.writesize = 1;
|
||||
|
||||
if (!(part->mtd.flags & MTD_NO_ERASE))
|
||||
part->mtd.flags |= MTD_WRITEABLE;
|
||||
|
||||
part->mtd.owner = THIS_MODULE;
|
||||
part->mtd.priv = efx;
|
||||
part->mtd.name = part->name;
|
||||
|
Loading…
Reference in New Issue
Block a user