📄 ucm.c
字号:
return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_rtu);}static ssize_t ib_ucm_send_dreq(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_dreq);}static ssize_t ib_ucm_send_drep(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ return ib_ucm_send_private_data(file, inbuf, in_len, ib_send_cm_drep);}static ssize_t ib_ucm_send_info(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int (*func)(struct ib_cm_id *cm_id, int status, const void *info, u8 info_len, const void *data, u8 data_len)){ struct ib_ucm_context *ctx; struct ib_ucm_info cmd; const void *data = NULL; const void *info = NULL; int result; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(&data, cmd.data, cmd.data_len); if (result) goto done; result = ib_ucm_alloc_data(&info, cmd.info, cmd.info_len); if (result) goto done; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { result = func(ctx->cm_id, cmd.status, info, cmd.info_len, data, cmd.data_len); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx);done: kfree(data); kfree(info); return result;}static ssize_t ib_ucm_send_rej(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ return ib_ucm_send_info(file, inbuf, in_len, (void *)ib_send_cm_rej);}static ssize_t ib_ucm_send_apr(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ return ib_ucm_send_info(file, inbuf, in_len, (void *)ib_send_cm_apr);}static ssize_t ib_ucm_send_mra(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_context *ctx; struct ib_ucm_mra cmd; const void *data = NULL; int result; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(&data, cmd.data, cmd.len); if (result) return result; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { result = ib_send_cm_mra(ctx->cm_id, cmd.timeout, data, cmd.len); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx); kfree(data); return result;}static ssize_t ib_ucm_send_lap(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_context *ctx; struct ib_sa_path_rec *path = NULL; struct ib_ucm_lap cmd; const void *data = NULL; int result; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(&data, cmd.data, cmd.len); if (result) goto done; result = ib_ucm_path_get(&path, cmd.path); if (result) goto done; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { result = ib_send_cm_lap(ctx->cm_id, path, data, cmd.len); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx);done: kfree(data); kfree(path); return result;}static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_cm_sidr_req_param param; struct ib_ucm_context *ctx; struct ib_ucm_sidr_req cmd; int result; param.private_data = NULL; param.path = NULL; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(¶m.private_data, cmd.data, cmd.len); if (result) goto done; result = ib_ucm_path_get(¶m.path, cmd.path); if (result) goto done; param.private_data_len = cmd.len; param.service_id = cmd.sid; param.timeout_ms = cmd.timeout; param.max_cm_retries = cmd.max_cm_retries; param.pkey = cmd.pkey; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { result = ib_send_cm_sidr_req(ctx->cm_id, ¶m); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx);done: kfree(param.private_data); kfree(param.path); return result;}static ssize_t ib_ucm_send_sidr_rep(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_cm_sidr_rep_param param; struct ib_ucm_sidr_rep cmd; struct ib_ucm_context *ctx; int result; param.info = NULL; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(¶m.private_data, cmd.data, cmd.data_len); if (result) goto done; result = ib_ucm_alloc_data(¶m.info, cmd.info, cmd.info_len); if (result) goto done; param.qp_num = cmd.qpn; param.qkey = cmd.qkey; param.status = cmd.status; param.info_length = cmd.info_len; param.private_data_len = cmd.data_len; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { result = ib_send_cm_sidr_rep(ctx->cm_id, ¶m); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx);done: kfree(param.private_data); kfree(param.info); return result;}static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len) = { [IB_USER_CM_CMD_CREATE_ID] = ib_ucm_create_id, [IB_USER_CM_CMD_DESTROY_ID] = ib_ucm_destroy_id, [IB_USER_CM_CMD_ATTR_ID] = ib_ucm_attr_id, [IB_USER_CM_CMD_LISTEN] = ib_ucm_listen, [IB_USER_CM_CMD_ESTABLISH] = ib_ucm_establish, [IB_USER_CM_CMD_SEND_REQ] = ib_ucm_send_req, [IB_USER_CM_CMD_SEND_REP] = ib_ucm_send_rep, [IB_USER_CM_CMD_SEND_RTU] = ib_ucm_send_rtu, [IB_USER_CM_CMD_SEND_DREQ] = ib_ucm_send_dreq, [IB_USER_CM_CMD_SEND_DREP] = ib_ucm_send_drep, [IB_USER_CM_CMD_SEND_REJ] = ib_ucm_send_rej, [IB_USER_CM_CMD_SEND_MRA] = ib_ucm_send_mra, [IB_USER_CM_CMD_SEND_LAP] = ib_ucm_send_lap, [IB_USER_CM_CMD_SEND_APR] = ib_ucm_send_apr, [IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req, [IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep, [IB_USER_CM_CMD_EVENT] = ib_ucm_event, [IB_USER_CM_CMD_INIT_QP_ATTR] = ib_ucm_init_qp_attr,};static ssize_t ib_ucm_write(struct file *filp, const char __user *buf, size_t len, loff_t *pos){ struct ib_ucm_file *file = filp->private_data; struct ib_ucm_cmd_hdr hdr; ssize_t result; if (len < sizeof(hdr)) return -EINVAL; if (copy_from_user(&hdr, buf, sizeof(hdr))) return -EFAULT; if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table)) return -EINVAL; if (hdr.in + sizeof(hdr) > len) return -EINVAL; result = ucm_cmd_table[hdr.cmd](file, buf + sizeof(hdr), hdr.in, hdr.out); if (!result) result = len; return result;}static unsigned int ib_ucm_poll(struct file *filp, struct poll_table_struct *wait){ struct ib_ucm_file *file = filp->private_data; unsigned int mask = 0; poll_wait(filp, &file->poll_wait, wait); if (!list_empty(&file->events)) mask = POLLIN | POLLRDNORM; return mask;}static int ib_ucm_open(struct inode *inode, struct file *filp){ struct ib_ucm_file *file; file = kmalloc(sizeof(*file), GFP_KERNEL); if (!file) return -ENOMEM; INIT_LIST_HEAD(&file->events); INIT_LIST_HEAD(&file->ctxs); init_waitqueue_head(&file->poll_wait); init_MUTEX(&file->mutex); filp->private_data = file; file->filp = filp; file->device = container_of(inode->i_cdev, struct ib_ucm_device, dev); return 0;}static int ib_ucm_close(struct inode *inode, struct file *filp){ struct ib_ucm_file *file = filp->private_data; struct ib_ucm_context *ctx; down(&file->mutex); while (!list_empty(&file->ctxs)) { ctx = list_entry(file->ctxs.next, struct ib_ucm_context, file_list); up(&file->mutex); down(&ctx_id_mutex); idr_remove(&ctx_id_table, ctx->id); up(&ctx_id_mutex); ib_destroy_cm_id(ctx->cm_id); ib_ucm_cleanup_events(ctx); kfree(ctx); down(&file->mutex); } up(&file->mutex); kfree(file); return 0;}static void ib_ucm_release_class_dev(struct class_device *class_dev){ struct ib_ucm_device *dev; dev = container_of(class_dev, struct ib_ucm_device, class_dev); cdev_del(&dev->dev); clear_bit(dev->devnum, dev_map); kfree(dev);}static struct file_operations ucm_fops = { .owner = THIS_MODULE, .open = ib_ucm_open, .release = ib_ucm_close, .write = ib_ucm_write, .poll = ib_ucm_poll,};static struct class ucm_class = { .name = "infiniband_cm", .release = ib_ucm_release_class_dev};static ssize_t show_dev(struct class_device *class_dev, char *buf){ struct ib_ucm_device *dev; dev = container_of(class_dev, struct ib_ucm_device, class_dev); return print_dev_t(buf, dev->dev.dev);}static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);static ssize_t show_ibdev(struct class_device *class_dev, char *buf){ struct ib_ucm_device *dev; dev = container_of(class_dev, struct ib_ucm_device, class_dev); return sprintf(buf, "%s\n", dev->ib_dev->name);}static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);static void ib_ucm_add_one(struct ib_device *device){ struct ib_ucm_device *ucm_dev; if (!device->alloc_ucontext) return; ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL); if (!ucm_dev) return; ucm_dev->ib_dev = device; ucm_dev->devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES); if (ucm_dev->devnum >= IB_UCM_MAX_DEVICES) goto err; set_bit(ucm_dev->devnum, dev_map); cdev_init(&ucm_dev->dev, &ucm_fops); ucm_dev->dev.owner = THIS_MODULE; kobject_set_name(&ucm_dev->dev.kobj, "ucm%d", ucm_dev->devnum); if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1)) goto err; ucm_dev->class_dev.class = &ucm_class; ucm_dev->class_dev.dev = device->dma_device; snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d", ucm_dev->devnum); if (class_device_register(&ucm_dev->class_dev)) goto err_cdev; if (class_device_create_file(&ucm_dev->class_dev, &class_device_attr_dev)) goto err_class; if (class_device_create_file(&ucm_dev->class_dev, &class_device_attr_ibdev)) goto err_class; ib_set_client_data(device, &ucm_client, ucm_dev); return;err_class: class_device_unregister(&ucm_dev->class_dev);err_cdev: cdev_del(&ucm_dev->dev); clear_bit(ucm_dev->devnum, dev_map);err: kfree(ucm_dev); return;}static void ib_ucm_remove_one(struct ib_device *device){ struct ib_ucm_device *ucm_dev = ib_get_client_data(device, &ucm_client); if (!ucm_dev) return; class_device_unregister(&ucm_dev->class_dev);}static ssize_t show_abi_version(struct class *class, char *buf){ return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION);}static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);static int __init ib_ucm_init(void){ int ret; ret = register_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES, "infiniband_cm"); if (ret) { printk(KERN_ERR "ucm: couldn't register device number\n"); goto err; } ret = class_register(&ucm_class); if (ret) { printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n"); goto err_chrdev; } ret = class_create_file(&ucm_class, &class_attr_abi_version); if (ret) { printk(KERN_ERR "ucm: couldn't create abi_version attribute\n"); goto err_class; } ret = ib_register_client(&ucm_client); if (ret) { printk(KERN_ERR "ucm: couldn't register client\n"); goto err_class; } return 0;err_class: class_unregister(&ucm_class);err_chrdev: unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);err: return ret;}static void __exit ib_ucm_cleanup(void){ ib_unregister_client(&ucm_client); class_unregister(&ucm_class); unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES); idr_destroy(&ctx_id_table);}module_init(ib_ucm_init);module_exit(ib_ucm_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -