xref: /linux/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c (revision f6b588af3d575acba469f15ef519ae4befb0ad63)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2025, Intel Corporation. */
3 
4 #include "ixgbe.h"
5 #include "devlink.h"
6 
7 struct ixgbe_info_ctx {
8 	char buf[128];
9 };
10 
11 static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter,
12 			       struct ixgbe_info_ctx *ctx)
13 {
14 	u8 dsn[8];
15 
16 	/* Copy the DSN into an array in Big Endian format */
17 	put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn);
18 
19 	snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
20 }
21 
22 static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
23 			       struct ixgbe_info_ctx *ctx)
24 {
25 	struct ixgbe_hw *hw = &adapter->hw;
26 	struct ixgbe_nvm_version nvm_ver;
27 
28 	ctx->buf[0] = '\0';
29 
30 	ixgbe_get_oem_prod_version(hw, &nvm_ver);
31 	if (nvm_ver.oem_valid) {
32 		snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x",
33 			 nvm_ver.oem_major, nvm_ver.oem_minor,
34 			 nvm_ver.oem_release);
35 
36 		return;
37 	}
38 
39 	ixgbe_get_orom_version(hw, &nvm_ver);
40 	if (nvm_ver.or_valid)
41 		snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d",
42 			 nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch);
43 }
44 
45 static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
46 			       struct ixgbe_info_ctx *ctx)
47 {
48 	struct ixgbe_hw *hw = &adapter->hw;
49 	struct ixgbe_nvm_version nvm_ver;
50 
51 	ixgbe_get_oem_prod_version(hw, &nvm_ver);
52 
53 	/* No ETRACK version for OEM */
54 	if (nvm_ver.oem_valid) {
55 		ctx->buf[0] = '\0';
56 		return;
57 	}
58 
59 	ixgbe_get_etk_id(hw, &nvm_ver);
60 	snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
61 }
62 
63 static int ixgbe_devlink_info_get(struct devlink *devlink,
64 				  struct devlink_info_req *req,
65 				  struct netlink_ext_ack *extack)
66 {
67 	struct ixgbe_adapter *adapter = devlink_priv(devlink);
68 	struct ixgbe_hw *hw = &adapter->hw;
69 	struct ixgbe_info_ctx *ctx;
70 	int err;
71 
72 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
73 	if (!ctx)
74 		return -ENOMEM;
75 
76 	ixgbe_info_get_dsn(adapter, ctx);
77 	err = devlink_info_serial_number_put(req, ctx->buf);
78 	if (err)
79 		goto free_ctx;
80 
81 	err = ixgbe_read_pba_string_generic(hw, ctx->buf, sizeof(ctx->buf));
82 	if (err)
83 		goto free_ctx;
84 
85 	err = devlink_info_version_fixed_put(req,
86 					     DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
87 					     ctx->buf);
88 	if (err)
89 		goto free_ctx;
90 
91 	ixgbe_info_nvm_ver(adapter, ctx);
92 	err = devlink_info_version_running_put(req,
93 					       DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
94 					       ctx->buf);
95 	if (err)
96 		goto free_ctx;
97 
98 	ixgbe_info_eetrack(adapter, ctx);
99 	err = devlink_info_version_running_put(req,
100 					       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
101 					       ctx->buf);
102 free_ctx:
103 	kfree(ctx);
104 	return err;
105 }
106 
107 static const struct devlink_ops ixgbe_devlink_ops = {
108 	.info_get = ixgbe_devlink_info_get,
109 };
110 
111 /**
112  * ixgbe_allocate_devlink - Allocate devlink instance
113  * @dev: device to allocate devlink for
114  *
115  * Allocate a devlink instance for this physical function.
116  *
117  * Return: pointer to the device adapter structure on success,
118  * ERR_PTR(-ENOMEM) when allocation failed.
119  */
120 struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev)
121 {
122 	struct ixgbe_adapter *adapter;
123 	struct devlink *devlink;
124 
125 	devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev);
126 	if (!devlink)
127 		return ERR_PTR(-ENOMEM);
128 
129 	adapter = devlink_priv(devlink);
130 	adapter->devlink = devlink;
131 
132 	return adapter;
133 }
134 
135 /**
136  * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN
137  * @adapter: pointer to the device adapter structure
138  * @ppid: struct with switch id information
139  */
140 static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter,
141 					struct netdev_phys_item_id *ppid)
142 {
143 	u64 id = pci_get_dsn(adapter->pdev);
144 
145 	ppid->id_len = sizeof(id);
146 	put_unaligned_be64(id, &ppid->id);
147 }
148 
149 /**
150  * ixgbe_devlink_register_port - Register devlink port
151  * @adapter: pointer to the device adapter structure
152  *
153  * Create and register a devlink_port for this physical function.
154  *
155  * Return: 0 on success, error code on failure.
156  */
157 int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter)
158 {
159 	struct devlink_port *devlink_port = &adapter->devlink_port;
160 	struct devlink *devlink = adapter->devlink;
161 	struct device *dev = &adapter->pdev->dev;
162 	struct devlink_port_attrs attrs = {};
163 	int err;
164 
165 	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
166 	attrs.phys.port_number = adapter->hw.bus.func;
167 	ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id);
168 
169 	devlink_port_attrs_set(devlink_port, &attrs);
170 
171 	err = devl_port_register(devlink, devlink_port, 0);
172 	if (err) {
173 		dev_err(dev,
174 			"devlink port registration failed, err %d\n", err);
175 	}
176 
177 	return err;
178 }
179