blob: b9fb256c25fad1227a8c3b6a176e1ac79dec7e85 [file] [log] [blame]
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001/*
2 * Copyright (c) 2005 Topspin Communications. All rights reserved.
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08003 * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved.
Roland Dreiereb9d3cd2005-09-27 15:07:25 -07004 * Copyright (c) 2005 PathScale, Inc. All rights reserved.
Dotan Barak8bdb0e82006-02-13 16:31:57 -08005 * Copyright (c) 2006 Mellanox Technologies. All rights reserved.
Roland Dreierbc38a6a2005-07-07 17:57:13 -07006 *
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
12 *
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
15 * conditions are met:
16 *
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer.
20 *
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * SOFTWARE.
Roland Dreierbc38a6a2005-07-07 17:57:13 -070034 */
35
Roland Dreier6b73597e2005-09-26 13:53:25 -070036#include <linux/file.h>
Roland Dreier70a30e12005-10-28 15:38:26 -070037#include <linux/fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090038#include <linux/slab.h>
Shachar Raindel8ada2c12014-12-11 17:04:17 +020039#include <linux/sched.h>
Roland Dreier6b73597e2005-09-26 13:53:25 -070040
Roland Dreierbc38a6a2005-07-07 17:57:13 -070041#include <asm/uaccess.h>
42
43#include "uverbs.h"
Or Gerlitzed4c54e2013-12-12 18:03:17 +020044#include "core_priv.h"
Roland Dreierbc38a6a2005-07-07 17:57:13 -070045
Roland Dreier3bea57a2012-04-30 10:27:26 -070046struct uverbs_lock_class {
47 struct lock_class_key key;
48 char name[16];
49};
50
51static struct uverbs_lock_class pd_lock_class = { .name = "PD-uobj" };
52static struct uverbs_lock_class mr_lock_class = { .name = "MR-uobj" };
Shani Michaeli6b52a122013-02-06 16:19:13 +000053static struct uverbs_lock_class mw_lock_class = { .name = "MW-uobj" };
Roland Dreier3bea57a2012-04-30 10:27:26 -070054static struct uverbs_lock_class cq_lock_class = { .name = "CQ-uobj" };
55static struct uverbs_lock_class qp_lock_class = { .name = "QP-uobj" };
56static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" };
57static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" };
58static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +030059static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
Yishai Hadasf213c052016-05-23 15:20:49 +030060static struct uverbs_lock_class wq_lock_class = { .name = "WQ-uobj" };
Yishai Hadasde019a92016-05-23 15:20:52 +030061static struct uverbs_lock_class rwq_ind_table_lock_class = { .name = "IND_TBL-uobj" };
Roland Dreierbc38a6a2005-07-07 17:57:13 -070062
Roland Dreier9ead1902006-06-17 20:44:49 -070063/*
64 * The ib_uobject locking scheme is as follows:
65 *
66 * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it
Mike Marciniszynd144da82015-11-02 12:13:25 -050067 * needs to be held during all idr write operations. When an object is
Roland Dreier9ead1902006-06-17 20:44:49 -070068 * looked up, a reference must be taken on the object's kref before
Mike Marciniszynd144da82015-11-02 12:13:25 -050069 * dropping this lock. For read operations, the rcu_read_lock()
70 * and rcu_write_lock() but similarly the kref reference is grabbed
71 * before the rcu_read_unlock().
Roland Dreier9ead1902006-06-17 20:44:49 -070072 *
73 * - Each object also has an rwsem. This rwsem must be held for
74 * reading while an operation that uses the object is performed.
75 * For example, while registering an MR, the associated PD's
76 * uobject.mutex must be held for reading. The rwsem must be held
77 * for writing while initializing or destroying an object.
78 *
79 * - In addition, each object has a "live" flag. If this flag is not
80 * set, then lookups of the object will fail even if it is found in
81 * the idr. This handles a reader that blocks and does not acquire
82 * the rwsem until after the object is destroyed. The destroy
83 * operation will set the live flag to 0 and then drop the rwsem;
84 * this will allow the reader to acquire the rwsem, see that the
85 * live flag is 0, and then drop the rwsem and its reference to
86 * object. The underlying storage will not be freed until the last
87 * reference to the object is dropped.
88 */
89
90static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
Roland Dreier3bea57a2012-04-30 10:27:26 -070091 struct ib_ucontext *context, struct uverbs_lock_class *c)
Roland Dreier9ead1902006-06-17 20:44:49 -070092{
93 uobj->user_handle = user_handle;
94 uobj->context = context;
95 kref_init(&uobj->ref);
96 init_rwsem(&uobj->mutex);
Roland Dreier3bea57a2012-04-30 10:27:26 -070097 lockdep_set_class_and_name(&uobj->mutex, &c->key, c->name);
Roland Dreier9ead1902006-06-17 20:44:49 -070098 uobj->live = 0;
99}
100
101static void release_uobj(struct kref *kref)
102{
Mike Marciniszynd144da82015-11-02 12:13:25 -0500103 kfree_rcu(container_of(kref, struct ib_uobject, ref), rcu);
Roland Dreier9ead1902006-06-17 20:44:49 -0700104}
105
106static void put_uobj(struct ib_uobject *uobj)
107{
108 kref_put(&uobj->ref, release_uobj);
109}
110
111static void put_uobj_read(struct ib_uobject *uobj)
112{
113 up_read(&uobj->mutex);
114 put_uobj(uobj);
115}
116
117static void put_uobj_write(struct ib_uobject *uobj)
118{
119 up_write(&uobj->mutex);
120 put_uobj(uobj);
121}
122
123static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj)
Roland Dreier34631752006-06-17 20:37:40 -0700124{
125 int ret;
126
Tejun Heo3b069c52013-02-27 17:04:16 -0800127 idr_preload(GFP_KERNEL);
Roland Dreier9ead1902006-06-17 20:44:49 -0700128 spin_lock(&ib_uverbs_idr_lock);
Tejun Heo3b069c52013-02-27 17:04:16 -0800129
130 ret = idr_alloc(idr, uobj, 0, 0, GFP_NOWAIT);
131 if (ret >= 0)
132 uobj->id = ret;
133
Roland Dreier9ead1902006-06-17 20:44:49 -0700134 spin_unlock(&ib_uverbs_idr_lock);
Tejun Heo3b069c52013-02-27 17:04:16 -0800135 idr_preload_end();
Roland Dreier34631752006-06-17 20:37:40 -0700136
Tejun Heo3b069c52013-02-27 17:04:16 -0800137 return ret < 0 ? ret : 0;
Roland Dreier34631752006-06-17 20:37:40 -0700138}
139
Roland Dreier9ead1902006-06-17 20:44:49 -0700140void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj)
141{
142 spin_lock(&ib_uverbs_idr_lock);
143 idr_remove(idr, uobj->id);
144 spin_unlock(&ib_uverbs_idr_lock);
145}
146
147static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
148 struct ib_ucontext *context)
149{
150 struct ib_uobject *uobj;
151
Mike Marciniszynd144da82015-11-02 12:13:25 -0500152 rcu_read_lock();
Roland Dreier9ead1902006-06-17 20:44:49 -0700153 uobj = idr_find(idr, id);
Roland Dreiercbfb50e2007-10-19 20:01:43 -0700154 if (uobj) {
155 if (uobj->context == context)
156 kref_get(&uobj->ref);
157 else
158 uobj = NULL;
159 }
Mike Marciniszynd144da82015-11-02 12:13:25 -0500160 rcu_read_unlock();
Roland Dreier9ead1902006-06-17 20:44:49 -0700161
162 return uobj;
163}
164
165static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700166 struct ib_ucontext *context, int nested)
Roland Dreier9ead1902006-06-17 20:44:49 -0700167{
168 struct ib_uobject *uobj;
169
170 uobj = __idr_get_uobj(idr, id, context);
171 if (!uobj)
172 return NULL;
173
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700174 if (nested)
175 down_read_nested(&uobj->mutex, SINGLE_DEPTH_NESTING);
176 else
177 down_read(&uobj->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -0700178 if (!uobj->live) {
179 put_uobj_read(uobj);
180 return NULL;
181 }
182
183 return uobj;
184}
185
186static struct ib_uobject *idr_write_uobj(struct idr *idr, int id,
187 struct ib_ucontext *context)
188{
189 struct ib_uobject *uobj;
190
191 uobj = __idr_get_uobj(idr, id, context);
192 if (!uobj)
193 return NULL;
194
195 down_write(&uobj->mutex);
196 if (!uobj->live) {
197 put_uobj_write(uobj);
198 return NULL;
199 }
200
201 return uobj;
202}
203
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700204static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context,
205 int nested)
Roland Dreier9ead1902006-06-17 20:44:49 -0700206{
207 struct ib_uobject *uobj;
208
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700209 uobj = idr_read_uobj(idr, id, context, nested);
Roland Dreier9ead1902006-06-17 20:44:49 -0700210 return uobj ? uobj->object : NULL;
211}
212
213static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context)
214{
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700215 return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context, 0);
Roland Dreier9ead1902006-06-17 20:44:49 -0700216}
217
218static void put_pd_read(struct ib_pd *pd)
219{
220 put_uobj_read(pd->uobject);
221}
222
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700223static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context, int nested)
Roland Dreier9ead1902006-06-17 20:44:49 -0700224{
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700225 return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context, nested);
Roland Dreier9ead1902006-06-17 20:44:49 -0700226}
227
228static void put_cq_read(struct ib_cq *cq)
229{
230 put_uobj_read(cq->uobject);
231}
232
233static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context)
234{
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700235 return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context, 0);
Roland Dreier9ead1902006-06-17 20:44:49 -0700236}
237
238static void put_ah_read(struct ib_ah *ah)
239{
240 put_uobj_read(ah->uobject);
241}
242
243static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
244{
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700245 return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0);
Roland Dreier9ead1902006-06-17 20:44:49 -0700246}
247
Yishai Hadasf213c052016-05-23 15:20:49 +0300248static struct ib_wq *idr_read_wq(int wq_handle, struct ib_ucontext *context)
249{
250 return idr_read_obj(&ib_uverbs_wq_idr, wq_handle, context, 0);
251}
252
253static void put_wq_read(struct ib_wq *wq)
254{
255 put_uobj_read(wq->uobject);
256}
257
Yishai Hadasc70285f2016-05-23 15:20:55 +0300258static struct ib_rwq_ind_table *idr_read_rwq_indirection_table(int ind_table_handle,
259 struct ib_ucontext *context)
260{
261 return idr_read_obj(&ib_uverbs_rwq_ind_tbl_idr, ind_table_handle, context, 0);
262}
263
264static void put_rwq_indirection_table_read(struct ib_rwq_ind_table *ind_table)
265{
266 put_uobj_read(ind_table->uobject);
267}
268
Eli Cohene214a0f2012-01-03 20:36:48 -0800269static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context)
270{
271 struct ib_uobject *uobj;
272
273 uobj = idr_write_uobj(&ib_uverbs_qp_idr, qp_handle, context);
274 return uobj ? uobj->object : NULL;
275}
276
Roland Dreier9ead1902006-06-17 20:44:49 -0700277static void put_qp_read(struct ib_qp *qp)
278{
279 put_uobj_read(qp->uobject);
280}
281
Eli Cohene214a0f2012-01-03 20:36:48 -0800282static void put_qp_write(struct ib_qp *qp)
283{
284 put_uobj_write(qp->uobject);
285}
286
Roland Dreier9ead1902006-06-17 20:44:49 -0700287static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
288{
Roland Dreier1ccf6aa2006-09-22 15:17:20 -0700289 return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0);
Roland Dreier9ead1902006-06-17 20:44:49 -0700290}
291
292static void put_srq_read(struct ib_srq *srq)
293{
294 put_uobj_read(srq->uobject);
295}
296
Sean Hefty53d0bd12011-05-24 08:33:46 -0700297static struct ib_xrcd *idr_read_xrcd(int xrcd_handle, struct ib_ucontext *context,
298 struct ib_uobject **uobj)
299{
300 *uobj = idr_read_uobj(&ib_uverbs_xrcd_idr, xrcd_handle, context, 0);
301 return *uobj ? (*uobj)->object : NULL;
302}
303
304static void put_xrcd_read(struct ib_uobject *uobj)
305{
306 put_uobj_read(uobj);
307}
308
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700309ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300310 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700311 const char __user *buf,
312 int in_len, int out_len)
313{
314 struct ib_uverbs_get_context cmd;
315 struct ib_uverbs_get_context_resp resp;
316 struct ib_udata udata;
Roland Dreier63c47c22005-09-26 13:01:03 -0700317 struct ib_ucontext *ucontext;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700318 struct file *filp;
Roland Dreier63c47c22005-09-26 13:01:03 -0700319 int ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700320
321 if (out_len < sizeof resp)
322 return -ENOSPC;
323
324 if (copy_from_user(&cmd, buf, sizeof cmd))
325 return -EFAULT;
326
Ingo Molnar95ed6442006-01-13 14:51:39 -0800327 mutex_lock(&file->mutex);
Roland Dreier63c47c22005-09-26 13:01:03 -0700328
329 if (file->ucontext) {
330 ret = -EINVAL;
331 goto err;
332 }
333
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700334 INIT_UDATA(&udata, buf + sizeof cmd,
335 (unsigned long) cmd.response + sizeof resp,
336 in_len - sizeof cmd, out_len - sizeof resp);
337
Yishai Hadas057aec02015-08-13 18:32:04 +0300338 ucontext = ib_dev->alloc_ucontext(ib_dev, &udata);
Ganapathi CH77f76012006-06-17 20:37:40 -0700339 if (IS_ERR(ucontext)) {
Roel Kluindf422452009-12-09 14:30:44 -0800340 ret = PTR_ERR(ucontext);
Ganapathi CH77f76012006-06-17 20:37:40 -0700341 goto err;
342 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700343
Yishai Hadas057aec02015-08-13 18:32:04 +0300344 ucontext->device = ib_dev;
Roland Dreier63c47c22005-09-26 13:01:03 -0700345 INIT_LIST_HEAD(&ucontext->pd_list);
346 INIT_LIST_HEAD(&ucontext->mr_list);
347 INIT_LIST_HEAD(&ucontext->mw_list);
348 INIT_LIST_HEAD(&ucontext->cq_list);
349 INIT_LIST_HEAD(&ucontext->qp_list);
350 INIT_LIST_HEAD(&ucontext->srq_list);
351 INIT_LIST_HEAD(&ucontext->ah_list);
Yishai Hadasf213c052016-05-23 15:20:49 +0300352 INIT_LIST_HEAD(&ucontext->wq_list);
Yishai Hadasde019a92016-05-23 15:20:52 +0300353 INIT_LIST_HEAD(&ucontext->rwq_ind_tbl_list);
Sean Hefty53d0bd12011-05-24 08:33:46 -0700354 INIT_LIST_HEAD(&ucontext->xrcd_list);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +0300355 INIT_LIST_HEAD(&ucontext->rule_list);
Shachar Raindel8ada2c12014-12-11 17:04:17 +0200356 rcu_read_lock();
357 ucontext->tgid = get_task_pid(current->group_leader, PIDTYPE_PID);
358 rcu_read_unlock();
Roland Dreierf7c6a7b2007-03-04 16:15:11 -0800359 ucontext->closing = 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700360
Haggai Eran882214e2014-12-11 17:04:18 +0200361#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
362 ucontext->umem_tree = RB_ROOT;
363 init_rwsem(&ucontext->umem_rwsem);
364 ucontext->odp_mrs_count = 0;
365 INIT_LIST_HEAD(&ucontext->no_private_counters);
366
Or Gerlitz86bee4c2015-12-18 10:59:45 +0200367 if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_ON_DEMAND_PAGING))
Haggai Eran882214e2014-12-11 17:04:18 +0200368 ucontext->invalidate_range = NULL;
369
370#endif
371
Roland Dreier6b73597e2005-09-26 13:53:25 -0700372 resp.num_comp_vectors = file->device->num_comp_vectors;
373
Roland Dreierda183c72013-07-08 11:15:45 -0700374 ret = get_unused_fd_flags(O_CLOEXEC);
Al Virob1e45942010-01-18 01:38:00 -0500375 if (ret < 0)
376 goto err_free;
377 resp.async_fd = ret;
378
Yishai Hadas057aec02015-08-13 18:32:04 +0300379 filp = ib_uverbs_alloc_event_file(file, ib_dev, 1);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700380 if (IS_ERR(filp)) {
381 ret = PTR_ERR(filp);
Al Virob1e45942010-01-18 01:38:00 -0500382 goto err_fd;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700383 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700384
385 if (copy_to_user((void __user *) (unsigned long) cmd.response,
Roland Dreier63c47c22005-09-26 13:01:03 -0700386 &resp, sizeof resp)) {
387 ret = -EFAULT;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700388 goto err_file;
Roland Dreier63c47c22005-09-26 13:01:03 -0700389 }
390
Roland Dreier70a30e12005-10-28 15:38:26 -0700391 file->ucontext = ucontext;
Roland Dreier6b73597e2005-09-26 13:53:25 -0700392
393 fd_install(resp.async_fd, filp);
394
Ingo Molnar95ed6442006-01-13 14:51:39 -0800395 mutex_unlock(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700396
397 return in_len;
398
Roland Dreier6b73597e2005-09-26 13:53:25 -0700399err_file:
Yishai Hadas03c40442015-08-13 18:32:02 +0300400 ib_uverbs_free_async_event_file(file);
Roland Dreier6b73597e2005-09-26 13:53:25 -0700401 fput(filp);
402
Al Virob1e45942010-01-18 01:38:00 -0500403err_fd:
404 put_unused_fd(resp.async_fd);
405
Roland Dreier63c47c22005-09-26 13:01:03 -0700406err_free:
Shachar Raindel8ada2c12014-12-11 17:04:17 +0200407 put_pid(ucontext->tgid);
Yishai Hadas057aec02015-08-13 18:32:04 +0300408 ib_dev->dealloc_ucontext(ucontext);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700409
Roland Dreier63c47c22005-09-26 13:01:03 -0700410err:
Ingo Molnar95ed6442006-01-13 14:51:39 -0800411 mutex_unlock(&file->mutex);
Roland Dreier63c47c22005-09-26 13:01:03 -0700412 return ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700413}
414
Eli Cohen02d1aa72015-02-08 13:28:50 +0200415static void copy_query_dev_fields(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300416 struct ib_device *ib_dev,
Eli Cohen02d1aa72015-02-08 13:28:50 +0200417 struct ib_uverbs_query_device_resp *resp,
418 struct ib_device_attr *attr)
419{
420 resp->fw_ver = attr->fw_ver;
Yishai Hadas057aec02015-08-13 18:32:04 +0300421 resp->node_guid = ib_dev->node_guid;
Eli Cohen02d1aa72015-02-08 13:28:50 +0200422 resp->sys_image_guid = attr->sys_image_guid;
423 resp->max_mr_size = attr->max_mr_size;
424 resp->page_size_cap = attr->page_size_cap;
425 resp->vendor_id = attr->vendor_id;
426 resp->vendor_part_id = attr->vendor_part_id;
427 resp->hw_ver = attr->hw_ver;
428 resp->max_qp = attr->max_qp;
429 resp->max_qp_wr = attr->max_qp_wr;
Leon Romanovskyfb532d62016-02-23 10:25:25 +0200430 resp->device_cap_flags = lower_32_bits(attr->device_cap_flags);
Eli Cohen02d1aa72015-02-08 13:28:50 +0200431 resp->max_sge = attr->max_sge;
432 resp->max_sge_rd = attr->max_sge_rd;
433 resp->max_cq = attr->max_cq;
434 resp->max_cqe = attr->max_cqe;
435 resp->max_mr = attr->max_mr;
436 resp->max_pd = attr->max_pd;
437 resp->max_qp_rd_atom = attr->max_qp_rd_atom;
438 resp->max_ee_rd_atom = attr->max_ee_rd_atom;
439 resp->max_res_rd_atom = attr->max_res_rd_atom;
440 resp->max_qp_init_rd_atom = attr->max_qp_init_rd_atom;
441 resp->max_ee_init_rd_atom = attr->max_ee_init_rd_atom;
442 resp->atomic_cap = attr->atomic_cap;
443 resp->max_ee = attr->max_ee;
444 resp->max_rdd = attr->max_rdd;
445 resp->max_mw = attr->max_mw;
446 resp->max_raw_ipv6_qp = attr->max_raw_ipv6_qp;
447 resp->max_raw_ethy_qp = attr->max_raw_ethy_qp;
448 resp->max_mcast_grp = attr->max_mcast_grp;
449 resp->max_mcast_qp_attach = attr->max_mcast_qp_attach;
450 resp->max_total_mcast_qp_attach = attr->max_total_mcast_qp_attach;
451 resp->max_ah = attr->max_ah;
452 resp->max_fmr = attr->max_fmr;
453 resp->max_map_per_fmr = attr->max_map_per_fmr;
454 resp->max_srq = attr->max_srq;
455 resp->max_srq_wr = attr->max_srq_wr;
456 resp->max_srq_sge = attr->max_srq_sge;
457 resp->max_pkeys = attr->max_pkeys;
458 resp->local_ca_ack_delay = attr->local_ca_ack_delay;
Yishai Hadas057aec02015-08-13 18:32:04 +0300459 resp->phys_port_cnt = ib_dev->phys_port_cnt;
Eli Cohen02d1aa72015-02-08 13:28:50 +0200460}
461
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700462ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300463 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700464 const char __user *buf,
465 int in_len, int out_len)
466{
467 struct ib_uverbs_query_device cmd;
468 struct ib_uverbs_query_device_resp resp;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700469
470 if (out_len < sizeof resp)
471 return -ENOSPC;
472
473 if (copy_from_user(&cmd, buf, sizeof cmd))
474 return -EFAULT;
475
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700476 memset(&resp, 0, sizeof resp);
Or Gerlitz86bee4c2015-12-18 10:59:45 +0200477 copy_query_dev_fields(file, ib_dev, &resp, &ib_dev->attrs);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700478
479 if (copy_to_user((void __user *) (unsigned long) cmd.response,
480 &resp, sizeof resp))
481 return -EFAULT;
482
483 return in_len;
484}
485
486ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300487 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700488 const char __user *buf,
489 int in_len, int out_len)
490{
491 struct ib_uverbs_query_port cmd;
492 struct ib_uverbs_query_port_resp resp;
493 struct ib_port_attr attr;
494 int ret;
495
496 if (out_len < sizeof resp)
497 return -ENOSPC;
498
499 if (copy_from_user(&cmd, buf, sizeof cmd))
500 return -EFAULT;
501
Yishai Hadas057aec02015-08-13 18:32:04 +0300502 ret = ib_query_port(ib_dev, cmd.port_num, &attr);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700503 if (ret)
504 return ret;
505
506 memset(&resp, 0, sizeof resp);
507
508 resp.state = attr.state;
509 resp.max_mtu = attr.max_mtu;
510 resp.active_mtu = attr.active_mtu;
511 resp.gid_tbl_len = attr.gid_tbl_len;
512 resp.port_cap_flags = attr.port_cap_flags;
513 resp.max_msg_sz = attr.max_msg_sz;
514 resp.bad_pkey_cntr = attr.bad_pkey_cntr;
515 resp.qkey_viol_cntr = attr.qkey_viol_cntr;
516 resp.pkey_tbl_len = attr.pkey_tbl_len;
517 resp.lid = attr.lid;
518 resp.sm_lid = attr.sm_lid;
519 resp.lmc = attr.lmc;
520 resp.max_vl_num = attr.max_vl_num;
521 resp.sm_sl = attr.sm_sl;
522 resp.subnet_timeout = attr.subnet_timeout;
523 resp.init_type_reply = attr.init_type_reply;
524 resp.active_width = attr.active_width;
525 resp.active_speed = attr.active_speed;
526 resp.phys_state = attr.phys_state;
Yishai Hadas057aec02015-08-13 18:32:04 +0300527 resp.link_layer = rdma_port_get_link_layer(ib_dev,
Eli Cohen2420b602010-10-18 14:45:20 -0700528 cmd.port_num);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700529
530 if (copy_to_user((void __user *) (unsigned long) cmd.response,
531 &resp, sizeof resp))
532 return -EFAULT;
533
534 return in_len;
535}
536
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700537ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300538 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700539 const char __user *buf,
540 int in_len, int out_len)
541{
542 struct ib_uverbs_alloc_pd cmd;
543 struct ib_uverbs_alloc_pd_resp resp;
544 struct ib_udata udata;
545 struct ib_uobject *uobj;
546 struct ib_pd *pd;
547 int ret;
548
549 if (out_len < sizeof resp)
550 return -ENOSPC;
551
552 if (copy_from_user(&cmd, buf, sizeof cmd))
553 return -EFAULT;
554
555 INIT_UDATA(&udata, buf + sizeof cmd,
556 (unsigned long) cmd.response + sizeof resp,
557 in_len - sizeof cmd, out_len - sizeof resp);
558
559 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
560 if (!uobj)
561 return -ENOMEM;
562
Roland Dreier3bea57a2012-04-30 10:27:26 -0700563 init_uobj(uobj, 0, file->ucontext, &pd_lock_class);
Roland Dreier9ead1902006-06-17 20:44:49 -0700564 down_write(&uobj->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700565
Yishai Hadas057aec02015-08-13 18:32:04 +0300566 pd = ib_dev->alloc_pd(ib_dev, file->ucontext, &udata);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700567 if (IS_ERR(pd)) {
568 ret = PTR_ERR(pd);
569 goto err;
570 }
571
Yishai Hadas057aec02015-08-13 18:32:04 +0300572 pd->device = ib_dev;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700573 pd->uobject = uobj;
Christoph Hellwig50d46332016-09-05 12:56:16 +0200574 pd->__internal_mr = NULL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700575 atomic_set(&pd->usecnt, 0);
576
Roland Dreier9ead1902006-06-17 20:44:49 -0700577 uobj->object = pd;
578 ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700579 if (ret)
Roland Dreier9ead1902006-06-17 20:44:49 -0700580 goto err_idr;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700581
582 memset(&resp, 0, sizeof resp);
583 resp.pd_handle = uobj->id;
584
585 if (copy_to_user((void __user *) (unsigned long) cmd.response,
586 &resp, sizeof resp)) {
587 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -0700588 goto err_copy;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700589 }
590
Ingo Molnar95ed6442006-01-13 14:51:39 -0800591 mutex_lock(&file->mutex);
Roland Dreiereb9d3cd2005-09-27 15:07:25 -0700592 list_add_tail(&uobj->list, &file->ucontext->pd_list);
Ingo Molnar95ed6442006-01-13 14:51:39 -0800593 mutex_unlock(&file->mutex);
Roland Dreiereb9d3cd2005-09-27 15:07:25 -0700594
Roland Dreier9ead1902006-06-17 20:44:49 -0700595 uobj->live = 1;
596
597 up_write(&uobj->mutex);
Roland Dreiereb9d3cd2005-09-27 15:07:25 -0700598
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700599 return in_len;
600
Roland Dreier9ead1902006-06-17 20:44:49 -0700601err_copy:
602 idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700603
Roland Dreier9ead1902006-06-17 20:44:49 -0700604err_idr:
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700605 ib_dealloc_pd(pd);
606
607err:
Roland Dreier9ead1902006-06-17 20:44:49 -0700608 put_uobj_write(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700609 return ret;
610}
611
612ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300613 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700614 const char __user *buf,
615 int in_len, int out_len)
616{
617 struct ib_uverbs_dealloc_pd cmd;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700618 struct ib_uobject *uobj;
Jason Gunthorpe7dd78642015-08-05 14:34:31 -0600619 struct ib_pd *pd;
Roland Dreier9ead1902006-06-17 20:44:49 -0700620 int ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700621
622 if (copy_from_user(&cmd, buf, sizeof cmd))
623 return -EFAULT;
624
Roland Dreier9ead1902006-06-17 20:44:49 -0700625 uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext);
626 if (!uobj)
627 return -EINVAL;
Jason Gunthorpe7dd78642015-08-05 14:34:31 -0600628 pd = uobj->object;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700629
Jason Gunthorpe7dd78642015-08-05 14:34:31 -0600630 if (atomic_read(&pd->usecnt)) {
631 ret = -EBUSY;
632 goto err_put;
633 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700634
Jason Gunthorpe7dd78642015-08-05 14:34:31 -0600635 ret = pd->device->dealloc_pd(uobj->object);
636 WARN_ONCE(ret, "Infiniband HW driver failed dealloc_pd");
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700637 if (ret)
Jason Gunthorpe7dd78642015-08-05 14:34:31 -0600638 goto err_put;
639
640 uobj->live = 0;
641 put_uobj_write(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700642
Roland Dreier9ead1902006-06-17 20:44:49 -0700643 idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700644
Ingo Molnar95ed6442006-01-13 14:51:39 -0800645 mutex_lock(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700646 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -0800647 mutex_unlock(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700648
Roland Dreier9ead1902006-06-17 20:44:49 -0700649 put_uobj(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700650
Roland Dreier9ead1902006-06-17 20:44:49 -0700651 return in_len;
Jason Gunthorpe7dd78642015-08-05 14:34:31 -0600652
653err_put:
654 put_uobj_write(uobj);
655 return ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700656}
657
Sean Hefty53d0bd12011-05-24 08:33:46 -0700658struct xrcd_table_entry {
659 struct rb_node node;
660 struct ib_xrcd *xrcd;
661 struct inode *inode;
662};
663
664static int xrcd_table_insert(struct ib_uverbs_device *dev,
665 struct inode *inode,
666 struct ib_xrcd *xrcd)
667{
668 struct xrcd_table_entry *entry, *scan;
669 struct rb_node **p = &dev->xrcd_tree.rb_node;
670 struct rb_node *parent = NULL;
671
672 entry = kmalloc(sizeof *entry, GFP_KERNEL);
673 if (!entry)
674 return -ENOMEM;
675
676 entry->xrcd = xrcd;
677 entry->inode = inode;
678
679 while (*p) {
680 parent = *p;
681 scan = rb_entry(parent, struct xrcd_table_entry, node);
682
683 if (inode < scan->inode) {
684 p = &(*p)->rb_left;
685 } else if (inode > scan->inode) {
686 p = &(*p)->rb_right;
687 } else {
688 kfree(entry);
689 return -EEXIST;
690 }
691 }
692
693 rb_link_node(&entry->node, parent, p);
694 rb_insert_color(&entry->node, &dev->xrcd_tree);
695 igrab(inode);
696 return 0;
697}
698
699static struct xrcd_table_entry *xrcd_table_search(struct ib_uverbs_device *dev,
700 struct inode *inode)
701{
702 struct xrcd_table_entry *entry;
703 struct rb_node *p = dev->xrcd_tree.rb_node;
704
705 while (p) {
706 entry = rb_entry(p, struct xrcd_table_entry, node);
707
708 if (inode < entry->inode)
709 p = p->rb_left;
710 else if (inode > entry->inode)
711 p = p->rb_right;
712 else
713 return entry;
714 }
715
716 return NULL;
717}
718
719static struct ib_xrcd *find_xrcd(struct ib_uverbs_device *dev, struct inode *inode)
720{
721 struct xrcd_table_entry *entry;
722
723 entry = xrcd_table_search(dev, inode);
724 if (!entry)
725 return NULL;
726
727 return entry->xrcd;
728}
729
730static void xrcd_table_delete(struct ib_uverbs_device *dev,
731 struct inode *inode)
732{
733 struct xrcd_table_entry *entry;
734
735 entry = xrcd_table_search(dev, inode);
736 if (entry) {
737 iput(inode);
738 rb_erase(&entry->node, &dev->xrcd_tree);
739 kfree(entry);
740 }
741}
742
743ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300744 struct ib_device *ib_dev,
Sean Hefty53d0bd12011-05-24 08:33:46 -0700745 const char __user *buf, int in_len,
746 int out_len)
747{
748 struct ib_uverbs_open_xrcd cmd;
749 struct ib_uverbs_open_xrcd_resp resp;
750 struct ib_udata udata;
751 struct ib_uxrcd_object *obj;
752 struct ib_xrcd *xrcd = NULL;
Al Viro2903ff02012-08-28 12:52:22 -0400753 struct fd f = {NULL, 0};
Sean Hefty53d0bd12011-05-24 08:33:46 -0700754 struct inode *inode = NULL;
Al Viro2903ff02012-08-28 12:52:22 -0400755 int ret = 0;
Sean Hefty53d0bd12011-05-24 08:33:46 -0700756 int new_xrcd = 0;
757
758 if (out_len < sizeof resp)
759 return -ENOSPC;
760
761 if (copy_from_user(&cmd, buf, sizeof cmd))
762 return -EFAULT;
763
764 INIT_UDATA(&udata, buf + sizeof cmd,
765 (unsigned long) cmd.response + sizeof resp,
766 in_len - sizeof cmd, out_len - sizeof resp);
767
768 mutex_lock(&file->device->xrcd_tree_mutex);
769
770 if (cmd.fd != -1) {
771 /* search for file descriptor */
Al Viro2903ff02012-08-28 12:52:22 -0400772 f = fdget(cmd.fd);
773 if (!f.file) {
Sean Hefty53d0bd12011-05-24 08:33:46 -0700774 ret = -EBADF;
775 goto err_tree_mutex_unlock;
776 }
777
Al Viro496ad9a2013-01-23 17:07:38 -0500778 inode = file_inode(f.file);
Sean Hefty53d0bd12011-05-24 08:33:46 -0700779 xrcd = find_xrcd(file->device, inode);
780 if (!xrcd && !(cmd.oflags & O_CREAT)) {
781 /* no file descriptor. Need CREATE flag */
782 ret = -EAGAIN;
783 goto err_tree_mutex_unlock;
784 }
785
786 if (xrcd && cmd.oflags & O_EXCL) {
787 ret = -EINVAL;
788 goto err_tree_mutex_unlock;
789 }
790 }
791
792 obj = kmalloc(sizeof *obj, GFP_KERNEL);
793 if (!obj) {
794 ret = -ENOMEM;
795 goto err_tree_mutex_unlock;
796 }
797
Roland Dreier3bea57a2012-04-30 10:27:26 -0700798 init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_class);
Sean Hefty53d0bd12011-05-24 08:33:46 -0700799
800 down_write(&obj->uobject.mutex);
801
802 if (!xrcd) {
Yishai Hadas057aec02015-08-13 18:32:04 +0300803 xrcd = ib_dev->alloc_xrcd(ib_dev, file->ucontext, &udata);
Sean Hefty53d0bd12011-05-24 08:33:46 -0700804 if (IS_ERR(xrcd)) {
805 ret = PTR_ERR(xrcd);
806 goto err;
807 }
808
809 xrcd->inode = inode;
Yishai Hadas057aec02015-08-13 18:32:04 +0300810 xrcd->device = ib_dev;
Sean Hefty53d0bd12011-05-24 08:33:46 -0700811 atomic_set(&xrcd->usecnt, 0);
812 mutex_init(&xrcd->tgt_qp_mutex);
813 INIT_LIST_HEAD(&xrcd->tgt_qp_list);
814 new_xrcd = 1;
815 }
816
817 atomic_set(&obj->refcnt, 0);
818 obj->uobject.object = xrcd;
819 ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
820 if (ret)
821 goto err_idr;
822
823 memset(&resp, 0, sizeof resp);
824 resp.xrcd_handle = obj->uobject.id;
825
826 if (inode) {
827 if (new_xrcd) {
828 /* create new inode/xrcd table entry */
829 ret = xrcd_table_insert(file->device, inode, xrcd);
830 if (ret)
831 goto err_insert_xrcd;
832 }
833 atomic_inc(&xrcd->usecnt);
834 }
835
836 if (copy_to_user((void __user *) (unsigned long) cmd.response,
837 &resp, sizeof resp)) {
838 ret = -EFAULT;
839 goto err_copy;
840 }
841
Al Viro2903ff02012-08-28 12:52:22 -0400842 if (f.file)
843 fdput(f);
Sean Hefty53d0bd12011-05-24 08:33:46 -0700844
845 mutex_lock(&file->mutex);
846 list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list);
847 mutex_unlock(&file->mutex);
848
849 obj->uobject.live = 1;
850 up_write(&obj->uobject.mutex);
851
852 mutex_unlock(&file->device->xrcd_tree_mutex);
853 return in_len;
854
855err_copy:
856 if (inode) {
857 if (new_xrcd)
858 xrcd_table_delete(file->device, inode);
859 atomic_dec(&xrcd->usecnt);
860 }
861
862err_insert_xrcd:
863 idr_remove_uobj(&ib_uverbs_xrcd_idr, &obj->uobject);
864
865err_idr:
866 ib_dealloc_xrcd(xrcd);
867
868err:
869 put_uobj_write(&obj->uobject);
870
871err_tree_mutex_unlock:
Al Viro2903ff02012-08-28 12:52:22 -0400872 if (f.file)
873 fdput(f);
Sean Hefty53d0bd12011-05-24 08:33:46 -0700874
875 mutex_unlock(&file->device->xrcd_tree_mutex);
876
877 return ret;
878}
879
880ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300881 struct ib_device *ib_dev,
Sean Hefty53d0bd12011-05-24 08:33:46 -0700882 const char __user *buf, int in_len,
883 int out_len)
884{
885 struct ib_uverbs_close_xrcd cmd;
886 struct ib_uobject *uobj;
887 struct ib_xrcd *xrcd = NULL;
888 struct inode *inode = NULL;
889 struct ib_uxrcd_object *obj;
890 int live;
891 int ret = 0;
892
893 if (copy_from_user(&cmd, buf, sizeof cmd))
894 return -EFAULT;
895
896 mutex_lock(&file->device->xrcd_tree_mutex);
897 uobj = idr_write_uobj(&ib_uverbs_xrcd_idr, cmd.xrcd_handle, file->ucontext);
898 if (!uobj) {
899 ret = -EINVAL;
900 goto out;
901 }
902
903 xrcd = uobj->object;
904 inode = xrcd->inode;
905 obj = container_of(uobj, struct ib_uxrcd_object, uobject);
906 if (atomic_read(&obj->refcnt)) {
907 put_uobj_write(uobj);
908 ret = -EBUSY;
909 goto out;
910 }
911
912 if (!inode || atomic_dec_and_test(&xrcd->usecnt)) {
913 ret = ib_dealloc_xrcd(uobj->object);
914 if (!ret)
915 uobj->live = 0;
916 }
917
918 live = uobj->live;
919 if (inode && ret)
920 atomic_inc(&xrcd->usecnt);
921
922 put_uobj_write(uobj);
923
924 if (ret)
925 goto out;
926
927 if (inode && !live)
928 xrcd_table_delete(file->device, inode);
929
930 idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
931 mutex_lock(&file->mutex);
932 list_del(&uobj->list);
933 mutex_unlock(&file->mutex);
934
935 put_uobj(uobj);
936 ret = in_len;
937
938out:
939 mutex_unlock(&file->device->xrcd_tree_mutex);
940 return ret;
941}
942
943void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev,
944 struct ib_xrcd *xrcd)
945{
946 struct inode *inode;
947
948 inode = xrcd->inode;
949 if (inode && !atomic_dec_and_test(&xrcd->usecnt))
950 return;
951
952 ib_dealloc_xrcd(xrcd);
953
954 if (inode)
955 xrcd_table_delete(dev, inode);
956}
957
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700958ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +0300959 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700960 const char __user *buf, int in_len,
961 int out_len)
962{
963 struct ib_uverbs_reg_mr cmd;
964 struct ib_uverbs_reg_mr_resp resp;
965 struct ib_udata udata;
Roland Dreierf7c6a7b2007-03-04 16:15:11 -0800966 struct ib_uobject *uobj;
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700967 struct ib_pd *pd;
968 struct ib_mr *mr;
969 int ret;
970
971 if (out_len < sizeof resp)
972 return -ENOSPC;
973
974 if (copy_from_user(&cmd, buf, sizeof cmd))
975 return -EFAULT;
976
977 INIT_UDATA(&udata, buf + sizeof cmd,
978 (unsigned long) cmd.response + sizeof resp,
979 in_len - sizeof cmd, out_len - sizeof resp);
980
981 if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
982 return -EINVAL;
983
Eli Cohen1c636f82013-10-31 15:26:32 +0200984 ret = ib_check_mr_access(cmd.access_flags);
985 if (ret)
986 return ret;
Roland Dreierf5753942005-10-03 09:18:02 -0700987
Roland Dreierf7c6a7b2007-03-04 16:15:11 -0800988 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
989 if (!uobj)
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700990 return -ENOMEM;
991
Roland Dreier3bea57a2012-04-30 10:27:26 -0700992 init_uobj(uobj, 0, file->ucontext, &mr_lock_class);
Roland Dreierf7c6a7b2007-03-04 16:15:11 -0800993 down_write(&uobj->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -0700994
Roland Dreier9ead1902006-06-17 20:44:49 -0700995 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
Roland Dreieraaf1aef2007-02-22 13:16:51 -0800996 if (!pd) {
997 ret = -EINVAL;
Roland Dreierf7c6a7b2007-03-04 16:15:11 -0800998 goto err_free;
Roland Dreieraaf1aef2007-02-22 13:16:51 -0800999 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001000
Sagi Grimberg860f10a2014-12-11 17:04:16 +02001001 if (cmd.access_flags & IB_ACCESS_ON_DEMAND) {
Or Gerlitz86bee4c2015-12-18 10:59:45 +02001002 if (!(pd->device->attrs.device_cap_flags &
1003 IB_DEVICE_ON_DEMAND_PAGING)) {
Sagi Grimberg860f10a2014-12-11 17:04:16 +02001004 pr_debug("ODP support not available\n");
1005 ret = -EINVAL;
1006 goto err_put;
1007 }
1008 }
1009
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001010 mr = pd->device->reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va,
1011 cmd.access_flags, &udata);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001012 if (IS_ERR(mr)) {
1013 ret = PTR_ERR(mr);
Roland Dreier9ead1902006-06-17 20:44:49 -07001014 goto err_put;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001015 }
1016
1017 mr->device = pd->device;
1018 mr->pd = pd;
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001019 mr->uobject = uobj;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001020 atomic_inc(&pd->usecnt);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001021
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001022 uobj->object = mr;
1023 ret = idr_add_uobj(&ib_uverbs_mr_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001024 if (ret)
1025 goto err_unreg;
1026
Roland Dreier9ead1902006-06-17 20:44:49 -07001027 memset(&resp, 0, sizeof resp);
1028 resp.lkey = mr->lkey;
1029 resp.rkey = mr->rkey;
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001030 resp.mr_handle = uobj->id;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001031
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001032 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1033 &resp, sizeof resp)) {
1034 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -07001035 goto err_copy;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001036 }
1037
Roland Dreier9ead1902006-06-17 20:44:49 -07001038 put_pd_read(pd);
1039
Ingo Molnar95ed6442006-01-13 14:51:39 -08001040 mutex_lock(&file->mutex);
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001041 list_add_tail(&uobj->list, &file->ucontext->mr_list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08001042 mutex_unlock(&file->mutex);
Roland Dreiereb9d3cd2005-09-27 15:07:25 -07001043
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001044 uobj->live = 1;
Roland Dreier9ead1902006-06-17 20:44:49 -07001045
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001046 up_write(&uobj->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001047
1048 return in_len;
1049
Roland Dreier9ead1902006-06-17 20:44:49 -07001050err_copy:
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001051 idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001052
1053err_unreg:
1054 ib_dereg_mr(mr);
1055
Roland Dreier9ead1902006-06-17 20:44:49 -07001056err_put:
1057 put_pd_read(pd);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001058
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001059err_free:
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001060 put_uobj_write(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001061 return ret;
1062}
1063
Matan Barak7e6edb92014-07-31 11:01:28 +03001064ssize_t ib_uverbs_rereg_mr(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001065 struct ib_device *ib_dev,
Matan Barak7e6edb92014-07-31 11:01:28 +03001066 const char __user *buf, int in_len,
1067 int out_len)
1068{
1069 struct ib_uverbs_rereg_mr cmd;
1070 struct ib_uverbs_rereg_mr_resp resp;
1071 struct ib_udata udata;
1072 struct ib_pd *pd = NULL;
1073 struct ib_mr *mr;
1074 struct ib_pd *old_pd;
1075 int ret;
1076 struct ib_uobject *uobj;
1077
1078 if (out_len < sizeof(resp))
1079 return -ENOSPC;
1080
1081 if (copy_from_user(&cmd, buf, sizeof(cmd)))
1082 return -EFAULT;
1083
1084 INIT_UDATA(&udata, buf + sizeof(cmd),
1085 (unsigned long) cmd.response + sizeof(resp),
1086 in_len - sizeof(cmd), out_len - sizeof(resp));
1087
1088 if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags)
1089 return -EINVAL;
1090
1091 if ((cmd.flags & IB_MR_REREG_TRANS) &&
1092 (!cmd.start || !cmd.hca_va || 0 >= cmd.length ||
1093 (cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)))
1094 return -EINVAL;
1095
1096 uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle,
1097 file->ucontext);
1098
1099 if (!uobj)
1100 return -EINVAL;
1101
1102 mr = uobj->object;
1103
1104 if (cmd.flags & IB_MR_REREG_ACCESS) {
1105 ret = ib_check_mr_access(cmd.access_flags);
1106 if (ret)
1107 goto put_uobjs;
1108 }
1109
1110 if (cmd.flags & IB_MR_REREG_PD) {
1111 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1112 if (!pd) {
1113 ret = -EINVAL;
1114 goto put_uobjs;
1115 }
1116 }
1117
Matan Barak7e6edb92014-07-31 11:01:28 +03001118 old_pd = mr->pd;
1119 ret = mr->device->rereg_user_mr(mr, cmd.flags, cmd.start,
1120 cmd.length, cmd.hca_va,
1121 cmd.access_flags, pd, &udata);
1122 if (!ret) {
1123 if (cmd.flags & IB_MR_REREG_PD) {
1124 atomic_inc(&pd->usecnt);
1125 mr->pd = pd;
1126 atomic_dec(&old_pd->usecnt);
1127 }
1128 } else {
1129 goto put_uobj_pd;
1130 }
1131
1132 memset(&resp, 0, sizeof(resp));
1133 resp.lkey = mr->lkey;
1134 resp.rkey = mr->rkey;
1135
1136 if (copy_to_user((void __user *)(unsigned long)cmd.response,
1137 &resp, sizeof(resp)))
1138 ret = -EFAULT;
1139 else
1140 ret = in_len;
1141
1142put_uobj_pd:
1143 if (cmd.flags & IB_MR_REREG_PD)
1144 put_pd_read(pd);
1145
1146put_uobjs:
1147
1148 put_uobj_write(mr->uobject);
1149
1150 return ret;
1151}
1152
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001153ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001154 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001155 const char __user *buf, int in_len,
1156 int out_len)
1157{
1158 struct ib_uverbs_dereg_mr cmd;
1159 struct ib_mr *mr;
Roland Dreier9ead1902006-06-17 20:44:49 -07001160 struct ib_uobject *uobj;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001161 int ret = -EINVAL;
1162
1163 if (copy_from_user(&cmd, buf, sizeof cmd))
1164 return -EFAULT;
1165
Roland Dreier9ead1902006-06-17 20:44:49 -07001166 uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle, file->ucontext);
1167 if (!uobj)
1168 return -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001169
Roland Dreierf7c6a7b2007-03-04 16:15:11 -08001170 mr = uobj->object;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001171
1172 ret = ib_dereg_mr(mr);
Roland Dreier9ead1902006-06-17 20:44:49 -07001173 if (!ret)
1174 uobj->live = 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001175
Roland Dreier9ead1902006-06-17 20:44:49 -07001176 put_uobj_write(uobj);
1177
1178 if (ret)
1179 return ret;
1180
1181 idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001182
Ingo Molnar95ed6442006-01-13 14:51:39 -08001183 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07001184 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08001185 mutex_unlock(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001186
Roland Dreier9ead1902006-06-17 20:44:49 -07001187 put_uobj(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001188
Roland Dreier9ead1902006-06-17 20:44:49 -07001189 return in_len;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001190}
1191
Shani Michaeli6b52a122013-02-06 16:19:13 +00001192ssize_t ib_uverbs_alloc_mw(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001193 struct ib_device *ib_dev,
1194 const char __user *buf, int in_len,
1195 int out_len)
Shani Michaeli6b52a122013-02-06 16:19:13 +00001196{
1197 struct ib_uverbs_alloc_mw cmd;
1198 struct ib_uverbs_alloc_mw_resp resp;
1199 struct ib_uobject *uobj;
1200 struct ib_pd *pd;
1201 struct ib_mw *mw;
Matan Barakb2a239d2016-02-29 18:05:29 +02001202 struct ib_udata udata;
Shani Michaeli6b52a122013-02-06 16:19:13 +00001203 int ret;
1204
1205 if (out_len < sizeof(resp))
1206 return -ENOSPC;
1207
1208 if (copy_from_user(&cmd, buf, sizeof(cmd)))
1209 return -EFAULT;
1210
1211 uobj = kmalloc(sizeof(*uobj), GFP_KERNEL);
1212 if (!uobj)
1213 return -ENOMEM;
1214
1215 init_uobj(uobj, 0, file->ucontext, &mw_lock_class);
1216 down_write(&uobj->mutex);
1217
1218 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
1219 if (!pd) {
1220 ret = -EINVAL;
1221 goto err_free;
1222 }
1223
Matan Barakb2a239d2016-02-29 18:05:29 +02001224 INIT_UDATA(&udata, buf + sizeof(cmd),
1225 (unsigned long)cmd.response + sizeof(resp),
1226 in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
1227 out_len - sizeof(resp));
1228
1229 mw = pd->device->alloc_mw(pd, cmd.mw_type, &udata);
Shani Michaeli6b52a122013-02-06 16:19:13 +00001230 if (IS_ERR(mw)) {
1231 ret = PTR_ERR(mw);
1232 goto err_put;
1233 }
1234
1235 mw->device = pd->device;
1236 mw->pd = pd;
1237 mw->uobject = uobj;
1238 atomic_inc(&pd->usecnt);
1239
1240 uobj->object = mw;
1241 ret = idr_add_uobj(&ib_uverbs_mw_idr, uobj);
1242 if (ret)
1243 goto err_unalloc;
1244
1245 memset(&resp, 0, sizeof(resp));
1246 resp.rkey = mw->rkey;
1247 resp.mw_handle = uobj->id;
1248
1249 if (copy_to_user((void __user *)(unsigned long)cmd.response,
1250 &resp, sizeof(resp))) {
1251 ret = -EFAULT;
1252 goto err_copy;
1253 }
1254
1255 put_pd_read(pd);
1256
1257 mutex_lock(&file->mutex);
1258 list_add_tail(&uobj->list, &file->ucontext->mw_list);
1259 mutex_unlock(&file->mutex);
1260
1261 uobj->live = 1;
1262
1263 up_write(&uobj->mutex);
1264
1265 return in_len;
1266
1267err_copy:
1268 idr_remove_uobj(&ib_uverbs_mw_idr, uobj);
1269
1270err_unalloc:
Christoph Hellwigfeb7c1e2015-12-23 19:12:48 +01001271 uverbs_dealloc_mw(mw);
Shani Michaeli6b52a122013-02-06 16:19:13 +00001272
1273err_put:
1274 put_pd_read(pd);
1275
1276err_free:
1277 put_uobj_write(uobj);
1278 return ret;
1279}
1280
1281ssize_t ib_uverbs_dealloc_mw(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001282 struct ib_device *ib_dev,
1283 const char __user *buf, int in_len,
1284 int out_len)
Shani Michaeli6b52a122013-02-06 16:19:13 +00001285{
1286 struct ib_uverbs_dealloc_mw cmd;
1287 struct ib_mw *mw;
1288 struct ib_uobject *uobj;
1289 int ret = -EINVAL;
1290
1291 if (copy_from_user(&cmd, buf, sizeof(cmd)))
1292 return -EFAULT;
1293
1294 uobj = idr_write_uobj(&ib_uverbs_mw_idr, cmd.mw_handle, file->ucontext);
1295 if (!uobj)
1296 return -EINVAL;
1297
1298 mw = uobj->object;
1299
Christoph Hellwigfeb7c1e2015-12-23 19:12:48 +01001300 ret = uverbs_dealloc_mw(mw);
Shani Michaeli6b52a122013-02-06 16:19:13 +00001301 if (!ret)
1302 uobj->live = 0;
1303
1304 put_uobj_write(uobj);
1305
1306 if (ret)
1307 return ret;
1308
1309 idr_remove_uobj(&ib_uverbs_mw_idr, uobj);
1310
1311 mutex_lock(&file->mutex);
1312 list_del(&uobj->list);
1313 mutex_unlock(&file->mutex);
1314
1315 put_uobj(uobj);
1316
1317 return in_len;
1318}
1319
Roland Dreier6b73597e2005-09-26 13:53:25 -07001320ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001321 struct ib_device *ib_dev,
Roland Dreier6b73597e2005-09-26 13:53:25 -07001322 const char __user *buf, int in_len,
1323 int out_len)
1324{
1325 struct ib_uverbs_create_comp_channel cmd;
1326 struct ib_uverbs_create_comp_channel_resp resp;
1327 struct file *filp;
Al Virob1e45942010-01-18 01:38:00 -05001328 int ret;
Roland Dreier6b73597e2005-09-26 13:53:25 -07001329
1330 if (out_len < sizeof resp)
1331 return -ENOSPC;
1332
1333 if (copy_from_user(&cmd, buf, sizeof cmd))
1334 return -EFAULT;
1335
Roland Dreierda183c72013-07-08 11:15:45 -07001336 ret = get_unused_fd_flags(O_CLOEXEC);
Al Virob1e45942010-01-18 01:38:00 -05001337 if (ret < 0)
1338 return ret;
1339 resp.fd = ret;
1340
Yishai Hadas057aec02015-08-13 18:32:04 +03001341 filp = ib_uverbs_alloc_event_file(file, ib_dev, 0);
Al Virob1e45942010-01-18 01:38:00 -05001342 if (IS_ERR(filp)) {
1343 put_unused_fd(resp.fd);
Roland Dreier6b73597e2005-09-26 13:53:25 -07001344 return PTR_ERR(filp);
Al Virob1e45942010-01-18 01:38:00 -05001345 }
Roland Dreier6b73597e2005-09-26 13:53:25 -07001346
1347 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1348 &resp, sizeof resp)) {
1349 put_unused_fd(resp.fd);
1350 fput(filp);
1351 return -EFAULT;
1352 }
1353
1354 fd_install(resp.fd, filp);
1355 return in_len;
1356}
1357
Matan Barak565197d2015-06-11 16:35:23 +03001358static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001359 struct ib_device *ib_dev,
Matan Barak565197d2015-06-11 16:35:23 +03001360 struct ib_udata *ucore,
1361 struct ib_udata *uhw,
1362 struct ib_uverbs_ex_create_cq *cmd,
1363 size_t cmd_sz,
1364 int (*cb)(struct ib_uverbs_file *file,
1365 struct ib_ucq_object *obj,
1366 struct ib_uverbs_ex_create_cq_resp *resp,
1367 struct ib_udata *udata,
1368 void *context),
1369 void *context)
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001370{
Roland Dreier9ead1902006-06-17 20:44:49 -07001371 struct ib_ucq_object *obj;
Roland Dreier6b73597e2005-09-26 13:53:25 -07001372 struct ib_uverbs_event_file *ev_file = NULL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001373 struct ib_cq *cq;
1374 int ret;
Matan Barak565197d2015-06-11 16:35:23 +03001375 struct ib_uverbs_ex_create_cq_resp resp;
Matan Barakbcf4c1e2015-06-11 16:35:20 +03001376 struct ib_cq_init_attr attr = {};
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001377
Matan Barak565197d2015-06-11 16:35:23 +03001378 if (cmd->comp_vector >= file->device->num_comp_vectors)
1379 return ERR_PTR(-EINVAL);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001380
Roland Dreier9ead1902006-06-17 20:44:49 -07001381 obj = kmalloc(sizeof *obj, GFP_KERNEL);
1382 if (!obj)
Matan Barak565197d2015-06-11 16:35:23 +03001383 return ERR_PTR(-ENOMEM);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001384
Matan Barak565197d2015-06-11 16:35:23 +03001385 init_uobj(&obj->uobject, cmd->user_handle, file->ucontext, &cq_lock_class);
Roland Dreier9ead1902006-06-17 20:44:49 -07001386 down_write(&obj->uobject.mutex);
1387
Matan Barak565197d2015-06-11 16:35:23 +03001388 if (cmd->comp_channel >= 0) {
1389 ev_file = ib_uverbs_lookup_comp_file(cmd->comp_channel);
Jack Morgensteinac4e7b32006-01-06 16:43:14 -08001390 if (!ev_file) {
1391 ret = -EINVAL;
1392 goto err;
1393 }
1394 }
1395
Roland Dreier9ead1902006-06-17 20:44:49 -07001396 obj->uverbs_file = file;
1397 obj->comp_events_reported = 0;
1398 obj->async_events_reported = 0;
1399 INIT_LIST_HEAD(&obj->comp_list);
1400 INIT_LIST_HEAD(&obj->async_list);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001401
Matan Barak565197d2015-06-11 16:35:23 +03001402 attr.cqe = cmd->cqe;
1403 attr.comp_vector = cmd->comp_vector;
1404
1405 if (cmd_sz > offsetof(typeof(*cmd), flags) + sizeof(cmd->flags))
1406 attr.flags = cmd->flags;
1407
Yishai Hadas057aec02015-08-13 18:32:04 +03001408 cq = ib_dev->create_cq(ib_dev, &attr,
Matan Barak565197d2015-06-11 16:35:23 +03001409 file->ucontext, uhw);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001410 if (IS_ERR(cq)) {
1411 ret = PTR_ERR(cq);
Roland Dreier9ead1902006-06-17 20:44:49 -07001412 goto err_file;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001413 }
1414
Yishai Hadas057aec02015-08-13 18:32:04 +03001415 cq->device = ib_dev;
Roland Dreier9ead1902006-06-17 20:44:49 -07001416 cq->uobject = &obj->uobject;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001417 cq->comp_handler = ib_uverbs_comp_handler;
1418 cq->event_handler = ib_uverbs_cq_event_handler;
Roland Dreier6b73597e2005-09-26 13:53:25 -07001419 cq->cq_context = ev_file;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001420 atomic_set(&cq->usecnt, 0);
1421
Roland Dreier9ead1902006-06-17 20:44:49 -07001422 obj->uobject.object = cq;
1423 ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001424 if (ret)
Roland Dreier9ead1902006-06-17 20:44:49 -07001425 goto err_free;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001426
1427 memset(&resp, 0, sizeof resp);
Matan Barak565197d2015-06-11 16:35:23 +03001428 resp.base.cq_handle = obj->uobject.id;
1429 resp.base.cqe = cq->cqe;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001430
Matan Barak565197d2015-06-11 16:35:23 +03001431 resp.response_length = offsetof(typeof(resp), response_length) +
1432 sizeof(resp.response_length);
1433
1434 ret = cb(file, obj, &resp, ucore, context);
1435 if (ret)
1436 goto err_cb;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001437
Ingo Molnar95ed6442006-01-13 14:51:39 -08001438 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07001439 list_add_tail(&obj->uobject.list, &file->ucontext->cq_list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08001440 mutex_unlock(&file->mutex);
Roland Dreiereb9d3cd2005-09-27 15:07:25 -07001441
Roland Dreier9ead1902006-06-17 20:44:49 -07001442 obj->uobject.live = 1;
1443
1444 up_write(&obj->uobject.mutex);
Roland Dreiereb9d3cd2005-09-27 15:07:25 -07001445
Matan Barak565197d2015-06-11 16:35:23 +03001446 return obj;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001447
Matan Barak565197d2015-06-11 16:35:23 +03001448err_cb:
Roland Dreier9ead1902006-06-17 20:44:49 -07001449 idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001450
Roland Dreier9ead1902006-06-17 20:44:49 -07001451err_free:
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001452 ib_destroy_cq(cq);
1453
Roland Dreier9ead1902006-06-17 20:44:49 -07001454err_file:
Jack Morgensteinac4e7b32006-01-06 16:43:14 -08001455 if (ev_file)
Roland Dreier9ead1902006-06-17 20:44:49 -07001456 ib_uverbs_release_ucq(file, ev_file, obj);
1457
1458err:
1459 put_uobj_write(&obj->uobject);
Matan Barak565197d2015-06-11 16:35:23 +03001460
1461 return ERR_PTR(ret);
1462}
1463
1464static int ib_uverbs_create_cq_cb(struct ib_uverbs_file *file,
1465 struct ib_ucq_object *obj,
1466 struct ib_uverbs_ex_create_cq_resp *resp,
1467 struct ib_udata *ucore, void *context)
1468{
1469 if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base)))
1470 return -EFAULT;
1471
1472 return 0;
1473}
1474
1475ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001476 struct ib_device *ib_dev,
Matan Barak565197d2015-06-11 16:35:23 +03001477 const char __user *buf, int in_len,
1478 int out_len)
1479{
1480 struct ib_uverbs_create_cq cmd;
1481 struct ib_uverbs_ex_create_cq cmd_ex;
1482 struct ib_uverbs_create_cq_resp resp;
1483 struct ib_udata ucore;
1484 struct ib_udata uhw;
1485 struct ib_ucq_object *obj;
1486
1487 if (out_len < sizeof(resp))
1488 return -ENOSPC;
1489
1490 if (copy_from_user(&cmd, buf, sizeof(cmd)))
1491 return -EFAULT;
1492
Arnd Bergmann5d1e6232015-10-07 14:29:51 +02001493 INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd), sizeof(resp));
Matan Barak565197d2015-06-11 16:35:23 +03001494
1495 INIT_UDATA(&uhw, buf + sizeof(cmd),
1496 (unsigned long)cmd.response + sizeof(resp),
1497 in_len - sizeof(cmd), out_len - sizeof(resp));
1498
1499 memset(&cmd_ex, 0, sizeof(cmd_ex));
1500 cmd_ex.user_handle = cmd.user_handle;
1501 cmd_ex.cqe = cmd.cqe;
1502 cmd_ex.comp_vector = cmd.comp_vector;
1503 cmd_ex.comp_channel = cmd.comp_channel;
1504
Yishai Hadas057aec02015-08-13 18:32:04 +03001505 obj = create_cq(file, ib_dev, &ucore, &uhw, &cmd_ex,
Matan Barak565197d2015-06-11 16:35:23 +03001506 offsetof(typeof(cmd_ex), comp_channel) +
1507 sizeof(cmd.comp_channel), ib_uverbs_create_cq_cb,
1508 NULL);
1509
1510 if (IS_ERR(obj))
1511 return PTR_ERR(obj);
1512
1513 return in_len;
1514}
1515
1516static int ib_uverbs_ex_create_cq_cb(struct ib_uverbs_file *file,
1517 struct ib_ucq_object *obj,
1518 struct ib_uverbs_ex_create_cq_resp *resp,
1519 struct ib_udata *ucore, void *context)
1520{
1521 if (ib_copy_to_udata(ucore, resp, resp->response_length))
1522 return -EFAULT;
1523
1524 return 0;
1525}
1526
1527int ib_uverbs_ex_create_cq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001528 struct ib_device *ib_dev,
Matan Barak565197d2015-06-11 16:35:23 +03001529 struct ib_udata *ucore,
1530 struct ib_udata *uhw)
1531{
1532 struct ib_uverbs_ex_create_cq_resp resp;
1533 struct ib_uverbs_ex_create_cq cmd;
1534 struct ib_ucq_object *obj;
1535 int err;
1536
1537 if (ucore->inlen < sizeof(cmd))
1538 return -EINVAL;
1539
1540 err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
1541 if (err)
1542 return err;
1543
1544 if (cmd.comp_mask)
1545 return -EINVAL;
1546
1547 if (cmd.reserved)
1548 return -EINVAL;
1549
1550 if (ucore->outlen < (offsetof(typeof(resp), response_length) +
1551 sizeof(resp.response_length)))
1552 return -ENOSPC;
1553
Yishai Hadas057aec02015-08-13 18:32:04 +03001554 obj = create_cq(file, ib_dev, ucore, uhw, &cmd,
Matan Barak565197d2015-06-11 16:35:23 +03001555 min(ucore->inlen, sizeof(cmd)),
1556 ib_uverbs_ex_create_cq_cb, NULL);
1557
1558 if (IS_ERR(obj))
1559 return PTR_ERR(obj);
1560
1561 return 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001562}
1563
Roland Dreier33b9b3e2006-01-30 14:29:21 -08001564ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001565 struct ib_device *ib_dev,
Roland Dreier33b9b3e2006-01-30 14:29:21 -08001566 const char __user *buf, int in_len,
1567 int out_len)
1568{
1569 struct ib_uverbs_resize_cq cmd;
1570 struct ib_uverbs_resize_cq_resp resp;
1571 struct ib_udata udata;
1572 struct ib_cq *cq;
1573 int ret = -EINVAL;
1574
1575 if (copy_from_user(&cmd, buf, sizeof cmd))
1576 return -EFAULT;
1577
1578 INIT_UDATA(&udata, buf + sizeof cmd,
1579 (unsigned long) cmd.response + sizeof resp,
1580 in_len - sizeof cmd, out_len - sizeof resp);
1581
Roland Dreier1ccf6aa2006-09-22 15:17:20 -07001582 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
Roland Dreier9ead1902006-06-17 20:44:49 -07001583 if (!cq)
1584 return -EINVAL;
Roland Dreier33b9b3e2006-01-30 14:29:21 -08001585
1586 ret = cq->device->resize_cq(cq, cmd.cqe, &udata);
1587 if (ret)
1588 goto out;
1589
Roland Dreier33b9b3e2006-01-30 14:29:21 -08001590 resp.cqe = cq->cqe;
1591
1592 if (copy_to_user((void __user *) (unsigned long) cmd.response,
Ralph Campbell64f817b2006-09-22 15:22:24 -07001593 &resp, sizeof resp.cqe))
Roland Dreier33b9b3e2006-01-30 14:29:21 -08001594 ret = -EFAULT;
1595
1596out:
Roland Dreier9ead1902006-06-17 20:44:49 -07001597 put_cq_read(cq);
Roland Dreier33b9b3e2006-01-30 14:29:21 -08001598
1599 return ret ? ret : in_len;
1600}
1601
Dan Carpenter7182afe2010-10-13 09:13:12 +00001602static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
1603{
1604 struct ib_uverbs_wc tmp;
1605
1606 tmp.wr_id = wc->wr_id;
1607 tmp.status = wc->status;
1608 tmp.opcode = wc->opcode;
1609 tmp.vendor_err = wc->vendor_err;
1610 tmp.byte_len = wc->byte_len;
1611 tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data;
1612 tmp.qp_num = wc->qp->qp_num;
1613 tmp.src_qp = wc->src_qp;
1614 tmp.wc_flags = wc->wc_flags;
1615 tmp.pkey_index = wc->pkey_index;
1616 tmp.slid = wc->slid;
1617 tmp.sl = wc->sl;
1618 tmp.dlid_path_bits = wc->dlid_path_bits;
1619 tmp.port_num = wc->port_num;
1620 tmp.reserved = 0;
1621
1622 if (copy_to_user(dest, &tmp, sizeof tmp))
1623 return -EFAULT;
1624
1625 return 0;
1626}
1627
Roland Dreier67cdb402005-10-14 15:26:04 -07001628ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001629 struct ib_device *ib_dev,
Roland Dreier67cdb402005-10-14 15:26:04 -07001630 const char __user *buf, int in_len,
1631 int out_len)
1632{
1633 struct ib_uverbs_poll_cq cmd;
Dan Carpenter7182afe2010-10-13 09:13:12 +00001634 struct ib_uverbs_poll_cq_resp resp;
1635 u8 __user *header_ptr;
1636 u8 __user *data_ptr;
Roland Dreier67cdb402005-10-14 15:26:04 -07001637 struct ib_cq *cq;
Dan Carpenter7182afe2010-10-13 09:13:12 +00001638 struct ib_wc wc;
1639 int ret;
Roland Dreier67cdb402005-10-14 15:26:04 -07001640
1641 if (copy_from_user(&cmd, buf, sizeof cmd))
1642 return -EFAULT;
1643
Roland Dreier1ccf6aa2006-09-22 15:17:20 -07001644 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
Dan Carpenter7182afe2010-10-13 09:13:12 +00001645 if (!cq)
1646 return -EINVAL;
1647
1648 /* we copy a struct ib_uverbs_poll_cq_resp to user space */
1649 header_ptr = (void __user *)(unsigned long) cmd.response;
1650 data_ptr = header_ptr + sizeof resp;
1651
1652 memset(&resp, 0, sizeof resp);
1653 while (resp.count < cmd.ne) {
1654 ret = ib_poll_cq(cq, 1, &wc);
1655 if (ret < 0)
1656 goto out_put;
1657 if (!ret)
1658 break;
1659
1660 ret = copy_wc_to_user(data_ptr, &wc);
1661 if (ret)
1662 goto out_put;
1663
1664 data_ptr += sizeof(struct ib_uverbs_wc);
1665 ++resp.count;
Roland Dreier67cdb402005-10-14 15:26:04 -07001666 }
1667
Dan Carpenter7182afe2010-10-13 09:13:12 +00001668 if (copy_to_user(header_ptr, &resp, sizeof resp)) {
Roland Dreier67cdb402005-10-14 15:26:04 -07001669 ret = -EFAULT;
Dan Carpenter7182afe2010-10-13 09:13:12 +00001670 goto out_put;
1671 }
Roland Dreier67cdb402005-10-14 15:26:04 -07001672
Dan Carpenter7182afe2010-10-13 09:13:12 +00001673 ret = in_len;
Roland Dreier67cdb402005-10-14 15:26:04 -07001674
Dan Carpenter7182afe2010-10-13 09:13:12 +00001675out_put:
1676 put_cq_read(cq);
1677 return ret;
Roland Dreier67cdb402005-10-14 15:26:04 -07001678}
1679
1680ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001681 struct ib_device *ib_dev,
Roland Dreier67cdb402005-10-14 15:26:04 -07001682 const char __user *buf, int in_len,
1683 int out_len)
1684{
1685 struct ib_uverbs_req_notify_cq cmd;
1686 struct ib_cq *cq;
Roland Dreier67cdb402005-10-14 15:26:04 -07001687
1688 if (copy_from_user(&cmd, buf, sizeof cmd))
1689 return -EFAULT;
1690
Roland Dreier1ccf6aa2006-09-22 15:17:20 -07001691 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
Roland Dreierab108672006-09-22 15:17:19 -07001692 if (!cq)
Roland Dreier9ead1902006-06-17 20:44:49 -07001693 return -EINVAL;
Roland Dreier67cdb402005-10-14 15:26:04 -07001694
Roland Dreier9ead1902006-06-17 20:44:49 -07001695 ib_req_notify_cq(cq, cmd.solicited_only ?
1696 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
1697
Roland Dreierab108672006-09-22 15:17:19 -07001698 put_cq_read(cq);
Roland Dreier9ead1902006-06-17 20:44:49 -07001699
1700 return in_len;
Roland Dreier67cdb402005-10-14 15:26:04 -07001701}
1702
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001703ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03001704 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001705 const char __user *buf, int in_len,
1706 int out_len)
1707{
Roland Dreier63aaf642005-09-09 15:55:08 -07001708 struct ib_uverbs_destroy_cq cmd;
1709 struct ib_uverbs_destroy_cq_resp resp;
Roland Dreier9ead1902006-06-17 20:44:49 -07001710 struct ib_uobject *uobj;
Roland Dreier63aaf642005-09-09 15:55:08 -07001711 struct ib_cq *cq;
Roland Dreier9ead1902006-06-17 20:44:49 -07001712 struct ib_ucq_object *obj;
Roland Dreier6b73597e2005-09-26 13:53:25 -07001713 struct ib_uverbs_event_file *ev_file;
Roland Dreier63aaf642005-09-09 15:55:08 -07001714 int ret = -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001715
1716 if (copy_from_user(&cmd, buf, sizeof cmd))
1717 return -EFAULT;
1718
Roland Dreier9ead1902006-06-17 20:44:49 -07001719 uobj = idr_write_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
1720 if (!uobj)
1721 return -EINVAL;
1722 cq = uobj->object;
1723 ev_file = cq->cq_context;
1724 obj = container_of(cq->uobject, struct ib_ucq_object, uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001725
1726 ret = ib_destroy_cq(cq);
Roland Dreier9ead1902006-06-17 20:44:49 -07001727 if (!ret)
1728 uobj->live = 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001729
Roland Dreier9ead1902006-06-17 20:44:49 -07001730 put_uobj_write(uobj);
1731
1732 if (ret)
1733 return ret;
1734
1735 idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001736
Ingo Molnar95ed6442006-01-13 14:51:39 -08001737 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07001738 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08001739 mutex_unlock(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001740
Roland Dreier9ead1902006-06-17 20:44:49 -07001741 ib_uverbs_release_ucq(file, ev_file, obj);
Roland Dreier63aaf642005-09-09 15:55:08 -07001742
Roland Dreier9ead1902006-06-17 20:44:49 -07001743 memset(&resp, 0, sizeof resp);
1744 resp.comp_events_reported = obj->comp_events_reported;
1745 resp.async_events_reported = obj->async_events_reported;
Roland Dreier63aaf642005-09-09 15:55:08 -07001746
Roland Dreier9ead1902006-06-17 20:44:49 -07001747 put_uobj(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001748
Roland Dreier63aaf642005-09-09 15:55:08 -07001749 if (copy_to_user((void __user *) (unsigned long) cmd.response,
1750 &resp, sizeof resp))
Roland Dreier9ead1902006-06-17 20:44:49 -07001751 return -EFAULT;
Roland Dreier63aaf642005-09-09 15:55:08 -07001752
Roland Dreier9ead1902006-06-17 20:44:49 -07001753 return in_len;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001754}
1755
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001756static int create_qp(struct ib_uverbs_file *file,
1757 struct ib_udata *ucore,
1758 struct ib_udata *uhw,
1759 struct ib_uverbs_ex_create_qp *cmd,
1760 size_t cmd_sz,
1761 int (*cb)(struct ib_uverbs_file *file,
1762 struct ib_uverbs_ex_create_qp_resp *resp,
1763 struct ib_udata *udata),
1764 void *context)
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001765{
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001766 struct ib_uqp_object *obj;
1767 struct ib_device *device;
1768 struct ib_pd *pd = NULL;
1769 struct ib_xrcd *xrcd = NULL;
1770 struct ib_uobject *uninitialized_var(xrcd_uobj);
1771 struct ib_cq *scq = NULL, *rcq = NULL;
1772 struct ib_srq *srq = NULL;
1773 struct ib_qp *qp;
1774 char *buf;
Yishai Hadasc70285f2016-05-23 15:20:55 +03001775 struct ib_qp_init_attr attr = {};
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001776 struct ib_uverbs_ex_create_qp_resp resp;
1777 int ret;
Yishai Hadasc70285f2016-05-23 15:20:55 +03001778 struct ib_rwq_ind_table *ind_tbl = NULL;
1779 bool has_sq = true;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001780
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001781 if (cmd->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
Or Gerlitzc938a612012-03-01 12:17:51 +02001782 return -EPERM;
1783
Yishai Hadas846be902013-08-01 18:49:54 +03001784 obj = kzalloc(sizeof *obj, GFP_KERNEL);
Roland Dreier9ead1902006-06-17 20:44:49 -07001785 if (!obj)
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001786 return -ENOMEM;
1787
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001788 init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext,
1789 &qp_lock_class);
Roland Dreier9ead1902006-06-17 20:44:49 -07001790 down_write(&obj->uevent.uobject.mutex);
Yishai Hadasc70285f2016-05-23 15:20:55 +03001791 if (cmd_sz >= offsetof(typeof(*cmd), rwq_ind_tbl_handle) +
1792 sizeof(cmd->rwq_ind_tbl_handle) &&
1793 (cmd->comp_mask & IB_UVERBS_CREATE_QP_MASK_IND_TABLE)) {
1794 ind_tbl = idr_read_rwq_indirection_table(cmd->rwq_ind_tbl_handle,
1795 file->ucontext);
1796 if (!ind_tbl) {
1797 ret = -EINVAL;
1798 goto err_put;
1799 }
1800
1801 attr.rwq_ind_tbl = ind_tbl;
1802 }
1803
1804 if ((cmd_sz >= offsetof(typeof(*cmd), reserved1) +
1805 sizeof(cmd->reserved1)) && cmd->reserved1) {
1806 ret = -EOPNOTSUPP;
1807 goto err_put;
1808 }
1809
1810 if (ind_tbl && (cmd->max_recv_wr || cmd->max_recv_sge || cmd->is_srq)) {
1811 ret = -EINVAL;
1812 goto err_put;
1813 }
1814
1815 if (ind_tbl && !cmd->max_send_wr)
1816 has_sq = false;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001817
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001818 if (cmd->qp_type == IB_QPT_XRC_TGT) {
1819 xrcd = idr_read_xrcd(cmd->pd_handle, file->ucontext,
1820 &xrcd_uobj);
Sean Heftyb93f3c12011-05-27 00:00:12 -07001821 if (!xrcd) {
1822 ret = -EINVAL;
1823 goto err_put;
1824 }
1825 device = xrcd->device;
Sean Hefty9977f4f2011-05-26 08:17:04 -07001826 } else {
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001827 if (cmd->qp_type == IB_QPT_XRC_INI) {
1828 cmd->max_recv_wr = 0;
1829 cmd->max_recv_sge = 0;
Sean Heftyb93f3c12011-05-27 00:00:12 -07001830 } else {
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001831 if (cmd->is_srq) {
1832 srq = idr_read_srq(cmd->srq_handle,
1833 file->ucontext);
Sean Heftyb93f3c12011-05-27 00:00:12 -07001834 if (!srq || srq->srq_type != IB_SRQT_BASIC) {
1835 ret = -EINVAL;
1836 goto err_put;
1837 }
1838 }
Roland Dreier5909ce52012-04-30 12:51:50 -07001839
Yishai Hadasc70285f2016-05-23 15:20:55 +03001840 if (!ind_tbl) {
1841 if (cmd->recv_cq_handle != cmd->send_cq_handle) {
1842 rcq = idr_read_cq(cmd->recv_cq_handle,
1843 file->ucontext, 0);
1844 if (!rcq) {
1845 ret = -EINVAL;
1846 goto err_put;
1847 }
Roland Dreier5909ce52012-04-30 12:51:50 -07001848 }
Sean Hefty9977f4f2011-05-26 08:17:04 -07001849 }
1850 }
Roland Dreier5909ce52012-04-30 12:51:50 -07001851
Yishai Hadasc70285f2016-05-23 15:20:55 +03001852 if (has_sq)
1853 scq = idr_read_cq(cmd->send_cq_handle, file->ucontext, !!rcq);
1854 if (!ind_tbl)
1855 rcq = rcq ?: scq;
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001856 pd = idr_read_pd(cmd->pd_handle, file->ucontext);
Yishai Hadasc70285f2016-05-23 15:20:55 +03001857 if (!pd || (!scq && has_sq)) {
Roland Dreier5909ce52012-04-30 12:51:50 -07001858 ret = -EINVAL;
1859 goto err_put;
1860 }
1861
Sean Heftyb93f3c12011-05-27 00:00:12 -07001862 device = pd->device;
Sean Hefty9977f4f2011-05-26 08:17:04 -07001863 }
1864
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001865 attr.event_handler = ib_uverbs_qp_event_handler;
1866 attr.qp_context = file;
1867 attr.send_cq = scq;
1868 attr.recv_cq = rcq;
Roland Dreierf520ba52005-08-18 12:24:13 -07001869 attr.srq = srq;
Sean Heftyb93f3c12011-05-27 00:00:12 -07001870 attr.xrcd = xrcd;
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001871 attr.sq_sig_type = cmd->sq_sig_all ? IB_SIGNAL_ALL_WR :
1872 IB_SIGNAL_REQ_WR;
1873 attr.qp_type = cmd->qp_type;
Eli Cohenb846f252008-04-16 21:09:27 -07001874 attr.create_flags = 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001875
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001876 attr.cap.max_send_wr = cmd->max_send_wr;
1877 attr.cap.max_recv_wr = cmd->max_recv_wr;
1878 attr.cap.max_send_sge = cmd->max_send_sge;
1879 attr.cap.max_recv_sge = cmd->max_recv_sge;
1880 attr.cap.max_inline_data = cmd->max_inline_data;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001881
Roland Dreier9ead1902006-06-17 20:44:49 -07001882 obj->uevent.events_reported = 0;
1883 INIT_LIST_HEAD(&obj->uevent.event_list);
1884 INIT_LIST_HEAD(&obj->mcast_list);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001885
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001886 if (cmd_sz >= offsetof(typeof(*cmd), create_flags) +
1887 sizeof(cmd->create_flags))
1888 attr.create_flags = cmd->create_flags;
1889
Leon Romanovsky8a06ce52015-12-20 12:16:10 +02001890 if (attr.create_flags & ~(IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK |
1891 IB_QP_CREATE_CROSS_CHANNEL |
1892 IB_QP_CREATE_MANAGED_SEND |
Majd Dibbinyb531b902016-04-17 17:19:36 +03001893 IB_QP_CREATE_MANAGED_RECV |
1894 IB_QP_CREATE_SCATTER_FCS)) {
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001895 ret = -EINVAL;
1896 goto err_put;
1897 }
1898
1899 buf = (void *)cmd + sizeof(*cmd);
1900 if (cmd_sz > sizeof(*cmd))
1901 if (!(buf[0] == 0 && !memcmp(buf, buf + 1,
1902 cmd_sz - sizeof(*cmd) - 1))) {
1903 ret = -EINVAL;
1904 goto err_put;
1905 }
1906
1907 if (cmd->qp_type == IB_QPT_XRC_TGT)
Sean Heftyb93f3c12011-05-27 00:00:12 -07001908 qp = ib_create_qp(pd, &attr);
1909 else
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001910 qp = device->create_qp(pd, &attr, uhw);
Sean Heftyb93f3c12011-05-27 00:00:12 -07001911
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001912 if (IS_ERR(qp)) {
1913 ret = PTR_ERR(qp);
Roland Dreier9ead1902006-06-17 20:44:49 -07001914 goto err_put;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001915 }
1916
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001917 if (cmd->qp_type != IB_QPT_XRC_TGT) {
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07001918 qp->real_qp = qp;
Sean Heftyb93f3c12011-05-27 00:00:12 -07001919 qp->device = device;
1920 qp->pd = pd;
1921 qp->send_cq = attr.send_cq;
1922 qp->recv_cq = attr.recv_cq;
1923 qp->srq = attr.srq;
Yishai Hadasc70285f2016-05-23 15:20:55 +03001924 qp->rwq_ind_tbl = ind_tbl;
Sean Heftyb93f3c12011-05-27 00:00:12 -07001925 qp->event_handler = attr.event_handler;
1926 qp->qp_context = attr.qp_context;
1927 qp->qp_type = attr.qp_type;
Bernd Schuberte47e3212012-01-20 18:43:54 +00001928 atomic_set(&qp->usecnt, 0);
Sean Heftyb93f3c12011-05-27 00:00:12 -07001929 atomic_inc(&pd->usecnt);
Yishai Hadasc70285f2016-05-23 15:20:55 +03001930 if (attr.send_cq)
1931 atomic_inc(&attr.send_cq->usecnt);
Sean Heftyb93f3c12011-05-27 00:00:12 -07001932 if (attr.recv_cq)
1933 atomic_inc(&attr.recv_cq->usecnt);
1934 if (attr.srq)
1935 atomic_inc(&attr.srq->usecnt);
Yishai Hadasc70285f2016-05-23 15:20:55 +03001936 if (ind_tbl)
1937 atomic_inc(&ind_tbl->usecnt);
Sean Heftyb93f3c12011-05-27 00:00:12 -07001938 }
1939 qp->uobject = &obj->uevent.uobject;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001940
Roland Dreier9ead1902006-06-17 20:44:49 -07001941 obj->uevent.uobject.object = qp;
1942 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001943 if (ret)
1944 goto err_destroy;
1945
Roland Dreier9ead1902006-06-17 20:44:49 -07001946 memset(&resp, 0, sizeof resp);
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001947 resp.base.qpn = qp->qp_num;
1948 resp.base.qp_handle = obj->uevent.uobject.id;
1949 resp.base.max_recv_sge = attr.cap.max_recv_sge;
1950 resp.base.max_send_sge = attr.cap.max_send_sge;
1951 resp.base.max_recv_wr = attr.cap.max_recv_wr;
1952 resp.base.max_send_wr = attr.cap.max_send_wr;
1953 resp.base.max_inline_data = attr.cap.max_inline_data;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001954
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001955 resp.response_length = offsetof(typeof(resp), response_length) +
1956 sizeof(resp.response_length);
1957
1958 ret = cb(file, &resp, ucore);
1959 if (ret)
1960 goto err_cb;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001961
Yishai Hadas846be902013-08-01 18:49:54 +03001962 if (xrcd) {
1963 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
1964 uobject);
1965 atomic_inc(&obj->uxrcd->refcnt);
Sean Heftyb93f3c12011-05-27 00:00:12 -07001966 put_xrcd_read(xrcd_uobj);
Yishai Hadas846be902013-08-01 18:49:54 +03001967 }
1968
Sean Heftyb93f3c12011-05-27 00:00:12 -07001969 if (pd)
1970 put_pd_read(pd);
1971 if (scq)
1972 put_cq_read(scq);
Sean Hefty9977f4f2011-05-26 08:17:04 -07001973 if (rcq && rcq != scq)
Roland Dreier43db2bc2006-07-23 15:16:04 -07001974 put_cq_read(rcq);
Roland Dreier9ead1902006-06-17 20:44:49 -07001975 if (srq)
1976 put_srq_read(srq);
Yishai Hadasc70285f2016-05-23 15:20:55 +03001977 if (ind_tbl)
1978 put_rwq_indirection_table_read(ind_tbl);
Roland Dreier9ead1902006-06-17 20:44:49 -07001979
Ingo Molnar95ed6442006-01-13 14:51:39 -08001980 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07001981 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08001982 mutex_unlock(&file->mutex);
Roland Dreiereb9d3cd2005-09-27 15:07:25 -07001983
Roland Dreier9ead1902006-06-17 20:44:49 -07001984 obj->uevent.uobject.live = 1;
1985
1986 up_write(&obj->uevent.uobject.mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001987
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03001988 return 0;
1989err_cb:
Roland Dreier9ead1902006-06-17 20:44:49 -07001990 idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07001991
1992err_destroy:
1993 ib_destroy_qp(qp);
1994
Roland Dreier9ead1902006-06-17 20:44:49 -07001995err_put:
Sean Heftyb93f3c12011-05-27 00:00:12 -07001996 if (xrcd)
1997 put_xrcd_read(xrcd_uobj);
Roland Dreier9ead1902006-06-17 20:44:49 -07001998 if (pd)
1999 put_pd_read(pd);
2000 if (scq)
2001 put_cq_read(scq);
Roland Dreier43db2bc2006-07-23 15:16:04 -07002002 if (rcq && rcq != scq)
Roland Dreier9ead1902006-06-17 20:44:49 -07002003 put_cq_read(rcq);
2004 if (srq)
2005 put_srq_read(srq);
Yishai Hadasc70285f2016-05-23 15:20:55 +03002006 if (ind_tbl)
2007 put_rwq_indirection_table_read(ind_tbl);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002008
Roland Dreier9ead1902006-06-17 20:44:49 -07002009 put_uobj_write(&obj->uevent.uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002010 return ret;
2011}
2012
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03002013static int ib_uverbs_create_qp_cb(struct ib_uverbs_file *file,
2014 struct ib_uverbs_ex_create_qp_resp *resp,
2015 struct ib_udata *ucore)
2016{
2017 if (ib_copy_to_udata(ucore, &resp->base, sizeof(resp->base)))
2018 return -EFAULT;
2019
2020 return 0;
2021}
2022
2023ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
2024 struct ib_device *ib_dev,
2025 const char __user *buf, int in_len,
2026 int out_len)
2027{
2028 struct ib_uverbs_create_qp cmd;
2029 struct ib_uverbs_ex_create_qp cmd_ex;
2030 struct ib_udata ucore;
2031 struct ib_udata uhw;
2032 ssize_t resp_size = sizeof(struct ib_uverbs_create_qp_resp);
2033 int err;
2034
2035 if (out_len < resp_size)
2036 return -ENOSPC;
2037
2038 if (copy_from_user(&cmd, buf, sizeof(cmd)))
2039 return -EFAULT;
2040
2041 INIT_UDATA(&ucore, buf, (unsigned long)cmd.response, sizeof(cmd),
2042 resp_size);
2043 INIT_UDATA(&uhw, buf + sizeof(cmd),
2044 (unsigned long)cmd.response + resp_size,
Majd Dibbiny3d943c92016-02-14 18:35:52 +02002045 in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
2046 out_len - resp_size);
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03002047
2048 memset(&cmd_ex, 0, sizeof(cmd_ex));
2049 cmd_ex.user_handle = cmd.user_handle;
2050 cmd_ex.pd_handle = cmd.pd_handle;
2051 cmd_ex.send_cq_handle = cmd.send_cq_handle;
2052 cmd_ex.recv_cq_handle = cmd.recv_cq_handle;
2053 cmd_ex.srq_handle = cmd.srq_handle;
2054 cmd_ex.max_send_wr = cmd.max_send_wr;
2055 cmd_ex.max_recv_wr = cmd.max_recv_wr;
2056 cmd_ex.max_send_sge = cmd.max_send_sge;
2057 cmd_ex.max_recv_sge = cmd.max_recv_sge;
2058 cmd_ex.max_inline_data = cmd.max_inline_data;
2059 cmd_ex.sq_sig_all = cmd.sq_sig_all;
2060 cmd_ex.qp_type = cmd.qp_type;
2061 cmd_ex.is_srq = cmd.is_srq;
2062
2063 err = create_qp(file, &ucore, &uhw, &cmd_ex,
2064 offsetof(typeof(cmd_ex), is_srq) +
2065 sizeof(cmd.is_srq), ib_uverbs_create_qp_cb,
2066 NULL);
2067
2068 if (err)
2069 return err;
2070
2071 return in_len;
2072}
2073
2074static int ib_uverbs_ex_create_qp_cb(struct ib_uverbs_file *file,
2075 struct ib_uverbs_ex_create_qp_resp *resp,
2076 struct ib_udata *ucore)
2077{
2078 if (ib_copy_to_udata(ucore, resp, resp->response_length))
2079 return -EFAULT;
2080
2081 return 0;
2082}
2083
2084int ib_uverbs_ex_create_qp(struct ib_uverbs_file *file,
2085 struct ib_device *ib_dev,
2086 struct ib_udata *ucore,
2087 struct ib_udata *uhw)
2088{
2089 struct ib_uverbs_ex_create_qp_resp resp;
2090 struct ib_uverbs_ex_create_qp cmd = {0};
2091 int err;
2092
2093 if (ucore->inlen < (offsetof(typeof(cmd), comp_mask) +
2094 sizeof(cmd.comp_mask)))
2095 return -EINVAL;
2096
2097 err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
2098 if (err)
2099 return err;
2100
Yishai Hadasc70285f2016-05-23 15:20:55 +03002101 if (cmd.comp_mask & ~IB_UVERBS_CREATE_QP_SUP_COMP_MASK)
Eran Ben Elisha6d8a7492015-10-21 17:00:42 +03002102 return -EINVAL;
2103
2104 if (cmd.reserved)
2105 return -EINVAL;
2106
2107 if (ucore->outlen < (offsetof(typeof(resp), response_length) +
2108 sizeof(resp.response_length)))
2109 return -ENOSPC;
2110
2111 err = create_qp(file, ucore, uhw, &cmd,
2112 min(ucore->inlen, sizeof(cmd)),
2113 ib_uverbs_ex_create_qp_cb, NULL);
2114
2115 if (err)
2116 return err;
2117
2118 return 0;
2119}
2120
Sean Hefty42849b22011-08-11 13:57:43 -07002121ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002122 struct ib_device *ib_dev,
Sean Hefty42849b22011-08-11 13:57:43 -07002123 const char __user *buf, int in_len, int out_len)
2124{
2125 struct ib_uverbs_open_qp cmd;
2126 struct ib_uverbs_create_qp_resp resp;
2127 struct ib_udata udata;
2128 struct ib_uqp_object *obj;
2129 struct ib_xrcd *xrcd;
2130 struct ib_uobject *uninitialized_var(xrcd_uobj);
2131 struct ib_qp *qp;
2132 struct ib_qp_open_attr attr;
2133 int ret;
2134
2135 if (out_len < sizeof resp)
2136 return -ENOSPC;
2137
2138 if (copy_from_user(&cmd, buf, sizeof cmd))
2139 return -EFAULT;
2140
2141 INIT_UDATA(&udata, buf + sizeof cmd,
2142 (unsigned long) cmd.response + sizeof resp,
2143 in_len - sizeof cmd, out_len - sizeof resp);
2144
2145 obj = kmalloc(sizeof *obj, GFP_KERNEL);
2146 if (!obj)
2147 return -ENOMEM;
2148
Roland Dreier3bea57a2012-04-30 10:27:26 -07002149 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class);
Sean Hefty42849b22011-08-11 13:57:43 -07002150 down_write(&obj->uevent.uobject.mutex);
2151
2152 xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
2153 if (!xrcd) {
2154 ret = -EINVAL;
2155 goto err_put;
2156 }
2157
2158 attr.event_handler = ib_uverbs_qp_event_handler;
2159 attr.qp_context = file;
2160 attr.qp_num = cmd.qpn;
2161 attr.qp_type = cmd.qp_type;
2162
2163 obj->uevent.events_reported = 0;
2164 INIT_LIST_HEAD(&obj->uevent.event_list);
2165 INIT_LIST_HEAD(&obj->mcast_list);
2166
2167 qp = ib_open_qp(xrcd, &attr);
2168 if (IS_ERR(qp)) {
2169 ret = PTR_ERR(qp);
2170 goto err_put;
2171 }
2172
2173 qp->uobject = &obj->uevent.uobject;
2174
2175 obj->uevent.uobject.object = qp;
2176 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
2177 if (ret)
2178 goto err_destroy;
2179
2180 memset(&resp, 0, sizeof resp);
2181 resp.qpn = qp->qp_num;
2182 resp.qp_handle = obj->uevent.uobject.id;
2183
2184 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2185 &resp, sizeof resp)) {
2186 ret = -EFAULT;
2187 goto err_remove;
2188 }
2189
Yishai Hadas846be902013-08-01 18:49:54 +03002190 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
2191 atomic_inc(&obj->uxrcd->refcnt);
Sean Hefty42849b22011-08-11 13:57:43 -07002192 put_xrcd_read(xrcd_uobj);
2193
2194 mutex_lock(&file->mutex);
2195 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
2196 mutex_unlock(&file->mutex);
2197
2198 obj->uevent.uobject.live = 1;
2199
2200 up_write(&obj->uevent.uobject.mutex);
2201
2202 return in_len;
2203
2204err_remove:
2205 idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
2206
2207err_destroy:
2208 ib_destroy_qp(qp);
2209
2210err_put:
2211 put_xrcd_read(xrcd_uobj);
2212 put_uobj_write(&obj->uevent.uobject);
2213 return ret;
2214}
2215
Dotan Barak7ccc9a22006-02-13 16:31:25 -08002216ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002217 struct ib_device *ib_dev,
Dotan Barak7ccc9a22006-02-13 16:31:25 -08002218 const char __user *buf, int in_len,
2219 int out_len)
2220{
2221 struct ib_uverbs_query_qp cmd;
2222 struct ib_uverbs_query_qp_resp resp;
2223 struct ib_qp *qp;
2224 struct ib_qp_attr *attr;
2225 struct ib_qp_init_attr *init_attr;
2226 int ret;
2227
2228 if (copy_from_user(&cmd, buf, sizeof cmd))
2229 return -EFAULT;
2230
2231 attr = kmalloc(sizeof *attr, GFP_KERNEL);
2232 init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL);
2233 if (!attr || !init_attr) {
2234 ret = -ENOMEM;
2235 goto out;
2236 }
2237
Roland Dreier9ead1902006-06-17 20:44:49 -07002238 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
2239 if (!qp) {
Dotan Barak7ccc9a22006-02-13 16:31:25 -08002240 ret = -EINVAL;
Roland Dreier9ead1902006-06-17 20:44:49 -07002241 goto out;
2242 }
Dotan Barak7ccc9a22006-02-13 16:31:25 -08002243
Roland Dreier9ead1902006-06-17 20:44:49 -07002244 ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr);
2245
2246 put_qp_read(qp);
Dotan Barak7ccc9a22006-02-13 16:31:25 -08002247
2248 if (ret)
2249 goto out;
2250
2251 memset(&resp, 0, sizeof resp);
2252
2253 resp.qp_state = attr->qp_state;
2254 resp.cur_qp_state = attr->cur_qp_state;
2255 resp.path_mtu = attr->path_mtu;
2256 resp.path_mig_state = attr->path_mig_state;
2257 resp.qkey = attr->qkey;
2258 resp.rq_psn = attr->rq_psn;
2259 resp.sq_psn = attr->sq_psn;
2260 resp.dest_qp_num = attr->dest_qp_num;
2261 resp.qp_access_flags = attr->qp_access_flags;
2262 resp.pkey_index = attr->pkey_index;
2263 resp.alt_pkey_index = attr->alt_pkey_index;
Jack Morgenstein0b26c882006-10-25 12:54:20 +02002264 resp.sq_draining = attr->sq_draining;
Dotan Barak7ccc9a22006-02-13 16:31:25 -08002265 resp.max_rd_atomic = attr->max_rd_atomic;
2266 resp.max_dest_rd_atomic = attr->max_dest_rd_atomic;
2267 resp.min_rnr_timer = attr->min_rnr_timer;
2268 resp.port_num = attr->port_num;
2269 resp.timeout = attr->timeout;
2270 resp.retry_cnt = attr->retry_cnt;
2271 resp.rnr_retry = attr->rnr_retry;
2272 resp.alt_port_num = attr->alt_port_num;
2273 resp.alt_timeout = attr->alt_timeout;
2274
2275 memcpy(resp.dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
2276 resp.dest.flow_label = attr->ah_attr.grh.flow_label;
2277 resp.dest.sgid_index = attr->ah_attr.grh.sgid_index;
2278 resp.dest.hop_limit = attr->ah_attr.grh.hop_limit;
2279 resp.dest.traffic_class = attr->ah_attr.grh.traffic_class;
2280 resp.dest.dlid = attr->ah_attr.dlid;
2281 resp.dest.sl = attr->ah_attr.sl;
2282 resp.dest.src_path_bits = attr->ah_attr.src_path_bits;
2283 resp.dest.static_rate = attr->ah_attr.static_rate;
2284 resp.dest.is_global = !!(attr->ah_attr.ah_flags & IB_AH_GRH);
2285 resp.dest.port_num = attr->ah_attr.port_num;
2286
2287 memcpy(resp.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
2288 resp.alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label;
2289 resp.alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index;
2290 resp.alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit;
2291 resp.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
2292 resp.alt_dest.dlid = attr->alt_ah_attr.dlid;
2293 resp.alt_dest.sl = attr->alt_ah_attr.sl;
2294 resp.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
2295 resp.alt_dest.static_rate = attr->alt_ah_attr.static_rate;
2296 resp.alt_dest.is_global = !!(attr->alt_ah_attr.ah_flags & IB_AH_GRH);
2297 resp.alt_dest.port_num = attr->alt_ah_attr.port_num;
2298
2299 resp.max_send_wr = init_attr->cap.max_send_wr;
2300 resp.max_recv_wr = init_attr->cap.max_recv_wr;
2301 resp.max_send_sge = init_attr->cap.max_send_sge;
2302 resp.max_recv_sge = init_attr->cap.max_recv_sge;
2303 resp.max_inline_data = init_attr->cap.max_inline_data;
Dotan Barak27d56302006-03-02 11:25:27 -08002304 resp.sq_sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
Dotan Barak7ccc9a22006-02-13 16:31:25 -08002305
2306 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2307 &resp, sizeof resp))
2308 ret = -EFAULT;
2309
2310out:
2311 kfree(attr);
2312 kfree(init_attr);
2313
2314 return ret ? ret : in_len;
2315}
2316
Sean Hefty9977f4f2011-05-26 08:17:04 -07002317/* Remove ignored fields set in the attribute mask */
2318static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
2319{
2320 switch (qp_type) {
2321 case IB_QPT_XRC_INI:
2322 return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
Sean Heftyb93f3c12011-05-27 00:00:12 -07002323 case IB_QPT_XRC_TGT:
2324 return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
2325 IB_QP_RNR_RETRY);
Sean Hefty9977f4f2011-05-26 08:17:04 -07002326 default:
2327 return mask;
2328 }
2329}
2330
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002331ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002332 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002333 const char __user *buf, int in_len,
2334 int out_len)
2335{
2336 struct ib_uverbs_modify_qp cmd;
Ralph Campbell9bc57e22006-08-11 14:58:09 -07002337 struct ib_udata udata;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002338 struct ib_qp *qp;
2339 struct ib_qp_attr *attr;
2340 int ret;
2341
2342 if (copy_from_user(&cmd, buf, sizeof cmd))
2343 return -EFAULT;
2344
Ralph Campbell9bc57e22006-08-11 14:58:09 -07002345 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
2346 out_len);
2347
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002348 attr = kmalloc(sizeof *attr, GFP_KERNEL);
2349 if (!attr)
2350 return -ENOMEM;
2351
Roland Dreier9ead1902006-06-17 20:44:49 -07002352 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
2353 if (!qp) {
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002354 ret = -EINVAL;
2355 goto out;
2356 }
2357
2358 attr->qp_state = cmd.qp_state;
2359 attr->cur_qp_state = cmd.cur_qp_state;
2360 attr->path_mtu = cmd.path_mtu;
2361 attr->path_mig_state = cmd.path_mig_state;
2362 attr->qkey = cmd.qkey;
2363 attr->rq_psn = cmd.rq_psn;
2364 attr->sq_psn = cmd.sq_psn;
2365 attr->dest_qp_num = cmd.dest_qp_num;
2366 attr->qp_access_flags = cmd.qp_access_flags;
2367 attr->pkey_index = cmd.pkey_index;
Ami Perlmutter702b2aa2006-03-20 10:08:24 -08002368 attr->alt_pkey_index = cmd.alt_pkey_index;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002369 attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
2370 attr->max_rd_atomic = cmd.max_rd_atomic;
2371 attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic;
2372 attr->min_rnr_timer = cmd.min_rnr_timer;
2373 attr->port_num = cmd.port_num;
2374 attr->timeout = cmd.timeout;
2375 attr->retry_cnt = cmd.retry_cnt;
2376 attr->rnr_retry = cmd.rnr_retry;
2377 attr->alt_port_num = cmd.alt_port_num;
2378 attr->alt_timeout = cmd.alt_timeout;
2379
2380 memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
2381 attr->ah_attr.grh.flow_label = cmd.dest.flow_label;
2382 attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index;
2383 attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit;
2384 attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class;
2385 attr->ah_attr.dlid = cmd.dest.dlid;
2386 attr->ah_attr.sl = cmd.dest.sl;
2387 attr->ah_attr.src_path_bits = cmd.dest.src_path_bits;
2388 attr->ah_attr.static_rate = cmd.dest.static_rate;
2389 attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0;
2390 attr->ah_attr.port_num = cmd.dest.port_num;
2391
2392 memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
2393 attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label;
2394 attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index;
2395 attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit;
2396 attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
2397 attr->alt_ah_attr.dlid = cmd.alt_dest.dlid;
2398 attr->alt_ah_attr.sl = cmd.alt_dest.sl;
2399 attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits;
2400 attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate;
2401 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
2402 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
2403
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002404 if (qp->real_qp == qp) {
Matan Barakdbf727d2015-10-15 18:38:51 +03002405 ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
Or Gerlitzed4c54e2013-12-12 18:03:17 +02002406 if (ret)
Moshe Lazer0fb8bcf2015-02-05 13:53:52 +02002407 goto release_qp;
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002408 ret = qp->device->modify_qp(qp, attr,
2409 modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
2410 } else {
2411 ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
2412 }
Roland Dreier9ead1902006-06-17 20:44:49 -07002413
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002414 if (ret)
Moshe Lazer0fb8bcf2015-02-05 13:53:52 +02002415 goto release_qp;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002416
2417 ret = in_len;
2418
Moshe Lazer0fb8bcf2015-02-05 13:53:52 +02002419release_qp:
2420 put_qp_read(qp);
2421
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002422out:
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002423 kfree(attr);
2424
2425 return ret;
2426}
2427
2428ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002429 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002430 const char __user *buf, int in_len,
2431 int out_len)
2432{
Roland Dreier63aaf642005-09-09 15:55:08 -07002433 struct ib_uverbs_destroy_qp cmd;
2434 struct ib_uverbs_destroy_qp_resp resp;
Roland Dreier9ead1902006-06-17 20:44:49 -07002435 struct ib_uobject *uobj;
Roland Dreier63aaf642005-09-09 15:55:08 -07002436 struct ib_qp *qp;
Roland Dreier9ead1902006-06-17 20:44:49 -07002437 struct ib_uqp_object *obj;
Roland Dreier63aaf642005-09-09 15:55:08 -07002438 int ret = -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002439
2440 if (copy_from_user(&cmd, buf, sizeof cmd))
2441 return -EFAULT;
2442
Roland Dreier63aaf642005-09-09 15:55:08 -07002443 memset(&resp, 0, sizeof resp);
2444
Roland Dreier9ead1902006-06-17 20:44:49 -07002445 uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext);
2446 if (!uobj)
2447 return -EINVAL;
2448 qp = uobj->object;
2449 obj = container_of(uobj, struct ib_uqp_object, uevent.uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002450
Roland Dreier9ead1902006-06-17 20:44:49 -07002451 if (!list_empty(&obj->mcast_list)) {
2452 put_uobj_write(uobj);
2453 return -EBUSY;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08002454 }
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002455
2456 ret = ib_destroy_qp(qp);
Roland Dreier9ead1902006-06-17 20:44:49 -07002457 if (!ret)
2458 uobj->live = 0;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002459
Roland Dreier9ead1902006-06-17 20:44:49 -07002460 put_uobj_write(uobj);
2461
2462 if (ret)
2463 return ret;
2464
Yishai Hadas846be902013-08-01 18:49:54 +03002465 if (obj->uxrcd)
2466 atomic_dec(&obj->uxrcd->refcnt);
2467
Roland Dreier9ead1902006-06-17 20:44:49 -07002468 idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002469
Ingo Molnar95ed6442006-01-13 14:51:39 -08002470 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07002471 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08002472 mutex_unlock(&file->mutex);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002473
Roland Dreier9ead1902006-06-17 20:44:49 -07002474 ib_uverbs_release_uevent(file, &obj->uevent);
Roland Dreier63aaf642005-09-09 15:55:08 -07002475
Roland Dreier9ead1902006-06-17 20:44:49 -07002476 resp.events_reported = obj->uevent.events_reported;
Roland Dreier63aaf642005-09-09 15:55:08 -07002477
Roland Dreier9ead1902006-06-17 20:44:49 -07002478 put_uobj(uobj);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002479
Roland Dreier63aaf642005-09-09 15:55:08 -07002480 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2481 &resp, sizeof resp))
Roland Dreier9ead1902006-06-17 20:44:49 -07002482 return -EFAULT;
Roland Dreier63aaf642005-09-09 15:55:08 -07002483
Roland Dreier9ead1902006-06-17 20:44:49 -07002484 return in_len;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002485}
2486
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002487static void *alloc_wr(size_t wr_size, __u32 num_sge)
2488{
2489 return kmalloc(ALIGN(wr_size, sizeof (struct ib_sge)) +
2490 num_sge * sizeof (struct ib_sge), GFP_KERNEL);
2491};
2492
Roland Dreier67cdb402005-10-14 15:26:04 -07002493ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002494 struct ib_device *ib_dev,
Roland Dreiera74cd4a2006-02-13 16:30:49 -08002495 const char __user *buf, int in_len,
2496 int out_len)
Roland Dreier67cdb402005-10-14 15:26:04 -07002497{
2498 struct ib_uverbs_post_send cmd;
2499 struct ib_uverbs_post_send_resp resp;
2500 struct ib_uverbs_send_wr *user_wr;
2501 struct ib_send_wr *wr = NULL, *last, *next, *bad_wr;
2502 struct ib_qp *qp;
2503 int i, sg_ind;
Roland Dreier9ead1902006-06-17 20:44:49 -07002504 int is_ud;
Roland Dreier67cdb402005-10-14 15:26:04 -07002505 ssize_t ret = -EINVAL;
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002506 size_t next_size;
Roland Dreier67cdb402005-10-14 15:26:04 -07002507
2508 if (copy_from_user(&cmd, buf, sizeof cmd))
2509 return -EFAULT;
2510
2511 if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count +
2512 cmd.sge_count * sizeof (struct ib_uverbs_sge))
2513 return -EINVAL;
2514
2515 if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr))
2516 return -EINVAL;
2517
2518 user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL);
2519 if (!user_wr)
2520 return -ENOMEM;
2521
Roland Dreier9ead1902006-06-17 20:44:49 -07002522 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
2523 if (!qp)
Roland Dreier67cdb402005-10-14 15:26:04 -07002524 goto out;
2525
Roland Dreier9ead1902006-06-17 20:44:49 -07002526 is_ud = qp->qp_type == IB_QPT_UD;
Roland Dreier67cdb402005-10-14 15:26:04 -07002527 sg_ind = 0;
2528 last = NULL;
2529 for (i = 0; i < cmd.wr_count; ++i) {
2530 if (copy_from_user(user_wr,
2531 buf + sizeof cmd + i * cmd.wqe_size,
2532 cmd.wqe_size)) {
2533 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -07002534 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002535 }
2536
2537 if (user_wr->num_sge + sg_ind > cmd.sge_count) {
2538 ret = -EINVAL;
Roland Dreier9ead1902006-06-17 20:44:49 -07002539 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002540 }
2541
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002542 if (is_ud) {
2543 struct ib_ud_wr *ud;
2544
2545 if (user_wr->opcode != IB_WR_SEND &&
2546 user_wr->opcode != IB_WR_SEND_WITH_IMM) {
2547 ret = -EINVAL;
2548 goto out_put;
2549 }
2550
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002551 next_size = sizeof(*ud);
2552 ud = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002553 if (!ud) {
2554 ret = -ENOMEM;
2555 goto out_put;
2556 }
2557
2558 ud->ah = idr_read_ah(user_wr->wr.ud.ah, file->ucontext);
2559 if (!ud->ah) {
2560 kfree(ud);
2561 ret = -EINVAL;
2562 goto out_put;
2563 }
2564 ud->remote_qpn = user_wr->wr.ud.remote_qpn;
2565 ud->remote_qkey = user_wr->wr.ud.remote_qkey;
2566
2567 next = &ud->wr;
2568 } else if (user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
2569 user_wr->opcode == IB_WR_RDMA_WRITE ||
2570 user_wr->opcode == IB_WR_RDMA_READ) {
2571 struct ib_rdma_wr *rdma;
2572
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002573 next_size = sizeof(*rdma);
2574 rdma = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002575 if (!rdma) {
2576 ret = -ENOMEM;
2577 goto out_put;
2578 }
2579
2580 rdma->remote_addr = user_wr->wr.rdma.remote_addr;
2581 rdma->rkey = user_wr->wr.rdma.rkey;
2582
2583 next = &rdma->wr;
2584 } else if (user_wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
2585 user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
2586 struct ib_atomic_wr *atomic;
2587
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002588 next_size = sizeof(*atomic);
2589 atomic = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002590 if (!atomic) {
2591 ret = -ENOMEM;
2592 goto out_put;
2593 }
2594
2595 atomic->remote_addr = user_wr->wr.atomic.remote_addr;
2596 atomic->compare_add = user_wr->wr.atomic.compare_add;
2597 atomic->swap = user_wr->wr.atomic.swap;
2598 atomic->rkey = user_wr->wr.atomic.rkey;
2599
2600 next = &atomic->wr;
2601 } else if (user_wr->opcode == IB_WR_SEND ||
2602 user_wr->opcode == IB_WR_SEND_WITH_IMM ||
2603 user_wr->opcode == IB_WR_SEND_WITH_INV) {
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002604 next_size = sizeof(*next);
2605 next = alloc_wr(next_size, user_wr->num_sge);
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002606 if (!next) {
2607 ret = -ENOMEM;
2608 goto out_put;
2609 }
2610 } else {
2611 ret = -EINVAL;
Roland Dreier9ead1902006-06-17 20:44:49 -07002612 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002613 }
2614
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002615 if (user_wr->opcode == IB_WR_SEND_WITH_IMM ||
2616 user_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
2617 next->ex.imm_data =
2618 (__be32 __force) user_wr->ex.imm_data;
2619 } else if (user_wr->opcode == IB_WR_SEND_WITH_INV) {
2620 next->ex.invalidate_rkey = user_wr->ex.invalidate_rkey;
2621 }
2622
Roland Dreier67cdb402005-10-14 15:26:04 -07002623 if (!last)
2624 wr = next;
2625 else
2626 last->next = next;
2627 last = next;
2628
2629 next->next = NULL;
2630 next->wr_id = user_wr->wr_id;
2631 next->num_sge = user_wr->num_sge;
2632 next->opcode = user_wr->opcode;
2633 next->send_flags = user_wr->send_flags;
Roland Dreier67cdb402005-10-14 15:26:04 -07002634
Roland Dreier67cdb402005-10-14 15:26:04 -07002635 if (next->num_sge) {
2636 next->sg_list = (void *) next +
Mike Marciniszyn1d784b82015-12-01 10:13:51 -05002637 ALIGN(next_size, sizeof(struct ib_sge));
Roland Dreier67cdb402005-10-14 15:26:04 -07002638 if (copy_from_user(next->sg_list,
2639 buf + sizeof cmd +
2640 cmd.wr_count * cmd.wqe_size +
2641 sg_ind * sizeof (struct ib_sge),
2642 next->num_sge * sizeof (struct ib_sge))) {
2643 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -07002644 goto out_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002645 }
2646 sg_ind += next->num_sge;
2647 } else
2648 next->sg_list = NULL;
2649 }
2650
2651 resp.bad_wr = 0;
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002652 ret = qp->device->post_send(qp->real_qp, wr, &bad_wr);
Roland Dreier67cdb402005-10-14 15:26:04 -07002653 if (ret)
2654 for (next = wr; next; next = next->next) {
2655 ++resp.bad_wr;
2656 if (next == bad_wr)
2657 break;
2658 }
2659
2660 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2661 &resp, sizeof resp))
2662 ret = -EFAULT;
2663
Roland Dreier9ead1902006-06-17 20:44:49 -07002664out_put:
2665 put_qp_read(qp);
Roland Dreier67cdb402005-10-14 15:26:04 -07002666
2667 while (wr) {
Christoph Hellwige622f2f2015-10-08 09:16:33 +01002668 if (is_ud && ud_wr(wr)->ah)
2669 put_ah_read(ud_wr(wr)->ah);
Roland Dreier67cdb402005-10-14 15:26:04 -07002670 next = wr->next;
2671 kfree(wr);
2672 wr = next;
2673 }
2674
Krishna Kumar18320822006-06-22 07:47:27 -07002675out:
Roland Dreier67cdb402005-10-14 15:26:04 -07002676 kfree(user_wr);
2677
2678 return ret ? ret : in_len;
2679}
2680
2681static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf,
2682 int in_len,
2683 u32 wr_count,
2684 u32 sge_count,
2685 u32 wqe_size)
2686{
2687 struct ib_uverbs_recv_wr *user_wr;
2688 struct ib_recv_wr *wr = NULL, *last, *next;
2689 int sg_ind;
2690 int i;
2691 int ret;
2692
2693 if (in_len < wqe_size * wr_count +
2694 sge_count * sizeof (struct ib_uverbs_sge))
2695 return ERR_PTR(-EINVAL);
2696
2697 if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
2698 return ERR_PTR(-EINVAL);
2699
2700 user_wr = kmalloc(wqe_size, GFP_KERNEL);
2701 if (!user_wr)
2702 return ERR_PTR(-ENOMEM);
2703
2704 sg_ind = 0;
2705 last = NULL;
2706 for (i = 0; i < wr_count; ++i) {
2707 if (copy_from_user(user_wr, buf + i * wqe_size,
2708 wqe_size)) {
2709 ret = -EFAULT;
2710 goto err;
2711 }
2712
2713 if (user_wr->num_sge + sg_ind > sge_count) {
2714 ret = -EINVAL;
2715 goto err;
2716 }
2717
2718 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
2719 user_wr->num_sge * sizeof (struct ib_sge),
2720 GFP_KERNEL);
2721 if (!next) {
2722 ret = -ENOMEM;
2723 goto err;
2724 }
2725
2726 if (!last)
2727 wr = next;
2728 else
2729 last->next = next;
2730 last = next;
2731
2732 next->next = NULL;
2733 next->wr_id = user_wr->wr_id;
2734 next->num_sge = user_wr->num_sge;
2735
2736 if (next->num_sge) {
2737 next->sg_list = (void *) next +
2738 ALIGN(sizeof *next, sizeof (struct ib_sge));
2739 if (copy_from_user(next->sg_list,
2740 buf + wr_count * wqe_size +
2741 sg_ind * sizeof (struct ib_sge),
2742 next->num_sge * sizeof (struct ib_sge))) {
2743 ret = -EFAULT;
2744 goto err;
2745 }
2746 sg_ind += next->num_sge;
2747 } else
2748 next->sg_list = NULL;
2749 }
2750
2751 kfree(user_wr);
2752 return wr;
2753
2754err:
2755 kfree(user_wr);
2756
2757 while (wr) {
2758 next = wr->next;
2759 kfree(wr);
2760 wr = next;
2761 }
2762
2763 return ERR_PTR(ret);
2764}
2765
2766ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002767 struct ib_device *ib_dev,
Roland Dreiera74cd4a2006-02-13 16:30:49 -08002768 const char __user *buf, int in_len,
2769 int out_len)
Roland Dreier67cdb402005-10-14 15:26:04 -07002770{
2771 struct ib_uverbs_post_recv cmd;
2772 struct ib_uverbs_post_recv_resp resp;
2773 struct ib_recv_wr *wr, *next, *bad_wr;
2774 struct ib_qp *qp;
2775 ssize_t ret = -EINVAL;
2776
2777 if (copy_from_user(&cmd, buf, sizeof cmd))
2778 return -EFAULT;
2779
2780 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
2781 in_len - sizeof cmd, cmd.wr_count,
2782 cmd.sge_count, cmd.wqe_size);
2783 if (IS_ERR(wr))
2784 return PTR_ERR(wr);
2785
Roland Dreier9ead1902006-06-17 20:44:49 -07002786 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
2787 if (!qp)
Roland Dreier67cdb402005-10-14 15:26:04 -07002788 goto out;
2789
2790 resp.bad_wr = 0;
Sean Hefty0e0ec7e2011-08-08 15:31:51 -07002791 ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr);
Roland Dreier9ead1902006-06-17 20:44:49 -07002792
2793 put_qp_read(qp);
2794
Roland Dreier67cdb402005-10-14 15:26:04 -07002795 if (ret)
2796 for (next = wr; next; next = next->next) {
2797 ++resp.bad_wr;
2798 if (next == bad_wr)
2799 break;
2800 }
2801
Roland Dreier67cdb402005-10-14 15:26:04 -07002802 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2803 &resp, sizeof resp))
2804 ret = -EFAULT;
2805
2806out:
Roland Dreier67cdb402005-10-14 15:26:04 -07002807 while (wr) {
2808 next = wr->next;
2809 kfree(wr);
2810 wr = next;
2811 }
2812
2813 return ret ? ret : in_len;
2814}
2815
2816ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002817 struct ib_device *ib_dev,
Roland Dreiera74cd4a2006-02-13 16:30:49 -08002818 const char __user *buf, int in_len,
2819 int out_len)
Roland Dreier67cdb402005-10-14 15:26:04 -07002820{
2821 struct ib_uverbs_post_srq_recv cmd;
2822 struct ib_uverbs_post_srq_recv_resp resp;
2823 struct ib_recv_wr *wr, *next, *bad_wr;
2824 struct ib_srq *srq;
2825 ssize_t ret = -EINVAL;
2826
2827 if (copy_from_user(&cmd, buf, sizeof cmd))
2828 return -EFAULT;
2829
2830 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,
2831 in_len - sizeof cmd, cmd.wr_count,
2832 cmd.sge_count, cmd.wqe_size);
2833 if (IS_ERR(wr))
2834 return PTR_ERR(wr);
2835
Roland Dreier9ead1902006-06-17 20:44:49 -07002836 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
2837 if (!srq)
Roland Dreier67cdb402005-10-14 15:26:04 -07002838 goto out;
2839
2840 resp.bad_wr = 0;
2841 ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
Roland Dreier9ead1902006-06-17 20:44:49 -07002842
2843 put_srq_read(srq);
2844
Roland Dreier67cdb402005-10-14 15:26:04 -07002845 if (ret)
2846 for (next = wr; next; next = next->next) {
2847 ++resp.bad_wr;
2848 if (next == bad_wr)
2849 break;
2850 }
2851
Roland Dreier67cdb402005-10-14 15:26:04 -07002852 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2853 &resp, sizeof resp))
2854 ret = -EFAULT;
2855
2856out:
Roland Dreier67cdb402005-10-14 15:26:04 -07002857 while (wr) {
2858 next = wr->next;
2859 kfree(wr);
2860 wr = next;
2861 }
2862
2863 return ret ? ret : in_len;
2864}
2865
2866ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002867 struct ib_device *ib_dev,
Roland Dreier67cdb402005-10-14 15:26:04 -07002868 const char __user *buf, int in_len,
2869 int out_len)
2870{
2871 struct ib_uverbs_create_ah cmd;
2872 struct ib_uverbs_create_ah_resp resp;
2873 struct ib_uobject *uobj;
2874 struct ib_pd *pd;
2875 struct ib_ah *ah;
2876 struct ib_ah_attr attr;
2877 int ret;
2878
2879 if (out_len < sizeof resp)
2880 return -ENOSPC;
2881
2882 if (copy_from_user(&cmd, buf, sizeof cmd))
2883 return -EFAULT;
2884
2885 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
2886 if (!uobj)
2887 return -ENOMEM;
2888
Roland Dreier3bea57a2012-04-30 10:27:26 -07002889 init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_class);
Roland Dreier9ead1902006-06-17 20:44:49 -07002890 down_write(&uobj->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002891
Roland Dreier9ead1902006-06-17 20:44:49 -07002892 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
2893 if (!pd) {
Roland Dreier67cdb402005-10-14 15:26:04 -07002894 ret = -EINVAL;
Roland Dreier9ead1902006-06-17 20:44:49 -07002895 goto err;
Roland Dreier67cdb402005-10-14 15:26:04 -07002896 }
2897
Roland Dreier67cdb402005-10-14 15:26:04 -07002898 attr.dlid = cmd.attr.dlid;
2899 attr.sl = cmd.attr.sl;
2900 attr.src_path_bits = cmd.attr.src_path_bits;
2901 attr.static_rate = cmd.attr.static_rate;
Ralph Campbellea5d4a62006-01-06 16:24:45 -08002902 attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0;
Roland Dreier67cdb402005-10-14 15:26:04 -07002903 attr.port_num = cmd.attr.port_num;
2904 attr.grh.flow_label = cmd.attr.grh.flow_label;
2905 attr.grh.sgid_index = cmd.attr.grh.sgid_index;
2906 attr.grh.hop_limit = cmd.attr.grh.hop_limit;
2907 attr.grh.traffic_class = cmd.attr.grh.traffic_class;
Devesh Sharma8b0f93d2014-09-26 20:45:32 +05302908 memset(&attr.dmac, 0, sizeof(attr.dmac));
Roland Dreier67cdb402005-10-14 15:26:04 -07002909 memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
2910
2911 ah = ib_create_ah(pd, &attr);
2912 if (IS_ERR(ah)) {
2913 ret = PTR_ERR(ah);
Michael S. Tsirkinec924b42006-07-17 18:20:51 +03002914 goto err_put;
Roland Dreier67cdb402005-10-14 15:26:04 -07002915 }
2916
Roland Dreier9ead1902006-06-17 20:44:49 -07002917 ah->uobject = uobj;
2918 uobj->object = ah;
Roland Dreier67cdb402005-10-14 15:26:04 -07002919
Roland Dreier9ead1902006-06-17 20:44:49 -07002920 ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002921 if (ret)
2922 goto err_destroy;
2923
2924 resp.ah_handle = uobj->id;
2925
2926 if (copy_to_user((void __user *) (unsigned long) cmd.response,
2927 &resp, sizeof resp)) {
2928 ret = -EFAULT;
Roland Dreier9ead1902006-06-17 20:44:49 -07002929 goto err_copy;
Roland Dreier67cdb402005-10-14 15:26:04 -07002930 }
2931
Roland Dreier9ead1902006-06-17 20:44:49 -07002932 put_pd_read(pd);
2933
Ingo Molnar95ed6442006-01-13 14:51:39 -08002934 mutex_lock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002935 list_add_tail(&uobj->list, &file->ucontext->ah_list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08002936 mutex_unlock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002937
Roland Dreier9ead1902006-06-17 20:44:49 -07002938 uobj->live = 1;
2939
2940 up_write(&uobj->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002941
2942 return in_len;
2943
Roland Dreier9ead1902006-06-17 20:44:49 -07002944err_copy:
2945 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002946
2947err_destroy:
2948 ib_destroy_ah(ah);
2949
Michael S. Tsirkinec924b42006-07-17 18:20:51 +03002950err_put:
2951 put_pd_read(pd);
2952
Roland Dreier9ead1902006-06-17 20:44:49 -07002953err:
2954 put_uobj_write(uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002955 return ret;
2956}
2957
2958ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002959 struct ib_device *ib_dev,
Roland Dreier67cdb402005-10-14 15:26:04 -07002960 const char __user *buf, int in_len, int out_len)
2961{
2962 struct ib_uverbs_destroy_ah cmd;
2963 struct ib_ah *ah;
2964 struct ib_uobject *uobj;
Roland Dreier9ead1902006-06-17 20:44:49 -07002965 int ret;
Roland Dreier67cdb402005-10-14 15:26:04 -07002966
2967 if (copy_from_user(&cmd, buf, sizeof cmd))
2968 return -EFAULT;
2969
Roland Dreier9ead1902006-06-17 20:44:49 -07002970 uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext);
2971 if (!uobj)
2972 return -EINVAL;
2973 ah = uobj->object;
Roland Dreier67cdb402005-10-14 15:26:04 -07002974
2975 ret = ib_destroy_ah(ah);
Roland Dreier9ead1902006-06-17 20:44:49 -07002976 if (!ret)
2977 uobj->live = 0;
Roland Dreier67cdb402005-10-14 15:26:04 -07002978
Roland Dreier9ead1902006-06-17 20:44:49 -07002979 put_uobj_write(uobj);
2980
2981 if (ret)
2982 return ret;
2983
2984 idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002985
Ingo Molnar95ed6442006-01-13 14:51:39 -08002986 mutex_lock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002987 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08002988 mutex_unlock(&file->mutex);
Roland Dreier67cdb402005-10-14 15:26:04 -07002989
Roland Dreier9ead1902006-06-17 20:44:49 -07002990 put_uobj(uobj);
Roland Dreier67cdb402005-10-14 15:26:04 -07002991
Roland Dreier9ead1902006-06-17 20:44:49 -07002992 return in_len;
Roland Dreier67cdb402005-10-14 15:26:04 -07002993}
2994
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002995ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03002996 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07002997 const char __user *buf, int in_len,
2998 int out_len)
2999{
3000 struct ib_uverbs_attach_mcast cmd;
3001 struct ib_qp *qp;
Roland Dreier9ead1902006-06-17 20:44:49 -07003002 struct ib_uqp_object *obj;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003003 struct ib_uverbs_mcast_entry *mcast;
Roland Dreier9ead1902006-06-17 20:44:49 -07003004 int ret;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003005
3006 if (copy_from_user(&cmd, buf, sizeof cmd))
3007 return -EFAULT;
3008
Eli Cohene214a0f2012-01-03 20:36:48 -08003009 qp = idr_write_qp(cmd.qp_handle, file->ucontext);
Roland Dreier9ead1902006-06-17 20:44:49 -07003010 if (!qp)
3011 return -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003012
Roland Dreier9ead1902006-06-17 20:44:49 -07003013 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003014
Roland Dreier9ead1902006-06-17 20:44:49 -07003015 list_for_each_entry(mcast, &obj->mcast_list, list)
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003016 if (cmd.mlid == mcast->lid &&
3017 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
3018 ret = 0;
Roland Dreier9ead1902006-06-17 20:44:49 -07003019 goto out_put;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003020 }
3021
3022 mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
3023 if (!mcast) {
3024 ret = -ENOMEM;
Roland Dreier9ead1902006-06-17 20:44:49 -07003025 goto out_put;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003026 }
3027
3028 mcast->lid = cmd.mlid;
3029 memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);
3030
3031 ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);
Roland Dreier9ead1902006-06-17 20:44:49 -07003032 if (!ret)
3033 list_add_tail(&mcast->list, &obj->mcast_list);
3034 else
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003035 kfree(mcast);
3036
Roland Dreier9ead1902006-06-17 20:44:49 -07003037out_put:
Eli Cohene214a0f2012-01-03 20:36:48 -08003038 put_qp_write(qp);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003039
3040 return ret ? ret : in_len;
3041}
3042
3043ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003044 struct ib_device *ib_dev,
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003045 const char __user *buf, int in_len,
3046 int out_len)
3047{
3048 struct ib_uverbs_detach_mcast cmd;
Roland Dreier9ead1902006-06-17 20:44:49 -07003049 struct ib_uqp_object *obj;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003050 struct ib_qp *qp;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003051 struct ib_uverbs_mcast_entry *mcast;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003052 int ret = -EINVAL;
3053
3054 if (copy_from_user(&cmd, buf, sizeof cmd))
3055 return -EFAULT;
3056
Eli Cohene214a0f2012-01-03 20:36:48 -08003057 qp = idr_write_qp(cmd.qp_handle, file->ucontext);
Roland Dreier9ead1902006-06-17 20:44:49 -07003058 if (!qp)
3059 return -EINVAL;
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003060
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003061 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
3062 if (ret)
Roland Dreier9ead1902006-06-17 20:44:49 -07003063 goto out_put;
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003064
Roland Dreier9ead1902006-06-17 20:44:49 -07003065 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003066
Roland Dreier9ead1902006-06-17 20:44:49 -07003067 list_for_each_entry(mcast, &obj->mcast_list, list)
Jack Morgensteinf4e40152005-11-29 16:57:01 -08003068 if (cmd.mlid == mcast->lid &&
3069 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
3070 list_del(&mcast->list);
3071 kfree(mcast);
3072 break;
3073 }
3074
Roland Dreier9ead1902006-06-17 20:44:49 -07003075out_put:
Eli Cohene214a0f2012-01-03 20:36:48 -08003076 put_qp_write(qp);
Roland Dreierbc38a6a2005-07-07 17:57:13 -07003077
3078 return ret ? ret : in_len;
3079}
Roland Dreierf520ba52005-08-18 12:24:13 -07003080
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003081static size_t kern_spec_filter_sz(struct ib_uverbs_flow_spec_hdr *spec)
3082{
3083 /* Returns user space filter size, includes padding */
3084 return (spec->size - sizeof(struct ib_uverbs_flow_spec_hdr)) / 2;
3085}
3086
3087static ssize_t spec_filter_size(void *kern_spec_filter, u16 kern_filter_size,
3088 u16 ib_real_filter_sz)
3089{
3090 /*
3091 * User space filter structures must be 64 bit aligned, otherwise this
3092 * may pass, but we won't handle additional new attributes.
3093 */
3094
3095 if (kern_filter_size > ib_real_filter_sz) {
3096 if (memchr_inv(kern_spec_filter +
3097 ib_real_filter_sz, 0,
3098 kern_filter_size - ib_real_filter_sz))
3099 return -EINVAL;
3100 return ib_real_filter_sz;
3101 }
3102 return kern_filter_size;
3103}
3104
Yann Droneaudb68c9562013-11-06 23:21:46 +01003105static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003106 union ib_flow_spec *ib_spec)
3107{
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003108 ssize_t actual_filter_sz;
3109 ssize_t kern_filter_sz;
3110 ssize_t ib_filter_sz;
3111 void *kern_spec_mask;
3112 void *kern_spec_val;
3113
Yann Droneaudc780d822013-12-11 23:01:49 +01003114 if (kern_spec->reserved)
3115 return -EINVAL;
3116
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003117 ib_spec->type = kern_spec->type;
3118
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003119 kern_filter_sz = kern_spec_filter_sz(&kern_spec->hdr);
3120 /* User flow spec size must be aligned to 4 bytes */
3121 if (kern_filter_sz != ALIGN(kern_filter_sz, 4))
3122 return -EINVAL;
3123
3124 kern_spec_val = (void *)kern_spec +
3125 sizeof(struct ib_uverbs_flow_spec_hdr);
3126 kern_spec_mask = kern_spec_val + kern_filter_sz;
3127
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003128 switch (ib_spec->type) {
3129 case IB_FLOW_SPEC_ETH:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003130 ib_filter_sz = offsetof(struct ib_flow_eth_filter, real_sz);
3131 actual_filter_sz = spec_filter_size(kern_spec_mask,
3132 kern_filter_sz,
3133 ib_filter_sz);
3134 if (actual_filter_sz <= 0)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003135 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003136 ib_spec->size = sizeof(struct ib_flow_spec_eth);
3137 memcpy(&ib_spec->eth.val, kern_spec_val, actual_filter_sz);
3138 memcpy(&ib_spec->eth.mask, kern_spec_mask, actual_filter_sz);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003139 break;
3140 case IB_FLOW_SPEC_IPV4:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003141 ib_filter_sz = offsetof(struct ib_flow_ipv4_filter, real_sz);
3142 actual_filter_sz = spec_filter_size(kern_spec_mask,
3143 kern_filter_sz,
3144 ib_filter_sz);
3145 if (actual_filter_sz <= 0)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003146 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003147 ib_spec->size = sizeof(struct ib_flow_spec_ipv4);
3148 memcpy(&ib_spec->ipv4.val, kern_spec_val, actual_filter_sz);
3149 memcpy(&ib_spec->ipv4.mask, kern_spec_mask, actual_filter_sz);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003150 break;
Maor Gottlieb4c2aae72016-06-17 15:14:50 +03003151 case IB_FLOW_SPEC_IPV6:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003152 ib_filter_sz = offsetof(struct ib_flow_ipv6_filter, real_sz);
3153 actual_filter_sz = spec_filter_size(kern_spec_mask,
3154 kern_filter_sz,
3155 ib_filter_sz);
3156 if (actual_filter_sz <= 0)
Maor Gottlieb4c2aae72016-06-17 15:14:50 +03003157 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003158 ib_spec->size = sizeof(struct ib_flow_spec_ipv6);
3159 memcpy(&ib_spec->ipv6.val, kern_spec_val, actual_filter_sz);
3160 memcpy(&ib_spec->ipv6.mask, kern_spec_mask, actual_filter_sz);
Maor Gottlieb4c2aae72016-06-17 15:14:50 +03003161 break;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003162 case IB_FLOW_SPEC_TCP:
3163 case IB_FLOW_SPEC_UDP:
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003164 ib_filter_sz = offsetof(struct ib_flow_tcp_udp_filter, real_sz);
3165 actual_filter_sz = spec_filter_size(kern_spec_mask,
3166 kern_filter_sz,
3167 ib_filter_sz);
3168 if (actual_filter_sz <= 0)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003169 return -EINVAL;
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003170 ib_spec->size = sizeof(struct ib_flow_spec_tcp_udp);
3171 memcpy(&ib_spec->tcp_udp.val, kern_spec_val, actual_filter_sz);
3172 memcpy(&ib_spec->tcp_udp.mask, kern_spec_mask, actual_filter_sz);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003173 break;
3174 default:
3175 return -EINVAL;
3176 }
3177 return 0;
3178}
3179
Yishai Hadasf213c052016-05-23 15:20:49 +03003180int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file,
3181 struct ib_device *ib_dev,
3182 struct ib_udata *ucore,
3183 struct ib_udata *uhw)
3184{
3185 struct ib_uverbs_ex_create_wq cmd = {};
3186 struct ib_uverbs_ex_create_wq_resp resp = {};
3187 struct ib_uwq_object *obj;
3188 int err = 0;
3189 struct ib_cq *cq;
3190 struct ib_pd *pd;
3191 struct ib_wq *wq;
3192 struct ib_wq_init_attr wq_init_attr = {};
3193 size_t required_cmd_sz;
3194 size_t required_resp_len;
3195
3196 required_cmd_sz = offsetof(typeof(cmd), max_sge) + sizeof(cmd.max_sge);
3197 required_resp_len = offsetof(typeof(resp), wqn) + sizeof(resp.wqn);
3198
3199 if (ucore->inlen < required_cmd_sz)
3200 return -EINVAL;
3201
3202 if (ucore->outlen < required_resp_len)
3203 return -ENOSPC;
3204
3205 if (ucore->inlen > sizeof(cmd) &&
3206 !ib_is_udata_cleared(ucore, sizeof(cmd),
3207 ucore->inlen - sizeof(cmd)))
3208 return -EOPNOTSUPP;
3209
3210 err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3211 if (err)
3212 return err;
3213
3214 if (cmd.comp_mask)
3215 return -EOPNOTSUPP;
3216
3217 obj = kmalloc(sizeof(*obj), GFP_KERNEL);
3218 if (!obj)
3219 return -ENOMEM;
3220
3221 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext,
3222 &wq_lock_class);
3223 down_write(&obj->uevent.uobject.mutex);
3224 pd = idr_read_pd(cmd.pd_handle, file->ucontext);
3225 if (!pd) {
3226 err = -EINVAL;
3227 goto err_uobj;
3228 }
3229
3230 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
3231 if (!cq) {
3232 err = -EINVAL;
3233 goto err_put_pd;
3234 }
3235
3236 wq_init_attr.cq = cq;
3237 wq_init_attr.max_sge = cmd.max_sge;
3238 wq_init_attr.max_wr = cmd.max_wr;
3239 wq_init_attr.wq_context = file;
3240 wq_init_attr.wq_type = cmd.wq_type;
3241 wq_init_attr.event_handler = ib_uverbs_wq_event_handler;
3242 obj->uevent.events_reported = 0;
3243 INIT_LIST_HEAD(&obj->uevent.event_list);
3244 wq = pd->device->create_wq(pd, &wq_init_attr, uhw);
3245 if (IS_ERR(wq)) {
3246 err = PTR_ERR(wq);
3247 goto err_put_cq;
3248 }
3249
3250 wq->uobject = &obj->uevent.uobject;
3251 obj->uevent.uobject.object = wq;
3252 wq->wq_type = wq_init_attr.wq_type;
3253 wq->cq = cq;
3254 wq->pd = pd;
3255 wq->device = pd->device;
3256 wq->wq_context = wq_init_attr.wq_context;
3257 atomic_set(&wq->usecnt, 0);
3258 atomic_inc(&pd->usecnt);
3259 atomic_inc(&cq->usecnt);
3260 wq->uobject = &obj->uevent.uobject;
3261 obj->uevent.uobject.object = wq;
3262 err = idr_add_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject);
3263 if (err)
3264 goto destroy_wq;
3265
3266 memset(&resp, 0, sizeof(resp));
3267 resp.wq_handle = obj->uevent.uobject.id;
3268 resp.max_sge = wq_init_attr.max_sge;
3269 resp.max_wr = wq_init_attr.max_wr;
3270 resp.wqn = wq->wq_num;
3271 resp.response_length = required_resp_len;
3272 err = ib_copy_to_udata(ucore,
3273 &resp, resp.response_length);
3274 if (err)
3275 goto err_copy;
3276
3277 put_pd_read(pd);
3278 put_cq_read(cq);
3279
3280 mutex_lock(&file->mutex);
3281 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->wq_list);
3282 mutex_unlock(&file->mutex);
3283
3284 obj->uevent.uobject.live = 1;
3285 up_write(&obj->uevent.uobject.mutex);
3286 return 0;
3287
3288err_copy:
3289 idr_remove_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject);
3290destroy_wq:
3291 ib_destroy_wq(wq);
3292err_put_cq:
3293 put_cq_read(cq);
3294err_put_pd:
3295 put_pd_read(pd);
3296err_uobj:
3297 put_uobj_write(&obj->uevent.uobject);
3298
3299 return err;
3300}
3301
3302int ib_uverbs_ex_destroy_wq(struct ib_uverbs_file *file,
3303 struct ib_device *ib_dev,
3304 struct ib_udata *ucore,
3305 struct ib_udata *uhw)
3306{
3307 struct ib_uverbs_ex_destroy_wq cmd = {};
3308 struct ib_uverbs_ex_destroy_wq_resp resp = {};
3309 struct ib_wq *wq;
3310 struct ib_uobject *uobj;
3311 struct ib_uwq_object *obj;
3312 size_t required_cmd_sz;
3313 size_t required_resp_len;
3314 int ret;
3315
3316 required_cmd_sz = offsetof(typeof(cmd), wq_handle) + sizeof(cmd.wq_handle);
3317 required_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
3318
3319 if (ucore->inlen < required_cmd_sz)
3320 return -EINVAL;
3321
3322 if (ucore->outlen < required_resp_len)
3323 return -ENOSPC;
3324
3325 if (ucore->inlen > sizeof(cmd) &&
3326 !ib_is_udata_cleared(ucore, sizeof(cmd),
3327 ucore->inlen - sizeof(cmd)))
3328 return -EOPNOTSUPP;
3329
3330 ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3331 if (ret)
3332 return ret;
3333
3334 if (cmd.comp_mask)
3335 return -EOPNOTSUPP;
3336
3337 resp.response_length = required_resp_len;
3338 uobj = idr_write_uobj(&ib_uverbs_wq_idr, cmd.wq_handle,
3339 file->ucontext);
3340 if (!uobj)
3341 return -EINVAL;
3342
3343 wq = uobj->object;
3344 obj = container_of(uobj, struct ib_uwq_object, uevent.uobject);
3345 ret = ib_destroy_wq(wq);
3346 if (!ret)
3347 uobj->live = 0;
3348
3349 put_uobj_write(uobj);
3350 if (ret)
3351 return ret;
3352
3353 idr_remove_uobj(&ib_uverbs_wq_idr, uobj);
3354
3355 mutex_lock(&file->mutex);
3356 list_del(&uobj->list);
3357 mutex_unlock(&file->mutex);
3358
3359 ib_uverbs_release_uevent(file, &obj->uevent);
3360 resp.events_reported = obj->uevent.events_reported;
3361 put_uobj(uobj);
3362
3363 ret = ib_copy_to_udata(ucore, &resp, resp.response_length);
3364 if (ret)
3365 return ret;
3366
3367 return 0;
3368}
3369
3370int ib_uverbs_ex_modify_wq(struct ib_uverbs_file *file,
3371 struct ib_device *ib_dev,
3372 struct ib_udata *ucore,
3373 struct ib_udata *uhw)
3374{
3375 struct ib_uverbs_ex_modify_wq cmd = {};
3376 struct ib_wq *wq;
3377 struct ib_wq_attr wq_attr = {};
3378 size_t required_cmd_sz;
3379 int ret;
3380
3381 required_cmd_sz = offsetof(typeof(cmd), curr_wq_state) + sizeof(cmd.curr_wq_state);
3382 if (ucore->inlen < required_cmd_sz)
3383 return -EINVAL;
3384
3385 if (ucore->inlen > sizeof(cmd) &&
3386 !ib_is_udata_cleared(ucore, sizeof(cmd),
3387 ucore->inlen - sizeof(cmd)))
3388 return -EOPNOTSUPP;
3389
3390 ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3391 if (ret)
3392 return ret;
3393
3394 if (!cmd.attr_mask)
3395 return -EINVAL;
3396
3397 if (cmd.attr_mask > (IB_WQ_STATE | IB_WQ_CUR_STATE))
3398 return -EINVAL;
3399
3400 wq = idr_read_wq(cmd.wq_handle, file->ucontext);
3401 if (!wq)
3402 return -EINVAL;
3403
3404 wq_attr.curr_wq_state = cmd.curr_wq_state;
3405 wq_attr.wq_state = cmd.wq_state;
3406 ret = wq->device->modify_wq(wq, &wq_attr, cmd.attr_mask, uhw);
3407 put_wq_read(wq);
3408 return ret;
3409}
3410
Yishai Hadasde019a92016-05-23 15:20:52 +03003411int ib_uverbs_ex_create_rwq_ind_table(struct ib_uverbs_file *file,
3412 struct ib_device *ib_dev,
3413 struct ib_udata *ucore,
3414 struct ib_udata *uhw)
3415{
3416 struct ib_uverbs_ex_create_rwq_ind_table cmd = {};
3417 struct ib_uverbs_ex_create_rwq_ind_table_resp resp = {};
3418 struct ib_uobject *uobj;
3419 int err = 0;
3420 struct ib_rwq_ind_table_init_attr init_attr = {};
3421 struct ib_rwq_ind_table *rwq_ind_tbl;
3422 struct ib_wq **wqs = NULL;
3423 u32 *wqs_handles = NULL;
3424 struct ib_wq *wq = NULL;
3425 int i, j, num_read_wqs;
3426 u32 num_wq_handles;
3427 u32 expected_in_size;
3428 size_t required_cmd_sz_header;
3429 size_t required_resp_len;
3430
3431 required_cmd_sz_header = offsetof(typeof(cmd), log_ind_tbl_size) + sizeof(cmd.log_ind_tbl_size);
3432 required_resp_len = offsetof(typeof(resp), ind_tbl_num) + sizeof(resp.ind_tbl_num);
3433
3434 if (ucore->inlen < required_cmd_sz_header)
3435 return -EINVAL;
3436
3437 if (ucore->outlen < required_resp_len)
3438 return -ENOSPC;
3439
3440 err = ib_copy_from_udata(&cmd, ucore, required_cmd_sz_header);
3441 if (err)
3442 return err;
3443
3444 ucore->inbuf += required_cmd_sz_header;
3445 ucore->inlen -= required_cmd_sz_header;
3446
3447 if (cmd.comp_mask)
3448 return -EOPNOTSUPP;
3449
3450 if (cmd.log_ind_tbl_size > IB_USER_VERBS_MAX_LOG_IND_TBL_SIZE)
3451 return -EINVAL;
3452
3453 num_wq_handles = 1 << cmd.log_ind_tbl_size;
3454 expected_in_size = num_wq_handles * sizeof(__u32);
3455 if (num_wq_handles == 1)
3456 /* input size for wq handles is u64 aligned */
3457 expected_in_size += sizeof(__u32);
3458
3459 if (ucore->inlen < expected_in_size)
3460 return -EINVAL;
3461
3462 if (ucore->inlen > expected_in_size &&
3463 !ib_is_udata_cleared(ucore, expected_in_size,
3464 ucore->inlen - expected_in_size))
3465 return -EOPNOTSUPP;
3466
3467 wqs_handles = kcalloc(num_wq_handles, sizeof(*wqs_handles),
3468 GFP_KERNEL);
3469 if (!wqs_handles)
3470 return -ENOMEM;
3471
3472 err = ib_copy_from_udata(wqs_handles, ucore,
3473 num_wq_handles * sizeof(__u32));
3474 if (err)
3475 goto err_free;
3476
3477 wqs = kcalloc(num_wq_handles, sizeof(*wqs), GFP_KERNEL);
3478 if (!wqs) {
3479 err = -ENOMEM;
3480 goto err_free;
3481 }
3482
3483 for (num_read_wqs = 0; num_read_wqs < num_wq_handles;
3484 num_read_wqs++) {
3485 wq = idr_read_wq(wqs_handles[num_read_wqs], file->ucontext);
3486 if (!wq) {
3487 err = -EINVAL;
3488 goto put_wqs;
3489 }
3490
3491 wqs[num_read_wqs] = wq;
3492 }
3493
3494 uobj = kmalloc(sizeof(*uobj), GFP_KERNEL);
3495 if (!uobj) {
3496 err = -ENOMEM;
3497 goto put_wqs;
3498 }
3499
3500 init_uobj(uobj, 0, file->ucontext, &rwq_ind_table_lock_class);
3501 down_write(&uobj->mutex);
3502 init_attr.log_ind_tbl_size = cmd.log_ind_tbl_size;
3503 init_attr.ind_tbl = wqs;
3504 rwq_ind_tbl = ib_dev->create_rwq_ind_table(ib_dev, &init_attr, uhw);
3505
3506 if (IS_ERR(rwq_ind_tbl)) {
3507 err = PTR_ERR(rwq_ind_tbl);
3508 goto err_uobj;
3509 }
3510
3511 rwq_ind_tbl->ind_tbl = wqs;
3512 rwq_ind_tbl->log_ind_tbl_size = init_attr.log_ind_tbl_size;
3513 rwq_ind_tbl->uobject = uobj;
3514 uobj->object = rwq_ind_tbl;
3515 rwq_ind_tbl->device = ib_dev;
3516 atomic_set(&rwq_ind_tbl->usecnt, 0);
3517
3518 for (i = 0; i < num_wq_handles; i++)
3519 atomic_inc(&wqs[i]->usecnt);
3520
3521 err = idr_add_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
3522 if (err)
3523 goto destroy_ind_tbl;
3524
3525 resp.ind_tbl_handle = uobj->id;
3526 resp.ind_tbl_num = rwq_ind_tbl->ind_tbl_num;
3527 resp.response_length = required_resp_len;
3528
3529 err = ib_copy_to_udata(ucore,
3530 &resp, resp.response_length);
3531 if (err)
3532 goto err_copy;
3533
3534 kfree(wqs_handles);
3535
3536 for (j = 0; j < num_read_wqs; j++)
3537 put_wq_read(wqs[j]);
3538
3539 mutex_lock(&file->mutex);
3540 list_add_tail(&uobj->list, &file->ucontext->rwq_ind_tbl_list);
3541 mutex_unlock(&file->mutex);
3542
3543 uobj->live = 1;
3544
3545 up_write(&uobj->mutex);
3546 return 0;
3547
3548err_copy:
3549 idr_remove_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
3550destroy_ind_tbl:
3551 ib_destroy_rwq_ind_table(rwq_ind_tbl);
3552err_uobj:
3553 put_uobj_write(uobj);
3554put_wqs:
3555 for (j = 0; j < num_read_wqs; j++)
3556 put_wq_read(wqs[j]);
3557err_free:
3558 kfree(wqs_handles);
3559 kfree(wqs);
3560 return err;
3561}
3562
3563int ib_uverbs_ex_destroy_rwq_ind_table(struct ib_uverbs_file *file,
3564 struct ib_device *ib_dev,
3565 struct ib_udata *ucore,
3566 struct ib_udata *uhw)
3567{
3568 struct ib_uverbs_ex_destroy_rwq_ind_table cmd = {};
3569 struct ib_rwq_ind_table *rwq_ind_tbl;
3570 struct ib_uobject *uobj;
3571 int ret;
3572 struct ib_wq **ind_tbl;
3573 size_t required_cmd_sz;
3574
3575 required_cmd_sz = offsetof(typeof(cmd), ind_tbl_handle) + sizeof(cmd.ind_tbl_handle);
3576
3577 if (ucore->inlen < required_cmd_sz)
3578 return -EINVAL;
3579
3580 if (ucore->inlen > sizeof(cmd) &&
3581 !ib_is_udata_cleared(ucore, sizeof(cmd),
3582 ucore->inlen - sizeof(cmd)))
3583 return -EOPNOTSUPP;
3584
3585 ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
3586 if (ret)
3587 return ret;
3588
3589 if (cmd.comp_mask)
3590 return -EOPNOTSUPP;
3591
3592 uobj = idr_write_uobj(&ib_uverbs_rwq_ind_tbl_idr, cmd.ind_tbl_handle,
3593 file->ucontext);
3594 if (!uobj)
3595 return -EINVAL;
3596 rwq_ind_tbl = uobj->object;
3597 ind_tbl = rwq_ind_tbl->ind_tbl;
3598
3599 ret = ib_destroy_rwq_ind_table(rwq_ind_tbl);
3600 if (!ret)
3601 uobj->live = 0;
3602
3603 put_uobj_write(uobj);
3604
3605 if (ret)
3606 return ret;
3607
3608 idr_remove_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
3609
3610 mutex_lock(&file->mutex);
3611 list_del(&uobj->list);
3612 mutex_unlock(&file->mutex);
3613
3614 put_uobj(uobj);
3615 kfree(ind_tbl);
3616 return ret;
3617}
3618
Yann Droneaudf21519b2013-11-06 23:21:49 +01003619int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003620 struct ib_device *ib_dev,
Yann Droneaudf21519b2013-11-06 23:21:49 +01003621 struct ib_udata *ucore,
3622 struct ib_udata *uhw)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003623{
3624 struct ib_uverbs_create_flow cmd;
3625 struct ib_uverbs_create_flow_resp resp;
3626 struct ib_uobject *uobj;
3627 struct ib_flow *flow_id;
Yann Droneaudd82693d2013-11-06 23:21:45 +01003628 struct ib_uverbs_flow_attr *kern_flow_attr;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003629 struct ib_flow_attr *flow_attr;
3630 struct ib_qp *qp;
3631 int err = 0;
3632 void *kern_spec;
3633 void *ib_spec;
3634 int i;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003635
Yann Droneaud6bcca3d2013-12-11 23:01:52 +01003636 if (ucore->inlen < sizeof(cmd))
3637 return -EINVAL;
3638
Yann Droneaudf21519b2013-11-06 23:21:49 +01003639 if (ucore->outlen < sizeof(resp))
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003640 return -ENOSPC;
3641
Yann Droneaudf21519b2013-11-06 23:21:49 +01003642 err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
3643 if (err)
3644 return err;
3645
3646 ucore->inbuf += sizeof(cmd);
3647 ucore->inlen -= sizeof(cmd);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003648
Matan Barak22878db2013-09-01 18:39:52 +03003649 if (cmd.comp_mask)
3650 return -EINVAL;
3651
Christoph Lametere3b6d8c2016-05-13 10:52:26 -05003652 if (!capable(CAP_NET_RAW))
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003653 return -EPERM;
3654
Marina Varshavera3100a72016-02-18 18:31:05 +02003655 if (cmd.flow_attr.flags >= IB_FLOW_ATTR_FLAGS_RESERVED)
3656 return -EINVAL;
3657
3658 if ((cmd.flow_attr.flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) &&
3659 ((cmd.flow_attr.type == IB_FLOW_ATTR_ALL_DEFAULT) ||
3660 (cmd.flow_attr.type == IB_FLOW_ATTR_MC_DEFAULT)))
3661 return -EINVAL;
3662
Matan Barakf8848272013-11-06 23:21:44 +01003663 if (cmd.flow_attr.num_of_specs > IB_FLOW_SPEC_SUPPORT_LAYERS)
Matan Barak22878db2013-09-01 18:39:52 +03003664 return -EINVAL;
3665
Yann Droneaudf21519b2013-11-06 23:21:49 +01003666 if (cmd.flow_attr.size > ucore->inlen ||
Matan Barakf8848272013-11-06 23:21:44 +01003667 cmd.flow_attr.size >
Yann Droneaudb68c9562013-11-06 23:21:46 +01003668 (cmd.flow_attr.num_of_specs * sizeof(struct ib_uverbs_flow_spec)))
Matan Barak22878db2013-09-01 18:39:52 +03003669 return -EINVAL;
3670
Yann Droneaudc780d822013-12-11 23:01:49 +01003671 if (cmd.flow_attr.reserved[0] ||
3672 cmd.flow_attr.reserved[1])
3673 return -EINVAL;
3674
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003675 if (cmd.flow_attr.num_of_specs) {
Matan Barakf8848272013-11-06 23:21:44 +01003676 kern_flow_attr = kmalloc(sizeof(*kern_flow_attr) + cmd.flow_attr.size,
3677 GFP_KERNEL);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003678 if (!kern_flow_attr)
3679 return -ENOMEM;
3680
3681 memcpy(kern_flow_attr, &cmd.flow_attr, sizeof(*kern_flow_attr));
Yann Droneaudf21519b2013-11-06 23:21:49 +01003682 err = ib_copy_from_udata(kern_flow_attr + 1, ucore,
3683 cmd.flow_attr.size);
3684 if (err)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003685 goto err_free_attr;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003686 } else {
3687 kern_flow_attr = &cmd.flow_attr;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003688 }
3689
3690 uobj = kmalloc(sizeof(*uobj), GFP_KERNEL);
3691 if (!uobj) {
3692 err = -ENOMEM;
3693 goto err_free_attr;
3694 }
3695 init_uobj(uobj, 0, file->ucontext, &rule_lock_class);
3696 down_write(&uobj->mutex);
3697
3698 qp = idr_read_qp(cmd.qp_handle, file->ucontext);
3699 if (!qp) {
3700 err = -EINVAL;
3701 goto err_uobj;
3702 }
3703
Maor Gottlieb15dfbd62016-08-30 16:58:32 +03003704 flow_attr = kzalloc(sizeof(*flow_attr) + cmd.flow_attr.num_of_specs *
3705 sizeof(union ib_flow_spec), GFP_KERNEL);
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003706 if (!flow_attr) {
3707 err = -ENOMEM;
3708 goto err_put;
3709 }
3710
3711 flow_attr->type = kern_flow_attr->type;
3712 flow_attr->priority = kern_flow_attr->priority;
3713 flow_attr->num_of_specs = kern_flow_attr->num_of_specs;
3714 flow_attr->port = kern_flow_attr->port;
3715 flow_attr->flags = kern_flow_attr->flags;
3716 flow_attr->size = sizeof(*flow_attr);
3717
3718 kern_spec = kern_flow_attr + 1;
3719 ib_spec = flow_attr + 1;
Matan Barakf8848272013-11-06 23:21:44 +01003720 for (i = 0; i < flow_attr->num_of_specs &&
Yann Droneaudb68c9562013-11-06 23:21:46 +01003721 cmd.flow_attr.size > offsetof(struct ib_uverbs_flow_spec, reserved) &&
Matan Barakf8848272013-11-06 23:21:44 +01003722 cmd.flow_attr.size >=
Yann Droneaudb68c9562013-11-06 23:21:46 +01003723 ((struct ib_uverbs_flow_spec *)kern_spec)->size; i++) {
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003724 err = kern_spec_to_ib_spec(kern_spec, ib_spec);
3725 if (err)
3726 goto err_free;
3727 flow_attr->size +=
3728 ((union ib_flow_spec *) ib_spec)->size;
Yann Droneaudb68c9562013-11-06 23:21:46 +01003729 cmd.flow_attr.size -= ((struct ib_uverbs_flow_spec *)kern_spec)->size;
3730 kern_spec += ((struct ib_uverbs_flow_spec *) kern_spec)->size;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003731 ib_spec += ((union ib_flow_spec *) ib_spec)->size;
3732 }
Matan Barakf8848272013-11-06 23:21:44 +01003733 if (cmd.flow_attr.size || (i != flow_attr->num_of_specs)) {
3734 pr_warn("create flow failed, flow %d: %d bytes left from uverb cmd\n",
3735 i, cmd.flow_attr.size);
Yann Droneaud98a37512013-12-11 23:01:50 +01003736 err = -EINVAL;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003737 goto err_free;
3738 }
3739 flow_id = ib_create_flow(qp, flow_attr, IB_FLOW_DOMAIN_USER);
3740 if (IS_ERR(flow_id)) {
3741 err = PTR_ERR(flow_id);
3742 goto err_free;
3743 }
3744 flow_id->qp = qp;
3745 flow_id->uobject = uobj;
3746 uobj->object = flow_id;
3747
3748 err = idr_add_uobj(&ib_uverbs_rule_idr, uobj);
3749 if (err)
3750 goto destroy_flow;
3751
3752 memset(&resp, 0, sizeof(resp));
3753 resp.flow_handle = uobj->id;
3754
Yann Droneaudf21519b2013-11-06 23:21:49 +01003755 err = ib_copy_to_udata(ucore,
3756 &resp, sizeof(resp));
3757 if (err)
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003758 goto err_copy;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003759
3760 put_qp_read(qp);
3761 mutex_lock(&file->mutex);
3762 list_add_tail(&uobj->list, &file->ucontext->rule_list);
3763 mutex_unlock(&file->mutex);
3764
3765 uobj->live = 1;
3766
3767 up_write(&uobj->mutex);
3768 kfree(flow_attr);
3769 if (cmd.flow_attr.num_of_specs)
3770 kfree(kern_flow_attr);
Yann Droneaudf21519b2013-11-06 23:21:49 +01003771 return 0;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003772err_copy:
3773 idr_remove_uobj(&ib_uverbs_rule_idr, uobj);
3774destroy_flow:
3775 ib_destroy_flow(flow_id);
3776err_free:
3777 kfree(flow_attr);
3778err_put:
3779 put_qp_read(qp);
3780err_uobj:
3781 put_uobj_write(uobj);
3782err_free_attr:
3783 if (cmd.flow_attr.num_of_specs)
3784 kfree(kern_flow_attr);
3785 return err;
3786}
3787
Yann Droneaudf21519b2013-11-06 23:21:49 +01003788int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003789 struct ib_device *ib_dev,
Yann Droneaudf21519b2013-11-06 23:21:49 +01003790 struct ib_udata *ucore,
3791 struct ib_udata *uhw)
3792{
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003793 struct ib_uverbs_destroy_flow cmd;
3794 struct ib_flow *flow_id;
3795 struct ib_uobject *uobj;
3796 int ret;
3797
Yann Droneaud6bcca3d2013-12-11 23:01:52 +01003798 if (ucore->inlen < sizeof(cmd))
3799 return -EINVAL;
3800
Yann Droneaudf21519b2013-11-06 23:21:49 +01003801 ret = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
3802 if (ret)
3803 return ret;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003804
Yann Droneaud2782c2d2013-12-11 23:01:48 +01003805 if (cmd.comp_mask)
3806 return -EINVAL;
3807
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003808 uobj = idr_write_uobj(&ib_uverbs_rule_idr, cmd.flow_handle,
3809 file->ucontext);
3810 if (!uobj)
3811 return -EINVAL;
3812 flow_id = uobj->object;
3813
3814 ret = ib_destroy_flow(flow_id);
3815 if (!ret)
3816 uobj->live = 0;
3817
3818 put_uobj_write(uobj);
3819
3820 idr_remove_uobj(&ib_uverbs_rule_idr, uobj);
3821
3822 mutex_lock(&file->mutex);
3823 list_del(&uobj->list);
3824 mutex_unlock(&file->mutex);
3825
3826 put_uobj(uobj);
3827
Yann Droneaudf21519b2013-11-06 23:21:49 +01003828 return ret;
Hadar Hen Zion436f2ad2013-08-14 13:58:30 +03003829}
3830
Sean Heftyc89d1be2011-12-06 21:13:10 +00003831static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003832 struct ib_device *ib_dev,
Sean Heftyc89d1be2011-12-06 21:13:10 +00003833 struct ib_uverbs_create_xsrq *cmd,
3834 struct ib_udata *udata)
Sean Hefty8541f8d2011-05-25 17:08:38 -07003835{
3836 struct ib_uverbs_create_srq_resp resp;
3837 struct ib_usrq_object *obj;
3838 struct ib_pd *pd;
3839 struct ib_srq *srq;
3840 struct ib_uobject *uninitialized_var(xrcd_uobj);
3841 struct ib_srq_init_attr attr;
3842 int ret;
3843
3844 obj = kmalloc(sizeof *obj, GFP_KERNEL);
3845 if (!obj)
3846 return -ENOMEM;
3847
Roland Dreier3bea57a2012-04-30 10:27:26 -07003848 init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_class);
Sean Hefty8541f8d2011-05-25 17:08:38 -07003849 down_write(&obj->uevent.uobject.mutex);
3850
Sean Hefty8541f8d2011-05-25 17:08:38 -07003851 if (cmd->srq_type == IB_SRQT_XRC) {
Sean Hefty8541f8d2011-05-25 17:08:38 -07003852 attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
3853 if (!attr.ext.xrc.xrcd) {
3854 ret = -EINVAL;
Roland Dreier5909ce52012-04-30 12:51:50 -07003855 goto err;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003856 }
3857
3858 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
3859 atomic_inc(&obj->uxrcd->refcnt);
Roland Dreier5909ce52012-04-30 12:51:50 -07003860
3861 attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
3862 if (!attr.ext.xrc.cq) {
3863 ret = -EINVAL;
3864 goto err_put_xrcd;
3865 }
3866 }
3867
3868 pd = idr_read_pd(cmd->pd_handle, file->ucontext);
3869 if (!pd) {
3870 ret = -EINVAL;
3871 goto err_put_cq;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003872 }
3873
3874 attr.event_handler = ib_uverbs_srq_event_handler;
3875 attr.srq_context = file;
3876 attr.srq_type = cmd->srq_type;
3877 attr.attr.max_wr = cmd->max_wr;
3878 attr.attr.max_sge = cmd->max_sge;
3879 attr.attr.srq_limit = cmd->srq_limit;
3880
3881 obj->uevent.events_reported = 0;
3882 INIT_LIST_HEAD(&obj->uevent.event_list);
3883
3884 srq = pd->device->create_srq(pd, &attr, udata);
3885 if (IS_ERR(srq)) {
3886 ret = PTR_ERR(srq);
3887 goto err_put;
3888 }
3889
3890 srq->device = pd->device;
3891 srq->pd = pd;
3892 srq->srq_type = cmd->srq_type;
3893 srq->uobject = &obj->uevent.uobject;
3894 srq->event_handler = attr.event_handler;
3895 srq->srq_context = attr.srq_context;
3896
3897 if (cmd->srq_type == IB_SRQT_XRC) {
3898 srq->ext.xrc.cq = attr.ext.xrc.cq;
3899 srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
3900 atomic_inc(&attr.ext.xrc.cq->usecnt);
3901 atomic_inc(&attr.ext.xrc.xrcd->usecnt);
3902 }
3903
3904 atomic_inc(&pd->usecnt);
3905 atomic_set(&srq->usecnt, 0);
3906
3907 obj->uevent.uobject.object = srq;
3908 ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
3909 if (ret)
3910 goto err_destroy;
3911
3912 memset(&resp, 0, sizeof resp);
3913 resp.srq_handle = obj->uevent.uobject.id;
3914 resp.max_wr = attr.attr.max_wr;
3915 resp.max_sge = attr.attr.max_sge;
3916 if (cmd->srq_type == IB_SRQT_XRC)
3917 resp.srqn = srq->ext.xrc.srq_num;
3918
3919 if (copy_to_user((void __user *) (unsigned long) cmd->response,
3920 &resp, sizeof resp)) {
3921 ret = -EFAULT;
3922 goto err_copy;
3923 }
3924
3925 if (cmd->srq_type == IB_SRQT_XRC) {
3926 put_uobj_read(xrcd_uobj);
3927 put_cq_read(attr.ext.xrc.cq);
3928 }
3929 put_pd_read(pd);
3930
3931 mutex_lock(&file->mutex);
3932 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
3933 mutex_unlock(&file->mutex);
3934
3935 obj->uevent.uobject.live = 1;
3936
3937 up_write(&obj->uevent.uobject.mutex);
3938
3939 return 0;
3940
3941err_copy:
3942 idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
3943
3944err_destroy:
3945 ib_destroy_srq(srq);
3946
3947err_put:
Roland Dreier5909ce52012-04-30 12:51:50 -07003948 put_pd_read(pd);
Sean Hefty8541f8d2011-05-25 17:08:38 -07003949
3950err_put_cq:
3951 if (cmd->srq_type == IB_SRQT_XRC)
3952 put_cq_read(attr.ext.xrc.cq);
3953
Roland Dreier5909ce52012-04-30 12:51:50 -07003954err_put_xrcd:
3955 if (cmd->srq_type == IB_SRQT_XRC) {
3956 atomic_dec(&obj->uxrcd->refcnt);
3957 put_uobj_read(xrcd_uobj);
3958 }
Sean Hefty8541f8d2011-05-25 17:08:38 -07003959
3960err:
3961 put_uobj_write(&obj->uevent.uobject);
3962 return ret;
3963}
3964
Roland Dreierf520ba52005-08-18 12:24:13 -07003965ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03003966 struct ib_device *ib_dev,
Roland Dreierf520ba52005-08-18 12:24:13 -07003967 const char __user *buf, int in_len,
3968 int out_len)
3969{
3970 struct ib_uverbs_create_srq cmd;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003971 struct ib_uverbs_create_xsrq xcmd;
Roland Dreierf520ba52005-08-18 12:24:13 -07003972 struct ib_uverbs_create_srq_resp resp;
3973 struct ib_udata udata;
Sean Hefty8541f8d2011-05-25 17:08:38 -07003974 int ret;
3975
3976 if (out_len < sizeof resp)
3977 return -ENOSPC;
3978
3979 if (copy_from_user(&cmd, buf, sizeof cmd))
3980 return -EFAULT;
3981
3982 xcmd.response = cmd.response;
3983 xcmd.user_handle = cmd.user_handle;
3984 xcmd.srq_type = IB_SRQT_BASIC;
3985 xcmd.pd_handle = cmd.pd_handle;
3986 xcmd.max_wr = cmd.max_wr;
3987 xcmd.max_sge = cmd.max_sge;
3988 xcmd.srq_limit = cmd.srq_limit;
3989
3990 INIT_UDATA(&udata, buf + sizeof cmd,
3991 (unsigned long) cmd.response + sizeof resp,
Majd Dibbiny3d943c92016-02-14 18:35:52 +02003992 in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
3993 out_len - sizeof resp);
Sean Hefty8541f8d2011-05-25 17:08:38 -07003994
Yishai Hadas057aec02015-08-13 18:32:04 +03003995 ret = __uverbs_create_xsrq(file, ib_dev, &xcmd, &udata);
Sean Hefty8541f8d2011-05-25 17:08:38 -07003996 if (ret)
3997 return ret;
3998
3999 return in_len;
4000}
4001
4002ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004003 struct ib_device *ib_dev,
Sean Hefty8541f8d2011-05-25 17:08:38 -07004004 const char __user *buf, int in_len, int out_len)
4005{
4006 struct ib_uverbs_create_xsrq cmd;
4007 struct ib_uverbs_create_srq_resp resp;
4008 struct ib_udata udata;
Roland Dreierf520ba52005-08-18 12:24:13 -07004009 int ret;
4010
4011 if (out_len < sizeof resp)
4012 return -ENOSPC;
4013
4014 if (copy_from_user(&cmd, buf, sizeof cmd))
4015 return -EFAULT;
4016
4017 INIT_UDATA(&udata, buf + sizeof cmd,
4018 (unsigned long) cmd.response + sizeof resp,
Majd Dibbiny3d943c92016-02-14 18:35:52 +02004019 in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
4020 out_len - sizeof resp);
Roland Dreierf520ba52005-08-18 12:24:13 -07004021
Yishai Hadas057aec02015-08-13 18:32:04 +03004022 ret = __uverbs_create_xsrq(file, ib_dev, &cmd, &udata);
Roland Dreierf520ba52005-08-18 12:24:13 -07004023 if (ret)
Sean Hefty8541f8d2011-05-25 17:08:38 -07004024 return ret;
Roland Dreierf520ba52005-08-18 12:24:13 -07004025
4026 return in_len;
Roland Dreierf520ba52005-08-18 12:24:13 -07004027}
4028
4029ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004030 struct ib_device *ib_dev,
Roland Dreierf520ba52005-08-18 12:24:13 -07004031 const char __user *buf, int in_len,
4032 int out_len)
4033{
4034 struct ib_uverbs_modify_srq cmd;
Ralph Campbell9bc57e22006-08-11 14:58:09 -07004035 struct ib_udata udata;
Roland Dreierf520ba52005-08-18 12:24:13 -07004036 struct ib_srq *srq;
4037 struct ib_srq_attr attr;
4038 int ret;
4039
4040 if (copy_from_user(&cmd, buf, sizeof cmd))
4041 return -EFAULT;
4042
Ralph Campbell9bc57e22006-08-11 14:58:09 -07004043 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
4044 out_len);
4045
Roland Dreier9ead1902006-06-17 20:44:49 -07004046 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
4047 if (!srq)
4048 return -EINVAL;
Roland Dreierf520ba52005-08-18 12:24:13 -07004049
4050 attr.max_wr = cmd.max_wr;
Roland Dreierf520ba52005-08-18 12:24:13 -07004051 attr.srq_limit = cmd.srq_limit;
4052
Ralph Campbell9bc57e22006-08-11 14:58:09 -07004053 ret = srq->device->modify_srq(srq, &attr, cmd.attr_mask, &udata);
Roland Dreierf520ba52005-08-18 12:24:13 -07004054
Roland Dreier9ead1902006-06-17 20:44:49 -07004055 put_srq_read(srq);
Roland Dreierf520ba52005-08-18 12:24:13 -07004056
4057 return ret ? ret : in_len;
4058}
4059
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004060ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004061 struct ib_device *ib_dev,
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004062 const char __user *buf,
4063 int in_len, int out_len)
4064{
4065 struct ib_uverbs_query_srq cmd;
4066 struct ib_uverbs_query_srq_resp resp;
4067 struct ib_srq_attr attr;
4068 struct ib_srq *srq;
4069 int ret;
4070
4071 if (out_len < sizeof resp)
4072 return -ENOSPC;
4073
4074 if (copy_from_user(&cmd, buf, sizeof cmd))
4075 return -EFAULT;
4076
Roland Dreier9ead1902006-06-17 20:44:49 -07004077 srq = idr_read_srq(cmd.srq_handle, file->ucontext);
4078 if (!srq)
4079 return -EINVAL;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004080
Roland Dreier9ead1902006-06-17 20:44:49 -07004081 ret = ib_query_srq(srq, &attr);
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004082
Roland Dreier9ead1902006-06-17 20:44:49 -07004083 put_srq_read(srq);
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004084
4085 if (ret)
Roland Dreier9ead1902006-06-17 20:44:49 -07004086 return ret;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004087
4088 memset(&resp, 0, sizeof resp);
4089
4090 resp.max_wr = attr.max_wr;
4091 resp.max_sge = attr.max_sge;
4092 resp.srq_limit = attr.srq_limit;
4093
4094 if (copy_to_user((void __user *) (unsigned long) cmd.response,
4095 &resp, sizeof resp))
Roland Dreier9ead1902006-06-17 20:44:49 -07004096 return -EFAULT;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004097
Roland Dreier9ead1902006-06-17 20:44:49 -07004098 return in_len;
Dotan Barak8bdb0e82006-02-13 16:31:57 -08004099}
4100
Roland Dreierf520ba52005-08-18 12:24:13 -07004101ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004102 struct ib_device *ib_dev,
Roland Dreierf520ba52005-08-18 12:24:13 -07004103 const char __user *buf, int in_len,
4104 int out_len)
4105{
Roland Dreier63aaf642005-09-09 15:55:08 -07004106 struct ib_uverbs_destroy_srq cmd;
4107 struct ib_uverbs_destroy_srq_resp resp;
Roland Dreier9ead1902006-06-17 20:44:49 -07004108 struct ib_uobject *uobj;
Roland Dreier63aaf642005-09-09 15:55:08 -07004109 struct ib_srq *srq;
Roland Dreier9ead1902006-06-17 20:44:49 -07004110 struct ib_uevent_object *obj;
Roland Dreier63aaf642005-09-09 15:55:08 -07004111 int ret = -EINVAL;
Yishai Hadas846be902013-08-01 18:49:54 +03004112 struct ib_usrq_object *us;
4113 enum ib_srq_type srq_type;
Roland Dreierf520ba52005-08-18 12:24:13 -07004114
4115 if (copy_from_user(&cmd, buf, sizeof cmd))
4116 return -EFAULT;
4117
Roland Dreier9ead1902006-06-17 20:44:49 -07004118 uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext);
4119 if (!uobj)
4120 return -EINVAL;
4121 srq = uobj->object;
4122 obj = container_of(uobj, struct ib_uevent_object, uobject);
Yishai Hadas846be902013-08-01 18:49:54 +03004123 srq_type = srq->srq_type;
Roland Dreierf520ba52005-08-18 12:24:13 -07004124
4125 ret = ib_destroy_srq(srq);
Roland Dreier9ead1902006-06-17 20:44:49 -07004126 if (!ret)
4127 uobj->live = 0;
Roland Dreierf520ba52005-08-18 12:24:13 -07004128
Roland Dreier9ead1902006-06-17 20:44:49 -07004129 put_uobj_write(uobj);
4130
4131 if (ret)
4132 return ret;
4133
Yishai Hadas846be902013-08-01 18:49:54 +03004134 if (srq_type == IB_SRQT_XRC) {
4135 us = container_of(obj, struct ib_usrq_object, uevent);
4136 atomic_dec(&us->uxrcd->refcnt);
4137 }
4138
Roland Dreier9ead1902006-06-17 20:44:49 -07004139 idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
Roland Dreierf520ba52005-08-18 12:24:13 -07004140
Ingo Molnar95ed6442006-01-13 14:51:39 -08004141 mutex_lock(&file->mutex);
Roland Dreier9ead1902006-06-17 20:44:49 -07004142 list_del(&uobj->list);
Ingo Molnar95ed6442006-01-13 14:51:39 -08004143 mutex_unlock(&file->mutex);
Roland Dreierf520ba52005-08-18 12:24:13 -07004144
Roland Dreier9ead1902006-06-17 20:44:49 -07004145 ib_uverbs_release_uevent(file, obj);
Roland Dreier63aaf642005-09-09 15:55:08 -07004146
Roland Dreier9ead1902006-06-17 20:44:49 -07004147 memset(&resp, 0, sizeof resp);
4148 resp.events_reported = obj->events_reported;
Roland Dreier63aaf642005-09-09 15:55:08 -07004149
Roland Dreier9ead1902006-06-17 20:44:49 -07004150 put_uobj(uobj);
Roland Dreierf520ba52005-08-18 12:24:13 -07004151
Roland Dreier63aaf642005-09-09 15:55:08 -07004152 if (copy_to_user((void __user *) (unsigned long) cmd.response,
4153 &resp, sizeof resp))
4154 ret = -EFAULT;
4155
Roland Dreierf520ba52005-08-18 12:24:13 -07004156 return ret ? ret : in_len;
4157}
Eli Cohen02d1aa72015-02-08 13:28:50 +02004158
4159int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
Yishai Hadas057aec02015-08-13 18:32:04 +03004160 struct ib_device *ib_dev,
Eli Cohen02d1aa72015-02-08 13:28:50 +02004161 struct ib_udata *ucore,
4162 struct ib_udata *uhw)
4163{
Leon Romanovsky2953f422016-02-23 10:25:24 +02004164 struct ib_uverbs_ex_query_device_resp resp = { {0} };
Eli Cohen02d1aa72015-02-08 13:28:50 +02004165 struct ib_uverbs_ex_query_device cmd;
Leon Romanovsky2953f422016-02-23 10:25:24 +02004166 struct ib_device_attr attr = {0};
Eli Cohen02d1aa72015-02-08 13:28:50 +02004167 int err;
4168
Eli Cohen02d1aa72015-02-08 13:28:50 +02004169 if (ucore->inlen < sizeof(cmd))
4170 return -EINVAL;
4171
4172 err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
4173 if (err)
4174 return err;
4175
4176 if (cmd.comp_mask)
4177 return -EINVAL;
4178
4179 if (cmd.reserved)
4180 return -EINVAL;
4181
Haggai Eranf4056bf2015-02-08 13:28:51 +02004182 resp.response_length = offsetof(typeof(resp), odp_caps);
Eli Cohen02d1aa72015-02-08 13:28:50 +02004183
4184 if (ucore->outlen < resp.response_length)
4185 return -ENOSPC;
4186
Yishai Hadas057aec02015-08-13 18:32:04 +03004187 err = ib_dev->query_device(ib_dev, &attr, uhw);
Eli Cohen02d1aa72015-02-08 13:28:50 +02004188 if (err)
4189 return err;
4190
Yishai Hadas057aec02015-08-13 18:32:04 +03004191 copy_query_dev_fields(file, ib_dev, &resp.base, &attr);
Eli Cohen02d1aa72015-02-08 13:28:50 +02004192
Haggai Eranf4056bf2015-02-08 13:28:51 +02004193 if (ucore->outlen < resp.response_length + sizeof(resp.odp_caps))
4194 goto end;
4195
4196#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
4197 resp.odp_caps.general_caps = attr.odp_caps.general_caps;
4198 resp.odp_caps.per_transport_caps.rc_odp_caps =
4199 attr.odp_caps.per_transport_caps.rc_odp_caps;
4200 resp.odp_caps.per_transport_caps.uc_odp_caps =
4201 attr.odp_caps.per_transport_caps.uc_odp_caps;
4202 resp.odp_caps.per_transport_caps.ud_odp_caps =
4203 attr.odp_caps.per_transport_caps.ud_odp_caps;
Haggai Eranf4056bf2015-02-08 13:28:51 +02004204#endif
4205 resp.response_length += sizeof(resp.odp_caps);
4206
Matan Barak24306dc2015-06-11 16:35:24 +03004207 if (ucore->outlen < resp.response_length + sizeof(resp.timestamp_mask))
4208 goto end;
4209
4210 resp.timestamp_mask = attr.timestamp_mask;
4211 resp.response_length += sizeof(resp.timestamp_mask);
4212
4213 if (ucore->outlen < resp.response_length + sizeof(resp.hca_core_clock))
4214 goto end;
4215
4216 resp.hca_core_clock = attr.hca_core_clock;
4217 resp.response_length += sizeof(resp.hca_core_clock);
4218
Majd Dibbiny0b24e5a2016-04-17 17:19:34 +03004219 if (ucore->outlen < resp.response_length + sizeof(resp.device_cap_flags_ex))
4220 goto end;
4221
4222 resp.device_cap_flags_ex = attr.device_cap_flags;
4223 resp.response_length += sizeof(resp.device_cap_flags_ex);
Yishai Hadas47adf2f2016-08-28 11:28:44 +03004224
4225 if (ucore->outlen < resp.response_length + sizeof(resp.rss_caps))
4226 goto end;
4227
4228 resp.rss_caps.supported_qpts = attr.rss_caps.supported_qpts;
4229 resp.rss_caps.max_rwq_indirection_tables =
4230 attr.rss_caps.max_rwq_indirection_tables;
4231 resp.rss_caps.max_rwq_indirection_table_size =
4232 attr.rss_caps.max_rwq_indirection_table_size;
4233
4234 resp.response_length += sizeof(resp.rss_caps);
4235
4236 if (ucore->outlen < resp.response_length + sizeof(resp.max_wq_type_rq))
4237 goto end;
4238
4239 resp.max_wq_type_rq = attr.max_wq_type_rq;
4240 resp.response_length += sizeof(resp.max_wq_type_rq);
Haggai Eranf4056bf2015-02-08 13:28:51 +02004241end:
Eli Cohen02d1aa72015-02-08 13:28:50 +02004242 err = ib_copy_to_udata(ucore, &resp, resp.response_length);
Leon Romanovsky2953f422016-02-23 10:25:24 +02004243 return err;
Eli Cohen02d1aa72015-02-08 13:28:50 +02004244}