xref: /linux/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c (revision 8210ff738077ed3581e022e5cc8721aa041d42cb)
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 
22*8210ff73SJedrzej 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 
30*8210ff73SJedrzej Jagielski 	if (hw->mac.type == ixgbe_mac_e610) {
31*8210ff73SJedrzej Jagielski 		struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
32*8210ff73SJedrzej Jagielski 
33*8210ff73SJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
34*8210ff73SJedrzej Jagielski 			 orom->major, orom->build, orom->patch);
35*8210ff73SJedrzej Jagielski 		return;
36*8210ff73SJedrzej Jagielski 	}
37*8210ff73SJedrzej 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 
59*8210ff73SJedrzej Jagielski 	if (hw->mac.type == ixgbe_mac_e610) {
60*8210ff73SJedrzej Jagielski 		snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x",
61*8210ff73SJedrzej Jagielski 			 hw->flash.nvm.eetrack);
62*8210ff73SJedrzej Jagielski 		return;
63*8210ff73SJedrzej Jagielski 	}
64*8210ff73SJedrzej 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 
77*8210ff73SJedrzej Jagielski static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter,
78*8210ff73SJedrzej Jagielski 			      struct ixgbe_info_ctx *ctx)
79*8210ff73SJedrzej Jagielski {
80*8210ff73SJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
81*8210ff73SJedrzej Jagielski 
82*8210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
83*8210ff73SJedrzej Jagielski 		 hw->api_maj_ver, hw->api_min_ver, hw->api_patch);
84*8210ff73SJedrzej Jagielski }
85*8210ff73SJedrzej Jagielski 
86*8210ff73SJedrzej Jagielski static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter,
87*8210ff73SJedrzej Jagielski 				struct ixgbe_info_ctx *ctx)
88*8210ff73SJedrzej Jagielski {
89*8210ff73SJedrzej Jagielski 	struct ixgbe_hw *hw = &adapter->hw;
90*8210ff73SJedrzej Jagielski 
91*8210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
92*8210ff73SJedrzej Jagielski }
93*8210ff73SJedrzej Jagielski 
94*8210ff73SJedrzej Jagielski static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter,
95*8210ff73SJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx)
96*8210ff73SJedrzej Jagielski {
97*8210ff73SJedrzej Jagielski 	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
98*8210ff73SJedrzej Jagielski 
99*8210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev);
100*8210ff73SJedrzej Jagielski }
101*8210ff73SJedrzej Jagielski 
102*8210ff73SJedrzej Jagielski static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter,
103*8210ff73SJedrzej Jagielski 				 struct ixgbe_info_ctx *ctx)
104*8210ff73SJedrzej Jagielski {
105*8210ff73SJedrzej Jagielski 	struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
106*8210ff73SJedrzej Jagielski 
107*8210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev);
108*8210ff73SJedrzej Jagielski }
109*8210ff73SJedrzej Jagielski 
110*8210ff73SJedrzej Jagielski static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
111*8210ff73SJedrzej Jagielski 			       struct ixgbe_info_ctx *ctx)
112*8210ff73SJedrzej Jagielski {
113*8210ff73SJedrzej Jagielski 	struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
114*8210ff73SJedrzej Jagielski 
115*8210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
116*8210ff73SJedrzej Jagielski }
117*8210ff73SJedrzej Jagielski 
118*8210ff73SJedrzej Jagielski static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter,
119*8210ff73SJedrzej Jagielski 				   struct ixgbe_info_ctx *ctx)
120*8210ff73SJedrzej Jagielski {
121*8210ff73SJedrzej Jagielski 	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
122*8210ff73SJedrzej Jagielski 
123*8210ff73SJedrzej Jagielski 	/* The netlist version fields are BCD formatted */
124*8210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
125*8210ff73SJedrzej Jagielski 		 netlist->major, netlist->minor,
126*8210ff73SJedrzej Jagielski 		 netlist->type >> 16, netlist->type & 0xFFFF,
127*8210ff73SJedrzej Jagielski 		 netlist->rev, netlist->cust_ver);
128*8210ff73SJedrzej Jagielski }
129*8210ff73SJedrzej Jagielski 
130*8210ff73SJedrzej Jagielski static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter,
131*8210ff73SJedrzej Jagielski 				     struct ixgbe_info_ctx *ctx)
132*8210ff73SJedrzej Jagielski {
133*8210ff73SJedrzej Jagielski 	struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist;
134*8210ff73SJedrzej Jagielski 
135*8210ff73SJedrzej Jagielski 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
136*8210ff73SJedrzej Jagielski }
137*8210ff73SJedrzej Jagielski 
138*8210ff73SJedrzej Jagielski static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter,
139*8210ff73SJedrzej Jagielski 				       struct devlink_info_req *req,
140*8210ff73SJedrzej Jagielski 				       struct ixgbe_info_ctx *ctx)
141*8210ff73SJedrzej Jagielski {
142*8210ff73SJedrzej Jagielski 	int err;
143*8210ff73SJedrzej Jagielski 
144*8210ff73SJedrzej Jagielski 	ixgbe_info_fw_api(adapter, ctx);
145*8210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req,
146*8210ff73SJedrzej Jagielski 					       DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
147*8210ff73SJedrzej Jagielski 					       ctx->buf);
148*8210ff73SJedrzej Jagielski 	if (err)
149*8210ff73SJedrzej Jagielski 		return err;
150*8210ff73SJedrzej Jagielski 
151*8210ff73SJedrzej Jagielski 	ixgbe_info_fw_build(adapter, ctx);
152*8210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf);
153*8210ff73SJedrzej Jagielski 	if (err)
154*8210ff73SJedrzej Jagielski 		return err;
155*8210ff73SJedrzej Jagielski 
156*8210ff73SJedrzej Jagielski 	ixgbe_info_fw_srev(adapter, ctx);
157*8210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf);
158*8210ff73SJedrzej Jagielski 	if (err)
159*8210ff73SJedrzej Jagielski 		return err;
160*8210ff73SJedrzej Jagielski 
161*8210ff73SJedrzej Jagielski 	ixgbe_info_orom_srev(adapter, ctx);
162*8210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf);
163*8210ff73SJedrzej Jagielski 	if (err)
164*8210ff73SJedrzej Jagielski 		return err;
165*8210ff73SJedrzej Jagielski 
166*8210ff73SJedrzej Jagielski 	ixgbe_info_nvm_ver(adapter, ctx);
167*8210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf);
168*8210ff73SJedrzej Jagielski 	if (err)
169*8210ff73SJedrzej Jagielski 		return err;
170*8210ff73SJedrzej Jagielski 
171*8210ff73SJedrzej Jagielski 	ixgbe_info_netlist_ver(adapter, ctx);
172*8210ff73SJedrzej Jagielski 	err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf);
173*8210ff73SJedrzej Jagielski 	if (err)
174*8210ff73SJedrzej Jagielski 		return err;
175*8210ff73SJedrzej Jagielski 
176*8210ff73SJedrzej Jagielski 	ixgbe_info_netlist_build(adapter, ctx);
177*8210ff73SJedrzej Jagielski 	return devlink_info_version_running_put(req, "fw.netlist.build",
178*8210ff73SJedrzej Jagielski 						ctx->buf);
179*8210ff73SJedrzej Jagielski }
180*8210ff73SJedrzej 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 
199f6b588afSJedrzej Jagielski 	err = ixgbe_read_pba_string_generic(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 
209*8210ff73SJedrzej 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);
220*8210ff73SJedrzej Jagielski 	if (err || hw->mac.type != ixgbe_mac_e610)
221*8210ff73SJedrzej Jagielski 		goto free_ctx;
222*8210ff73SJedrzej Jagielski 
223*8210ff73SJedrzej 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