aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/uverbs_cmd.c')
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c182
1 files changed, 180 insertions, 2 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 5f2bbcda4c7..ebccf9f38af 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}