From: Doug Ledford <doug.ledford@hpe.com>
To: Jason Gunthorpe <jgg@ziepe.ca>, Leon Romanovsky <leon@kernel.org>,
Slingshot Open Source Team <slingshot-os-team@groups.ext.hpe.com>
Cc: <linux-rdma@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
Doug Ledford <doug.ledford@hpe.com>
Subject: [PATCH 01/11] RDMA/core: read selected counters with timestamps
Date: Fri, 30 Oct 2026 21:35:29 -0700 [thread overview]
Message-ID: <20261030-cxi-for-next-v1-1-bc6e49e07037@hpe.com> (raw)
In-Reply-To: <20261030-cxi-for-next-v1-0-bc6e49e07037@hpe.com>
The COUNTERS object reads every counter attached to it into one
array, which suits a fixed set but not a device with thousands of
status values of which a monitor wants a few. Add two optional
attributes to the read method. ITEMS is an array of driver defined
item numbers, and the values come back in the same order. TIMESTAMPS
returns, per item, when the driver sampled it, in nanoseconds since the
epoch. Either may be used without the other.
A driver advertises the extension by providing read_counters_ex(). A
counters object created for such a driver need not have any counters
attached, because the items are chosen at read time; the check for an
attached counter is skipped for those drivers. Without the callback
the new attributes are rejected with EOPNOTSUPP, and the original
behaviour is unchanged.
Signed-off-by: Doug Ledford <doug.ledford@hpe.com>
---
drivers/infiniband/core/device.c | 1 +
.../infiniband/core/uverbs_std_types_counters.c | 68 ++++++++++++++++++++--
include/rdma/ib_verbs.h | 11 ++++
include/uapi/rdma/ib_user_ioctl_cmds.h | 2 +
4 files changed, 78 insertions(+), 4 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 1b838bf3600d..18c0d9243909 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -3026,6 +3026,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
SET_DEVICE_OP(dev_ops, query_ucontext);
SET_DEVICE_OP(dev_ops, rdma_netdev_get_params);
SET_DEVICE_OP(dev_ops, read_counters);
+ SET_DEVICE_OP(dev_ops, read_counters_ex);
SET_DEVICE_OP(dev_ops, read_comp_cntr);
SET_DEVICE_OP(dev_ops, reg_dm_mr);
SET_DEVICE_OP(dev_ops, reg_user_mr);
diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c
index 381aa5797641..e452854ddaa9 100644
--- a/drivers/infiniband/core/uverbs_std_types_counters.c
+++ b/drivers/infiniband/core/uverbs_std_types_counters.c
@@ -92,12 +92,20 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_READ)(
const struct uverbs_attr *uattr;
struct ib_counters *counters =
uverbs_attr_get_obj(attrs, UVERBS_ATTR_READ_COUNTERS_HANDLE);
+ bool has_items, has_timestamps;
+ size_t len;
int ret;
- if (!counters->device->ops.read_counters)
+ /*
+ * A driver with read_counters_ex defines what its counters are, so
+ * they need not be attached to anything before they are read.
+ */
+ if (!counters->device->ops.read_counters &&
+ !counters->device->ops.read_counters_ex)
return -EOPNOTSUPP;
- if (!atomic_read(&counters->usecnt))
+ if (!counters->device->ops.read_counters_ex &&
+ !atomic_read(&counters->usecnt))
return -EINVAL;
ret = uverbs_get_flags32(&read_attr.flags, attrs,
@@ -115,10 +123,56 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_READ)(
if (IS_ERR(read_attr.counters_buff))
return PTR_ERR(read_attr.counters_buff);
- ret = counters->device->ops.read_counters(counters, &read_attr, attrs);
+ has_items = uverbs_attr_is_valid(attrs, UVERBS_ATTR_READ_COUNTERS_ITEMS);
+ has_timestamps = uverbs_attr_is_valid(attrs,
+ UVERBS_ATTR_READ_COUNTERS_TIMESTAMPS);
+ if ((has_items || has_timestamps) &&
+ !counters->device->ops.read_counters_ex)
+ return -EOPNOTSUPP;
+
+ if (has_items) {
+ u64 *items;
+
+ len = uverbs_attr_get_len(attrs, UVERBS_ATTR_READ_COUNTERS_ITEMS);
+ if (len != array_size(read_attr.ncounters, sizeof(u64)))
+ return -EINVAL;
+ items = uverbs_zalloc(attrs, len);
+ if (IS_ERR(items))
+ return PTR_ERR(items);
+ ret = _uverbs_copy_from(items, attrs,
+ UVERBS_ATTR_READ_COUNTERS_ITEMS, len);
+ if (ret)
+ return ret;
+ read_attr.items = items;
+ }
+
+ if (has_timestamps) {
+ len = uverbs_attr_get_len(attrs,
+ UVERBS_ATTR_READ_COUNTERS_TIMESTAMPS);
+ if (len != array_size(read_attr.ncounters, sizeof(u64)))
+ return -EINVAL;
+ read_attr.timestamps = uverbs_zalloc(attrs, len);
+ if (IS_ERR(read_attr.timestamps))
+ return PTR_ERR(read_attr.timestamps);
+ }
+
+ if (counters->device->ops.read_counters_ex)
+ ret = counters->device->ops.read_counters_ex(counters,
+ &read_attr, attrs);
+ else
+ ret = counters->device->ops.read_counters(counters, &read_attr,
+ attrs);
if (ret)
return ret;
+ if (has_timestamps) {
+ ret = uverbs_copy_to(attrs, UVERBS_ATTR_READ_COUNTERS_TIMESTAMPS,
+ read_attr.timestamps,
+ read_attr.ncounters * sizeof(u64));
+ if (ret)
+ return ret;
+ }
+
return uverbs_copy_to(attrs, UVERBS_ATTR_READ_COUNTERS_BUFF,
read_attr.counters_buff,
read_attr.ncounters * sizeof(u64));
@@ -148,7 +202,13 @@ DECLARE_UVERBS_NAMED_METHOD(
UVERBS_ATTR_MIN_SIZE(0),
UA_MANDATORY),
UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_READ_COUNTERS_FLAGS,
- enum ib_uverbs_read_counters_flags));
+ enum ib_uverbs_read_counters_flags),
+ UVERBS_ATTR_PTR_IN(UVERBS_ATTR_READ_COUNTERS_ITEMS,
+ UVERBS_ATTR_MIN_SIZE(sizeof(u64)),
+ UA_OPTIONAL),
+ UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_READ_COUNTERS_TIMESTAMPS,
+ UVERBS_ATTR_MIN_SIZE(sizeof(u64)),
+ UA_OPTIONAL));
DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_COUNTERS,
UVERBS_TYPE_ALLOC_IDR(uverbs_free_counters),
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index a93715323ad5..5aa1fa576a44 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2595,6 +2595,10 @@ struct ib_counters_read_attr {
u64 *counters_buff;
u32 ncounters;
u32 flags; /* use enum ib_read_counters_flags */
+ /* Optional: counter numbers to read, ncounters entries */
+ const u64 *items;
+ /* Optional: filled with a timestamp for each counter read */
+ u64 *timestamps;
};
struct uverbs_attr_bundle;
@@ -2936,6 +2940,13 @@ struct ib_device_ops {
int (*create_counters)(struct ib_counters *counters,
struct uverbs_attr_bundle *attrs);
int (*destroy_counters)(struct ib_counters *counters);
+ /*
+ * Used instead of read_counters when the user selects counters with
+ * items or asks for timestamps.
+ */
+ int (*read_counters_ex)(struct ib_counters *counters,
+ struct ib_counters_read_attr *counters_read_attr,
+ struct uverbs_attr_bundle *attrs);
int (*read_counters)(struct ib_counters *counters,
struct ib_counters_read_attr *counters_read_attr,
struct uverbs_attr_bundle *attrs);
diff --git a/include/uapi/rdma/ib_user_ioctl_cmds.h b/include/uapi/rdma/ib_user_ioctl_cmds.h
index 8de110b8db34..9ee083eed044 100644
--- a/include/uapi/rdma/ib_user_ioctl_cmds.h
+++ b/include/uapi/rdma/ib_user_ioctl_cmds.h
@@ -404,6 +404,8 @@ enum uverbs_attrs_read_counters_cmd_attr_ids {
UVERBS_ATTR_READ_COUNTERS_HANDLE,
UVERBS_ATTR_READ_COUNTERS_BUFF,
UVERBS_ATTR_READ_COUNTERS_FLAGS,
+ UVERBS_ATTR_READ_COUNTERS_ITEMS,
+ UVERBS_ATTR_READ_COUNTERS_TIMESTAMPS,
};
enum uverbs_methods_actions_counters_ops {
--
2.56.0
next prev parent reply other threads:[~2026-10-31 4:36 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 4:35 [PATCH 00/11] Subject: [PATCH for-next 00/11] RDMA/cxi: add the HPE Cassini verbs driver Doug Ledford
2026-10-31 4:35 ` Doug Ledford [this message]
2026-10-31 4:35 ` [PATCH 02/11] RDMA/core: allow jobs without an address table Doug Ledford
2026-10-31 4:35 ` [PATCH 03/11] RDMA/core: add Slingshot identifiers and driver-owned GIDs Doug Ledford
2026-10-31 4:35 ` [PATCH 04/11] RDMA/cxi: add the native ABI and resource definitions Doug Ledford
2026-11-05 13:54 ` Uwe Kleine-König
2026-10-31 4:35 ` [PATCH 05/11] RDMA/cxi: add the auxiliary device and driver ops Doug Ledford
2026-10-31 4:35 ` [PATCH 06/11] RDMA/cxi: add explicit context LNI and PID lifetimes Doug Ledford
2026-10-31 4:35 ` [PATCH 07/11] RDMA/cxi: add VNI-isolated queue pairs Doug Ledford
2026-10-31 4:35 ` [PATCH 08/11] RDMA/cxi: add native memory registration Doug Ledford
2026-10-31 4:35 ` [PATCH 09/11] RDMA/cxi: add services jobs profiles queues and counting triggers Doug Ledford
2026-10-31 4:35 ` [PATCH 10/11] RDMA/cxi: read the NIC telemetry through counters Doug Ledford
2026-10-31 4:35 ` [PATCH 11/11] RDMA/cxi: wire the driver into the build Doug Ledford
2026-11-03 14:28 ` [PATCH 00/11] Subject: [PATCH for-next 00/11] RDMA/cxi: add the HPE Cassini verbs driver Leon Romanovsky
2026-11-03 14:30 ` Jason Gunthorpe
2026-11-04 9:54 ` Leon Romanovsky
2026-11-04 16:17 ` Doug Ledford
2026-11-04 16:14 ` Doug Ledford
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261030-cxi-for-next-v1-1-bc6e49e07037@hpe.com \
--to=doug.ledford@hpe.com \
--cc=jgg@ziepe.ca \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=slingshot-os-team@groups.ext.hpe.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®