netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 net-next 0/8] sfc: devlink support for ef100
@ 2023-02-08 14:25 alejandro.lucero-palau
  2023-02-08 14:25 ` [PATCH v6 net-next 1/8] sfc: add " alejandro.lucero-palau
                   ` (7 more replies)
  0 siblings, 8 replies; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

v6 changes:
 - add file headers at its due time
 - fix sfc.rst warnings
 - add sfc.rst to the index.rst file
 - avoid microblaze build error
 - simplify devlink info errors reported

v5 changes
 - add extack error report for devlink info
 - Rename devlink functions stating locking
 - Check functions return through a variable
 - Remove unnecessary non related changes
 - put SRIOV dependent code inside #ifdefs (is ia64 still alive?)

v4 changes:
 - Add new doc file to MAINTAINERS
 - nvram metadata call independent of MTD config
 - add more useful info with extack

v3 changes:
 - fix compilation warnings/errors reported by checkpatch

v2 changes:
 - splitting up devlink info from basic devlink support
 - using devlink lock/unlock during initialization and removal
 - fix devlink registration order
 - splitting up efx_devlink_info_running_versions
 - Add sfc.rst with specifics about sfc info
 - embedding dl_port in mports
 - using extack for error reports to user space

This patchset adds devlink port support for ef100 allowing setting VFs
mac addresses through the VF representor devlink ports.

Basic devlink infrastructure is first introduced, then support for info
command. Next changes for enumerating MAE ports which will be used for
devlink port creation when netdevs are registered.

Adding support for devlink port_function_hw_addr_get requires changes in
the ef100 driver for getting the mac address based on a client handle.
This allows to obtain VFs mac addresses during netdev initialization as
well what is included in patch 6.

Such client handle is used in patches 7 and 8 for getting and setting
devlink port addresses.

Alejandro Lucero (8):
  sfc: add devlink support for ef100
  sfc: add devlink info support for ef100
  sfc: enumerate mports in ef100
  sfc: add mport lookup based on driver's mport data
  sfc: add devlink port support for ef100
  sfc: obtain device mac address based on firmware handle for ef100
  sfc: add support for devlink port_function_hw_addr_get in ef100
  sfc: add support for devlink port_function_hw_addr_set in ef100

 Documentation/networking/devlink/index.rst |   1 +
 Documentation/networking/devlink/sfc.rst   |  57 ++
 MAINTAINERS                                |   1 +
 drivers/net/ethernet/sfc/Kconfig           |   1 +
 drivers/net/ethernet/sfc/Makefile          |   3 +-
 drivers/net/ethernet/sfc/ef100_netdev.c    |  30 +
 drivers/net/ethernet/sfc/ef100_nic.c       |  93 ++-
 drivers/net/ethernet/sfc/ef100_nic.h       |   7 +
 drivers/net/ethernet/sfc/ef100_rep.c       |  57 +-
 drivers/net/ethernet/sfc/ef100_rep.h       |  10 +
 drivers/net/ethernet/sfc/efx_devlink.c     | 713 +++++++++++++++++++++
 drivers/net/ethernet/sfc/efx_devlink.h     |  48 ++
 drivers/net/ethernet/sfc/mae.c             | 218 ++++++-
 drivers/net/ethernet/sfc/mae.h             |  40 ++
 drivers/net/ethernet/sfc/mcdi.c            |  74 +++
 drivers/net/ethernet/sfc/mcdi.h            |  10 +
 drivers/net/ethernet/sfc/net_driver.h      |   8 +
 17 files changed, 1346 insertions(+), 25 deletions(-)
 create mode 100644 Documentation/networking/devlink/sfc.rst
 create mode 100644 drivers/net/ethernet/sfc/efx_devlink.c
 create mode 100644 drivers/net/ethernet/sfc/efx_devlink.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 1/8] sfc: add devlink support for ef100
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-10  8:28   ` Martin Habets
  2023-02-08 14:25 ` [PATCH v6 net-next 2/8] sfc: add devlink info " alejandro.lucero-palau
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Add devlink infrastructure support. Further patches add devlink
info and devlink port support.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/net/ethernet/sfc/Kconfig        |  1 +
 drivers/net/ethernet/sfc/Makefile       |  3 +-
 drivers/net/ethernet/sfc/ef100_netdev.c | 10 ++++
 drivers/net/ethernet/sfc/efx_devlink.c  | 64 +++++++++++++++++++++++++
 drivers/net/ethernet/sfc/efx_devlink.h  | 22 +++++++++
 drivers/net/ethernet/sfc/net_driver.h   |  2 +
 6 files changed, 101 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/sfc/efx_devlink.c
 create mode 100644 drivers/net/ethernet/sfc/efx_devlink.h

diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 0950e6b0508f..4af36ba8906b 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -22,6 +22,7 @@ config SFC
 	depends on PTP_1588_CLOCK_OPTIONAL
 	select MDIO
 	select CRC32
+	select NET_DEVLINK
 	help
 	  This driver supports 10/40-gigabit Ethernet cards based on
 	  the Solarflare SFC9100-family controllers.
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index 712a48d00069..55b9c73cd8ef 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -6,7 +6,8 @@ sfc-y			+= efx.o efx_common.o efx_channels.o nic.o \
 			   mcdi.o mcdi_port.o mcdi_port_common.o \
 			   mcdi_functions.o mcdi_filters.o mcdi_mon.o \
 			   ef100.o ef100_nic.o ef100_netdev.o \
-			   ef100_ethtool.o ef100_rx.o ef100_tx.o
+			   ef100_ethtool.o ef100_rx.o ef100_tx.o \
+			   efx_devlink.o
 sfc-$(CONFIG_SFC_MTD)	+= mtd.o
 sfc-$(CONFIG_SFC_SRIOV)	+= sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
                            mae.o tc.o tc_bindings.o tc_counters.o
diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index ddcc325ed570..6cf74788b27a 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -24,6 +24,7 @@
 #include "rx_common.h"
 #include "ef100_sriov.h"
 #include "tc_bindings.h"
+#include "efx_devlink.h"
 
 static void ef100_update_name(struct efx_nic *efx)
 {
@@ -332,6 +333,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
 		efx_ef100_pci_sriov_disable(efx, true);
 #endif
 
+	efx_fini_devlink_lock(efx);
 	ef100_unregister_netdev(efx);
 
 #ifdef CONFIG_SFC_SRIOV
@@ -345,6 +347,8 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
 	kfree(efx->phy_data);
 	efx->phy_data = NULL;
 
+	efx_fini_devlink_and_unlock(efx);
+
 	free_netdev(efx->net_dev);
 	efx->net_dev = NULL;
 	efx->state = STATE_PROBED;
@@ -405,6 +409,11 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 	/* Don't fail init if RSS setup doesn't work. */
 	efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);
 
+	/* devlink creation, registration and lock */
+	rc = efx_probe_devlink_and_lock(efx);
+	if (rc)
+		pci_info(efx->pci_dev, "devlink registration failed");
+
 	rc = ef100_register_netdev(efx);
 	if (rc)
 		goto fail;
@@ -424,5 +433,6 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 	}
 
 fail:
+	efx_probe_devlink_unlock(efx);
 	return rc;
 }
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
new file mode 100644
index 000000000000..57a7023d3cb6
--- /dev/null
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/****************************************************************************
+ * Driver for AMD network controllers and boards
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include "efx_devlink.h"
+
+struct efx_devlink {
+	struct efx_nic *efx;
+};
+
+static const struct devlink_ops sfc_devlink_ops = {
+};
+
+void efx_fini_devlink_lock(struct efx_nic *efx)
+{
+	if (efx->devlink)
+		devl_lock(efx->devlink);
+}
+
+void efx_fini_devlink_and_unlock(struct efx_nic *efx)
+{
+	if (efx->devlink) {
+		devl_unregister(efx->devlink);
+		devl_unlock(efx->devlink);
+		devlink_free(efx->devlink);
+		efx->devlink = NULL;
+	}
+}
+
+int efx_probe_devlink_and_lock(struct efx_nic *efx)
+{
+	struct efx_devlink *devlink_private;
+
+	if (efx->type->is_vf)
+		return 0;
+
+	efx->devlink = devlink_alloc(&sfc_devlink_ops,
+				     sizeof(struct efx_devlink),
+				     &efx->pci_dev->dev);
+	if (!efx->devlink)
+		return -ENOMEM;
+
+	devl_lock(efx->devlink);
+	devlink_private = devlink_priv(efx->devlink);
+	devlink_private->efx = efx;
+
+	devl_register(efx->devlink);
+
+	return 0;
+}
+
+void efx_probe_devlink_unlock(struct efx_nic *efx)
+{
+	if (!efx->devlink)
+		return;
+
+	devl_unlock(efx->devlink);
+}
diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
new file mode 100644
index 000000000000..8ff85b035e87
--- /dev/null
+++ b/drivers/net/ethernet/sfc/efx_devlink.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/****************************************************************************
+ * Driver for AMD network controllers and boards
+ * Copyright (C) 2023, Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef _EFX_DEVLINK_H
+#define _EFX_DEVLINK_H
+
+#include "net_driver.h"
+#include <net/devlink.h>
+
+int efx_probe_devlink_and_lock(struct efx_nic *efx);
+void efx_probe_devlink_unlock(struct efx_nic *efx);
+void efx_fini_devlink_lock(struct efx_nic *efx);
+void efx_fini_devlink_and_unlock(struct efx_nic *efx);
+
+#endif	/* _EFX_DEVLINK_H */
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 3b49e216768b..d036641dc043 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -994,6 +994,7 @@ enum efx_xdp_tx_queues_mode {
  *      xdp_rxq_info structures?
  * @netdev_notifier: Netdevice notifier.
  * @tc: state for TC offload (EF100).
+ * @devlink: reference to devlink structure owned by this device
  * @mem_bar: The BAR that is mapped into membase.
  * @reg_base: Offset from the start of the bar to the function control window.
  * @monitor_work: Hardware monitor workitem
@@ -1179,6 +1180,7 @@ struct efx_nic {
 	struct notifier_block netdev_notifier;
 	struct efx_tc_state *tc;
 
+	struct devlink *devlink;
 	unsigned int mem_bar;
 	u32 reg_base;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
  2023-02-08 14:25 ` [PATCH v6 net-next 1/8] sfc: add " alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-08 14:38   ` Jiri Pirko
  2023-02-10  8:40   ` Martin Habets
  2023-02-08 14:25 ` [PATCH v6 net-next 3/8] sfc: enumerate mports in ef100 alejandro.lucero-palau
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Add devlink info support for ef100. The information reported is obtained
through the MCDI interface with the specific meaning defined in new
documentation file.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
---
 Documentation/networking/devlink/index.rst |   1 +
 Documentation/networking/devlink/sfc.rst   |  57 +++
 MAINTAINERS                                |   1 +
 drivers/net/ethernet/sfc/efx_devlink.c     | 460 +++++++++++++++++++++
 drivers/net/ethernet/sfc/efx_devlink.h     |  17 +
 drivers/net/ethernet/sfc/mcdi.c            |  74 ++++
 drivers/net/ethernet/sfc/mcdi.h            |   5 +
 7 files changed, 615 insertions(+)
 create mode 100644 Documentation/networking/devlink/sfc.rst

diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
index fee4d3968309..b49749e2b9a6 100644
--- a/Documentation/networking/devlink/index.rst
+++ b/Documentation/networking/devlink/index.rst
@@ -66,3 +66,4 @@ parameters, info versions, and other features it supports.
    prestera
    iosm
    octeontx2
+   sfc
diff --git a/Documentation/networking/devlink/sfc.rst b/Documentation/networking/devlink/sfc.rst
new file mode 100644
index 000000000000..db64a1bd9733
--- /dev/null
+++ b/Documentation/networking/devlink/sfc.rst
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================
+sfc devlink support
+===================
+
+This document describes the devlink features implemented by the ``sfc``
+device driver for the ef100 device.
+
+Info versions
+=============
+
+The ``sfc`` driver reports the following versions
+
+.. list-table:: devlink info versions implemented
+   :widths: 5 5 90
+
+   * - Name
+     - Type
+     - Description
+   * - ``fw.mgmt.suc``
+     - running
+     - For boards where the management function is split between multiple
+       control units, this is the SUC control unit's firmware version.
+   * - ``fw.mgmt.cmc``
+     - running
+     - For boards where the management function is split between multiple
+       control units, this is the CMC control unit's firmware version.
+   * - ``fpga.rev``
+     - running
+     - FPGA design revision.
+   * - ``fpga.app``
+     - running
+     - Datapath programmable logic version.
+   * - ``fw.app``
+     - running
+     - Datapath software/microcode/firmware version.
+   * - ``coproc.boot``
+     - running
+     - SmartNIC application co-processor (APU) first stage boot loader version.
+   * - ``coproc.uboot``
+     - running
+     - SmartNIC application co-processor (APU) co-operating system loader version.
+   * - ``coproc.main``
+     - running
+     - SmartNIC application co-processor (APU) main operating system version.
+   * - ``coproc.recovery``
+     - running
+     - SmartNIC application co-processor (APU) recovery operating system version.
+   * - ``fw.exprom``
+     - running
+     - Expansion ROM version. For boards where the expansion ROM is split between
+       multiple images (e.g. PXE and UEFI), this is the specifically the PXE boot
+       ROM version.
+   * - ``fw.uefi``
+     - running
+     - UEFI driver version (No UNDI support).
diff --git a/MAINTAINERS b/MAINTAINERS
index 2cf9eb43ed8f..51f7d3448295 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18937,6 +18937,7 @@ M:	Edward Cree <ecree.xilinx@gmail.com>
 M:	Martin Habets <habetsm.xilinx@gmail.com>
 L:	netdev@vger.kernel.org
 S:	Supported
+F:	Documentation/networking/devlink/sfc.rst
 F:	drivers/net/ethernet/sfc/
 
 SFF/SFP/SFP+ MODULE SUPPORT
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index 57a7023d3cb6..c06efeac11e5 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -9,12 +9,472 @@
  */
 
 #include "efx_devlink.h"
+#ifdef CONFIG_SFC_SRIOV
+#include <linux/rtc.h>
+#include "mcdi.h"
+#include "mcdi_functions.h"
+#include "mcdi_pcol.h"
+#endif
 
 struct efx_devlink {
 	struct efx_nic *efx;
 };
 
+#ifdef CONFIG_SFC_SRIOV
+static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
+					    struct devlink_info_req *req,
+					    unsigned int partition_type,
+					    const char *version_name)
+{
+	char buf[EFX_MAX_VERSION_INFO_LEN];
+	u16 version[4];
+	int rc;
+
+	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
+				     0);
+	if (rc) {
+		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
+			  version_name);
+		return rc;
+	}
+
+	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
+		 version[1], version[2], version[3]);
+	devlink_info_version_stored_put(req, version_name, buf);
+
+	return 0;
+}
+
+static int efx_devlink_info_stored_versions(struct efx_nic *efx,
+					    struct devlink_info_req *req)
+{
+	int rc;
+
+	rc = efx_devlink_info_nvram_partition(efx, req,
+					      NVRAM_PARTITION_TYPE_BUNDLE,
+					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
+	if (rc)
+		return rc;
+
+	rc = efx_devlink_info_nvram_partition(efx, req,
+					      NVRAM_PARTITION_TYPE_MC_FIRMWARE,
+					      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
+	if (rc)
+		return rc;
+
+	rc = efx_devlink_info_nvram_partition(efx, req,
+					      NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
+					      EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
+	if (rc)
+		return rc;
+
+	rc = efx_devlink_info_nvram_partition(efx, req,
+					      NVRAM_PARTITION_TYPE_EXPANSION_ROM,
+					      EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
+	if (rc)
+		return rc;
+
+	rc = efx_devlink_info_nvram_partition(efx, req,
+					      NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
+					      EFX_DEVLINK_INFO_VERSION_FW_UEFI);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+#define EFX_VER_FLAG(_f)	\
+	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
+
+static void efx_devlink_info_running_v2(struct efx_nic *efx,
+					struct devlink_info_req *req,
+					unsigned int flags, efx_dword_t *outbuf)
+{
+	char buf[EFX_MAX_VERSION_INFO_LEN];
+	union {
+		const __le32 *dwords;
+		const __le16 *words;
+		const char *str;
+	} ver;
+	struct rtc_time build_date;
+	unsigned int build_id;
+	size_t offset;
+	u64 tstamp;
+
+	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
+			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
+		devlink_info_version_fixed_put(req,
+					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
+					       buf);
+
+		/* Favour full board version if present (in V5 or later) */
+		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
+			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
+				 MCDI_DWORD(outbuf,
+					    GET_VERSION_V2_OUT_BOARD_REVISION));
+			devlink_info_version_fixed_put(req,
+						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
+						       buf);
+		}
+
+		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
+		if (ver.str[0])
+			devlink_info_board_serial_number_put(req, ver.str);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V2_OUT_FPGA_VERSION);
+		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
+				  le32_to_cpu(ver.dwords[0]),
+				  'A' + le32_to_cpu(ver.dwords[1]),
+				  le32_to_cpu(ver.dwords[2]));
+
+		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
+		if (ver.str[0])
+			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
+				 " (%s)", ver.str);
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
+						 buf);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V2_OUT_CMCFW_VERSION);
+		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+				  le32_to_cpu(ver.dwords[0]),
+				  le32_to_cpu(ver.dwords[1]),
+				  le32_to_cpu(ver.dwords[2]),
+				  le32_to_cpu(ver.dwords[3]));
+
+		tstamp = MCDI_QWORD(outbuf,
+				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
+		if (tstamp) {
+			rtc_time64_to_tm(tstamp, &build_date);
+			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
+				 " (%ptRd)", &build_date);
+		}
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
+						 buf);
+	}
+
+	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
+	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
+			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
+	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
+		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
+		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
+			 " (%x) %s", build_id,
+			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
+	}
+	devlink_info_version_running_put(req,
+					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
+					 buf);
+
+	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V2_OUT_SUCFW_VERSION);
+		tstamp = MCDI_QWORD(outbuf,
+				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
+		rtc_time64_to_tm(tstamp, &build_date);
+		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
+			 "%u.%u.%u.%u type %x (%ptRd)",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
+			 build_id, &build_date);
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
+						 buf);
+	}
+}
+
+static void efx_devlink_info_running_v3(struct efx_nic *efx,
+					struct devlink_info_req *req,
+					unsigned int flags, efx_dword_t *outbuf)
+{
+	char buf[EFX_MAX_VERSION_INFO_LEN];
+	union {
+		const __le32 *dwords;
+		const __le16 *words;
+		const char *str;
+	} ver;
+
+	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]));
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
+						 buf);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]));
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
+						 buf);
+	}
+}
+
+static void efx_devlink_info_running_v4(struct efx_nic *efx,
+					struct devlink_info_req *req,
+					unsigned int flags, efx_dword_t *outbuf)
+{
+	char buf[EFX_MAX_VERSION_INFO_LEN];
+	union {
+		const __le32 *dwords;
+		const __le16 *words;
+		const char *str;
+	} ver;
+
+	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]),
+			 le32_to_cpu(ver.dwords[3]));
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
+						 buf);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]),
+			 le32_to_cpu(ver.dwords[3]));
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
+						 buf);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]),
+			 le32_to_cpu(ver.dwords[3]));
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
+						 buf);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]),
+			 le32_to_cpu(ver.dwords[3]));
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
+						 buf);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
+	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V4_OUT_SUCFW_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]),
+			 le32_to_cpu(ver.dwords[3]));
+
+		devlink_info_version_running_put(req,
+						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
+						 buf);
+	}
+}
+
+static void efx_devlink_info_running_v5(struct efx_nic *efx,
+					struct devlink_info_req *req,
+					unsigned int flags, efx_dword_t *outbuf)
+{
+	char buf[EFX_MAX_VERSION_INFO_LEN];
+	union {
+		const __le32 *dwords;
+		const __le16 *words;
+		const char *str;
+	} ver;
+
+	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V5_OUT_BOARD_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]),
+			 le32_to_cpu(ver.dwords[3]));
+
+		devlink_info_version_running_put(req,
+						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
+						 buf);
+	}
+
+	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
+		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
+						GET_VERSION_V5_OUT_BUNDLE_VERSION);
+
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
+			 le32_to_cpu(ver.dwords[2]),
+			 le32_to_cpu(ver.dwords[3]));
+
+		devlink_info_version_running_put(req,
+						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
+						 buf);
+	}
+}
+
+static int efx_devlink_info_running_versions(struct efx_nic *efx,
+					     struct devlink_info_req *req)
+{
+	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
+	char buf[EFX_MAX_VERSION_INFO_LEN];
+	union {
+		const __le32 *dwords;
+		const __le16 *words;
+		const char *str;
+	} ver;
+	size_t outlength;
+	unsigned int flags;
+	int rc;
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlength);
+	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
+		netif_err(efx, drv, efx->net_dev,
+			  "mcdi MC_CMD_GET_VERSION failed\n");
+		return rc;
+	}
+
+	/* Handle previous output */
+	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
+		ver.words = (__le16 *)MCDI_PTR(outbuf,
+					       GET_VERSION_EXT_OUT_VERSION);
+		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
+			 le16_to_cpu(ver.words[0]),
+			 le16_to_cpu(ver.words[1]),
+			 le16_to_cpu(ver.words[2]),
+			 le16_to_cpu(ver.words[3]));
+
+		devlink_info_version_running_put(req,
+						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
+						 buf);
+		return 0;
+	}
+
+	/* Handle V2 additions */
+	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
+	efx_devlink_info_running_v2(efx, req, flags, outbuf);
+
+	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
+		return 0;
+
+	/* Handle V3 additions */
+	efx_devlink_info_running_v3(efx, req, flags, outbuf);
+
+	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
+		return 0;
+
+	/* Handle V4 additions */
+	efx_devlink_info_running_v4(efx, req, flags, outbuf);
+
+	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
+		return 0;
+
+	/* Handle V5 additions */
+	efx_devlink_info_running_v5(efx, req, flags, outbuf);
+
+	return 0;
+}
+
+#define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
+
+static int efx_devlink_info_board_cfg(struct efx_nic *efx,
+				      struct devlink_info_req *req)
+{
+	char sn[EFX_MAX_SERIALNUM_LEN];
+	u8 mac_address[ETH_ALEN];
+	int rc;
+
+	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
+	if (!rc) {
+		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
+		devlink_info_serial_number_put(req, sn);
+	}
+	return rc;
+}
+
+static int efx_devlink_info_get(struct devlink *devlink,
+				struct devlink_info_req *req,
+				struct netlink_ext_ack *extack)
+{
+	struct efx_devlink *devlink_private = devlink_priv(devlink);
+	struct efx_nic *efx = devlink_private->efx;
+	int rc;
+
+	/* Several different MCDI commands are used. We report first error
+	 * through extack along with total number of errors. Specific error
+	 * information via system messages.
+	 */
+	rc = efx_devlink_info_board_cfg(efx, req);
+	if (rc) {
+		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
+		return rc;
+	}
+	rc = efx_devlink_info_stored_versions(efx, req);
+	if (rc) {
+		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
+		return rc;
+	}
+	rc = efx_devlink_info_running_versions(efx, req);
+	if (rc) {
+		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
+		return rc;
+	}
+
+	return 0;
+}
+#endif
+
 static const struct devlink_ops sfc_devlink_ops = {
+#ifdef CONFIG_SFC_SRIOV
+	.info_get			= efx_devlink_info_get,
+#endif
 };
 
 void efx_fini_devlink_lock(struct efx_nic *efx)
diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
index 8ff85b035e87..a5269361c3e0 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.h
+++ b/drivers/net/ethernet/sfc/efx_devlink.h
@@ -14,6 +14,23 @@
 #include "net_driver.h"
 #include <net/devlink.h>
 
+/* Custom devlink-info version object names for details that do not map to the
+ * generic standardized names.
+ */
+#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC	"fw.mgmt.suc"
+#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC	"fw.mgmt.cmc"
+#define EFX_DEVLINK_INFO_VERSION_FPGA_REV	"fpga.rev"
+#define EFX_DEVLINK_INFO_VERSION_DATAPATH_HW	"fpga.app"
+#define EFX_DEVLINK_INFO_VERSION_DATAPATH_FW	DEVLINK_INFO_VERSION_GENERIC_FW_APP
+#define EFX_DEVLINK_INFO_VERSION_SOC_BOOT	"coproc.boot"
+#define EFX_DEVLINK_INFO_VERSION_SOC_UBOOT	"coproc.uboot"
+#define EFX_DEVLINK_INFO_VERSION_SOC_MAIN	"coproc.main"
+#define EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY	"coproc.recovery"
+#define EFX_DEVLINK_INFO_VERSION_FW_EXPROM	"fw.exprom"
+#define EFX_DEVLINK_INFO_VERSION_FW_UEFI	"fw.uefi"
+
+#define EFX_MAX_VERSION_INFO_LEN	64
+
 int efx_probe_devlink_and_lock(struct efx_nic *efx);
 void efx_probe_devlink_unlock(struct efx_nic *efx);
 void efx_fini_devlink_lock(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index af338208eae9..2442e33225a6 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -2175,6 +2175,80 @@ int efx_mcdi_get_privilege_mask(struct efx_nic *efx, u32 *mask)
 	return 0;
 }
 
+#ifdef CONFIG_SFC_SRIOV
+int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
+			    u32 *subtype, u16 version[4], char *desc,
+			    size_t descsize)
+{
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
+	efx_dword_t *outbuf;
+	size_t outlen;
+	u32 flags;
+	int rc;
+
+	outbuf = kzalloc(MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2, GFP_KERNEL);
+	if (!outbuf)
+		return -ENOMEM;
+
+	MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
+
+	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_NVRAM_METADATA, inbuf,
+				sizeof(inbuf), outbuf,
+				MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2,
+				&outlen);
+	if (rc)
+		goto out_free;
+	if (outlen < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
+		rc = -EIO;
+		goto out_free;
+	}
+
+	flags = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_FLAGS);
+
+	if (desc && descsize > 0) {
+		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_VALID_LBN)) {
+			if (descsize <=
+			    MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)) {
+				rc = -E2BIG;
+				goto out_free;
+			}
+
+			strncpy(desc,
+				MCDI_PTR(outbuf, NVRAM_METADATA_OUT_DESCRIPTION),
+				MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen));
+			desc[MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)] = '\0';
+		} else {
+			desc[0] = '\0';
+		}
+	}
+
+	if (subtype) {
+		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_SUBTYPE_VALID_LBN))
+			*subtype = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_SUBTYPE);
+		else
+			*subtype = 0;
+	}
+
+	if (version) {
+		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_VERSION_VALID_LBN)) {
+			version[0] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_W);
+			version[1] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_X);
+			version[2] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Y);
+			version[3] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Z);
+		} else {
+			version[0] = 0;
+			version[1] = 0;
+			version[2] = 0;
+			version[3] = 0;
+		}
+	}
+
+out_free:
+	kfree(outbuf);
+	return rc;
+}
+#endif
+
 #ifdef CONFIG_SFC_MTD
 
 #define EFX_MCDI_NVRAM_LEN_MAX 128
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 7e35fec9da35..32f54ce2492e 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -378,6 +378,11 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
 			size_t *size_out, size_t *erase_size_out,
 			bool *protected_out);
 int efx_new_mcdi_nvram_test_all(struct efx_nic *efx);
+#ifdef CONFIG_SFC_SRIOV
+int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
+			    u32 *subtype, u16 version[4], char *desc,
+			    size_t descsize);
+#endif
 int efx_mcdi_nvram_test_all(struct efx_nic *efx);
 int efx_mcdi_handle_assertion(struct efx_nic *efx);
 int efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 3/8] sfc: enumerate mports in ef100
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
  2023-02-08 14:25 ` [PATCH v6 net-next 1/8] sfc: add " alejandro.lucero-palau
  2023-02-08 14:25 ` [PATCH v6 net-next 2/8] sfc: add devlink info " alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-10  8:46   ` Martin Habets
  2023-02-08 14:25 ` [PATCH v6 net-next 4/8] sfc: add mport lookup based on driver's mport data alejandro.lucero-palau
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

MAE ports (mports) are the ports on the EF100 embedded switch such
as networking PCIe functions, the physical port, and potentially
others.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
---
 drivers/net/ethernet/sfc/ef100_nic.c  |  27 ++++
 drivers/net/ethernet/sfc/ef100_nic.h  |   4 +
 drivers/net/ethernet/sfc/ef100_rep.c  |  22 +++
 drivers/net/ethernet/sfc/ef100_rep.h  |   2 +
 drivers/net/ethernet/sfc/mae.c        | 191 ++++++++++++++++++++++++++
 drivers/net/ethernet/sfc/mae.h        |  36 +++++
 drivers/net/ethernet/sfc/mcdi.h       |   5 +
 drivers/net/ethernet/sfc/net_driver.h |   4 +
 8 files changed, 291 insertions(+)

diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index ad686c671ab8..07e7dca0e4f2 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -747,6 +747,19 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
 			   id);
 	nic_data->base_mport = id;
 	nic_data->have_mport = true;
+
+	/* Construct mport selector for "calling PF" */
+	efx_mae_mport_uplink(efx, &selector);
+	/* Look up actual mport ID */
+	rc = efx_mae_lookup_mport(efx, selector, &id);
+	if (rc)
+		return rc;
+	if (id >> 16)
+		netif_warn(efx, probe, efx->net_dev, "Bad own m-port id %#x\n",
+			   id);
+	nic_data->own_mport = id;
+	nic_data->have_own_mport = true;
+
 	return 0;
 }
 #endif
@@ -1126,6 +1139,14 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
 			   rc);
 	}
 
+	rc = efx_init_mae(efx);
+	if (rc)
+		netif_warn(efx, probe, net_dev,
+			   "Failed to init MAE rc %d; representors will not function\n",
+			   rc);
+	else
+		efx_ef100_init_reps(efx);
+
 	rc = efx_init_tc(efx);
 	if (rc) {
 		/* Either we don't have an MAE at all (i.e. legacy v-switching),
@@ -1157,6 +1178,12 @@ void ef100_remove(struct efx_nic *efx)
 {
 	struct ef100_nic_data *nic_data = efx->nic_data;
 
+#ifdef CONFIG_SFC_SRIOV
+	if (efx->mae) {
+		efx_ef100_fini_reps(efx);
+		efx_fini_mae(efx);
+	}
+#endif
 	efx_mcdi_detach(efx);
 	efx_mcdi_fini(efx);
 	if (nic_data)
diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h
index 0295933145fa..496aea43c60f 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.h
+++ b/drivers/net/ethernet/sfc/ef100_nic.h
@@ -74,6 +74,10 @@ struct ef100_nic_data {
 	u64 stats[EF100_STAT_COUNT];
 	u32 base_mport;
 	bool have_mport; /* base_mport was populated successfully */
+	u32 own_mport;
+	u32 local_mae_intf; /* interface_idx that corresponds to us, in mport enumerate */
+	bool have_own_mport; /* own_mport was populated successfully */
+	bool have_local_intf; /* local_mae_intf was populated successfully */
 	bool grp_mae; /* MAE Privilege */
 	u16 tso_max_hdr_len;
 	u16 tso_max_payload_num_segs;
diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
index 81ab22c74635..ebe7b1275713 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.c
+++ b/drivers/net/ethernet/sfc/ef100_rep.c
@@ -9,6 +9,7 @@
  * by the Free Software Foundation, incorporated herein by reference.
  */
 
+#include <linux/rhashtable.h>
 #include "ef100_rep.h"
 #include "ef100_netdev.h"
 #include "ef100_nic.h"
@@ -341,6 +342,27 @@ void efx_ef100_fini_vfreps(struct efx_nic *efx)
 		efx_ef100_vfrep_destroy(efx, efv);
 }
 
+void efx_ef100_init_reps(struct efx_nic *efx)
+{
+	struct ef100_nic_data *nic_data = efx->nic_data;
+	int rc;
+
+	nic_data->have_local_intf = false;
+	rc = efx_mae_enumerate_mports(efx);
+	if (rc)
+		pci_warn(efx->pci_dev,
+			 "Could not enumerate mports (rc=%d), are we admin?",
+			 rc);
+}
+
+void efx_ef100_fini_reps(struct efx_nic *efx)
+{
+	struct efx_mae *mae = efx->mae;
+
+	rhashtable_free_and_destroy(&mae->mports_ht, efx_mae_remove_mport,
+				    NULL);
+}
+
 static int efx_ef100_rep_poll(struct napi_struct *napi, int weight)
 {
 	struct efx_rep *efv = container_of(napi, struct efx_rep, napi);
diff --git a/drivers/net/ethernet/sfc/ef100_rep.h b/drivers/net/ethernet/sfc/ef100_rep.h
index c21bc716f847..328ac0cbb532 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.h
+++ b/drivers/net/ethernet/sfc/ef100_rep.h
@@ -67,4 +67,6 @@ void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf);
  */
 struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport);
 extern const struct net_device_ops efx_ef100_rep_netdev_ops;
+void efx_ef100_init_reps(struct efx_nic *efx);
+void efx_ef100_fini_reps(struct efx_nic *efx);
 #endif /* EF100_REP_H */
diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
index 583baf69981c..725a3ab31087 100644
--- a/drivers/net/ethernet/sfc/mae.c
+++ b/drivers/net/ethernet/sfc/mae.c
@@ -9,8 +9,11 @@
  * by the Free Software Foundation, incorporated herein by reference.
  */
 
+#include <linux/rhashtable.h>
+#include "ef100_nic.h"
 #include "mae.h"
 #include "mcdi.h"
+#include "mcdi_pcol.h"
 #include "mcdi_pcol_mae.h"
 
 int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
@@ -490,6 +493,163 @@ static bool efx_mae_asl_id(u32 id)
 	return !!(id & BIT(31));
 }
 
+/* mport handling */
+static const struct rhashtable_params efx_mae_mports_ht_params = {
+	.key_len	= sizeof(u32),
+	.key_offset	= offsetof(struct mae_mport_desc, mport_id),
+	.head_offset	= offsetof(struct mae_mport_desc, linkage),
+};
+
+struct mae_mport_desc *efx_mae_get_mport(struct efx_nic *efx, u32 mport_id)
+{
+	return rhashtable_lookup_fast(&efx->mae->mports_ht, &mport_id,
+				      efx_mae_mports_ht_params);
+}
+
+static int efx_mae_add_mport(struct efx_nic *efx, struct mae_mport_desc *desc)
+{
+	struct efx_mae *mae = efx->mae;
+	int rc;
+
+	rc = rhashtable_insert_fast(&mae->mports_ht, &desc->linkage,
+				    efx_mae_mports_ht_params);
+
+	if (rc) {
+		pci_err(efx->pci_dev, "Failed to insert MPORT %08x, rc %d\n",
+			desc->mport_id, rc);
+		kfree(desc);
+		return rc;
+	}
+
+	return rc;
+}
+
+void efx_mae_remove_mport(void *desc, void *arg)
+{
+	struct mae_mport_desc *mport = desc;
+
+	synchronize_rcu();
+	kfree(mport);
+}
+
+static int efx_mae_process_mport(struct efx_nic *efx,
+				 struct mae_mport_desc *desc)
+{
+	struct ef100_nic_data *nic_data = efx->nic_data;
+	struct mae_mport_desc *mport;
+
+	mport = efx_mae_get_mport(efx, desc->mport_id);
+	if (!IS_ERR_OR_NULL(mport)) {
+		netif_err(efx, drv, efx->net_dev,
+			  "mport with id %u does exist!!!\n", desc->mport_id);
+		return -EEXIST;
+	}
+
+	if (nic_data->have_own_mport &&
+	    desc->mport_id == nic_data->own_mport) {
+		WARN_ON(desc->mport_type != MAE_MPORT_DESC_MPORT_TYPE_VNIC);
+		WARN_ON(desc->vnic_client_type !=
+			MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION);
+		nic_data->local_mae_intf = desc->interface_idx;
+		nic_data->have_local_intf = true;
+		pci_dbg(efx->pci_dev, "MAE interface_idx is %u\n",
+			nic_data->local_mae_intf);
+	}
+
+	return efx_mae_add_mport(efx, desc);
+}
+
+#define MCDI_MPORT_JOURNAL_LEN \
+	ALIGN(MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2, 4)
+
+int efx_mae_enumerate_mports(struct efx_nic *efx)
+{
+	efx_dword_t *outbuf = kzalloc(MCDI_MPORT_JOURNAL_LEN, GFP_KERNEL);
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN);
+	MCDI_DECLARE_STRUCT_PTR(desc);
+	size_t outlen, stride, count;
+	int rc = 0, i;
+
+	if (!outbuf)
+		return -ENOMEM;
+	do {
+		rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_READ_JOURNAL, inbuf,
+				  sizeof(inbuf), outbuf,
+				  MCDI_MPORT_JOURNAL_LEN, &outlen);
+		if (rc)
+			goto fail;
+		if (outlen < MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_OFST) {
+			rc = -EIO;
+			goto fail;
+		}
+		count = MCDI_DWORD(outbuf, MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT);
+		if (!count)
+			continue; /* not break; we want to look at MORE flag */
+		stride = MCDI_DWORD(outbuf, MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC);
+		if (stride < MAE_MPORT_DESC_LEN) {
+			rc = -EIO;
+			goto fail;
+		}
+		if (outlen < MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LEN(count * stride)) {
+			rc = -EIO;
+			goto fail;
+		}
+
+		for (i = 0; i < count; i++) {
+			struct mae_mport_desc *d;
+
+			d = kzalloc(sizeof(*d), GFP_KERNEL);
+			if (!d) {
+				rc = -ENOMEM;
+				goto fail;
+			}
+
+			desc = (efx_dword_t *)
+				_MCDI_PTR(outbuf, MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_OFST +
+					  i * stride);
+			d->mport_id = MCDI_STRUCT_DWORD(desc, MAE_MPORT_DESC_MPORT_ID);
+			d->flags = MCDI_STRUCT_DWORD(desc, MAE_MPORT_DESC_FLAGS);
+			d->caller_flags = MCDI_STRUCT_DWORD(desc,
+							    MAE_MPORT_DESC_CALLER_FLAGS);
+			d->mport_type = MCDI_STRUCT_DWORD(desc,
+							  MAE_MPORT_DESC_MPORT_TYPE);
+			switch (d->mport_type) {
+			case MAE_MPORT_DESC_MPORT_TYPE_NET_PORT:
+				d->port_idx = MCDI_STRUCT_DWORD(desc,
+								MAE_MPORT_DESC_NET_PORT_IDX);
+				break;
+			case MAE_MPORT_DESC_MPORT_TYPE_ALIAS:
+				d->alias_mport_id = MCDI_STRUCT_DWORD(desc,
+								      MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID);
+				break;
+			case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
+				d->vnic_client_type = MCDI_STRUCT_DWORD(desc,
+									MAE_MPORT_DESC_VNIC_CLIENT_TYPE);
+				d->interface_idx = MCDI_STRUCT_DWORD(desc,
+								     MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE);
+				d->pf_idx = MCDI_STRUCT_WORD(desc,
+							     MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX);
+			d->vf_idx = MCDI_STRUCT_WORD(desc,
+						     MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX);
+				break;
+			default:
+				/* Unknown mport_type, just accept it */
+				break;
+			}
+			rc = efx_mae_process_mport(efx, d);
+			/* Any failure will be due to memory allocation faiure,
+			 * so there is no point to try subsequent entries.
+			 */
+			if (rc)
+				goto fail;
+		}
+	} while (MCDI_FIELD(outbuf, MAE_MPORT_READ_JOURNAL_OUT, MORE) &&
+		 !WARN_ON(!count));
+fail:
+	kfree(outbuf);
+	return rc;
+}
+
 int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
 {
 	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
@@ -805,3 +965,34 @@ int efx_mae_delete_rule(struct efx_nic *efx, u32 id)
 		return -EIO;
 	return 0;
 }
+
+int efx_init_mae(struct efx_nic *efx)
+{
+	struct ef100_nic_data *nic_data = efx->nic_data;
+	struct efx_mae *mae;
+	int rc;
+
+	if (!nic_data->have_mport)
+		return -EINVAL;
+
+	mae = kmalloc(sizeof(*mae), GFP_KERNEL);
+	if (!mae)
+		return -ENOMEM;
+
+	rc = rhashtable_init(&mae->mports_ht, &efx_mae_mports_ht_params);
+	if (rc < 0) {
+		kfree(mae);
+		return rc;
+	}
+	efx->mae = mae;
+	mae->efx = efx;
+	return 0;
+}
+
+void efx_fini_mae(struct efx_nic *efx)
+{
+	struct efx_mae *mae = efx->mae;
+
+	kfree(mae);
+	efx->mae = NULL;
+}
diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
index 72343e90e222..daa29d2cde96 100644
--- a/drivers/net/ethernet/sfc/mae.h
+++ b/drivers/net/ethernet/sfc/mae.h
@@ -27,6 +27,39 @@ void efx_mae_mport_mport(struct efx_nic *efx, u32 mport_id, u32 *out);
 
 int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id);
 
+struct mae_mport_desc {
+	u32 mport_id;
+	u32 flags;
+	u32 caller_flags; /* enum mae_mport_desc_caller_flags */
+	u32 mport_type; /* MAE_MPORT_DESC_MPORT_TYPE_* */
+	union {
+		u32 port_idx; /* for mport_type == NET_PORT */
+		u32 alias_mport_id; /* for mport_type == ALIAS */
+		struct { /* for mport_type == VNIC */
+			u32 vnic_client_type; /* MAE_MPORT_DESC_VNIC_CLIENT_TYPE_* */
+			u32 interface_idx;
+			u16 pf_idx;
+			u16 vf_idx;
+		};
+	};
+	struct rhash_head linkage;
+};
+
+int efx_mae_enumerate_mports(struct efx_nic *efx);
+struct mae_mport_desc *efx_mae_get_mport(struct efx_nic *efx, u32 mport_id);
+void efx_mae_put_mport(struct efx_nic *efx, struct mae_mport_desc *desc);
+
+/**
+ * struct efx_mae - MAE information
+ *
+ * @efx: The associated NIC
+ * @mports_ht: m-port descriptions from MC_CMD_MAE_MPORT_READ_JOURNAL
+ */
+struct efx_mae {
+	struct efx_nic *efx;
+	struct rhashtable mports_ht;
+};
+
 int efx_mae_start_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue);
 int efx_mae_stop_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue);
 void efx_mae_counters_grant_credits(struct work_struct *work);
@@ -60,4 +93,7 @@ int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
 			u32 prio, u32 acts_id, u32 *id);
 int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
 
+int efx_init_mae(struct efx_nic *efx);
+void efx_fini_mae(struct efx_nic *efx);
+void efx_mae_remove_mport(void *desc, void *arg);
 #endif /* EF100_MAE_H */
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 32f54ce2492e..d280ad8f7836 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -229,6 +229,9 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
 #define MCDI_WORD(_buf, _field)						\
 	((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) +	\
 	 le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field)))
+#define MCDI_STRUCT_WORD(_buf, _field)                                  \
+	((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 2),  \
+	le16_to_cpu(*(__force const __le16 *)MCDI_STRUCT_PTR(_buf, _field)))
 /* Write a 16-bit field defined in the protocol as being big-endian. */
 #define MCDI_STRUCT_SET_WORD_BE(_buf, _field, _value) do {		\
 	BUILD_BUG_ON(_field ## _LEN != 2);				\
@@ -241,6 +244,8 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
 	EFX_POPULATE_DWORD_1(*_MCDI_STRUCT_DWORD(_buf, _field), EFX_DWORD_0, _value)
 #define MCDI_DWORD(_buf, _field)					\
 	EFX_DWORD_FIELD(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0)
+#define MCDI_STRUCT_DWORD(_buf, _field)                                 \
+	EFX_DWORD_FIELD(*_MCDI_STRUCT_DWORD(_buf, _field), EFX_DWORD_0)
 /* Write a 32-bit field defined in the protocol as being big-endian. */
 #define MCDI_STRUCT_SET_DWORD_BE(_buf, _field, _value) do {		\
 	BUILD_BUG_ON(_field ## _LEN != 4);				\
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index d036641dc043..bc9efbfb3d6b 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -845,6 +845,8 @@ enum efx_xdp_tx_queues_mode {
 	EFX_XDP_TX_QUEUES_BORROWED	/* queues borrowed from net stack */
 };
 
+struct efx_mae;
+
 /**
  * struct efx_nic - an Efx NIC
  * @name: Device name (net device name or bus id before net device registered)
@@ -881,6 +883,7 @@ enum efx_xdp_tx_queues_mode {
  * @msi_context: Context for each MSI
  * @extra_channel_types: Types of extra (non-traffic) channels that
  *	should be allocated for this NIC
+ * @mae: Details of the Match Action Engine
  * @xdp_tx_queue_count: Number of entries in %xdp_tx_queues.
  * @xdp_tx_queues: Array of pointers to tx queues used for XDP transmit.
  * @xdp_txq_queues_mode: XDP TX queues sharing strategy.
@@ -1044,6 +1047,7 @@ struct efx_nic {
 	struct efx_msi_context msi_context[EFX_MAX_CHANNELS];
 	const struct efx_channel_type *
 	extra_channel_type[EFX_MAX_EXTRA_CHANNELS];
+	struct efx_mae *mae;
 
 	unsigned int xdp_tx_queue_count;
 	struct efx_tx_queue **xdp_tx_queues;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 4/8] sfc: add mport lookup based on driver's mport data
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
                   ` (2 preceding siblings ...)
  2023-02-08 14:25 ` [PATCH v6 net-next 3/8] sfc: enumerate mports in ef100 alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-10  8:47   ` Martin Habets
  2023-02-08 14:25 ` [PATCH v6 net-next 5/8] sfc: add devlink port support for ef100 alejandro.lucero-palau
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Obtaining mport id is based on asking the firmware about it. This is
still needed for mport initialization itself, but once the mport data is
now kept by the driver, further mport id request can be satisfied
internally without firmware interaction.

Previous function is just modified in name making clear the firmware
interaction. The new function uses the old name and looks for the data
in the mport data structure.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
---
 drivers/net/ethernet/sfc/ef100_nic.c |  4 ++--
 drivers/net/ethernet/sfc/ef100_rep.c |  5 +----
 drivers/net/ethernet/sfc/mae.c       | 27 ++++++++++++++++++++++++++-
 drivers/net/ethernet/sfc/mae.h       |  2 ++
 4 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 07e7dca0e4f2..aa11f0925e27 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -736,7 +736,7 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
 	/* Construct mport selector for "physical network port" */
 	efx_mae_mport_wire(efx, &selector);
 	/* Look up actual mport ID */
-	rc = efx_mae_lookup_mport(efx, selector, &id);
+	rc = efx_mae_fw_lookup_mport(efx, selector, &id);
 	if (rc)
 		return rc;
 	/* The ID should always fit in 16 bits, because that's how wide the
@@ -751,7 +751,7 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
 	/* Construct mport selector for "calling PF" */
 	efx_mae_mport_uplink(efx, &selector);
 	/* Look up actual mport ID */
-	rc = efx_mae_lookup_mport(efx, selector, &id);
+	rc = efx_mae_fw_lookup_mport(efx, selector, &id);
 	if (rc)
 		return rc;
 	if (id >> 16)
diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
index ebe7b1275713..9cd1a3ac67e0 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.c
+++ b/drivers/net/ethernet/sfc/ef100_rep.c
@@ -243,14 +243,11 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
 static int efx_ef100_configure_rep(struct efx_rep *efv)
 {
 	struct efx_nic *efx = efv->parent;
-	u32 selector;
 	int rc;
 
 	efv->rx_pring_size = EFX_REP_DEFAULT_PSEUDO_RING_SIZE;
-	/* Construct mport selector for corresponding VF */
-	efx_mae_mport_vf(efx, efv->idx, &selector);
 	/* Look up actual mport ID */
-	rc = efx_mae_lookup_mport(efx, selector, &efv->mport);
+	rc = efx_mae_lookup_mport(efx, efv->idx, &efv->mport);
 	if (rc)
 		return rc;
 	pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport);
diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
index 725a3ab31087..6321fd393fc3 100644
--- a/drivers/net/ethernet/sfc/mae.c
+++ b/drivers/net/ethernet/sfc/mae.c
@@ -97,7 +97,7 @@ void efx_mae_mport_mport(struct efx_nic *efx __always_unused, u32 mport_id, u32
 }
 
 /* id is really only 24 bits wide */
-int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id)
+int efx_mae_fw_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id)
 {
 	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN);
 	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_LOOKUP_IN_LEN);
@@ -488,6 +488,31 @@ int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt)
 	return 0;
 }
 
+int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id)
+{
+	struct ef100_nic_data *nic_data = efx->nic_data;
+	struct efx_mae *mae = efx->mae;
+	struct rhashtable_iter walk;
+	struct mae_mport_desc *m;
+	int rc = -ENOENT;
+
+	rhashtable_walk_enter(&mae->mports_ht, &walk);
+	rhashtable_walk_start(&walk);
+	while ((m = rhashtable_walk_next(&walk)) != NULL) {
+		if (m->mport_type == MAE_MPORT_DESC_MPORT_TYPE_VNIC &&
+		    m->interface_idx == nic_data->local_mae_intf &&
+		    m->pf_idx == 0 &&
+		    m->vf_idx == vf_idx) {
+			*id = m->mport_id;
+			rc = 0;
+			break;
+		}
+	}
+	rhashtable_walk_stop(&walk);
+	rhashtable_walk_exit(&walk);
+	return rc;
+}
+
 static bool efx_mae_asl_id(u32 id)
 {
 	return !!(id & BIT(31));
diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
index daa29d2cde96..b9bf86c47cda 100644
--- a/drivers/net/ethernet/sfc/mae.h
+++ b/drivers/net/ethernet/sfc/mae.h
@@ -96,4 +96,6 @@ int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
 int efx_init_mae(struct efx_nic *efx);
 void efx_fini_mae(struct efx_nic *efx);
 void efx_mae_remove_mport(void *desc, void *arg);
+int efx_mae_fw_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id);
+int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf, u32 *id);
 #endif /* EF100_MAE_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 5/8] sfc: add devlink port support for ef100
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
                   ` (3 preceding siblings ...)
  2023-02-08 14:25 ` [PATCH v6 net-next 4/8] sfc: add mport lookup based on driver's mport data alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-10  8:49   ` Martin Habets
  2023-02-08 14:25 ` [PATCH v6 net-next 6/8] sfc: obtain device mac address based on firmware handle " alejandro.lucero-palau
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Using the data when enumerating mports, create devlink ports just before
netdevs are registered and remove those devlink ports after netdev has
been unregistered.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/net/ethernet/sfc/ef100_netdev.c |  10 +++
 drivers/net/ethernet/sfc/ef100_rep.c    |  22 ++++++
 drivers/net/ethernet/sfc/ef100_rep.h    |   7 ++
 drivers/net/ethernet/sfc/efx_devlink.c  | 101 ++++++++++++++++++++++++
 drivers/net/ethernet/sfc/efx_devlink.h  |   9 +++
 drivers/net/ethernet/sfc/mae.h          |   2 +
 drivers/net/ethernet/sfc/net_driver.h   |   2 +
 7 files changed, 153 insertions(+)

diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index 6cf74788b27a..368147359299 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -337,6 +337,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
 	ef100_unregister_netdev(efx);
 
 #ifdef CONFIG_SFC_SRIOV
+	ef100_pf_unset_devlink_port(efx);
 	efx_fini_tc(efx);
 #endif
 
@@ -422,6 +423,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 		rc = ef100_probe_netdev_pf(efx);
 		if (rc)
 			goto fail;
+#ifdef CONFIG_SFC_SRIOV
+		ef100_pf_set_devlink_port(efx);
+#endif
 	}
 
 	efx->netdev_notifier.notifier_call = ef100_netdev_event;
@@ -432,7 +436,13 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 		goto fail;
 	}
 
+	efx_probe_devlink_unlock(efx);
+	return rc;
 fail:
+#ifdef CONFIG_SFC_SRIOV
+	/* remove devlink port if does exist */
+	ef100_pf_unset_devlink_port(efx);
+#endif
 	efx_probe_devlink_unlock(efx);
 	return rc;
 }
diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
index 9cd1a3ac67e0..6b5bc5d6955d 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.c
+++ b/drivers/net/ethernet/sfc/ef100_rep.c
@@ -16,6 +16,7 @@
 #include "mae.h"
 #include "rx_common.h"
 #include "tc_bindings.h"
+#include "efx_devlink.h"
 
 #define EFX_EF100_REP_DRIVER	"efx_ef100_rep"
 
@@ -297,6 +298,7 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
 			i, rc);
 		goto fail1;
 	}
+	ef100_rep_set_devlink_port(efv);
 	rc = register_netdev(efv->net_dev);
 	if (rc) {
 		pci_err(efx->pci_dev,
@@ -308,6 +310,7 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
 		efv->net_dev->name);
 	return 0;
 fail2:
+	ef100_rep_unset_devlink_port(efv);
 	efx_ef100_deconfigure_rep(efv);
 fail1:
 	efx_ef100_rep_destroy_netdev(efv);
@@ -323,6 +326,7 @@ void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv)
 		return;
 	netif_dbg(efx, drv, rep_dev, "Removing VF representor\n");
 	unregister_netdev(rep_dev);
+	ef100_rep_unset_devlink_port(efv);
 	efx_ef100_deconfigure_rep(efv);
 	efx_ef100_rep_destroy_netdev(efv);
 }
@@ -339,6 +343,24 @@ void efx_ef100_fini_vfreps(struct efx_nic *efx)
 		efx_ef100_vfrep_destroy(efx, efv);
 }
 
+static bool ef100_mport_is_pcie_vnic(struct mae_mport_desc *mport_desc)
+{
+	return mport_desc->mport_type == MAE_MPORT_DESC_MPORT_TYPE_VNIC &&
+	       mport_desc->vnic_client_type == MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION;
+}
+
+bool ef100_mport_on_local_intf(struct efx_nic *efx,
+			       struct mae_mport_desc *mport_desc)
+{
+	struct ef100_nic_data *nic_data = efx->nic_data;
+	bool pcie_func;
+
+	pcie_func = ef100_mport_is_pcie_vnic(mport_desc);
+
+	return nic_data->have_local_intf && pcie_func &&
+		     mport_desc->interface_idx == nic_data->local_mae_intf;
+}
+
 void efx_ef100_init_reps(struct efx_nic *efx)
 {
 	struct ef100_nic_data *nic_data = efx->nic_data;
diff --git a/drivers/net/ethernet/sfc/ef100_rep.h b/drivers/net/ethernet/sfc/ef100_rep.h
index 328ac0cbb532..ae6add4b0855 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.h
+++ b/drivers/net/ethernet/sfc/ef100_rep.h
@@ -22,6 +22,8 @@ struct efx_rep_sw_stats {
 	atomic64_t rx_dropped, tx_errors;
 };
 
+struct devlink_port;
+
 /**
  * struct efx_rep - Private data for an Efx representor
  *
@@ -39,6 +41,7 @@ struct efx_rep_sw_stats {
  * @rx_lock: protects @rx_list
  * @napi: NAPI control structure
  * @stats: software traffic counters for netdev stats
+ * @dl_port: devlink port associated to this netdev representor
  */
 struct efx_rep {
 	struct efx_nic *parent;
@@ -54,6 +57,7 @@ struct efx_rep {
 	spinlock_t rx_lock;
 	struct napi_struct napi;
 	struct efx_rep_sw_stats stats;
+	struct devlink_port *dl_port;
 };
 
 int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i);
@@ -69,4 +73,7 @@ struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport);
 extern const struct net_device_ops efx_ef100_rep_netdev_ops;
 void efx_ef100_init_reps(struct efx_nic *efx);
 void efx_ef100_fini_reps(struct efx_nic *efx);
+struct mae_mport_desc;
+bool ef100_mport_on_local_intf(struct efx_nic *efx,
+			       struct mae_mport_desc *mport_desc);
 #endif /* EF100_REP_H */
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index c06efeac11e5..1b1276716113 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -14,6 +14,8 @@
 #include "mcdi.h"
 #include "mcdi_functions.h"
 #include "mcdi_pcol.h"
+#include "mae.h"
+#include "ef100_rep.h"
 #endif
 
 struct efx_devlink {
@@ -21,6 +23,41 @@ struct efx_devlink {
 };
 
 #ifdef CONFIG_SFC_SRIOV
+static void efx_devlink_del_port(struct devlink_port *dl_port)
+{
+	if (!dl_port)
+		return;
+	devl_port_unregister(dl_port);
+}
+
+static int efx_devlink_add_port(struct efx_nic *efx,
+				struct mae_mport_desc *mport)
+{
+	bool external = false;
+
+	if (!ef100_mport_on_local_intf(efx, mport))
+		external = true;
+
+	switch (mport->mport_type) {
+	case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
+		if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
+			devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
+						      mport->vf_idx,
+						      external);
+		else
+			devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
+						      external);
+		break;
+	default:
+		/* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
+		return 0;
+	}
+
+	mport->dl_port.index = mport->mport_id;
+
+	return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
+}
+
 static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
 					    struct devlink_info_req *req,
 					    unsigned int partition_type,
@@ -477,6 +514,70 @@ static const struct devlink_ops sfc_devlink_ops = {
 #endif
 };
 
+#ifdef CONFIG_SFC_SRIOV
+static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
+{
+	struct mae_mport_desc *mport;
+	u32 id;
+	int rc;
+
+	if (efx_mae_lookup_mport(efx, idx, &id)) {
+		/* This should not happen. */
+		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
+			pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
+		else
+			pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
+				      idx);
+		return NULL;
+	}
+
+	mport = efx_mae_get_mport(efx, id);
+	if (!mport) {
+		/* This should not happen. */
+		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
+			pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
+		else
+			pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
+				      idx);
+		return NULL;
+	}
+
+	rc = efx_devlink_add_port(efx, mport);
+	if (rc) {
+		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
+			pci_warn(efx->pci_dev,
+				 "devlink port creation for PF failed.\n");
+		else
+			pci_warn(efx->pci_dev,
+				 "devlink_port creationg for VF %u failed.\n",
+				 idx);
+		return NULL;
+	}
+
+	return &mport->dl_port;
+}
+
+void ef100_rep_set_devlink_port(struct efx_rep *efv)
+{
+	efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
+}
+
+void ef100_pf_set_devlink_port(struct efx_nic *efx)
+{
+	efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
+}
+
+void ef100_rep_unset_devlink_port(struct efx_rep *efv)
+{
+	efx_devlink_del_port(efv->dl_port);
+}
+
+void ef100_pf_unset_devlink_port(struct efx_nic *efx)
+{
+	efx_devlink_del_port(efx->dl_port);
+}
+#endif
+
 void efx_fini_devlink_lock(struct efx_nic *efx)
 {
 	if (efx->devlink)
diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
index a5269361c3e0..d544885d3dbf 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.h
+++ b/drivers/net/ethernet/sfc/efx_devlink.h
@@ -36,4 +36,13 @@ void efx_probe_devlink_unlock(struct efx_nic *efx);
 void efx_fini_devlink_lock(struct efx_nic *efx);
 void efx_fini_devlink_and_unlock(struct efx_nic *efx);
 
+#ifdef CONFIG_SFC_SRIOV
+struct efx_rep;
+
+void ef100_pf_set_devlink_port(struct efx_nic *efx);
+void ef100_rep_set_devlink_port(struct efx_rep *efv);
+void ef100_pf_unset_devlink_port(struct efx_nic *efx);
+void ef100_rep_unset_devlink_port(struct efx_rep *efv);
+#endif
+
 #endif	/* _EFX_DEVLINK_H */
diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
index b9bf86c47cda..bec293a06733 100644
--- a/drivers/net/ethernet/sfc/mae.h
+++ b/drivers/net/ethernet/sfc/mae.h
@@ -13,6 +13,7 @@
 #define EF100_MAE_H
 /* MCDI interface for the ef100 Match-Action Engine */
 
+#include <net/devlink.h>
 #include "net_driver.h"
 #include "tc.h"
 #include "mcdi_pcol.h" /* needed for various MC_CMD_MAE_*_NULL defines */
@@ -43,6 +44,7 @@ struct mae_mport_desc {
 		};
 	};
 	struct rhash_head linkage;
+	struct devlink_port dl_port;
 };
 
 int efx_mae_enumerate_mports(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index bc9efbfb3d6b..fcd51d3992fa 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -998,6 +998,7 @@ struct efx_mae;
  * @netdev_notifier: Netdevice notifier.
  * @tc: state for TC offload (EF100).
  * @devlink: reference to devlink structure owned by this device
+ * @dl_port: devlink port associated with the PF
  * @mem_bar: The BAR that is mapped into membase.
  * @reg_base: Offset from the start of the bar to the function control window.
  * @monitor_work: Hardware monitor workitem
@@ -1185,6 +1186,7 @@ struct efx_nic {
 	struct efx_tc_state *tc;
 
 	struct devlink *devlink;
+	struct devlink_port *dl_port;
 	unsigned int mem_bar;
 	u32 reg_base;
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 6/8] sfc: obtain device mac address based on firmware handle for ef100
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
                   ` (4 preceding siblings ...)
  2023-02-08 14:25 ` [PATCH v6 net-next 5/8] sfc: add devlink port support for ef100 alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-10  8:50   ` Martin Habets
  2023-02-08 14:25 ` [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100 alejandro.lucero-palau
  2023-02-08 14:25 ` [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set " alejandro.lucero-palau
  7 siblings, 1 reply; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Getting device mac address is currently based on a specific MCDI command
only available for the PF. This patch changes the MCDI command to a
generic one for PFs and VFs based on a client handle. This allows both
PFs and VFs to ask for their mac address during initialization using the
CLIENT_HANDLE_SELF.

Moreover, the patch allows other client handles which will be used by
the PF to ask for mac addresses linked to VFs. This is necessary for
suporting the port_function_hw_addr_get devlink function in further
patches.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
---
 drivers/net/ethernet/sfc/ef100_netdev.c | 10 +++++++
 drivers/net/ethernet/sfc/ef100_nic.c    | 37 +++++++++++++------------
 drivers/net/ethernet/sfc/ef100_nic.h    |  2 ++
 3 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
index 368147359299..d916877b5a9a 100644
--- a/drivers/net/ethernet/sfc/ef100_netdev.c
+++ b/drivers/net/ethernet/sfc/ef100_netdev.c
@@ -359,6 +359,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 {
 	struct efx_nic *efx = &probe_data->efx;
 	struct efx_probe_data **probe_ptr;
+	struct ef100_nic_data *nic_data;
 	struct net_device *net_dev;
 	int rc;
 
@@ -410,6 +411,15 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
 	/* Don't fail init if RSS setup doesn't work. */
 	efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);
 
+	nic_data = efx->nic_data;
+	rc = ef100_get_mac_address(efx, net_dev->perm_addr, CLIENT_HANDLE_SELF,
+				   efx->type->is_vf);
+	if (rc)
+		return rc;
+	/* Assign MAC address */
+	eth_hw_addr_set(net_dev, net_dev->perm_addr);
+	ether_addr_copy(nic_data->port_id, net_dev->perm_addr);
+
 	/* devlink creation, registration and lock */
 	rc = efx_probe_devlink_and_lock(efx);
 	if (rc)
diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index aa11f0925e27..aa48c79a2149 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -130,23 +130,34 @@ static void ef100_mcdi_reboot_detected(struct efx_nic *efx)
 
 /*	MCDI calls
  */
-static int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address)
+int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
+			  int client_handle, bool empty_ok)
 {
-	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
+	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1));
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_CLIENT_MAC_ADDRESSES_IN_LEN);
 	size_t outlen;
 	int rc;
 
 	BUILD_BUG_ON(MC_CMD_GET_MAC_ADDRESSES_IN_LEN != 0);
