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