aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/uverbs.h5
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c182
-rw-r--r--drivers/infiniband/core/uverbs_main.c20
-rw-r--r--drivers/infiniband/include/ib_user_verbs.h35
4 files changed, 238 insertions, 4 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 3e158f5acfc6..db161810c0c0 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -99,10 +99,12 @@ extern struct idr ib_uverbs_mw_idr;
99extern struct idr ib_uverbs_ah_idr; 99extern struct idr ib_uverbs_ah_idr;
100extern struct idr ib_uverbs_cq_idr; 100extern struct idr ib_uverbs_cq_idr;
101extern struct idr ib_uverbs_qp_idr; 101extern struct idr ib_uverbs_qp_idr;
102extern struct idr ib_uverbs_srq_idr;
102 103
103void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context); 104void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
104void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr); 105void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
105void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); 106void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
107void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
106 108
107int ib_umem_get(struct ib_device *dev, struct ib_umem *mem, 109int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
108 void *addr, size_t size, int write); 110 void *addr, size_t size, int write);
@@ -131,5 +133,8 @@ IB_UVERBS_DECLARE_CMD(modify_qp);
131IB_UVERBS_DECLARE_CMD(destroy_qp); 133IB_UVERBS_DECLARE_CMD(destroy_qp);
132IB_UVERBS_DECLARE_CMD(attach_mcast); 134IB_UVERBS_DECLARE_CMD(attach_mcast);
133IB_UVERBS_DECLARE_CMD(detach_mcast); 135IB_UVERBS_DECLARE_CMD(detach_mcast);
136IB_UVERBS_DECLARE_CMD(create_srq);
137IB_UVERBS_DECLARE_CMD(modify_srq);
138IB_UVERBS_DECLARE_CMD(destroy_srq);
134 139
135#endif /* UVERBS_H */ 140#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 5f2bbcda4c73..ebccf9f38af9 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -724,6 +724,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
724 struct ib_uobject *uobj; 724 struct ib_uobject *uobj;
725 struct ib_pd *pd; 725 struct ib_pd *pd;
726 struct ib_cq *scq, *rcq; 726 struct ib_cq *scq, *rcq;
727 struct ib_srq *srq;
727 struct ib_qp *qp; 728 struct ib_qp *qp;
728 struct ib_qp_init_attr attr; 729 struct ib_qp_init_attr attr;
729 int ret; 730 int ret;
@@ -747,10 +748,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
747 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 748 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
748 scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); 749 scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
749 rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle); 750 rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
751 srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
750 752
751 if (!pd || pd->uobject->context != file->ucontext || 753 if (!pd || pd->uobject->context != file->ucontext ||
752 !scq || scq->uobject->context != file->ucontext || 754 !scq || scq->uobject->context != file->ucontext ||
753 !rcq || rcq->uobject->context != file->ucontext) { 755 !rcq || rcq->uobject->context != file->ucontext ||
756 (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
754 ret = -EINVAL; 757 ret = -EINVAL;
755 goto err_up; 758 goto err_up;
756 } 759 }
@@ -759,7 +762,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
759 attr.qp_context = file; 762 attr.qp_context = file;
760 attr.send_cq = scq; 763 attr.send_cq = scq;
761 attr.recv_cq = rcq; 764 attr.recv_cq = rcq;
762 attr.srq = NULL; 765 attr.srq = srq;
763 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 766 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
764 attr.qp_type = cmd.qp_type; 767 attr.qp_type = cmd.qp_type;
765 768
@@ -1004,3 +1007,178 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
1004 1007
1005 return ret ? ret : in_len; 1008 return ret ? ret : in_len;
1006} 1009}
1010
1011ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
1012 const char __user *buf, int in_len,
1013 int out_len)
1014{
1015 struct ib_uverbs_create_srq cmd;
1016 struct ib_uverbs_create_srq_resp resp;
1017 struct ib_udata udata;
1018 struct ib_uobject *uobj;
1019 struct ib_pd *pd;
1020 struct ib_srq *srq;
1021 struct ib_srq_init_attr attr;
1022 int ret;
1023
1024 if (out_len < sizeof resp)
1025 return -ENOSPC;
1026
1027 if (copy_from_user(&cmd, buf, sizeof cmd))
1028 return -EFAULT;
1029
1030 INIT_UDATA(&udata, buf + sizeof cmd,
1031 (unsigned long) cmd.response + sizeof resp,
1032 in_len - sizeof cmd, out_len - sizeof resp);
1033
1034 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
1035 if (!uobj)
1036 return -ENOMEM;
1037
1038 down(&ib_uverbs_idr_mutex);
1039
1040 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
1041
1042 if (!pd || pd->uobject->context != file->ucontext) {
1043 ret = -EINVAL;
1044 goto err_up;
1045 }
1046
1047 attr.event_handler = ib_uverbs_srq_event_handler;
1048 attr.srq_context = file;
1049 attr.attr.max_wr = cmd.max_wr;
1050 attr.attr.max_sge = cmd.max_sge;
1051 attr.attr.srq_limit = cmd.srq_limit;
1052
1053 uobj->user_handle = cmd.user_handle;
1054 uobj->context = file->ucontext;
1055
1056 srq = pd->device->create_srq(pd, &attr, &udata);
1057 if (IS_ERR(srq)) {
1058 ret = PTR_ERR(srq);
1059 goto err_up;
1060 }
1061
1062 srq->device = pd->device;
1063 srq->pd = pd;
1064 srq->uobject = uobj;
1065 srq->event_handler = attr.event_handler;
1066 srq->srq_context = attr.srq_context;
1067 atomic_inc(&pd->usecnt);
1068 atomic_set(&srq->usecnt, 0);
1069
1070 memset(&resp, 0, sizeof resp);
1071
1072retry:
1073 if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
1074 ret = -ENOMEM;
1075 goto err_destroy;
1076 }
1077
1078 ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id);
1079
1080 if (ret == -EAGAIN)
1081 goto retry;
1082 if (ret)
1083 goto err_destroy;
1084
1085 resp.srq_handle = uobj->id;
1086
1087 spin_lock_irq(&file->ucontext->lock);
1088 list_add_tail(&uobj->list, &file->ucontext->srq_list);
1089 spin_unlock_irq(&file->ucontext->lock);
1090
1091 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1092 &resp, sizeof resp)) {
1093 ret = -EFAULT;
1094 goto err_list;
1095 }
1096
1097 up(&ib_uverbs_idr_mutex);
1098
1099 return in_len;
1100
1101err_list:
1102 spin_lock_irq(&file->ucontext->lock);
1103 list_del(&uobj->list);
1104 spin_unlock_irq(&file->ucontext->lock);
1105
1106err_destroy:
1107 ib_destroy_srq(srq);
1108
1109err_up:
1110 up(&ib_uverbs_idr_mutex);
1111
1112 kfree(uobj);
1113 return ret;
1114}
1115
1116ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
1117 const char __user *buf, int in_len,
1118 int out_len)
1119{
1120 struct ib_uverbs_modify_srq cmd;
1121 struct ib_srq *srq;
1122 struct ib_srq_attr attr;
1123 int ret;
1124
1125 if (copy_from_user(&cmd, buf, sizeof cmd))
1126 return -EFAULT;
1127
1128 down(&ib_uverbs_idr_mutex);
1129
1130 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1131 if (!srq || srq->uobject->context != file->ucontext) {
1132 ret = -EINVAL;
1133 goto out;
1134 }
1135
1136 attr.max_wr = cmd.max_wr;
1137 attr.max_sge = cmd.max_sge;
1138 attr.srq_limit = cmd.srq_limit;
1139
1140 ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
1141
1142out:
1143 up(&ib_uverbs_idr_mutex);
1144
1145 return ret ? ret : in_len;
1146}
1147
1148ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
1149 const char __user *buf, int in_len,
1150 int out_len)
1151{
1152 struct ib_uverbs_destroy_srq cmd;
1153 struct ib_srq *srq;
1154 struct ib_uobject *uobj;
1155 int ret = -EINVAL;
1156
1157 if (copy_from_user(&cmd, buf, sizeof cmd))
1158 return -EFAULT;
1159
1160 down(&ib_uverbs_idr_mutex);
1161
1162 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
1163 if (!srq || srq->uobject->context != file->ucontext)
1164 goto out;
1165
1166 uobj = srq->uobject;
1167
1168 ret = ib_destroy_srq(srq);
1169 if (ret)
1170 goto out;
1171
1172 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
1173
1174 spin_lock_irq(&file->ucontext->lock);
1175 list_del(&uobj->list);
1176 spin_unlock_irq(&file->ucontext->lock);
1177
1178 kfree(uobj);
1179
1180out:
1181 up(&ib_uverbs_idr_mutex);
1182
1183 return ret ? ret : in_len;
1184}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index fd8e96359304..09caf5b1ef36 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -69,6 +69,7 @@ DEFINE_IDR(ib_uverbs_mw_idr);
69DEFINE_IDR(ib_uverbs_ah_idr); 69DEFINE_IDR(ib_uverbs_ah_idr);
70DEFINE_IDR(ib_uverbs_cq_idr); 70DEFINE_IDR(ib_uverbs_cq_idr);
71DEFINE_IDR(ib_uverbs_qp_idr); 71DEFINE_IDR(ib_uverbs_qp_idr);
72DEFINE_IDR(ib_uverbs_srq_idr);
72 73
73static spinlock_t map_lock; 74static spinlock_t map_lock;
74static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); 75static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -93,6 +94,9 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
93 [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp, 94 [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,
94 [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast, 95 [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,
95 [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast, 96 [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,
97 [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,
98 [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
99 [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
96}; 100};
97 101
98static struct vfsmount *uverbs_event_mnt; 102static struct vfsmount *uverbs_event_mnt;
@@ -127,7 +131,14 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
127 kfree(uobj); 131 kfree(uobj);
128 } 132 }
129 133
130 /* XXX Free SRQs */ 134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
135 struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
136 idr_remove(&ib_uverbs_srq_idr, uobj->id);
137 ib_destroy_srq(srq);
138 list_del(&uobj->list);
139 kfree(uobj);
140 }
141
131 /* XXX Free MWs */ 142 /* XXX Free MWs */
132 143
133 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { 144 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
@@ -346,6 +357,13 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
346 event->event); 357 event->event);
347} 358}
348 359
360void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
361{
362 ib_uverbs_async_handler(context_ptr,
363 event->element.srq->uobject->user_handle,
364 event->event);
365}
366
349static void ib_uverbs_event_handler(struct ib_event_handler *handler, 367static void ib_uverbs_event_handler(struct ib_event_handler *handler,
350 struct ib_event *event) 368 struct ib_event *event)
351{ 369{
diff --git a/drivers/infiniband/include/ib_user_verbs.h b/drivers/infiniband/include/ib_user_verbs.h
index 35857857aa3e..7ebb01c8f996 100644
--- a/drivers/infiniband/include/ib_user_verbs.h
+++ b/drivers/infiniband/include/ib_user_verbs.h
@@ -78,7 +78,12 @@ enum {
78 IB_USER_VERBS_CMD_POST_SEND, 78 IB_USER_VERBS_CMD_POST_SEND,
79 IB_USER_VERBS_CMD_POST_RECV, 79 IB_USER_VERBS_CMD_POST_RECV,
80 IB_USER_VERBS_CMD_ATTACH_MCAST, 80 IB_USER_VERBS_CMD_ATTACH_MCAST,
81 IB_USER_VERBS_CMD_DETACH_MCAST 81 IB_USER_VERBS_CMD_DETACH_MCAST,
82 IB_USER_VERBS_CMD_CREATE_SRQ,
83 IB_USER_VERBS_CMD_MODIFY_SRQ,
84 IB_USER_VERBS_CMD_QUERY_SRQ,
85 IB_USER_VERBS_CMD_DESTROY_SRQ,
86 IB_USER_VERBS_CMD_POST_SRQ_RECV
82}; 87};
83 88
84/* 89/*
@@ -386,4 +391,32 @@ struct ib_uverbs_detach_mcast {
386 __u64 driver_data[0]; 391 __u64 driver_data[0];
387}; 392};
388 393
394struct ib_uverbs_create_srq {
395 __u64 response;
396 __u64 user_handle;
397 __u32 pd_handle;
398 __u32 max_wr;
399 __u32 max_sge;
400 __u32 srq_limit;
401 __u64 driver_data[0];
402};
403
404struct ib_uverbs_create_srq_resp {
405 __u32 srq_handle;
406};
407
408struct ib_uverbs_modify_srq {
409 __u32 srq_handle;
410 __u32 attr_mask;
411 __u32 max_wr;
412 __u32 max_sge;
413 __u32 srq_limit;
414 __u32 reserved;
415 __u64 driver_data[0];
416};
417
418struct ib_uverbs_destroy_srq {
419 __u32 srq_handle;
420};
421
389#endif /* IB_USER_VERBS_H */ 422#endif /* IB_USER_VERBS_H */