xref: /linux/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c (revision 4654ec6194b22af73c797508c72710e2e2bba4ad)
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"
6a0285236SJedrzej Jagielski 
7f6b588afSJedrzej Jagielski struct ixgbe_info_ctx {
8f6b588afSJedrzej Jagielski 	char buf[128];
9f6b588afSJedrzej Jagielski };
10f6b588afSJedrzej Jagielski 
11f6b588afSJedrzej Jagielski static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter,
12f6b588afSJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx)
13f6b588afSJedrzej Jagielski {
14f6b588afSJedrzej Jagielski 	u8 dsn[8];
15f6b588afSJedrzej Jagielski 
16f6b588afSJedrzej Jagielski 	/* Copy the DSN into an array in Big Endian format */
17f6b588afSJedrzej Jagielski 	put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn);
18f6b588afSJedrzej Jagielski 
19f6b588afSJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
20f6b588afSJedrzej Jagielski }
21f6b588afSJedrzej Jagielski 
228210ff73SJedrzej Jagielski static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter,
23f6b588afSJedrzej Jagielski 				struct ixgbe_info_ctx *ctx)
24f6b588afSJedrzej Jagielski {
25f6b588afSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
26f6b588afSJedrzej Jagielski 	struct ixgbe_nvm_version nvm_ver;
27f6b588afSJedrzej Jagielski 
28f6b588afSJedrzej Jagielski 	ctx->buf[0] = '\0';
29f6b588afSJedrzej Jagielski 
308210ff73SJedrzej Jagielski 	if (hw->mac.type == ixgbe_mac_e610) {
318210ff73SJedrzej Jagielski 		struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
328210ff73SJedrzej Jagielski 
338210ff73SJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
348210ff73SJedrzej Jagielski 			 orom->major, orom->build, orom->patch);
358210ff73SJedrzej Jagielski 		return;
368210ff73SJedrzej Jagielski 	}
378210ff73SJedrzej Jagielski 
38f6b588afSJedrzej Jagielski 	ixgbe_get_oem_prod_version(hw, &nvm_ver);
39f6b588afSJedrzej Jagielski 	if (nvm_ver.oem_valid) {
40f6b588afSJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x",
41f6b588afSJedrzej Jagielski 			 nvm_ver.oem_major, nvm_ver.oem_minor,
42f6b588afSJedrzej Jagielski 			 nvm_ver.oem_release);
43f6b588afSJedrzej Jagielski 
44f6b588afSJedrzej Jagielski 		return;
45f6b588afSJedrzej Jagielski 	}
46f6b588afSJedrzej Jagielski 
47f6b588afSJedrzej Jagielski 	ixgbe_get_orom_version(hw, &nvm_ver);
48f6b588afSJedrzej Jagielski 	if (nvm_ver.or_valid)
49f6b588afSJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d",
50f6b588afSJedrzej Jagielski 			 nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch);
51f6b588afSJedrzej Jagielski }
52f6b588afSJedrzej Jagielski 
53f6b588afSJedrzej Jagielski static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
54f6b588afSJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx)
55f6b588afSJedrzej Jagielski {
56f6b588afSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
57f6b588afSJedrzej Jagielski 	struct ixgbe_nvm_version nvm_ver;
58f6b588afSJedrzej Jagielski 
598210ff73SJedrzej Jagielski 	if (hw->mac.type == ixgbe_mac_e610) {
608210ff73SJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x",
618210ff73SJedrzej Jagielski 			 hw->flash.nvm.eetrack);
628210ff73SJedrzej Jagielski 		return;
638210ff73SJedrzej Jagielski 	}
648210ff73SJedrzej Jagielski 
65f6b588afSJedrzej Jagielski 	ixgbe_get_oem_prod_version(hw, &nvm_ver);
66f6b588afSJedrzej Jagielski 
67f6b588afSJedrzej Jagielski 	/* No ETRACK version for OEM */
68f6b588afSJedrzej Jagielski 	if (nvm_ver.oem_valid) {
69f6b588afSJedrzej Jagielski 		ctx->buf[0] = '\0';
70f6b588afSJedrzej Jagielski 		return;
71f6b588afSJedrzej Jagielski 	}
72f6b588afSJedrzej Jagielski 
73f6b588afSJedrzej Jagielski 	ixgbe_get_etk_id(hw, &nvm_ver);
74f6b588afSJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
75f6b588afSJedrzej Jagielski }
76f6b588afSJedrzej Jagielski 
778210ff73SJedrzej Jagielski static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter,
788210ff73SJedrzej Jagielski 			      struct ixgbe_info_ctx *ctx)
798210ff73SJedrzej Jagielski {
808210ff73SJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
818210ff73SJedrzej Jagielski 
828210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
838210ff73SJedrzej Jagielski 		 hw->api_maj_ver, hw->api_min_ver, hw->api_patch);
848210ff73SJedrzej Jagielski }
858210ff73SJedrzej Jagielski 
868210ff73SJedrzej Jagielski static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter,
878210ff73SJedrzej Jagielski 				struct ixgbe_info_ctx *ctx)
888210ff73SJedrzej Jagielski {
898210ff73SJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
908210ff73SJedrzej Jagielski 
918210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
928210ff73SJedrzej Jagielski }
938210ff73SJedrzej Jagielski 
948210ff73SJedrzej Jagielski static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter,
958210ff73SJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx)
968210ff73SJedrzej Jagielski {
978210ff73SJedrzej Jagielski 	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
988210ff73SJedrzej Jagielski 
998210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
1008210ff73SJedrzej Jagielski }
1018210ff73SJedrzej Jagielski 
1028210ff73SJedrzej Jagielski static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
1038210ff73SJedrzej Jagielski 				 struct ixgbe_info_ctx *ctx)
1048210ff73SJedrzej Jagielski {
1058210ff73SJedrzej Jagielski 	struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
1068210ff73SJedrzej Jagielski 
1078210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
1088210ff73SJedrzej Jagielski }
1098210ff73SJedrzej Jagielski 
1108210ff73SJedrzej Jagielski static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
1118210ff73SJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx)
1128210ff73SJedrzej Jagielski {
1138210ff73SJedrzej Jagielski 	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
1148210ff73SJedrzej Jagielski 
1158210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
1168210ff73SJedrzej Jagielski }
1178210ff73SJedrzej Jagielski 
1188210ff73SJedrzej Jagielski static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
1198210ff73SJedrzej Jagielski 				   struct ixgbe_info_ctx *ctx)
1208210ff73SJedrzej Jagielski {
1218210ff73SJedrzej Jagielski 	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
1228210ff73SJedrzej Jagielski 
1238210ff73SJedrzej Jagielski 	/* The netlist version fields are BCD formatted */
1248210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
1258210ff73SJedrzej Jagielski 		 netlist->major, netlist->minor,
1268210ff73SJedrzej Jagielski 		 netlist->type >> 16, netlist->type & 0xFFFF,
1278210ff73SJedrzej Jagielski 		 netlist->rev, netlist->cust_ver);
1288210ff73SJedrzej Jagielski }
1298210ff73SJedrzej Jagielski 
1308210ff73SJedrzej Jagielski static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
1318210ff73SJedrzej Jagielski 				     struct ixgbe_info_ctx *ctx)
1328210ff73SJedrzej Jagielski {
1338210ff73SJedrzej Jagielski 	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
1348210ff73SJedrzej Jagielski 
1358210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
1368210ff73SJedrzej Jagielski }
1378210ff73SJedrzej Jagielski 
1388210ff73SJedrzej Jagielski static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter,
1398210ff73SJedrzej Jagielski 				       struct devlink_info_req *req,
1408210ff73SJedrzej Jagielski 				       struct ixgbe_info_ctx *ctx)
1418210ff73SJedrzej Jagielski {
1428210ff73SJedrzej Jagielski 	int err;
1438210ff73SJedrzej Jagielski 
1448210ff73SJedrzej Jagielski 	ixgbe_info_fw_api(adapter, ctx);
1458210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req,
1468210ff73SJedrzej Jagielski 					       DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
1478210ff73SJedrzej Jagielski 					       ctx->buf);
1488210ff73SJedrzej Jagielski 	if (err)
1498210ff73SJedrzej Jagielski 		return err;
1508210ff73SJedrzej Jagielski 
1518210ff73SJedrzej Jagielski 	ixgbe_info_fw_build(adapter, ctx);
1528210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf);
1538210ff73SJedrzej Jagielski 	if (err)
1548210ff73SJedrzej Jagielski 		return err;
1558210ff73SJedrzej Jagielski 
1568210ff73SJedrzej Jagielski 	ixgbe_info_fw_srev(adapter, ctx);
1578210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf);
1588210ff73SJedrzej Jagielski 	if (err)
1598210ff73SJedrzej Jagielski 		return err;
1608210ff73SJedrzej Jagielski 
1618210ff73SJedrzej Jagielski 	ixgbe_info_orom_srev(adapter, ctx);
1628210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf);
1638210ff73SJedrzej Jagielski 	if (err)
1648210ff73SJedrzej Jagielski 		return err;
1658210ff73SJedrzej Jagielski 
1668210ff73SJedrzej Jagielski 	ixgbe_info_nvm_ver(adapter, ctx);
1678210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf);
1688210ff73SJedrzej Jagielski 	if (err)
1698210ff73SJedrzej Jagielski 		return err;
1708210ff73SJedrzej Jagielski 
1718210ff73SJedrzej Jagielski 	ixgbe_info_netlist_ver(adapter, ctx);
1728210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf);
1738210ff73SJedrzej Jagielski 	if (err)
1748210ff73SJedrzej Jagielski 		return err;
1758210ff73SJedrzej Jagielski 
1768210ff73SJedrzej Jagielski 	ixgbe_info_netlist_build(adapter, ctx);
1778210ff73SJedrzej Jagielski 	return devlink_info_version_running_put(req, "fw.netlist.build",
1788210ff73SJedrzej Jagielski 						ctx->buf);
1798210ff73SJedrzej Jagielski }
1808210ff73SJedrzej Jagielski 
181f6b588afSJedrzej Jagielski static int ixgbe_devlink_info_get(struct devlink *devlink,
182f6b588afSJedrzej Jagielski 				  struct devlink_info_req *req,
183f6b588afSJedrzej Jagielski 				  struct netlink_ext_ack *extack)
184f6b588afSJedrzej Jagielski {
185f6b588afSJedrzej Jagielski 	struct ixgbe_adapter *adapter = devlink_priv(devlink);
186f6b588afSJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
187f6b588afSJedrzej Jagielski 	struct ixgbe_info_ctx *ctx;
188f6b588afSJedrzej Jagielski 	int err;
189f6b588afSJedrzej Jagielski 
190f6b588afSJedrzej Jagielski 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
191f6b588afSJedrzej Jagielski 	if (!ctx)
192f6b588afSJedrzej Jagielski 		return -ENOMEM;
193f6b588afSJedrzej Jagielski 
194f6b588afSJedrzej Jagielski 	ixgbe_info_get_dsn(adapter, ctx);
195f6b588afSJedrzej Jagielski 	err = devlink_info_serial_number_put(req, ctx->buf);
196f6b588afSJedrzej Jagielski 	if (err)
197f6b588afSJedrzej Jagielski 		goto free_ctx;
198f6b588afSJedrzej Jagielski 
199*4654ec61SJedrzej Jagielski 	err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf));
200f6b588afSJedrzej Jagielski 	if (err)
201f6b588afSJedrzej Jagielski 		goto free_ctx;
202f6b588afSJedrzej Jagielski 
203f6b588afSJedrzej Jagielski 	err = devlink_info_version_fixed_put(req,
204f6b588afSJedrzej Jagielski 					     DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
205f6b588afSJedrzej Jagielski 					     ctx->buf);
206f6b588afSJedrzej Jagielski 	if (err)
207f6b588afSJedrzej Jagielski 		goto free_ctx;
208f6b588afSJedrzej Jagielski 
2098210ff73SJedrzej Jagielski 	ixgbe_info_orom_ver(adapter, ctx);
210f6b588afSJedrzej Jagielski 	err = devlink_info_version_running_put(req,
211f6b588afSJedrzej Jagielski 					       DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
212f6b588afSJedrzej Jagielski 					       ctx->buf);
213f6b588afSJedrzej Jagielski 	if (err)
214f6b588afSJedrzej Jagielski 		goto free_ctx;
215f6b588afSJedrzej Jagielski 
216f6b588afSJedrzej Jagielski 	ixgbe_info_eetrack(adapter, ctx);
217f6b588afSJedrzej Jagielski 	err = devlink_info_version_running_put(req,
218f6b588afSJedrzej Jagielski 					       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
219f6b588afSJedrzej Jagielski 					       ctx->buf);
2208210ff73SJedrzej Jagielski 	if (err || hw->mac.type != ixgbe_mac_e610)
2218210ff73SJedrzej Jagielski 		goto free_ctx;
2228210ff73SJedrzej Jagielski 
2238210ff73SJedrzej Jagielski 	err = ixgbe_devlink_info_get_e610(adapter, req, ctx);
224f6b588afSJedrzej Jagielski free_ctx:
225f6b588afSJedrzej Jagielski 	kfree(ctx);
226f6b588afSJedrzej Jagielski 	return err;
227f6b588afSJedrzej Jagielski }
228f6b588afSJedrzej Jagielski 
229a0285236SJedrzej Jagielski static const struct devlink_ops ixgbe_devlink_ops = {
230f6b588afSJedrzej Jagielski 	.info_get = ixgbe_devlink_info_get,
231a0285236SJedrzej Jagielski };
232a0285236SJedrzej Jagielski 
233a0285236SJedrzej Jagielski /**
234a0285236SJedrzej Jagielski  * ixgbe_allocate_devlink - Allocate devlink instance
235a0285236SJedrzej Jagielski  * @dev: device to allocate devlink for
236a0285236SJedrzej Jagielski  *
237a0285236SJedrzej Jagielski  * Allocate a devlink instance for this physical function.
238a0285236SJedrzej Jagielski  *
239a0285236SJedrzej Jagielski  * Return: pointer to the device adapter structure on success,
240a0285236SJedrzej Jagielski  * ERR_PTR(-ENOMEM) when allocation failed.
241a0285236SJedrzej Jagielski  */
242a0285236SJedrzej Jagielski struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev)
243a0285236SJedrzej Jagielski {
244a0285236SJedrzej Jagielski 	struct ixgbe_adapter *adapter;
245a0285236SJedrzej Jagielski 	struct devlink *devlink;
246a0285236SJedrzej Jagielski 
247a0285236SJedrzej Jagielski 	devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev);
248a0285236SJedrzej Jagielski 	if (!devlink)
249a0285236SJedrzej Jagielski 		return ERR_PTR(-ENOMEM);
250a0285236SJedrzej Jagielski 
251a0285236SJedrzej Jagielski 	adapter = devlink_priv(devlink);
252a0285236SJedrzej Jagielski 	adapter->devlink = devlink;
253a0285236SJedrzej Jagielski 
254a0285236SJedrzej Jagielski 	return adapter;
255a0285236SJedrzej Jagielski }
256a0285236SJedrzej Jagielski 
257a0285236SJedrzej Jagielski /**
258a0285236SJedrzej Jagielski  * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN
259a0285236SJedrzej Jagielski  * @adapter: pointer to the device adapter structure
260a0285236SJedrzej Jagielski  * @ppid: struct with switch id information
261a0285236SJedrzej Jagielski  */
262a0285236SJedrzej Jagielski static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter,
263a0285236SJedrzej Jagielski 					struct netdev_phys_item_id *ppid)
264a0285236SJedrzej Jagielski {
265a0285236SJedrzej Jagielski 	u64 id = pci_get_dsn(adapter->pdev);
266a0285236SJedrzej Jagielski 
267a0285236SJedrzej Jagielski 	ppid->id_len = sizeof(id);
268a0285236SJedrzej Jagielski 	put_unaligned_be64(id, &ppid->id);
269a0285236SJedrzej Jagielski }
270a0285236SJedrzej Jagielski 
271a0285236SJedrzej Jagielski /**
272a0285236SJedrzej Jagielski  * ixgbe_devlink_register_port - Register devlink port
273a0285236SJedrzej Jagielski  * @adapter: pointer to the device adapter structure
274a0285236SJedrzej Jagielski  *
275a0285236SJedrzej Jagielski  * Create and register a devlink_port for this physical function.
276a0285236SJedrzej Jagielski  *
277a0285236SJedrzej Jagielski  * Return: 0 on success, error code on failure.
278a0285236SJedrzej Jagielski  */
279a0285236SJedrzej Jagielski int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter)
280a0285236SJedrzej Jagielski {
281a0285236SJedrzej Jagielski 	struct devlink_port *devlink_port = &adapter->devlink_port;
282a0285236SJedrzej Jagielski 	struct devlink *devlink = adapter->devlink;
283a0285236SJedrzej Jagielski 	struct device *dev = &adapter->pdev->dev;
284a0285236SJedrzej Jagielski 	struct devlink_port_attrs attrs = {};
285a0285236SJedrzej Jagielski 	int err;
286a0285236SJedrzej Jagielski 
287a0285236SJedrzej Jagielski 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
288a0285236SJedrzej Jagielski 	attrs.phys.port_number = adapter->hw.bus.func;
289a0285236SJedrzej Jagielski 	ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id);
290a0285236SJedrzej Jagielski 
291a0285236SJedrzej Jagielski 	devlink_port_attrs_set(devlink_port, &attrs);
292a0285236SJedrzej Jagielski 
293a0285236SJedrzej Jagielski 	err = devl_port_register(devlink, devlink_port, 0);
294a0285236SJedrzej Jagielski 	if (err) {
295a0285236SJedrzej Jagielski 		dev_err(dev,
296a0285236SJedrzej Jagielski 			"devlink port registration failed, err %d\n", err);
297a0285236SJedrzej Jagielski 	}
298a0285236SJedrzej Jagielski 
299a0285236SJedrzej Jagielski 	return err;
300a0285236SJedrzej Jagielski }
301