sfc: extend MTD support for newer hardware
authorBert Kenward <bkenward@solarflare.com>
Wed, 16 Jan 2019 10:00:39 +0000 (10:00 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 17 Jan 2019 20:10:14 +0000 (12:10 -0800)
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>
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mtd.c

index b6a50058bb8db90b0f8c459469b3cc058692efdc..ee42d4a887d7955c9fa5f355d8daf85c1be57103 100644 (file)
@@ -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;
 
index dfad93fca0a61c1d353ad4d8527751a930f517ef..295ec1787b9f2d6c79154774c83a5f7587f25020 100644 (file)
@@ -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;
 }
 
index 4ac30b6e5dab2655015fd53d8c426765218ae9d1..0d03e0577d8586b11774a2755c67bf711a0ed0ad 100644 (file)
@@ -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;