+	MCDI_SET_DWORD(inbuf, GET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
+		       client_handle);
 
-	rc = efx_mcdi_rpc(efx, MC_CMD_GET_MAC_ADDRESSES, NULL, 0,
-			  outbuf, sizeof(outbuf), &outlen);
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLIENT_MAC_ADDRESSES, inbuf,
+			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
 	if (rc)
 		return rc;
-	if (outlen < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)
-		return -EIO;
 
-	ether_addr_copy(mac_address,
-			MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE));
+	if (outlen >= MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1)) {
+		ether_addr_copy(mac_address,
+				MCDI_PTR(outbuf, GET_CLIENT_MAC_ADDRESSES_OUT_MAC_ADDRS));
+	} else if (empty_ok) {
+		pci_warn(efx->pci_dev,
+			 "No MAC address provisioned for client ID %#x.\n",
+			 client_handle);
+		eth_zero_addr(mac_address);
+	} else {
+		return -ENOENT;
+	}
 	return 0;
 }
 
@@ -1117,13 +1128,6 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
 	struct net_device *net_dev = efx->net_dev;
 	int rc;
 
-	rc = ef100_get_mac_address(efx, net_dev->perm_addr);
-	if (rc)
-		goto fail;
-	/* Assign MAC address */
-	eth_hw_addr_set(net_dev, net_dev->perm_addr);
-	memcpy(nic_data->port_id, net_dev->perm_addr, ETH_ALEN);
-
 	if (!nic_data->grp_mae)
 		return 0;
 
@@ -1163,9 +1167,6 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
 		efx->fixed_features |= NETIF_F_HW_TC;
 	}
 #endif
-	return 0;
-
-fail:
 	return rc;
 }
 
diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h
index 496aea43c60f..e59044072333 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.h
+++ b/drivers/net/ethernet/sfc/ef100_nic.h
@@ -92,4 +92,6 @@ int efx_ef100_init_datapath_caps(struct efx_nic *efx);
 int ef100_phy_probe(struct efx_nic *efx);
 int ef100_filter_table_probe(struct efx_nic *efx);
 
+int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
+			  int client_handle, bool empty_ok);
 #endif	/* EFX_EF100_NIC_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
                   ` (5 preceding siblings ...)
  2023-02-08 14:25 ` [PATCH v6 net-next 6/8] sfc: obtain device mac address based on firmware handle " alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-08 14:40   ` Jiri Pirko
  2023-02-10  8:52   ` Martin Habets
  2023-02-08 14:25 ` [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set " alejandro.lucero-palau
  7 siblings, 2 replies; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Using the builtin client handle id infrastructure, add support for
obtaining the mac address linked to mports in ef100. This implies
to execute an MCDI command for getting the data from the firmware
for each devlink port.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
---
 drivers/net/ethernet/sfc/ef100_nic.c   | 27 +++++++++++++++
 drivers/net/ethernet/sfc/ef100_nic.h   |  1 +
 drivers/net/ethernet/sfc/ef100_rep.c   |  8 +++++
 drivers/net/ethernet/sfc/ef100_rep.h   |  1 +
 drivers/net/ethernet/sfc/efx_devlink.c | 46 ++++++++++++++++++++++++++
 5 files changed, 83 insertions(+)

diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index aa48c79a2149..becd21c2325d 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -1122,6 +1122,33 @@ static int ef100_probe_main(struct efx_nic *efx)
 	return rc;
 }
 
+/* MCDI commands are related to the same device issuing them. This function
+ * allows to do an MCDI command on behalf of another device, mainly PFs setting
+ * things for VFs.
+ */
+int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id)
+{
+	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLIENT_HANDLE_OUT_LEN);
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_CLIENT_HANDLE_IN_LEN);
+	u64 pciefn_flat = le64_to_cpu(pciefn.u64[0]);
+	size_t outlen;
+	int rc;
+
+	MCDI_SET_DWORD(inbuf, GET_CLIENT_HANDLE_IN_TYPE,
+		       MC_CMD_GET_CLIENT_HANDLE_IN_TYPE_FUNC);
+	MCDI_SET_QWORD(inbuf, GET_CLIENT_HANDLE_IN_FUNC,
+		       pciefn_flat);
+
+	rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLIENT_HANDLE, inbuf, sizeof(inbuf),
+			  outbuf, sizeof(outbuf), &outlen);
+	if (rc)
+		return rc;
+	if (outlen < sizeof(outbuf))
+		return -EIO;
+	*id = MCDI_DWORD(outbuf, GET_CLIENT_HANDLE_OUT_HANDLE);
+	return 0;
+}
+
 int ef100_probe_netdev_pf(struct efx_nic *efx)
 {
 	struct ef100_nic_data *nic_data = efx->nic_data;
diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h
index e59044072333..f1ed481c1260 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.h
+++ b/drivers/net/ethernet/sfc/ef100_nic.h
@@ -94,4 +94,5 @@ int ef100_filter_table_probe(struct efx_nic *efx);
 
 int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
 			  int client_handle, bool empty_ok);
+int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id);
 #endif	/* EFX_EF100_NIC_H */
diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
index 6b5bc5d6955d..0b3083ef0ead 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.c
+++ b/drivers/net/ethernet/sfc/ef100_rep.c
@@ -361,6 +361,14 @@ bool ef100_mport_on_local_intf(struct efx_nic *efx,
 		     mport_desc->interface_idx == nic_data->local_mae_intf;
 }
 
+bool ef100_mport_is_vf(struct mae_mport_desc *mport_desc)
+{
+	bool pcie_func;
+
+	pcie_func = ef100_mport_is_pcie_vnic(mport_desc);
+	return pcie_func && (mport_desc->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL);
+}
+
 void efx_ef100_init_reps(struct efx_nic *efx)
 {
 	struct ef100_nic_data *nic_data = efx->nic_data;
diff --git a/drivers/net/ethernet/sfc/ef100_rep.h b/drivers/net/ethernet/sfc/ef100_rep.h
index ae6add4b0855..a042525a2240 100644
--- a/drivers/net/ethernet/sfc/ef100_rep.h
+++ b/drivers/net/ethernet/sfc/ef100_rep.h
@@ -76,4 +76,5 @@ void efx_ef100_fini_reps(struct efx_nic *efx);
 struct mae_mport_desc;
 bool ef100_mport_on_local_intf(struct efx_nic *efx,
 			       struct mae_mport_desc *mport_desc);
+bool ef100_mport_is_vf(struct mae_mport_desc *mport_desc);
 #endif /* EF100_REP_H */
diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index 1b1276716113..68d04c2176d3 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -11,6 +11,7 @@
 #include "efx_devlink.h"
 #ifdef CONFIG_SFC_SRIOV
 #include <linux/rtc.h>
+#include "ef100_nic.h"
 #include "mcdi.h"
 #include "mcdi_functions.h"
 #include "mcdi_pcol.h"
@@ -58,6 +59,50 @@ static int efx_devlink_add_port(struct efx_nic *efx,
 	return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
 }
 
+static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
+				     int *hw_addr_len,
+				     struct netlink_ext_ack *extack)
+{
+	struct efx_devlink *devlink = devlink_priv(port->devlink);
+	struct mae_mport_desc *mport_desc;
+	efx_qword_t pciefn;
+	u32 client_id;
+	int rc;
+
+	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
+
+	if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
+		NL_SET_ERR_MSG_MOD(extack, "Port not on local interface");
+		return -EINVAL;
+	}
+
+	if (ef100_mport_is_vf(mport_desc))
+		EFX_POPULATE_QWORD_3(pciefn,
+				     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
+				     PCIE_FUNCTION_VF, mport_desc->vf_idx,
+				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
+	else
+		EFX_POPULATE_QWORD_3(pciefn,
+				     PCIE_FUNCTION_PF, mport_desc->pf_idx,
+				     PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
+				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
+
+	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
+	if (rc) {
+		NL_SET_ERR_MSG_MOD(extack, "No internal client_ID for port");
+		return -EIO;
+	}
+
+	rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
+	if (rc) {
+		NL_SET_ERR_MSG_MOD(extack, "No MAC available");
+		return -ENOENT;
+	}
+
+	*hw_addr_len = ETH_ALEN;
+	return rc;
+}
+
 static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
 					    struct devlink_info_req *req,
 					    unsigned int partition_type,
@@ -511,6 +556,7 @@ static int efx_devlink_info_get(struct devlink *devlink,
 static const struct devlink_ops sfc_devlink_ops = {
 #ifdef CONFIG_SFC_SRIOV
 	.info_get			= efx_devlink_info_get,
+	.port_function_hw_addr_get	= efx_devlink_port_addr_get,
 #endif
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set in ef100
  2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
                   ` (6 preceding siblings ...)
  2023-02-08 14:25 ` [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100 alejandro.lucero-palau
@ 2023-02-08 14:25 ` alejandro.lucero-palau
  2023-02-08 14:40   ` Jiri Pirko
  2023-02-10  8:53   ` Martin Habets
  7 siblings, 2 replies; 25+ messages in thread
From: alejandro.lucero-palau @ 2023-02-08 14:25 UTC (permalink / raw)
  To: netdev, linux-net-drivers
  Cc: davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri, Alejandro Lucero

From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Using the builtin client handle id infrastructure, add support for
setting the mac address linked to mports in ef100. This implies to
execute an MCDI command for giving the address to the firmware for
the specific devlink port.

Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
---
 drivers/net/ethernet/sfc/efx_devlink.c | 42 ++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
index 68d04c2176d3..9fc2fe862303 100644
--- a/drivers/net/ethernet/sfc/efx_devlink.c
+++ b/drivers/net/ethernet/sfc/efx_devlink.c
@@ -103,6 +103,47 @@ static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
 	return rc;
 }
 
+static int efx_devlink_port_addr_set(struct devlink_port *port,
+				     const u8 *hw_addr, int hw_addr_len,
+				     struct netlink_ext_ack *extack)
+{
+	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1));
+	struct efx_devlink *devlink = devlink_priv(port->devlink);
+	struct mae_mport_desc *mport_desc;
+	efx_qword_t pciefn;
+	u32 client_id;
+	int rc;
+
+	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
+
+	if (!ef100_mport_is_vf(mport_desc)) {
+		NL_SET_ERR_MSG_MOD(extack, "Port MAC change not allowed");
+		return -EPERM;
+	}
+
+	EFX_POPULATE_QWORD_3(pciefn,
+			     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
+			     PCIE_FUNCTION_VF, mport_desc->vf_idx,
+			     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
+
+	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
+	if (rc) {
+		NL_SET_ERR_MSG_MOD(extack, "No internal client_ID");
+		return rc;
+	}
+
+	MCDI_SET_DWORD(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
+		       client_id);
+
+	ether_addr_copy(MCDI_PTR(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
+			hw_addr);
+
+	rc = efx_mcdi_rpc(devlink->efx, MC_CMD_SET_CLIENT_MAC_ADDRESSES, inbuf,
+			  sizeof(inbuf), NULL, 0, NULL);
+
+	return rc;
+}
+
 static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
 					    struct devlink_info_req *req,
 					    unsigned int partition_type,
@@ -557,6 +598,7 @@ static const struct devlink_ops sfc_devlink_ops = {
 #ifdef CONFIG_SFC_SRIOV
 	.info_get			= efx_devlink_info_get,
 	.port_function_hw_addr_get	= efx_devlink_port_addr_get,
+	.port_function_hw_addr_set	= efx_devlink_port_addr_set,
 #endif
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 2/8] sfc: add devlink info " alejandro.lucero-palau
@ 2023-02-08 14:38   ` Jiri Pirko
  2023-02-08 15:24     ` Lucero Palau, Alejandro
  2023-02-10  8:40   ` Martin Habets
  1 sibling, 1 reply; 25+ messages in thread
From: Jiri Pirko @ 2023-02-08 14:38 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	habetsm.xilinx, ecree.xilinx, linux-doc, corbet, jiri

Wed, Feb 08, 2023 at 03:25:13PM CET, alejandro.lucero-palau@amd.com wrote:
>From: Alejandro Lucero <alejandro.lucero-palau@amd.com>

[..]


>+static int efx_devlink_info_get(struct devlink *devlink,
>+				struct devlink_info_req *req,
>+				struct netlink_ext_ack *extack)
>+{
>+	struct efx_devlink *devlink_private = devlink_priv(devlink);
>+	struct efx_nic *efx = devlink_private->efx;
>+	int rc;
>+
>+	/* Several different MCDI commands are used. We report first error
>+	 * through extack along with total number of errors. Specific error
>+	 * information via system messages.

I think you forgot to remove this comment.

With this nit fixed, free free to add:
Reviewed-by: Jiri Pirko <jiri@nvidia.com>



>+	 */
>+	rc = efx_devlink_info_board_cfg(efx, req);
>+	if (rc) {
>+		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
>+		return rc;
>+	}
>+	rc = efx_devlink_info_stored_versions(efx, req);
>+	if (rc) {
>+		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
>+		return rc;
>+	}
>+	rc = efx_devlink_info_running_versions(efx, req);
>+	if (rc) {
>+		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
>+		return rc;
>+	}
>+
>+	return 0;
>+}
>+#endif

[..]


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100 alejandro.lucero-palau
@ 2023-02-08 14:40   ` Jiri Pirko
  2023-02-10  8:52   ` Martin Habets
  1 sibling, 0 replies; 25+ messages in thread
From: Jiri Pirko @ 2023-02-08 14:40 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	habetsm.xilinx, ecree.xilinx, linux-doc, corbet, jiri

Wed, Feb 08, 2023 at 03:25:18PM CET, alejandro.lucero-palau@amd.com wrote:
>From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>
>Using the builtin client handle id infrastructure, add support for
>obtaining the mac address linked to mports in ef100. This implies
>to execute an MCDI command for getting the data from the firmware
>for each devlink port.
>
>Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Reviewed-by: Jiri Pirko <jiri@nvidia.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set in ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set " alejandro.lucero-palau
@ 2023-02-08 14:40   ` Jiri Pirko
  2023-02-10  8:53   ` Martin Habets
  1 sibling, 0 replies; 25+ messages in thread
From: Jiri Pirko @ 2023-02-08 14:40 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	habetsm.xilinx, ecree.xilinx, linux-doc, corbet, jiri

Wed, Feb 08, 2023 at 03:25:19PM CET, alejandro.lucero-palau@amd.com wrote:
>From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>
>Using the builtin client handle id infrastructure, add support for
>setting the mac address linked to mports in ef100. This implies to
>execute an MCDI command for giving the address to the firmware for
>the specific devlink port.
>
>Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Reviewed-by: Jiri Pirko <jiri@nvidia.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-08 14:38   ` Jiri Pirko
@ 2023-02-08 15:24     ` Lucero Palau, Alejandro
  2023-02-09 10:46       ` Lucero Palau, Alejandro
  0 siblings, 1 reply; 25+ messages in thread
From: Lucero Palau, Alejandro @ 2023-02-08 15:24 UTC (permalink / raw)
  To: Jiri Pirko, Lucero Palau, Alejandro
  Cc: netdev, linux-net-drivers (AMD-Xilinx),
	davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri


On 2/8/23 14:38, Jiri Pirko wrote:
> Wed, Feb 08, 2023 at 03:25:13PM CET, alejandro.lucero-palau@amd.com wrote:
>> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> [..]
>
>
>> +static int efx_devlink_info_get(struct devlink *devlink,
>> +				struct devlink_info_req *req,
>> +				struct netlink_ext_ack *extack)
>> +{
>> +	struct efx_devlink *devlink_private = devlink_priv(devlink);
>> +	struct efx_nic *efx = devlink_private->efx;
>> +	int rc;
>> +
>> +	/* Several different MCDI commands are used. We report first error
>> +	 * through extack along with total number of errors. Specific error
>> +	 * information via system messages.
> I think you forgot to remove this comment.
>
> With this nit fixed, free free to add:
> Reviewed-by: Jiri Pirko <jiri@nvidia.com>
>

I'll do.

Thanks

>
>> +	 */
>> +	rc = efx_devlink_info_board_cfg(efx, req);
>> +	if (rc) {
>> +		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
>> +		return rc;
>> +	}
>> +	rc = efx_devlink_info_stored_versions(efx, req);
>> +	if (rc) {
>> +		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
>> +		return rc;
>> +	}
>> +	rc = efx_devlink_info_running_versions(efx, req);
>> +	if (rc) {
>> +		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
>> +		return rc;
>> +	}
>> +
>> +	return 0;
>> +}
>> +#endif
> [..]
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-08 15:24     ` Lucero Palau, Alejandro
@ 2023-02-09 10:46       ` Lucero Palau, Alejandro
  2023-02-10 11:56         ` Jiri Pirko
  0 siblings, 1 reply; 25+ messages in thread
From: Lucero Palau, Alejandro @ 2023-02-09 10:46 UTC (permalink / raw)
  To: Lucero Palau, Alejandro, Jiri Pirko
  Cc: netdev, linux-net-drivers (AMD-Xilinx),
	davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri


On 2/8/23 15:24, Lucero Palau, Alejandro wrote:
> On 2/8/23 14:38, Jiri Pirko wrote:
>> Wed, Feb 08, 2023 at 03:25:13PM CET, alejandro.lucero-palau@amd.com wrote:
>>> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>> [..]
>>
>>
>>> +static int efx_devlink_info_get(struct devlink *devlink,
>>> +				struct devlink_info_req *req,
>>> +				struct netlink_ext_ack *extack)
>>> +{
>>> +	struct efx_devlink *devlink_private = devlink_priv(devlink);
>>> +	struct efx_nic *efx = devlink_private->efx;
>>> +	int rc;
>>> +
>>> +	/* Several different MCDI commands are used. We report first error
>>> +	 * through extack along with total number of errors. Specific error
>>> +	 * information via system messages.
>> I think you forgot to remove this comment.
>>
>> With this nit fixed, free free to add:
>> Reviewed-by: Jiri Pirko <jiri@nvidia.com>
>>
> I'll do.
>
> Thanks

Just wondering if this single nit deserves a v7 or better to delay it as 
another patch.

We got another patchset for ef100 ready to be sent and we would prefer 
to not delay this one more than needed.

>>> +	 */
>>> +	rc = efx_devlink_info_board_cfg(efx, req);
>>> +	if (rc) {
>>> +		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
>>> +		return rc;
>>> +	}
>>> +	rc = efx_devlink_info_stored_versions(efx, req);
>>> +	if (rc) {
>>> +		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
>>> +		return rc;
>>> +	}
>>> +	rc = efx_devlink_info_running_versions(efx, req);
>>> +	if (rc) {
>>> +		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
>>> +		return rc;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +#endif
>> [..]
>>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 1/8] sfc: add devlink support for ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 1/8] sfc: add " alejandro.lucero-palau
@ 2023-02-10  8:28   ` Martin Habets
  0 siblings, 0 replies; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:28 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

On Wed, Feb 08, 2023 at 02:25:12PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> Add devlink infrastructure support. Further patches add devlink
> info and devlink port support.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> Reviewed-by: Jiri Pirko <jiri@nvidia.com>

Acked-by: Martin Habets <habetsm.xilinx@gmail.com>

> ---
>  drivers/net/ethernet/sfc/Kconfig        |  1 +
>  drivers/net/ethernet/sfc/Makefile       |  3 +-
>  drivers/net/ethernet/sfc/ef100_netdev.c | 10 ++++
>  drivers/net/ethernet/sfc/efx_devlink.c  | 64 +++++++++++++++++++++++++
>  drivers/net/ethernet/sfc/efx_devlink.h  | 22 +++++++++
>  drivers/net/ethernet/sfc/net_driver.h   |  2 +
>  6 files changed, 101 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/ethernet/sfc/efx_devlink.c
>  create mode 100644 drivers/net/ethernet/sfc/efx_devlink.h
> 
> diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
> index 0950e6b0508f..4af36ba8906b 100644
> --- a/drivers/net/ethernet/sfc/Kconfig
> +++ b/drivers/net/ethernet/sfc/Kconfig
> @@ -22,6 +22,7 @@ config SFC
>  	depends on PTP_1588_CLOCK_OPTIONAL
>  	select MDIO
>  	select CRC32
> +	select NET_DEVLINK
>  	help
>  	  This driver supports 10/40-gigabit Ethernet cards based on
>  	  the Solarflare SFC9100-family controllers.
> diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
> index 712a48d00069..55b9c73cd8ef 100644
> --- a/drivers/net/ethernet/sfc/Makefile
> +++ b/drivers/net/ethernet/sfc/Makefile
> @@ -6,7 +6,8 @@ sfc-y			+= efx.o efx_common.o efx_channels.o nic.o \
>  			   mcdi.o mcdi_port.o mcdi_port_common.o \
>  			   mcdi_functions.o mcdi_filters.o mcdi_mon.o \
>  			   ef100.o ef100_nic.o ef100_netdev.o \
> -			   ef100_ethtool.o ef100_rx.o ef100_tx.o
> +			   ef100_ethtool.o ef100_rx.o ef100_tx.o \
> +			   efx_devlink.o
>  sfc-$(CONFIG_SFC_MTD)	+= mtd.o
>  sfc-$(CONFIG_SFC_SRIOV)	+= sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \
>                             mae.o tc.o tc_bindings.o tc_counters.o
> diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
> index ddcc325ed570..6cf74788b27a 100644
> --- a/drivers/net/ethernet/sfc/ef100_netdev.c
> +++ b/drivers/net/ethernet/sfc/ef100_netdev.c
> @@ -24,6 +24,7 @@
>  #include "rx_common.h"
>  #include "ef100_sriov.h"
>  #include "tc_bindings.h"
> +#include "efx_devlink.h"
>  
>  static void ef100_update_name(struct efx_nic *efx)
>  {
> @@ -332,6 +333,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
>  		efx_ef100_pci_sriov_disable(efx, true);
>  #endif
>  
> +	efx_fini_devlink_lock(efx);
>  	ef100_unregister_netdev(efx);
>  
>  #ifdef CONFIG_SFC_SRIOV
> @@ -345,6 +347,8 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
>  	kfree(efx->phy_data);
>  	efx->phy_data = NULL;
>  
> +	efx_fini_devlink_and_unlock(efx);
> +
>  	free_netdev(efx->net_dev);
>  	efx->net_dev = NULL;
>  	efx->state = STATE_PROBED;
> @@ -405,6 +409,11 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>  	/* Don't fail init if RSS setup doesn't work. */
>  	efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);
>  
> +	/* devlink creation, registration and lock */
> +	rc = efx_probe_devlink_and_lock(efx);
> +	if (rc)
> +		pci_info(efx->pci_dev, "devlink registration failed");
> +
>  	rc = ef100_register_netdev(efx);
>  	if (rc)
>  		goto fail;
> @@ -424,5 +433,6 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>  	}
>  
>  fail:
> +	efx_probe_devlink_unlock(efx);
>  	return rc;
>  }
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
> new file mode 100644
> index 000000000000..57a7023d3cb6
> --- /dev/null
> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
> @@ -0,0 +1,64 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/****************************************************************************
> + * Driver for AMD network controllers and boards
> + * Copyright (C) 2023, Advanced Micro Devices, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation, incorporated herein by reference.
> + */
> +
> +#include "efx_devlink.h"
> +
> +struct efx_devlink {
> +	struct efx_nic *efx;
> +};
> +
> +static const struct devlink_ops sfc_devlink_ops = {
> +};
> +
> +void efx_fini_devlink_lock(struct efx_nic *efx)
> +{
> +	if (efx->devlink)
> +		devl_lock(efx->devlink);
> +}
> +
> +void efx_fini_devlink_and_unlock(struct efx_nic *efx)
> +{
> +	if (efx->devlink) {
> +		devl_unregister(efx->devlink);
> +		devl_unlock(efx->devlink);
> +		devlink_free(efx->devlink);
> +		efx->devlink = NULL;
> +	}
> +}
> +
> +int efx_probe_devlink_and_lock(struct efx_nic *efx)
> +{
> +	struct efx_devlink *devlink_private;
> +
> +	if (efx->type->is_vf)
> +		return 0;
> +
> +	efx->devlink = devlink_alloc(&sfc_devlink_ops,
> +				     sizeof(struct efx_devlink),
> +				     &efx->pci_dev->dev);
> +	if (!efx->devlink)
> +		return -ENOMEM;
> +
> +	devl_lock(efx->devlink);
> +	devlink_private = devlink_priv(efx->devlink);
> +	devlink_private->efx = efx;
> +
> +	devl_register(efx->devlink);
> +
> +	return 0;
> +}
> +
> +void efx_probe_devlink_unlock(struct efx_nic *efx)
> +{
> +	if (!efx->devlink)
> +		return;
> +
> +	devl_unlock(efx->devlink);
> +}
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
> new file mode 100644
> index 000000000000..8ff85b035e87
> --- /dev/null
> +++ b/drivers/net/ethernet/sfc/efx_devlink.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/****************************************************************************
> + * Driver for AMD network controllers and boards
> + * Copyright (C) 2023, Advanced Micro Devices, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation, incorporated herein by reference.
> + */
> +
> +#ifndef _EFX_DEVLINK_H
> +#define _EFX_DEVLINK_H
> +
> +#include "net_driver.h"
> +#include <net/devlink.h>
> +
> +int efx_probe_devlink_and_lock(struct efx_nic *efx);
> +void efx_probe_devlink_unlock(struct efx_nic *efx);
> +void efx_fini_devlink_lock(struct efx_nic *efx);
> +void efx_fini_devlink_and_unlock(struct efx_nic *efx);
> +
> +#endif	/* _EFX_DEVLINK_H */
> diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
> index 3b49e216768b..d036641dc043 100644
> --- a/drivers/net/ethernet/sfc/net_driver.h
> +++ b/drivers/net/ethernet/sfc/net_driver.h
> @@ -994,6 +994,7 @@ enum efx_xdp_tx_queues_mode {
>   *      xdp_rxq_info structures?
>   * @netdev_notifier: Netdevice notifier.
>   * @tc: state for TC offload (EF100).
> + * @devlink: reference to devlink structure owned by this device
>   * @mem_bar: The BAR that is mapped into membase.
>   * @reg_base: Offset from the start of the bar to the function control window.
>   * @monitor_work: Hardware monitor workitem
> @@ -1179,6 +1180,7 @@ struct efx_nic {
>  	struct notifier_block netdev_notifier;
>  	struct efx_tc_state *tc;
>  
> +	struct devlink *devlink;
>  	unsigned int mem_bar;
>  	u32 reg_base;
>  
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 2/8] sfc: add devlink info " alejandro.lucero-palau
  2023-02-08 14:38   ` Jiri Pirko
@ 2023-02-10  8:40   ` Martin Habets
  2023-02-10  9:07     ` Lucero Palau, Alejandro
  1 sibling, 1 reply; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:40 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

NAK, see below.

On Wed, Feb 08, 2023 at 02:25:13PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> Add devlink info support for ef100. The information reported is obtained
> through the MCDI interface with the specific meaning defined in new
> documentation file.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> ---
>  Documentation/networking/devlink/index.rst |   1 +
>  Documentation/networking/devlink/sfc.rst   |  57 +++
>  MAINTAINERS                                |   1 +
>  drivers/net/ethernet/sfc/efx_devlink.c     | 460 +++++++++++++++++++++
>  drivers/net/ethernet/sfc/efx_devlink.h     |  17 +
>  drivers/net/ethernet/sfc/mcdi.c            |  74 ++++
>  drivers/net/ethernet/sfc/mcdi.h            |   5 +
>  7 files changed, 615 insertions(+)
>  create mode 100644 Documentation/networking/devlink/sfc.rst
> 
> diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
> index fee4d3968309..b49749e2b9a6 100644
> --- a/Documentation/networking/devlink/index.rst
> +++ b/Documentation/networking/devlink/index.rst
> @@ -66,3 +66,4 @@ parameters, info versions, and other features it supports.
>     prestera
>     iosm
>     octeontx2
> +   sfc
> diff --git a/Documentation/networking/devlink/sfc.rst b/Documentation/networking/devlink/sfc.rst
> new file mode 100644
> index 000000000000..db64a1bd9733
> --- /dev/null
> +++ b/Documentation/networking/devlink/sfc.rst
> @@ -0,0 +1,57 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +===================
> +sfc devlink support
> +===================
> +
> +This document describes the devlink features implemented by the ``sfc``
> +device driver for the ef100 device.
> +
> +Info versions
> +=============
> +
> +The ``sfc`` driver reports the following versions
> +
> +.. list-table:: devlink info versions implemented
> +   :widths: 5 5 90
> +
> +   * - Name
> +     - Type
> +     - Description
> +   * - ``fw.mgmt.suc``
> +     - running
> +     - For boards where the management function is split between multiple
> +       control units, this is the SUC control unit's firmware version.
> +   * - ``fw.mgmt.cmc``
> +     - running
> +     - For boards where the management function is split between multiple
> +       control units, this is the CMC control unit's firmware version.
> +   * - ``fpga.rev``
> +     - running
> +     - FPGA design revision.
> +   * - ``fpga.app``
> +     - running
> +     - Datapath programmable logic version.
> +   * - ``fw.app``
> +     - running
> +     - Datapath software/microcode/firmware version.
> +   * - ``coproc.boot``
> +     - running
> +     - SmartNIC application co-processor (APU) first stage boot loader version.
> +   * - ``coproc.uboot``
> +     - running
> +     - SmartNIC application co-processor (APU) co-operating system loader version.
> +   * - ``coproc.main``
> +     - running
> +     - SmartNIC application co-processor (APU) main operating system version.
> +   * - ``coproc.recovery``
> +     - running
> +     - SmartNIC application co-processor (APU) recovery operating system version.
> +   * - ``fw.exprom``
> +     - running
> +     - Expansion ROM version. For boards where the expansion ROM is split between
> +       multiple images (e.g. PXE and UEFI), this is the specifically the PXE boot
> +       ROM version.
> +   * - ``fw.uefi``
> +     - running
> +     - UEFI driver version (No UNDI support).
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2cf9eb43ed8f..51f7d3448295 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -18937,6 +18937,7 @@ M:	Edward Cree <ecree.xilinx@gmail.com>
>  M:	Martin Habets <habetsm.xilinx@gmail.com>
>  L:	netdev@vger.kernel.org
>  S:	Supported
> +F:	Documentation/networking/devlink/sfc.rst
>  F:	drivers/net/ethernet/sfc/
>  
>  SFF/SFP/SFP+ MODULE SUPPORT
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
> index 57a7023d3cb6..c06efeac11e5 100644
> --- a/drivers/net/ethernet/sfc/efx_devlink.c
> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
> @@ -9,12 +9,472 @@
>   */
>  
>  #include "efx_devlink.h"
> +#ifdef CONFIG_SFC_SRIOV

I don't get this SRIOV dependency. In the cover letter you say it
was because of IA64, bu those errors were:

ia64-linux-ld: drivers/net/ethernet/sfc/ef100_nic.o: in function `ef100_remove':
 ef100_nic.c:(.text+0x2e82): undefined reference to `efx_ef100_fini_reps'
 ia64-linux-ld: ef100_nic.c:(.text+0x2e92): undefined reference to `efx_fini_mae'

which is completely unrelated to this patch.
This extra ifdef must not be needed at all. I suspect something else
is going wrong in your builds.
Please explain in detail why you think you need this.

Martin

> +#include <linux/rtc.h>
> +#include "mcdi.h"
> +#include "mcdi_functions.h"
> +#include "mcdi_pcol.h"
> +#endif
>  
>  struct efx_devlink {
>  	struct efx_nic *efx;
>  };
>  
> +#ifdef CONFIG_SFC_SRIOV
> +static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
> +					    struct devlink_info_req *req,
> +					    unsigned int partition_type,
> +					    const char *version_name)
> +{
> +	char buf[EFX_MAX_VERSION_INFO_LEN];
> +	u16 version[4];
> +	int rc;
> +
> +	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
> +				     0);
> +	if (rc) {
> +		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
> +			  version_name);
> +		return rc;
> +	}
> +
> +	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
> +		 version[1], version[2], version[3]);
> +	devlink_info_version_stored_put(req, version_name, buf);
> +
> +	return 0;
> +}
> +
> +static int efx_devlink_info_stored_versions(struct efx_nic *efx,
> +					    struct devlink_info_req *req)
> +{
> +	int rc;
> +
> +	rc = efx_devlink_info_nvram_partition(efx, req,
> +					      NVRAM_PARTITION_TYPE_BUNDLE,
> +					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
> +	if (rc)
> +		return rc;
> +
> +	rc = efx_devlink_info_nvram_partition(efx, req,
> +					      NVRAM_PARTITION_TYPE_MC_FIRMWARE,
> +					      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
> +	if (rc)
> +		return rc;
> +
> +	rc = efx_devlink_info_nvram_partition(efx, req,
> +					      NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
> +					      EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
> +	if (rc)
> +		return rc;
> +
> +	rc = efx_devlink_info_nvram_partition(efx, req,
> +					      NVRAM_PARTITION_TYPE_EXPANSION_ROM,
> +					      EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
> +	if (rc)
> +		return rc;
> +
> +	rc = efx_devlink_info_nvram_partition(efx, req,
> +					      NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
> +					      EFX_DEVLINK_INFO_VERSION_FW_UEFI);
> +	if (rc)
> +		return rc;
> +
> +	return 0;
> +}
> +
> +#define EFX_VER_FLAG(_f)	\
> +	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
> +
> +static void efx_devlink_info_running_v2(struct efx_nic *efx,
> +					struct devlink_info_req *req,
> +					unsigned int flags, efx_dword_t *outbuf)
> +{
> +	char buf[EFX_MAX_VERSION_INFO_LEN];
> +	union {
> +		const __le32 *dwords;
> +		const __le16 *words;
> +		const char *str;
> +	} ver;
> +	struct rtc_time build_date;
> +	unsigned int build_id;
> +	size_t offset;
> +	u64 tstamp;
> +
> +	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
> +			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
> +		devlink_info_version_fixed_put(req,
> +					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
> +					       buf);
> +
> +		/* Favour full board version if present (in V5 or later) */
> +		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
> +			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
> +				 MCDI_DWORD(outbuf,
> +					    GET_VERSION_V2_OUT_BOARD_REVISION));
> +			devlink_info_version_fixed_put(req,
> +						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
> +						       buf);
> +		}
> +
> +		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
> +		if (ver.str[0])
> +			devlink_info_board_serial_number_put(req, ver.str);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V2_OUT_FPGA_VERSION);
> +		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
> +				  le32_to_cpu(ver.dwords[0]),
> +				  'A' + le32_to_cpu(ver.dwords[1]),
> +				  le32_to_cpu(ver.dwords[2]));
> +
> +		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
> +		if (ver.str[0])
> +			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
> +				 " (%s)", ver.str);
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
> +						 buf);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V2_OUT_CMCFW_VERSION);
> +		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +				  le32_to_cpu(ver.dwords[0]),
> +				  le32_to_cpu(ver.dwords[1]),
> +				  le32_to_cpu(ver.dwords[2]),
> +				  le32_to_cpu(ver.dwords[3]));
> +
> +		tstamp = MCDI_QWORD(outbuf,
> +				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
> +		if (tstamp) {
> +			rtc_time64_to_tm(tstamp, &build_date);
> +			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
> +				 " (%ptRd)", &build_date);
> +		}
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
> +						 buf);
> +	}
> +
> +	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
> +	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
> +			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
> +	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
> +		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
> +		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
> +			 " (%x) %s", build_id,
> +			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
> +	}
> +	devlink_info_version_running_put(req,
> +					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
> +					 buf);
> +
> +	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V2_OUT_SUCFW_VERSION);
> +		tstamp = MCDI_QWORD(outbuf,
> +				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
> +		rtc_time64_to_tm(tstamp, &build_date);
> +		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
> +			 "%u.%u.%u.%u type %x (%ptRd)",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
> +			 build_id, &build_date);
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
> +						 buf);
> +	}
> +}
> +
> +static void efx_devlink_info_running_v3(struct efx_nic *efx,
> +					struct devlink_info_req *req,
> +					unsigned int flags, efx_dword_t *outbuf)
> +{
> +	char buf[EFX_MAX_VERSION_INFO_LEN];
> +	union {
> +		const __le32 *dwords;
> +		const __le16 *words;
> +		const char *str;
> +	} ver;
> +
> +	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]));
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
> +						 buf);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]));
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
> +						 buf);
> +	}
> +}
> +
> +static void efx_devlink_info_running_v4(struct efx_nic *efx,
> +					struct devlink_info_req *req,
> +					unsigned int flags, efx_dword_t *outbuf)
> +{
> +	char buf[EFX_MAX_VERSION_INFO_LEN];
> +	union {
> +		const __le32 *dwords;
> +		const __le16 *words;
> +		const char *str;
> +	} ver;
> +
> +	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]),
> +			 le32_to_cpu(ver.dwords[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
> +						 buf);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]),
> +			 le32_to_cpu(ver.dwords[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
> +						 buf);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]),
> +			 le32_to_cpu(ver.dwords[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
> +						 buf);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]),
> +			 le32_to_cpu(ver.dwords[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
> +						 buf);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
> +	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V4_OUT_SUCFW_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]),
> +			 le32_to_cpu(ver.dwords[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
> +						 buf);
> +	}
> +}
> +
> +static void efx_devlink_info_running_v5(struct efx_nic *efx,
> +					struct devlink_info_req *req,
> +					unsigned int flags, efx_dword_t *outbuf)
> +{
> +	char buf[EFX_MAX_VERSION_INFO_LEN];
> +	union {
> +		const __le32 *dwords;
> +		const __le16 *words;
> +		const char *str;
> +	} ver;
> +
> +	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V5_OUT_BOARD_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]),
> +			 le32_to_cpu(ver.dwords[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
> +						 buf);
> +	}
> +
> +	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
> +						GET_VERSION_V5_OUT_BUNDLE_VERSION);
> +
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
> +			 le32_to_cpu(ver.dwords[2]),
> +			 le32_to_cpu(ver.dwords[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
> +						 buf);
> +	}
> +}
> +
> +static int efx_devlink_info_running_versions(struct efx_nic *efx,
> +					     struct devlink_info_req *req)
> +{
> +	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
> +	char buf[EFX_MAX_VERSION_INFO_LEN];
> +	union {
> +		const __le32 *dwords;
> +		const __le16 *words;
> +		const char *str;
> +	} ver;
> +	size_t outlength;
> +	unsigned int flags;
> +	int rc;
> +
> +	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
> +			  outbuf, sizeof(outbuf), &outlength);
> +	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
> +		netif_err(efx, drv, efx->net_dev,
> +			  "mcdi MC_CMD_GET_VERSION failed\n");
> +		return rc;
> +	}
> +
> +	/* Handle previous output */
> +	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
> +		ver.words = (__le16 *)MCDI_PTR(outbuf,
> +					       GET_VERSION_EXT_OUT_VERSION);
> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
> +			 le16_to_cpu(ver.words[0]),
> +			 le16_to_cpu(ver.words[1]),
> +			 le16_to_cpu(ver.words[2]),
> +			 le16_to_cpu(ver.words[3]));
> +
> +		devlink_info_version_running_put(req,
> +						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
> +						 buf);
> +		return 0;
> +	}
> +
> +	/* Handle V2 additions */
> +	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
> +	efx_devlink_info_running_v2(efx, req, flags, outbuf);
> +
> +	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
> +		return 0;
> +
> +	/* Handle V3 additions */
> +	efx_devlink_info_running_v3(efx, req, flags, outbuf);
> +
> +	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
> +		return 0;
> +
> +	/* Handle V4 additions */
> +	efx_devlink_info_running_v4(efx, req, flags, outbuf);
> +
> +	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
> +		return 0;
> +
> +	/* Handle V5 additions */
> +	efx_devlink_info_running_v5(efx, req, flags, outbuf);
> +
> +	return 0;
> +}
> +
> +#define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
> +
> +static int efx_devlink_info_board_cfg(struct efx_nic *efx,
> +				      struct devlink_info_req *req)
> +{
> +	char sn[EFX_MAX_SERIALNUM_LEN];
> +	u8 mac_address[ETH_ALEN];
> +	int rc;
> +
> +	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
> +	if (!rc) {
> +		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
> +		devlink_info_serial_number_put(req, sn);
> +	}
> +	return rc;
> +}
> +
> +static int efx_devlink_info_get(struct devlink *devlink,
> +				struct devlink_info_req *req,
> +				struct netlink_ext_ack *extack)
> +{
> +	struct efx_devlink *devlink_private = devlink_priv(devlink);
> +	struct efx_nic *efx = devlink_private->efx;
> +	int rc;
> +
> +	/* Several different MCDI commands are used. We report first error
> +	 * through extack along with total number of errors. Specific error
> +	 * information via system messages.
> +	 */
> +	rc = efx_devlink_info_board_cfg(efx, req);
> +	if (rc) {
> +		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
> +		return rc;
> +	}
> +	rc = efx_devlink_info_stored_versions(efx, req);
> +	if (rc) {
> +		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
> +		return rc;
> +	}
> +	rc = efx_devlink_info_running_versions(efx, req);
> +	if (rc) {
> +		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
> +		return rc;
> +	}
> +
> +	return 0;
> +}
> +#endif
> +
>  static const struct devlink_ops sfc_devlink_ops = {
> +#ifdef CONFIG_SFC_SRIOV
> +	.info_get			= efx_devlink_info_get,
> +#endif
>  };
>  
>  void efx_fini_devlink_lock(struct efx_nic *efx)
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
> index 8ff85b035e87..a5269361c3e0 100644
> --- a/drivers/net/ethernet/sfc/efx_devlink.h
> +++ b/drivers/net/ethernet/sfc/efx_devlink.h
> @@ -14,6 +14,23 @@
>  #include "net_driver.h"
>  #include <net/devlink.h>
>  
> +/* Custom devlink-info version object names for details that do not map to the
> + * generic standardized names.
> + */
> +#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC	"fw.mgmt.suc"
> +#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC	"fw.mgmt.cmc"
> +#define EFX_DEVLINK_INFO_VERSION_FPGA_REV	"fpga.rev"
> +#define EFX_DEVLINK_INFO_VERSION_DATAPATH_HW	"fpga.app"
> +#define EFX_DEVLINK_INFO_VERSION_DATAPATH_FW	DEVLINK_INFO_VERSION_GENERIC_FW_APP
> +#define EFX_DEVLINK_INFO_VERSION_SOC_BOOT	"coproc.boot"
> +#define EFX_DEVLINK_INFO_VERSION_SOC_UBOOT	"coproc.uboot"
> +#define EFX_DEVLINK_INFO_VERSION_SOC_MAIN	"coproc.main"
> +#define EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY	"coproc.recovery"
> +#define EFX_DEVLINK_INFO_VERSION_FW_EXPROM	"fw.exprom"
> +#define EFX_DEVLINK_INFO_VERSION_FW_UEFI	"fw.uefi"
> +
> +#define EFX_MAX_VERSION_INFO_LEN	64
> +
>  int efx_probe_devlink_and_lock(struct efx_nic *efx);
>  void efx_probe_devlink_unlock(struct efx_nic *efx);
>  void efx_fini_devlink_lock(struct efx_nic *efx);
> diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
> index af338208eae9..2442e33225a6 100644
> --- a/drivers/net/ethernet/sfc/mcdi.c
> +++ b/drivers/net/ethernet/sfc/mcdi.c
> @@ -2175,6 +2175,80 @@ int efx_mcdi_get_privilege_mask(struct efx_nic *efx, u32 *mask)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_SFC_SRIOV
> +int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
> +			    u32 *subtype, u16 version[4], char *desc,
> +			    size_t descsize)
> +{
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
> +	efx_dword_t *outbuf;
> +	size_t outlen;
> +	u32 flags;
> +	int rc;
> +
> +	outbuf = kzalloc(MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2, GFP_KERNEL);
> +	if (!outbuf)
> +		return -ENOMEM;
> +
> +	MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
> +
> +	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_NVRAM_METADATA, inbuf,
> +				sizeof(inbuf), outbuf,
> +				MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2,
> +				&outlen);
> +	if (rc)
> +		goto out_free;
> +	if (outlen < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
> +		rc = -EIO;
> +		goto out_free;
> +	}
> +
> +	flags = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_FLAGS);
> +
> +	if (desc && descsize > 0) {
> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_VALID_LBN)) {
> +			if (descsize <=
> +			    MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)) {
> +				rc = -E2BIG;
> +				goto out_free;
> +			}
> +
> +			strncpy(desc,
> +				MCDI_PTR(outbuf, NVRAM_METADATA_OUT_DESCRIPTION),
> +				MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen));
> +			desc[MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)] = '\0';
> +		} else {
> +			desc[0] = '\0';
> +		}
> +	}
> +
> +	if (subtype) {
> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_SUBTYPE_VALID_LBN))
> +			*subtype = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_SUBTYPE);
> +		else
> +			*subtype = 0;
> +	}
> +
> +	if (version) {
> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_VERSION_VALID_LBN)) {
> +			version[0] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_W);
> +			version[1] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_X);
> +			version[2] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Y);
> +			version[3] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Z);
> +		} else {
> +			version[0] = 0;
> +			version[1] = 0;
> +			version[2] = 0;
> +			version[3] = 0;
> +		}
> +	}
> +
> +out_free:
> +	kfree(outbuf);
> +	return rc;
> +}
> +#endif
> +
>  #ifdef CONFIG_SFC_MTD
>  
>  #define EFX_MCDI_NVRAM_LEN_MAX 128
> diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
> index 7e35fec9da35..32f54ce2492e 100644
> --- a/drivers/net/ethernet/sfc/mcdi.h
> +++ b/drivers/net/ethernet/sfc/mcdi.h
> @@ -378,6 +378,11 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
>  			size_t *size_out, size_t *erase_size_out,
>  			bool *protected_out);
>  int efx_new_mcdi_nvram_test_all(struct efx_nic *efx);
> +#ifdef CONFIG_SFC_SRIOV
> +int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
> +			    u32 *subtype, u16 version[4], char *desc,
> +			    size_t descsize);
> +#endif
>  int efx_mcdi_nvram_test_all(struct efx_nic *efx);
>  int efx_mcdi_handle_assertion(struct efx_nic *efx);
>  int efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 3/8] sfc: enumerate mports in ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 3/8] sfc: enumerate mports in ef100 alejandro.lucero-palau
@ 2023-02-10  8:46   ` Martin Habets
  0 siblings, 0 replies; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:46 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

On Wed, Feb 08, 2023 at 02:25:14PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> MAE ports (mports) are the ports on the EF100 embedded switch such
> as networking PCIe functions, the physical port, and potentially
> others.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Acked-by: Martin Habets <habetsm.xilinx@gmail.com>

I can see this patch uses ifdef CONFIG_SFC_SRIOV, which makes sense
to me as it is for for devlink port.
The previous patch [2/8] is for devlink dev info, which must always
work. Even without SRIOV.

> ---
>  drivers/net/ethernet/sfc/ef100_nic.c  |  27 ++++
>  drivers/net/ethernet/sfc/ef100_nic.h  |   4 +
>  drivers/net/ethernet/sfc/ef100_rep.c  |  22 +++
>  drivers/net/ethernet/sfc/ef100_rep.h  |   2 +
>  drivers/net/ethernet/sfc/mae.c        | 191 ++++++++++++++++++++++++++
>  drivers/net/ethernet/sfc/mae.h        |  36 +++++
>  drivers/net/ethernet/sfc/mcdi.h       |   5 +
>  drivers/net/ethernet/sfc/net_driver.h |   4 +
>  8 files changed, 291 insertions(+)
> 
> diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
> index ad686c671ab8..07e7dca0e4f2 100644
> --- a/drivers/net/ethernet/sfc/ef100_nic.c
> +++ b/drivers/net/ethernet/sfc/ef100_nic.c
> @@ -747,6 +747,19 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
>  			   id);
>  	nic_data->base_mport = id;
>  	nic_data->have_mport = true;
> +
> +	/* Construct mport selector for "calling PF" */
> +	efx_mae_mport_uplink(efx, &selector);
> +	/* Look up actual mport ID */
> +	rc = efx_mae_lookup_mport(efx, selector, &id);
> +	if (rc)
> +		return rc;
> +	if (id >> 16)
> +		netif_warn(efx, probe, efx->net_dev, "Bad own m-port id %#x\n",
> +			   id);
> +	nic_data->own_mport = id;
> +	nic_data->have_own_mport = true;
> +
>  	return 0;
>  }
>  #endif
> @@ -1126,6 +1139,14 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
>  			   rc);
>  	}
>  
> +	rc = efx_init_mae(efx);
> +	if (rc)
> +		netif_warn(efx, probe, net_dev,
> +			   "Failed to init MAE rc %d; representors will not function\n",
> +			   rc);
> +	else
> +		efx_ef100_init_reps(efx);
> +
>  	rc = efx_init_tc(efx);
>  	if (rc) {
>  		/* Either we don't have an MAE at all (i.e. legacy v-switching),
> @@ -1157,6 +1178,12 @@ void ef100_remove(struct efx_nic *efx)
>  {
>  	struct ef100_nic_data *nic_data = efx->nic_data;
>  
> +#ifdef CONFIG_SFC_SRIOV
> +	if (efx->mae) {
> +		efx_ef100_fini_reps(efx);
> +		efx_fini_mae(efx);
> +	}
> +#endif
>  	efx_mcdi_detach(efx);
>  	efx_mcdi_fini(efx);
>  	if (nic_data)
> diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h
> index 0295933145fa..496aea43c60f 100644
> --- a/drivers/net/ethernet/sfc/ef100_nic.h
> +++ b/drivers/net/ethernet/sfc/ef100_nic.h
> @@ -74,6 +74,10 @@ struct ef100_nic_data {
>  	u64 stats[EF100_STAT_COUNT];
>  	u32 base_mport;
>  	bool have_mport; /* base_mport was populated successfully */
> +	u32 own_mport;
> +	u32 local_mae_intf; /* interface_idx that corresponds to us, in mport enumerate */
> +	bool have_own_mport; /* own_mport was populated successfully */
> +	bool have_local_intf; /* local_mae_intf was populated successfully */
>  	bool grp_mae; /* MAE Privilege */
>  	u16 tso_max_hdr_len;
>  	u16 tso_max_payload_num_segs;
> diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
> index 81ab22c74635..ebe7b1275713 100644
> --- a/drivers/net/ethernet/sfc/ef100_rep.c
> +++ b/drivers/net/ethernet/sfc/ef100_rep.c
> @@ -9,6 +9,7 @@
>   * by the Free Software Foundation, incorporated herein by reference.
>   */
>  
> +#include <linux/rhashtable.h>
>  #include "ef100_rep.h"
>  #include "ef100_netdev.h"
>  #include "ef100_nic.h"
> @@ -341,6 +342,27 @@ void efx_ef100_fini_vfreps(struct efx_nic *efx)
>  		efx_ef100_vfrep_destroy(efx, efv);
>  }
>  
> +void efx_ef100_init_reps(struct efx_nic *efx)
> +{
> +	struct ef100_nic_data *nic_data = efx->nic_data;
> +	int rc;
> +
> +	nic_data->have_local_intf = false;
> +	rc = efx_mae_enumerate_mports(efx);
> +	if (rc)
> +		pci_warn(efx->pci_dev,
> +			 "Could not enumerate mports (rc=%d), are we admin?",
> +			 rc);
> +}
> +
> +void efx_ef100_fini_reps(struct efx_nic *efx)
> +{
> +	struct efx_mae *mae = efx->mae;
> +
> +	rhashtable_free_and_destroy(&mae->mports_ht, efx_mae_remove_mport,
> +				    NULL);
> +}
> +
>  static int efx_ef100_rep_poll(struct napi_struct *napi, int weight)
>  {
>  	struct efx_rep *efv = container_of(napi, struct efx_rep, napi);
> diff --git a/drivers/net/ethernet/sfc/ef100_rep.h b/drivers/net/ethernet/sfc/ef100_rep.h
> index c21bc716f847..328ac0cbb532 100644
> --- a/drivers/net/ethernet/sfc/ef100_rep.h
> +++ b/drivers/net/ethernet/sfc/ef100_rep.h
> @@ -67,4 +67,6 @@ void efx_ef100_rep_rx_packet(struct efx_rep *efv, struct efx_rx_buffer *rx_buf);
>   */
>  struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport);
>  extern const struct net_device_ops efx_ef100_rep_netdev_ops;
> +void efx_ef100_init_reps(struct efx_nic *efx);
> +void efx_ef100_fini_reps(struct efx_nic *efx);
>  #endif /* EF100_REP_H */
> diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
> index 583baf69981c..725a3ab31087 100644
> --- a/drivers/net/ethernet/sfc/mae.c
> +++ b/drivers/net/ethernet/sfc/mae.c
> @@ -9,8 +9,11 @@
>   * by the Free Software Foundation, incorporated herein by reference.
>   */
>  
> +#include <linux/rhashtable.h>
> +#include "ef100_nic.h"
>  #include "mae.h"
>  #include "mcdi.h"
> +#include "mcdi_pcol.h"
>  #include "mcdi_pcol_mae.h"
>  
>  int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
> @@ -490,6 +493,163 @@ static bool efx_mae_asl_id(u32 id)
>  	return !!(id & BIT(31));
>  }
>  
> +/* mport handling */
> +static const struct rhashtable_params efx_mae_mports_ht_params = {
> +	.key_len	= sizeof(u32),
> +	.key_offset	= offsetof(struct mae_mport_desc, mport_id),
> +	.head_offset	= offsetof(struct mae_mport_desc, linkage),
> +};
> +
> +struct mae_mport_desc *efx_mae_get_mport(struct efx_nic *efx, u32 mport_id)
> +{
> +	return rhashtable_lookup_fast(&efx->mae->mports_ht, &mport_id,
> +				      efx_mae_mports_ht_params);
> +}
> +
> +static int efx_mae_add_mport(struct efx_nic *efx, struct mae_mport_desc *desc)
> +{
> +	struct efx_mae *mae = efx->mae;
> +	int rc;
> +
> +	rc = rhashtable_insert_fast(&mae->mports_ht, &desc->linkage,
> +				    efx_mae_mports_ht_params);
> +
> +	if (rc) {
> +		pci_err(efx->pci_dev, "Failed to insert MPORT %08x, rc %d\n",
> +			desc->mport_id, rc);
> +		kfree(desc);
> +		return rc;
> +	}
> +
> +	return rc;
> +}
> +
> +void efx_mae_remove_mport(void *desc, void *arg)
> +{
> +	struct mae_mport_desc *mport = desc;
> +
> +	synchronize_rcu();
> +	kfree(mport);
> +}
> +
> +static int efx_mae_process_mport(struct efx_nic *efx,
> +				 struct mae_mport_desc *desc)
> +{
> +	struct ef100_nic_data *nic_data = efx->nic_data;
> +	struct mae_mport_desc *mport;
> +
> +	mport = efx_mae_get_mport(efx, desc->mport_id);
> +	if (!IS_ERR_OR_NULL(mport)) {
> +		netif_err(efx, drv, efx->net_dev,
> +			  "mport with id %u does exist!!!\n", desc->mport_id);
> +		return -EEXIST;
> +	}
> +
> +	if (nic_data->have_own_mport &&
> +	    desc->mport_id == nic_data->own_mport) {
> +		WARN_ON(desc->mport_type != MAE_MPORT_DESC_MPORT_TYPE_VNIC);
> +		WARN_ON(desc->vnic_client_type !=
> +			MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION);
> +		nic_data->local_mae_intf = desc->interface_idx;
> +		nic_data->have_local_intf = true;
> +		pci_dbg(efx->pci_dev, "MAE interface_idx is %u\n",
> +			nic_data->local_mae_intf);
> +	}
> +
> +	return efx_mae_add_mport(efx, desc);
> +}
> +
> +#define MCDI_MPORT_JOURNAL_LEN \
> +	ALIGN(MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2, 4)
> +
> +int efx_mae_enumerate_mports(struct efx_nic *efx)
> +{
> +	efx_dword_t *outbuf = kzalloc(MCDI_MPORT_JOURNAL_LEN, GFP_KERNEL);
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN);
> +	MCDI_DECLARE_STRUCT_PTR(desc);
> +	size_t outlen, stride, count;
> +	int rc = 0, i;
> +
> +	if (!outbuf)
> +		return -ENOMEM;
> +	do {
> +		rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_READ_JOURNAL, inbuf,
> +				  sizeof(inbuf), outbuf,
> +				  MCDI_MPORT_JOURNAL_LEN, &outlen);
> +		if (rc)
> +			goto fail;
> +		if (outlen < MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_OFST) {
> +			rc = -EIO;
> +			goto fail;
> +		}
> +		count = MCDI_DWORD(outbuf, MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT);
> +		if (!count)
> +			continue; /* not break; we want to look at MORE flag */
> +		stride = MCDI_DWORD(outbuf, MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC);
> +		if (stride < MAE_MPORT_DESC_LEN) {
> +			rc = -EIO;
> +			goto fail;
> +		}
> +		if (outlen < MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LEN(count * stride)) {
> +			rc = -EIO;
> +			goto fail;
> +		}
> +
> +		for (i = 0; i < count; i++) {
> +			struct mae_mport_desc *d;
> +
> +			d = kzalloc(sizeof(*d), GFP_KERNEL);
> +			if (!d) {
> +				rc = -ENOMEM;
> +				goto fail;
> +			}
> +
> +			desc = (efx_dword_t *)
> +				_MCDI_PTR(outbuf, MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_OFST +
> +					  i * stride);
> +			d->mport_id = MCDI_STRUCT_DWORD(desc, MAE_MPORT_DESC_MPORT_ID);
> +			d->flags = MCDI_STRUCT_DWORD(desc, MAE_MPORT_DESC_FLAGS);
> +			d->caller_flags = MCDI_STRUCT_DWORD(desc,
> +							    MAE_MPORT_DESC_CALLER_FLAGS);
> +			d->mport_type = MCDI_STRUCT_DWORD(desc,
> +							  MAE_MPORT_DESC_MPORT_TYPE);
> +			switch (d->mport_type) {
> +			case MAE_MPORT_DESC_MPORT_TYPE_NET_PORT:
> +				d->port_idx = MCDI_STRUCT_DWORD(desc,
> +								MAE_MPORT_DESC_NET_PORT_IDX);
> +				break;
> +			case MAE_MPORT_DESC_MPORT_TYPE_ALIAS:
> +				d->alias_mport_id = MCDI_STRUCT_DWORD(desc,
> +								      MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID);
> +				break;
> +			case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
> +				d->vnic_client_type = MCDI_STRUCT_DWORD(desc,
> +									MAE_MPORT_DESC_VNIC_CLIENT_TYPE);
> +				d->interface_idx = MCDI_STRUCT_DWORD(desc,
> +								     MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE);
> +				d->pf_idx = MCDI_STRUCT_WORD(desc,
> +							     MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX);
> +			d->vf_idx = MCDI_STRUCT_WORD(desc,
> +						     MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX);
> +				break;
> +			default:
> +				/* Unknown mport_type, just accept it */
> +				break;
> +			}
> +			rc = efx_mae_process_mport(efx, d);
> +			/* Any failure will be due to memory allocation faiure,
> +			 * so there is no point to try subsequent entries.
> +			 */
> +			if (rc)
> +				goto fail;
> +		}
> +	} while (MCDI_FIELD(outbuf, MAE_MPORT_READ_JOURNAL_OUT, MORE) &&
> +		 !WARN_ON(!count));
> +fail:
> +	kfree(outbuf);
> +	return rc;
> +}
> +
>  int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act)
>  {
>  	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
> @@ -805,3 +965,34 @@ int efx_mae_delete_rule(struct efx_nic *efx, u32 id)
>  		return -EIO;
>  	return 0;
>  }
> +
> +int efx_init_mae(struct efx_nic *efx)
> +{
> +	struct ef100_nic_data *nic_data = efx->nic_data;
> +	struct efx_mae *mae;
> +	int rc;
> +
> +	if (!nic_data->have_mport)
> +		return -EINVAL;
> +
> +	mae = kmalloc(sizeof(*mae), GFP_KERNEL);
> +	if (!mae)
> +		return -ENOMEM;
> +
> +	rc = rhashtable_init(&mae->mports_ht, &efx_mae_mports_ht_params);
> +	if (rc < 0) {
> +		kfree(mae);
> +		return rc;
> +	}
> +	efx->mae = mae;
> +	mae->efx = efx;
> +	return 0;
> +}
> +
> +void efx_fini_mae(struct efx_nic *efx)
> +{
> +	struct efx_mae *mae = efx->mae;
> +
> +	kfree(mae);
> +	efx->mae = NULL;
> +}
> diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
> index 72343e90e222..daa29d2cde96 100644
> --- a/drivers/net/ethernet/sfc/mae.h
> +++ b/drivers/net/ethernet/sfc/mae.h
> @@ -27,6 +27,39 @@ void efx_mae_mport_mport(struct efx_nic *efx, u32 mport_id, u32 *out);
>  
>  int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id);
>  
> +struct mae_mport_desc {
> +	u32 mport_id;
> +	u32 flags;
> +	u32 caller_flags; /* enum mae_mport_desc_caller_flags */
> +	u32 mport_type; /* MAE_MPORT_DESC_MPORT_TYPE_* */
> +	union {
> +		u32 port_idx; /* for mport_type == NET_PORT */
> +		u32 alias_mport_id; /* for mport_type == ALIAS */
> +		struct { /* for mport_type == VNIC */
> +			u32 vnic_client_type; /* MAE_MPORT_DESC_VNIC_CLIENT_TYPE_* */
> +			u32 interface_idx;
> +			u16 pf_idx;
> +			u16 vf_idx;
> +		};
> +	};
> +	struct rhash_head linkage;
> +};
> +
> +int efx_mae_enumerate_mports(struct efx_nic *efx);
> +struct mae_mport_desc *efx_mae_get_mport(struct efx_nic *efx, u32 mport_id);
> +void efx_mae_put_mport(struct efx_nic *efx, struct mae_mport_desc *desc);
> +
> +/**
> + * struct efx_mae - MAE information
> + *
> + * @efx: The associated NIC
> + * @mports_ht: m-port descriptions from MC_CMD_MAE_MPORT_READ_JOURNAL
> + */
> +struct efx_mae {
> +	struct efx_nic *efx;
> +	struct rhashtable mports_ht;
> +};
> +
>  int efx_mae_start_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue);
>  int efx_mae_stop_counters(struct efx_nic *efx, struct efx_rx_queue *rx_queue);
>  void efx_mae_counters_grant_credits(struct work_struct *work);
> @@ -60,4 +93,7 @@ int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match,
>  			u32 prio, u32 acts_id, u32 *id);
>  int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
>  
> +int efx_init_mae(struct efx_nic *efx);
> +void efx_fini_mae(struct efx_nic *efx);
> +void efx_mae_remove_mport(void *desc, void *arg);
>  #endif /* EF100_MAE_H */
> diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
> index 32f54ce2492e..d280ad8f7836 100644
> --- a/drivers/net/ethernet/sfc/mcdi.h
> +++ b/drivers/net/ethernet/sfc/mcdi.h
> @@ -229,6 +229,9 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
>  #define MCDI_WORD(_buf, _field)						\
>  	((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) +	\
>  	 le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field)))
> +#define MCDI_STRUCT_WORD(_buf, _field)                                  \
> +	((void)BUILD_BUG_ON_ZERO(_field ## _LEN != 2),  \
> +	le16_to_cpu(*(__force const __le16 *)MCDI_STRUCT_PTR(_buf, _field)))
>  /* Write a 16-bit field defined in the protocol as being big-endian. */
>  #define MCDI_STRUCT_SET_WORD_BE(_buf, _field, _value) do {		\
>  	BUILD_BUG_ON(_field ## _LEN != 2);				\
> @@ -241,6 +244,8 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
>  	EFX_POPULATE_DWORD_1(*_MCDI_STRUCT_DWORD(_buf, _field), EFX_DWORD_0, _value)
>  #define MCDI_DWORD(_buf, _field)					\
>  	EFX_DWORD_FIELD(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0)
> +#define MCDI_STRUCT_DWORD(_buf, _field)                                 \
> +	EFX_DWORD_FIELD(*_MCDI_STRUCT_DWORD(_buf, _field), EFX_DWORD_0)
>  /* Write a 32-bit field defined in the protocol as being big-endian. */
>  #define MCDI_STRUCT_SET_DWORD_BE(_buf, _field, _value) do {		\
>  	BUILD_BUG_ON(_field ## _LEN != 4);				\
> diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
> index d036641dc043..bc9efbfb3d6b 100644
> --- a/drivers/net/ethernet/sfc/net_driver.h
> +++ b/drivers/net/ethernet/sfc/net_driver.h
> @@ -845,6 +845,8 @@ enum efx_xdp_tx_queues_mode {
>  	EFX_XDP_TX_QUEUES_BORROWED	/* queues borrowed from net stack */
>  };
>  
> +struct efx_mae;
> +
>  /**
>   * struct efx_nic - an Efx NIC
>   * @name: Device name (net device name or bus id before net device registered)
> @@ -881,6 +883,7 @@ enum efx_xdp_tx_queues_mode {
>   * @msi_context: Context for each MSI
>   * @extra_channel_types: Types of extra (non-traffic) channels that
>   *	should be allocated for this NIC
> + * @mae: Details of the Match Action Engine
>   * @xdp_tx_queue_count: Number of entries in %xdp_tx_queues.
>   * @xdp_tx_queues: Array of pointers to tx queues used for XDP transmit.
>   * @xdp_txq_queues_mode: XDP TX queues sharing strategy.
> @@ -1044,6 +1047,7 @@ struct efx_nic {
>  	struct efx_msi_context msi_context[EFX_MAX_CHANNELS];
>  	const struct efx_channel_type *
>  	extra_channel_type[EFX_MAX_EXTRA_CHANNELS];
> +	struct efx_mae *mae;
>  
>  	unsigned int xdp_tx_queue_count;
>  	struct efx_tx_queue **xdp_tx_queues;
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 4/8] sfc: add mport lookup based on driver's mport data
  2023-02-08 14:25 ` [PATCH v6 net-next 4/8] sfc: add mport lookup based on driver's mport data alejandro.lucero-palau
@ 2023-02-10  8:47   ` Martin Habets
  0 siblings, 0 replies; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:47 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

On Wed, Feb 08, 2023 at 02:25:15PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> Obtaining mport id is based on asking the firmware about it. This is
> still needed for mport initialization itself, but once the mport data is
> now kept by the driver, further mport id request can be satisfied
> internally without firmware interaction.
> 
> Previous function is just modified in name making clear the firmware
> interaction. The new function uses the old name and looks for the data
> in the mport data structure.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Acked-by: Martin Habets <habetsm.xilinx@gmail.com>

> ---
>  drivers/net/ethernet/sfc/ef100_nic.c |  4 ++--
>  drivers/net/ethernet/sfc/ef100_rep.c |  5 +----
>  drivers/net/ethernet/sfc/mae.c       | 27 ++++++++++++++++++++++++++-
>  drivers/net/ethernet/sfc/mae.h       |  2 ++
>  4 files changed, 31 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
> index 07e7dca0e4f2..aa11f0925e27 100644
> --- a/drivers/net/ethernet/sfc/ef100_nic.c
> +++ b/drivers/net/ethernet/sfc/ef100_nic.c
> @@ -736,7 +736,7 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
>  	/* Construct mport selector for "physical network port" */
>  	efx_mae_mport_wire(efx, &selector);
>  	/* Look up actual mport ID */
> -	rc = efx_mae_lookup_mport(efx, selector, &id);
> +	rc = efx_mae_fw_lookup_mport(efx, selector, &id);
>  	if (rc)
>  		return rc;
>  	/* The ID should always fit in 16 bits, because that's how wide the
> @@ -751,7 +751,7 @@ static int efx_ef100_get_base_mport(struct efx_nic *efx)
>  	/* Construct mport selector for "calling PF" */
>  	efx_mae_mport_uplink(efx, &selector);
>  	/* Look up actual mport ID */
> -	rc = efx_mae_lookup_mport(efx, selector, &id);
> +	rc = efx_mae_fw_lookup_mport(efx, selector, &id);
>  	if (rc)
>  		return rc;
>  	if (id >> 16)
> diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
> index ebe7b1275713..9cd1a3ac67e0 100644
> --- a/drivers/net/ethernet/sfc/ef100_rep.c
> +++ b/drivers/net/ethernet/sfc/ef100_rep.c
> @@ -243,14 +243,11 @@ static struct efx_rep *efx_ef100_rep_create_netdev(struct efx_nic *efx,
>  static int efx_ef100_configure_rep(struct efx_rep *efv)
>  {
>  	struct efx_nic *efx = efv->parent;
> -	u32 selector;
>  	int rc;
>  
>  	efv->rx_pring_size = EFX_REP_DEFAULT_PSEUDO_RING_SIZE;
> -	/* Construct mport selector for corresponding VF */
> -	efx_mae_mport_vf(efx, efv->idx, &selector);
>  	/* Look up actual mport ID */
> -	rc = efx_mae_lookup_mport(efx, selector, &efv->mport);
> +	rc = efx_mae_lookup_mport(efx, efv->idx, &efv->mport);
>  	if (rc)
>  		return rc;
>  	pci_dbg(efx->pci_dev, "VF %u has mport ID %#x\n", efv->idx, efv->mport);
> diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c
> index 725a3ab31087..6321fd393fc3 100644
> --- a/drivers/net/ethernet/sfc/mae.c
> +++ b/drivers/net/ethernet/sfc/mae.c
> @@ -97,7 +97,7 @@ void efx_mae_mport_mport(struct efx_nic *efx __always_unused, u32 mport_id, u32
>  }
>  
>  /* id is really only 24 bits wide */
> -int efx_mae_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id)
> +int efx_mae_fw_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id)
>  {
>  	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN);
>  	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_LOOKUP_IN_LEN);
> @@ -488,6 +488,31 @@ int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt)
>  	return 0;
>  }
>  
> +int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id)
> +{
> +	struct ef100_nic_data *nic_data = efx->nic_data;
> +	struct efx_mae *mae = efx->mae;
> +	struct rhashtable_iter walk;
> +	struct mae_mport_desc *m;
> +	int rc = -ENOENT;
> +
> +	rhashtable_walk_enter(&mae->mports_ht, &walk);
> +	rhashtable_walk_start(&walk);
> +	while ((m = rhashtable_walk_next(&walk)) != NULL) {
> +		if (m->mport_type == MAE_MPORT_DESC_MPORT_TYPE_VNIC &&
> +		    m->interface_idx == nic_data->local_mae_intf &&
> +		    m->pf_idx == 0 &&
> +		    m->vf_idx == vf_idx) {
> +			*id = m->mport_id;
> +			rc = 0;
> +			break;
> +		}
> +	}
> +	rhashtable_walk_stop(&walk);
> +	rhashtable_walk_exit(&walk);
> +	return rc;
> +}
> +
>  static bool efx_mae_asl_id(u32 id)
>  {
>  	return !!(id & BIT(31));
> diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
> index daa29d2cde96..b9bf86c47cda 100644
> --- a/drivers/net/ethernet/sfc/mae.h
> +++ b/drivers/net/ethernet/sfc/mae.h
> @@ -96,4 +96,6 @@ int efx_mae_delete_rule(struct efx_nic *efx, u32 id);
>  int efx_init_mae(struct efx_nic *efx);
>  void efx_fini_mae(struct efx_nic *efx);
>  void efx_mae_remove_mport(void *desc, void *arg);
> +int efx_mae_fw_lookup_mport(struct efx_nic *efx, u32 selector, u32 *id);
> +int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf, u32 *id);
>  #endif /* EF100_MAE_H */
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 5/8] sfc: add devlink port support for ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 5/8] sfc: add devlink port support for ef100 alejandro.lucero-palau
@ 2023-02-10  8:49   ` Martin Habets
  0 siblings, 0 replies; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:49 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

On Wed, Feb 08, 2023 at 02:25:16PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> Using the data when enumerating mports, create devlink ports just before
> netdevs are registered and remove those devlink ports after netdev has
> been unregistered.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> Reviewed-by: Jiri Pirko <jiri@nvidia.com>

Acked-by: Martin Habets <habetsm.xilinx@gmail.com>

> ---
>  drivers/net/ethernet/sfc/ef100_netdev.c |  10 +++
>  drivers/net/ethernet/sfc/ef100_rep.c    |  22 ++++++
>  drivers/net/ethernet/sfc/ef100_rep.h    |   7 ++
>  drivers/net/ethernet/sfc/efx_devlink.c  | 101 ++++++++++++++++++++++++
>  drivers/net/ethernet/sfc/efx_devlink.h  |   9 +++
>  drivers/net/ethernet/sfc/mae.h          |   2 +
>  drivers/net/ethernet/sfc/net_driver.h   |   2 +
>  7 files changed, 153 insertions(+)
> 
> diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
> index 6cf74788b27a..368147359299 100644
> --- a/drivers/net/ethernet/sfc/ef100_netdev.c
> +++ b/drivers/net/ethernet/sfc/ef100_netdev.c
> @@ -337,6 +337,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
>  	ef100_unregister_netdev(efx);
>  
>  #ifdef CONFIG_SFC_SRIOV
> +	ef100_pf_unset_devlink_port(efx);
>  	efx_fini_tc(efx);
>  #endif
>  
> @@ -422,6 +423,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>  		rc = ef100_probe_netdev_pf(efx);
>  		if (rc)
>  			goto fail;
> +#ifdef CONFIG_SFC_SRIOV
> +		ef100_pf_set_devlink_port(efx);
> +#endif
>  	}
>  
>  	efx->netdev_notifier.notifier_call = ef100_netdev_event;
> @@ -432,7 +436,13 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>  		goto fail;
>  	}
>  
> +	efx_probe_devlink_unlock(efx);
> +	return rc;
>  fail:
> +#ifdef CONFIG_SFC_SRIOV
> +	/* remove devlink port if does exist */
> +	ef100_pf_unset_devlink_port(efx);
> +#endif
>  	efx_probe_devlink_unlock(efx);
>  	return rc;
>  }
> diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
> index 9cd1a3ac67e0..6b5bc5d6955d 100644
> --- a/drivers/net/ethernet/sfc/ef100_rep.c
> +++ b/drivers/net/ethernet/sfc/ef100_rep.c
> @@ -16,6 +16,7 @@
>  #include "mae.h"
>  #include "rx_common.h"
>  #include "tc_bindings.h"
> +#include "efx_devlink.h"
>  
>  #define EFX_EF100_REP_DRIVER	"efx_ef100_rep"
>  
> @@ -297,6 +298,7 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
>  			i, rc);
>  		goto fail1;
>  	}
> +	ef100_rep_set_devlink_port(efv);
>  	rc = register_netdev(efv->net_dev);
>  	if (rc) {
>  		pci_err(efx->pci_dev,
> @@ -308,6 +310,7 @@ int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i)
>  		efv->net_dev->name);
>  	return 0;
>  fail2:
> +	ef100_rep_unset_devlink_port(efv);
>  	efx_ef100_deconfigure_rep(efv);
>  fail1:
>  	efx_ef100_rep_destroy_netdev(efv);
> @@ -323,6 +326,7 @@ void efx_ef100_vfrep_destroy(struct efx_nic *efx, struct efx_rep *efv)
>  		return;
>  	netif_dbg(efx, drv, rep_dev, "Removing VF representor\n");
>  	unregister_netdev(rep_dev);
> +	ef100_rep_unset_devlink_port(efv);
>  	efx_ef100_deconfigure_rep(efv);
>  	efx_ef100_rep_destroy_netdev(efv);
>  }
> @@ -339,6 +343,24 @@ void efx_ef100_fini_vfreps(struct efx_nic *efx)
>  		efx_ef100_vfrep_destroy(efx, efv);
>  }
>  
> +static bool ef100_mport_is_pcie_vnic(struct mae_mport_desc *mport_desc)
> +{
> +	return mport_desc->mport_type == MAE_MPORT_DESC_MPORT_TYPE_VNIC &&
> +	       mport_desc->vnic_client_type == MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION;
> +}
> +
> +bool ef100_mport_on_local_intf(struct efx_nic *efx,
> +			       struct mae_mport_desc *mport_desc)
> +{
> +	struct ef100_nic_data *nic_data = efx->nic_data;
> +	bool pcie_func;
> +
> +	pcie_func = ef100_mport_is_pcie_vnic(mport_desc);
> +
> +	return nic_data->have_local_intf && pcie_func &&
> +		     mport_desc->interface_idx == nic_data->local_mae_intf;
> +}
> +
>  void efx_ef100_init_reps(struct efx_nic *efx)
>  {
>  	struct ef100_nic_data *nic_data = efx->nic_data;
> diff --git a/drivers/net/ethernet/sfc/ef100_rep.h b/drivers/net/ethernet/sfc/ef100_rep.h
> index 328ac0cbb532..ae6add4b0855 100644
> --- a/drivers/net/ethernet/sfc/ef100_rep.h
> +++ b/drivers/net/ethernet/sfc/ef100_rep.h
> @@ -22,6 +22,8 @@ struct efx_rep_sw_stats {
>  	atomic64_t rx_dropped, tx_errors;
>  };
>  
> +struct devlink_port;
> +
>  /**
>   * struct efx_rep - Private data for an Efx representor
>   *
> @@ -39,6 +41,7 @@ struct efx_rep_sw_stats {
>   * @rx_lock: protects @rx_list
>   * @napi: NAPI control structure
>   * @stats: software traffic counters for netdev stats
> + * @dl_port: devlink port associated to this netdev representor
>   */
>  struct efx_rep {
>  	struct efx_nic *parent;
> @@ -54,6 +57,7 @@ struct efx_rep {
>  	spinlock_t rx_lock;
>  	struct napi_struct napi;
>  	struct efx_rep_sw_stats stats;
> +	struct devlink_port *dl_port;
>  };
>  
>  int efx_ef100_vfrep_create(struct efx_nic *efx, unsigned int i);
> @@ -69,4 +73,7 @@ struct efx_rep *efx_ef100_find_rep_by_mport(struct efx_nic *efx, u16 mport);
>  extern const struct net_device_ops efx_ef100_rep_netdev_ops;
>  void efx_ef100_init_reps(struct efx_nic *efx);
>  void efx_ef100_fini_reps(struct efx_nic *efx);
> +struct mae_mport_desc;
> +bool ef100_mport_on_local_intf(struct efx_nic *efx,
> +			       struct mae_mport_desc *mport_desc);
>  #endif /* EF100_REP_H */
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
> index c06efeac11e5..1b1276716113 100644
> --- a/drivers/net/ethernet/sfc/efx_devlink.c
> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
> @@ -14,6 +14,8 @@
>  #include "mcdi.h"
>  #include "mcdi_functions.h"
>  #include "mcdi_pcol.h"
> +#include "mae.h"
> +#include "ef100_rep.h"
>  #endif
>  
>  struct efx_devlink {
> @@ -21,6 +23,41 @@ struct efx_devlink {
>  };
>  
>  #ifdef CONFIG_SFC_SRIOV
> +static void efx_devlink_del_port(struct devlink_port *dl_port)
> +{
> +	if (!dl_port)
> +		return;
> +	devl_port_unregister(dl_port);
> +}
> +
> +static int efx_devlink_add_port(struct efx_nic *efx,
> +				struct mae_mport_desc *mport)
> +{
> +	bool external = false;
> +
> +	if (!ef100_mport_on_local_intf(efx, mport))
> +		external = true;
> +
> +	switch (mport->mport_type) {
> +	case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
> +		if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
> +			devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
> +						      mport->vf_idx,
> +						      external);
> +		else
> +			devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
> +						      external);
> +		break;
> +	default:
> +		/* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
> +		return 0;
> +	}
> +
> +	mport->dl_port.index = mport->mport_id;
> +
> +	return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
> +}
> +
>  static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
>  					    struct devlink_info_req *req,
>  					    unsigned int partition_type,
> @@ -477,6 +514,70 @@ static const struct devlink_ops sfc_devlink_ops = {
>  #endif
>  };
>  
> +#ifdef CONFIG_SFC_SRIOV
> +static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
> +{
> +	struct mae_mport_desc *mport;
> +	u32 id;
> +	int rc;
> +
> +	if (efx_mae_lookup_mport(efx, idx, &id)) {
> +		/* This should not happen. */
> +		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
> +			pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
> +		else
> +			pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
> +				      idx);
> +		return NULL;
> +	}
> +
> +	mport = efx_mae_get_mport(efx, id);
> +	if (!mport) {
> +		/* This should not happen. */
> +		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
> +			pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
> +		else
> +			pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
> +				      idx);
> +		return NULL;
> +	}
> +
> +	rc = efx_devlink_add_port(efx, mport);
> +	if (rc) {
> +		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
> +			pci_warn(efx->pci_dev,
> +				 "devlink port creation for PF failed.\n");
> +		else
> +			pci_warn(efx->pci_dev,
> +				 "devlink_port creationg for VF %u failed.\n",
> +				 idx);
> +		return NULL;
> +	}
> +
> +	return &mport->dl_port;
> +}
> +
> +void ef100_rep_set_devlink_port(struct efx_rep *efv)
> +{
> +	efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
> +}
> +
> +void ef100_pf_set_devlink_port(struct efx_nic *efx)
> +{
> +	efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
> +}
> +
> +void ef100_rep_unset_devlink_port(struct efx_rep *efv)
> +{
> +	efx_devlink_del_port(efv->dl_port);
> +}
> +
> +void ef100_pf_unset_devlink_port(struct efx_nic *efx)
> +{
> +	efx_devlink_del_port(efx->dl_port);
> +}
> +#endif
> +
>  void efx_fini_devlink_lock(struct efx_nic *efx)
>  {
>  	if (efx->devlink)
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
> index a5269361c3e0..d544885d3dbf 100644
> --- a/drivers/net/ethernet/sfc/efx_devlink.h
> +++ b/drivers/net/ethernet/sfc/efx_devlink.h
> @@ -36,4 +36,13 @@ void efx_probe_devlink_unlock(struct efx_nic *efx);
>  void efx_fini_devlink_lock(struct efx_nic *efx);
>  void efx_fini_devlink_and_unlock(struct efx_nic *efx);
>  
> +#ifdef CONFIG_SFC_SRIOV
> +struct efx_rep;
> +
> +void ef100_pf_set_devlink_port(struct efx_nic *efx);
> +void ef100_rep_set_devlink_port(struct efx_rep *efv);
> +void ef100_pf_unset_devlink_port(struct efx_nic *efx);
> +void ef100_rep_unset_devlink_port(struct efx_rep *efv);
> +#endif
> +
>  #endif	/* _EFX_DEVLINK_H */
> diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h
> index b9bf86c47cda..bec293a06733 100644
> --- a/drivers/net/ethernet/sfc/mae.h
> +++ b/drivers/net/ethernet/sfc/mae.h
> @@ -13,6 +13,7 @@
>  #define EF100_MAE_H
>  /* MCDI interface for the ef100 Match-Action Engine */
>  
> +#include <net/devlink.h>
>  #include "net_driver.h"
>  #include "tc.h"
>  #include "mcdi_pcol.h" /* needed for various MC_CMD_MAE_*_NULL defines */
> @@ -43,6 +44,7 @@ struct mae_mport_desc {
>  		};
>  	};
>  	struct rhash_head linkage;
> +	struct devlink_port dl_port;
>  };
>  
>  int efx_mae_enumerate_mports(struct efx_nic *efx);
> diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
> index bc9efbfb3d6b..fcd51d3992fa 100644
> --- a/drivers/net/ethernet/sfc/net_driver.h
> +++ b/drivers/net/ethernet/sfc/net_driver.h
> @@ -998,6 +998,7 @@ struct efx_mae;
>   * @netdev_notifier: Netdevice notifier.
>   * @tc: state for TC offload (EF100).
>   * @devlink: reference to devlink structure owned by this device
> + * @dl_port: devlink port associated with the PF
>   * @mem_bar: The BAR that is mapped into membase.
>   * @reg_base: Offset from the start of the bar to the function control window.
>   * @monitor_work: Hardware monitor workitem
> @@ -1185,6 +1186,7 @@ struct efx_nic {
>  	struct efx_tc_state *tc;
>  
>  	struct devlink *devlink;
> +	struct devlink_port *dl_port;
>  	unsigned int mem_bar;
>  	u32 reg_base;
>  
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 6/8] sfc: obtain device mac address based on firmware handle for ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 6/8] sfc: obtain device mac address based on firmware handle " alejandro.lucero-palau
@ 2023-02-10  8:50   ` Martin Habets
  0 siblings, 0 replies; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:50 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

