IB/core: Infrastructure for extensible uverbs commands

Add infrastructure to support extended uverbs capabilities in a
forward/backward manner.  Uverbs command opcodes which are based on
the verbs extensions approach should be greater or equal to
IB_USER_VERBS_CMD_THRESHOLD.  They have new header format and
processed a bit differently.

Whenever a specific IB_USER_VERBS_CMD_XXX is extended, which practically means
it needs to have additional arguments, we will be able to add them without creating
a completely new IB_USER_VERBS_CMD_YYY command or bumping the uverbs ABI version.

This patch for itself doesn't provide the whole scheme which is also dependent
on adding a comp_mask field to each extended uverbs command struct.

The new header framework allows for future extension of the CMD arguments
(ib_uverbs_cmd_hdr.in_words, ib_uverbs_cmd_hdr.out_words) for an existing
new command (that is a command that supports the new uverbs command header format
suggested in this patch) w/o bumping ABI version and with maintaining backward
and formward compatibility to new and old libibverbs versions.

In the uverbs command we are passing both uverbs arguments and the provider arguments.
We split the ib_uverbs_cmd_hdr.in_words to ib_uverbs_cmd_hdr.in_words which will now carry only
uverbs input argument struct size and  ib_uverbs_cmd_hdr.provider_in_words that will carry
the provider input argument size. Same goes for the response (the uverbs CMD output argument).

For example take the create_cq call and the mlx4_ib provider:

The uverbs layer gets libibverb's struct ibv_create_cq (named struct ib_uverbs_create_cq
in the kernel), mlx4_ib gets libmlx4's struct mlx4_create_cq (which includes struct
ibv_create_cq and is named struct mlx4_ib_create_cq in the kernel) and
in_words = sizeof(mlx4_create_cq)/4 .

Thus ib_uverbs_cmd_hdr.in_words carry both uverbs plus mlx4_ib input argument sizes,
where uverbs assumes it knows the size of its input argument - struct ibv_create_cq.

Now, if we wish to add a variable to struct ibv_create_cq, we can add a comp_mask field
to the struct which is basically bit field indicating which fields exists in the struct
(as done for the libibverbs API extension), but we need a way to tell what is the total
size of the struct and not assume the struct size is predefined (since we may get different
struct sizes from different user libibverbs versions). So we know at which point the
provider input argument (struct mlx4_create_cq) begins. Same goes for extending the
provider struct mlx4_create_cq. Thus we split the ib_uverbs_cmd_hdr.in_words to
ib_uverbs_cmd_hdr.in_words which will now carry only uverbs input argument struct size and
ib_uverbs_cmd_hdr.provider_in_words that will carry the provider (mlx4_ib) input argument size.

Signed-off-by: Igor Ivanov <Igor.Ivanov@itseez.com>
Signed-off-by: Hadar Hen Zion <hadarh@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
Igor Ivanov 2013-08-14 13:58:29 +03:00 коммит произвёл Roland Dreier
Родитель 319a441d13
Коммит 400dbc9658
2 изменённых файлов: 34 добавлений и 5 удалений

Просмотреть файл

@ -583,9 +583,6 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof hdr)) if (copy_from_user(&hdr, buf, sizeof hdr))
return -EFAULT; return -EFAULT;
if (hdr.in_words * 4 != count)
return -EINVAL;
if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) || if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
!uverbs_cmd_table[hdr.command]) !uverbs_cmd_table[hdr.command])
return -EINVAL; return -EINVAL;
@ -597,8 +594,30 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command))) if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
return -ENOSYS; return -ENOSYS;
return uverbs_cmd_table[hdr.command](file, buf + sizeof hdr, if (hdr.command >= IB_USER_VERBS_CMD_THRESHOLD) {
hdr.in_words * 4, hdr.out_words * 4); struct ib_uverbs_cmd_hdr_ex hdr_ex;
if (copy_from_user(&hdr_ex, buf, sizeof(hdr_ex)))
return -EFAULT;
if (((hdr_ex.in_words + hdr_ex.provider_in_words) * 4) != count)
return -EINVAL;
return uverbs_cmd_table[hdr.command](file,
buf + sizeof(hdr_ex),
(hdr_ex.in_words +
hdr_ex.provider_in_words) * 4,
(hdr_ex.out_words +
hdr_ex.provider_out_words) * 4);
} else {
if (hdr.in_words * 4 != count)
return -EINVAL;
return uverbs_cmd_table[hdr.command](file,
buf + sizeof(hdr),
hdr.in_words * 4,
hdr.out_words * 4);
}
} }
static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)

Просмотреть файл

@ -43,6 +43,7 @@
* compatibility are made. * compatibility are made.
*/ */
#define IB_USER_VERBS_ABI_VERSION 6 #define IB_USER_VERBS_ABI_VERSION 6
#define IB_USER_VERBS_CMD_THRESHOLD 50
enum { enum {
IB_USER_VERBS_CMD_GET_CONTEXT, IB_USER_VERBS_CMD_GET_CONTEXT,
@ -123,6 +124,15 @@ struct ib_uverbs_cmd_hdr {
__u16 out_words; __u16 out_words;
}; };
struct ib_uverbs_cmd_hdr_ex {
__u32 command;
__u16 in_words;
__u16 out_words;
__u16 provider_in_words;
__u16 provider_out_words;
__u32 cmd_hdr_reserved;
};
struct ib_uverbs_get_context { struct ib_uverbs_get_context {
__u64 response; __u64 response;
__u64 driver_data[0]; __u64 driver_data[0];