Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH iwl-next v2 0/4] idpf: add devlink info support with selftest
@ 2026-09-03  8:27 Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 1/4] idpf: clear drvdata in idpf_decfg_device() Paul Greenwalt
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Paul Greenwalt @ 2026-09-03  8:27 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: Paul Greenwalt

Add initial devlink support for idpf and a matching selftest.

Patch 1 consolidates the drvdata clear into idpf_decfg_device(), the
declared inverse of idpf_cfg_device() which sets it.

Patch 2 adds the devlink instance. It is registered once the virtchnl
handshake has completed rather than from idpf_probe(), so the instance
is not exposed to userspace while the adapter is still coming up.

Patch 3 implements .info_get and reports:
  - serial_number: PCI Device Serial Number, for NIPA CI identification
  - fw.mgmt.api (running): driver-device communication protocol version

This follows a phased approach and reports stable, readily-available
information. Firmware version support will be added in future patches as
it becomes available through virtchnl.

Patch 4 adds a hardware selftest that logs devlink info in the format
NIPA CI consumes.

v1 -> v2:
- Patch 1:
  - Reworked: instead of adding a second, redundant pci_set_drvdata(NULL)
    at idpf_probe()'s err_free label, move the clear into
    idpf_decfg_device() so it pairs with the set in idpf_cfg_device(),
    and drop the now-redundant explicit clear in idpf_remove().
- Patch 2 (new, split out of the old patch 2):
  - Register the devlink instance from idpf_init_hard_reset() once
    idpf_vc_core_init() has succeeded, instead of from idpf_probe().
    Registration is guarded by IDPF_DEVLINK_REGISTERED since
    idpf_init_hard_reset() also runs on every function and PCI reset.
  - Unregister only after the init/reset worker is quiesced, and only if
    registration actually happened.
- Patch 3:
  - Select NET_DEVLINK in Kconfig.
  - Omit serial_number when the device reports no PCI DSN, instead of
    reporting an all-zero serial number.
  - Pass the buffer size to the DSN helper rather than hardcoding it.
  - The version guard is no longer needed now that the instance is only
    registered after the virtchnl handshake has completed.
- Patch 4:
  - Read NETIF from drivers/net/net.config as documented in
    drivers/net/README.rst, in addition to the environment.
  - Skip, rather than fail, devices that report no versions and no serial
    number; implementing devlink info is optional and devlink reports a
    driver name even when info_get is absent.
  - Count and log board.serial_number.
  - Treat a devlink/ethtool driver name difference as informational; it
    is legitimate for e.g. mlx4 and DSA user ports.
  - Do not require ethtool; it is only used for an optional fallback
    handle lookup and the driver name comparison.
  - Query devlink dev info once and validate a single snapshot.
  - Log the reported versions.

Paul Greenwalt (4):
  idpf: clear drvdata in idpf_decfg_device()
  idpf: add devlink support
  idpf: add devlink info support
  selftests: net: hw: add devlink info test

 Documentation/networking/devlink/idpf.rst     |  30 ++++
 Documentation/networking/devlink/index.rst    |   1 +
 drivers/net/ethernet/intel/idpf/Kconfig       |   1 +
 drivers/net/ethernet/intel/idpf/Makefile      |   1 +
 drivers/net/ethernet/intel/idpf/idpf.h        |   4 +-
 .../net/ethernet/intel/idpf/idpf_devlink.c    |  94 ++++++++++
 .../net/ethernet/intel/idpf/idpf_devlink.h    |  45 +++++
 drivers/net/ethernet/intel/idpf/idpf_lib.c    |   8 +
 drivers/net/ethernet/intel/idpf/idpf_main.c   |  19 ++-
 .../testing/selftests/drivers/net/hw/Makefile |   1 +
 .../selftests/drivers/net/hw/devlink_info.sh  | 160 ++++++++++++++++++
 11 files changed, 359 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/networking/devlink/idpf.rst
 create mode 100644 drivers/net/ethernet/intel/idpf/idpf_devlink.c
 create mode 100644 drivers/net/ethernet/intel/idpf/idpf_devlink.h
 create mode 100755 tools/testing/selftests/drivers/net/hw/devlink_info.sh

-- 
2.52.0


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

* [PATCH iwl-next v2 1/4] idpf: clear drvdata in idpf_decfg_device()
  2026-09-03  8:27 [PATCH iwl-next v2 0/4] idpf: add devlink info support with selftest Paul Greenwalt
@ 2026-09-03  8:27 ` Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 2/4] idpf: add devlink support Paul Greenwalt
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Greenwalt @ 2026-09-03  8:27 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: Paul Greenwalt, Przemek Kitszel, Aleksandr Loktionov

pci_set_drvdata(pdev, adapter) is set as the last step of
idpf_cfg_device(), but its declared inverse, idpf_decfg_device(),
does not clear it. idpf_remove() open-codes the clear right after
calling idpf_decfg_device(), so the two functions are not true
opposites of each other.

Move the pci_set_drvdata(pdev, NULL) into idpf_decfg_device() so the
set/clear pairing lives in one place, and drop the now-redundant
explicit clear from idpf_remove(). idpf_decfg_device() is also called
from idpf_probe()'s err_init_wq unwind path, which did not previously
clear drvdata at all; it now does too, closing that window for
consistency with the rest of the teardown path. This has no
observable effect: the driver core already clears drvdata via
dev_set_drvdata() when a probe function returns an error, under
device_lock(), before any consumer of drvdata can observe a stale
pointer.

Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
---
 drivers/net/ethernet/intel/idpf/idpf_main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c
index 1e4dd9b713a0..fc67d8f02569 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_main.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -112,6 +112,9 @@ static void idpf_decfg_device(struct idpf_adapter *adapter)
 		pci_disable_ptm(pdev);
 
 	libie_pci_unmap_all_mmio_regions(&adapter->ctlq_ctx.mmio_info);
+
+	/* pairs with pci_set_drvdata() in idpf_cfg_device() */
+	pci_set_drvdata(pdev, NULL);
 }
 
 /**
@@ -182,7 +185,6 @@ static void idpf_remove(struct pci_dev *pdev)
 	mutex_destroy(&adapter->vc_buf_lock);
 
 	idpf_decfg_device(adapter);
-	pci_set_drvdata(pdev, NULL);
 	kfree(adapter);
 }
 
-- 
2.52.0


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

* [PATCH iwl-next v2 2/4] idpf: add devlink support
  2026-09-03  8:27 [PATCH iwl-next v2 0/4] idpf: add devlink info support with selftest Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 1/4] idpf: clear drvdata in idpf_decfg_device() Paul Greenwalt
@ 2026-09-03  8:27 ` Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 3/4] idpf: add devlink info support Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 4/4] selftests: net: hw: add devlink info test Paul Greenwalt
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Greenwalt @ 2026-09-03  8:27 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: Paul Greenwalt

Add a devlink instance for the idpf adapter. The adapter structure is
carved out of the devlink private area, so devlink_alloc() replaces the
plain kzalloc_obj() in idpf_probe() and devlink_free() replaces the
corresponding kfree() on both the probe error path and in idpf_remove().

The instance is registered from idpf_init_hard_reset(), once
idpf_vc_core_init() has succeeded, rather than from idpf_probe(). Device
information is only meaningful after the virtchnl handshake has
completed, and registering in idpf_probe() would expose the instance to
userspace while the adapter is still being brought up. Since
idpf_init_hard_reset() also runs for every function and PCI reset,
registration is guarded by IDPF_DEVLINK_REGISTERED so that it happens at
most once; devlink_register() warns on an already registered instance.

