36 #include <linux/poll.h>
37 #include <linux/sched.h>
40 #include <linux/in6.h>
42 #include <linux/slab.h>
43 #include <linux/sysctl.h>
44 #include <linux/module.h>
55 static unsigned int max_backlog = 1024;
62 .maxlen =
sizeof max_backlog,
114 static inline struct ucma_context *_ucma_find_context(
int id,
122 else if (ctx->
file != file)
132 ctx = _ucma_find_context(
id, file);
155 init_completion(&ctx->
comp);
239 static void ucma_set_event_context(
struct ucma_context *ctx,
244 switch (event->
event) {
249 uevent->
resp.uid = uevent->
mc->uid;
250 uevent->
resp.id = uevent->
mc->id;
254 uevent->
resp.id = ctx->
id;
266 uevent = kzalloc(
sizeof(*uevent),
GFP_KERNEL);
272 ucma_set_event_context(ctx, event, uevent);
273 uevent->
resp.event =
event->event;
274 uevent->
resp.status =
event->status;
276 ucma_copy_ud_event(&uevent->
resp.param.ud, &event->
param.
ud);
278 ucma_copy_conn_event(&uevent->
resp.param.conn,
288 }
else if (!ctx->
uid) {
314 if (out_len < sizeof uevent->
resp)
337 ctx = ucma_alloc_ctx(file);
342 uevent->
ctx->backlog++;
345 uevent->
resp.id = ctx->
id;
349 &uevent->
resp,
sizeof uevent->
resp)) {
355 uevent->
ctx->events_reported++;
357 uevent->
mc->events_reported++;
382 static ssize_t ucma_create_id(
struct ucma_file *file,
const char __user *inbuf,
383 int in_len,
int out_len)
391 if (out_len <
sizeof(resp))
397 ret = ucma_get_qp_type(&cmd, &qp_type);
402 ctx = ucma_alloc_ctx(file);
409 if (IS_ERR(ctx->
cm_id)) {
410 ret = PTR_ERR(ctx->
cm_id);
416 &resp,
sizeof(resp))) {
432 static void ucma_cleanup_multicast(
struct ucma_context *ctx)
450 if (uevent->
mc != mc)
472 ucma_cleanup_multicast(ctx);
477 if (uevent->
ctx == ctx)
478 list_move_tail(&uevent->
list, &
list);
492 return events_reported;
495 static ssize_t ucma_destroy_id(
struct ucma_file *file,
const char __user *inbuf,
496 int in_len,
int out_len)
503 if (out_len <
sizeof(resp))
510 ctx = _ucma_find_context(cmd.id, file);
520 resp.events_reported = ucma_free_ctx(ctx);
523 &resp,
sizeof(resp)))
529 static ssize_t ucma_bind_addr(
struct ucma_file *file,
const char __user *inbuf,
530 int in_len,
int out_len)
539 ctx = ucma_get_ctx(file, cmd.id);
549 const char __user *inbuf,
550 int in_len,
int out_len)
559 ctx = ucma_get_ctx(file, cmd.id);
571 const char __user *inbuf,
572 int in_len,
int out_len)
581 ctx = ucma_get_ctx(file, cmd.id);
598 dev_addr = &route->
addr.dev_addr;
599 rdma_addr_get_dgid(dev_addr,
601 rdma_addr_get_sgid(dev_addr,
628 dev_addr = &route->
addr.dev_addr;
631 vid = rdma_vlan_dev_vlan_id(dev);
637 iboe_addr_get_sgid(dev_addr,
659 dev_addr = &route->
addr.dev_addr;
660 rdma_addr_get_dgid(dev_addr, (
union ib_gid *) &resp->
ib_route[0].dgid);
661 rdma_addr_get_sgid(dev_addr, (
union ib_gid *) &resp->
ib_route[0].sgid);
665 const char __user *inbuf,
666 int in_len,
int out_len)
674 if (out_len <
sizeof(resp))
680 ctx = ucma_get_ctx(file, cmd.id);
684 memset(&resp, 0,
sizeof resp);
693 if (!ctx->
cm_id->device)
701 ctx->
cm_id->port_num)) {
703 ucma_copy_ib_route(&resp, &ctx->
cm_id->route);
706 ucma_copy_iboe_route(&resp, &ctx->
cm_id->route);
713 ucma_copy_iw_route(&resp, &ctx->
cm_id->route);
721 &resp,
sizeof(resp)))
742 static ssize_t ucma_connect(
struct ucma_file *file,
const char __user *inbuf,
743 int in_len,
int out_len)
753 if (!cmd.conn_param.valid)
756 ctx = ucma_get_ctx(file, cmd.id);
760 ucma_copy_conn_param(&conn_param, &cmd.conn_param);
766 static ssize_t ucma_listen(
struct ucma_file *file,
const char __user *inbuf,
767 int in_len,
int out_len)
776 ctx = ucma_get_ctx(file, cmd.id);
780 ctx->
backlog = cmd.backlog > 0 && cmd.backlog < max_backlog ?
781 cmd.backlog : max_backlog;
787 static ssize_t ucma_accept(
struct ucma_file *file,
const char __user *inbuf,
788 int in_len,
int out_len)
798 ctx = ucma_get_ctx(file, cmd.id);
802 if (cmd.conn_param.valid) {
803 ucma_copy_conn_param(&conn_param, &cmd.conn_param);
816 static ssize_t ucma_reject(
struct ucma_file *file,
const char __user *inbuf,
817 int in_len,
int out_len)
826 ctx = ucma_get_ctx(file, cmd.id);
835 static ssize_t ucma_disconnect(
struct ucma_file *file,
const char __user *inbuf,
836 int in_len,
int out_len)
845 ctx = ucma_get_ctx(file, cmd.id);
855 const char __user *inbuf,
856 int in_len,
int out_len)
864 if (out_len <
sizeof(resp))
870 ctx = ucma_get_ctx(file, cmd.id);
874 resp.qp_attr_mask = 0;
875 memset(&qp_attr, 0,
sizeof qp_attr);
876 qp_attr.qp_state = cmd.qp_state;
883 &resp,
sizeof(resp)))
891 static int ucma_set_option_id(
struct ucma_context *ctx,
int optname,
892 void *optval,
size_t optlen)
898 if (optlen !=
sizeof(
u8)) {
905 if (optlen !=
sizeof(
int)) {
912 if (optlen !=
sizeof(
int)) {
932 if (optlen %
sizeof(*path_data))
935 for (; optlen; optlen -=
sizeof(*path_data), path_data++) {
949 memset(&event, 0,
sizeof event);
951 return ucma_event_handler(ctx->
cm_id, &event);
954 static int ucma_set_option_ib(
struct ucma_context *ctx,
int optname,
955 void *optval,
size_t optlen)
961 ret = ucma_set_ib_path(ctx, optval, optlen);
971 int optname,
void *optval,
size_t optlen)
977 ret = ucma_set_option_id(ctx, optname, optval, optlen);
980 ret = ucma_set_option_ib(ctx, optname, optval, optlen);
989 static ssize_t ucma_set_option(
struct ucma_file *file,
const char __user *inbuf,
990 int in_len,
int out_len)
1000 ctx = ucma_get_ctx(file, cmd.id);
1002 return PTR_ERR(ctx);
1004 optval =
memdup_user((
void __user *) (
unsigned long) cmd.optval,
1006 if (IS_ERR(optval)) {
1007 ret = PTR_ERR(optval);
1011 ret = ucma_set_option_level(ctx, cmd.level, cmd.optname, optval,
1020 static ssize_t ucma_notify(
struct ucma_file *file,
const char __user *inbuf,
1021 int in_len,
int out_len)
1030 ctx = ucma_get_ctx(file, cmd.id);
1032 return PTR_ERR(ctx);
1040 const char __user *inbuf,
1041 int in_len,
int out_len)
1049 if (out_len <
sizeof(resp))
1055 ctx = ucma_get_ctx(file, cmd.id);
1057 return PTR_ERR(ctx);
1060 mc = ucma_alloc_multicast(ctx);
1067 memcpy(&mc->
addr, &cmd.addr,
sizeof cmd.addr);
1074 &resp,
sizeof(resp))) {
1085 ucma_cleanup_mc_events(mc);
1099 const char __user *inbuf,
1100 int in_len,
int out_len)
1107 if (out_len <
sizeof(resp))
1114 mc =
idr_find(&multicast_idr, cmd.id);
1117 else if (mc->
ctx->file != file)
1132 ucma_cleanup_mc_events(mc);
1136 ucma_put_ctx(mc->
ctx);
1141 &resp,
sizeof(resp)))
1150 if (file1 < file2) {
1161 if (file1 < file2) {
1175 if (uevent->ctx == ctx)
1180 const char __user *inbuf,
1181 int in_len,
int out_len)
1199 ctx = ucma_get_ctx(
f.file->private_data, cmd.id);
1205 cur_file = ctx->
file;
1206 if (cur_file == new_file) {
1215 ucma_lock_files(cur_file, new_file);
1218 list_move_tail(&ctx->
list, &new_file->ctx_list);
1219 ucma_move_events(ctx, new_file);
1220 ctx->
file = new_file;
1224 ucma_unlock_files(cur_file, new_file);
1228 &resp,
sizeof(resp)))
1238 const char __user *inbuf,
1261 static ssize_t ucma_write(
struct file *
filp,
const char __user *
buf,
1262 size_t len, loff_t *
pos)
1268 if (len <
sizeof(
hdr))
1277 if (
hdr.in +
sizeof(
hdr) > len)
1280 if (!ucma_cmd_table[
hdr.cmd])
1293 unsigned int mask = 0;
1311 static int ucma_open(
struct inode *
inode,
struct file *filp)
1330 static int ucma_close(
struct inode *inode,
struct file *filp)
1354 .release = ucma_close,
1355 .write = ucma_write,
1363 .nodename =
"infiniband/rdma_cm",
1376 static int __init ucma_init(
void)
1391 if (!ucma_ctl_table_hdr) {
1404 static void __exit ucma_cleanup(
void)