On Wed, Feb 08, 2023 at 02:25:17PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> Getting device mac address is currently based on a specific MCDI command
> only available for the PF. This patch changes the MCDI command to a
> generic one for PFs and VFs based on a client handle. This allows both
> PFs and VFs to ask for their mac address during initialization using the
> CLIENT_HANDLE_SELF.
> 
> Moreover, the patch allows other client handles which will be used by
> the PF to ask for mac addresses linked to VFs. This is necessary for
> suporting the port_function_hw_addr_get devlink function in further
> patches.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Acked-by: Martin Habets <habetsm.xilinx@gmail.com>

> ---
>  drivers/net/ethernet/sfc/ef100_netdev.c | 10 +++++++
>  drivers/net/ethernet/sfc/ef100_nic.c    | 37 +++++++++++++------------
>  drivers/net/ethernet/sfc/ef100_nic.h    |  2 ++
>  3 files changed, 31 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c
> index 368147359299..d916877b5a9a 100644
> --- a/drivers/net/ethernet/sfc/ef100_netdev.c
> +++ b/drivers/net/ethernet/sfc/ef100_netdev.c
> @@ -359,6 +359,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>  {
>  	struct efx_nic *efx = &probe_data->efx;
>  	struct efx_probe_data **probe_ptr;
> +	struct ef100_nic_data *nic_data;
>  	struct net_device *net_dev;
>  	int rc;
>  
> @@ -410,6 +411,15 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
>  	/* Don't fail init if RSS setup doesn't work. */
>  	efx_mcdi_push_default_indir_table(efx, efx->n_rx_channels);
>  
> +	nic_data = efx->nic_data;
> +	rc = ef100_get_mac_address(efx, net_dev->perm_addr, CLIENT_HANDLE_SELF,
> +				   efx->type->is_vf);
> +	if (rc)
> +		return rc;
> +	/* Assign MAC address */
> +	eth_hw_addr_set(net_dev, net_dev->perm_addr);
> +	ether_addr_copy(nic_data->port_id, net_dev->perm_addr);
> +
>  	/* devlink creation, registration and lock */
>  	rc = efx_probe_devlink_and_lock(efx);
>  	if (rc)
> diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
> index aa11f0925e27..aa48c79a2149 100644
> --- a/drivers/net/ethernet/sfc/ef100_nic.c
> +++ b/drivers/net/ethernet/sfc/ef100_nic.c
> @@ -130,23 +130,34 @@ static void ef100_mcdi_reboot_detected(struct efx_nic *efx)
>  
>  /*	MCDI calls
>   */
> -static int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address)
> +int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
> +			  int client_handle, bool empty_ok)
>  {
> -	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
> +	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1));
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_CLIENT_MAC_ADDRESSES_IN_LEN);
>  	size_t outlen;
>  	int rc;
>  
>  	BUILD_BUG_ON(MC_CMD_GET_MAC_ADDRESSES_IN_LEN != 0);
> +	MCDI_SET_DWORD(inbuf, GET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
> +		       client_handle);
>  
> -	rc = efx_mcdi_rpc(efx, MC_CMD_GET_MAC_ADDRESSES, NULL, 0,
> -			  outbuf, sizeof(outbuf), &outlen);
> +	rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLIENT_MAC_ADDRESSES, inbuf,
> +			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
>  	if (rc)
>  		return rc;
> -	if (outlen < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)
> -		return -EIO;
>  
> -	ether_addr_copy(mac_address,
> -			MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE));
> +	if (outlen >= MC_CMD_GET_CLIENT_MAC_ADDRESSES_OUT_LEN(1)) {
> +		ether_addr_copy(mac_address,
> +				MCDI_PTR(outbuf, GET_CLIENT_MAC_ADDRESSES_OUT_MAC_ADDRS));
> +	} else if (empty_ok) {
> +		pci_warn(efx->pci_dev,
> +			 "No MAC address provisioned for client ID %#x.\n",
> +			 client_handle);
> +		eth_zero_addr(mac_address);
> +	} else {
> +		return -ENOENT;
> +	}
>  	return 0;
>  }
>  
> @@ -1117,13 +1128,6 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
>  	struct net_device *net_dev = efx->net_dev;
>  	int rc;
>  
> -	rc = ef100_get_mac_address(efx, net_dev->perm_addr);
> -	if (rc)
> -		goto fail;
> -	/* Assign MAC address */
> -	eth_hw_addr_set(net_dev, net_dev->perm_addr);
> -	memcpy(nic_data->port_id, net_dev->perm_addr, ETH_ALEN);
> -
>  	if (!nic_data->grp_mae)
>  		return 0;
>  
> @@ -1163,9 +1167,6 @@ int ef100_probe_netdev_pf(struct efx_nic *efx)
>  		efx->fixed_features |= NETIF_F_HW_TC;
>  	}
>  #endif
> -	return 0;
> -
> -fail:
>  	return rc;
>  }
>  
> diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h
> index 496aea43c60f..e59044072333 100644
> --- a/drivers/net/ethernet/sfc/ef100_nic.h
> +++ b/drivers/net/ethernet/sfc/ef100_nic.h
> @@ -92,4 +92,6 @@ int efx_ef100_init_datapath_caps(struct efx_nic *efx);
>  int ef100_phy_probe(struct efx_nic *efx);
>  int ef100_filter_table_probe(struct efx_nic *efx);
>  
> +int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
> +			  int client_handle, bool empty_ok);
>  #endif	/* EFX_EF100_NIC_H */
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100 alejandro.lucero-palau
  2023-02-08 14:40   ` Jiri Pirko
@ 2023-02-10  8:52   ` Martin Habets
  1 sibling, 0 replies; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:52 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

