Skip to content

Commit 9f85cbe

Browse files
avihai1122jgunthorpe
authored andcommitted
RDMA/uverbs: Expose the new GID query API to user space
Expose the query GID table and entry API to user space by adding two new methods and method handlers to the device object. This API provides a faster way to query a GID table using single call and will be used in libibverbs to improve current approach that requires multiple calls to open, close and read multiple sysfs files for a single GID table entry. Link: https://lore.kernel.org/r/20200923165015.2491894-5-leon@kernel.org Signed-off-by: Avihai Horon <avihaih@nvidia.com> Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent c4b4d54 commit 9f85cbe

4 files changed

Lines changed: 220 additions & 4 deletions

File tree

drivers/infiniband/core/uverbs_std_types_device.c

Lines changed: 195 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
* Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
44
*/
55

6+
#include <linux/overflow.h>
67
#include <rdma/uverbs_std_types.h>
78
#include "rdma_core.h"
89
#include "uverbs.h"
910
#include <rdma/uverbs_ioctl.h>
1011
#include <rdma/opa_addr.h>
12+
#include <rdma/ib_cache.h>
1113

1214
/*
1315
* This ioctl method allows calling any defined write or write_ex
@@ -266,6 +268,172 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_CONTEXT)(
266268
return ucontext->device->ops.query_ucontext(ucontext, attrs);
267269
}
268270

271+
static int copy_gid_entries_to_user(struct uverbs_attr_bundle *attrs,
272+
struct ib_uverbs_gid_entry *entries,
273+
size_t num_entries, size_t user_entry_size)
274+
{
275+
const struct uverbs_attr *attr;
276+
void __user *user_entries;
277+
size_t copy_len;
278+
int ret;
279+
int i;
280+
281+
if (user_entry_size == sizeof(*entries)) {
282+
ret = uverbs_copy_to(attrs,
283+
UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
284+
entries, sizeof(*entries) * num_entries);
285+
return ret;
286+
}
287+
288+
copy_len = min_t(size_t, user_entry_size, sizeof(*entries));
289+
attr = uverbs_attr_get(attrs, UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES);
290+
if (IS_ERR(attr))
291+
return PTR_ERR(attr);
292+
293+
user_entries = u64_to_user_ptr(attr->ptr_attr.data);
294+
for (i = 0; i < num_entries; i++) {
295+
if (copy_to_user(user_entries, entries, copy_len))
296+
return -EFAULT;
297+
298+
if (user_entry_size > sizeof(*entries)) {
299+
if (clear_user(user_entries + sizeof(*entries),
300+
user_entry_size - sizeof(*entries)))
301+
return -EFAULT;
302+
}
303+
304+
entries++;
305+
user_entries += user_entry_size;
306+
}
307+
308+
return uverbs_output_written(attrs,
309+
UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES);
310+
}
311+
312+
static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_TABLE)(
313+
struct uverbs_attr_bundle *attrs)
314+
{
315+
struct ib_uverbs_gid_entry *entries;
316+
struct ib_ucontext *ucontext;
317+
struct ib_device *ib_dev;
318+
size_t user_entry_size;
319+
ssize_t num_entries;
320+
size_t max_entries;
321+
size_t num_bytes;
322+
u32 flags;
323+
int ret;
324+
325+
ret = uverbs_get_flags32(&flags, attrs,
326+
UVERBS_ATTR_QUERY_GID_TABLE_FLAGS, 0);
327+
if (ret)
328+
return ret;
329+
330+
ret = uverbs_get_const(&user_entry_size, attrs,
331+
UVERBS_ATTR_QUERY_GID_TABLE_ENTRY_SIZE);
332+
if (ret)
333+
return ret;
334+
335+
max_entries = uverbs_attr_ptr_get_array_size(
336+
attrs, UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
337+
user_entry_size);
338+
if (max_entries <= 0)
339+
return -EINVAL;
340+
341+
ucontext = ib_uverbs_get_ucontext(attrs);
342+
if (IS_ERR(ucontext))
343+
return PTR_ERR(ucontext);
344+
ib_dev = ucontext->device;
345+
346+
if (check_mul_overflow(max_entries, sizeof(*entries), &num_bytes))
347+
return -EINVAL;
348+
349+
entries = uverbs_zalloc(attrs, num_bytes);
350+
if (!entries)
351+
return -ENOMEM;
352+
353+
num_entries = rdma_query_gid_table(ib_dev, entries, max_entries);
354+
if (num_entries < 0)
355+
return -EINVAL;
356+
357+
ret = copy_gid_entries_to_user(attrs, entries, num_entries,
358+
user_entry_size);
359+
if (ret)
360+
return ret;
361+
362+
ret = uverbs_copy_to(attrs,
363+
UVERBS_ATTR_QUERY_GID_TABLE_RESP_NUM_ENTRIES,
364+
&num_entries, sizeof(num_entries));
365+
return ret;
366+
}
367+
368+
static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_ENTRY)(
369+
struct uverbs_attr_bundle *attrs)
370+
{
371+
struct ib_uverbs_gid_entry entry = {};
372+
const struct ib_gid_attr *gid_attr;
373+
struct ib_ucontext *ucontext;
374+
struct ib_device *ib_dev;
375+
struct net_device *ndev;
376+
u32 gid_index;
377+
u32 port_num;
378+
u32 flags;
379+
int ret;
380+
381+
ret = uverbs_get_flags32(&flags, attrs,
382+
UVERBS_ATTR_QUERY_GID_ENTRY_FLAGS, 0);
383+
if (ret)
384+
return ret;
385+
386+
ret = uverbs_get_const(&port_num, attrs,
387+
UVERBS_ATTR_QUERY_GID_ENTRY_PORT);
388+
if (ret)
389+
return ret;
390+
391+
ret = uverbs_get_const(&gid_index, attrs,
392+
UVERBS_ATTR_QUERY_GID_ENTRY_GID_INDEX);
393+
if (ret)
394+
return ret;
395+
396+
ucontext = ib_uverbs_get_ucontext(attrs);
397+
if (IS_ERR(ucontext))
398+
return PTR_ERR(ucontext);
399+
ib_dev = ucontext->device;
400+
401+
if (!rdma_is_port_valid(ib_dev, port_num))
402+
return -EINVAL;
403+
404+
if (!rdma_ib_or_roce(ib_dev, port_num))
405+
return -EOPNOTSUPP;
406+
407+
gid_attr = rdma_get_gid_attr(ib_dev, port_num, gid_index);
408+
if (IS_ERR(gid_attr))
409+
return PTR_ERR(gid_attr);
410+
411+
memcpy(&entry.gid, &gid_attr->gid, sizeof(gid_attr->gid));
412+
entry.gid_index = gid_attr->index;
413+
entry.port_num = gid_attr->port_num;
414+
entry.gid_type = gid_attr->gid_type;
415+
416+
rcu_read_lock();
417+
ndev = rdma_read_gid_attr_ndev_rcu(gid_attr);
418+
if (IS_ERR(ndev)) {
419+
if (PTR_ERR(ndev) != -ENODEV) {
420+
ret = PTR_ERR(ndev);
421+
rcu_read_unlock();
422+
goto out;
423+
}
424+
} else {
425+
entry.netdev_ifindex = ndev->ifindex;
426+
}
427+
rcu_read_unlock();
428+
429+
ret = uverbs_copy_to_struct_or_zero(
430+
attrs, UVERBS_ATTR_QUERY_GID_ENTRY_RESP_ENTRY, &entry,
431+
sizeof(entry));
432+
out:
433+
rdma_put_gid_attr(gid_attr);
434+
return ret;
435+
}
436+
269437
DECLARE_UVERBS_NAMED_METHOD(
270438
UVERBS_METHOD_GET_CONTEXT,
271439
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS,
@@ -300,12 +468,38 @@ DECLARE_UVERBS_NAMED_METHOD(
300468
reserved),
301469
UA_MANDATORY));
302470

471+
DECLARE_UVERBS_NAMED_METHOD(
472+
UVERBS_METHOD_QUERY_GID_TABLE,
473+
UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_GID_TABLE_ENTRY_SIZE, u64,
474+
UA_MANDATORY),
475+
UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_QUERY_GID_TABLE_FLAGS, u32,
476+
UA_OPTIONAL),
477+
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
478+
UVERBS_ATTR_MIN_SIZE(0), UA_MANDATORY),
479+
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_GID_TABLE_RESP_NUM_ENTRIES,
480+
UVERBS_ATTR_TYPE(u64), UA_MANDATORY));
481+
482+
DECLARE_UVERBS_NAMED_METHOD(
483+
UVERBS_METHOD_QUERY_GID_ENTRY,
484+
UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_GID_ENTRY_PORT, u32,
485+
UA_MANDATORY),
486+
UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_GID_ENTRY_GID_INDEX, u32,
487+
UA_MANDATORY),
488+
UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_QUERY_GID_ENTRY_FLAGS, u32,
489+
UA_MANDATORY),
490+
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_GID_ENTRY_RESP_ENTRY,
491+
UVERBS_ATTR_STRUCT(struct ib_uverbs_gid_entry,
492+
netdev_ifindex),
493+
UA_MANDATORY));
494+
303495
DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,
304496
&UVERBS_METHOD(UVERBS_METHOD_GET_CONTEXT),
305497
&UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE),
306498
&UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES),
307499
&UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT),
308-
&UVERBS_METHOD(UVERBS_METHOD_QUERY_CONTEXT));
500+
&UVERBS_METHOD(UVERBS_METHOD_QUERY_CONTEXT),
501+
&UVERBS_METHOD(UVERBS_METHOD_QUERY_GID_TABLE),
502+
&UVERBS_METHOD(UVERBS_METHOD_QUERY_GID_ENTRY));
309503

310504
const struct uapi_definition uverbs_def_obj_device[] = {
311505
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),

include/rdma/ib_verbs.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ union ib_gid {
138138
extern union ib_gid zgid;
139139

140140
enum ib_gid_type {
141-
IB_GID_TYPE_IB = 0,
142-
IB_GID_TYPE_ROCE = 1,
143-
IB_GID_TYPE_ROCE_UDP_ENCAP = 2,
141+
IB_GID_TYPE_IB = IB_UVERBS_GID_TYPE_IB,
142+
IB_GID_TYPE_ROCE = IB_UVERBS_GID_TYPE_ROCE_V1,
143+
IB_GID_TYPE_ROCE_UDP_ENCAP = IB_UVERBS_GID_TYPE_ROCE_V2,
144144
IB_GID_TYPE_SIZE
145145
};
146146

include/uapi/rdma/ib_user_ioctl_cmds.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ enum uverbs_methods_device {
7070
UVERBS_METHOD_QUERY_PORT,
7171
UVERBS_METHOD_GET_CONTEXT,
7272
UVERBS_METHOD_QUERY_CONTEXT,
73+
UVERBS_METHOD_QUERY_GID_TABLE,
74+
UVERBS_METHOD_QUERY_GID_ENTRY,
7375
};
7476

7577
enum uverbs_attrs_invoke_write_cmd_attr_ids {
@@ -352,4 +354,18 @@ enum uverbs_attrs_async_event_create {
352354
UVERBS_ATTR_ASYNC_EVENT_ALLOC_FD_HANDLE,
353355
};
354356

357+
enum uverbs_attrs_query_gid_table_cmd_attr_ids {
358+
UVERBS_ATTR_QUERY_GID_TABLE_ENTRY_SIZE,
359+
UVERBS_ATTR_QUERY_GID_TABLE_FLAGS,
360+
UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
361+
UVERBS_ATTR_QUERY_GID_TABLE_RESP_NUM_ENTRIES,
362+
};
363+
364+
enum uverbs_attrs_query_gid_entry_cmd_attr_ids {
365+
UVERBS_ATTR_QUERY_GID_ENTRY_PORT,
366+
UVERBS_ATTR_QUERY_GID_ENTRY_GID_INDEX,
367+
UVERBS_ATTR_QUERY_GID_ENTRY_FLAGS,
368+
UVERBS_ATTR_QUERY_GID_ENTRY_RESP_ENTRY,
369+
};
370+
355371
#endif

include/uapi/rdma/ib_user_ioctl_verbs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ enum rdma_driver_id {
251251
RDMA_DRIVER_SIW,
252252
};
253253

254+
enum ib_uverbs_gid_type {
255+
IB_UVERBS_GID_TYPE_IB,
256+
IB_UVERBS_GID_TYPE_ROCE_V1,
257+
IB_UVERBS_GID_TYPE_ROCE_V2,
258+
};
259+
254260
struct ib_uverbs_gid_entry {
255261
__aligned_u64 gid[2];
256262
__u32 gid_index;

0 commit comments

Comments
 (0)