xref: /linux/drivers/net/ethernet/sfc/efx_devlink.c (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3  * Driver for AMD network controllers and boards
4  * Copyright (C) 2023, Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published
8  * by the Free Software Foundation, incorporated herein by reference.
9  */
10 
11 #include "net_driver.h"
12 #include "ef100_nic.h"
13 #include "efx_devlink.h"
14 #include <linux/rtc.h>
15 #include "mcdi.h"
16 #include "mcdi_functions.h"
17 #include "mcdi_pcol.h"
18 #ifdef CONFIG_SFC_SRIOV
19 #include "mae.h"
20 #include "ef100_rep.h"
21 #endif
22 #include "efx_reflash.h"
23 
24 struct efx_devlink {
25 	struct efx_nic *efx;
26 };
27 
28 #ifdef CONFIG_SFC_SRIOV
29 
efx_devlink_port_addr_get(struct devlink_port * port,u8 * hw_addr,int * hw_addr_len,struct netlink_ext_ack * extack)30 static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
31 				     int *hw_addr_len,
32 				     struct netlink_ext_ack *extack)
33 {
34 	struct efx_devlink *devlink = devlink_priv(port->devlink);
35 	struct mae_mport_desc *mport_desc;
36 	efx_qword_t pciefn;
37 	u32 client_id;
38 	int rc = 0;
39 
40 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
41 
42 	if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
43 		rc = -EINVAL;
44 		NL_SET_ERR_MSG_FMT(extack,
45 				   "Port not on local interface (mport: %u)",
46 				   mport_desc->mport_id);
47 		goto out;
48 	}
49 
50 	if (ef100_mport_is_vf(mport_desc))
51 		EFX_POPULATE_QWORD_3(pciefn,
52 				     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
53 				     PCIE_FUNCTION_VF, mport_desc->vf_idx,
54 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
55 	else
56 		EFX_POPULATE_QWORD_3(pciefn,
57 				     PCIE_FUNCTION_PF, mport_desc->pf_idx,
58 				     PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
59 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
60 
61 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
62 	if (rc) {
63 		NL_SET_ERR_MSG_FMT(extack,
64 				   "No internal client_ID for port (mport: %u)",
65 				   mport_desc->mport_id);
66 		goto out;
67 	}
68 
69 	rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
70 	if (rc != 0)
71 		NL_SET_ERR_MSG_FMT(extack,
72 				   "No available MAC for port (mport: %u)",
73 				   mport_desc->mport_id);
74 out:
75 	*hw_addr_len = ETH_ALEN;
76 	return rc;
77 }
78 
efx_devlink_port_addr_set(struct devlink_port * port,const u8 * hw_addr,int hw_addr_len,struct netlink_ext_ack * extack)79 static int efx_devlink_port_addr_set(struct devlink_port *port,
80 				     const u8 *hw_addr, int hw_addr_len,
81 				     struct netlink_ext_ack *extack)
82 {
83 	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1));
84 	struct efx_devlink *devlink = devlink_priv(port->devlink);
85 	struct mae_mport_desc *mport_desc;
86 	efx_qword_t pciefn;
87 	u32 client_id;
88 	int rc;
89 
90 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
91 
92 	if (!ef100_mport_is_vf(mport_desc)) {
93 		NL_SET_ERR_MSG_FMT(extack,
94 				   "port mac change not allowed (mport: %u)",
95 				   mport_desc->mport_id);
96 		return -EPERM;
97 	}
98 
99 	EFX_POPULATE_QWORD_3(pciefn,
100 			     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
101 			     PCIE_FUNCTION_VF, mport_desc->vf_idx,
102 			     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
103 
104 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
105 	if (rc) {
106 		NL_SET_ERR_MSG_FMT(extack,
107 				   "No internal client_ID for port (mport: %u)",
108 				   mport_desc->mport_id);
109 		return rc;
110 	}
111 
112 	MCDI_SET_DWORD(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
113 		       client_id);
114 
115 	ether_addr_copy(MCDI_PTR(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
116 			hw_addr);
117 
118 	rc = efx_mcdi_rpc(devlink->efx, MC_CMD_SET_CLIENT_MAC_ADDRESSES, inbuf,
119 			  sizeof(inbuf), NULL, 0, NULL);
120 	if (rc)
121 		NL_SET_ERR_MSG_FMT(extack,
122 				   "sfc MC_CMD_SET_CLIENT_MAC_ADDRESSES mcdi error (mport: %u)",
123 				   mport_desc->mport_id);
124 
125 	return rc;
126 }
127 
128 static const struct devlink_port_ops sfc_devlink_port_ops = {
129 	.port_fn_hw_addr_get = efx_devlink_port_addr_get,
130 	.port_fn_hw_addr_set = efx_devlink_port_addr_set,
131 };
132 
efx_devlink_del_port(struct devlink_port * dl_port)133 static void efx_devlink_del_port(struct devlink_port *dl_port)
134 {
135 	if (!dl_port)
136 		return;
137 	devl_port_unregister(dl_port);
138 }
139 
efx_devlink_add_port(struct efx_nic * efx,struct mae_mport_desc * mport)140 static int efx_devlink_add_port(struct efx_nic *efx,
141 				struct mae_mport_desc *mport)
142 {
143 	bool external = false;
144 
145 	if (!ef100_mport_on_local_intf(efx, mport))
146 		external = true;
147 
148 	switch (mport->mport_type) {
149 	case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
150 		if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
151 			devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
152 						      mport->vf_idx,
153 						      external);
154 		else
155 			devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
156 						      external);
157 		break;
158 	default:
159 		/* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
160 		return 0;
161 	}
162 
163 	mport->dl_port.index = mport->mport_id;
164 
165 	return devl_port_register_with_ops(efx->devlink, &mport->dl_port,
166 					   mport->mport_id,
167 					   &sfc_devlink_port_ops);
168 }
169 
170 #endif
171 
efx_devlink_info_nvram_partition(struct efx_nic * efx,struct devlink_info_req * req,unsigned int partition_type,const char * version_name)172 static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
173 					    struct devlink_info_req *req,
174 					    unsigned int partition_type,
175 					    const char *version_name)
176 {
177 	char buf[EFX_MAX_VERSION_INFO_LEN];
178 	u16 version[4];
179 	int rc;
180 
181 	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
182 				     0);
183 
184 	/* If the partition does not exist, that is not an error. */
185 	if (rc == -ENOENT)
186 		return 0;
187 
188 	if (rc) {
189 		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed (rc=%d)\n",
190 			  version_name, rc);
191 		return rc;
192 	}
193 
194 	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
195 		 version[1], version[2], version[3]);
196 	devlink_info_version_stored_put(req, version_name, buf);
197 
198 	return 0;
199 }
200 
efx_devlink_info_stored_versions(struct efx_nic * efx,struct devlink_info_req * req)201 static int efx_devlink_info_stored_versions(struct efx_nic *efx,
202 					    struct devlink_info_req *req)
203 {
204 	int err;
205 
206 	/* We do not care here about the specific error but just if an error
207 	 * happened. The specific error will be reported inside the call
208 	 * through system messages, and if any error happened in any call
209 	 * below, we report it through extack.
210 	 */
211 	err = efx_devlink_info_nvram_partition(efx, req,
212 					       NVRAM_PARTITION_TYPE_BUNDLE,
213 					       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
214 
215 	err |= efx_devlink_info_nvram_partition(efx, req,
216 						NVRAM_PARTITION_TYPE_MC_FIRMWARE,
217 						DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
218 
219 	err |= efx_devlink_info_nvram_partition(efx, req,
220 						NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
221 						EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
222 
223 	err |= efx_devlink_info_nvram_partition(efx, req,
224 						NVRAM_PARTITION_TYPE_EXPANSION_ROM,
225 						EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
226 
227 	err |= efx_devlink_info_nvram_partition(efx, req,
228 						NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
229 						EFX_DEVLINK_INFO_VERSION_FW_UEFI);
230 	return err;
231 }
232 
233 #define EFX_VER_FLAG(_f)	\
234 	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
235 
efx_devlink_info_running_v2(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)236 static void efx_devlink_info_running_v2(struct efx_nic *efx,
237 					struct devlink_info_req *req,
238 					unsigned int flags, efx_dword_t *outbuf)
239 {
240 	char buf[EFX_MAX_VERSION_INFO_LEN];
241 	union {
242 		const __le32 *dwords;
243 		const __le16 *words;
244 		const char *str;
245 	} ver;
246 	struct rtc_time build_date;
247 	unsigned int build_id;
248 	size_t offset;
249 	__maybe_unused u64 tstamp;
250 
251 	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
252 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
253 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
254 		devlink_info_version_fixed_put(req,
255 					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
256 					       buf);
257 
258 		/* Favour full board version if present (in V5 or later) */
259 		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
260 			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
261 				 MCDI_DWORD(outbuf,
262 					    GET_VERSION_V2_OUT_BOARD_REVISION));
263 			devlink_info_version_fixed_put(req,
264 						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
265 						       buf);
266 		}
267 
268 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
269 		if (ver.str[0])
270 			devlink_info_board_serial_number_put(req, ver.str);
271 	}
272 
273 	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
274 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
275 						GET_VERSION_V2_OUT_FPGA_VERSION);
276 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
277 				  le32_to_cpu(ver.dwords[0]),
278 				  'A' + le32_to_cpu(ver.dwords[1]),
279 				  le32_to_cpu(ver.dwords[2]));
280 
281 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
282 		if (ver.str[0])
283 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
284 				 " (%s)", ver.str);
285 
286 		devlink_info_version_running_put(req,
287 						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
288 						 buf);
289 	}
290 
291 	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
292 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
293 						GET_VERSION_V2_OUT_CMCFW_VERSION);
294 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
295 				  le32_to_cpu(ver.dwords[0]),
296 				  le32_to_cpu(ver.dwords[1]),
297 				  le32_to_cpu(ver.dwords[2]),
298 				  le32_to_cpu(ver.dwords[3]));
299 
300 #ifdef CONFIG_RTC_LIB
301 		tstamp = MCDI_QWORD(outbuf,
302 				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
303 		if (tstamp) {
304 			rtc_time64_to_tm(tstamp, &build_date);
305 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
306 				 " (%ptRd)", &build_date);
307 		}
308 #endif
309 
310 		devlink_info_version_running_put(req,
311 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
312 						 buf);
313 	}
314 
315 	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
316 	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
317 			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
318 			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
319 	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
320 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
321 		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
322 			 " (%x) %s", build_id,
323 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
324 	}
325 	devlink_info_version_running_put(req,
326 					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
327 					 buf);
328 
329 	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
330 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
331 						GET_VERSION_V2_OUT_SUCFW_VERSION);
332 #ifdef CONFIG_RTC_LIB
333 		tstamp = MCDI_QWORD(outbuf,
334 				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
335 		rtc_time64_to_tm(tstamp, &build_date);
336 #else
337 		memset(&build_date, 0, sizeof(build_date));
338 #endif
339 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
340 
341 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
342 			 "%u.%u.%u.%u type %x (%ptRd)",
343 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
344 			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
345 			 build_id, &build_date);
346 
347 		devlink_info_version_running_put(req,
348 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
349 						 buf);
350 	}
351 }
352 
efx_devlink_info_running_v3(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)353 static void efx_devlink_info_running_v3(struct efx_nic *efx,
354 					struct devlink_info_req *req,
355 					unsigned int flags, efx_dword_t *outbuf)
356 {
357 	char buf[EFX_MAX_VERSION_INFO_LEN];
358 	union {
359 		const __le32 *dwords;
360 		const __le16 *words;
361 		const char *str;
362 	} ver;
363 
364 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
365 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
366 						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
367 
368 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
369 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
370 			 le32_to_cpu(ver.dwords[2]));
371 
372 		devlink_info_version_running_put(req,
373 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
374 						 buf);
375 	}
376 
377 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
378 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
379 						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
380 
381 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
382 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
383 			 le32_to_cpu(ver.dwords[2]));
384 
385 		devlink_info_version_running_put(req,
386 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
387 						 buf);
388 	}
389 }
390 
efx_devlink_info_running_v4(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)391 static void efx_devlink_info_running_v4(struct efx_nic *efx,
392 					struct devlink_info_req *req,
393 					unsigned int flags, efx_dword_t *outbuf)
394 {
395 	char buf[EFX_MAX_VERSION_INFO_LEN];
396 	union {
397 		const __le32 *dwords;
398 		const __le16 *words;
399 		const char *str;
400 	} ver;
401 
402 	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
403 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
404 						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
405 
406 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
407 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
408 			 le32_to_cpu(ver.dwords[2]),
409 			 le32_to_cpu(ver.dwords[3]));
410 
411 		devlink_info_version_running_put(req,
412 						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
413 						 buf);
414 	}
415 
416 	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
417 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
418 						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
419 
420 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
421 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
422 			 le32_to_cpu(ver.dwords[2]),
423 			 le32_to_cpu(ver.dwords[3]));
424 
425 		devlink_info_version_running_put(req,
426 						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
427 						 buf);
428 	}
429 
430 	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
431 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
432 					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
433 
434 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
435 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
436 			 le32_to_cpu(ver.dwords[2]),
437 			 le32_to_cpu(ver.dwords[3]));
438 
439 		devlink_info_version_running_put(req,
440 						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
441 						 buf);
442 	}
443 
444 	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
445 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
446 						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
447 
448 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
449 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
450 			 le32_to_cpu(ver.dwords[2]),
451 			 le32_to_cpu(ver.dwords[3]));
452 
453 		devlink_info_version_running_put(req,
454 						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
455 						 buf);
456 	}
457 
458 	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
459 	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
460 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
461 						GET_VERSION_V4_OUT_SUCFW_VERSION);
462 
463 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
464 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
465 			 le32_to_cpu(ver.dwords[2]),
466 			 le32_to_cpu(ver.dwords[3]));
467 
468 		devlink_info_version_running_put(req,
469 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
470 						 buf);
471 	}
472 }
473 
efx_devlink_info_running_v5(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)474 static void efx_devlink_info_running_v5(struct efx_nic *efx,
475 					struct devlink_info_req *req,
476 					unsigned int flags, efx_dword_t *outbuf)
477 {
478 	char buf[EFX_MAX_VERSION_INFO_LEN];
479 	union {
480 		const __le32 *dwords;
481 		const __le16 *words;
482 		const char *str;
483 	} ver;
484 
485 	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
486 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
487 						GET_VERSION_V5_OUT_BOARD_VERSION);
488 
489 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
490 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
491 			 le32_to_cpu(ver.dwords[2]),
492 			 le32_to_cpu(ver.dwords[3]));
493 
494 		devlink_info_version_running_put(req,
495 						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
496 						 buf);
497 	}
498 
499 	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
500 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
501 						GET_VERSION_V5_OUT_BUNDLE_VERSION);
502 
503 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
504 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
505 			 le32_to_cpu(ver.dwords[2]),
506 			 le32_to_cpu(ver.dwords[3]));
507 
508 		devlink_info_version_running_put(req,
509 						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
510 						 buf);
511 	}
512 }
513 
efx_devlink_info_running_versions(struct efx_nic * efx,struct devlink_info_req * req)514 static int efx_devlink_info_running_versions(struct efx_nic *efx,
515 					     struct devlink_info_req *req)
516 {
517 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
518 	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
519 	char buf[EFX_MAX_VERSION_INFO_LEN];
520 	union {
521 		const __le32 *dwords;
522 		const __le16 *words;
523 		const char *str;
524 	} ver;
525 	size_t outlength;
526 	unsigned int flags;
527 	int rc;
528 
529 	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
530 			  outbuf, sizeof(outbuf), &outlength);
531 	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
532 		netif_err(efx, drv, efx->net_dev,
533 			  "mcdi MC_CMD_GET_VERSION failed\n");
534 		return rc;
535 	}
536 
537 	/* Handle previous output */
538 	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
539 		ver.words = (__le16 *)MCDI_PTR(outbuf,
540 					       GET_VERSION_EXT_OUT_VERSION);
541 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
542 			 le16_to_cpu(ver.words[0]),
543 			 le16_to_cpu(ver.words[1]),
544 			 le16_to_cpu(ver.words[2]),
545 			 le16_to_cpu(ver.words[3]));
546 
547 		devlink_info_version_running_put(req,
548 						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
549 						 buf);
550 		return 0;
551 	}
552 
553 	/* Handle V2 additions */
554 	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
555 	efx_devlink_info_running_v2(efx, req, flags, outbuf);
556 
557 	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
558 		return 0;
559 
560 	/* Handle V3 additions */
561 	efx_devlink_info_running_v3(efx, req, flags, outbuf);
562 
563 	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
564 		return 0;
565 
566 	/* Handle V4 additions */
567 	efx_devlink_info_running_v4(efx, req, flags, outbuf);
568 
569 	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
570 		return 0;
571 
572 	/* Handle V5 additions */
573 	efx_devlink_info_running_v5(efx, req, flags, outbuf);
574 
575 	return 0;
576 }
577 
578 #define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
579 
efx_devlink_info_board_cfg(struct efx_nic * efx,struct devlink_info_req * req)580 static int efx_devlink_info_board_cfg(struct efx_nic *efx,
581 				      struct devlink_info_req *req)
582 {
583 	char sn[EFX_MAX_SERIALNUM_LEN];
584 	u8 mac_address[ETH_ALEN];
585 	int rc;
586 
587 	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
588 	if (!rc) {
589 		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
590 		devlink_info_serial_number_put(req, sn);
591 	}
592 	return rc;
593 }
594 
efx_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)595 static int efx_devlink_info_get(struct devlink *devlink,
596 				struct devlink_info_req *req,
597 				struct netlink_ext_ack *extack)
598 {
599 	struct efx_devlink *devlink_private = devlink_priv(devlink);
600 	struct efx_nic *efx = devlink_private->efx;
601 	int err;
602 
603 	/* Several different MCDI commands are used. We report if errors
604 	 * happened through extack. Specific error information via system
605 	 * messages inside the calls.
606 	 */
607 	err = efx_devlink_info_board_cfg(efx, req);
608 
609 	err |= efx_devlink_info_stored_versions(efx, req);
610 
611 	err |= efx_devlink_info_running_versions(efx, req);
612 
613 	if (err)
614 		NL_SET_ERR_MSG_MOD(extack, "Errors when getting device info. Check system messages");
615 
616 	return 0;
617 }
618 
efx_devlink_flash_update(struct devlink * devlink,struct devlink_flash_update_params * params,struct netlink_ext_ack * extack)619 static int efx_devlink_flash_update(struct devlink *devlink,
620 				    struct devlink_flash_update_params *params,
621 				    struct netlink_ext_ack *extack)
622 {
623 	struct efx_devlink *devlink_private = devlink_priv(devlink);
624 	struct efx_nic *efx = devlink_private->efx;
625 
626 	return efx_reflash_flash_firmware(efx, params->fw, extack);
627 }
628 
629 static const struct devlink_ops sfc_devlink_ops = {
630 	.supported_flash_update_params	= 0,
631 	.flash_update			= efx_devlink_flash_update,
632 	.info_get			= efx_devlink_info_get,
633 };
634 
635 #ifdef CONFIG_SFC_SRIOV
ef100_set_devlink_port(struct efx_nic * efx,u32 idx)636 static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
637 {
638 	struct mae_mport_desc *mport;
639 	u32 id;
640 	int rc;
641 
642 	if (!efx->mae)
643 		return NULL;
644 
645 	if (efx_mae_lookup_mport(efx, idx, &id)) {
646 		/* This should not happen. */
647 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
648 			pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
649 		else
650 			pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
651 				      idx);
652 		return NULL;
653 	}
654 
655 	mport = efx_mae_get_mport(efx, id);
656 	if (!mport) {
657 		/* This should not happen. */
658 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
659 			pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
660 		else
661 			pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
662 				      idx);
663 		return NULL;
664 	}
665 
666 	rc = efx_devlink_add_port(efx, mport);
667 	if (rc) {
668 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
669 			pci_warn(efx->pci_dev,
670 				 "devlink port creation for PF failed.\n");
671 		else
672 			pci_warn(efx->pci_dev,
673 				 "devlink_port creation for VF %u failed.\n",
674 				 idx);
675 		return NULL;
676 	}
677 
678 	return &mport->dl_port;
679 }
680 
ef100_rep_set_devlink_port(struct efx_rep * efv)681 void ef100_rep_set_devlink_port(struct efx_rep *efv)
682 {
683 	efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
684 }
685 
ef100_pf_set_devlink_port(struct efx_nic * efx)686 void ef100_pf_set_devlink_port(struct efx_nic *efx)
687 {
688 	efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
689 }
690 
ef100_rep_unset_devlink_port(struct efx_rep * efv)691 void ef100_rep_unset_devlink_port(struct efx_rep *efv)
692 {
693 	efx_devlink_del_port(efv->dl_port);
694 }
695 
ef100_pf_unset_devlink_port(struct efx_nic * efx)696 void ef100_pf_unset_devlink_port(struct efx_nic *efx)
697 {
698 	efx_devlink_del_port(efx->dl_port);
699 }
700 #endif
701 
efx_fini_devlink_lock(struct efx_nic * efx)702 void efx_fini_devlink_lock(struct efx_nic *efx)
703 {
704 	if (efx->devlink)
705 		devl_lock(efx->devlink);
706 }
707 
efx_fini_devlink_and_unlock(struct efx_nic * efx)708 void efx_fini_devlink_and_unlock(struct efx_nic *efx)
709 {
710 	if (efx->devlink) {
711 		devl_unregister(efx->devlink);
712 		devl_unlock(efx->devlink);
713 		devlink_free(efx->devlink);
714 		efx->devlink = NULL;
715 	}
716 }
717 
efx_probe_devlink_and_lock(struct efx_nic * efx)718 int efx_probe_devlink_and_lock(struct efx_nic *efx)
719 {
720 	struct efx_devlink *devlink_private;
721 
722 	if (efx->type->is_vf)
723 		return 0;
724 
725 	efx->devlink = devlink_alloc(&sfc_devlink_ops,
726 				     sizeof(struct efx_devlink),
727 				     &efx->pci_dev->dev);
728 	if (!efx->devlink)
729 		return -ENOMEM;
730 
731 	devl_lock(efx->devlink);
732 	devlink_private = devlink_priv(efx->devlink);
733 	devlink_private->efx = efx;
734 
735 	devl_register(efx->devlink);
736 
737 	return 0;
738 }
739 
efx_probe_devlink_unlock(struct efx_nic * efx)740 void efx_probe_devlink_unlock(struct efx_nic *efx)
741 {
742 	if (!efx->devlink)
743 		return;
744 
745 	devl_unlock(efx->devlink);
746 }
747