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 */ |
