@@ -6,11 +6,16 @@
struct ixgbe_info_ctx {
char buf[128];
+ struct ixgbe_orom_info pending_orom;
+ struct ixgbe_nvm_info pending_nvm;
+ struct ixgbe_netlist_info pending_netlist;
+ struct ixgbe_hw_dev_caps dev_caps;
};
enum ixgbe_devlink_version_type {
IXGBE_DL_VERSION_FIXED,
IXGBE_DL_VERSION_RUNNING,
+ IXGBE_DL_VERSION_STORED,
};
static int ixgbe_devlink_info_put(struct devlink_info_req *req,
@@ -25,6 +30,8 @@ static int ixgbe_devlink_info_put(struct devlink_info_req *req,
return devlink_info_version_fixed_put(req, key, value);
case IXGBE_DL_VERSION_RUNNING:
return devlink_info_version_running_put(req, key, value);
+ case IXGBE_DL_VERSION_STORED:
+ return devlink_info_version_stored_put(req, key, value);
}
return 0;
@@ -91,6 +98,15 @@ static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
}
+static void ixgbe_info_pending_eetrack(struct ixgbe_adapter *adapter,
+ struct ixgbe_info_ctx *ctx)
+{
+ struct ixgbe_nvm_info *nvm = &ctx->pending_nvm;
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
+ snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
+}
+
static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
@@ -116,6 +132,25 @@ static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter,
snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
}
+static void ixgbe_info_pending_fw_srev(struct ixgbe_adapter *adapter,
+ struct ixgbe_info_ctx *ctx)
+{
+ struct ixgbe_nvm_info *nvm = &ctx->pending_nvm;
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
+ snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
+}
+
+static void ixgbe_info_pending_orom_ver(struct ixgbe_adapter *adapter,
+ struct ixgbe_info_ctx *ctx)
+{
+ struct ixgbe_orom_info *orom = &ctx->pending_orom;
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_orom)
+ snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
+ orom->major, orom->build, orom->patch);
+}
+
static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
@@ -124,6 +159,15 @@ static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
}
+static void ixgbe_info_pending_orom_srev(struct ixgbe_adapter *adapter,
+ struct ixgbe_info_ctx *ctx)
+{
+ struct ixgbe_orom_info *orom = &ctx->pending_orom;
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_orom)
+ snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
+}
+
static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
@@ -132,6 +176,16 @@ static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
}
+static void ixgbe_info_pending_nvm_ver(struct ixgbe_adapter *adapter,
+ struct ixgbe_info_ctx *ctx)
+{
+ struct ixgbe_nvm_info *nvm = &ctx->pending_nvm;
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
+ snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x",
+ nvm->major, nvm->minor);
+}
+
static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
@@ -144,6 +198,19 @@ static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
netlist->rev, netlist->cust_ver);
}
+static void ixgbe_info_pending_netlist_ver(struct ixgbe_adapter *adapter,
+ struct ixgbe_info_ctx *ctx)
+{
+ struct ixgbe_netlist_info *netlist = &ctx->pending_netlist;
+
+ /* The netlist version fields are BCD formatted */
+ if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
+ snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
+ netlist->major, netlist->minor,
+ netlist->type >> 16, netlist->type & 0xFFFF,
+ netlist->rev, netlist->cust_ver);
+}
+
static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
struct ixgbe_info_ctx *ctx)
{
@@ -152,6 +219,50 @@ static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
}
+static void ixgbe_info_pending_netlist_build(struct ixgbe_adapter *adapter,
+ struct ixgbe_info_ctx *ctx)
+{
+ struct ixgbe_netlist_info *netlist = &ctx->pending_netlist;
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
+ snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
+}
+
+static int ixgbe_set_ctx_dev_caps(struct ixgbe_hw *hw,
+ struct ixgbe_info_ctx *ctx,
+ struct netlink_ext_ack *extack)
+{
+ int err = ixgbe_discover_dev_caps(hw, &ctx->dev_caps);
+
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Unable to discover device capabilities");
+ return err;
+ }
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_orom) {
+ err = ixgbe_get_inactive_orom_ver(hw, &ctx->pending_orom);
+ if (err)
+ ctx->dev_caps.common_cap.nvm_update_pending_orom =
+ false;
+ }
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) {
+ err = ixgbe_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
+ if (err)
+ ctx->dev_caps.common_cap.nvm_update_pending_nvm = false;
+ }
+
+ if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) {
+ err = ixgbe_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
+ if (err)
+ ctx->dev_caps.common_cap.nvm_update_pending_netlist =
+ false;
+ }
+
+ return 0;
+}
+
static int ixgbe_devlink_info_get_E610(struct ixgbe_adapter *adapter,
struct devlink_info_req *req,
struct ixgbe_info_ctx *ctx)
@@ -198,6 +309,67 @@ static int ixgbe_devlink_info_get_E610(struct ixgbe_adapter *adapter,
return err;
}
+static int
+ixgbe_devlink_pending_info_get_E610(struct ixgbe_adapter *adapter,
+ struct devlink_info_req *req,
+ struct ixgbe_info_ctx *ctx)
+{
+ int err = 0;
+
+ if (!ctx->dev_caps.common_cap.nvm_update_pending_nvm)
+ goto no_nvm;
+
+ ixgbe_info_pending_fw_srev(adapter, ctx);
+ err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_STORED,
+ "fw.mgmt.srev", ctx->buf);
+ if (err)
+ return err;
+
+ ixgbe_info_pending_eetrack(adapter, ctx);
+ err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_STORED,
+ DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
+ ctx->buf);
+ if (err)
+ return err;
+
+ ixgbe_info_pending_nvm_ver(adapter, ctx);
+ err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_STORED,
+ "fw.psid.api", ctx->buf);
+ if (err)
+ return err;
+
+no_nvm:
+ if (!ctx->dev_caps.common_cap.nvm_update_pending_orom)
+ goto no_orom;
+
+ ixgbe_info_pending_orom_ver(adapter, ctx);
+ err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_STORED,
+ DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
+ ctx->buf);
+ if (err)
+ return err;
+
+ ixgbe_info_pending_orom_srev(adapter, ctx);
+ err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_STORED,
+ "fw.undi.srev", ctx->buf);
+no_orom:
+ if (err || !ctx->dev_caps.common_cap.nvm_update_pending_netlist)
+ return err;
+
+ ixgbe_info_pending_netlist_ver(adapter, ctx);
+ err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_STORED,
+ "fw.netlist", ctx->buf);
+
+ if (err)
+ return err;
+
+ ixgbe_info_pending_netlist_build(adapter, ctx);
+ err = ixgbe_devlink_info_put(req, IXGBE_DL_VERSION_STORED,
+ "fw.netlist.build", ctx->buf);
+
+ return err;
+}
+
static int ixgbe_devlink_info_get(struct devlink *devlink,
struct devlink_info_req *req,
struct netlink_ext_ack *extack)
@@ -239,7 +411,15 @@ static int ixgbe_devlink_info_get(struct devlink *devlink,
if (err || hw->mac.type != ixgbe_mac_e610)
goto free_ctx;
+ err = ixgbe_set_ctx_dev_caps(hw, ctx, extack);
+ if (err)
+ goto free_ctx;
+
err = ixgbe_devlink_info_get_E610(adapter, req, ctx);
+ if (err)
+ goto free_ctx;
+
+ err = ixgbe_devlink_pending_info_get_E610(adapter, req, ctx);
free_ctx:
kfree(ctx);
@@ -588,6 +588,15 @@ static bool ixgbe_parse_e610_caps(struct ixgbe_hw *hw,
break;
case IXGBE_ACI_CAPS_NVM_VER:
break;
+ case IXGBE_ACI_CAPS_PENDING_NVM_VER:
+ caps->nvm_update_pending_nvm = true;
+ break;
+ case IXGBE_ACI_CAPS_PENDING_OROM_VER:
+ caps->nvm_update_pending_orom = true;
+ break;
+ case IXGBE_ACI_CAPS_PENDING_NET_VER:
+ caps->nvm_update_pending_netlist = true;
+ break;
case IXGBE_ACI_CAPS_MAX_MTU:
caps->max_mtu = number;
break;
@@ -2929,6 +2938,23 @@ static int ixgbe_get_orom_ver_info(struct ixgbe_hw *hw,
return err;
}
+/**
+ * ixgbe_get_inactive_orom_ver - Read Option ROM version from the inactive bank
+ * @hw: pointer to the HW structure
+ * @orom: storage for Option ROM version information
+ *
+ * Read the Option ROM version and security revision data for the inactive
+ * section of flash. Used to access version data for a pending update that has
+ * not yet been activated.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_get_inactive_orom_ver(struct ixgbe_hw *hw,
+ struct ixgbe_orom_info *orom)
+{
+ return ixgbe_get_orom_ver_info(hw, IXGBE_INACTIVE_FLASH_BANK, orom);
+}
+
/**
* ixgbe_get_nvm_ver_info - Read NVM version information
* @hw: pointer to the HW struct
@@ -2972,6 +2998,22 @@ static int ixgbe_get_nvm_ver_info(struct ixgbe_hw *hw,
return 0;
}
+/**
+ * ixgbe_get_inactive_nvm_ver - Read Option ROM version from the inactive bank
+ * @hw: pointer to the HW structure
+ * @nvm: storage for Option ROM version information
+ *
+ * Read the NVM EETRACK ID, Map version, and security revision of the
+ * inactive NVM bank. Used to access version data for a pending update that
+ * has not yet been activated.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_get_inactive_nvm_ver(struct ixgbe_hw *hw, struct ixgbe_nvm_info *nvm)
+{
+ return ixgbe_get_nvm_ver_info(hw, IXGBE_INACTIVE_FLASH_BANK, nvm);
+}
+
/**
* ixgbe_get_netlist_info - Read the netlist version information
* @hw: pointer to the HW struct
@@ -3052,6 +3094,23 @@ static int ixgbe_get_netlist_info(struct ixgbe_hw *hw,
return err;
}
+/**
+ * ixgbe_get_inactive_netlist_ver - Read netlist version from the inactive bank
+ * @hw: pointer to the HW struct
+ * @netlist: pointer to netlist version info structure
+ *
+ * Read the netlist version data from the inactive netlist bank. Used to
+ * extract version data of a pending flash update in order to display the
+ * version data.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_get_inactive_netlist_ver(struct ixgbe_hw *hw,
+ struct ixgbe_netlist_info *netlist)
+{
+ return ixgbe_get_netlist_info(hw, IXGBE_INACTIVE_FLASH_BANK, netlist);
+}
+
/**
* ixgbe_get_flash_data - get flash data
* @hw: pointer to the HW struct
@@ -67,6 +67,9 @@ int ixgbe_aci_read_nvm(struct ixgbe_hw *hw, u16 module_typeid, u32 offset,
u16 length, void *data, bool last_command,
bool read_shadow_ram);
int ixgbe_nvm_validate_checksum(struct ixgbe_hw *hw);
+int ixgbe_get_inactive_orom_ver(struct ixgbe_hw *hw, struct ixgbe_orom_info *orom);
+int ixgbe_get_inactive_nvm_ver(struct ixgbe_hw *hw, struct ixgbe_nvm_info *nvm);
+int ixgbe_get_inactive_netlist_ver(struct ixgbe_hw *hw, struct ixgbe_netlist_info *netlist);
int ixgbe_read_sr_word_aci(struct ixgbe_hw *hw, u16 offset, u16 *data);
int ixgbe_read_flat_nvm(struct ixgbe_hw *hw, u32 offset, u32 *length,
u8 *data, bool read_shadow_ram);