History

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.

Avihai Horon committed 6 years ago

Commit 9f85cbe1 parent c4b4d544 files · +220 −4Browse files

Unified · Split

4 files
  1. drivers/infiniband/core/uverbs_std_types_device.c +195 −1
  2. include/rdma/ib_verbs.h +3 −3
  3. include/uapi/rdma/ib_user_ioctl_cmds.h +16 −0
  4. include/uapi/rdma/ib_user_ioctl_verbs.h +6 −0
drivers/infiniband/core/uverbs_std_types_device.c+195−1
@@ -3,11 +3,13 @@ · 2 unmodified lines
3 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.3 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
4 */4 */
5 5
6#include <linux/overflow.h>
6#include <rdma/uverbs_std_types.h>7#include <rdma/uverbs_std_types.h>
7#include "rdma_core.h"8#include "rdma_core.h"
8#include "uverbs.h"9#include "uverbs.h"
9#include <rdma/uverbs_ioctl.h>10#include <rdma/uverbs_ioctl.h>
10#include <rdma/opa_addr.h>11#include <rdma/opa_addr.h>
12#include <rdma/ib_cache.h>
11 13
12/*14/*
13 * This ioctl method allows calling any defined write or write_ex15 * This ioctl method allows calling any defined write or write_ex
@@ -266,6 +268,172 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_CONTEXT)( · 252 unmodified lines
266 return ucontext->device->ops.query_ucontext(ucontext, attrs);268 return ucontext->device->ops.query_ucontext(ucontext, attrs);
267}269}
268 270
271static 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
312static 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
368static 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));
432out:
433 rdma_put_gid_attr(gid_attr);
434 return ret;
435}
436
269DECLARE_UVERBS_NAMED_METHOD(437DECLARE_UVERBS_NAMED_METHOD(
270 UVERBS_METHOD_GET_CONTEXT,438 UVERBS_METHOD_GET_CONTEXT,
271 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS,439 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS,
@@ -300,12 +468,38 @@ DECLARE_UVERBS_NAMED_METHOD( · 28 unmodified lines
300 reserved),468 reserved),
301 UA_MANDATORY));469 UA_MANDATORY));
302 470
471DECLARE_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
482DECLARE_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
303DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,495DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE,
304 &UVERBS_METHOD(UVERBS_METHOD_GET_CONTEXT),496 &UVERBS_METHOD(UVERBS_METHOD_GET_CONTEXT),
305 &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE),497 &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE),
306 &UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES),498 &UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES),
307 &UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT),499 &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));
309 503
310const struct uapi_definition uverbs_def_obj_device[] = {504const struct uapi_definition uverbs_def_obj_device[] = {
311 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),505 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE),
include/rdma/ib_verbs.h+3−3
@@ -138,9 +138,9 @@ union ib_gid { · 137 unmodified lines
138extern union ib_gid zgid;138extern union ib_gid zgid;
139 139
140enum ib_gid_type {140enum ib_gid_type {
141 IB_GID_TYPE_IB = 0,141 IB_GID_TYPE_IB = IB_UVERBS_GID_TYPE_IB,
142 IB_GID_TYPE_ROCE = 1,142 IB_GID_TYPE_ROCE = IB_UVERBS_GID_TYPE_ROCE_V1,
143 IB_GID_TYPE_ROCE_UDP_ENCAP = 2,143 IB_GID_TYPE_ROCE_UDP_ENCAP = IB_UVERBS_GID_TYPE_ROCE_V2,
144 IB_GID_TYPE_SIZE144 IB_GID_TYPE_SIZE
145};145};
146 146
include/uapi/rdma/ib_user_ioctl_cmds.h+16−0
@@ -70,6 +70,8 @@ enum uverbs_methods_device { · 69 unmodified lines
70 UVERBS_METHOD_QUERY_PORT,70 UVERBS_METHOD_QUERY_PORT,
71 UVERBS_METHOD_GET_CONTEXT,71 UVERBS_METHOD_GET_CONTEXT,
72 UVERBS_METHOD_QUERY_CONTEXT,72 UVERBS_METHOD_QUERY_CONTEXT,
73 UVERBS_METHOD_QUERY_GID_TABLE,
74 UVERBS_METHOD_QUERY_GID_ENTRY,
73};75};
74 76
75enum uverbs_attrs_invoke_write_cmd_attr_ids {77enum uverbs_attrs_invoke_write_cmd_attr_ids {
@@ -352,4 +354,18 @@ enum uverbs_attrs_async_event_create { · 276 unmodified lines
352 UVERBS_ATTR_ASYNC_EVENT_ALLOC_FD_HANDLE,354 UVERBS_ATTR_ASYNC_EVENT_ALLOC_FD_HANDLE,
353};355};
354 356
357enum 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
364enum 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
355#endif371#endif
include/uapi/rdma/ib_user_ioctl_verbs.h+6−0
@@ -251,6 +251,12 @@ enum rdma_driver_id { · 250 unmodified lines
251 RDMA_DRIVER_SIW,251 RDMA_DRIVER_SIW,
252};252};
253 253
254enum 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
254struct ib_uverbs_gid_entry {260struct ib_uverbs_gid_entry {
255 __aligned_u64 gid[2];261 __aligned_u64 gid[2];
256 __u32 gid_index;262 __u32 gid_index;