在infiniband/core/uverbs_main.c 中的ib_uverbs_init是整个roce 像libverbs提供接口的入口函数.在ib_uverbs_init 中会调用
ret = ib_register_client(&uverbs_client);
if (ret) {
pr_err("user_verbs: couldn't register client\n");
goto out_class;
}
来注册一个client,这样吗,每注册一个roce的驱动就会调用client的add函数
static struct ib_client uverbs_client = {
.name = "uverbs",
.add = ib_uverbs_add_one,
.remove = ib_uverbs_remove_one
};
static void ib_uverbs_add_one(struct ib_device *device)
{
#这里最重要的就是为每个roce设备添加一个字符设备,这个字符设备的ops是uverbs_fops
cdev_init(&uverbs_dev->cdev, NULL);
uverbs_dev->cdev.owner = THIS_MODULE;
uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
cdev_set_parent(&uverbs_dev->cdev, &uverbs_dev->kobj);
kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
if (cdev_add(&uverbs_dev->cdev, base, 1))
goto err_cdev;
}
#当用户调用libverbs接口是会调用ib_uverbs_write,
static const struct file_operations uverbs_fops = {
.owner = THIS_MODULE,
.write = ib_uverbs_write,
.open = ib_uverbs_open,
};
在写函数中,就会根据uverbs的命令来调用不同的实现
static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
size_t count, loff_t *pos)
{
ret = uverbs_cmd_table[command](file, &ucore, &uhw);
ret = (ret) ? : count;
}
static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len) = {
[IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,
[IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,