On Wed, Feb 08, 2023 at 02:25:18PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> Using the builtin client handle id infrastructure, add support for
> obtaining the mac address linked to mports in ef100. This implies
> to execute an MCDI command for getting the data from the firmware
> for each devlink port.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Acked-by: Martin Habets <habetsm.xilinx@gmail.com>

> ---
>  drivers/net/ethernet/sfc/ef100_nic.c   | 27 +++++++++++++++
>  drivers/net/ethernet/sfc/ef100_nic.h   |  1 +
>  drivers/net/ethernet/sfc/ef100_rep.c   |  8 +++++
>  drivers/net/ethernet/sfc/ef100_rep.h   |  1 +
>  drivers/net/ethernet/sfc/efx_devlink.c | 46 ++++++++++++++++++++++++++
>  5 files changed, 83 insertions(+)
> 
> diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
> index aa48c79a2149..becd21c2325d 100644
> --- a/drivers/net/ethernet/sfc/ef100_nic.c
> +++ b/drivers/net/ethernet/sfc/ef100_nic.c
> @@ -1122,6 +1122,33 @@ static int ef100_probe_main(struct efx_nic *efx)
>  	return rc;
>  }
>  
> +/* MCDI commands are related to the same device issuing them. This function
> + * allows to do an MCDI command on behalf of another device, mainly PFs setting
> + * things for VFs.
> + */
> +int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id)
> +{
> +	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLIENT_HANDLE_OUT_LEN);
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_CLIENT_HANDLE_IN_LEN);
> +	u64 pciefn_flat = le64_to_cpu(pciefn.u64[0]);
> +	size_t outlen;
> +	int rc;
> +
> +	MCDI_SET_DWORD(inbuf, GET_CLIENT_HANDLE_IN_TYPE,
> +		       MC_CMD_GET_CLIENT_HANDLE_IN_TYPE_FUNC);
> +	MCDI_SET_QWORD(inbuf, GET_CLIENT_HANDLE_IN_FUNC,
> +		       pciefn_flat);
> +
> +	rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLIENT_HANDLE, inbuf, sizeof(inbuf),
> +			  outbuf, sizeof(outbuf), &outlen);
> +	if (rc)
> +		return rc;
> +	if (outlen < sizeof(outbuf))
> +		return -EIO;
> +	*id = MCDI_DWORD(outbuf, GET_CLIENT_HANDLE_OUT_HANDLE);
> +	return 0;
> +}
> +
>  int ef100_probe_netdev_pf(struct efx_nic *efx)
>  {
>  	struct ef100_nic_data *nic_data = efx->nic_data;
> diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h
> index e59044072333..f1ed481c1260 100644
> --- a/drivers/net/ethernet/sfc/ef100_nic.h
> +++ b/drivers/net/ethernet/sfc/ef100_nic.h
> @@ -94,4 +94,5 @@ int ef100_filter_table_probe(struct efx_nic *efx);
>  
>  int ef100_get_mac_address(struct efx_nic *efx, u8 *mac_address,
>  			  int client_handle, bool empty_ok);
> +int efx_ef100_lookup_client_id(struct efx_nic *efx, efx_qword_t pciefn, u32 *id);
>  #endif	/* EFX_EF100_NIC_H */
> diff --git a/drivers/net/ethernet/sfc/ef100_rep.c b/drivers/net/ethernet/sfc/ef100_rep.c
> index 6b5bc5d6955d..0b3083ef0ead 100644
> --- a/drivers/net/ethernet/sfc/ef100_rep.c
> +++ b/drivers/net/ethernet/sfc/ef100_rep.c
> @@ -361,6 +361,14 @@ bool ef100_mport_on_local_intf(struct efx_nic *efx,
>  		     mport_desc->interface_idx == nic_data->local_mae_intf;
>  }
>  
> +bool ef100_mport_is_vf(struct mae_mport_desc *mport_desc)
> +{
> +	bool pcie_func;
> +
> +	pcie_func = ef100_mport_is_pcie_vnic(mport_desc);
> +	return pcie_func && (mport_desc->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL);
> +}
> +
>  void efx_ef100_init_reps(struct efx_nic *efx)
>  {
>  	struct ef100_nic_data *nic_data = efx->nic_data;
> diff --git a/drivers/net/ethernet/sfc/ef100_rep.h b/drivers/net/ethernet/sfc/ef100_rep.h
> index ae6add4b0855..a042525a2240 100644
> --- a/drivers/net/ethernet/sfc/ef100_rep.h
> +++ b/drivers/net/ethernet/sfc/ef100_rep.h
> @@ -76,4 +76,5 @@ void efx_ef100_fini_reps(struct efx_nic *efx);
>  struct mae_mport_desc;
>  bool ef100_mport_on_local_intf(struct efx_nic *efx,
>  			       struct mae_mport_desc *mport_desc);
> +bool ef100_mport_is_vf(struct mae_mport_desc *mport_desc);
>  #endif /* EF100_REP_H */
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
> index 1b1276716113..68d04c2176d3 100644
> --- a/drivers/net/ethernet/sfc/efx_devlink.c
> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
> @@ -11,6 +11,7 @@
>  #include "efx_devlink.h"
>  #ifdef CONFIG_SFC_SRIOV
>  #include <linux/rtc.h>
> +#include "ef100_nic.h"
>  #include "mcdi.h"
>  #include "mcdi_functions.h"
>  #include "mcdi_pcol.h"
> @@ -58,6 +59,50 @@ static int efx_devlink_add_port(struct efx_nic *efx,
>  	return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
>  }
>  
> +static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
> +				     int *hw_addr_len,
> +				     struct netlink_ext_ack *extack)
> +{
> +	struct efx_devlink *devlink = devlink_priv(port->devlink);
> +	struct mae_mport_desc *mport_desc;
> +	efx_qword_t pciefn;
> +	u32 client_id;
> +	int rc;
> +
> +	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
> +
> +	if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
> +		NL_SET_ERR_MSG_MOD(extack, "Port not on local interface");
> +		return -EINVAL;
> +	}
> +
> +	if (ef100_mport_is_vf(mport_desc))
> +		EFX_POPULATE_QWORD_3(pciefn,
> +				     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
> +				     PCIE_FUNCTION_VF, mport_desc->vf_idx,
> +				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
> +	else
> +		EFX_POPULATE_QWORD_3(pciefn,
> +				     PCIE_FUNCTION_PF, mport_desc->pf_idx,
> +				     PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
> +				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
> +
> +	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
> +	if (rc) {
> +		NL_SET_ERR_MSG_MOD(extack, "No internal client_ID for port");
> +		return -EIO;
> +	}
> +
> +	rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
> +	if (rc) {
> +		NL_SET_ERR_MSG_MOD(extack, "No MAC available");
> +		return -ENOENT;
> +	}
> +
> +	*hw_addr_len = ETH_ALEN;
> +	return rc;
> +}
> +
>  static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
>  					    struct devlink_info_req *req,
>  					    unsigned int partition_type,
> @@ -511,6 +556,7 @@ static int efx_devlink_info_get(struct devlink *devlink,
>  static const struct devlink_ops sfc_devlink_ops = {
>  #ifdef CONFIG_SFC_SRIOV
>  	.info_get			= efx_devlink_info_get,
> +	.port_function_hw_addr_get	= efx_devlink_port_addr_get,
>  #endif
>  };
>  
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set in ef100
  2023-02-08 14:25 ` [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set " alejandro.lucero-palau
  2023-02-08 14:40   ` Jiri Pirko
@ 2023-02-10  8:53   ` Martin Habets
  1 sibling, 0 replies; 25+ messages in thread
From: Martin Habets @ 2023-02-10  8:53 UTC (permalink / raw)
  To: alejandro.lucero-palau
  Cc: netdev, linux-net-drivers, davem, kuba, pabeni, edumazet,
	ecree.xilinx, linux-doc, corbet, jiri

On Wed, Feb 08, 2023 at 02:25:19PM +0000, alejandro.lucero-palau@amd.com wrote:
> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
> 
> Using the builtin client handle id infrastructure, add support for
> setting the mac address linked to mports in ef100. This implies to
> execute an MCDI command for giving the address to the firmware for
> the specific devlink port.
> 
> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>

Acked-by: Martin Habets <habetsm.xilinx@gmail.com>

> ---
>  drivers/net/ethernet/sfc/efx_devlink.c | 42 ++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
> index 68d04c2176d3..9fc2fe862303 100644
> --- a/drivers/net/ethernet/sfc/efx_devlink.c
> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
> @@ -103,6 +103,47 @@ static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
>  	return rc;
>  }
>  
> +static int efx_devlink_port_addr_set(struct devlink_port *port,
> +				     const u8 *hw_addr, int hw_addr_len,
> +				     struct netlink_ext_ack *extack)
> +{
> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1));
> +	struct efx_devlink *devlink = devlink_priv(port->devlink);
> +	struct mae_mport_desc *mport_desc;
> +	efx_qword_t pciefn;
> +	u32 client_id;
> +	int rc;
> +
> +	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
> +
> +	if (!ef100_mport_is_vf(mport_desc)) {
> +		NL_SET_ERR_MSG_MOD(extack, "Port MAC change not allowed");
> +		return -EPERM;
> +	}
> +
> +	EFX_POPULATE_QWORD_3(pciefn,
> +			     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
> +			     PCIE_FUNCTION_VF, mport_desc->vf_idx,
> +			     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
> +
> +	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
> +	if (rc) {
> +		NL_SET_ERR_MSG_MOD(extack, "No internal client_ID");
> +		return rc;
> +	}
> +
> +	MCDI_SET_DWORD(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
> +		       client_id);
> +
> +	ether_addr_copy(MCDI_PTR(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
> +			hw_addr);
> +
> +	rc = efx_mcdi_rpc(devlink->efx, MC_CMD_SET_CLIENT_MAC_ADDRESSES, inbuf,
> +			  sizeof(inbuf), NULL, 0, NULL);
> +
> +	return rc;
> +}
> +
>  static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
>  					    struct devlink_info_req *req,
>  					    unsigned int partition_type,
> @@ -557,6 +598,7 @@ static const struct devlink_ops sfc_devlink_ops = {
>  #ifdef CONFIG_SFC_SRIOV
>  	.info_get			= efx_devlink_info_get,
>  	.port_function_hw_addr_get	= efx_devlink_port_addr_get,
> +	.port_function_hw_addr_set	= efx_devlink_port_addr_set,
>  #endif
>  };
>  
> -- 
> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-10  8:40   ` Martin Habets
@ 2023-02-10  9:07     ` Lucero Palau, Alejandro
  2023-02-10 15:01       ` Lucero Palau, Alejandro
  0 siblings, 1 reply; 25+ messages in thread
From: Lucero Palau, Alejandro @ 2023-02-10  9:07 UTC (permalink / raw)
  To: Lucero Palau, Alejandro, netdev, linux-net-drivers (AMD-Xilinx),
	davem, kuba, pabeni, edumazet, ecree.xilinx, linux-doc, corbet,
	jiri


On 2/10/23 08:40, Martin Habets wrote:
> NAK, see below.
>
> On Wed, Feb 08, 2023 at 02:25:13PM +0000, alejandro.lucero-palau@amd.com wrote:
>> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>>
>> Add devlink info support for ef100. The information reported is obtained
>> through the MCDI interface with the specific meaning defined in new
>> documentation file.
>>
>> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>> ---
>>   Documentation/networking/devlink/index.rst |   1 +
>>   Documentation/networking/devlink/sfc.rst   |  57 +++
>>   MAINTAINERS                                |   1 +
>>   drivers/net/ethernet/sfc/efx_devlink.c     | 460 +++++++++++++++++++++
>>   drivers/net/ethernet/sfc/efx_devlink.h     |  17 +
>>   drivers/net/ethernet/sfc/mcdi.c            |  74 ++++
>>   drivers/net/ethernet/sfc/mcdi.h            |   5 +
>>   7 files changed, 615 insertions(+)
>>   create mode 100644 Documentation/networking/devlink/sfc.rst
>>
>> diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
>> index fee4d3968309..b49749e2b9a6 100644
>> --- a/Documentation/networking/devlink/index.rst
>> +++ b/Documentation/networking/devlink/index.rst
>> @@ -66,3 +66,4 @@ parameters, info versions, and other features it supports.
>>      prestera
>>      iosm
>>      octeontx2
>> +   sfc
>> diff --git a/Documentation/networking/devlink/sfc.rst b/Documentation/networking/devlink/sfc.rst
>> new file mode 100644
>> index 000000000000..db64a1bd9733
>> --- /dev/null
>> +++ b/Documentation/networking/devlink/sfc.rst
>> @@ -0,0 +1,57 @@
>> +.. SPDX-License-Identifier: GPL-2.0
>> +
>> +===================
>> +sfc devlink support
>> +===================
>> +
>> +This document describes the devlink features implemented by the ``sfc``
>> +device driver for the ef100 device.
>> +
>> +Info versions
>> +=============
>> +
>> +The ``sfc`` driver reports the following versions
>> +
>> +.. list-table:: devlink info versions implemented
>> +   :widths: 5 5 90
>> +
>> +   * - Name
>> +     - Type
>> +     - Description
>> +   * - ``fw.mgmt.suc``
>> +     - running
>> +     - For boards where the management function is split between multiple
>> +       control units, this is the SUC control unit's firmware version.
>> +   * - ``fw.mgmt.cmc``
>> +     - running
>> +     - For boards where the management function is split between multiple
>> +       control units, this is the CMC control unit's firmware version.
>> +   * - ``fpga.rev``
>> +     - running
>> +     - FPGA design revision.
>> +   * - ``fpga.app``
>> +     - running
>> +     - Datapath programmable logic version.
>> +   * - ``fw.app``
>> +     - running
>> +     - Datapath software/microcode/firmware version.
>> +   * - ``coproc.boot``
>> +     - running
>> +     - SmartNIC application co-processor (APU) first stage boot loader version.
>> +   * - ``coproc.uboot``
>> +     - running
>> +     - SmartNIC application co-processor (APU) co-operating system loader version.
>> +   * - ``coproc.main``
>> +     - running
>> +     - SmartNIC application co-processor (APU) main operating system version.
>> +   * - ``coproc.recovery``
>> +     - running
>> +     - SmartNIC application co-processor (APU) recovery operating system version.
>> +   * - ``fw.exprom``
>> +     - running
>> +     - Expansion ROM version. For boards where the expansion ROM is split between
>> +       multiple images (e.g. PXE and UEFI), this is the specifically the PXE boot
>> +       ROM version.
>> +   * - ``fw.uefi``
>> +     - running
>> +     - UEFI driver version (No UNDI support).
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 2cf9eb43ed8f..51f7d3448295 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -18937,6 +18937,7 @@ M:	Edward Cree <ecree.xilinx@gmail.com>
>>   M:	Martin Habets <habetsm.xilinx@gmail.com>
>>   L:	netdev@vger.kernel.org
>>   S:	Supported
>> +F:	Documentation/networking/devlink/sfc.rst
>>   F:	drivers/net/ethernet/sfc/
>>   
>>   SFF/SFP/SFP+ MODULE SUPPORT
>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
>> index 57a7023d3cb6..c06efeac11e5 100644
>> --- a/drivers/net/ethernet/sfc/efx_devlink.c
>> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
>> @@ -9,12 +9,472 @@
>>    */
>>   
>>   #include "efx_devlink.h"
>> +#ifdef CONFIG_SFC_SRIOV
> I don't get this SRIOV dependency. In the cover letter you say it
> was because of IA64, bu those errors were:
>
> ia64-linux-ld: drivers/net/ethernet/sfc/ef100_nic.o: in function `ef100_remove':
>   ef100_nic.c:(.text+0x2e82): undefined reference to `efx_ef100_fini_reps'
>   ia64-linux-ld: ef100_nic.c:(.text+0x2e92): undefined reference to `efx_fini_mae'
>
> which is completely unrelated to this patch.
> This extra ifdef must not be needed at all. I suspect something else
> is going wrong in your builds.
> Please explain in detail why you think you need this.
>
> Martin

This is not due to the ia64 build errors but due to the microblaze build 
errors.

We are using rtc_time64_to_tm twice in the info related code which turns 
out to be not available for Microblaze.

I did take a look and not found a quick way of substituting those calls. 
SRIOV is not configured for Microblaze and I guess it will never be.

This change makes the devlink info command not available if SRIOV is not 
configured which is arguably not a big problem. It can be said the 
device info could be useful in that case what I really doubt. Yes, a 
netdev for the PF can be used, but what do we need devlink for then? Our 
firmware installation/setup is not based on devlink and we have other 
means for obtaining firmware related info.

IMO, Microblaze should have not ef100 configured ...

>> +#include <linux/rtc.h>
>> +#include "mcdi.h"
>> +#include "mcdi_functions.h"
>> +#include "mcdi_pcol.h"
>> +#endif
>>   
>>   struct efx_devlink {
>>   	struct efx_nic *efx;
>>   };
>>   
>> +#ifdef CONFIG_SFC_SRIOV
>> +static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
>> +					    struct devlink_info_req *req,
>> +					    unsigned int partition_type,
>> +					    const char *version_name)
>> +{
>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>> +	u16 version[4];
>> +	int rc;
>> +
>> +	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
>> +				     0);
>> +	if (rc) {
>> +		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
>> +			  version_name);
>> +		return rc;
>> +	}
>> +
>> +	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
>> +		 version[1], version[2], version[3]);
>> +	devlink_info_version_stored_put(req, version_name, buf);
>> +
>> +	return 0;
>> +}
>> +
>> +static int efx_devlink_info_stored_versions(struct efx_nic *efx,
>> +					    struct devlink_info_req *req)
>> +{
>> +	int rc;
>> +
>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>> +					      NVRAM_PARTITION_TYPE_BUNDLE,
>> +					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
>> +	if (rc)
>> +		return rc;
>> +
>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>> +					      NVRAM_PARTITION_TYPE_MC_FIRMWARE,
>> +					      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
>> +	if (rc)
>> +		return rc;
>> +
>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>> +					      NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
>> +					      EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
>> +	if (rc)
>> +		return rc;
>> +
>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>> +					      NVRAM_PARTITION_TYPE_EXPANSION_ROM,
>> +					      EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
>> +	if (rc)
>> +		return rc;
>> +
>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>> +					      NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
>> +					      EFX_DEVLINK_INFO_VERSION_FW_UEFI);
>> +	if (rc)
>> +		return rc;
>> +
>> +	return 0;
>> +}
>> +
>> +#define EFX_VER_FLAG(_f)	\
>> +	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
>> +
>> +static void efx_devlink_info_running_v2(struct efx_nic *efx,
>> +					struct devlink_info_req *req,
>> +					unsigned int flags, efx_dword_t *outbuf)
>> +{
>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>> +	union {
>> +		const __le32 *dwords;
>> +		const __le16 *words;
>> +		const char *str;
>> +	} ver;
>> +	struct rtc_time build_date;
>> +	unsigned int build_id;
>> +	size_t offset;
>> +	u64 tstamp;
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
>> +			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
>> +		devlink_info_version_fixed_put(req,
>> +					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
>> +					       buf);
>> +
>> +		/* Favour full board version if present (in V5 or later) */
>> +		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
>> +			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
>> +				 MCDI_DWORD(outbuf,
>> +					    GET_VERSION_V2_OUT_BOARD_REVISION));
>> +			devlink_info_version_fixed_put(req,
>> +						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
>> +						       buf);
>> +		}
>> +
>> +		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
>> +		if (ver.str[0])
>> +			devlink_info_board_serial_number_put(req, ver.str);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V2_OUT_FPGA_VERSION);
>> +		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
>> +				  le32_to_cpu(ver.dwords[0]),
>> +				  'A' + le32_to_cpu(ver.dwords[1]),
>> +				  le32_to_cpu(ver.dwords[2]));
>> +
>> +		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
>> +		if (ver.str[0])
>> +			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
>> +				 " (%s)", ver.str);
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
>> +						 buf);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V2_OUT_CMCFW_VERSION);
>> +		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +				  le32_to_cpu(ver.dwords[0]),
>> +				  le32_to_cpu(ver.dwords[1]),
>> +				  le32_to_cpu(ver.dwords[2]),
>> +				  le32_to_cpu(ver.dwords[3]));
>> +
>> +		tstamp = MCDI_QWORD(outbuf,
>> +				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
>> +		if (tstamp) {
>> +			rtc_time64_to_tm(tstamp, &build_date);
>> +			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
>> +				 " (%ptRd)", &build_date);
>> +		}
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
>> +						 buf);
>> +	}
>> +
>> +	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
>> +	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
>> +			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
>> +	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
>> +		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
>> +		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
>> +			 " (%x) %s", build_id,
>> +			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
>> +	}
>> +	devlink_info_version_running_put(req,
>> +					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
>> +					 buf);
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V2_OUT_SUCFW_VERSION);
>> +		tstamp = MCDI_QWORD(outbuf,
>> +				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
>> +		rtc_time64_to_tm(tstamp, &build_date);
>> +		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
>> +			 "%u.%u.%u.%u type %x (%ptRd)",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
>> +			 build_id, &build_date);
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
>> +						 buf);
>> +	}
>> +}
>> +
>> +static void efx_devlink_info_running_v3(struct efx_nic *efx,
>> +					struct devlink_info_req *req,
>> +					unsigned int flags, efx_dword_t *outbuf)
>> +{
>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>> +	union {
>> +		const __le32 *dwords;
>> +		const __le16 *words;
>> +		const char *str;
>> +	} ver;
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
>> +						 buf);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
>> +						 buf);
>> +	}
>> +}
>> +
>> +static void efx_devlink_info_running_v4(struct efx_nic *efx,
>> +					struct devlink_info_req *req,
>> +					unsigned int flags, efx_dword_t *outbuf)
>> +{
>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>> +	union {
>> +		const __le32 *dwords;
>> +		const __le16 *words;
>> +		const char *str;
>> +	} ver;
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]),
>> +			 le32_to_cpu(ver.dwords[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
>> +						 buf);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]),
>> +			 le32_to_cpu(ver.dwords[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
>> +						 buf);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]),
>> +			 le32_to_cpu(ver.dwords[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
>> +						 buf);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]),
>> +			 le32_to_cpu(ver.dwords[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
>> +						 buf);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
>> +	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V4_OUT_SUCFW_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]),
>> +			 le32_to_cpu(ver.dwords[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
>> +						 buf);
>> +	}
>> +}
>> +
>> +static void efx_devlink_info_running_v5(struct efx_nic *efx,
>> +					struct devlink_info_req *req,
>> +					unsigned int flags, efx_dword_t *outbuf)
>> +{
>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>> +	union {
>> +		const __le32 *dwords;
>> +		const __le16 *words;
>> +		const char *str;
>> +	} ver;
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V5_OUT_BOARD_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]),
>> +			 le32_to_cpu(ver.dwords[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
>> +						 buf);
>> +	}
>> +
>> +	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>> +						GET_VERSION_V5_OUT_BUNDLE_VERSION);
>> +
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>> +			 le32_to_cpu(ver.dwords[2]),
>> +			 le32_to_cpu(ver.dwords[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
>> +						 buf);
>> +	}
>> +}
>> +
>> +static int efx_devlink_info_running_versions(struct efx_nic *efx,
>> +					     struct devlink_info_req *req)
>> +{
>> +	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
>> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>> +	union {
>> +		const __le32 *dwords;
>> +		const __le16 *words;
>> +		const char *str;
>> +	} ver;
>> +	size_t outlength;
>> +	unsigned int flags;
>> +	int rc;
>> +
>> +	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
>> +			  outbuf, sizeof(outbuf), &outlength);
>> +	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
>> +		netif_err(efx, drv, efx->net_dev,
>> +			  "mcdi MC_CMD_GET_VERSION failed\n");
>> +		return rc;
>> +	}
>> +
>> +	/* Handle previous output */
>> +	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
>> +		ver.words = (__le16 *)MCDI_PTR(outbuf,
>> +					       GET_VERSION_EXT_OUT_VERSION);
>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>> +			 le16_to_cpu(ver.words[0]),
>> +			 le16_to_cpu(ver.words[1]),
>> +			 le16_to_cpu(ver.words[2]),
>> +			 le16_to_cpu(ver.words[3]));
>> +
>> +		devlink_info_version_running_put(req,
>> +						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
>> +						 buf);
>> +		return 0;
>> +	}
>> +
>> +	/* Handle V2 additions */
>> +	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
>> +	efx_devlink_info_running_v2(efx, req, flags, outbuf);
>> +
>> +	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
>> +		return 0;
>> +
>> +	/* Handle V3 additions */
>> +	efx_devlink_info_running_v3(efx, req, flags, outbuf);
>> +
>> +	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
>> +		return 0;
>> +
>> +	/* Handle V4 additions */
>> +	efx_devlink_info_running_v4(efx, req, flags, outbuf);
>> +
>> +	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
>> +		return 0;
>> +
>> +	/* Handle V5 additions */
>> +	efx_devlink_info_running_v5(efx, req, flags, outbuf);
>> +
>> +	return 0;
>> +}
>> +
>> +#define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
>> +
>> +static int efx_devlink_info_board_cfg(struct efx_nic *efx,
>> +				      struct devlink_info_req *req)
>> +{
>> +	char sn[EFX_MAX_SERIALNUM_LEN];
>> +	u8 mac_address[ETH_ALEN];
>> +	int rc;
>> +
>> +	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
>> +	if (!rc) {
>> +		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
>> +		devlink_info_serial_number_put(req, sn);
>> +	}
>> +	return rc;
>> +}
>> +
>> +static int efx_devlink_info_get(struct devlink *devlink,
>> +				struct devlink_info_req *req,
>> +				struct netlink_ext_ack *extack)
>> +{
>> +	struct efx_devlink *devlink_private = devlink_priv(devlink);
>> +	struct efx_nic *efx = devlink_private->efx;
>> +	int rc;
>> +
>> +	/* Several different MCDI commands are used. We report first error
>> +	 * through extack along with total number of errors. Specific error
>> +	 * information via system messages.
>> +	 */
>> +	rc = efx_devlink_info_board_cfg(efx, req);
>> +	if (rc) {
>> +		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
>> +		return rc;
>> +	}
>> +	rc = efx_devlink_info_stored_versions(efx, req);
>> +	if (rc) {
>> +		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
>> +		return rc;
>> +	}
>> +	rc = efx_devlink_info_running_versions(efx, req);
>> +	if (rc) {
>> +		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
>> +		return rc;
>> +	}
>> +
>> +	return 0;
>> +}
>> +#endif
>> +
>>   static const struct devlink_ops sfc_devlink_ops = {
>> +#ifdef CONFIG_SFC_SRIOV
>> +	.info_get			= efx_devlink_info_get,
>> +#endif
>>   };
>>   
>>   void efx_fini_devlink_lock(struct efx_nic *efx)
>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
>> index 8ff85b035e87..a5269361c3e0 100644
>> --- a/drivers/net/ethernet/sfc/efx_devlink.h
>> +++ b/drivers/net/ethernet/sfc/efx_devlink.h
>> @@ -14,6 +14,23 @@
>>   #include "net_driver.h"
>>   #include <net/devlink.h>
>>   
>> +/* Custom devlink-info version object names for details that do not map to the
>> + * generic standardized names.
>> + */
>> +#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC	"fw.mgmt.suc"
>> +#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC	"fw.mgmt.cmc"
>> +#define EFX_DEVLINK_INFO_VERSION_FPGA_REV	"fpga.rev"
>> +#define EFX_DEVLINK_INFO_VERSION_DATAPATH_HW	"fpga.app"
>> +#define EFX_DEVLINK_INFO_VERSION_DATAPATH_FW	DEVLINK_INFO_VERSION_GENERIC_FW_APP
>> +#define EFX_DEVLINK_INFO_VERSION_SOC_BOOT	"coproc.boot"
>> +#define EFX_DEVLINK_INFO_VERSION_SOC_UBOOT	"coproc.uboot"
>> +#define EFX_DEVLINK_INFO_VERSION_SOC_MAIN	"coproc.main"
>> +#define EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY	"coproc.recovery"
>> +#define EFX_DEVLINK_INFO_VERSION_FW_EXPROM	"fw.exprom"
>> +#define EFX_DEVLINK_INFO_VERSION_FW_UEFI	"fw.uefi"
>> +
>> +#define EFX_MAX_VERSION_INFO_LEN	64
>> +
>>   int efx_probe_devlink_and_lock(struct efx_nic *efx);
>>   void efx_probe_devlink_unlock(struct efx_nic *efx);
>>   void efx_fini_devlink_lock(struct efx_nic *efx);
>> diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
>> index af338208eae9..2442e33225a6 100644
>> --- a/drivers/net/ethernet/sfc/mcdi.c
>> +++ b/drivers/net/ethernet/sfc/mcdi.c
>> @@ -2175,6 +2175,80 @@ int efx_mcdi_get_privilege_mask(struct efx_nic *efx, u32 *mask)
>>   	return 0;
>>   }
>>   
>> +#ifdef CONFIG_SFC_SRIOV
>> +int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
>> +			    u32 *subtype, u16 version[4], char *desc,
>> +			    size_t descsize)
>> +{
>> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
>> +	efx_dword_t *outbuf;
>> +	size_t outlen;
>> +	u32 flags;
>> +	int rc;
>> +
>> +	outbuf = kzalloc(MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2, GFP_KERNEL);
>> +	if (!outbuf)
>> +		return -ENOMEM;
>> +
>> +	MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
>> +
>> +	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_NVRAM_METADATA, inbuf,
>> +				sizeof(inbuf), outbuf,
>> +				MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2,
>> +				&outlen);
>> +	if (rc)
>> +		goto out_free;
>> +	if (outlen < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
>> +		rc = -EIO;
>> +		goto out_free;
>> +	}
>> +
>> +	flags = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_FLAGS);
>> +
>> +	if (desc && descsize > 0) {
>> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_VALID_LBN)) {
>> +			if (descsize <=
>> +			    MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)) {
>> +				rc = -E2BIG;
>> +				goto out_free;
>> +			}
>> +
>> +			strncpy(desc,
>> +				MCDI_PTR(outbuf, NVRAM_METADATA_OUT_DESCRIPTION),
>> +				MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen));
>> +			desc[MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)] = '\0';
>> +		} else {
>> +			desc[0] = '\0';
>> +		}
>> +	}
>> +
>> +	if (subtype) {
>> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_SUBTYPE_VALID_LBN))
>> +			*subtype = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_SUBTYPE);
>> +		else
>> +			*subtype = 0;
>> +	}
>> +
>> +	if (version) {
>> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_VERSION_VALID_LBN)) {
>> +			version[0] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_W);
>> +			version[1] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_X);
>> +			version[2] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Y);
>> +			version[3] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Z);
>> +		} else {
>> +			version[0] = 0;
>> +			version[1] = 0;
>> +			version[2] = 0;
>> +			version[3] = 0;
>> +		}
>> +	}
>> +
>> +out_free:
>> +	kfree(outbuf);
>> +	return rc;
>> +}
>> +#endif
>> +
>>   #ifdef CONFIG_SFC_MTD
>>   
>>   #define EFX_MCDI_NVRAM_LEN_MAX 128
>> diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
>> index 7e35fec9da35..32f54ce2492e 100644
>> --- a/drivers/net/ethernet/sfc/mcdi.h
>> +++ b/drivers/net/ethernet/sfc/mcdi.h
>> @@ -378,6 +378,11 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
>>   			size_t *size_out, size_t *erase_size_out,
>>   			bool *protected_out);
>>   int efx_new_mcdi_nvram_test_all(struct efx_nic *efx);
>> +#ifdef CONFIG_SFC_SRIOV
>> +int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
>> +			    u32 *subtype, u16 version[4], char *desc,
>> +			    size_t descsize);
>> +#endif
>>   int efx_mcdi_nvram_test_all(struct efx_nic *efx);
>>   int efx_mcdi_handle_assertion(struct efx_nic *efx);
>>   int efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
>> -- 
>> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-09 10:46       ` Lucero Palau, Alejandro
@ 2023-02-10 11:56         ` Jiri Pirko
  0 siblings, 0 replies; 25+ messages in thread
From: Jiri Pirko @ 2023-02-10 11:56 UTC (permalink / raw)
  To: Lucero Palau, Alejandro
  Cc: netdev, linux-net-drivers (AMD-Xilinx),
	davem, kuba, pabeni, edumazet, habetsm.xilinx, ecree.xilinx,
	linux-doc, corbet, jiri

Thu, Feb 09, 2023 at 11:46:04AM CET, alejandro.lucero-palau@amd.com wrote:
>
>On 2/8/23 15:24, Lucero Palau, Alejandro wrote:
>> On 2/8/23 14:38, Jiri Pirko wrote:
>>> Wed, Feb 08, 2023 at 03:25:13PM CET, alejandro.lucero-palau@amd.com wrote:
>>>> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>>> [..]
>>>
>>>
>>>> +static int efx_devlink_info_get(struct devlink *devlink,
>>>> +				struct devlink_info_req *req,
>>>> +				struct netlink_ext_ack *extack)
>>>> +{
>>>> +	struct efx_devlink *devlink_private = devlink_priv(devlink);
>>>> +	struct efx_nic *efx = devlink_private->efx;
>>>> +	int rc;
>>>> +
>>>> +	/* Several different MCDI commands are used. We report first error
>>>> +	 * through extack along with total number of errors. Specific error
>>>> +	 * information via system messages.
>>> I think you forgot to remove this comment.
>>>
>>> With this nit fixed, free free to add:
>>> Reviewed-by: Jiri Pirko <jiri@nvidia.com>
>>>
>> I'll do.
>>
>> Thanks
>
>Just wondering if this single nit deserves a v7 or better to delay it as 
>another patch.
>
>We got another patchset for ef100 ready to be sent and we would prefer 
>to not delay this one more than needed.

Cleaner would be v7, but I don't mind that much. Let the patchbot to
decide :)

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH v6 net-next 2/8] sfc: add devlink info support for ef100
  2023-02-10  9:07     ` Lucero Palau, Alejandro
@ 2023-02-10 15:01       ` Lucero Palau, Alejandro
  0 siblings, 0 replies; 25+ messages in thread
From: Lucero Palau, Alejandro @ 2023-02-10 15:01 UTC (permalink / raw)
  To: Lucero Palau, Alejandro, netdev, linux-net-drivers (AMD-Xilinx),
	davem, kuba, pabeni, edumazet, ecree.xilinx, linux-doc, corbet,
	jiri


On 2/10/23 09:07, Lucero Palau, Alejandro wrote:
> On 2/10/23 08:40, Martin Habets wrote:
>> NAK, see below.
>>
>> On Wed, Feb 08, 2023 at 02:25:13PM +0000, alejandro.lucero-palau@amd.com wrote:
>>> From: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>>>
>>> Add devlink info support for ef100. The information reported is obtained
>>> through the MCDI interface with the specific meaning defined in new
>>> documentation file.
>>>
>>> Signed-off-by: Alejandro Lucero <alejandro.lucero-palau@amd.com>
>>> ---
>>>    Documentation/networking/devlink/index.rst |   1 +
>>>    Documentation/networking/devlink/sfc.rst   |  57 +++
>>>    MAINTAINERS                                |   1 +
>>>    drivers/net/ethernet/sfc/efx_devlink.c     | 460 +++++++++++++++++++++
>>>    drivers/net/ethernet/sfc/efx_devlink.h     |  17 +
>>>    drivers/net/ethernet/sfc/mcdi.c            |  74 ++++
>>>    drivers/net/ethernet/sfc/mcdi.h            |   5 +
>>>    7 files changed, 615 insertions(+)
>>>    create mode 100644 Documentation/networking/devlink/sfc.rst
>>>
>>> diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
>>> index fee4d3968309..b49749e2b9a6 100644
>>> --- a/Documentation/networking/devlink/index.rst
>>> +++ b/Documentation/networking/devlink/index.rst
>>> @@ -66,3 +66,4 @@ parameters, info versions, and other features it supports.
>>>       prestera
>>>       iosm
>>>       octeontx2
>>> +   sfc
>>> diff --git a/Documentation/networking/devlink/sfc.rst b/Documentation/networking/devlink/sfc.rst
>>> new file mode 100644
>>> index 000000000000..db64a1bd9733
>>> --- /dev/null
>>> +++ b/Documentation/networking/devlink/sfc.rst
>>> @@ -0,0 +1,57 @@
>>> +.. SPDX-License-Identifier: GPL-2.0
>>> +
>>> +===================
>>> +sfc devlink support
>>> +===================
>>> +
>>> +This document describes the devlink features implemented by the ``sfc``
>>> +device driver for the ef100 device.
>>> +
>>> +Info versions
>>> +=============
>>> +
>>> +The ``sfc`` driver reports the following versions
>>> +
>>> +.. list-table:: devlink info versions implemented
>>> +   :widths: 5 5 90
>>> +
>>> +   * - Name
>>> +     - Type
>>> +     - Description
>>> +   * - ``fw.mgmt.suc``
>>> +     - running
>>> +     - For boards where the management function is split between multiple
>>> +       control units, this is the SUC control unit's firmware version.
>>> +   * - ``fw.mgmt.cmc``
>>> +     - running
>>> +     - For boards where the management function is split between multiple
>>> +       control units, this is the CMC control unit's firmware version.
>>> +   * - ``fpga.rev``
>>> +     - running
>>> +     - FPGA design revision.
>>> +   * - ``fpga.app``
>>> +     - running
>>> +     - Datapath programmable logic version.
>>> +   * - ``fw.app``
>>> +     - running
>>> +     - Datapath software/microcode/firmware version.
>>> +   * - ``coproc.boot``
>>> +     - running
>>> +     - SmartNIC application co-processor (APU) first stage boot loader version.
>>> +   * - ``coproc.uboot``
>>> +     - running
>>> +     - SmartNIC application co-processor (APU) co-operating system loader version.
>>> +   * - ``coproc.main``
>>> +     - running
>>> +     - SmartNIC application co-processor (APU) main operating system version.
>>> +   * - ``coproc.recovery``
>>> +     - running
>>> +     - SmartNIC application co-processor (APU) recovery operating system version.
>>> +   * - ``fw.exprom``
>>> +     - running
>>> +     - Expansion ROM version. For boards where the expansion ROM is split between
>>> +       multiple images (e.g. PXE and UEFI), this is the specifically the PXE boot
>>> +       ROM version.
>>> +   * - ``fw.uefi``
>>> +     - running
>>> +     - UEFI driver version (No UNDI support).
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 2cf9eb43ed8f..51f7d3448295 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -18937,6 +18937,7 @@ M:	Edward Cree <ecree.xilinx@gmail.com>
>>>    M:	Martin Habets <habetsm.xilinx@gmail.com>
>>>    L:	netdev@vger.kernel.org
>>>    S:	Supported
>>> +F:	Documentation/networking/devlink/sfc.rst
>>>    F:	drivers/net/ethernet/sfc/
>>>    
>>>    SFF/SFP/SFP+ MODULE SUPPORT
>>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c
>>> index 57a7023d3cb6..c06efeac11e5 100644
>>> --- a/drivers/net/ethernet/sfc/efx_devlink.c
>>> +++ b/drivers/net/ethernet/sfc/efx_devlink.c
>>> @@ -9,12 +9,472 @@
>>>     */
>>>    
>>>    #include "efx_devlink.h"
>>> +#ifdef CONFIG_SFC_SRIOV
>> I don't get this SRIOV dependency. In the cover letter you say it
>> was because of IA64, bu those errors were:
>>
>> ia64-linux-ld: drivers/net/ethernet/sfc/ef100_nic.o: in function `ef100_remove':
>>    ef100_nic.c:(.text+0x2e82): undefined reference to `efx_ef100_fini_reps'
>>    ia64-linux-ld: ef100_nic.c:(.text+0x2e92): undefined reference to `efx_fini_mae'
>>
>> which is completely unrelated to this patch.
>> This extra ifdef must not be needed at all. I suspect something else
>> is going wrong in your builds.
>> Please explain in detail why you think you need this.
>>
>> Martin
> This is not due to the ia64 build errors but due to the microblaze build
> errors.
>
> We are using rtc_time64_to_tm twice in the info related code which turns
> out to be not available for Microblaze.
>
> I did take a look and not found a quick way of substituting those calls.
> SRIOV is not configured for Microblaze and I guess it will never be.
>
> This change makes the devlink info command not available if SRIOV is not
> configured which is arguably not a big problem. It can be said the
> device info could be useful in that case what I really doubt. Yes, a
> netdev for the PF can be used, but what do we need devlink for then? Our
> firmware installation/setup is not based on devlink and we have other
> means for obtaining firmware related info.

I'm working on just avoiding calling those functions based on 
CONFIG_RTC_LIB.

That way all the devlink info, except from those timestamps, will be 
available even without SRIOV configured.

> IMO, Microblaze should have not ef100 configured ...
>
>>> +#include <linux/rtc.h>
>>> +#include "mcdi.h"
>>> +#include "mcdi_functions.h"
>>> +#include "mcdi_pcol.h"
>>> +#endif
>>>    
>>>    struct efx_devlink {
>>>    	struct efx_nic *efx;
>>>    };
>>>    
>>> +#ifdef CONFIG_SFC_SRIOV
>>> +static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
>>> +					    struct devlink_info_req *req,
>>> +					    unsigned int partition_type,
>>> +					    const char *version_name)
>>> +{
>>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>>> +	u16 version[4];
>>> +	int rc;
>>> +
>>> +	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
>>> +				     0);
>>> +	if (rc) {
>>> +		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
>>> +			  version_name);
>>> +		return rc;
>>> +	}
>>> +
>>> +	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
>>> +		 version[1], version[2], version[3]);
>>> +	devlink_info_version_stored_put(req, version_name, buf);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int efx_devlink_info_stored_versions(struct efx_nic *efx,
>>> +					    struct devlink_info_req *req)
>>> +{
>>> +	int rc;
>>> +
>>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>>> +					      NVRAM_PARTITION_TYPE_BUNDLE,
>>> +					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
>>> +	if (rc)
>>> +		return rc;
>>> +
>>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>>> +					      NVRAM_PARTITION_TYPE_MC_FIRMWARE,
>>> +					      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
>>> +	if (rc)
>>> +		return rc;
>>> +
>>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>>> +					      NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
>>> +					      EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
>>> +	if (rc)
>>> +		return rc;
>>> +
>>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>>> +					      NVRAM_PARTITION_TYPE_EXPANSION_ROM,
>>> +					      EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
>>> +	if (rc)
>>> +		return rc;
>>> +
>>> +	rc = efx_devlink_info_nvram_partition(efx, req,
>>> +					      NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
>>> +					      EFX_DEVLINK_INFO_VERSION_FW_UEFI);
>>> +	if (rc)
>>> +		return rc;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +#define EFX_VER_FLAG(_f)	\
>>> +	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
>>> +
>>> +static void efx_devlink_info_running_v2(struct efx_nic *efx,
>>> +					struct devlink_info_req *req,
>>> +					unsigned int flags, efx_dword_t *outbuf)
>>> +{
>>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>>> +	union {
>>> +		const __le32 *dwords;
>>> +		const __le16 *words;
>>> +		const char *str;
>>> +	} ver;
>>> +	struct rtc_time build_date;
>>> +	unsigned int build_id;
>>> +	size_t offset;
>>> +	u64 tstamp;
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
>>> +			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
>>> +		devlink_info_version_fixed_put(req,
>>> +					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
>>> +					       buf);
>>> +
>>> +		/* Favour full board version if present (in V5 or later) */
>>> +		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
>>> +			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
>>> +				 MCDI_DWORD(outbuf,
>>> +					    GET_VERSION_V2_OUT_BOARD_REVISION));
>>> +			devlink_info_version_fixed_put(req,
>>> +						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
>>> +						       buf);
>>> +		}
>>> +
>>> +		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
>>> +		if (ver.str[0])
>>> +			devlink_info_board_serial_number_put(req, ver.str);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V2_OUT_FPGA_VERSION);
>>> +		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
>>> +				  le32_to_cpu(ver.dwords[0]),
>>> +				  'A' + le32_to_cpu(ver.dwords[1]),
>>> +				  le32_to_cpu(ver.dwords[2]));
>>> +
>>> +		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
>>> +		if (ver.str[0])
>>> +			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
>>> +				 " (%s)", ver.str);
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
>>> +						 buf);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V2_OUT_CMCFW_VERSION);
>>> +		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +				  le32_to_cpu(ver.dwords[0]),
>>> +				  le32_to_cpu(ver.dwords[1]),
>>> +				  le32_to_cpu(ver.dwords[2]),
>>> +				  le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		tstamp = MCDI_QWORD(outbuf,
>>> +				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
>>> +		if (tstamp) {
>>> +			rtc_time64_to_tm(tstamp, &build_date);
>>> +			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
>>> +				 " (%ptRd)", &build_date);
>>> +		}
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
>>> +						 buf);
>>> +	}
>>> +
>>> +	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
>>> +	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
>>> +			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
>>> +	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
>>> +		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
>>> +		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
>>> +			 " (%x) %s", build_id,
>>> +			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
>>> +	}
>>> +	devlink_info_version_running_put(req,
>>> +					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
>>> +					 buf);
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V2_OUT_SUCFW_VERSION);
>>> +		tstamp = MCDI_QWORD(outbuf,
>>> +				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
>>> +		rtc_time64_to_tm(tstamp, &build_date);
>>> +		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
>>> +			 "%u.%u.%u.%u type %x (%ptRd)",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
>>> +			 build_id, &build_date);
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
>>> +						 buf);
>>> +	}
>>> +}
>>> +
>>> +static void efx_devlink_info_running_v3(struct efx_nic *efx,
>>> +					struct devlink_info_req *req,
>>> +					unsigned int flags, efx_dword_t *outbuf)
>>> +{
>>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>>> +	union {
>>> +		const __le32 *dwords;
>>> +		const __le16 *words;
>>> +		const char *str;
>>> +	} ver;
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
>>> +						 buf);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
>>> +						 buf);
>>> +	}
>>> +}
>>> +
>>> +static void efx_devlink_info_running_v4(struct efx_nic *efx,
>>> +					struct devlink_info_req *req,
>>> +					unsigned int flags, efx_dword_t *outbuf)
>>> +{
>>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>>> +	union {
>>> +		const __le32 *dwords;
>>> +		const __le16 *words;
>>> +		const char *str;
>>> +	} ver;
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]),
>>> +			 le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
>>> +						 buf);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]),
>>> +			 le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
>>> +						 buf);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]),
>>> +			 le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
>>> +						 buf);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]),
>>> +			 le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
>>> +						 buf);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
>>> +	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V4_OUT_SUCFW_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]),
>>> +			 le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
>>> +						 buf);
>>> +	}
>>> +}
>>> +
>>> +static void efx_devlink_info_running_v5(struct efx_nic *efx,
>>> +					struct devlink_info_req *req,
>>> +					unsigned int flags, efx_dword_t *outbuf)
>>> +{
>>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>>> +	union {
>>> +		const __le32 *dwords;
>>> +		const __le16 *words;
>>> +		const char *str;
>>> +	} ver;
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V5_OUT_BOARD_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]),
>>> +			 le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
>>> +						 buf);
>>> +	}
>>> +
>>> +	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
>>> +		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
>>> +						GET_VERSION_V5_OUT_BUNDLE_VERSION);
>>> +
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
>>> +			 le32_to_cpu(ver.dwords[2]),
>>> +			 le32_to_cpu(ver.dwords[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
>>> +						 buf);
>>> +	}
>>> +}
>>> +
>>> +static int efx_devlink_info_running_versions(struct efx_nic *efx,
>>> +					     struct devlink_info_req *req)
>>> +{
>>> +	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
>>> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
>>> +	char buf[EFX_MAX_VERSION_INFO_LEN];
>>> +	union {
>>> +		const __le32 *dwords;
>>> +		const __le16 *words;
>>> +		const char *str;
>>> +	} ver;
>>> +	size_t outlength;
>>> +	unsigned int flags;
>>> +	int rc;
>>> +
>>> +	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
>>> +			  outbuf, sizeof(outbuf), &outlength);
>>> +	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
>>> +		netif_err(efx, drv, efx->net_dev,
>>> +			  "mcdi MC_CMD_GET_VERSION failed\n");
>>> +		return rc;
>>> +	}
>>> +
>>> +	/* Handle previous output */
>>> +	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
>>> +		ver.words = (__le16 *)MCDI_PTR(outbuf,
>>> +					       GET_VERSION_EXT_OUT_VERSION);
>>> +		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
>>> +			 le16_to_cpu(ver.words[0]),
>>> +			 le16_to_cpu(ver.words[1]),
>>> +			 le16_to_cpu(ver.words[2]),
>>> +			 le16_to_cpu(ver.words[3]));
>>> +
>>> +		devlink_info_version_running_put(req,
>>> +						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
>>> +						 buf);
>>> +		return 0;
>>> +	}
>>> +
>>> +	/* Handle V2 additions */
>>> +	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
>>> +	efx_devlink_info_running_v2(efx, req, flags, outbuf);
>>> +
>>> +	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
>>> +		return 0;
>>> +
>>> +	/* Handle V3 additions */
>>> +	efx_devlink_info_running_v3(efx, req, flags, outbuf);
>>> +
>>> +	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
>>> +		return 0;
>>> +
>>> +	/* Handle V4 additions */
>>> +	efx_devlink_info_running_v4(efx, req, flags, outbuf);
>>> +
>>> +	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
>>> +		return 0;
>>> +
>>> +	/* Handle V5 additions */
>>> +	efx_devlink_info_running_v5(efx, req, flags, outbuf);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +#define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
>>> +
>>> +static int efx_devlink_info_board_cfg(struct efx_nic *efx,
>>> +				      struct devlink_info_req *req)
>>> +{
>>> +	char sn[EFX_MAX_SERIALNUM_LEN];
>>> +	u8 mac_address[ETH_ALEN];
>>> +	int rc;
>>> +
>>> +	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
>>> +	if (!rc) {
>>> +		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
>>> +		devlink_info_serial_number_put(req, sn);
>>> +	}
>>> +	return rc;
>>> +}
>>> +
>>> +static int efx_devlink_info_get(struct devlink *devlink,
>>> +				struct devlink_info_req *req,
>>> +				struct netlink_ext_ack *extack)
>>> +{
>>> +	struct efx_devlink *devlink_private = devlink_priv(devlink);
>>> +	struct efx_nic *efx = devlink_private->efx;
>>> +	int rc;
>>> +
>>> +	/* Several different MCDI commands are used. We report first error
>>> +	 * through extack along with total number of errors. Specific error
>>> +	 * information via system messages.
>>> +	 */
>>> +	rc = efx_devlink_info_board_cfg(efx, req);
>>> +	if (rc) {
>>> +		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
>>> +		return rc;
>>> +	}
>>> +	rc = efx_devlink_info_stored_versions(efx, req);
>>> +	if (rc) {
>>> +		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
>>> +		return rc;
>>> +	}
>>> +	rc = efx_devlink_info_running_versions(efx, req);
>>> +	if (rc) {
>>> +		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
>>> +		return rc;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +#endif
>>> +
>>>    static const struct devlink_ops sfc_devlink_ops = {
>>> +#ifdef CONFIG_SFC_SRIOV
>>> +	.info_get			= efx_devlink_info_get,
>>> +#endif
>>>    };
>>>    
>>>    void efx_fini_devlink_lock(struct efx_nic *efx)
>>> diff --git a/drivers/net/ethernet/sfc/efx_devlink.h b/drivers/net/ethernet/sfc/efx_devlink.h
>>> index 8ff85b035e87..a5269361c3e0 100644
>>> --- a/drivers/net/ethernet/sfc/efx_devlink.h
>>> +++ b/drivers/net/ethernet/sfc/efx_devlink.h
>>> @@ -14,6 +14,23 @@
>>>    #include "net_driver.h"
>>>    #include <net/devlink.h>
>>>    
>>> +/* Custom devlink-info version object names for details that do not map to the
>>> + * generic standardized names.
>>> + */
>>> +#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC	"fw.mgmt.suc"
>>> +#define EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC	"fw.mgmt.cmc"
>>> +#define EFX_DEVLINK_INFO_VERSION_FPGA_REV	"fpga.rev"
>>> +#define EFX_DEVLINK_INFO_VERSION_DATAPATH_HW	"fpga.app"
>>> +#define EFX_DEVLINK_INFO_VERSION_DATAPATH_FW	DEVLINK_INFO_VERSION_GENERIC_FW_APP
>>> +#define EFX_DEVLINK_INFO_VERSION_SOC_BOOT	"coproc.boot"
>>> +#define EFX_DEVLINK_INFO_VERSION_SOC_UBOOT	"coproc.uboot"
>>> +#define EFX_DEVLINK_INFO_VERSION_SOC_MAIN	"coproc.main"
>>> +#define EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY	"coproc.recovery"
>>> +#define EFX_DEVLINK_INFO_VERSION_FW_EXPROM	"fw.exprom"
>>> +#define EFX_DEVLINK_INFO_VERSION_FW_UEFI	"fw.uefi"
>>> +
>>> +#define EFX_MAX_VERSION_INFO_LEN	64
>>> +
>>>    int efx_probe_devlink_and_lock(struct efx_nic *efx);
>>>    void efx_probe_devlink_unlock(struct efx_nic *efx);
>>>    void efx_fini_devlink_lock(struct efx_nic *efx);
>>> diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
>>> index af338208eae9..2442e33225a6 100644
>>> --- a/drivers/net/ethernet/sfc/mcdi.c
>>> +++ b/drivers/net/ethernet/sfc/mcdi.c
>>> @@ -2175,6 +2175,80 @@ int efx_mcdi_get_privilege_mask(struct efx_nic *efx, u32 *mask)
>>>    	return 0;
>>>    }
>>>    
>>> +#ifdef CONFIG_SFC_SRIOV
>>> +int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
>>> +			    u32 *subtype, u16 version[4], char *desc,
>>> +			    size_t descsize)
>>> +{
>>> +	MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
>>> +	efx_dword_t *outbuf;
>>> +	size_t outlen;
>>> +	u32 flags;
>>> +	int rc;
>>> +
>>> +	outbuf = kzalloc(MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2, GFP_KERNEL);
>>> +	if (!outbuf)
>>> +		return -ENOMEM;
>>> +
>>> +	MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
>>> +
>>> +	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_NVRAM_METADATA, inbuf,
>>> +				sizeof(inbuf), outbuf,
>>> +				MC_CMD_NVRAM_METADATA_OUT_LENMAX_MCDI2,
>>> +				&outlen);
>>> +	if (rc)
>>> +		goto out_free;
>>> +	if (outlen < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
>>> +		rc = -EIO;
>>> +		goto out_free;
>>> +	}
>>> +
>>> +	flags = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_FLAGS);
>>> +
>>> +	if (desc && descsize > 0) {
>>> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_VALID_LBN)) {
>>> +			if (descsize <=
>>> +			    MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)) {
>>> +				rc = -E2BIG;
>>> +				goto out_free;
>>> +			}
>>> +
>>> +			strncpy(desc,
>>> +				MCDI_PTR(outbuf, NVRAM_METADATA_OUT_DESCRIPTION),
>>> +				MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen));
>>> +			desc[MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_NUM(outlen)] = '\0';
>>> +		} else {
>>> +			desc[0] = '\0';
>>> +		}
>>> +	}
>>> +
>>> +	if (subtype) {
>>> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_SUBTYPE_VALID_LBN))
>>> +			*subtype = MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_SUBTYPE);
>>> +		else
>>> +			*subtype = 0;
>>> +	}
>>> +
>>> +	if (version) {
>>> +		if (flags & BIT(MC_CMD_NVRAM_METADATA_OUT_VERSION_VALID_LBN)) {
>>> +			version[0] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_W);
>>> +			version[1] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_X);
>>> +			version[2] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Y);
>>> +			version[3] = MCDI_WORD(outbuf, NVRAM_METADATA_OUT_VERSION_Z);
>>> +		} else {
>>> +			version[0] = 0;
>>> +			version[1] = 0;
>>> +			version[2] = 0;
>>> +			version[3] = 0;
>>> +		}
>>> +	}
>>> +
>>> +out_free:
>>> +	kfree(outbuf);
>>> +	return rc;
>>> +}
>>> +#endif
>>> +
>>>    #ifdef CONFIG_SFC_MTD
>>>    
>>>    #define EFX_MCDI_NVRAM_LEN_MAX 128
>>> diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
>>> index 7e35fec9da35..32f54ce2492e 100644
>>> --- a/drivers/net/ethernet/sfc/mcdi.h
>>> +++ b/drivers/net/ethernet/sfc/mcdi.h
>>> @@ -378,6 +378,11 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
>>>    			size_t *size_out, size_t *erase_size_out,
>>>    			bool *protected_out);
>>>    int efx_new_mcdi_nvram_test_all(struct efx_nic *efx);
>>> +#ifdef CONFIG_SFC_SRIOV
>>> +int efx_mcdi_nvram_metadata(struct efx_nic *efx, unsigned int type,
>>> +			    u32 *subtype, u16 version[4], char *desc,
>>> +			    size_t descsize);
>>> +#endif
>>>    int efx_mcdi_nvram_test_all(struct efx_nic *efx);
>>>    int efx_mcdi_handle_assertion(struct efx_nic *efx);
>>>    int efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
>>> -- 
>>> 2.17.1

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2023-02-10 15:02 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-08 14:25 [PATCH v6 net-next 0/8] sfc: devlink support for ef100 alejandro.lucero-palau
2023-02-08 14:25 ` [PATCH v6 net-next 1/8] sfc: add " alejandro.lucero-palau
2023-02-10  8:28   ` Martin Habets
2023-02-08 14:25 ` [PATCH v6 net-next 2/8] sfc: add devlink info " alejandro.lucero-palau
2023-02-08 14:38   ` Jiri Pirko
2023-02-08 15:24     ` Lucero Palau, Alejandro
2023-02-09 10:46       ` Lucero Palau, Alejandro
2023-02-10 11:56         ` Jiri Pirko
2023-02-10  8:40   ` Martin Habets
2023-02-10  9:07     ` Lucero Palau, Alejandro
2023-02-10 15:01       ` Lucero Palau, Alejandro
2023-02-08 14:25 ` [PATCH v6 net-next 3/8] sfc: enumerate mports in ef100 alejandro.lucero-palau
2023-02-10  8:46   ` Martin Habets
2023-02-08 14:25 ` [PATCH v6 net-next 4/8] sfc: add mport lookup based on driver's mport data alejandro.lucero-palau
2023-02-10  8:47   ` Martin Habets
2023-02-08 14:25 ` [PATCH v6 net-next 5/8] sfc: add devlink port support for ef100 alejandro.lucero-palau
2023-02-10  8:49   ` Martin Habets
2023-02-08 14:25 ` [PATCH v6 net-next 6/8] sfc: obtain device mac address based on firmware handle " alejandro.lucero-palau
2023-02-10  8:50   ` Martin Habets
2023-02-08 14:25 ` [PATCH v6 net-next 7/8] sfc: add support for devlink port_function_hw_addr_get in ef100 alejandro.lucero-palau
2023-02-08 14:40   ` Jiri Pirko
2023-02-10  8:52   ` Martin Habets
2023-02-08 14:25 ` [PATCH v6 net-next 8/8] sfc: add support for devlink port_function_hw_addr_set " alejandro.lucero-palau
2023-02-08 14:40   ` Jiri Pirko
2023-02-10  8:53   ` Martin Habets

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).