xref: /linux/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c (revision 63467137ecc0ff6f804d53903ad87a2f0397a18b)
1a0285236SJedrzej Jagielski // SPDX-License-Identifier: GPL-2.0
2a0285236SJedrzej Jagielski /* Copyright (c) 2025, Intel Corporation. */
3a0285236SJedrzej Jagielski 
4a0285236SJedrzej Jagielski #include "ixgbe.h"
5a0285236SJedrzej Jagielski #include "devlink.h"
6a0f45672SJedrzej Jagielski #include "ixgbe_fw_update.h"
7a0285236SJedrzej Jagielski 
8f6b588afSJedrzej Jagielski struct ixgbe_info_ctx {
9f6b588afSJedrzej Jagielski 	char buf[128];
106eae2aebSJedrzej Jagielski 	struct ixgbe_orom_info pending_orom;
116eae2aebSJedrzej Jagielski 	struct ixgbe_nvm_info pending_nvm;
126eae2aebSJedrzej Jagielski 	struct ixgbe_netlist_info pending_netlist;
136eae2aebSJedrzej Jagielski 	struct ixgbe_hw_dev_caps dev_caps;
146eae2aebSJedrzej Jagielski };
156eae2aebSJedrzej Jagielski 
166eae2aebSJedrzej Jagielski enum ixgbe_devlink_version_type {
176eae2aebSJedrzej Jagielski 	IXGBE_DL_VERSION_RUNNING,
186eae2aebSJedrzej Jagielski 	IXGBE_DL_VERSION_STORED
19f6b588afSJedrzej Jagielski };
20f6b588afSJedrzej Jagielski 
ixgbe_info_get_dsn(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx)21f6b588afSJedrzej Jagielski static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter,
22f6b588afSJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx)
23f6b588afSJedrzej Jagielski {
24f6b588afSJedrzej Jagielski 	u8 dsn[8];
25f6b588afSJedrzej Jagielski 
26f6b588afSJedrzej Jagielski 	/* Copy the DSN into an array in Big Endian format */
27f6b588afSJedrzej Jagielski 	put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn);
28f6b588afSJedrzej Jagielski 
29f6b588afSJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
30f6b588afSJedrzej Jagielski }
31f6b588afSJedrzej Jagielski 
ixgbe_info_orom_ver(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx,enum ixgbe_devlink_version_type type)328210ff73SJedrzej Jagielski static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter,
336eae2aebSJedrzej Jagielski 				struct ixgbe_info_ctx *ctx,
346eae2aebSJedrzej Jagielski 				enum ixgbe_devlink_version_type type)
35f6b588afSJedrzej Jagielski {
36f6b588afSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
37f6b588afSJedrzej Jagielski 	struct ixgbe_nvm_version nvm_ver;
38f6b588afSJedrzej Jagielski 
39f6b588afSJedrzej Jagielski 	ctx->buf[0] = '\0';
40f6b588afSJedrzej Jagielski 
418210ff73SJedrzej Jagielski 	if (hw->mac.type == ixgbe_mac_e610) {
428210ff73SJedrzej Jagielski 		struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
438210ff73SJedrzej Jagielski 
446eae2aebSJedrzej Jagielski 		if (type == IXGBE_DL_VERSION_STORED &&
456eae2aebSJedrzej Jagielski 		    ctx->dev_caps.common_cap.nvm_update_pending_orom)
466eae2aebSJedrzej Jagielski 			orom = &ctx->pending_orom;
476eae2aebSJedrzej Jagielski 
488210ff73SJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
498210ff73SJedrzej Jagielski 			 orom->major, orom->build, orom->patch);
508210ff73SJedrzej Jagielski 		return;
518210ff73SJedrzej Jagielski 	}
528210ff73SJedrzej Jagielski 
53f6b588afSJedrzej Jagielski 	ixgbe_get_oem_prod_version(hw, &nvm_ver);
54f6b588afSJedrzej Jagielski 	if (nvm_ver.oem_valid) {
55f6b588afSJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x",
56f6b588afSJedrzej Jagielski 			 nvm_ver.oem_major, nvm_ver.oem_minor,
57f6b588afSJedrzej Jagielski 			 nvm_ver.oem_release);
58f6b588afSJedrzej Jagielski 
59f6b588afSJedrzej Jagielski 		return;
60f6b588afSJedrzej Jagielski 	}
61f6b588afSJedrzej Jagielski 
62f6b588afSJedrzej Jagielski 	ixgbe_get_orom_version(hw, &nvm_ver);
63f6b588afSJedrzej Jagielski 	if (nvm_ver.or_valid)
64f6b588afSJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d",
65f6b588afSJedrzej Jagielski 			 nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch);
66f6b588afSJedrzej Jagielski }
67f6b588afSJedrzej Jagielski 
ixgbe_info_eetrack(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx,enum ixgbe_devlink_version_type type)68f6b588afSJedrzej Jagielski static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
696eae2aebSJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx,
706eae2aebSJedrzej Jagielski 			       enum ixgbe_devlink_version_type type)
71f6b588afSJedrzej Jagielski {
72f6b588afSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
73f6b588afSJedrzej Jagielski 	struct ixgbe_nvm_version nvm_ver;
74f6b588afSJedrzej Jagielski 
758210ff73SJedrzej Jagielski 	if (hw->mac.type == ixgbe_mac_e610) {
766eae2aebSJedrzej Jagielski 		u32 eetrack = hw->flash.nvm.eetrack;
776eae2aebSJedrzej Jagielski 
786eae2aebSJedrzej Jagielski 		if (type == IXGBE_DL_VERSION_STORED &&
796eae2aebSJedrzej Jagielski 		    ctx->dev_caps.common_cap.nvm_update_pending_nvm)
806eae2aebSJedrzej Jagielski 			eetrack = ctx->pending_nvm.eetrack;
816eae2aebSJedrzej Jagielski 
826eae2aebSJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", eetrack);
838210ff73SJedrzej Jagielski 		return;
848210ff73SJedrzej Jagielski 	}
858210ff73SJedrzej Jagielski 
86f6b588afSJedrzej Jagielski 	ixgbe_get_oem_prod_version(hw, &nvm_ver);
87f6b588afSJedrzej Jagielski 
88f6b588afSJedrzej Jagielski 	/* No ETRACK version for OEM */
89f6b588afSJedrzej Jagielski 	if (nvm_ver.oem_valid) {
90f6b588afSJedrzej Jagielski 		ctx->buf[0] = '\0';
91f6b588afSJedrzej Jagielski 		return;
92f6b588afSJedrzej Jagielski 	}
93f6b588afSJedrzej Jagielski 
94f6b588afSJedrzej Jagielski 	ixgbe_get_etk_id(hw, &nvm_ver);
95f6b588afSJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
96f6b588afSJedrzej Jagielski }
97f6b588afSJedrzej Jagielski 
ixgbe_info_fw_api(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx)988210ff73SJedrzej Jagielski static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter,
998210ff73SJedrzej Jagielski 			      struct ixgbe_info_ctx *ctx)
1008210ff73SJedrzej Jagielski {
1018210ff73SJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
1028210ff73SJedrzej Jagielski 
1038210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
1048210ff73SJedrzej Jagielski 		 hw->api_maj_ver, hw->api_min_ver, hw->api_patch);
1058210ff73SJedrzej Jagielski }
1068210ff73SJedrzej Jagielski 
ixgbe_info_fw_build(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx)1078210ff73SJedrzej Jagielski static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter,
1088210ff73SJedrzej Jagielski 				struct ixgbe_info_ctx *ctx)
1098210ff73SJedrzej Jagielski {
1108210ff73SJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
1118210ff73SJedrzej Jagielski 
1128210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
1138210ff73SJedrzej Jagielski }
1148210ff73SJedrzej Jagielski 
ixgbe_info_fw_srev(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx,enum ixgbe_devlink_version_type type)1158210ff73SJedrzej Jagielski static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter,
1166eae2aebSJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx,
1176eae2aebSJedrzej Jagielski 			       enum ixgbe_devlink_version_type type)
1188210ff73SJedrzej Jagielski {
1198210ff73SJedrzej Jagielski 	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
1208210ff73SJedrzej Jagielski 
1216eae2aebSJedrzej Jagielski 	if (type == IXGBE_DL_VERSION_STORED &&
1226eae2aebSJedrzej Jagielski 	    ctx->dev_caps.common_cap.nvm_update_pending_nvm)
1236eae2aebSJedrzej Jagielski 		nvm = &ctx->pending_nvm;
1246eae2aebSJedrzej Jagielski 
1258210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
1268210ff73SJedrzej Jagielski }
1278210ff73SJedrzej Jagielski 
ixgbe_info_orom_srev(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx,enum ixgbe_devlink_version_type type)1288210ff73SJedrzej Jagielski static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
1296eae2aebSJedrzej Jagielski 				 struct ixgbe_info_ctx *ctx,
1306eae2aebSJedrzej Jagielski 				 enum ixgbe_devlink_version_type type)
1318210ff73SJedrzej Jagielski {
1328210ff73SJedrzej Jagielski 	struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
1338210ff73SJedrzej Jagielski 
1346eae2aebSJedrzej Jagielski 	if (type == IXGBE_DL_VERSION_STORED &&
1356eae2aebSJedrzej Jagielski 	    ctx->dev_caps.common_cap.nvm_update_pending_orom)
1366eae2aebSJedrzej Jagielski 		orom = &ctx->pending_orom;
1376eae2aebSJedrzej Jagielski 
1388210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
1398210ff73SJedrzej Jagielski }
1408210ff73SJedrzej Jagielski 
ixgbe_info_nvm_ver(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx,enum ixgbe_devlink_version_type type)1418210ff73SJedrzej Jagielski static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
1426eae2aebSJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx,
1436eae2aebSJedrzej Jagielski 			       enum ixgbe_devlink_version_type type)
1448210ff73SJedrzej Jagielski {
1458210ff73SJedrzej Jagielski 	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
1468210ff73SJedrzej Jagielski 
1476eae2aebSJedrzej Jagielski 	if (type == IXGBE_DL_VERSION_STORED &&
1486eae2aebSJedrzej Jagielski 	    ctx->dev_caps.common_cap.nvm_update_pending_nvm)
1496eae2aebSJedrzej Jagielski 		nvm = &ctx->pending_nvm;
1506eae2aebSJedrzej Jagielski 
1518210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
1528210ff73SJedrzej Jagielski }
1538210ff73SJedrzej Jagielski 
ixgbe_info_netlist_ver(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx,enum ixgbe_devlink_version_type type)1548210ff73SJedrzej Jagielski static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
1556eae2aebSJedrzej Jagielski 				   struct ixgbe_info_ctx *ctx,
1566eae2aebSJedrzej Jagielski 				   enum ixgbe_devlink_version_type type)
1578210ff73SJedrzej Jagielski {
1588210ff73SJedrzej Jagielski 	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
1598210ff73SJedrzej Jagielski 
1606eae2aebSJedrzej Jagielski 	if (type == IXGBE_DL_VERSION_STORED &&
1616eae2aebSJedrzej Jagielski 	    ctx->dev_caps.common_cap.nvm_update_pending_netlist)
1626eae2aebSJedrzej Jagielski 		netlist = &ctx->pending_netlist;
1636eae2aebSJedrzej Jagielski 
1648210ff73SJedrzej Jagielski 	/* The netlist version fields are BCD formatted */
1658210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
1668210ff73SJedrzej Jagielski 		 netlist->major, netlist->minor,
1678210ff73SJedrzej Jagielski 		 netlist->type >> 16, netlist->type & 0xFFFF,
1688210ff73SJedrzej Jagielski 		 netlist->rev, netlist->cust_ver);
1698210ff73SJedrzej Jagielski }
1708210ff73SJedrzej Jagielski 
ixgbe_info_netlist_build(struct ixgbe_adapter * adapter,struct ixgbe_info_ctx * ctx,enum ixgbe_devlink_version_type type)1718210ff73SJedrzej Jagielski static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
1726eae2aebSJedrzej Jagielski 				     struct ixgbe_info_ctx *ctx,
1736eae2aebSJedrzej Jagielski 				     enum ixgbe_devlink_version_type type)
1748210ff73SJedrzej Jagielski {
1758210ff73SJedrzej Jagielski 	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
1768210ff73SJedrzej Jagielski 
1776eae2aebSJedrzej Jagielski 	if (type == IXGBE_DL_VERSION_STORED &&
1786eae2aebSJedrzej Jagielski 	    ctx->dev_caps.common_cap.nvm_update_pending_netlist)
1796eae2aebSJedrzej Jagielski 		netlist = &ctx->pending_netlist;
1806eae2aebSJedrzej Jagielski 
1818210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
1828210ff73SJedrzej Jagielski }
1838210ff73SJedrzej Jagielski 
ixgbe_set_ctx_dev_caps(struct ixgbe_hw * hw,struct ixgbe_info_ctx * ctx,struct netlink_ext_ack * extack)1846eae2aebSJedrzej Jagielski static int ixgbe_set_ctx_dev_caps(struct ixgbe_hw *hw,
1856eae2aebSJedrzej Jagielski 				  struct ixgbe_info_ctx *ctx,
1866eae2aebSJedrzej Jagielski 				  struct netlink_ext_ack *extack)
1876eae2aebSJedrzej Jagielski {
1886eae2aebSJedrzej Jagielski 	bool *pending_orom, *pending_nvm, *pending_netlist;
1896eae2aebSJedrzej Jagielski 	int err;
1906eae2aebSJedrzej Jagielski 
1916eae2aebSJedrzej Jagielski 	err = ixgbe_discover_dev_caps(hw, &ctx->dev_caps);
1926eae2aebSJedrzej Jagielski 	if (err) {
1936eae2aebSJedrzej Jagielski 		NL_SET_ERR_MSG_MOD(extack,
1946eae2aebSJedrzej Jagielski 				   "Unable to discover device capabilities");
1956eae2aebSJedrzej Jagielski 		return err;
1966eae2aebSJedrzej Jagielski 	}
1976eae2aebSJedrzej Jagielski 
1986eae2aebSJedrzej Jagielski 	pending_orom = &ctx->dev_caps.common_cap.nvm_update_pending_orom;
1996eae2aebSJedrzej Jagielski 	pending_nvm = &ctx->dev_caps.common_cap.nvm_update_pending_nvm;
2006eae2aebSJedrzej Jagielski 	pending_netlist = &ctx->dev_caps.common_cap.nvm_update_pending_netlist;
2016eae2aebSJedrzej Jagielski 
2026eae2aebSJedrzej Jagielski 	if (*pending_orom) {
2036eae2aebSJedrzej Jagielski 		err = ixgbe_get_inactive_orom_ver(hw, &ctx->pending_orom);
2046eae2aebSJedrzej Jagielski 		if (err)
2056eae2aebSJedrzej Jagielski 			*pending_orom = false;
2066eae2aebSJedrzej Jagielski 	}
2076eae2aebSJedrzej Jagielski 
2086eae2aebSJedrzej Jagielski 	if (*pending_nvm) {
2096eae2aebSJedrzej Jagielski 		err = ixgbe_get_inactive_nvm_ver(hw, &ctx->pending_nvm);
2106eae2aebSJedrzej Jagielski 		if (err)
2116eae2aebSJedrzej Jagielski 			*pending_nvm = false;
2126eae2aebSJedrzej Jagielski 	}
2136eae2aebSJedrzej Jagielski 
2146eae2aebSJedrzej Jagielski 	if (*pending_netlist) {
2156eae2aebSJedrzej Jagielski 		err = ixgbe_get_inactive_netlist_ver(hw, &ctx->pending_netlist);
2166eae2aebSJedrzej Jagielski 		if (err)
2176eae2aebSJedrzej Jagielski 			*pending_netlist = false;
2186eae2aebSJedrzej Jagielski 	}
2196eae2aebSJedrzej Jagielski 
2206eae2aebSJedrzej Jagielski 	return 0;
2216eae2aebSJedrzej Jagielski }
2226eae2aebSJedrzej Jagielski 
ixgbe_devlink_info_get_e610(struct ixgbe_adapter * adapter,struct devlink_info_req * req,struct ixgbe_info_ctx * ctx)2238210ff73SJedrzej Jagielski static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter,
2248210ff73SJedrzej Jagielski 				       struct devlink_info_req *req,
2258210ff73SJedrzej Jagielski 				       struct ixgbe_info_ctx *ctx)
2268210ff73SJedrzej Jagielski {
2278210ff73SJedrzej Jagielski 	int err;
2288210ff73SJedrzej Jagielski 
2298210ff73SJedrzej Jagielski 	ixgbe_info_fw_api(adapter, ctx);
2308210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req,
2318210ff73SJedrzej Jagielski 					       DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
2328210ff73SJedrzej Jagielski 					       ctx->buf);
2338210ff73SJedrzej Jagielski 	if (err)
2348210ff73SJedrzej Jagielski 		return err;
2358210ff73SJedrzej Jagielski 
2368210ff73SJedrzej Jagielski 	ixgbe_info_fw_build(adapter, ctx);
2378210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf);
2388210ff73SJedrzej Jagielski 	if (err)
2398210ff73SJedrzej Jagielski 		return err;
2408210ff73SJedrzej Jagielski 
2416eae2aebSJedrzej Jagielski 	ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
2428210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf);
2438210ff73SJedrzej Jagielski 	if (err)
2448210ff73SJedrzej Jagielski 		return err;
2458210ff73SJedrzej Jagielski 
2466eae2aebSJedrzej Jagielski 	ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
2478210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf);
2488210ff73SJedrzej Jagielski 	if (err)
2498210ff73SJedrzej Jagielski 		return err;
2508210ff73SJedrzej Jagielski 
2516eae2aebSJedrzej Jagielski 	ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
2528210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf);
2538210ff73SJedrzej Jagielski 	if (err)
2548210ff73SJedrzej Jagielski 		return err;
2558210ff73SJedrzej Jagielski 
2566eae2aebSJedrzej Jagielski 	ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
2578210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf);
2588210ff73SJedrzej Jagielski 	if (err)
2598210ff73SJedrzej Jagielski 		return err;
2608210ff73SJedrzej Jagielski 
2616eae2aebSJedrzej Jagielski 	ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
2628210ff73SJedrzej Jagielski 	return devlink_info_version_running_put(req, "fw.netlist.build",
2638210ff73SJedrzej Jagielski 						ctx->buf);
2648210ff73SJedrzej Jagielski }
2658210ff73SJedrzej Jagielski 
2666eae2aebSJedrzej Jagielski static int
ixgbe_devlink_pending_info_get_e610(struct ixgbe_adapter * adapter,struct devlink_info_req * req,struct ixgbe_info_ctx * ctx)2676eae2aebSJedrzej Jagielski ixgbe_devlink_pending_info_get_e610(struct ixgbe_adapter *adapter,
2686eae2aebSJedrzej Jagielski 				    struct devlink_info_req *req,
2696eae2aebSJedrzej Jagielski 				    struct ixgbe_info_ctx *ctx)
2706eae2aebSJedrzej Jagielski {
2716eae2aebSJedrzej Jagielski 	int err;
2726eae2aebSJedrzej Jagielski 
2736eae2aebSJedrzej Jagielski 	ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
2746eae2aebSJedrzej Jagielski 	err = devlink_info_version_stored_put(req,
2756eae2aebSJedrzej Jagielski 					      DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
2766eae2aebSJedrzej Jagielski 					      ctx->buf);
2776eae2aebSJedrzej Jagielski 	if (err)
2786eae2aebSJedrzej Jagielski 		return err;
2796eae2aebSJedrzej Jagielski 
2806eae2aebSJedrzej Jagielski 	ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_STORED);
2816eae2aebSJedrzej Jagielski 	err = devlink_info_version_stored_put(req,
2826eae2aebSJedrzej Jagielski 					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
2836eae2aebSJedrzej Jagielski 					      ctx->buf);
2846eae2aebSJedrzej Jagielski 	if (err)
2856eae2aebSJedrzej Jagielski 		return err;
2866eae2aebSJedrzej Jagielski 
2876eae2aebSJedrzej Jagielski 	ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
2886eae2aebSJedrzej Jagielski 	err = devlink_info_version_stored_put(req, "fw.mgmt.srev", ctx->buf);
2896eae2aebSJedrzej Jagielski 	if (err)
2906eae2aebSJedrzej Jagielski 		return err;
2916eae2aebSJedrzej Jagielski 
2926eae2aebSJedrzej Jagielski 	ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_STORED);
2936eae2aebSJedrzej Jagielski 	err = devlink_info_version_stored_put(req, "fw.undi.srev", ctx->buf);
2946eae2aebSJedrzej Jagielski 	if (err)
2956eae2aebSJedrzej Jagielski 		return err;
2966eae2aebSJedrzej Jagielski 
2976eae2aebSJedrzej Jagielski 	ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
2986eae2aebSJedrzej Jagielski 	err = devlink_info_version_stored_put(req, "fw.psid.api", ctx->buf);
2996eae2aebSJedrzej Jagielski 	if (err)
3006eae2aebSJedrzej Jagielski 		return err;
3016eae2aebSJedrzej Jagielski 
3026eae2aebSJedrzej Jagielski 	ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_STORED);
3036eae2aebSJedrzej Jagielski 	err = devlink_info_version_stored_put(req, "fw.netlist", ctx->buf);
3046eae2aebSJedrzej Jagielski 	if (err)
3056eae2aebSJedrzej Jagielski 		return err;
3066eae2aebSJedrzej Jagielski 
3076eae2aebSJedrzej Jagielski 	ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_STORED);
3086eae2aebSJedrzej Jagielski 	return devlink_info_version_stored_put(req, "fw.netlist.build",
3096eae2aebSJedrzej Jagielski 					       ctx->buf);
3106eae2aebSJedrzej Jagielski }
3116eae2aebSJedrzej Jagielski 
ixgbe_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)312f6b588afSJedrzej Jagielski static int ixgbe_devlink_info_get(struct devlink *devlink,
313f6b588afSJedrzej Jagielski 				  struct devlink_info_req *req,
314f6b588afSJedrzej Jagielski 				  struct netlink_ext_ack *extack)
315f6b588afSJedrzej Jagielski {
316f6b588afSJedrzej Jagielski 	struct ixgbe_adapter *adapter = devlink_priv(devlink);
317f6b588afSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
318f6b588afSJedrzej Jagielski 	struct ixgbe_info_ctx *ctx;
319f6b588afSJedrzej Jagielski 	int err;
320f6b588afSJedrzej Jagielski 
321f6b588afSJedrzej Jagielski 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
322f6b588afSJedrzej Jagielski 	if (!ctx)
323f6b588afSJedrzej Jagielski 		return -ENOMEM;
324f6b588afSJedrzej Jagielski 
325c9e563caSJedrzej Jagielski 	if (hw->mac.type == ixgbe_mac_e610)
326c9e563caSJedrzej Jagielski 		ixgbe_refresh_fw_version(adapter);
327c9e563caSJedrzej Jagielski 
328f6b588afSJedrzej Jagielski 	ixgbe_info_get_dsn(adapter, ctx);
329f6b588afSJedrzej Jagielski 	err = devlink_info_serial_number_put(req, ctx->buf);
330f6b588afSJedrzej Jagielski 	if (err)
331f6b588afSJedrzej Jagielski 		goto free_ctx;
332f6b588afSJedrzej Jagielski 
3334654ec61SJedrzej Jagielski 	err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf));
334f6b588afSJedrzej Jagielski 	if (err)
335f6b588afSJedrzej Jagielski 		goto free_ctx;
336f6b588afSJedrzej Jagielski 
337f6b588afSJedrzej Jagielski 	err = devlink_info_version_fixed_put(req,
338f6b588afSJedrzej Jagielski 					     DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
339f6b588afSJedrzej Jagielski 					     ctx->buf);
340f6b588afSJedrzej Jagielski 	if (err)
341f6b588afSJedrzej Jagielski 		goto free_ctx;
342f6b588afSJedrzej Jagielski 
3436eae2aebSJedrzej Jagielski 	ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
344f6b588afSJedrzej Jagielski 	err = devlink_info_version_running_put(req,
345f6b588afSJedrzej Jagielski 					       DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
346f6b588afSJedrzej Jagielski 					       ctx->buf);
347f6b588afSJedrzej Jagielski 	if (err)
348f6b588afSJedrzej Jagielski 		goto free_ctx;
349f6b588afSJedrzej Jagielski 
3506eae2aebSJedrzej Jagielski 	ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_RUNNING);
351f6b588afSJedrzej Jagielski 	err = devlink_info_version_running_put(req,
352f6b588afSJedrzej Jagielski 					       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
353f6b588afSJedrzej Jagielski 					       ctx->buf);
3548210ff73SJedrzej Jagielski 	if (err || hw->mac.type != ixgbe_mac_e610)
3558210ff73SJedrzej Jagielski 		goto free_ctx;
3568210ff73SJedrzej Jagielski 
3576eae2aebSJedrzej Jagielski 	err = ixgbe_set_ctx_dev_caps(hw, ctx, extack);
3586eae2aebSJedrzej Jagielski 	if (err)
3596eae2aebSJedrzej Jagielski 		goto free_ctx;
3606eae2aebSJedrzej Jagielski 
3618210ff73SJedrzej Jagielski 	err = ixgbe_devlink_info_get_e610(adapter, req, ctx);
3626eae2aebSJedrzej Jagielski 	if (err)
3636eae2aebSJedrzej Jagielski 		goto free_ctx;
3646eae2aebSJedrzej Jagielski 
3656eae2aebSJedrzej Jagielski 	err = ixgbe_devlink_pending_info_get_e610(adapter, req, ctx);
366f6b588afSJedrzej Jagielski free_ctx:
367f6b588afSJedrzej Jagielski 	kfree(ctx);
368f6b588afSJedrzej Jagielski 	return err;
369f6b588afSJedrzej Jagielski }
370f6b588afSJedrzej Jagielski 
371c9e563caSJedrzej Jagielski /**
372c9e563caSJedrzej Jagielski  * ixgbe_devlink_reload_empr_start - Start EMP reset to activate new firmware
373c9e563caSJedrzej Jagielski  * @devlink: pointer to the devlink instance to reload
374c9e563caSJedrzej Jagielski  * @netns_change: if true, the network namespace is changing
375c9e563caSJedrzej Jagielski  * @action: the action to perform. Must be DEVLINK_RELOAD_ACTION_FW_ACTIVATE
376c9e563caSJedrzej Jagielski  * @limit: limits on what reload should do, such as not resetting
377c9e563caSJedrzej Jagielski  * @extack: netlink extended ACK structure
378c9e563caSJedrzej Jagielski  *
379c9e563caSJedrzej Jagielski  * Allow user to activate new Embedded Management Processor firmware by
380c9e563caSJedrzej Jagielski  * issuing device specific EMP reset. Called in response to
381c9e563caSJedrzej Jagielski  * a DEVLINK_CMD_RELOAD with the DEVLINK_RELOAD_ACTION_FW_ACTIVATE.
382c9e563caSJedrzej Jagielski  *
383c9e563caSJedrzej Jagielski  * Note that teardown and rebuild of the driver state happens automatically as
384c9e563caSJedrzej Jagielski  * part of an interrupt and watchdog task. This is because all physical
385c9e563caSJedrzej Jagielski  * functions on the device must be able to reset when an EMP reset occurs from
386c9e563caSJedrzej Jagielski  * any source.
387c9e563caSJedrzej Jagielski  *
388c9e563caSJedrzej Jagielski  * Return: the exit code of the operation.
389c9e563caSJedrzej Jagielski  */
ixgbe_devlink_reload_empr_start(struct devlink * devlink,bool netns_change,enum devlink_reload_action action,enum devlink_reload_limit limit,struct netlink_ext_ack * extack)390c9e563caSJedrzej Jagielski static int ixgbe_devlink_reload_empr_start(struct devlink *devlink,
391c9e563caSJedrzej Jagielski 					   bool netns_change,
392c9e563caSJedrzej Jagielski 					   enum devlink_reload_action action,
393c9e563caSJedrzej Jagielski 					   enum devlink_reload_limit limit,
394c9e563caSJedrzej Jagielski 					   struct netlink_ext_ack *extack)
395c9e563caSJedrzej Jagielski {
396c9e563caSJedrzej Jagielski 	struct ixgbe_adapter *adapter = devlink_priv(devlink);
397c9e563caSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
398c9e563caSJedrzej Jagielski 	u8 pending;
399c9e563caSJedrzej Jagielski 	int err;
400c9e563caSJedrzej Jagielski 
401c9e563caSJedrzej Jagielski 	if (hw->mac.type != ixgbe_mac_e610)
402c9e563caSJedrzej Jagielski 		return -EOPNOTSUPP;
403c9e563caSJedrzej Jagielski 
404c9e563caSJedrzej Jagielski 	err = ixgbe_get_pending_updates(adapter, &pending, extack);
405c9e563caSJedrzej Jagielski 	if (err)
406c9e563caSJedrzej Jagielski 		return err;
407c9e563caSJedrzej Jagielski 
408c9e563caSJedrzej Jagielski 	/* Pending is a bitmask of which flash banks have a pending update,
409c9e563caSJedrzej Jagielski 	 * including the main NVM bank, the Option ROM bank, and the netlist
410c9e563caSJedrzej Jagielski 	 * bank. If any of these bits are set, then there is a pending update
411c9e563caSJedrzej Jagielski 	 * waiting to be activated.
412c9e563caSJedrzej Jagielski 	 */
413c9e563caSJedrzej Jagielski 	if (!pending) {
414c9e563caSJedrzej Jagielski 		NL_SET_ERR_MSG_MOD(extack, "No pending firmware update");
415c9e563caSJedrzej Jagielski 		return -ECANCELED;
416c9e563caSJedrzej Jagielski 	}
417c9e563caSJedrzej Jagielski 
418c9e563caSJedrzej Jagielski 	if (adapter->fw_emp_reset_disabled) {
419c9e563caSJedrzej Jagielski 		NL_SET_ERR_MSG_MOD(extack,
420c9e563caSJedrzej Jagielski 				   "EMP reset is not available. To activate firmware, a reboot or power cycle is needed");
421c9e563caSJedrzej Jagielski 		return -ECANCELED;
422c9e563caSJedrzej Jagielski 	}
423c9e563caSJedrzej Jagielski 
424c9e563caSJedrzej Jagielski 	err = ixgbe_aci_nvm_update_empr(hw);
425c9e563caSJedrzej Jagielski 	if (err)
426c9e563caSJedrzej Jagielski 		NL_SET_ERR_MSG_MOD(extack,
427c9e563caSJedrzej Jagielski 				   "Failed to trigger EMP device reset to reload firmware");
428c9e563caSJedrzej Jagielski 
429c9e563caSJedrzej Jagielski 	return err;
430c9e563caSJedrzej Jagielski }
431c9e563caSJedrzej Jagielski 
432c9e563caSJedrzej Jagielski /*Wait for 10 sec with 0.5 sec tic. EMPR takes no less than half of a sec */
433c9e563caSJedrzej Jagielski #define IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC	20
434c9e563caSJedrzej Jagielski 
435c9e563caSJedrzej Jagielski /**
436c9e563caSJedrzej Jagielski  * ixgbe_devlink_reload_empr_finish - finishes EMP reset
437c9e563caSJedrzej Jagielski  * @devlink: pointer to the devlink instance
438c9e563caSJedrzej Jagielski  * @action: the action to perform.
439c9e563caSJedrzej Jagielski  * @limit: limits on what reload should do
440c9e563caSJedrzej Jagielski  * @actions_performed: actions performed
441c9e563caSJedrzej Jagielski  * @extack: netlink extended ACK structure
442c9e563caSJedrzej Jagielski  *
443c9e563caSJedrzej Jagielski  * Wait for new NVM to be loaded during EMP reset.
444c9e563caSJedrzej Jagielski  *
445c9e563caSJedrzej Jagielski  * Return: -ETIME when timer is exceeded, 0 on success.
446c9e563caSJedrzej Jagielski  */
ixgbe_devlink_reload_empr_finish(struct devlink * devlink,enum devlink_reload_action action,enum devlink_reload_limit limit,u32 * actions_performed,struct netlink_ext_ack * extack)447c9e563caSJedrzej Jagielski static int ixgbe_devlink_reload_empr_finish(struct devlink *devlink,
448c9e563caSJedrzej Jagielski 					    enum devlink_reload_action action,
449c9e563caSJedrzej Jagielski 					    enum devlink_reload_limit limit,
450c9e563caSJedrzej Jagielski 					    u32 *actions_performed,
451c9e563caSJedrzej Jagielski 					    struct netlink_ext_ack *extack)
452c9e563caSJedrzej Jagielski {
453c9e563caSJedrzej Jagielski 	struct ixgbe_adapter *adapter = devlink_priv(devlink);
454c9e563caSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
455c9e563caSJedrzej Jagielski 	int i = 0;
456c9e563caSJedrzej Jagielski 	u32 fwsm;
457c9e563caSJedrzej Jagielski 
458c9e563caSJedrzej Jagielski 	do {
459c9e563caSJedrzej Jagielski 		/* Just right away after triggering EMP reset the FWSM register
460c9e563caSJedrzej Jagielski 		 * may be not cleared yet, so begin the loop with the delay
461c9e563caSJedrzej Jagielski 		 * in order to not check the not updated register.
462c9e563caSJedrzej Jagielski 		 */
463c9e563caSJedrzej Jagielski 		mdelay(500);
464c9e563caSJedrzej Jagielski 
465c9e563caSJedrzej Jagielski 		fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw));
466c9e563caSJedrzej Jagielski 
467c9e563caSJedrzej Jagielski 		if (i++ >= IXGBE_DEVLINK_RELOAD_TIMEOUT_SEC)
468c9e563caSJedrzej Jagielski 			return -ETIME;
469c9e563caSJedrzej Jagielski 
470c9e563caSJedrzej Jagielski 	} while (!(fwsm & IXGBE_FWSM_FW_VAL_BIT));
471c9e563caSJedrzej Jagielski 
472c9e563caSJedrzej Jagielski 	*actions_performed = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE);
473c9e563caSJedrzej Jagielski 
4744811b0c2SAndrii Staikov 	adapter->flags2 &= ~(IXGBE_FLAG2_API_MISMATCH |
4754811b0c2SAndrii Staikov 			     IXGBE_FLAG2_FW_ROLLBACK);
476b5aae90bSJedrzej Jagielski 
477c9e563caSJedrzej Jagielski 	return 0;
478c9e563caSJedrzej Jagielski }
479c9e563caSJedrzej Jagielski 
480a0285236SJedrzej Jagielski static const struct devlink_ops ixgbe_devlink_ops = {
481f6b588afSJedrzej Jagielski 	.info_get = ixgbe_devlink_info_get,
482a0f45672SJedrzej Jagielski 	.supported_flash_update_params =
483a0f45672SJedrzej Jagielski 		DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
484a0f45672SJedrzej Jagielski 	.flash_update = ixgbe_flash_pldm_image,
485c9e563caSJedrzej Jagielski 	.reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
486c9e563caSJedrzej Jagielski 	.reload_down = ixgbe_devlink_reload_empr_start,
487c9e563caSJedrzej Jagielski 	.reload_up = ixgbe_devlink_reload_empr_finish,
488a0285236SJedrzej Jagielski };
489a0285236SJedrzej Jagielski 
490a0285236SJedrzej Jagielski /**
491a0285236SJedrzej Jagielski  * ixgbe_allocate_devlink - Allocate devlink instance
492a0285236SJedrzej Jagielski  * @dev: device to allocate devlink for
493a0285236SJedrzej Jagielski  *
494a0285236SJedrzej Jagielski  * Allocate a devlink instance for this physical function.
495a0285236SJedrzej Jagielski  *
496a0285236SJedrzej Jagielski  * Return: pointer to the device adapter structure on success,
497a0285236SJedrzej Jagielski  * ERR_PTR(-ENOMEM) when allocation failed.
498a0285236SJedrzej Jagielski  */
ixgbe_allocate_devlink(struct device * dev)499a0285236SJedrzej Jagielski struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev)
500a0285236SJedrzej Jagielski {
501a0285236SJedrzej Jagielski 	struct ixgbe_adapter *adapter;
502a0285236SJedrzej Jagielski 	struct devlink *devlink;
503a0285236SJedrzej Jagielski 
504a0285236SJedrzej Jagielski 	devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev);
505a0285236SJedrzej Jagielski 	if (!devlink)
506a0285236SJedrzej Jagielski 		return ERR_PTR(-ENOMEM);
507a0285236SJedrzej Jagielski 
508a0285236SJedrzej Jagielski 	adapter = devlink_priv(devlink);
509a0285236SJedrzej Jagielski 	adapter->devlink = devlink;
510a0285236SJedrzej Jagielski 
511a0285236SJedrzej Jagielski 	return adapter;
512a0285236SJedrzej Jagielski }
513a0285236SJedrzej Jagielski 
514a0285236SJedrzej Jagielski /**
515a0285236SJedrzej Jagielski  * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN
516a0285236SJedrzej Jagielski  * @adapter: pointer to the device adapter structure
517a0285236SJedrzej Jagielski  * @ppid: struct with switch id information
518a0285236SJedrzej Jagielski  */
ixgbe_devlink_set_switch_id(struct ixgbe_adapter * adapter,struct netdev_phys_item_id * ppid)519a0285236SJedrzej Jagielski static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter,
520a0285236SJedrzej Jagielski 					struct netdev_phys_item_id *ppid)
521a0285236SJedrzej Jagielski {
522a0285236SJedrzej Jagielski 	u64 id = pci_get_dsn(adapter->pdev);
523a0285236SJedrzej Jagielski 
524a0285236SJedrzej Jagielski 	ppid->id_len = sizeof(id);
525a0285236SJedrzej Jagielski 	put_unaligned_be64(id, &ppid->id);
526a0285236SJedrzej Jagielski }
527a0285236SJedrzej Jagielski 
528a0285236SJedrzej Jagielski /**
529a0285236SJedrzej Jagielski  * ixgbe_devlink_register_port - Register devlink port
530a0285236SJedrzej Jagielski  * @adapter: pointer to the device adapter structure
531a0285236SJedrzej Jagielski  *
532a0285236SJedrzej Jagielski  * Create and register a devlink_port for this physical function.
533a0285236SJedrzej Jagielski  *
534a0285236SJedrzej Jagielski  * Return: 0 on success, error code on failure.
535a0285236SJedrzej Jagielski  */
ixgbe_devlink_register_port(struct ixgbe_adapter * adapter)536a0285236SJedrzej Jagielski int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter)
537a0285236SJedrzej Jagielski {
538a0285236SJedrzej Jagielski 	struct devlink_port *devlink_port = &adapter->devlink_port;
539a0285236SJedrzej Jagielski 	struct devlink *devlink = adapter->devlink;
540a0285236SJedrzej Jagielski 	struct device *dev = &adapter->pdev->dev;
541a0285236SJedrzej Jagielski 	struct devlink_port_attrs attrs = {};
542a0285236SJedrzej Jagielski 	int err;
543a0285236SJedrzej Jagielski 
544a0285236SJedrzej Jagielski 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
545a0285236SJedrzej Jagielski 	attrs.phys.port_number = adapter->hw.bus.func;
546*e67a0bc3SJedrzej Jagielski 	attrs.no_phys_port_name = 1;
547a0285236SJedrzej Jagielski 	ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id);
548a0285236SJedrzej Jagielski 
549a0285236SJedrzej Jagielski 	devlink_port_attrs_set(devlink_port, &attrs);
550a0285236SJedrzej Jagielski 
551a0285236SJedrzej Jagielski 	err = devl_port_register(devlink, devlink_port, 0);
552a0285236SJedrzej Jagielski 	if (err) {
553a0285236SJedrzej Jagielski 		dev_err(dev,
554a0285236SJedrzej Jagielski 			"devlink port registration failed, err %d\n", err);
555a0285236SJedrzej Jagielski 	}
556a0285236SJedrzej Jagielski 
557a0285236SJedrzej Jagielski 	return err;
558a0285236SJedrzej Jagielski }
559