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.
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.
11 #include "net_driver.h"
12 #include "ef100_nic.h"
13 #include "efx_devlink.h"
14 #include <linux/rtc.h>
16 #include "mcdi_functions.h"
17 #include "mcdi_pcol.h"
18 #ifdef CONFIG_SFC_SRIOV
20 #include "ef100_rep.h"
27 #ifdef CONFIG_SFC_SRIOV
29 static int efx_devlink_port_addr_get(struct devlink_port
*port
, u8
*hw_addr
,
31 struct netlink_ext_ack
*extack
)
33 struct efx_devlink
*devlink
= devlink_priv(port
->devlink
);
34 struct mae_mport_desc
*mport_desc
;
39 mport_desc
= container_of(port
, struct mae_mport_desc
, dl_port
);
41 if (!ef100_mport_on_local_intf(devlink
->efx
, mport_desc
)) {
43 NL_SET_ERR_MSG_FMT(extack
,
44 "Port not on local interface (mport: %u)",
45 mport_desc
->mport_id
);
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
);
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
);
60 rc
= efx_ef100_lookup_client_id(devlink
->efx
, pciefn
, &client_id
);
62 NL_SET_ERR_MSG_FMT(extack
,
63 "No internal client_ID for port (mport: %u)",
64 mport_desc
->mport_id
);
68 rc
= ef100_get_mac_address(devlink
->efx
, hw_addr
, client_id
, true);
70 NL_SET_ERR_MSG_FMT(extack
,
71 "No available MAC for port (mport: %u)",
72 mport_desc
->mport_id
);
74 *hw_addr_len
= ETH_ALEN
;
78 static 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
)
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
;
89 mport_desc
= container_of(port
, struct mae_mport_desc
, dl_port
);
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
);
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
);
103 rc
= efx_ef100_lookup_client_id(devlink
->efx
, pciefn
, &client_id
);
105 NL_SET_ERR_MSG_FMT(extack
,
106 "No internal client_ID for port (mport: %u)",
107 mport_desc
->mport_id
);
111 MCDI_SET_DWORD(inbuf
, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE
,
114 ether_addr_copy(MCDI_PTR(inbuf
, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS
),
117 rc
= efx_mcdi_rpc(devlink
->efx
, MC_CMD_SET_CLIENT_MAC_ADDRESSES
, inbuf
,
118 sizeof(inbuf
), NULL
, 0, NULL
);
120 NL_SET_ERR_MSG_FMT(extack
,
121 "sfc MC_CMD_SET_CLIENT_MAC_ADDRESSES mcdi error (mport: %u)",
122 mport_desc
->mport_id
);
127 static 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
,
132 static void efx_devlink_del_port(struct devlink_port
*dl_port
)
136 devl_port_unregister(dl_port
);
139 static int efx_devlink_add_port(struct efx_nic
*efx
,
140 struct mae_mport_desc
*mport
)
142 bool external
= false;
144 if (!ef100_mport_on_local_intf(efx
, mport
))
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
,
154 devlink_port_attrs_pci_pf_set(&mport
->dl_port
, 0, mport
->pf_idx
,
158 /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
162 mport
->dl_port
.index
= mport
->mport_id
;
164 return devl_port_register_with_ops(efx
->devlink
, &mport
->dl_port
,
166 &sfc_devlink_port_ops
);
171 static 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
)
176 char buf
[EFX_MAX_VERSION_INFO_LEN
];
180 rc
= efx_mcdi_nvram_metadata(efx
, partition_type
, NULL
, version
, NULL
,
183 /* If the partition does not exist, that is not an error. */
188 netif_err(efx
, drv
, efx
->net_dev
, "mcdi nvram %s: failed (rc=%d)\n",
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
);
200 static int efx_devlink_info_stored_versions(struct efx_nic
*efx
,
201 struct devlink_info_req
*req
)
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.
210 err
= efx_devlink_info_nvram_partition(efx
, req
,
211 NVRAM_PARTITION_TYPE_BUNDLE
,
212 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID
);
214 err
|= efx_devlink_info_nvram_partition(efx
, req
,
215 NVRAM_PARTITION_TYPE_MC_FIRMWARE
,
216 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT
);
218 err
|= efx_devlink_info_nvram_partition(efx
, req
,
219 NVRAM_PARTITION_TYPE_SUC_FIRMWARE
,
220 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC
);
222 err
|= efx_devlink_info_nvram_partition(efx
, req
,
223 NVRAM_PARTITION_TYPE_EXPANSION_ROM
,
224 EFX_DEVLINK_INFO_VERSION_FW_EXPROM
);
226 err
|= efx_devlink_info_nvram_partition(efx
, req
,
227 NVRAM_PARTITION_TYPE_EXPANSION_UEFI
,
228 EFX_DEVLINK_INFO_VERSION_FW_UEFI
);
232 #define EFX_VER_FLAG(_f) \
233 (MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
235 static void efx_devlink_info_running_v2(struct efx_nic
*efx
,
236 struct devlink_info_req
*req
,
237 unsigned int flags
, efx_dword_t
*outbuf
)
239 char buf
[EFX_MAX_VERSION_INFO_LEN
];
241 const __le32
*dwords
;
245 struct rtc_time build_date
;
246 unsigned int build_id
;
248 __maybe_unused u64 tstamp
;
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
,
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",
261 GET_VERSION_V2_OUT_BOARD_REVISION
));
262 devlink_info_version_fixed_put(req
,
263 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV
,
267 ver
.str
= MCDI_PTR(outbuf
, GET_VERSION_V2_OUT_BOARD_SERIAL
);
269 devlink_info_board_serial_number_put(req
, ver
.str
);
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]));
280 ver
.str
= MCDI_PTR(outbuf
, GET_VERSION_V2_OUT_FPGA_EXTRA
);
282 snprintf(&buf
[offset
], EFX_MAX_VERSION_INFO_LEN
- offset
,
285 devlink_info_version_running_put(req
,
286 EFX_DEVLINK_INFO_VERSION_FPGA_REV
,
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]));
299 #ifdef CONFIG_RTC_LIB
300 tstamp
= MCDI_QWORD(outbuf
,
301 GET_VERSION_V2_OUT_CMCFW_BUILD_DATE
);
303 rtc_time64_to_tm(tstamp
, &build_date
);
304 snprintf(&buf
[offset
], EFX_MAX_VERSION_INFO_LEN
- offset
,
305 " (%ptRd)", &build_date
);
309 devlink_info_version_running_put(req
,
310 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC
,
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
));
324 devlink_info_version_running_put(req
,
325 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT
,
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
);
336 memset(&build_date
, 0, sizeof(build_date
));
338 build_id
= MCDI_DWORD(outbuf
, GET_VERSION_V2_OUT_SUCFW_CHIP_ID
);
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
);
346 devlink_info_version_running_put(req
,
347 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC
,
352 static void efx_devlink_info_running_v3(struct efx_nic
*efx
,
353 struct devlink_info_req
*req
,
354 unsigned int flags
, efx_dword_t
*outbuf
)
356 char buf
[EFX_MAX_VERSION_INFO_LEN
];
358 const __le32
*dwords
;
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
);
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]));
371 devlink_info_version_running_put(req
,
372 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW
,
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
);
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]));
384 devlink_info_version_running_put(req
,
385 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW
,
390 static void efx_devlink_info_running_v4(struct efx_nic
*efx
,
391 struct devlink_info_req
*req
,
392 unsigned int flags
, efx_dword_t
*outbuf
)
394 char buf
[EFX_MAX_VERSION_INFO_LEN
];
396 const __le32
*dwords
;
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
);
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]));
410 devlink_info_version_running_put(req
,
411 EFX_DEVLINK_INFO_VERSION_SOC_BOOT
,
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
);
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]));
424 devlink_info_version_running_put(req
,
425 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT
,
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
);
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]));
438 devlink_info_version_running_put(req
,
439 EFX_DEVLINK_INFO_VERSION_SOC_MAIN
,
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
);
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]));
452 devlink_info_version_running_put(req
,
453 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY
,
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
);
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]));
467 devlink_info_version_running_put(req
,
468 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC
,
473 static void efx_devlink_info_running_v5(struct efx_nic
*efx
,
474 struct devlink_info_req
*req
,
475 unsigned int flags
, efx_dword_t
*outbuf
)
477 char buf
[EFX_MAX_VERSION_INFO_LEN
];
479 const __le32
*dwords
;
484 if (flags
& BIT(EFX_VER_FLAG(BOARD_VERSION
))) {
485 ver
.dwords
= (__le32
*)MCDI_PTR(outbuf
,
486 GET_VERSION_V5_OUT_BOARD_VERSION
);
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]));
493 devlink_info_version_running_put(req
,
494 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV
,
498 if (flags
& BIT(EFX_VER_FLAG(BUNDLE_VERSION
))) {
499 ver
.dwords
= (__le32
*)MCDI_PTR(outbuf
,
500 GET_VERSION_V5_OUT_BUNDLE_VERSION
);
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]));
507 devlink_info_version_running_put(req
,
508 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID
,
513 static int efx_devlink_info_running_versions(struct efx_nic
*efx
,
514 struct devlink_info_req
*req
)
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
];
520 const __le32
*dwords
;
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");
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]));
546 devlink_info_version_running_put(req
,
547 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT
,
552 /* Handle V2 additions */
553 flags
= MCDI_DWORD(outbuf
, GET_VERSION_V2_OUT_FLAGS
);
554 efx_devlink_info_running_v2(efx
, req
, flags
, outbuf
);
556 if (outlength
< MC_CMD_GET_VERSION_V3_OUT_LEN
)
559 /* Handle V3 additions */
560 efx_devlink_info_running_v3(efx
, req
, flags
, outbuf
);
562 if (outlength
< MC_CMD_GET_VERSION_V4_OUT_LEN
)
565 /* Handle V4 additions */
566 efx_devlink_info_running_v4(efx
, req
, flags
, outbuf
);
568 if (outlength
< MC_CMD_GET_VERSION_V5_OUT_LEN
)
571 /* Handle V5 additions */
572 efx_devlink_info_running_v5(efx
, req
, flags
, outbuf
);
577 #define EFX_MAX_SERIALNUM_LEN (ETH_ALEN * 2 + 1)
579 static int efx_devlink_info_board_cfg(struct efx_nic
*efx
,
580 struct devlink_info_req
*req
)
582 char sn
[EFX_MAX_SERIALNUM_LEN
];
583 u8 mac_address
[ETH_ALEN
];
586 rc
= efx_mcdi_get_board_cfg(efx
, (u8
*)mac_address
, NULL
, NULL
);
588 snprintf(sn
, EFX_MAX_SERIALNUM_LEN
, "%pm", mac_address
);
589 devlink_info_serial_number_put(req
, sn
);
594 static int efx_devlink_info_get(struct devlink
*devlink
,
595 struct devlink_info_req
*req
,
596 struct netlink_ext_ack
*extack
)
598 struct efx_devlink
*devlink_private
= devlink_priv(devlink
);
599 struct efx_nic
*efx
= devlink_private
->efx
;
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.
606 err
= efx_devlink_info_board_cfg(efx
, req
);
608 err
|= efx_devlink_info_stored_versions(efx
, req
);
610 err
|= efx_devlink_info_running_versions(efx
, req
);
613 NL_SET_ERR_MSG_MOD(extack
, "Errors when getting device info. Check system messages");
618 static const struct devlink_ops sfc_devlink_ops
= {
619 .info_get
= efx_devlink_info_get
,
622 #ifdef CONFIG_SFC_SRIOV
623 static struct devlink_port
*ef100_set_devlink_port(struct efx_nic
*efx
, u32 idx
)
625 struct mae_mport_desc
*mport
;
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");
637 pci_warn_once(efx
->pci_dev
, "No mport ID found for VF %u.\n",
642 mport
= efx_mae_get_mport(efx
, id
);
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");
648 pci_warn_once(efx
->pci_dev
, "No mport found for VF %u.\n",
653 rc
= efx_devlink_add_port(efx
, mport
);
655 if (idx
== MAE_MPORT_DESC_VF_IDX_NULL
)
656 pci_warn(efx
->pci_dev
,
657 "devlink port creation for PF failed.\n");
659 pci_warn(efx
->pci_dev
,
660 "devlink_port creation for VF %u failed.\n",
665 return &mport
->dl_port
;
668 void ef100_rep_set_devlink_port(struct efx_rep
*efv
)
670 efv
->dl_port
= ef100_set_devlink_port(efv
->parent
, efv
->idx
);
673 void ef100_pf_set_devlink_port(struct efx_nic
*efx
)
675 efx
->dl_port
= ef100_set_devlink_port(efx
, MAE_MPORT_DESC_VF_IDX_NULL
);
678 void ef100_rep_unset_devlink_port(struct efx_rep
*efv
)
680 efx_devlink_del_port(efv
->dl_port
);
683 void ef100_pf_unset_devlink_port(struct efx_nic
*efx
)
685 efx_devlink_del_port(efx
->dl_port
);
689 void efx_fini_devlink_lock(struct efx_nic
*efx
)
692 devl_lock(efx
->devlink
);
695 void efx_fini_devlink_and_unlock(struct efx_nic
*efx
)
698 devl_unregister(efx
->devlink
);
699 devl_unlock(efx
->devlink
);
700 devlink_free(efx
->devlink
);
705 int efx_probe_devlink_and_lock(struct efx_nic
*efx
)
707 struct efx_devlink
*devlink_private
;
709 if (efx
->type
->is_vf
)
712 efx
->devlink
= devlink_alloc(&sfc_devlink_ops
,
713 sizeof(struct efx_devlink
),
718 devl_lock(efx
->devlink
);
719 devlink_private
= devlink_priv(efx
->devlink
);
720 devlink_private
->efx
= efx
;
722 devl_register(efx
->devlink
);
727 void efx_probe_devlink_unlock(struct efx_nic
*efx
)
732 devl_unlock(efx
->devlink
);