37 #include <linux/module.h>
38 #include <linux/device.h>
40 #include <linux/poll.h>
41 #include <linux/sched.h>
47 #include <linux/slab.h>
49 #include <asm/uaccess.h>
109 #define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR)
116 .add = ib_ucm_add_one,
117 .remove = ib_ucm_remove_one
132 else if (ctx->
file != file)
147 static inline int ib_ucm_new_cm_id(
int event)
158 while (!list_empty(&ctx->
events)) {
167 if (ib_ucm_new_cm_id(uevent->
resp.event))
186 init_completion(&ctx->
comp);
188 INIT_LIST_HEAD(&ctx->
events);
198 }
while (result == -
EAGAIN);
264 switch (evt->
event) {
266 ib_ucm_event_req_get(&uvt->
resp.u.req_resp,
274 ib_ucm_event_rep_get(&uvt->
resp.u.rep_resp,
291 uvt->
resp.u.mra_resp.timeout =
314 uvt->
resp.u.sidr_req_resp.pkey =
316 uvt->
resp.u.sidr_req_resp.port =
321 ib_ucm_event_sidr_rep_get(&uvt->
resp.u.sidr_rep_resp,
371 uevent->
resp.id = ctx->
id;
372 uevent->
resp.event =
event->event;
374 result = ib_ucm_event_process(event, uevent);
389 return ib_ucm_new_cm_id(event->
event);
393 const char __user *
inbuf,
408 while (list_empty(&file->
events)) {
415 !list_empty(&file->
events)))
423 if (ib_ucm_new_cm_id(uevent->
resp.event)) {
424 ctx = ib_ucm_ctx_alloc(file);
432 uevent->
resp.id = ctx->
id;
436 &uevent->
resp,
sizeof(uevent->
resp))) {
467 uevent->
ctx->events_reported++;
478 const char __user *inbuf,
479 int in_len,
int out_len)
486 if (out_len <
sizeof(
resp))
493 ctx = ib_ucm_ctx_alloc(file);
500 ib_ucm_event_handler, ctx);
501 if (IS_ERR(ctx->
cm_id)) {
502 result = PTR_ERR(ctx->
cm_id);
525 const char __user *inbuf,
526 int in_len,
int out_len)
533 if (out_len <
sizeof(
resp))
543 else if (ctx->
file != file)
558 ib_ucm_cleanup_events(ctx);
570 const char __user *inbuf,
571 int in_len,
int out_len)
578 if (out_len <
sizeof(
resp))
584 ctx = ib_ucm_ctx_get(file,
cmd.id);
588 resp.service_id = ctx->
cm_id->service_id;
589 resp.service_mask = ctx->
cm_id->service_mask;
602 const char __user *inbuf,
603 int in_len,
int out_len)
611 if (out_len <
sizeof(
resp))
617 ctx = ib_ucm_ctx_get(file,
cmd.id);
621 resp.qp_attr_mask = 0;
622 memset(&qp_attr, 0,
sizeof qp_attr);
623 qp_attr.qp_state =
cmd.qp_state;
641 service_id &= service_mask;
651 const char __user *inbuf,
652 int in_len,
int out_len)
661 ctx = ib_ucm_ctx_get(file,
cmd.id);
665 result = ucm_validate_listen(
cmd.service_id,
cmd.service_mask);
677 const char __user *inbuf,
678 int in_len,
int out_len)
687 ctx = ib_ucm_ctx_get(file,
cmd.id);
696 static int ib_ucm_alloc_data(
const void **
dest,
u64 src,
u32 len)
705 data =
memdup_user((
void __user *)(
unsigned long)src, len);
707 return PTR_ERR(data);
740 const char __user *inbuf,
741 int in_len,
int out_len)
755 result = ib_ucm_alloc_data(&
param.private_data,
cmd.data,
cmd.len);
759 result = ib_ucm_path_get(&
param.primary_path,
cmd.primary_path);
763 result = ib_ucm_path_get(&
param.alternate_path,
cmd.alternate_path);
772 param.peer_to_peer =
cmd.peer_to_peer;
773 param.responder_resources =
cmd.responder_resources;
774 param.initiator_depth =
cmd.initiator_depth;
775 param.remote_cm_response_timeout =
cmd.remote_cm_response_timeout;
776 param.flow_control =
cmd.flow_control;
777 param.local_cm_response_timeout =
cmd.local_cm_response_timeout;
778 param.retry_count =
cmd.retry_count;
779 param.rnr_retry_count =
cmd.rnr_retry_count;
780 param.max_cm_retries =
cmd.max_cm_retries;
783 ctx = ib_ucm_ctx_get(file,
cmd.id);
788 result = PTR_ERR(ctx);
798 const char __user *inbuf,
799 int in_len,
int out_len)
811 result = ib_ucm_alloc_data(&
param.private_data,
cmd.data,
cmd.len);
818 param.responder_resources =
cmd.responder_resources;
819 param.initiator_depth =
cmd.initiator_depth;
820 param.failover_accepted =
cmd.failover_accepted;
821 param.flow_control =
cmd.flow_control;
822 param.rnr_retry_count =
cmd.rnr_retry_count;
825 ctx = ib_ucm_ctx_get(file,
cmd.id);
831 result = PTR_ERR(ctx);
838 const char __user *inbuf,
int in_len,
841 u8 private_data_len))
845 const void *private_data =
NULL;
851 result = ib_ucm_alloc_data(&private_data,
cmd.data,
cmd.len);
855 ctx = ib_ucm_ctx_get(file,
cmd.id);
860 result = PTR_ERR(ctx);
867 const char __user *inbuf,
868 int in_len,
int out_len)
870 return ib_ucm_send_private_data(file, inbuf, in_len,
ib_send_cm_rtu);
874 const char __user *inbuf,
875 int in_len,
int out_len)
881 const char __user *inbuf,
882 int in_len,
int out_len)
888 const char __user *inbuf,
int in_len,
898 const void *data =
NULL;
899 const void *info =
NULL;
905 result = ib_ucm_alloc_data(&data,
cmd.data,
cmd.data_len);
909 result = ib_ucm_alloc_data(&info,
cmd.info,
cmd.info_len);
913 ctx = ib_ucm_ctx_get(file,
cmd.id);
919 result = PTR_ERR(ctx);
928 const char __user *inbuf,
929 int in_len,
int out_len)
931 return ib_ucm_send_info(file, inbuf, in_len, (
void *)
ib_send_cm_rej);
935 const char __user *inbuf,
936 int in_len,
int out_len)
938 return ib_ucm_send_info(file, inbuf, in_len, (
void *)
ib_send_cm_apr);
942 const char __user *inbuf,
943 int in_len,
int out_len)
947 const void *data =
NULL;
953 result = ib_ucm_alloc_data(&data,
cmd.data,
cmd.len);
957 ctx = ib_ucm_ctx_get(file,
cmd.id);
962 result = PTR_ERR(ctx);
969 const char __user *inbuf,
970 int in_len,
int out_len)
975 const void *data =
NULL;
981 result = ib_ucm_alloc_data(&data,
cmd.data,
cmd.len);
985 result = ib_ucm_path_get(&path,
cmd.path);
989 ctx = ib_ucm_ctx_get(file,
cmd.id);
994 result = PTR_ERR(ctx);
1003 const char __user *inbuf,
1004 int in_len,
int out_len)
1017 result = ib_ucm_alloc_data(&
param.private_data,
cmd.data,
cmd.len);
1021 result = ib_ucm_path_get(&
param.path,
cmd.path);
1028 param.max_cm_retries =
cmd.max_cm_retries;
1030 ctx = ib_ucm_ctx_get(file,
cmd.id);
1033 ib_ucm_ctx_put(ctx);
1035 result = PTR_ERR(ctx);
1044 const char __user *inbuf,
1045 int in_len,
int out_len)
1057 result = ib_ucm_alloc_data(&
param.private_data,
1062 result = ib_ucm_alloc_data(&
param.info,
cmd.info,
cmd.info_len);
1070 param.private_data_len =
cmd.data_len;
1072 ctx = ib_ucm_ctx_get(file,
cmd.id);
1075 ib_ucm_ctx_put(ctx);
1077 result = PTR_ERR(ctx);
1086 const char __user *inbuf,
1108 static ssize_t ib_ucm_write(
struct file *
filp,
const char __user *
buf,
1109 size_t len, loff_t *
pos)
1115 if (len <
sizeof(
hdr))
1124 if (
hdr.in +
sizeof(
hdr) > len)
1127 result = ucm_cmd_table[
hdr.cmd](
file, buf +
sizeof(
hdr),
1135 static unsigned int ib_ucm_poll(
struct file *filp,
1139 unsigned int mask = 0;
1143 if (!list_empty(&file->
events))
1157 static int ib_ucm_open(
struct inode *
inode,
struct file *filp)
1165 INIT_LIST_HEAD(&file->
events);
1166 INIT_LIST_HEAD(&file->
ctxs);
1178 static int ib_ucm_close(
struct inode *inode,
struct file *filp)
1184 while (!list_empty(&file->
ctxs)) {
1194 ib_ucm_cleanup_events(ctx);
1204 static void ib_ucm_release_dev(
struct device *
dev)
1219 .open = ib_ucm_open,
1220 .release = ib_ucm_close,
1221 .write = ib_ucm_write,
1222 .poll = ib_ucm_poll,
1236 static dev_t overflow_maj;
1238 static int find_overflow_devnum(
void)
1242 if (!overflow_maj) {
1246 printk(
KERN_ERR "ucm: couldn't register dynamic device number\n");
1268 ucm_dev = kzalloc(
sizeof *ucm_dev,
GFP_KERNEL);
1272 ucm_dev->
ib_dev = device;
1276 devnum = find_overflow_devnum();
1281 base = devnum + overflow_maj;
1282 set_bit(devnum, overflow_map);
1297 ucm_dev->
dev.devt = ucm_dev->
cdev.dev;
1298 ucm_dev->
dev.release = ib_ucm_release_dev;
1322 static void ib_ucm_remove_one(
struct ib_device *device)
1335 static int __init ib_ucm_init(
void)
1367 static void __exit ib_ucm_cleanup(
void)