idpf_remove() unregisters only after cancel_delayed_work_sync() has
quiesced the init/reset worker, so the worker cannot register the
instance again after teardown has started, and only if registration
actually happened - a probe that never completed the handshake leaves
the instance unregistered, and devlink_unregister() warns in that case.

Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
---
 drivers/net/ethernet/intel/idpf/Kconfig       |  1 +
 drivers/net/ethernet/intel/idpf/Makefile      |  1 +
 drivers/net/ethernet/intel/idpf/idpf.h        |  4 +-
 .../net/ethernet/intel/idpf/idpf_devlink.c    | 29 ++++++++++++
 .../net/ethernet/intel/idpf/idpf_devlink.h    | 45 +++++++++++++++++++
 drivers/net/ethernet/intel/idpf/idpf_lib.c    |  8 ++++
 drivers/net/ethernet/intel/idpf/idpf_main.c   | 15 +++++--
 7 files changed, 99 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/idpf/idpf_devlink.c
 create mode 100644 drivers/net/ethernet/intel/idpf/idpf_devlink.h

diff --git a/drivers/net/ethernet/intel/idpf/Kconfig b/drivers/net/ethernet/intel/idpf/Kconfig
index 586df3a4afe9..4ee8bbc401fe 100644
--- a/drivers/net/ethernet/intel/idpf/Kconfig
+++ b/drivers/net/ethernet/intel/idpf/Kconfig
@@ -6,6 +6,7 @@ config IDPF
 	depends on PCI_MSI
 	depends on PTP_1588_CLOCK_OPTIONAL
 	select DIMLIB
+	select NET_DEVLINK
 	select LIBIE_CP
 	select LIBETH_XDP
 	help
diff --git a/drivers/net/ethernet/intel/idpf/Makefile b/drivers/net/ethernet/intel/idpf/Makefile
index 4aaafa175ec3..81b27a406747 100644
--- a/drivers/net/ethernet/intel/idpf/Makefile
+++ b/drivers/net/ethernet/intel/idpf/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_IDPF) += idpf.o
 
 idpf-y := \
 	idpf_dev.o		\
+	idpf_devlink.o		\
 	idpf_ethtool.o		\
 	idpf_idc.o		\
 	idpf_lib.o		\
diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index df9e42bfeaa2..b72f31560fd2 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -81,7 +81,7 @@ enum idpf_state {
 };
 
 /**
- * enum idpf_flags - Hard reset causes.
+ * enum idpf_flags - Adapter state flags
  * @IDPF_HR_FUNC_RESET: Hard reset when TxRx timeout
  * @IDPF_HR_DRV_LOAD: Set on driver load for a clean HW
  * @IDPF_HR_RESET_IN_PROG: Reset in progress
@@ -89,6 +89,7 @@ enum idpf_state {
  * @IDPF_MB_INTR_MODE: Mailbox in interrupt mode
  * @IDPF_VC_CORE_INIT: virtchnl core has been init
  * @IDPF_PCI_CB_RESET: Reset via the PCI callbacks
+ * @IDPF_DEVLINK_REGISTERED: devlink instance is registered with userspace
  * @IDPF_FLAGS_NBITS: Must be last
  */
 enum idpf_flags {
@@ -99,6 +100,7 @@ enum idpf_flags {
 	IDPF_MB_INTR_MODE,
 	IDPF_VC_CORE_INIT,
 	IDPF_PCI_CB_RESET,
+	IDPF_DEVLINK_REGISTERED,
 	IDPF_FLAGS_NBITS,
 };
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_devlink.c b/drivers/net/ethernet/intel/idpf/idpf_devlink.c
new file mode 100644
index 000000000000..1669bdfc950b
--- /dev/null
+++ b/drivers/net/ethernet/intel/idpf/idpf_devlink.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2026 Intel Corporation */
+
+#include "idpf.h"
+#include "idpf_devlink.h"
+
+static const struct devlink_ops idpf_devlink_ops = {
+};
+
+/**
+ * idpf_adapter_alloc - allocate devlink and return adapter
+ * @dev: IDPF device to allocate for
+ *
+ * Allocate a devlink instance for this device and return the private area as
+ * the adapter structure.
+ *
+ * Return: adapter structure on success, NULL on failure
+ */
+struct idpf_adapter *idpf_adapter_alloc(struct device *dev)
+{
+	struct devlink *devlink;
+
+	devlink = devlink_alloc(&idpf_devlink_ops, sizeof(struct idpf_adapter),
+				dev);
+	if (!devlink)
+		return NULL;
+
+	return devlink_priv(devlink);
+}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_devlink.h b/drivers/net/ethernet/intel/idpf/idpf_devlink.h
new file mode 100644
index 000000000000..3ace09be8ddd
--- /dev/null
+++ b/drivers/net/ethernet/intel/idpf/idpf_devlink.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (C) 2026 Intel Corporation */
+
+#ifndef _IDPF_DEVLINK_H_
+#define _IDPF_DEVLINK_H_
+#include <net/devlink.h>
+
+struct idpf_adapter;
+
+struct idpf_adapter *idpf_adapter_alloc(struct device *dev);
+
+/**
+ * idpf_devlink_free - teardown the devlink
+ * @adapter: IDPF adapter structure to free
+ */
+static inline void idpf_devlink_free(struct idpf_adapter *adapter)
+{
+	struct devlink *devlink = priv_to_devlink(adapter);
+
+	devlink_free(devlink);
+}
+
+/**
+ * idpf_devlink_register - register the devlink
+ * @adapter: IDPF adapter structure
+ */
+static inline void idpf_devlink_register(struct idpf_adapter *adapter)
+{
+	struct devlink *devlink = priv_to_devlink(adapter);
+
+	devlink_register(devlink);
+}
+
+/**
+ * idpf_devlink_unregister - unregister the devlink
+ * @adapter: IDPF adapter structure
+ */
+static inline void idpf_devlink_unregister(struct idpf_adapter *adapter)
+{
+	struct devlink *devlink = priv_to_devlink(adapter);
+
+	devlink_unregister(devlink);
+}
+
+#endif /* _IDPF_DEVLINK_H_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 5d61ecb73a40..a375028c7080 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -2,6 +2,7 @@
 /* Copyright (C) 2023 Intel Corporation */
 
 #include "idpf.h"
+#include "idpf_devlink.h"
 #include "idpf_virtchnl.h"
 #include "idpf_ptp.h"
 #include "xdp.h"
@@ -1968,6 +1969,13 @@ static void idpf_init_hard_reset(struct idpf_adapter *adapter)
 	 * vports are not allocated at this point if the init task failed.
 	 */
 	if (!err) {
+		/* Expose the instance only once the device has been brought up
+		 * far enough to answer info requests. This runs on every hard
+		 * reset, so registration must happen at most once.
+		 */
+		if (!test_and_set_bit(IDPF_DEVLINK_REGISTERED, adapter->flags))
+			idpf_devlink_register(adapter);
+
 		idpf_attach_and_open(adapter);
 		idpf_idc_init(adapter);
 	}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c
index fc67d8f02569..ba09a130f200 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_main.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -3,6 +3,7 @@
 
 #include "idpf.h"
 #include "idpf_devids.h"
+#include "idpf_devlink.h"
 #include "idpf_lan_vf_regs.h"
 #include "idpf_virtchnl.h"
 
@@ -134,6 +135,13 @@ static void idpf_remove(struct pci_dev *pdev)
 	 * end up in bad state.
 	 */
 	cancel_delayed_work_sync(&adapter->vc_event_task);
+
+	/* IDPF_REMOVE_IN_PROG, set above, makes idpf_vc_event_task() return
+	 * early, so the instance cannot be registered again after this point.
+	 */
+	if (test_and_clear_bit(IDPF_DEVLINK_REGISTERED, adapter->flags))
+		idpf_devlink_unregister(adapter);
+
 	if (adapter->num_vfs)
 		idpf_sriov_configure(pdev, 0);
 
@@ -185,7 +193,8 @@ static void idpf_remove(struct pci_dev *pdev)
 	mutex_destroy(&adapter->vc_buf_lock);
 
 	idpf_decfg_device(adapter);
-	kfree(adapter);
+
+	idpf_devlink_free(adapter);
 }
 
 /**
@@ -264,7 +273,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct idpf_adapter *adapter;
 	int err;
 
-	adapter = kzalloc_obj(*adapter);
+	adapter = idpf_adapter_alloc(dev);
 	if (!adapter)
 		return -ENOMEM;
 
@@ -368,7 +377,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 err_init_wq:
 	idpf_decfg_device(adapter);
 err_free:
-	kfree(adapter);
+	idpf_devlink_free(adapter);
 	return err;
 }
 
-- 
2.52.0


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

* [PATCH iwl-next v2 3/4] idpf: add devlink info support
  2026-09-03  8:27 [PATCH iwl-next v2 0/4] idpf: add devlink info support with selftest Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 1/4] idpf: clear drvdata in idpf_decfg_device() Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 2/4] idpf: add devlink support Paul Greenwalt
@ 2026-09-03  8:27 ` Paul Greenwalt
  2026-09-03  8:27 ` [PATCH iwl-next v2 4/4] selftests: net: hw: add devlink info test Paul Greenwalt
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Greenwalt @ 2026-09-03  8:27 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: Paul Greenwalt

Implement the devlink .info_get callback for idpf, reporting:
  - serial_number: PCI Device Serial Number, for device identification
  - fw.mgmt.api: running version of the driver-device communication
    channel (virtchnl)

This enables NIPA CI and other tools to uniquely identify devices under
test and track device capabilities. This phased implementation initially
focuses on stable, readily available information. Firmware version
information will be added in future patches as support is exposed
through virtchnl and the driver architecture allows reliable retrieval.

The serial number is omitted on devices that do not implement the PCI
Device Serial Number extended capability, where pci_get_dsn() returns 0,
rather than reporting an all-zero serial number.

$ devlink dev show
pci/0000:85:00.0

$ devlink dev info pci/0000:85:00.0
pci/0000:85:00.0:
  driver idpf
  serial_number 00-a0-c9-ff-ff-23-45-67
  versions:
      running:
        fw.mgmt.api 2.0

Link: https://github.com/linux-netdev/nipa/wiki/Netdev-CI-system#device-information
Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
---
 Documentation/networking/devlink/idpf.rst     | 30 +++++++++
 Documentation/networking/devlink/index.rst    |  1 +
 .../net/ethernet/intel/idpf/idpf_devlink.c    | 65 +++++++++++++++++++
 3 files changed, 96 insertions(+)
 create mode 100644 Documentation/networking/devlink/idpf.rst

diff --git a/Documentation/networking/devlink/idpf.rst b/Documentation/networking/devlink/idpf.rst
new file mode 100644
index 000000000000..91e25b872f4f
--- /dev/null
+++ b/Documentation/networking/devlink/idpf.rst
@@ -0,0 +1,30 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================
+idpf devlink support
+====================
+
+This document describes the devlink features implemented by the ``idpf``
+device driver.
+
+Info versions
+=============
+
+The following table lists the version reported by the ``idpf`` driver.
+
+.. list-table:: devlink info versions implemented
+    :widths: 5 5 5 90
+
+    * - Name
+      - Type
+      - Example
+      - Description
+    * - ``fw.mgmt.api``
+      - running
+      - 2.0
+      - 2-digit version number (major.minor) of the communication channel
+        (virtchnl) used by the device.
+
+The driver also reports the PCI Device Serial Number through the
+``serial_number`` attribute, on devices that implement the PCI Device Serial
+Number extended capability.
diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst
index d4a83fdcff7f..538494b1051b 100644
--- a/Documentation/networking/devlink/index.rst
+++ b/Documentation/networking/devlink/index.rst
@@ -85,6 +85,7 @@ parameters, info versions, and other features it supports.
    hns3
    i40e
    ice
+   idpf
    ionic
    iosm
    ixd
diff --git a/drivers/net/ethernet/intel/idpf/idpf_devlink.c b/drivers/net/ethernet/intel/idpf/idpf_devlink.c
index 1669bdfc950b..527c7714f9f7 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_devlink.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_devlink.c
@@ -1,10 +1,75 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (C) 2026 Intel Corporation */
 
