Expose a telemetry command reporting per-function mbox send/ack counters so
mailbox activity can be observed for diagnosis.

Signed-off-by: Jiacheng Ye <[email protected]>
---
 doc/guides/rel_notes/release_26_11.rst |   1 +
 drivers/net/hinic3/hinic3_telemetry.c  | 104 +++++++++++++++++++++++++
 drivers/net/hinic3/hinic3_telemetry.h  |  25 ++++++
 drivers/net/hinic3/meson.build         |   1 +
 4 files changed, 131 insertions(+)
 create mode 100644 drivers/net/hinic3/hinic3_telemetry.c
 create mode 100644 drivers/net/hinic3/hinic3_telemetry.h

diff --git a/doc/guides/rel_notes/release_26_11.rst 
b/doc/guides/rel_notes/release_26_11.rst
index 216f2b297e..8280d24750 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -103,6 +103,7 @@ New Features
   * Added a compact CQE receive data path.
   * Extended TCP segmentation offload (TSO) to 255 segments.
   * Added a compact CQE transmit data path.
+  * Added a mailbox count telemetry endpoint.
 
 * **Updated Intel iavf driver.**
 
diff --git a/drivers/net/hinic3/hinic3_telemetry.c 
b/drivers/net/hinic3/hinic3_telemetry.c
new file mode 100644
index 0000000000..63180aaf85
--- /dev/null
+++ b/drivers/net/hinic3/hinic3_telemetry.c
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd
+ */
+
+#include <rte_os.h>
+#include <rte_telemetry.h>
+#include "base/hinic3_compat.h"
+#include "base/hinic3_mgmt.h"
+#include "base/hinic3_hwdev.h"
+#include "base/hinic3_mbox.h"
+#include "hinic3_ethdev.h"
+#include "hinic3_telemetry.h"
+
+static int
+hinic3_get_mbox_info(struct rte_eth_dev *eth_dev, struct mbox_cnt_info 
*mbox_cnt)
+{
+       struct rte_pci_device *pci_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, 
*pci_dev);
+       struct hinic3_nic_dev *nic_dev = 
HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+       uint32_t i;
+
+       if (pci_dev == NULL) {
+               PMD_DRV_LOG(ERR, "Get pci device failed.");
+               return -1;
+       }
+
+       if (nic_dev == NULL) {
+               PMD_DRV_LOG(ERR, "Get nic device failed.");
+               return -1;
+       }
+
+       i = mbox_cnt->func_num;
+       mbox_cnt->func_num++;
+       snprintf(mbox_cnt->func_info[i].bus_info,
+                sizeof(mbox_cnt->func_info[i].bus_info), "%.4x_%.2x_%.2x_%x",
+                pci_dev->addr.domain, pci_dev->addr.bus,
+                pci_dev->addr.devid, pci_dev->addr.function);
+
+       mbox_cnt->func_info[i].send_cnt = 
nic_dev->hwdev->func_to_func->mbox_send_cnt;
+       mbox_cnt->func_info[i].ack_cnt = 
nic_dev->hwdev->func_to_func->mbox_ack_cnt;
+
+       return 0;
+}
+
+static int
+hinic3_telemetry_info(const char *cmd __rte_unused, const char *params 
__rte_unused,
+                     struct rte_tel_data *d)
+{
+       struct rte_eth_dev *eth_dev = NULL;
+       struct rte_tel_data *i_data = NULL;
+       struct rte_tel_data *func_data = NULL;
+       struct mbox_cnt_info mbox_cnt;
+       uint32_t i;
+       int err;
+
+       memset(&mbox_cnt, 0, sizeof(struct mbox_cnt_info));
+
+       for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+               /* Skip if port is unused */
+               if (!rte_eth_dev_is_valid_port(i))
+                       continue;
+
+               eth_dev = &rte_eth_devices[i];
+               if (eth_dev) {
+                       err = hinic3_get_mbox_info(eth_dev, &mbox_cnt);
+                       if (err) {
+                               PMD_DRV_LOG(ERR, "Get mbox info failed.");
+                               return -1;
+                       }
+               }
+       }
+
+       rte_tel_data_start_dict(d);
+       rte_tel_data_add_dict_int(d, "func_num", mbox_cnt.func_num);
+
+       i_data = rte_tel_data_alloc();
+       if (i_data == NULL)
+               return -ENOMEM;
+
+       rte_tel_data_start_dict(i_data);
+
+       for (i = 0; i < mbox_cnt.func_num; i++) {
+               func_data = rte_tel_data_alloc();
+               if (func_data == NULL) {
+                       rte_tel_data_free(i_data);
+                       return -ENOMEM;
+               }
+
+               rte_tel_data_start_dict(func_data);
+               rte_tel_data_add_dict_int(func_data, "send_cnt", 
mbox_cnt.func_info[i].send_cnt);
+               rte_tel_data_add_dict_int(func_data, "ack_cnt", 
mbox_cnt.func_info[i].ack_cnt);
+               rte_tel_data_add_dict_container(i_data, 
mbox_cnt.func_info[i].bus_info,
+                                               func_data, 0);
+       }
+
+       rte_tel_data_add_dict_container(d, "func_info", i_data, 0);
+
+       return 0;
+}
+
+RTE_INIT(hinic3_init_telemetry)
+{
+       rte_telemetry_register_cmd("/hinic3/mbox_cnt", hinic3_telemetry_info,
+                                  "Returns mbox send and ack count 
information");
+}
diff --git a/drivers/net/hinic3/hinic3_telemetry.h 
b/drivers/net/hinic3/hinic3_telemetry.h
new file mode 100644
index 0000000000..8751082061
--- /dev/null
+++ b/drivers/net/hinic3/hinic3_telemetry.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC3_TELEMETRY_H_
+#define _HINIC3_TELEMETRY_H_
+
+#include <stdint.h>
+
+#define HINIC_PF_MAX_SIZE 16
+#define HINIC_VF_MAX_SIZE 4096
+#define BUSINFO_LEN      32
+
+struct func_mbox_cnt_info {
+       char bus_info[BUSINFO_LEN];
+       uint64_t send_cnt;
+       uint64_t ack_cnt;
+};
+
+struct mbox_cnt_info {
+       struct func_mbox_cnt_info func_info[HINIC_PF_MAX_SIZE + 
HINIC_VF_MAX_SIZE];
+       uint32_t func_num;
+};
+
+#endif /* _HINIC3_TELEMETRY_H_ */
diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build
index 3ce5a68fb2..400c4f1a53 100644
--- a/drivers/net/hinic3/meson.build
+++ b/drivers/net/hinic3/meson.build
@@ -23,6 +23,7 @@ sources = files(
         'hinic3_flow.c',
         'hinic3_rx.c',
         'hinic3_tx.c',
+        'hinic3_telemetry.c',
 )
 
 includes += include_directories('base')
-- 
2.33.0


Reply via email to