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