aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorShani Michaeli <shanim@mellanox.com>2013-02-06 11:19:13 -0500
committerRoland Dreier <roland@purestorage.com>2013-02-21 14:59:09 -0500
commit6b52a12bc3fc39053b5bac4d4927ec8d974f8f60 (patch)
treeee722399af38f19b84773e87a519b1da3d2d6268 /drivers/infiniband
parent7083e42ee2ff43a11481e0e7211ec4f9ac68cb79 (diff)
IB/uverbs: Implement memory windows support in uverbs
The existing user/kernel uverbs API has IB_USER_VERBS_CMD_ALLOC/DEALLOC_MW. Implement these calls, along with destroying user memory windows during process cleanup. Signed-off-by: Haggai Eran <haggaie@mellanox.com> Signed-off-by: Shani Michaeli <shanim@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/uverbs.h2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c121
-rw-r--r--drivers/infiniband/core/uverbs_main.c13
3 files changed, 134 insertions, 2 deletions
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 5bcb2afd3dcb..0fcd7aa26fa2 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -188,6 +188,8 @@ IB_UVERBS_DECLARE_CMD(alloc_pd);
188IB_UVERBS_DECLARE_CMD(dealloc_pd); 188IB_UVERBS_DECLARE_CMD(dealloc_pd);
189IB_UVERBS_DECLARE_CMD(reg_mr); 189IB_UVERBS_DECLARE_CMD(reg_mr);
190IB_UVERBS_DECLARE_CMD(dereg_mr); 190IB_UVERBS_DECLARE_CMD(dereg_mr);
191IB_UVERBS_DECLARE_CMD(alloc_mw);
192IB_UVERBS_DECLARE_CMD(dealloc_mw);
191IB_UVERBS_DECLARE_CMD(create_comp_channel); 193IB_UVERBS_DECLARE_CMD(create_comp_channel);
192IB_UVERBS_DECLARE_CMD(create_cq); 194IB_UVERBS_DECLARE_CMD(create_cq);
193IB_UVERBS_DECLARE_CMD(resize_cq); 195IB_UVERBS_DECLARE_CMD(resize_cq);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 0cb0007724a2..3983a0552775 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -48,6 +48,7 @@ struct uverbs_lock_class {
48 48
49static struct uverbs_lock_class pd_lock_class = { .name = "PD-uobj" }; 49static struct uverbs_lock_class pd_lock_class = { .name = "PD-uobj" };
50static struct uverbs_lock_class mr_lock_class = { .name = "MR-uobj" }; 50static struct uverbs_lock_class mr_lock_class = { .name = "MR-uobj" };
51static struct uverbs_lock_class mw_lock_class = { .name = "MW-uobj" };
51static struct uverbs_lock_class cq_lock_class = { .name = "CQ-uobj" }; 52static struct uverbs_lock_class cq_lock_class = { .name = "CQ-uobj" };
52static struct uverbs_lock_class qp_lock_class = { .name = "QP-uobj" }; 53static struct uverbs_lock_class qp_lock_class = { .name = "QP-uobj" };
53static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" }; 54static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" };
@@ -1049,6 +1050,126 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
1049 return in_len; 1050 return in_len;
1050} 1051}
1051 1052
1053ssize_t ib_uverbs_alloc_mw(struct ib_uverbs_file *file,
1054 const char __user *buf, int in_len,
1055 int out_len)
1056{
1057 struct ib_uverbs_alloc_mw cmd;
1058 struct ib_uverbs_alloc_mw_resp resp;
1059 struct ib_uobject *uobj;
1060 struct ib_pd *pd;
1061 struct ib_mw *mw;
1062 int ret;
1063
1064 if (out_len < sizeof(resp))
1065 return -ENOSPC;
1066
1067 if (copy_from_user(&cmd, buf, sizeof(cmd)))
1068 return -EFAULT;
1069
1070 uobj = kmalloc(sizeof(*uobj), GFP_KERNEL);
1071 if (!uobj)
1072 return -ENOMEM;
1073
1074 init_uobj(uobj, 0, file->ucontext, &mw_lock_class);
1075 down_write(&uobj->mutex);
1076
1077 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1078 if (!pd) {
1079 ret = -EINVAL;
1080 goto err_free;
1081 }
1082
1083 mw = pd->device->alloc_mw(pd, cmd.mw_type);
1084 if (IS_ERR(mw)) {
1085 ret = PTR_ERR(mw);
1086 goto err_put;
1087 }
1088
1089 mw->device = pd->device;
1090 mw->pd = pd;
1091 mw->uobject = uobj;
1092 atomic_inc(&pd->usecnt);
1093
1094 uobj->object = mw;
1095 ret = idr_add_uobj(&ib_uverbs_mw_idr, uobj);
1096 if (ret)
1097 goto err_unalloc;
1098
1099 memset(&resp, 0, sizeof(resp));
1100 resp.rkey = mw->rkey;
1101 resp.mw_handle = uobj->id;
1102
1103 if (copy_to_user((void __user *)(unsigned long)cmd.response,
1104 &resp, sizeof(resp))) {
1105 ret = -EFAULT;
1106 goto err_copy;
1107 }
1108
1109 put_pd_read(pd);
1110
1111 mutex_lock(&file->mutex);
1112 list_add_tail(&uobj->list, &file->ucontext->mw_list);
1113 mutex_unlock(&file->mutex);
1114
1115 uobj->live = 1;
1116
1117 up_write(&uobj->mutex);
1118
1119 return in_len;
1120
1121err_copy:
1122 idr_remove_uobj(&ib_uverbs_mw_idr, uobj);
1123
1124err_unalloc:
1125 ib_dealloc_mw(mw);
1126
1127err_put:
1128 put_pd_read(pd);
1129
1130err_free:
1131 put_uobj_write(uobj);
1132 return ret;
1133}
1134
1135ssize_t ib_uverbs_dealloc_mw(struct ib_uverbs_file *file,
1136 const char __user *buf, int in_len,
1137 int out_len)
1138{
1139 struct ib_uverbs_dealloc_mw cmd;
1140 struct ib_mw *mw;
1141 struct ib_uobject *uobj;
1142 int ret = -EINVAL;
1143
1144 if (copy_from_user(&cmd, buf, sizeof(cmd)))
1145 return -EFAULT;
1146
1147 uobj = idr_write_uobj(&ib_uverbs_mw_idr, cmd.mw_handle, file->ucontext);
1148 if (!uobj)
1149 return -EINVAL;
1150
1151 mw = uobj->object;
1152
1153 ret = ib_dealloc_mw(mw);
1154 if (!ret)
1155 uobj->live = 0;
1156
1157 put_uobj_write(uobj);
1158
1159 if (ret)
1160 return ret;
1161
1162 idr_remove_uobj(&ib_uverbs_mw_idr, uobj);
1163
1164 mutex_lock(&file->mutex);
1165 list_del(&uobj->list);
1166 mutex_unlock(&file->mutex);
1167
1168 put_uobj(uobj);
1169
1170 return in_len;
1171}
1172
1052ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file, 1173ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
1053 const char __user *buf, int in_len, 1174 const char __user *buf, int in_len,
1054 int out_len) 1175 int out_len)
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 6f2ce6fa98f8..2c6f0f2ecd9d 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -87,6 +87,8 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
87 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd, 87 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,
88 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr, 88 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,
89 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr, 89 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,
90 [IB_USER_VERBS_CMD_ALLOC_MW] = ib_uverbs_alloc_mw,
91 [IB_USER_VERBS_CMD_DEALLOC_MW] = ib_uverbs_dealloc_mw,
90 [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel, 92 [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
91 [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq, 93 [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,
92 [IB_USER_VERBS_CMD_RESIZE_CQ] = ib_uverbs_resize_cq, 94 [IB_USER_VERBS_CMD_RESIZE_CQ] = ib_uverbs_resize_cq,
@@ -201,6 +203,15 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
201 kfree(uobj); 203 kfree(uobj);
202 } 204 }
203 205
206 /* Remove MWs before QPs, in order to support type 2A MWs. */
207 list_for_each_entry_safe(uobj, tmp, &context->mw_list, list) {
208 struct ib_mw *mw = uobj->object;
209
210 idr_remove_uobj(&ib_uverbs_mw_idr, uobj);
211 ib_dealloc_mw(mw);
212 kfree(uobj);
213 }
214
204 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) { 215 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
205 struct ib_qp *qp = uobj->object; 216 struct ib_qp *qp = uobj->object;
206 struct ib_uqp_object *uqp = 217 struct ib_uqp_object *uqp =
@@ -240,8 +251,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
240 kfree(uevent); 251 kfree(uevent);
241 } 252 }
242 253
243 /* XXX Free MWs */
244
245 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { 254 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
246 struct ib_mr *mr = uobj->object; 255 struct ib_mr *mr = uobj->object;
247 256