+#include <linux/pci.h>
+#include <linux/unaligned.h>
+
 #include "idpf.h"
 #include "idpf_devlink.h"
 
+#define IDPF_DEVLINK_INFO_LEN		128
+
+/**
+ * idpf_info_get_dsn - format the PCI DSN as the device serial number
+ * @adapter: the idpf adapter structure
+ * @buf: buffer to store the formatted serial number
+ * @buf_size: size of @buf
+ *
+ * Return: true if the device reports a DSN, false otherwise.
+ */
+static bool idpf_info_get_dsn(struct idpf_adapter *adapter, char *buf,
+			      size_t buf_size)
+{
+	u64 dsn = pci_get_dsn(adapter->pdev);
+	u8 dsn_be[sizeof(dsn)];
+
+	if (!dsn)
+		return false;
+
+	/* Copy the DSN into an array in Big Endian format */
+	put_unaligned_be64(dsn, dsn_be);
+	snprintf(buf, buf_size, "%8phD", dsn_be);
+
+	return true;
+}
+
+/**
+ * idpf_devlink_info_get - .info_get devlink handler
+ * @devlink: devlink instance structure
+ * @req: the devlink info request
+ * @extack: extended netlink ack structure
+ *
+ * Callback for the devlink .info_get operation. Reports information about the
+ * device. The instance is registered only after the virtchnl handshake has
+ * completed, so the reported version is the one negotiated by the most recent
+ * successful handshake.
+ *
+ * Return: zero on success or a negative error code on failure.
+ */
+static int idpf_devlink_info_get(struct devlink *devlink,
+				 struct devlink_info_req *req,
+				 struct netlink_ext_ack *extack)
+{
+	struct idpf_adapter *adapter = devlink_priv(devlink);
+	char buf[IDPF_DEVLINK_INFO_LEN];
+	int err;
+
+	if (idpf_info_get_dsn(adapter, buf, sizeof(buf))) {
+		err = devlink_info_serial_number_put(req, buf);
+		if (err)
+			return err;
+	}
+
+	snprintf(buf, sizeof(buf), "%u.%u",
+		 adapter->virt_ver_maj, adapter->virt_ver_min);
+
+	return devlink_info_version_running_put(req,
+					DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API,
+					buf);
+}
+
 static const struct devlink_ops idpf_devlink_ops = {
+	.info_get = idpf_devlink_info_get,
 };
 
 /**
-- 
2.52.0


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

* [PATCH iwl-next v2 4/4] selftests: net: hw: add devlink info test
  2026-09-03  8:27 [PATCH iwl-next v2 0/4] idpf: add devlink info support with selftest Paul Greenwalt
                   ` (2 preceding siblings ...)
  2026-09-03  8:27 ` [PATCH iwl-next v2 3/4] idpf: add devlink info support Paul Greenwalt
@ 2026-09-03  8:27 ` Paul Greenwalt
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Greenwalt @ 2026-09-03  8:27 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: Paul Greenwalt

Add a selftest that logs the device information a driver reports through
the devlink info interface: the driver name, serial numbers and every
reported version, in the format NIPA CI consumes for device regression
tracking. This helps maintainers identify pass/fail status changes
caused by FW updates.

Implementing devlink info is optional. devlink reports the driver name
for every registered instance, even when the driver does not implement
info_get, so a device that reports no versions and no serial number is
skipped rather than failed. Devices with no devlink instance are skipped
as well.

The devlink 'driver' attribute names the driver bound to the parent
device, which may legitimately differ from the netdev's ethtool driver -
mlx4 reports mlx4_core and mlx4_en, and DSA user ports report dsa - so a
difference is logged but not treated as a failure. ethtool is only used
for an optional fallback handle lookup and that comparison, so it is not
required to run the test.

NETIF is read from the environment or from drivers/net/net.config as
described in drivers/net/README.rst. net.config is sourced before
net/lib.sh so that it cannot clobber the framework's globals. The test
needs only a single local interface, so it sources net/lib.sh rather
than the forwarding library, which requires NUM_NETIFS and a configured
remote host.

Example usage:

  NETIF=eth0 ./tools/testing/selftests/drivers/net/hw/devlink_info.sh

  INFO: driver: idpf
  INFO: serial_number: 00-a0-c9-ff-ff-23-45-67
  INFO: fw.mgmt.api (running): 2.0
  TEST: devlink info                                                  [ OK ]

Link: https://github.com/linux-netdev/nipa/wiki/Netdev-CI-system#device-information
Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
---
 .../testing/selftests/drivers/net/hw/Makefile |   1 +
 .../selftests/drivers/net/hw/devlink_info.sh  | 160 ++++++++++++++++++
 2 files changed, 161 insertions(+)
 create mode 100755 tools/testing/selftests/drivers/net/hw/devlink_info.sh

diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile
index 78bb0169350b..edd353f27a39 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -19,6 +19,7 @@ TEST_GEN_FILES := \
 
 TEST_PROGS = \
 	csum.py \
+	devlink_info.sh \
 	devlink_rate_cross_esw.py \
 	devlink_rate_tc_bw.py \
 	devmem.py \
diff --git a/tools/testing/selftests/drivers/net/hw/devlink_info.sh b/tools/testing/selftests/drivers/net/hw/devlink_info.sh
new file mode 100755
index 000000000000..1a23e7d3c5af
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/devlink_info.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test devlink info support
+#
+# This test logs the device information a driver reports through the devlink
+# info interface, in the format NIPA CI consumes for regression tracking (see
+# the Device information section at
+# https://github.com/linux-netdev/nipa/wiki/Netdev-CI-system).
+#
+# Implementing devlink info is optional, so a device whose driver reports no
+# versions and no serial number is skipped rather than failed.
+#
+# Usage:
+#   NETIF=eth0 ./devlink_info.sh
+
+ALL_TESTS="devlink_info_test"
+
+lib_dir=$(dirname "$0")
+
+# NETIF may also be provided through drivers/net/net.config, as documented in
+# drivers/net/README.rst. Source it before lib.sh so that a stray assignment
+# cannot clobber the framework's globals.
+if [[ -z "$NETIF" && -f "$lib_dir/../net.config" ]]; then
+	source "$lib_dir/../net.config"
+fi
+
+source "$lib_dir"/../../../net/lib.sh
+
+require_command devlink
+require_command jq
+
+DL_HANDLE=
+DL_INFO=
+
+setup_prepare()
+{
+	local err
+
+	if [[ -z "$NETIF" ]]; then
+		echo "SKIP: NETIF is not configured"
+		exit "$ksft_skip"
+	fi
+
+	# Try to get the devlink handle from the devlink port first.
+	DL_HANDLE=$(devlink -j port show 2>/dev/null |
+		jq -r --arg netif "$NETIF" \
+			'.port | to_entries[] |
+			 select(.value.netdev == $netif) | .key' 2>/dev/null |
+		head -n 1 |
+		cut -d/ -f1-2)
+
+	# Fall back to the PCI address reported by ethtool. Devices on other
+	# buses are only found through the devlink port lookup above.
+	if [[ -z "$DL_HANDLE" ]] && command -v ethtool >/dev/null; then
+		local bus_info
+
+		bus_info=$(ethtool -i "$NETIF" 2>/dev/null |
+			awk '/^bus-info:/ {print $2}')
+		if [[ -n "$bus_info" ]] &&
+		   devlink dev show "pci/$bus_info" &>/dev/null; then
+			DL_HANDLE="pci/$bus_info"
+		fi
+	fi
+
+	if [[ -z "$DL_HANDLE" ]]; then
+		echo "SKIP: could not find devlink handle for $NETIF"
+		exit "$ksft_skip"
+	fi
+
+	# Query once so that a single snapshot is validated throughout.
+	DL_INFO=$(devlink -j dev info "$DL_HANDLE" 2>/dev/null)
+	err=$?
+	if ((err)); then
+		echo "SKIP: devlink dev info failed for $DL_HANDLE"
+		exit "$ksft_skip"
+	fi
+}
+
+# jq's "// empty" maps a missing or null field to no output, so callers get an
+# empty string rather than the literal text "null".
+info_get()
+{
+	local name=$1
+
+	jq -r --arg name "$name" '.[][][$name] // empty' <<<"$DL_INFO"
+}
+
+log_versions()
+{
+	local versions line
+
+	versions=$(jq -r '.[][].versions // {} | to_entries[] | .key as $type |
+			  .value | to_entries[] |
+			  "\(.key) (\($type)): \(.value)"' <<<"$DL_INFO" \
+			  2>/dev/null)
+
+	while IFS= read -r line; do
+		[[ -n "$line" ]] && log_info "$line"
+	done <<<"$versions"
+}
+
+has_any_version()
+{
+	jq -e '.[][].versions // {} | [.[] | to_entries[]] | length > 0' \
+		<<<"$DL_INFO" &>/dev/null
+}
+
+devlink_info_test()
+{
+	RET=0
+
+	local driver serial board_serial
+
+	driver=$(info_get "driver")
+	serial=$(info_get "serial_number")
+	board_serial=$(info_get "board.serial_number")
+
+	# devlink reports the driver name for every registered instance, even
+	# when the driver does not implement info_get. Everything else is
+	# optional, so a device with nothing further to report is not a
+	# failure.
+	if ! has_any_version && [[ -z "$serial" && -z "$board_serial" ]]; then
+		log_test_skip "devlink info" "no info reported for $DL_HANDLE"
+		return
+	fi
+
+	if [[ -z "$driver" ]]; then
+		check_err 1 "no driver name reported"
+	else
+		log_info "driver: $driver"
+	fi
+
+	# devlink names the driver bound to the parent device, which can
+	# legitimately differ from the netdev's ethtool driver, so report a
+	# difference without failing.
+	if command -v ethtool >/dev/null; then
+		local ethtool_driver
+
+		ethtool_driver=$(ethtool -i "$NETIF" 2>/dev/null |
+			awk '/^driver:/ {print $2}')
+		if [[ -n "$driver" && -n "$ethtool_driver" &&
+		      "$driver" != "$ethtool_driver" ]]; then
+			log_info "driver mismatch: devlink='$driver' ethtool='$ethtool_driver'"
+		fi
+	fi
+
+	[[ -n "$serial" ]] && log_info "serial_number: $serial"
+	[[ -n "$board_serial" ]] && log_info "board.serial_number: $board_serial"
+
+	log_versions
+
+	log_test "devlink info"
+}
+
+setup_prepare
+
+tests_run
+
+exit "$EXIT_STATUS"
-- 
2.52.0


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

end of thread, other threads:[~2026-09-03 16:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03  8:27 [PATCH iwl-next v2 0/4] idpf: add devlink info support with selftest Paul Greenwalt
2026-09-03  8:27 ` [PATCH iwl-next v2 1/4] idpf: clear drvdata in idpf_decfg_device() Paul Greenwalt
2026-09-03  8:27 ` [PATCH iwl-next v2 2/4] idpf: add devlink support Paul Greenwalt
2026-09-03  8:27 ` [PATCH iwl-next v2 3/4] idpf: add devlink info support Paul Greenwalt
2026-09-03  8:27 ` [PATCH iwl-next v2 4/4] selftests: net: hw: add devlink info test Paul Greenwalt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox