diff options
-rw-r--r-- | drivers/infiniband/core/uverbs.h | 5 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 182 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 20 | ||||
-rw-r--r-- | drivers/infiniband/include/ib_user_verbs.h | 35 |
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; | |||
99 | extern struct idr ib_uverbs_ah_idr; | 99 | extern struct idr ib_uverbs_ah_idr; |
100 | extern struct idr ib_uverbs_cq_idr; | 100 | extern struct idr ib_uverbs_cq_idr; |
101 | extern struct idr ib_uverbs_qp_idr; | 101 | extern struct idr ib_uverbs_qp_idr; |
102 | extern struct idr ib_uverbs_srq_idr; | ||
102 | 103 | ||
103 | void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context); | 104 | void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context); |
104 | void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr); | 105 | void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr); |
105 | void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); | 106 | void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); |
107 | void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); | ||
106 | 108 | ||
107 | int ib_umem_get(struct ib_device *dev, struct ib_umem *mem, | 109 | int 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); | |||
131 | IB_UVERBS_DECLARE_CMD(destroy_qp); | 133 | IB_UVERBS_DECLARE_CMD(destroy_qp); |
132 | IB_UVERBS_DECLARE_CMD(attach_mcast); | 134 | IB_UVERBS_DECLARE_CMD(attach_mcast); |
133 | IB_UVERBS_DECLARE_CMD(detach_mcast); | 135 | IB_UVERBS_DECLARE_CMD(detach_mcast); |
136 | IB_UVERBS_DECLARE_CMD(create_srq); | ||
137 | IB_UVERBS_DECLARE_CMD(modify_srq); | ||
138 | IB_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 | |||
1011 | ssize_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 | |||
1072 | retry: | ||
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 | |||
1101 | err_list: | ||
1102 | spin_lock_irq(&file->ucontext->lock); | ||
1103 | list_del(&uobj->list); | ||
1104 | spin_unlock_irq(&file->ucontext->lock); | ||
1105 | |||
1106 | err_destroy: | ||
1107 | ib_destroy_srq(srq); | ||
1108 | |||
1109 | err_up: | ||
1110 | up(&ib_uverbs_idr_mutex); | ||
1111 | |||
1112 | kfree(uobj); | ||
1113 | return ret; | ||
1114 | } | ||
1115 | |||
1116 | ssize_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 | |||
1142 | out: | ||
1143 | up(&ib_uverbs_idr_mutex); | ||
1144 | |||
1145 | return ret ? ret : in_len; | ||
1146 | } | ||
1147 | |||
1148 | ssize_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 | |||
1180 | out: | ||
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); | |||
69 | DEFINE_IDR(ib_uverbs_ah_idr); | 69 | DEFINE_IDR(ib_uverbs_ah_idr); |
70 | DEFINE_IDR(ib_uverbs_cq_idr); | 70 | DEFINE_IDR(ib_uverbs_cq_idr); |
71 | DEFINE_IDR(ib_uverbs_qp_idr); | 71 | DEFINE_IDR(ib_uverbs_qp_idr); |
72 | DEFINE_IDR(ib_uverbs_srq_idr); | ||
72 | 73 | ||
73 | static spinlock_t map_lock; | 74 | static spinlock_t map_lock; |
74 | static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); | 75 | static 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 | ||
98 | static struct vfsmount *uverbs_event_mnt; | 102 | static 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 | ||
360 | void 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 | |||
349 | static void ib_uverbs_event_handler(struct ib_event_handler *handler, | 367 | static 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 | ||
394 | struct 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 | |||
404 | struct ib_uverbs_create_srq_resp { | ||
405 | __u32 srq_handle; | ||
406 | }; | ||
407 | |||
408 | struct 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 | |||
418 | struct ib_uverbs_destroy_srq { | ||
419 | __u32 srq_handle; | ||
420 | }; | ||
421 | |||
389 | #endif /* IB_USER_VERBS_H */ | 422 | #endif /* IB_USER_VERBS_H */ |